This commit is contained in:
Eugene Pankov
2017-05-01 13:35:26 +02:00
parent 8837173b1c
commit 889a60ba3b
62 changed files with 251 additions and 384 deletions

View File

@@ -29,39 +29,6 @@ build-mac:
echo :: Building application echo :: Building application
./node_modules/.bin/build --dir --mac --em.version=$(FULL_VERSION) ./node_modules/.bin/build --dir --mac --em.version=$(FULL_VERSION)
build-linux:
echo :: Building application
mkdir builtin-plugins || true
echo '{}' > builtin-plugins/package.json
cd builtin-plugins && for dir in $(builtin_plugins) ; do \
npm install ../$$dir; \
done
cd builtin-plugins && npm dedupe
./node_modules/.bin/electron-rebuild -f -m builtin-plugins -w node-pty,font-manager
./node_modules/.bin/build --linux --em.version=$(FULL_VERSION)
rm -r builtin-plugins || true
package-windows-app:
echo :: Building app MSI $(SHORT_VERSION)
heat dir dist/win-unpacked/ -cg Files -gg -scom -sreg -sfrag -srd -dr INSTALLDIR -var var.SourceDir -out build/files.wxs
candle -dSourceDir=dist\\win-unpacked -dProductVersion=$(SHORT_VERSION) -arch x64 -o dist/ build/files.wxs build/windows/elements.wxs
light -o dist/elements-app.msi dist/files.wixobj dist/elements.wixobj
build/windows/signtool.exe sign /f "build\\certificates\\Code Signing.p12" dist/elements-app.msi
package-windows-bundle:
echo :: Building installer
candle -dVersion=$(SHORT_VERSION) -ext WixBalExtension -arch x64 -o dist/build.wixobj build/windows/build.wxs
light -ext WixBalExtension -o bundle.exe dist/build.wixobj
insignia -ib bundle.exe -o engine.exe
build/windows/signtool.exe sign /f "build\\certificates\\Code Signing.p12" engine.exe
insignia -ab engine.exe bundle.exe -o dist/Elements-Electron.exe
build/windows/signtool.exe sign /f "build\\certificates\\Code Signing.p12" dist/Elements-Electron.exe
rm engine.exe bundle.exe || true
package-windows: build-windows package-windows-app package-windows-bundle
package-mac: driver-mac build-mac package-mac: driver-mac build-mac
rm -rf $(MAC_WS) || true rm -rf $(MAC_WS) || true

View File

@@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser' import { BrowserModule } from '@angular/platform-browser'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
export async function getRootModule(plugins: any[]): Promise<any> { export async function getRootModule (plugins: any[]): Promise<any> {
let imports = [ let imports = [
BrowserModule, BrowserModule,
...(plugins.map(x => x.default.forRoot ? x.default.forRoot() : x.default)), ...(plugins.map(x => x.default.forRoot ? x.default.forRoot() : x.default)),
@@ -12,7 +12,7 @@ export async function getRootModule(plugins: any[]): Promise<any> {
...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)), ...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)),
] ]
if (bootstrap.length == 0) { if (bootstrap.length === 0) {
throw new Error('Did not find any bootstrap components. Are there any plugins installed?') throw new Error('Did not find any bootstrap components. Are there any plugins installed?')
} }

View File

@@ -1,5 +1,3 @@
(<any>console).timeStamp('entry point')
import 'core-js' import 'core-js'
import 'zone.js/dist/zone.js' import 'zone.js/dist/zone.js'
import 'core-js/es7/reflect' import 'core-js/es7/reflect'
@@ -14,7 +12,7 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
import { getRootModule } from './app.module' import { getRootModule } from './app.module'
import { findPlugins, loadPlugins } from './plugins' import { findPlugins, loadPlugins } from './plugins'
if ((<any>global).require('electron-is-dev')) { if (require('electron-is-dev')) {
console.warn('Running in debug mode') console.warn('Running in debug mode')
} else { } else {
enableProdMode() enableProdMode()
@@ -22,7 +20,7 @@ if ((<any>global).require('electron-is-dev')) {
findPlugins().then(async plugins => { findPlugins().then(async plugins => {
let pluginsModules = await loadPlugins(plugins, (current, total) => { let pluginsModules = await loadPlugins(plugins, (current, total) => {
(<HTMLElement>document.querySelector('.progress .bar')).style.width = 100 * current / total + '%' (document.querySelector('.progress .bar') as HTMLElement).style.width = 100 * current / total + '%'
}) })
let module = await getRootModule(pluginsModules) let module = await getRootModule(pluginsModules)
platformBrowserDynamic().bootstrapModule(module) platformBrowserDynamic().bootstrapModule(module)

View File

@@ -1,6 +1,7 @@
import * as fs from 'fs-promise' import * as fs from 'fs-promise'
import * as path from 'path' import * as path from 'path'
const nodeModule = (<any>global).require('module') const nodeModule = require('module')
const nodeRequire = (global as any).require
function normalizePath (path: string): string { function normalizePath (path: string): string {
const cygwinPrefix = '/cygdrive/' const cygwinPrefix = '/cygdrive/'
@@ -9,9 +10,9 @@ function normalizePath (path: string): string {
path = path[0] + ':' + path.substring(1) path = path[0] + ':' + path.substring(1)
} }
return path return path
}; }
(<any>global).require.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x))) nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
if (process.env.DEV) { if (process.env.DEV) {
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath())) nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
@@ -80,10 +81,10 @@ export async function loadPlugins (foundPlugins: IPluginEntry[], progress: Progr
progress(0, 1) progress(0, 1)
let index = 0 let index = 0
for (let foundPlugin of foundPlugins) { for (let foundPlugin of foundPlugins) {
console.info(`Loading ${foundPlugin.name}: ${(<any>global).require.resolve(foundPlugin.path)}`) console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
progress(index, foundPlugins.length) progress(index, foundPlugins.length)
try { try {
let pluginModule = (<any>global).require(foundPlugin.path) let pluginModule = nodeRequire(foundPlugin.path)
plugins.push(pluginModule) plugins.push(pluginModule)
} catch (error) { } catch (error) {
console.error(`Could not load ${foundPlugin.name}:`, error) console.error(`Could not load ${foundPlugin.name}:`, error)

View File

@@ -1,6 +1,5 @@
import { Component } from '@angular/core' import { Component } from '@angular/core'
@Component({ @Component({
template: '<app-root></app-root>' template: '<app-root></app-root>'
}) })

View File

@@ -27,12 +27,5 @@
"*/node_modules", "*/node_modules",
"terminus*", "terminus*",
"platforms" "platforms"
],
"filesGlob" : [
"app/src/*.ts",
"app/src/**/*.ts",
"!node_modules/**",
"!app/node_modules/**",
"!*/node_modules/**"
] ]
} }

View File

@@ -57,6 +57,7 @@ module.exports = {
'@ng-bootstrap/ng-bootstrap': 'commonjs @ng-bootstrap/ng-bootstrap', '@ng-bootstrap/ng-bootstrap': 'commonjs @ng-bootstrap/ng-bootstrap',
'fs-promise': 'commonjs fs-promise', 'fs-promise': 'commonjs fs-promise',
'electron': 'commonjs electron', 'electron': 'commonjs electron',
'electron-is-dev': 'commonjs electron-is-dev',
'module': 'commonjs module', 'module': 'commonjs module',
'path': 'commonjs path', 'path': 'commonjs path',
'rxjs': 'commonjs rxjs', 'rxjs': 'commonjs rxjs',

View File

@@ -31,12 +31,12 @@
"source-sans-pro": "^2.0.10", "source-sans-pro": "^2.0.10",
"style-loader": "^0.13.1", "style-loader": "^0.13.1",
"to-string-loader": "^1.1.5", "to-string-loader": "^1.1.5",
"tslint": "5.0.0", "tslint": "^5.1.0",
"tslint-eslint-rules": "4.0.0", "tslint-config-standard": "^5.0.2",
"tslint-eslint-rules": "^4.0.0",
"typescript": "~2.1.0", "typescript": "~2.1.0",
"url-loader": "^0.5.7", "url-loader": "^0.5.7",
"val-loader": "^0.5.0", "val-loader": "^0.5.0",
"vrsource-tslint-rules": "^4.0.1",
"webpack": "2.4.1" "webpack": "2.4.1"
}, },
"build": { "build": {
@@ -47,7 +47,6 @@
"builtin-plugins" "builtin-plugins"
], ],
"win": { "win": {
"target": "zip",
"icon": "./app/assets/img/shortcut.ico" "icon": "./app/assets/img/shortcut.ico"
}, },
"mac": { "mac": {
@@ -56,17 +55,15 @@
"identity": "Syslink GmbH" "identity": "Syslink GmbH"
}, },
"linux": { "linux": {
"category": "Network", "category": "Utilities",
"target": "AppImage", "icon": "./build/icons"
"icon": "./app/assets/img/icon.png"
} }
}, },
"scripts": { "scripts": {
"build": "webpack --progress --color", "build": "webpack --progress --color",
"watch": "webpack --progress --color --watch", "watch": "webpack --progress --color --watch",
"start": "cross-env DEV=1 electron app --debug", "start": "cross-env DEV=1 electron app --debug",
"pack": "build --dir", "lint": "tslint -c tslint.json -t stylish terminus-*/src/**/*.ts terminus-*/src/*.ts app/src/*.ts",
"postinstall": "install-app-deps", "postinstall": "install-app-deps"
"dist": "build"
} }
} }

11
scripts/build-linux.js Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env node
const builder = require('electron-builder').build
const vars = require('./vars')
builder({
dir: true,
linux: ['appimage'],
extraMetadata: {
version: vars.version,
},
})

0
scripts/build-native.js Normal file → Executable file
View File

0
scripts/build-windows.js Normal file → Executable file
View File

0
scripts/install-deps.js Normal file → Executable file
View File

0
scripts/prepackage-plugins.js Normal file → Executable file
View File

0
scripts/vars.js Normal file → Executable file
View File

View File

@@ -3,7 +3,6 @@ import { TerminalDecorator, TerminalTabComponent } from 'terminus-terminal'
import { LinkHandler } from './api' import { LinkHandler } from './api'
@Injectable() @Injectable()
export class LinkHighlighterDecorator extends TerminalDecorator { export class LinkHighlighterDecorator extends TerminalDecorator {
constructor (@Inject(LinkHandler) private handlers: LinkHandler[]) { constructor (@Inject(LinkHandler) private handlers: LinkHandler[]) {
@@ -21,17 +20,17 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
insertLinks (screen) { insertLinks (screen) {
if ('#text' === screen.cursorNode_.nodeName) { if ('#text' === screen.cursorNode_.nodeName) {
// replace text node to element // replace text node to element
const cursorNode = document.createElement('span'); const cursorNode = document.createElement('span')
cursorNode.textContent = screen.cursorNode_.textContent; cursorNode.textContent = screen.cursorNode_.textContent
screen.cursorRowNode_.replaceChild(cursorNode, screen.cursorNode_); screen.cursorRowNode_.replaceChild(cursorNode, screen.cursorNode_)
screen.cursorNode_ = cursorNode; screen.cursorNode_ = cursorNode
} }
const traverse = (parentNode: Node) => { const traverse = (parentNode: Node) => {
Array.from(parentNode.childNodes).forEach((node) => { Array.from(parentNode.childNodes).forEach((node) => {
if (node.nodeName == '#text') { if (node.nodeName === '#text') {
parentNode.replaceChild(this.urlizeNode(node), node) parentNode.replaceChild(this.urlizeNode(node), node)
} else if (node.nodeName != 'A') { } else if (node.nodeName !== 'A') {
traverse(node) traverse(node)
} }
}) })
@@ -44,11 +43,14 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
let matches = [] let matches = []
this.handlers.forEach((handler) => { this.handlers.forEach((handler) => {
let regex = new RegExp(handler.regex, 'gi') let regex = new RegExp(handler.regex, 'gi')
let match while (true) {
while (match = regex.exec(node.textContent)) { let match = regex.exec(node.textContent)
if (!match) {
break
}
let uri = handler.convert(match[0]) let uri = handler.convert(match[0])
if (!handler.verify(uri)) { if (!handler.verify(uri)) {
continue; continue
} }
matches.push({ matches.push({
start: regex.lastIndex - match[0].length, start: regex.lastIndex - match[0].length,
@@ -60,7 +62,7 @@ export class LinkHighlighterDecorator extends TerminalDecorator {
} }
}) })
if (matches.length == 0) { if (matches.length === 0) {
return node return node
} }

View File

@@ -5,7 +5,6 @@ import { ElectronService } from 'terminus-core'
import { LinkHandler } from './api' import { LinkHandler } from './api'
@Injectable() @Injectable()
export class URLHandler extends LinkHandler { export class URLHandler extends LinkHandler {
regex = 'http(s)?://[^\\s;\'"]+[^,;\\s]' regex = 'http(s)?://[^\\s;\'"]+[^,;\\s]'

View File

@@ -10,7 +10,6 @@ import { LinkHandler } from './api'
import { FileHandler, URLHandler } from './handlers' import { FileHandler, URLHandler } from './handlers'
import { LinkHighlighterDecorator } from './decorator' import { LinkHighlighterDecorator } from './decorator'
@NgModule({ @NgModule({
providers: [ providers: [
{ provide: LinkHandler, useClass: FileHandler, multi: true }, { provide: LinkHandler, useClass: FileHandler, multi: true },

View File

@@ -3,14 +3,13 @@ import { TerminalColorSchemeProvider, ITerminalColorScheme } from 'terminus-term
const schemeContents = require.context('../schemes/', true, /.*/) const schemeContents = require.context('../schemes/', true, /.*/)
@Injectable() @Injectable()
export class ColorSchemes extends TerminalColorSchemeProvider { export class ColorSchemes extends TerminalColorSchemeProvider {
async getSchemes (): Promise<ITerminalColorScheme[]> { async getSchemes (): Promise<ITerminalColorScheme[]> {
let schemes: ITerminalColorScheme[] = [] let schemes: ITerminalColorScheme[] = []
schemeContents.keys().forEach(schemeFile => { schemeContents.keys().forEach(schemeFile => {
let lines = (<string>schemeContents(schemeFile)).split('\n') let lines = (schemeContents(schemeFile) as string).split('\n')
let values: any = {} let values: any = {}
lines lines
.filter(x => x.startsWith('*.')) .filter(x => x.startsWith('*.'))

View File

@@ -3,7 +3,6 @@ import { TerminalColorSchemeProvider } from 'terminus-terminal'
import { ColorSchemes } from './colorSchemes' import { ColorSchemes } from './colorSchemes'
@NgModule({ @NgModule({
providers: [ providers: [
{ provide: TerminalColorSchemeProvider, useClass: ColorSchemes, multi: true }, { provide: TerminalColorSchemeProvider, useClass: ColorSchemes, multi: true },

View File

@@ -14,7 +14,6 @@ import { ThemesService } from '../services/themes.service'
import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api' import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api'
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
template: require('./appRoot.component.pug'), template: require('./appRoot.component.pug'),
@@ -46,7 +45,7 @@ export class AppRootComponent {
Platform = Platform Platform = Platform
private logger: Logger private logger: Logger
constructor( constructor (
private docking: DockingService, private docking: DockingService,
private electron: ElectronService, private electron: ElectronService,
private tabRecovery: TabRecoveryService, private tabRecovery: TabRecoveryService,
@@ -76,16 +75,16 @@ export class AppRootComponent {
} }
} }
if (this.app.activeTab) { if (this.app.activeTab) {
if (hotkey == 'close-tab') { if (hotkey === 'close-tab') {
this.app.closeTab(this.app.activeTab) this.app.closeTab(this.app.activeTab)
} }
if (hotkey == 'toggle-last-tab') { if (hotkey === 'toggle-last-tab') {
this.app.toggleLastTab() this.app.toggleLastTab()
} }
if (hotkey == 'next-tab') { if (hotkey === 'next-tab') {
this.app.nextTab() this.app.nextTab()
} }
if (hotkey == 'previous-tab') { if (hotkey === 'previous-tab') {
this.app.previousTab() this.app.previousTab()
} }
} }
@@ -113,7 +112,7 @@ export class AppRootComponent {
// unfocused, invisible // unfocused, invisible
this.electron.app.window.show() this.electron.app.window.show()
} else { } else {
if (this.config.store.appearance.dock == 'off') { if (this.config.store.appearance.dock === 'off') {
// not docked, visible // not docked, visible
setTimeout(() => { setTimeout(() => {
this.electron.app.window.focus() this.electron.app.window.focus()
@@ -134,7 +133,7 @@ export class AppRootComponent {
await this.tabRecovery.recoverTabs() await this.tabRecovery.recoverTabs()
this.tabRecovery.saveTabs(this.app.tabs) this.tabRecovery.saveTabs(this.app.tabs)
if (this.app.tabs.length == 0) { if (this.app.tabs.length === 0) {
this.app.openDefaultTab() this.app.openDefaultTab()
} }
} }

View File

@@ -1,8 +1,8 @@
import { Subject, BehaviorSubject } from 'rxjs' import { Subject, BehaviorSubject } from 'rxjs'
import { ViewRef } from '@angular/core' import { ViewRef } from '@angular/core'
export abstract class BaseTabComponent { export abstract class BaseTabComponent {
private static lastTabID = 0
id: number id: number
title$ = new BehaviorSubject<string>(null) title$ = new BehaviorSubject<string>(null)
scrollable: boolean scrollable: boolean
@@ -11,7 +11,6 @@ export abstract class BaseTabComponent {
blurred$ = new Subject<void>() blurred$ = new Subject<void>()
hasFocus = false hasFocus = false
hostView: ViewRef hostView: ViewRef
private static lastTabID = 0
constructor () { constructor () {
this.id = BaseTabComponent.lastTabID++ this.id = BaseTabComponent.lastTabID++

View File

@@ -3,12 +3,12 @@ import { ElectronService } from '../services/electron.service'
import { IToolbarButton, ToolbarButtonProvider } from '../api' import { IToolbarButton, ToolbarButtonProvider } from '../api'
@Component({ @Component({
selector: 'start-page', selector: 'start-page',
template: require('./startPage.component.pug'), template: require('./startPage.component.pug'),
styles: [require('./startPage.component.scss')], styles: [require('./startPage.component.scss')],
}) })
export class StartPageComponent { export class StartPageComponent {
constructor( constructor (
private electron: ElectronService, private electron: ElectronService,
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[], @Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],
) { } ) { }

View File

@@ -2,9 +2,9 @@ import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/co
import { BaseTabComponent } from '../components/baseTab.component' import { BaseTabComponent } from '../components/baseTab.component'
@Component({ @Component({
selector: 'tab-header', selector: 'tab-header',
template: require('./tabHeader.component.pug'), template: require('./tabHeader.component.pug'),
styles: [require('./tabHeader.component.scss')], styles: [require('./tabHeader.component.scss')],
}) })
export class TabHeaderComponent { export class TabHeaderComponent {
@Input() index: number @Input() index: number

View File

@@ -1,9 +1,8 @@
import { Component } from '@angular/core' import { Component } from '@angular/core'
@Component({ @Component({
selector: 'title-bar', selector: 'title-bar',
template: require('./titleBar.component.pug'), template: require('./titleBar.component.pug'),
styles: [require('./titleBar.component.scss')], styles: [require('./titleBar.component.scss')],
}) })
export class TitleBarComponent { export class TitleBarComponent { }
}

View File

@@ -1,7 +1,6 @@
import { ConfigProvider } from './api/configProvider' import { ConfigProvider } from './api/configProvider'
import { Platform } from './services/hostApp.service' import { Platform } from './services/hostApp.service'
export class CoreConfigProvider extends ConfigProvider { export class CoreConfigProvider extends ConfigProvider {
platformDefaults = { platformDefaults = {
[Platform.macOS]: require('./configDefaults.macos.yaml'), [Platform.macOS]: require('./configDefaults.macos.yaml'),

View File

@@ -13,7 +13,6 @@ import { HostAppService } from './services/hostApp.service'
import { LogService } from './services/log.service' import { LogService } from './services/log.service'
import { HotkeysService, AppHotkeyProvider } from './services/hotkeys.service' import { HotkeysService, AppHotkeyProvider } from './services/hotkeys.service'
import { NotifyService } from './services/notify.service' import { NotifyService } from './services/notify.service'
import { PluginsService } from './services/plugins.service'
import { QuitterService } from './services/quitter.service' import { QuitterService } from './services/quitter.service'
import { DockingService } from './services/docking.service' import { DockingService } from './services/docking.service'
import { TabRecoveryService } from './services/tabRecovery.service' import { TabRecoveryService } from './services/tabRecovery.service'
@@ -43,7 +42,6 @@ const PROVIDERS = [
HotkeysService, HotkeysService,
LogService, LogService,
NotifyService, NotifyService,
PluginsService,
TabRecoveryService, TabRecoveryService,
ThemesService, ThemesService,
QuitterService, QuitterService,
@@ -52,7 +50,6 @@ const PROVIDERS = [
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true }, { provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
] ]
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
@@ -73,7 +70,7 @@ const PROVIDERS = [
], ],
}) })
export default class AppModule { export default class AppModule {
static forRoot(): ModuleWithProviders { static forRoot (): ModuleWithProviders {
return { return {
ngModule: AppModule, ngModule: AppModule,
providers: PROVIDERS, providers: PROVIDERS,

View File

@@ -6,7 +6,6 @@ import { Logger, LogService } from '../services/log.service'
export declare type TabComponentType = new (...args: any[]) => BaseTabComponent export declare type TabComponentType = new (...args: any[]) => BaseTabComponent
@Injectable() @Injectable()
export class AppService { export class AppService {
tabs: BaseTabComponent[] = [] tabs: BaseTabComponent[] = []
@@ -44,7 +43,7 @@ export class AppService {
} }
selectTab (tab: BaseTabComponent) { selectTab (tab: BaseTabComponent) {
if (this.activeTab == tab) { if (this.activeTab === tab) {
return return
} }
if (this.tabs.includes(this.activeTab)) { if (this.tabs.includes(this.activeTab)) {
@@ -85,12 +84,9 @@ export class AppService {
closeTab (tab: BaseTabComponent) { closeTab (tab: BaseTabComponent) {
tab.destroy() tab.destroy()
/* if (tab.session) {
this.sessions.destroySession(tab.session)
} */
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1) let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
this.tabs = this.tabs.filter((x) => x != tab) this.tabs = this.tabs.filter((x) => x !== tab)
if (tab == this.activeTab) { if (tab === this.activeTab) {
this.selectTab(this.tabs[newIndex]) this.selectTab(this.tabs[newIndex])
} }
this.tabsChanged$.next() this.tabsChanged$.next()

View File

@@ -6,6 +6,7 @@ import { ConfigProvider } from '../api/configProvider'
import { ElectronService } from './electron.service' import { ElectronService } from './electron.service'
import { HostAppService } from './hostApp.service' import { HostAppService } from './hostApp.service'
const configMerge = (a, b) => require('deepmerge')(a, b, { arrayMerge: (_d, s) => s })
export class ConfigProxy { export class ConfigProxy {
constructor (real: any, defaults: any) { constructor (real: any, defaults: any) {
@@ -47,10 +48,6 @@ export class ConfigProxy {
} }
} }
const configMerge = (a, b) => require('deepmerge')(a, b, { arrayMerge: (_d, s) => s })
@Injectable() @Injectable()
export class ConfigService { export class ConfigService {
store: any store: any

View File

@@ -3,7 +3,6 @@ import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service' import { ElectronService } from '../services/electron.service'
import { HostAppService } from '../services/hostApp.service' import { HostAppService } from '../services/hostApp.service'
export interface IScreen { export interface IScreen {
id: string id: string
name: string name: string
@@ -11,7 +10,7 @@ export interface IScreen {
@Injectable() @Injectable()
export class DockingService { export class DockingService {
constructor( constructor (
private electron: ElectronService, private electron: ElectronService,
private config: ConfigService, private config: ConfigService,
private hostApp: HostAppService, private hostApp: HostAppService,
@@ -19,7 +18,7 @@ export class DockingService {
dock () { dock () {
let display = this.electron.screen.getAllDisplays() let display = this.electron.screen.getAllDisplays()
.filter((x) => x.id == this.config.store.appearance.dockScreen)[0] .filter((x) => x.id === this.config.store.appearance.dockScreen)[0]
if (!display) { if (!display) {
display = this.getCurrentScreen() display = this.getCurrentScreen()
} }
@@ -28,31 +27,30 @@ export class DockingService {
let newBounds: Electron.Rectangle = { x: 0, y: 0, width: 0, height: 0 } let newBounds: Electron.Rectangle = { x: 0, y: 0, width: 0, height: 0 }
let fill = this.config.store.appearance.dockFill let fill = this.config.store.appearance.dockFill
if (dockSide == 'off') { if (dockSide === 'off') {
this.hostApp.setAlwaysOnTop(false) this.hostApp.setAlwaysOnTop(false)
return return
} }
if (dockSide == 'left' || dockSide == 'right') { if (dockSide === 'left' || dockSide === 'right') {
newBounds.width = Math.round(fill * display.bounds.width) newBounds.width = Math.round(fill * display.bounds.width)
newBounds.height = display.bounds.height newBounds.height = display.bounds.height
} }
if (dockSide == 'top' || dockSide == 'bottom') { if (dockSide === 'top' || dockSide === 'bottom') {
newBounds.width = display.bounds.width newBounds.width = display.bounds.width
newBounds.height = Math.round(fill * display.bounds.height) newBounds.height = Math.round(fill * display.bounds.height)
} }
if (dockSide == 'right') { if (dockSide === 'right') {
newBounds.x = display.bounds.x + display.bounds.width * (1.0 - fill) newBounds.x = display.bounds.x + display.bounds.width * (1.0 - fill)
} else { } else {
newBounds.x = display.bounds.x newBounds.x = display.bounds.x
} }
if (dockSide == 'bottom') { if (dockSide === 'bottom') {
newBounds.y = display.bounds.y + display.bounds.height * (1.0 - fill) newBounds.y = display.bounds.y + display.bounds.height * (1.0 - fill)
} else { } else {
newBounds.y = display.bounds.y newBounds.y = display.bounds.y
} }
this.hostApp.setAlwaysOnTop(true) this.hostApp.setAlwaysOnTop(true)
//this.hostApp.unmaximize()
setImmediate(() => { setImmediate(() => {
this.hostApp.setBounds(newBounds) this.hostApp.setBounds(newBounds)
}) })

View File

@@ -2,15 +2,17 @@ import { Injectable } from '@angular/core'
@Injectable() @Injectable()
export class ElectronService { export class ElectronService {
constructor() { app: any
if (process.env.TEST_ENV) { ipcRenderer: any
this.initTest() shell: any
} else { dialog: any
this.init() clipboard: any
} globalShortcut: any
} screen: any
private electron: any
private remoteElectron: any
init() { constructor () {
this.electron = require('electron') this.electron = require('electron')
this.remoteElectron = this.remoteRequire('electron') this.remoteElectron = this.remoteRequire('electron')
this.app = this.remoteElectron.app this.app = this.remoteElectron.app
@@ -22,21 +24,7 @@ export class ElectronService {
this.globalShortcut = this.remoteElectron.globalShortcut this.globalShortcut = this.remoteElectron.globalShortcut
} }
initTest() { remoteRequire (name: string): any {
;
}
remoteRequire(name: string): any {
return this.electron.remote.require(name) return this.electron.remote.require(name)
} }
app: any
ipcRenderer: any
shell: any
dialog: any
clipboard: any
globalShortcut: any
screen: any
private electron: any
private remoteElectron: any
} }

View File

@@ -6,13 +6,18 @@ export enum Platform {
Linux, macOS, Windows, Linux, macOS, Windows,
} }
@Injectable() @Injectable()
export class HostAppService { export class HostAppService {
platform: Platform platform: Platform
nodePlatform: string nodePlatform: string
quitRequested = new EventEmitter<any>()
ready = new EventEmitter<any>()
shown = new EventEmitter<any>()
secondInstance = new EventEmitter<any>()
constructor( private logger: Logger
constructor (
private zone: NgZone, private zone: NgZone,
private electron: ElectronService, private electron: ElectronService,
log: LogService, log: LogService,
@@ -27,7 +32,7 @@ export class HostAppService {
electron.ipcRenderer.on('host:quit-request', () => this.zone.run(() => this.quitRequested.emit())) electron.ipcRenderer.on('host:quit-request', () => this.zone.run(() => this.quitRequested.emit()))
electron.ipcRenderer.on('uncaughtException', function(err) { electron.ipcRenderer.on('uncaughtException', (err) => {
this.logger.error('Unhandled exception:', err) this.logger.error('Unhandled exception:', err)
}) })
@@ -44,13 +49,6 @@ export class HostAppService {
}) })
} }
quitRequested = new EventEmitter<any>()
ready = new EventEmitter<any>()
shown = new EventEmitter<any>()
secondInstance = new EventEmitter<any>()
private logger: Logger;
getWindow () { getWindow () {
return this.electron.app.window return this.electron.app.window
} }
@@ -63,23 +61,23 @@ export class HostAppService {
return this.electron.app.getAppPath() return this.electron.app.getAppPath()
} }
getPath(type: string) { getPath (type: string) {
return this.electron.app.getPath(type) return this.electron.app.getPath(type)
} }
openDevTools() { openDevTools () {
this.getWindow().webContents.openDevTools() this.getWindow().webContents.openDevTools()
} }
setCloseable(flag: boolean) { setCloseable (flag: boolean) {
this.electron.ipcRenderer.send('window-set-closeable', flag) this.electron.ipcRenderer.send('window-set-closeable', flag)
} }
focusWindow() { focusWindow () {
this.electron.ipcRenderer.send('window-focus') this.electron.ipcRenderer.send('window-focus')
} }
toggleWindow() { toggleWindow () {
this.electron.ipcRenderer.send('window-toggle-focus') this.electron.ipcRenderer.send('window-toggle-focus')
} }

View File

@@ -4,7 +4,6 @@ import { NativeKeyEvent, stringifyKeySequence } from './hotkeys.util'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service' import { ElectronService } from '../services/electron.service'
export interface PartialHotkeyMatch { export interface PartialHotkeyMatch {
id: string, id: string,
strokes: string[], strokes: string[],
@@ -27,7 +26,7 @@ export class HotkeysService {
private disabledLevel = 0 private disabledLevel = 0
private hotkeyDescriptions: IHotkeyDescription[] private hotkeyDescriptions: IHotkeyDescription[]
constructor( constructor (
private zone: NgZone, private zone: NgZone,
private electron: ElectronService, private electron: ElectronService,
private config: ConfigService, private config: ConfigService,
@@ -36,7 +35,7 @@ export class HotkeysService {
let events = ['keydown', 'keyup'] let events = ['keydown', 'keyup']
events.forEach((event) => { events.forEach((event) => {
document.addEventListener(event, (nativeEvent) => { document.addEventListener(event, (nativeEvent) => {
if (document.querySelectorAll('input:focus').length == 0) { if (document.querySelectorAll('input:focus').length === 0) {
this.pushKeystroke(event, nativeEvent) this.pushKeystroke(event, nativeEvent)
this.processKeystrokes() this.processKeystrokes()
this.emitKeyEvent(nativeEvent) this.emitKeyEvent(nativeEvent)
@@ -78,7 +77,7 @@ export class HotkeysService {
this.currentKeystrokes = [] this.currentKeystrokes = []
} }
getCurrentKeystrokes () : string[] { getCurrentKeystrokes (): string[] {
this.currentKeystrokes = this.currentKeystrokes.filter((x) => performance.now() - x.time < KEY_TIMEOUT ) this.currentKeystrokes = this.currentKeystrokes.filter((x) => performance.now() - x.time < KEY_TIMEOUT )
return stringifyKeySequence(this.currentKeystrokes.map((x) => x.event)) return stringifyKeySequence(this.currentKeystrokes.map((x) => x.event))
} }
@@ -86,11 +85,11 @@ export class HotkeysService {
registerGlobalHotkey () { registerGlobalHotkey () {
this.electron.globalShortcut.unregisterAll() this.electron.globalShortcut.unregisterAll()
let value = this.config.store.hotkeys['toggle-window'] let value = this.config.store.hotkeys['toggle-window']
if (typeof value == 'string') { if (typeof value === 'string') {
value = [value] value = [value]
} }
value.forEach(item => { value.forEach(item => {
item = (typeof item == 'string') ? [item] : item item = (typeof item === 'string') ? [item] : item
this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => { this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => {
this.globalHotkey.emit() this.globalHotkey.emit()
@@ -102,16 +101,16 @@ export class HotkeysService {
let keys = {} let keys = {}
for (let key in this.config.store.hotkeys) { for (let key in this.config.store.hotkeys) {
let value = this.config.store.hotkeys[key] let value = this.config.store.hotkeys[key]
if (typeof value == 'string') { if (typeof value === 'string') {
value = [value] value = [value]
} }
value = value.map((item) => (typeof item == 'string') ? [item] : item) value = value.map((item) => (typeof item === 'string') ? [item] : item)
keys[key] = value keys[key] = value
} }
return keys return keys
} }
getCurrentFullyMatchedHotkey () : string { getCurrentFullyMatchedHotkey (): string {
for (let id in this.getHotkeysConfig()) { for (let id in this.getHotkeysConfig()) {
for (let sequence of this.getHotkeysConfig()[id]) { for (let sequence of this.getHotkeysConfig()[id]) {
let currentStrokes = this.getCurrentKeystrokes() let currentStrokes = this.getCurrentKeystrokes()
@@ -119,7 +118,7 @@ export class HotkeysService {
break break
} }
if (sequence.every((x, index) => { if (sequence.every((x, index) => {
return x.toLowerCase() == currentStrokes[currentStrokes.length - sequence.length + index].toLowerCase() return x.toLowerCase() === currentStrokes[currentStrokes.length - sequence.length + index].toLowerCase()
})) { })) {
return id return id
} }
@@ -128,16 +127,15 @@ export class HotkeysService {
return null return null
} }
getCurrentPartiallyMatchedHotkeys () : PartialHotkeyMatch[] { getCurrentPartiallyMatchedHotkeys (): PartialHotkeyMatch[] {
let result = [] let result = []
for (let id in this.getHotkeysConfig()) { for (let id in this.getHotkeysConfig()) {
for (let sequence of this.getHotkeysConfig()[id]) { for (let sequence of this.getHotkeysConfig()[id]) {
let currentStrokes = this.getCurrentKeystrokes() let currentStrokes = this.getCurrentKeystrokes()
for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) { for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) {
//console.log(sequence, currentStrokes.slice(currentStrokes.length - sequence.length))
if (sequence.slice(0, matchLength).every((x, index) => { if (sequence.slice(0, matchLength).every((x, index) => {
return x.toLowerCase() == currentStrokes[currentStrokes.length - matchLength + index].toLowerCase() return x.toLowerCase() === currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
})) { })) {
result.push({ result.push({
matchedLength: matchLength, matchedLength: matchLength,
@@ -152,8 +150,8 @@ export class HotkeysService {
return result return result
} }
getHotkeyDescription (id: string) : IHotkeyDescription { getHotkeyDescription (id: string): IHotkeyDescription {
return this.hotkeyDescriptions.filter((x) => x.id == id)[0] return this.hotkeyDescriptions.filter((x) => x.id === id)[0]
} }
enable () { enable () {
@@ -165,12 +163,10 @@ export class HotkeysService {
} }
isEnabled () { isEnabled () {
return this.disabledLevel == 0 return this.disabledLevel === 0
} }
} }
@Injectable() @Injectable()
export class AppHotkeyProvider extends HotkeyProvider { export class AppHotkeyProvider extends HotkeyProvider {
hotkeys: IHotkeyDescription[] = [ hotkeys: IHotkeyDescription[] = [

View File

@@ -1,18 +1,14 @@
import * as os from 'os'
export const metaKeyName = { export const metaKeyName = {
darwin: '⌘', darwin: '⌘',
win32: 'Win', win32: 'Win',
linux: 'Super', linux: 'Super',
}[os.platform()] }[process.platform]
export const altKeyName = { export const altKeyName = {
darwin: 'Option', darwin: 'Option',
win32: 'Alt', win32: 'Alt',
linux: 'Alt', linux: 'Alt',
}[os.platform()] }[process.platform]
export interface NativeKeyEvent { export interface NativeKeyEvent {
event?: string, event?: string,
@@ -24,14 +20,13 @@ export interface NativeKeyEvent {
keyCode: string, keyCode: string,
} }
export function stringifyKeySequence (events: NativeKeyEvent[]): string[] {
export function stringifyKeySequence(events: NativeKeyEvent[]): string[] {
let items: string[] = [] let items: string[] = []
events = events.slice() events = events.slice()
while (events.length > 0) { while (events.length > 0) {
let event = events.shift() let event = events.shift()
if (event.event == 'keydown') { if (event.event === 'keydown') {
let itemKeys: string[] = [] let itemKeys: string[] = []
if (event.ctrlKey) { if (event.ctrlKey) {
itemKeys.push('Ctrl') itemKeys.push('Ctrl')
@@ -50,7 +45,7 @@ export function stringifyKeySequence(events: NativeKeyEvent[]): string[] {
// TODO make this optional? // TODO make this optional?
continue continue
} }
if (event.key.length == 1) { if (event.key.length === 1) {
itemKeys.push(event.key.toUpperCase()) itemKeys.push(event.key.toUpperCase())
} else { } else {
itemKeys.push(event.key) itemKeys.push(event.key)

View File

@@ -1,8 +1,7 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
export class Logger { export class Logger {
constructor( constructor (
private name: string, private name: string,
) {} ) {}
@@ -10,10 +9,10 @@ export class Logger {
console[level](`%c[${this.name}]`, 'color: #aaa', ...args) console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
} }
debug(...args: any[]) { this.log('debug', ...args) } debug (...args: any[]) { this.log('debug', ...args) }
info(...args: any[]) { this.log('info', ...args) } info (...args: any[]) { this.log('info', ...args) }
warn(...args: any[]) { this.log('warn', ...args) } warn (...args: any[]) { this.log('warn', ...args) }
error(...args: any[]) { this.log('error', ...args) } error (...args: any[]) { this.log('error', ...args) }
} }
@Injectable() @Injectable()

View File

@@ -1,18 +1,17 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { ToasterService } from 'angular2-toaster' import { ToasterService } from 'angular2-toaster'
@Injectable() @Injectable()
export class NotifyService { export class NotifyService {
constructor( constructor (
private toaster: ToasterService, private toaster: ToasterService,
) {} ) {}
pop(options) { pop (options) {
this.toaster.pop(options) this.toaster.pop(options)
} }
info(title: string, body: string = null) { info (title: string, body: string = null) {
return this.pop({ return this.pop({
type: 'info', type: 'info',
title, body, title, body,
@@ -20,7 +19,7 @@ export class NotifyService {
}) })
} }
success(title: string, body: string = null) { success (title: string, body: string = null) {
return this.pop({ return this.pop({
type: 'success', type: 'success',
title, body, title, body,
@@ -28,7 +27,7 @@ export class NotifyService {
}) })
} }
warning(title: string, body: string = null) { warning (title: string, body: string = null) {
return this.pop({ return this.pop({
type: 'warning', type: 'warning',
title, body, title, body,
@@ -36,7 +35,7 @@ export class NotifyService {
}) })
} }
error(title: string, body: string = null) { error (title: string, body: string = null) {
return this.pop({ return this.pop({
type: 'error', type: 'error',
title, body, title, body,

View File

@@ -1,21 +0,0 @@
import { Injectable } from '@angular/core'
class Plugin {
ngModule: any
name: string
}
@Injectable()
export class PluginsService {
plugins: Plugin[] = []
register (plugin: Plugin): void {
this.plugins.push(plugin)
}
getModules (): any[] {
return this.plugins.map((plugin) => plugin.ngModule)
}
}

View File

@@ -1,10 +1,9 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { HostAppService } from '../services/hostApp.service' import { HostAppService } from '../services/hostApp.service'
@Injectable() @Injectable()
export class QuitterService { export class QuitterService {
constructor( constructor (
private hostApp: HostAppService, private hostApp: HostAppService,
) { ) {
hostApp.quitRequested.subscribe(() => { hostApp.quitRequested.subscribe(() => {
@@ -12,7 +11,7 @@ export class QuitterService {
}) })
} }
quit() { quit () {
this.hostApp.setCloseable(true) this.hostApp.setCloseable(true)
this.hostApp.quit() this.hostApp.quit()
} }

View File

@@ -4,12 +4,11 @@ import { BaseTabComponent } from '../components/baseTab.component'
import { Logger, LogService } from '../services/log.service' import { Logger, LogService } from '../services/log.service'
import { AppService } from '../services/app.service' import { AppService } from '../services/app.service'
@Injectable() @Injectable()
export class TabRecoveryService { export class TabRecoveryService {
logger: Logger logger: Logger
constructor( constructor (
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[], @Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
app: AppService, app: AppService,
log: LogService log: LogService

View File

@@ -2,7 +2,6 @@ import { Inject, Injectable } from '@angular/core'
import { ConfigService } from '../services/config.service' import { ConfigService } from '../services/config.service'
import { Theme } from '../api/theme' import { Theme } from '../api/theme'
@Injectable() @Injectable()
export class ThemesService { export class ThemesService {
private styleElement: HTMLElement = null private styleElement: HTMLElement = null

View File

@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Theme } from './api' import { Theme } from './api'
@Injectable() @Injectable()
export class StandardTheme extends Theme { export class StandardTheme extends Theme {
name = 'Standard' name = 'Standard'

View File

@@ -3,7 +3,6 @@ import { ToolbarButtonProvider, IToolbarButton, AppService } from 'terminus-core
import { SettingsTabComponent } from './components/settingsTab.component' import { SettingsTabComponent } from './components/settingsTab.component'
@Injectable() @Injectable()
export class ButtonProvider extends ToolbarButtonProvider { export class ButtonProvider extends ToolbarButtonProvider {
constructor ( constructor (

View File

@@ -5,45 +5,44 @@ import { HotkeysService } from 'terminus-core'
const INPUT_TIMEOUT = 1000 const INPUT_TIMEOUT = 1000
@Component({ @Component({
selector: 'hotkey-input-modal', selector: 'hotkey-input-modal',
template: require('./hotkeyInputModal.component.pug'), template: require('./hotkeyInputModal.component.pug'),
styles: [require('./hotkeyInputModal.component.scss')], styles: [require('./hotkeyInputModal.component.scss')],
animations: [ animations: [
trigger('animateKey', [ trigger('animateKey', [
transition(':enter', [ transition(':enter', [
style({ style({
transform: 'translateX(25px)', transform: 'translateX(25px)',
opacity: '0', opacity: '0',
}), }),
animate('250ms ease-out', style({ animate('250ms ease-out', style({
transform: 'translateX(0)', transform: 'translateX(0)',
opacity: '1', opacity: '1',
})) }))
]), ]),
transition(':leave', [ transition(':leave', [
style({ style({
transform: 'translateX(0)', transform: 'translateX(0)',
opacity: '1', opacity: '1',
}), }),
animate('250ms ease-in', style({ animate('250ms ease-in', style({
transform: 'translateX(25px)', transform: 'translateX(25px)',
opacity: '0', opacity: '0',
})) }))
]) ])
]) ])
] ]
}) })
export class HotkeyInputModalComponent { export class HotkeyInputModalComponent {
@Input() value: string[] = []
@Input() timeoutProgress = 0
private keySubscription: Subscription private keySubscription: Subscription
private lastKeyEvent: number private lastKeyEvent: number
private keyTimeoutInterval: number = null private keyTimeoutInterval: number = null
@Input() value: string[] = [] constructor (
@Input() timeoutProgress = 0
constructor(
private modalInstance: NgbActiveModal, private modalInstance: NgbActiveModal,
public hotkeys: HotkeysService, public hotkeys: HotkeysService,
) { ) {
@@ -66,7 +65,7 @@ export class HotkeyInputModalComponent {
return return
} }
this.timeoutProgress = Math.min(100, (performance.now() - this.lastKeyEvent) * 100 / INPUT_TIMEOUT) this.timeoutProgress = Math.min(100, (performance.now() - this.lastKeyEvent) * 100 / INPUT_TIMEOUT)
if (this.timeoutProgress == 100) { if (this.timeoutProgress === 100) {
this.modalInstance.close(this.value) this.modalInstance.close(this.value)
} }
}, 25) }, 25)
@@ -78,7 +77,7 @@ export class HotkeyInputModalComponent {
clearInterval(this.keyTimeoutInterval) clearInterval(this.keyTimeoutInterval)
} }
close() { close () {
this.modalInstance.dismiss() this.modalInstance.dismiss()
} }
} }

View File

@@ -2,14 +2,16 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeyInputModalComponent } from './hotkeyInputModal.component' import { HotkeyInputModalComponent } from './hotkeyInputModal.component'
@Component({ @Component({
selector: 'multi-hotkey-input', selector: 'multi-hotkey-input',
template: require('./multiHotkeyInput.component.pug'), template: require('./multiHotkeyInput.component.pug'),
styles: [require('./multiHotkeyInput.component.scss')], styles: [require('./multiHotkeyInput.component.scss')],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class MultiHotkeyInputComponent { export class MultiHotkeyInputComponent {
@Input() model: string[][]
@Output() modelChange = new EventEmitter()
constructor ( constructor (
private ngbModal: NgbModal, private ngbModal: NgbModal,
) { } ) { }
@@ -18,10 +20,10 @@ export class MultiHotkeyInputComponent {
if (!this.model) { if (!this.model) {
this.model = [] this.model = []
} }
if (typeof this.model == 'string') { if (typeof this.model === 'string') {
this.model = [this.model] this.model = [this.model]
} }
this.model = this.model.map(item => (typeof item == 'string') ? [item] : item) this.model = this.model.map(item => (typeof item === 'string') ? [item] : item)
} }
editItem (item) { editItem (item) {
@@ -43,7 +45,4 @@ export class MultiHotkeyInputComponent {
this.model = this.model.filter(x => x !== item) this.model = this.model.filter(x => x !== item)
this.modelChange.emit(this.model) this.modelChange.emit(this.model)
} }
@Input() model: string[][]
@Output() modelChange = new EventEmitter()
} }

View File

@@ -3,20 +3,19 @@ import { ElectronService, DockingService, ConfigService, IHotkeyDescription, Hot
import { SettingsTabProvider } from '../api' import { SettingsTabProvider } from '../api'
@Component({ @Component({
selector: 'settings-tab', selector: 'settings-tab',
template: require('./settingsTab.component.pug'), template: require('./settingsTab.component.pug'),
styles: [ styles: [
require('./settingsTab.component.scss'), require('./settingsTab.component.scss'),
require('./settingsTab.deep.component.css'), require('./settingsTab.deep.component.css'),
], ],
}) })
export class SettingsTabComponent extends BaseTabComponent { export class SettingsTabComponent extends BaseTabComponent {
hotkeyFilter = { name: null } hotkeyFilter = { name: null }
private hotkeyDescriptions: IHotkeyDescription[] private hotkeyDescriptions: IHotkeyDescription[]
constructor( constructor (
public config: ConfigService, public config: ConfigService,
private electron: ElectronService, private electron: ElectronService,
public docking: DockingService, public docking: DockingService,

View File

@@ -1,10 +1,9 @@
import { Component, Input, ViewContainerRef, ViewChild, ComponentFactoryResolver, ComponentRef } from '@angular/core' import { Component, Input, ViewContainerRef, ViewChild, ComponentFactoryResolver, ComponentRef } from '@angular/core'
import { SettingsTabProvider } from '../api' import { SettingsTabProvider } from '../api'
@Component({ @Component({
selector: 'settings-tab-body', selector: 'settings-tab-body',
template: '<ng-template #placeholder></ng-template>', template: '<ng-template #placeholder></ng-template>',
}) })
export class SettingsTabBodyComponent { export class SettingsTabBodyComponent {
@Input() provider: SettingsTabProvider @Input() provider: SettingsTabProvider

View File

@@ -14,7 +14,6 @@ import { SettingsTabBodyComponent } from './components/settingsTabBody.component
import { ButtonProvider } from './buttonProvider' import { ButtonProvider } from './buttonProvider'
import { RecoveryProvider } from './recoveryProvider' import { RecoveryProvider } from './recoveryProvider'
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@@ -3,17 +3,16 @@ import { TabRecoveryProvider, AppService } from 'terminus-core'
import { SettingsTabComponent } from './components/settingsTab.component' import { SettingsTabComponent } from './components/settingsTab.component'
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
constructor( constructor (
private app: AppService private app: AppService
) { ) {
super() super()
} }
async recover (recoveryToken: any): Promise<void> { async recover (recoveryToken: any): Promise<void> {
if (recoveryToken.type == 'app:settings') { if (recoveryToken.type === 'app:settings') {
this.app.openNewTab(SettingsTabComponent) this.app.openNewTab(SettingsTabComponent)
} }
} }

View File

@@ -3,7 +3,9 @@ import { TerminalTabComponent } from './components/terminalTab.component'
export { TerminalTabComponent } export { TerminalTabComponent }
export abstract class TerminalDecorator { export abstract class TerminalDecorator {
// tslint:disable-next-line no-empty
attach (_terminal: TerminalTabComponent): void { } attach (_terminal: TerminalTabComponent): void { }
// tslint:disable-next-line no-empty
detach (_terminal: TerminalTabComponent): void { } detach (_terminal: TerminalTabComponent): void { }
} }

View File

@@ -4,7 +4,6 @@ import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService, Conf
import { SessionsService } from './services/sessions.service' import { SessionsService } from './services/sessions.service'
import { TerminalTabComponent } from './components/terminalTab.component' import { TerminalTabComponent } from './components/terminalTab.component'
@Injectable() @Injectable()
export class ButtonProvider extends ToolbarButtonProvider { export class ButtonProvider extends ToolbarButtonProvider {
constructor ( constructor (
@@ -15,7 +14,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
) { ) {
super() super()
hotkeys.matchedHotkey.subscribe(async (hotkey) => { hotkeys.matchedHotkey.subscribe(async (hotkey) => {
if (hotkey == 'new-tab') { if (hotkey === 'new-tab') {
this.openNewTab() this.openNewTab()
} }
}) })

View File

@@ -3,7 +3,6 @@ import * as path from 'path'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { TerminalColorSchemeProvider, ITerminalColorScheme } from './api' import { TerminalColorSchemeProvider, ITerminalColorScheme } from './api'
@Injectable() @Injectable()
export class HyperColorSchemes extends TerminalColorSchemeProvider { export class HyperColorSchemes extends TerminalColorSchemeProvider {
async getSchemes (): Promise<ITerminalColorScheme[]> { async getSchemes (): Promise<ITerminalColorScheme[]> {
@@ -14,7 +13,7 @@ export class HyperColorSchemes extends TerminalColorSchemeProvider {
let themes: ITerminalColorScheme[] = [] let themes: ITerminalColorScheme[] = []
plugins.forEach(plugin => { plugins.forEach(plugin => {
let module = (<any>global).require(path.join(pluginsPath, plugin)) let module = (global as any).require(path.join(pluginsPath, plugin))
if (module.decorateConfig) { if (module.decorateConfig) {
let config = module.decorateConfig({}) let config = module.decorateConfig({})
if (config.colors) { if (config.colors) {

View File

@@ -1,7 +1,6 @@
import { Component, Input, Output, EventEmitter, HostListener, ViewChild } from '@angular/core' import { Component, Input, Output, EventEmitter, HostListener, ViewChild } from '@angular/core'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
@Component({ @Component({
selector: 'color-picker', selector: 'color-picker',
template: require('./colorPicker.component.pug'), template: require('./colorPicker.component.pug'),
@@ -29,7 +28,7 @@ export class ColorPickerComponent {
if (!this.isOpen) { if (!this.isOpen) {
return return
} }
let windowRef = (<any>this.popover)._windowRef let windowRef = (this.popover as any)._windowRef
if (!windowRef) { if (!windowRef) {
return return
} }

View File

@@ -12,7 +12,7 @@ import { TerminalColorSchemeProvider, ITerminalColorScheme } from '../api'
let Registry = null let Registry = null
try { try {
Registry = require('winreg') Registry = require('winreg')
} catch (_) { } } catch (_) { } // tslint:disable-line no-empty
interface IShell { interface IShell {
name: string name: string
@@ -31,19 +31,19 @@ export class TerminalSettingsTabComponent {
editingColorScheme: ITerminalColorScheme editingColorScheme: ITerminalColorScheme
schemeChanged = false schemeChanged = false
constructor( constructor (
public config: ConfigService, public config: ConfigService,
private hostApp: HostAppService, private hostApp: HostAppService,
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[], @Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
) { } ) { }
async ngOnInit () { async ngOnInit () {
if (this.hostApp.platform == Platform.Windows || this.hostApp.platform == Platform.macOS) { if (this.hostApp.platform === Platform.Windows || this.hostApp.platform === Platform.macOS) {
let fonts = await new Promise<any[]>((resolve) => fontManager.findFonts({ monospace: true }, resolve)) let fonts = await new Promise<any[]>((resolve) => fontManager.findFonts({ monospace: true }, resolve))
this.fonts = fonts.map(x => x.family) this.fonts = fonts.map(x => x.family)
this.fonts.sort() this.fonts.sort()
} }
if (this.hostApp.platform == Platform.Linux) { if (this.hostApp.platform === Platform.Linux) {
exec('fc-list :spacing=mono').then(([stdout, _]) => { exec('fc-list :spacing=mono').then(([stdout, _]) => {
this.fonts = stdout.toString() this.fonts = stdout.toString()
.split('\n') .split('\n')
@@ -53,18 +53,18 @@ export class TerminalSettingsTabComponent {
this.fonts.sort() this.fonts.sort()
}) })
} }
if (this.hostApp.platform == Platform.Windows) { if (this.hostApp.platform === Platform.Windows) {
this.shells = [ this.shells = [
{ name: 'CMD', command: 'cmd.exe' }, { name: 'CMD', command: 'cmd.exe' },
{ name: 'PowerShell', command: 'powershell.exe' }, { name: 'PowerShell', command: 'powershell.exe' },
] ]
const wslPath =`${process.env.windir}\\system32\\bash.exe` const wslPath = `${process.env.windir}\\system32\\bash.exe`
if (await fs.exists(wslPath)) { if (await fs.exists(wslPath)) {
this.shells.push({ name: 'Bash on Windows', command: wslPath }) this.shells.push({ name: 'Bash on Windows', command: wslPath })
} }
let cygwinPath = await new Promise<string>(resolve => { let cygwinPath = await new Promise<string>(resolve => {
let reg = new Registry({ hive: Registry.HKLM, key: "\\Software\\Cygwin\\setup" }) let reg = new Registry({ hive: Registry.HKLM, key: '\\Software\\Cygwin\\setup' })
reg.get('rootdir', (err, item) => { reg.get('rootdir', (err, item) => {
if (err) { if (err) {
resolve(null) resolve(null)
@@ -76,7 +76,7 @@ export class TerminalSettingsTabComponent {
this.shells.push({ name: 'Cygwin', command: path.join(cygwinPath, 'bin', 'bash.exe') }) this.shells.push({ name: 'Cygwin', command: path.join(cygwinPath, 'bin', 'bash.exe') })
} }
} }
if (this.hostApp.platform == Platform.Linux || this.hostApp.platform == Platform.macOS) { if (this.hostApp.platform === Platform.Linux || this.hostApp.platform === Platform.macOS) {
this.shells = (await fs.readFile('/etc/shells', 'utf-8')) this.shells = (await fs.readFile('/etc/shells', 'utf-8'))
.split('\n') .split('\n')
.map(x => x.trim()) .map(x => x.trim())

View File

@@ -7,13 +7,15 @@ import { Session } from '../services/sessions.service'
import { TerminalDecorator, ResizeEvent } from '../api' import { TerminalDecorator, ResizeEvent } from '../api'
import { hterm, preferenceManager } from '../hterm' import { hterm, preferenceManager } from '../hterm'
@Component({ @Component({
selector: 'terminalTab', selector: 'terminalTab',
template: '<div #content class="content" [style.opacity]="htermVisible ? 1 : 0"></div>', template: '<div #content class="content" [style.opacity]="htermVisible ? 1 : 0"></div>',
styles: [require('./terminalTab.component.scss')], styles: [require('./terminalTab.component.scss')],
}) })
export class TerminalTabComponent extends BaseTabComponent { export class TerminalTabComponent extends BaseTabComponent {
@Input() session: Session
@ViewChild('content') content
@HostBinding('style.background-color') backgroundColor: string
hterm: any hterm: any
configSubscription: Subscription configSubscription: Subscription
sessionCloseSubscription: Subscription sessionCloseSubscription: Subscription
@@ -25,12 +27,9 @@ export class TerminalTabComponent extends BaseTabComponent {
alternateScreenActive$ = new BehaviorSubject(false) alternateScreenActive$ = new BehaviorSubject(false)
mouseEvent$ = new Subject<Event>() mouseEvent$ = new Subject<Event>()
htermVisible = false htermVisible = false
@Input() session: Session
@ViewChild('content') content
@HostBinding('style.background-color') backgroundColor: string
private io: any private io: any
constructor( constructor (
private zone: NgZone, private zone: NgZone,
private app: AppService, private app: AppService,
private themes: ThemesService, private themes: ThemesService,
@@ -92,7 +91,7 @@ export class TerminalTabComponent extends BaseTabComponent {
}, 1000) }, 1000)
this.bell$.subscribe(() => { this.bell$.subscribe(() => {
if (this.config.store.terminal.bell != 'off') { if (this.config.store.terminal.bell !== 'off') {
let bg = preferenceManager.get('background-color') let bg = preferenceManager.get('background-color')
preferenceManager.set('background-color', 'rgba(128,128,128,.25)') preferenceManager.set('background-color', 'rgba(128,128,128,.25)')
setTimeout(() => { setTimeout(() => {
@@ -116,10 +115,10 @@ export class TerminalTabComponent extends BaseTabComponent {
this.alternateScreenActive$.next(state) this.alternateScreenActive$.next(state)
} }
const _onPaste_ = hterm.scrollPort_.onPaste_.bind(hterm.scrollPort_) const _onPaste = hterm.scrollPort_.onPaste_.bind(hterm.scrollPort_)
hterm.scrollPort_.onPaste_ = (event) => { hterm.scrollPort_.onPaste_ = (event) => {
hterm.scrollPort_.pasteTarget_.value = event.clipboardData.getData('text/plain').trim() hterm.scrollPort_.pasteTarget_.value = event.clipboardData.getData('text/plain').trim()
_onPaste_() _onPaste()
event.preventDefault() event.preventDefault()
} }
@@ -131,7 +130,7 @@ export class TerminalTabComponent extends BaseTabComponent {
_resize() _resize()
} }
const _onMouse_ = hterm.onMouse_.bind(hterm) const _onMouse = hterm.onMouse_.bind(hterm)
hterm.onMouse_ = (event) => { hterm.onMouse_ = (event) => {
this.mouseEvent$.next(event) this.mouseEvent$.next(event)
if ((event.ctrlKey || event.metaKey) && event.type === 'mousewheel') { if ((event.ctrlKey || event.metaKey) && event.type === 'mousewheel') {
@@ -139,7 +138,7 @@ export class TerminalTabComponent extends BaseTabComponent {
let delta = Math.round(event.wheelDeltaY / 50) let delta = Math.round(event.wheelDeltaY / 50)
this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta))) this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
} }
_onMouse_(event) _onMouse(event)
} }
hterm.ringBell = () => { hterm.ringBell = () => {
@@ -192,18 +191,18 @@ export class TerminalTabComponent extends BaseTabComponent {
preferenceManager.set('font-size', config.terminal.fontSize) preferenceManager.set('font-size', config.terminal.fontSize)
preferenceManager.set('enable-bold', true) preferenceManager.set('enable-bold', true)
preferenceManager.set('audible-bell-sound', '') preferenceManager.set('audible-bell-sound', '')
preferenceManager.set('desktop-notification-bell', config.terminal.bell == 'notification') preferenceManager.set('desktop-notification-bell', config.terminal.bell === 'notification')
preferenceManager.set('enable-clipboard-notice', false) preferenceManager.set('enable-clipboard-notice', false)
preferenceManager.set('receive-encoding', 'raw') preferenceManager.set('receive-encoding', 'raw')
preferenceManager.set('send-encoding', 'raw') preferenceManager.set('send-encoding', 'raw')
preferenceManager.set('ctrl-plus-minus-zero-zoom', false) preferenceManager.set('ctrl-plus-minus-zero-zoom', false)
preferenceManager.set('scrollbar-visible', this.hostApp.platform == Platform.macOS) preferenceManager.set('scrollbar-visible', this.hostApp.platform === Platform.macOS)
preferenceManager.set('copy-on-select', false) preferenceManager.set('copy-on-select', false)
if (config.terminal.colorScheme.foreground) { if (config.terminal.colorScheme.foreground) {
preferenceManager.set('foreground-color', config.terminal.colorScheme.foreground) preferenceManager.set('foreground-color', config.terminal.colorScheme.foreground)
} }
if (config.terminal.background == 'colorScheme') { if (config.terminal.background === 'colorScheme') {
if (config.terminal.colorScheme.background) { if (config.terminal.colorScheme.background) {
this.backgroundColor = config.terminal.colorScheme.background this.backgroundColor = config.terminal.colorScheme.background
preferenceManager.set('background-color', config.terminal.colorScheme.background) preferenceManager.set('background-color', config.terminal.colorScheme.background)

View File

@@ -1,6 +1,5 @@
import { ConfigProvider, Platform } from 'terminus-core' import { ConfigProvider, Platform } from 'terminus-core'
export class TerminalConfigProvider extends ConfigProvider { export class TerminalConfigProvider extends ConfigProvider {
defaults = { defaults = {
terminal: { terminal: {

View File

@@ -3,12 +3,11 @@ export const hterm = require('hterm-commonjs')
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory() hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
export const preferenceManager = new hterm.hterm.PreferenceManager('default') export const preferenceManager = new hterm.hterm.PreferenceManager('default')
hterm.hterm.VT.ESC['k'] = function (parseState) {
parseState.resetArguments()
hterm.hterm.VT.ESC['k'] = function(parseState) { function parseOSC (ps) {
parseState.resetArguments(); if (!this.parseUntilStringTerminator_(ps) || ps.func === parseOSC) {
function parseOSC(ps) {
if (!this.parseUntilStringTerminator_(ps) || ps.func == parseOSC) {
return return
} }

View File

@@ -21,7 +21,6 @@ import { TerminalConfigProvider } from './config'
import { HyperColorSchemes } from './colorSchemes' import { HyperColorSchemes } from './colorSchemes'
import { hterm } from './hterm' import { hterm } from './hterm'
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
@@ -36,10 +35,10 @@ import { hterm } from './hterm'
{ {
provide: SessionPersistenceProvider, provide: SessionPersistenceProvider,
useFactory: (hostApp: HostAppService, screen: ScreenPersistenceProvider) => { useFactory: (hostApp: HostAppService, screen: ScreenPersistenceProvider) => {
if (hostApp.platform == Platform.Windows) { if (hostApp.platform === Platform.Windows) {
return null return null
} else { } else {
return screen return screen
} }
}, },
deps: [HostAppService, ScreenPersistenceProvider], deps: [HostAppService, ScreenPersistenceProvider],
@@ -74,7 +73,7 @@ export default class TerminalModule {
let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler] let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler]
hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) { hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) {
hotkeys.pushKeystroke(event.name, nativeEvent) hotkeys.pushKeystroke(event.name, nativeEvent)
if (hotkeys.getCurrentPartiallyMatchedHotkeys().length == 0) { if (hotkeys.getCurrentPartiallyMatchedHotkeys().length === 0) {
oldHandler.bind(this)(nativeEvent) oldHandler.bind(this)(nativeEvent)
} else { } else {
nativeEvent.stopPropagation() nativeEvent.stopPropagation()

View File

@@ -7,7 +7,6 @@ import { Injectable } from '@angular/core'
import { Logger, LogService } from 'terminus-core' import { Logger, LogService } from 'terminus-core'
import { SessionOptions, SessionPersistenceProvider } from './api' import { SessionOptions, SessionPersistenceProvider } from './api'
interface IChildProcess { interface IChildProcess {
pid: number pid: number
ppid: number ppid: number
@@ -52,16 +51,16 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider {
return null return null
} }
let truePID_ = new AsyncSubject<number>() let truePID$ = new AsyncSubject<number>()
this.extractShellPID(screenPID).then(pid => { this.extractShellPID(screenPID).then(pid => {
truePID_.next(pid) truePID$.next(pid)
truePID_.complete() truePID$.complete()
}) })
return { return {
recoveryId, recoveryId,
recoveredTruePID$: truePID_.asObservable(), recoveredTruePID$: truePID$.asObservable(),
command: 'screen', command: 'screen',
args: ['-r', recoveryId], args: ['-r', recoveryId],
} }
@@ -74,7 +73,7 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider {
throw new Error(`Could not find any children of the screen process (PID ${screenPID})!`) throw new Error(`Could not find any children of the screen process (PID ${screenPID})!`)
} }
if (child.command == 'login') { if (child.command === 'login') {
await delay(1000) await delay(1000)
child = (await listProcesses()).find(x => x.ppid === child.pid) child = (await listProcesses()).find(x => x.ppid === child.pid)
} }

View File

@@ -4,7 +4,6 @@ import { TabRecoveryProvider, AppService } from 'terminus-core'
import { TerminalTabComponent } from './components/terminalTab.component' import { TerminalTabComponent } from './components/terminalTab.component'
import { SessionsService } from './services/sessions.service' import { SessionsService } from './services/sessions.service'
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
constructor ( constructor (
@@ -15,7 +14,7 @@ export class RecoveryProvider extends TabRecoveryProvider {
} }
async recover (recoveryToken: any): Promise<void> { async recover (recoveryToken: any): Promise<void> {
if (recoveryToken.type == 'app:terminal') { if (recoveryToken.type === 'app:terminal') {
let session = await this.sessions.recover(recoveryToken.recoveryId) let session = await this.sessions.recover(recoveryToken.recoveryId)
if (!session) { if (!session) {
return return

View File

@@ -7,7 +7,6 @@ import { exec } from 'mz/child_process'
import { SessionOptions, SessionPersistenceProvider } from '../api' import { SessionOptions, SessionPersistenceProvider } from '../api'
export class Session { export class Session {
open: boolean open: boolean
name: string name: string
@@ -34,9 +33,7 @@ export class Session {
options.command = 'sh' options.command = 'sh'
} }
this.pty = nodePTY.spawn(options.command, options.args || [], { this.pty = nodePTY.spawn(options.command, options.args || [], {
//name: 'screen-256color',
name: 'xterm-256color', name: 'xterm-256color',
//name: 'xterm-color',
cols: 80, cols: 80,
rows: 30, rows: 30,
cwd: options.cwd || process.env.HOME, cwd: options.cwd || process.env.HOME,
@@ -48,7 +45,7 @@ export class Session {
this.truePID = pid this.truePID = pid
}) })
} else { } else {
this.truePID = (<any>this.pty).pid this.truePID = (this.pty as any).pid
} }
this.open = true this.open = true
@@ -87,7 +84,7 @@ export class Session {
} }
async gracefullyKillProcess (): Promise<void> { async gracefullyKillProcess (): Promise<void> {
if (process.platform == 'win32') { if (process.platform === 'win32') {
this.kill() this.kill()
} else { } else {
await new Promise((resolve) => { await new Promise((resolve) => {
@@ -119,32 +116,31 @@ export class Session {
} }
async getWorkingDirectory (): Promise<string> { async getWorkingDirectory (): Promise<string> {
if (process.platform == 'darwin') { if (process.platform === 'darwin') {
let lines = (await exec(`lsof -p ${this.truePID} -Fn`))[0].toString().split('\n') let lines = (await exec(`lsof -p ${this.truePID} -Fn`))[0].toString().split('\n')
return lines[2].substring(1) return lines[2].substring(1)
} }
if (process.platform == 'linux') { if (process.platform === 'linux') {
return await fs.readlink(`/proc/${this.truePID}/cwd`) return await fs.readlink(`/proc/${this.truePID}/cwd`)
} }
return null return null
} }
} }
@Injectable() @Injectable()
export class SessionsService { export class SessionsService {
sessions: {[id: string]: Session} = {} sessions: {[id: string]: Session} = {}
logger: Logger logger: Logger
private lastID = 0 private lastID = 0
constructor( constructor (
private persistence: SessionPersistenceProvider, private persistence: SessionPersistenceProvider,
log: LogService, log: LogService,
) { ) {
this.logger = log.create('sessions') this.logger = log.create('sessions')
} }
async createNewSession (options: SessionOptions) : Promise<Session> { async createNewSession (options: SessionOptions): Promise<Session> {
if (this.persistence) { if (this.persistence) {
let recoveryId = await this.persistence.startSession(options) let recoveryId = await this.persistence.startSession(options)
options = await this.persistence.attachSession(recoveryId) options = await this.persistence.attachSession(recoveryId)
@@ -153,7 +149,7 @@ export class SessionsService {
return session return session
} }
addSession (options: SessionOptions) : Session { addSession (options: SessionOptions): Session {
this.lastID++ this.lastID++
options.name = `session-${this.lastID}` options.name = `session-${this.lastID}`
let session = new Session(options) let session = new Session(options)
@@ -167,7 +163,7 @@ export class SessionsService {
return session return session
} }
async recover (recoveryId: string) : Promise<Session> { async recover (recoveryId: string): Promise<Session> {
if (!this.persistence) { if (!this.persistence) {
return null return null
} }

View File

@@ -3,7 +3,6 @@ import { SettingsTabProvider, ComponentType } from 'terminus-settings'
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component' import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
@Injectable() @Injectable()
export class TerminalSettingsTabProvider extends SettingsTabProvider { export class TerminalSettingsTabProvider extends SettingsTabProvider {
title = 'Terminal' title = 'Terminal'

View File

@@ -1,7 +1,6 @@
import { NgModule, Injectable } from '@angular/core' import { NgModule, Injectable } from '@angular/core'
import { Theme } from 'terminus-core' import { Theme } from 'terminus-core'
@Injectable() @Injectable()
class HypeTheme extends Theme { class HypeTheme extends Theme {
name = 'Hype' name = 'Hype'
@@ -9,7 +8,6 @@ class HypeTheme extends Theme {
terminalBackground = '#010101' terminalBackground = '#010101'
} }
@NgModule({ @NgModule({
providers: [ providers: [
{ provide: Theme, useClass: HypeTheme, multi: true }, { provide: Theme, useClass: HypeTheme, multi: true },

View File

@@ -1,31 +1,20 @@
{ {
"rulesDirectory": [ "extends": [
"node_modules/vrsource-tslint-rules/rules", "tslint-eslint-rules",
"node_modules/tslint-eslint-rules/dist/rules" "tslint-config-standard"
],
"rules": {
"radix": false,
"indent": [
true,
"spaces"
], ],
"rules": { "ter-indent": [true, 4],
"no-duplicate-imports": true, "trailing-comma": [
"no-duplicate-variable": true, true,
"no-jasmine-focus": true, {
"no-var-keyword": true, "singleline": "never"
"no-eval": true, }
"no-shadowed-variable": true, ]
"no-undef": true, }
"no-unused-expression": true,
"no-unused-new": true,
"no-unused-variable": true,
"no-use-before-declare": true,
"require-internal-with-underscore": true,
"semicolon": [
false
],
"variable-name": [
true,
"ban-keywords"
],
"no-inner-declarations": [
true,
"function"
]
}
} }