diff --git a/tmp/assets/activity.png b/tmp/assets/activity.png deleted file mode 100644 index adc9b6f8..00000000 Binary files a/tmp/assets/activity.png and /dev/null differ diff --git a/tmp/assets/logo.svg b/tmp/assets/logo.svg deleted file mode 100644 index e6eeb7a0..00000000 --- a/tmp/assets/logo.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tmp/assets/tray-darwinHighlightTemplate.png b/tmp/assets/tray-darwinHighlightTemplate.png deleted file mode 100644 index ca1065ee..00000000 Binary files a/tmp/assets/tray-darwinHighlightTemplate.png and /dev/null differ diff --git a/tmp/assets/tray-darwinHighlightTemplate@2x.png b/tmp/assets/tray-darwinHighlightTemplate@2x.png deleted file mode 100644 index fda38f28..00000000 Binary files a/tmp/assets/tray-darwinHighlightTemplate@2x.png and /dev/null differ diff --git a/tmp/assets/tray-darwinTemplate.png b/tmp/assets/tray-darwinTemplate.png deleted file mode 100644 index 11b1a940..00000000 Binary files a/tmp/assets/tray-darwinTemplate.png and /dev/null differ diff --git a/tmp/assets/tray-darwinTemplate@2x.png b/tmp/assets/tray-darwinTemplate@2x.png deleted file mode 100644 index eda5bbf3..00000000 Binary files a/tmp/assets/tray-darwinTemplate@2x.png and /dev/null differ diff --git a/tmp/assets/tray.png b/tmp/assets/tray.png deleted file mode 100644 index e91d83a7..00000000 Binary files a/tmp/assets/tray.png and /dev/null differ diff --git a/tmp/dev-app-update.yml b/tmp/dev-app-update.yml deleted file mode 100644 index e95e81c4..00000000 --- a/tmp/dev-app-update.yml +++ /dev/null @@ -1,4 +0,0 @@ -owner: eugeny -repo: terminus -provider: github -updaterCacheDirName: terminus-updater diff --git a/tmp/index.pug b/tmp/index.pug deleted file mode 100644 index 4a689daf..00000000 --- a/tmp/index.pug +++ /dev/null @@ -1,22 +0,0 @@ -doctype html -html - head - meta(charset='UTF-8') - base(href='index.html') - script. - console.timeStamp('index') - window.nodeRequire = require - script(src='./preload.js') - script(src='./bundle.js', defer) - style. - body { transition: 0.5s background; } - body - style#custom-css - app-root - .preload-logo - div - .terminus-logo - h1.terminus-title Terminus - sup α - .progress - .bar(style='width: 0%') diff --git a/tmp/lib/app.ts b/tmp/lib/app.ts deleted file mode 100644 index 329892e5..00000000 --- a/tmp/lib/app.ts +++ /dev/null @@ -1,230 +0,0 @@ -import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron' -import { loadConfig } from './config' -import { Window, WindowOptions } from './window' - -export class Application { - private tray: Tray - private windows: Window[] = [] - - constructor () { - ipcMain.on('app:config-change', (_event, config) => { - this.broadcast('host:config-change', config) - }) - - ipcMain.on('app:register-global-hotkey', (_event, specs) => { - globalShortcut.unregisterAll() - for (const spec of specs) { - globalShortcut.register(spec, () => { - this.onGlobalHotkey() - }) - } - }) - - const configData = loadConfig() - if (process.platform === 'linux') { - app.commandLine.appendSwitch('no-sandbox') - if (((configData.appearance || {}).opacity || 1) !== 1) { - app.commandLine.appendSwitch('enable-transparent-visuals') - app.disableHardwareAcceleration() - } - } - - app.commandLine.appendSwitch('disable-http-cache') - app.commandLine.appendSwitch('lang', 'EN') - app.allowRendererProcessReuse = false - - for (const flag of configData.flags || [['force_discrete_gpu', '0']]) { - app.commandLine.appendSwitch(flag[0], flag[1]) - } - } - - init (): void { - screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed')) - screen.on('display-added', () => this.broadcast('host:displays-changed')) - screen.on('display-removed', () => this.broadcast('host:displays-changed')) - } - - async newWindow (options?: WindowOptions): Promise { - const window = new Window(options) - this.windows.push(window) - window.visible$.subscribe(visible => { - if (visible) { - this.disableTray() - } else { - this.enableTray() - } - }) - window.closed$.subscribe(() => { - this.windows = this.windows.filter(x => x !== window) - }) - if (process.platform === 'darwin') { - this.setupMenu() - } - await window.ready - return window - } - - onGlobalHotkey (): void { - if (this.windows.some(x => x.isFocused())) { - for (const window of this.windows) { - window.hide() - } - } else { - for (const window of this.windows) { - window.present() - } - } - } - - presentAllWindows (): void { - for (const window of this.windows) { - window.present() - } - } - - broadcast (event: string, ...args: any[]): void { - for (const window of this.windows) { - window.send(event, ...args) - } - } - - async send (event: string, ...args: any[]): Promise { - if (!this.hasWindows()) { - await this.newWindow() - } - this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args) - } - - enableTray (): void { - if (this.tray) { - return - } - if (process.platform === 'darwin') { - this.tray = new Tray(`${app.getAppPath()}/assets/tray-darwinTemplate.png`) - this.tray.setPressedImage(`${app.getAppPath()}/assets/tray-darwinHighlightTemplate.png`) - } else { - this.tray = new Tray(`${app.getAppPath()}/assets/tray.png`) - } - - this.tray.on('click', () => setTimeout(() => this.focus())) - - const contextMenu = Menu.buildFromTemplate([{ - label: 'Show', - click: () => this.focus(), - }]) - - if (process.platform !== 'darwin') { - this.tray.setContextMenu(contextMenu) - } - - this.tray.setToolTip(`Terminus ${app.getVersion()}`) - } - - disableTray (): void { - if (this.tray) { - this.tray.destroy() - this.tray = null - } - } - - hasWindows (): boolean { - return !!this.windows.length - } - - focus (): void { - for (const window of this.windows) { - window.show() - } - } - - handleSecondInstance (argv: string[], cwd: string): void { - this.presentAllWindows() - this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd) - } - - private setupMenu () { - const template: MenuItemConstructorOptions[] = [ - { - label: 'Application', - submenu: [ - { role: 'about', label: 'About Terminus' }, - { type: 'separator' }, - { - label: 'Preferences', - accelerator: 'Cmd+,', - click: async () => { - if (!this.hasWindows()) { - await this.newWindow() - } - this.windows[0].send('host:preferences-menu') - }, - }, - { type: 'separator' }, - { role: 'services', submenu: [] }, - { type: 'separator' }, - { role: 'hide' }, - { role: 'hideOthers' }, - { role: 'unhide' }, - { type: 'separator' }, - { - label: 'Quit', - accelerator: 'Cmd+Q', - click () { - app.quit() - }, - }, - ], - }, - { - label: 'Edit', - submenu: [ - { role: 'undo' }, - { role: 'redo' }, - { type: 'separator' }, - { role: 'cut' }, - { role: 'copy' }, - { role: 'paste' }, - { role: 'pasteAndMatchStyle' }, - { role: 'delete' }, - { role: 'selectAll' }, - ], - }, - { - label: 'View', - submenu: [ - { role: 'reload' }, - { role: 'forceReload' }, - { role: 'toggleDevTools' }, - { type: 'separator' }, - { role: 'resetZoom' }, - { role: 'zoomIn' }, - { role: 'zoomOut' }, - { type: 'separator' }, - { role: 'togglefullscreen' }, - ], - }, - { - role: 'window', - submenu: [ - { role: 'minimize' }, - { role: 'zoom' }, - { type: 'separator' }, - { role: 'front' }, - ], - }, - { - role: 'help', - submenu: [ - { - label: 'Website', - click () { - shell.openExternal('https://eugeny.github.io/terminus') - }, - }, - ], - }, - ] - - Menu.setApplicationMenu(Menu.buildFromTemplate(template)) - } -} diff --git a/tmp/lib/cli.ts b/tmp/lib/cli.ts deleted file mode 100644 index 66290f70..00000000 --- a/tmp/lib/cli.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { app } from 'electron' - -export function parseArgs (argv: string[], cwd: string): any { - if (argv[0].includes('node')) { - argv = argv.slice(1) - } - - return require('yargs') - .usage('terminus [command] [arguments]') - .command('open [directory]', 'open a shell in a directory', { - directory: { type: 'string', 'default': cwd }, - }) - .command('run [command...]', 'run a command in the terminal', { - command: { type: 'string' }, - }) - .command('profile [profileName]', 'open a tab with specified profile', { - profileName: { type: 'string' }, - }) - .command('paste [text]', 'paste stdin into the active tab', yargs => { - return yargs.option('escape', { - alias: 'e', - type: 'boolean', - describe: 'Perform shell escaping', - }).positional('text', { - type: 'string', - }) - }) - .version('version', '', app.getVersion()) - .option('debug', { - alias: 'd', - describe: 'Show DevTools on start', - type: 'boolean', - }) - .option('hidden', { - describe: 'Start minimized', - type: 'boolean', - }) - .option('version', { - alias: 'v', - describe: 'Show version and exit', - type: 'boolean', - }) - .help('help') - .parse(argv.slice(1)) -} diff --git a/tmp/lib/config.ts b/tmp/lib/config.ts deleted file mode 100644 index 8ef3d529..00000000 --- a/tmp/lib/config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as fs from 'fs' -import * as path from 'path' -import * as yaml from 'js-yaml' -import { app } from 'electron' - -export function loadConfig (): any { - const configPath = path.join(app.getPath('userData'), 'config.yaml') - if (fs.existsSync(configPath)) { - return yaml.safeLoad(fs.readFileSync(configPath, 'utf8')) - } else { - return {} - } -} diff --git a/tmp/lib/index.ts b/tmp/lib/index.ts deleted file mode 100644 index 49f08dc0..00000000 --- a/tmp/lib/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -import './portable' -import './sentry' -import './lru' -import { app, ipcMain, Menu } from 'electron' -import { parseArgs } from './cli' -import { Application } from './app' -import electronDebug = require('electron-debug') - -if (!process.env.TERMINUS_PLUGINS) { - process.env.TERMINUS_PLUGINS = '' -} - -const application = new Application() - -ipcMain.on('app:new-window', () => { - application.newWindow() -}) - -app.on('activate', () => { - if (!application.hasWindows()) { - application.newWindow() - } else { - application.focus() - } -}) - -app.on('window-all-closed', () => { - app.quit() -}) - -process.on('uncaughtException' as any, err => { - console.log(err) - application.broadcast('uncaughtException', err) -}) - -app.on('second-instance', (_event, argv, cwd) => { - application.handleSecondInstance(argv, cwd) -}) - -const argv = parseArgs(process.argv, process.cwd()) - -if (!app.requestSingleInstanceLock()) { - app.quit() - app.exit(0) -} - -if (argv.d) { - electronDebug({ - isEnabled: true, - showDevTools: true, - devToolsMode: 'undocked', - }) -} - -app.on('ready', () => { - if (process.platform === 'darwin') { - app.dock.setMenu(Menu.buildFromTemplate([ - { - label: 'New window', - click () { - this.app.newWindow() - }, - }, - ])) - } - application.init() - application.newWindow({ hidden: argv.hidden }) -}) diff --git a/tmp/lib/lru.ts b/tmp/lib/lru.ts deleted file mode 100644 index b79ad003..00000000 --- a/tmp/lib/lru.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as LRU from 'lru-cache' -import * as fs from 'fs' -const lru = new LRU({ max: 256, maxAge: 250 }) -const origLstat = fs.realpathSync.bind(fs) - -// NB: The biggest offender of thrashing realpathSync is the node module system -// itself, which we can't get into via any sane means. -require('fs').realpathSync = function (p) { - let r = lru.get(p) - if (r) { - return r - } - - r = origLstat(p) - lru.set(p, r) - return r -} diff --git a/tmp/lib/portable.ts b/tmp/lib/portable.ts deleted file mode 100644 index 2fbcf461..00000000 --- a/tmp/lib/portable.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as path from 'path' -import * as fs from 'fs' - -let appPath: string | null = null -try { - appPath = path.dirname(require('electron').app.getPath('exe')) -} catch { - appPath = path.dirname(require('electron').remote.app.getPath('exe')) -} - -if (null != appPath) { - if (fs.existsSync(path.join(appPath, 'terminus-data'))) { - fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data')) - } - const portableData = path.join(appPath, 'data') - if (fs.existsSync(portableData)) { - console.log('reset user data to ' + portableData) - try { - require('electron').app.setPath('userData', portableData) - } catch { - require('electron').remote.app.setPath('userData', portableData) - } - } -} diff --git a/tmp/lib/sentry.ts b/tmp/lib/sentry.ts deleted file mode 100644 index d87c9538..00000000 --- a/tmp/lib/sentry.ts +++ /dev/null @@ -1,21 +0,0 @@ -const { init } = String(process.type) === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer') -import * as isDev from 'electron-is-dev' - - -const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876' -let release = null -try { - release = require('electron').app.getVersion() -} catch { - release = require('electron').remote.app.getVersion() -} - -if (!isDev) { - init({ - dsn: SENTRY_DSN, - release, - integrations (integrations) { - return integrations.filter(integration => integration.name !== 'Breadcrumbs') - }, - }) -} diff --git a/tmp/lib/window.ts b/tmp/lib/window.ts deleted file mode 100644 index bad3db3d..00000000 --- a/tmp/lib/window.ts +++ /dev/null @@ -1,389 +0,0 @@ -import * as glasstron from 'glasstron' -if (process.platform === 'win32' || process.platform === 'linux') { - glasstron.init() -} - -import { Subject, Observable } from 'rxjs' -import { debounceTime } from 'rxjs/operators' -import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen, BrowserWindowConstructorOptions } from 'electron' -import ElectronConfig = require('electron-config') -import * as os from 'os' -import * as path from 'path' - -import { parseArgs } from './cli' -import { loadConfig } from './config' - -let DwmEnableBlurBehindWindow: any = null -if (process.platform === 'win32') { - DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow -} - -export interface WindowOptions { - hidden?: boolean -} - -export class Window { - ready: Promise - private visible = new Subject() - private closed = new Subject() - private window: BrowserWindow - private windowConfig: ElectronConfig - private windowBounds: Rectangle - private closing = false - private lastVibrancy: {enabled: boolean, type?: string} | null = null - private disableVibrancyWhileDragging = false - private configStore: any - - get visible$ (): Observable { return this.visible } - get closed$ (): Observable { return this.closed } - - constructor (options?: WindowOptions) { - this.configStore = loadConfig() - - options = options || {} - - this.windowConfig = new ElectronConfig({ name: 'window' }) - this.windowBounds = this.windowConfig.get('windowBoundaries') - - const maximized = this.windowConfig.get('maximized') - const bwOptions: BrowserWindowConstructorOptions = { - width: 800, - height: 600, - title: 'Terminus', - minWidth: 400, - minHeight: 300, - webPreferences: { - nodeIntegration: true, - preload: path.join(__dirname, 'sentry.js'), - backgroundThrottling: false, - enableRemoteModule: true, - }, - frame: false, - show: false, - backgroundColor: '#00000000', - } - - if (this.windowBounds) { - Object.assign(bwOptions, this.windowBounds) - const closestDisplay = screen.getDisplayNearestPoint( { x: this.windowBounds.x, y: this.windowBounds.y } ) - - const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height] - const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height] - - if ((left2 > right1 || right2 < left1 || top2 > bottom1 || bottom2 < top1) && !maximized) { - bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2 - bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2 - } - } - - if ((this.configStore.appearance || {}).frame === 'native') { - bwOptions.frame = true - } else { - if (process.platform === 'darwin') { - bwOptions.titleBarStyle = 'hiddenInset' - } - } - - this.window = new BrowserWindow(bwOptions) - - this.window.once('ready-to-show', () => { - if (process.platform === 'darwin') { - this.window.setVibrancy('window') - } else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) { - this.setVibrancy(true) - } - - if (!options.hidden) { - if (maximized) { - this.window.maximize() - } else { - this.window.show() - } - this.window.focus() - this.window.moveTop() - } - }) - - this.window.on('blur', () => { - if (this.configStore.appearance?.dockHideOnBlur) { - this.hide() - } - }) - - this.window.loadURL(`file://${app.getAppPath()}/dist/index.html?${this.window.id}`, { extraHeaders: 'pragma: no-cache\n' }) - - if (process.platform !== 'darwin') { - this.window.setMenu(null) - } - - this.setupWindowManagement() - - this.ready = new Promise(resolve => { - const listener = event => { - if (event.sender === this.window.webContents) { - ipcMain.removeListener('app:ready', listener as any) - resolve() - } - } - ipcMain.on('app:ready', listener) - }) - } - - setVibrancy (enabled: boolean, type?: string): void { - this.lastVibrancy = { enabled, type } - if (process.platform === 'win32') { - if (parseFloat(os.release()) >= 10) { - glasstron.update(this.window, { - windows: { blurType: enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null }, - }) - } else { - DwmEnableBlurBehindWindow(this.window, enabled) - } - } else if (process.platform === 'linux') { - glasstron.update(this.window, { - linux: { requestBlur: enabled }, - }) - this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27') - } else { - this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269 - } - } - - show (): void { - this.window.show() - this.window.moveTop() - } - - focus (): void { - this.window.focus() - } - - send (event: string, ...args: any[]): void { - if (!this.window) { - return - } - this.window.webContents.send(event, ...args) - if (event === 'host:config-change') { - this.configStore = args[0] - } - } - - isDestroyed (): boolean { - return !this.window || this.window.isDestroyed() - } - - isFocused (): boolean { - return this.window.isFocused() - } - - hide (): void { - if (process.platform === 'darwin') { - // Lose focus - Menu.sendActionToFirstResponder('hide:') - } - this.window.blur() - if (process.platform !== 'darwin') { - this.window.hide() - } - } - - present (): void { - if (!this.window.isVisible()) { - // unfocused, invisible - this.window.show() - this.window.focus() - } else { - if (!this.configStore.appearance?.dock || this.configStore.appearance?.dock === 'off') { - // not docked, visible - setTimeout(() => { - this.window.show() - this.window.focus() - }) - } else { - if (this.configStore.appearance?.dockAlwaysOnTop) { - // docked, visible, on top - this.window.hide() - } else { - // docked, visible, not on top - this.window.focus() - } - } - } - } - - handleSecondInstance (argv: string[], cwd: string): void { - this.send('host:second-instance', parseArgs(argv, cwd), cwd) - } - - private setupWindowManagement () { - this.window.on('show', () => { - this.visible.next(true) - this.send('host:window-shown') - }) - - this.window.on('hide', () => { - this.visible.next(false) - }) - - const moveSubscription = new Observable(observer => { - this.window.on('move', () => observer.next()) - }).pipe(debounceTime(250)).subscribe(() => { - this.send('host:window-moved') - }) - - this.window.on('closed', () => { - moveSubscription.unsubscribe() - }) - - this.window.on('enter-full-screen', () => this.send('host:window-enter-full-screen')) - this.window.on('leave-full-screen', () => this.send('host:window-leave-full-screen')) - - this.window.on('close', event => { - if (!this.closing) { - event.preventDefault() - this.send('host:window-close-request') - return - } - this.windowConfig.set('windowBoundaries', this.windowBounds) - this.windowConfig.set('maximized', this.window.isMaximized()) - }) - - this.window.on('closed', () => { - this.destroy() - }) - - this.window.on('resize', () => { - if (!this.window.isMaximized()) { - this.windowBounds = this.window.getBounds() - } - }) - - this.window.on('move', () => { - if (!this.window.isMaximized()) { - this.windowBounds = this.window.getBounds() - } - }) - - this.window.on('focus', () => { - this.send('host:window-focused') - }) - - ipcMain.on('window-focus', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.focus() - }) - - ipcMain.on('window-maximize', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.maximize() - }) - - ipcMain.on('window-unmaximize', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.unmaximize() - }) - - ipcMain.on('window-toggle-maximize', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - if (this.window.isMaximized()) { - this.window.unmaximize() - } else { - this.window.maximize() - } - }) - - ipcMain.on('window-minimize', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.minimize() - }) - - ipcMain.on('window-set-bounds', (event, bounds) => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.setBounds(bounds) - }) - - ipcMain.on('window-set-always-on-top', (event, flag) => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.setAlwaysOnTop(flag) - }) - - ipcMain.on('window-set-vibrancy', (event, enabled, type) => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.setVibrancy(enabled, type) - }) - - ipcMain.on('window-set-title', (event, title) => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.window.setTitle(title) - }) - - ipcMain.on('window-bring-to-front', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - if (this.window.isMinimized()) { - this.window.restore() - } - this.window.show() - this.window.moveTop() - }) - - ipcMain.on('window-close', event => { - if (!this.window || event.sender !== this.window.webContents) { - return - } - this.closing = true - this.window.close() - }) - - this.window.webContents.on('new-window', event => event.preventDefault()) - - ipcMain.on('window-set-disable-vibrancy-while-dragging', (_event, value) => { - this.disableVibrancyWhileDragging = value - }) - - this.window.on('will-move', () => { - if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) { - return - } - let timeout: number|null = null - const oldVibrancy = this.lastVibrancy - this.setVibrancy(false) - const onMove = () => { - if (timeout) { - clearTimeout(timeout) - } - timeout = setTimeout(() => { - this.window.off('move', onMove) - this.setVibrancy(oldVibrancy.enabled, oldVibrancy.type) - }, 500) - } - this.window.on('move', onMove) - }) - } - - private destroy () { - this.window = null - this.closed.next() - this.visible.complete() - this.closed.complete() - } -} diff --git a/tmp/package.json b/tmp/package.json deleted file mode 100644 index 1eb5e3a7..00000000 --- a/tmp/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "terminus", - "description": "A terminal for a modern age", - "repository": "https://github.com/eugeny/terminus", - "author": { - "name": "Eugene Pankov", - "email": "e@ajenti.org" - }, - "main": "dist/main.js", - "version": "1.0.123-nightly.0", - "dependencies": { - "@angular/animations": "^9.1.9", - "@angular/common": "^9.1.11", - "@angular/compiler": "^9.1.9", - "@angular/core": "^9.1.9", - "@angular/forms": "^9.1.11", - "@angular/platform-browser": "^9.1.9", - "@angular/platform-browser-dynamic": "^9.1.9", - "@ng-bootstrap/ng-bootstrap": "^6.1.0", - "@terminus-term/node-pty": "0.10.0-beta10", - "devtron": "1.4.0", - "electron-config": "2.0.0", - "electron-debug": "^3.0.1", - "electron-is-dev": "1.1.0", - "fontmanager-redux": "1.0.0", - "glasstron": "AryToNeX/Glasstron#dependabot/npm_and_yarn/electron-11.1.0", - "js-yaml": "3.14.0", - "keytar": "^7.2.0", - "mz": "^2.7.0", - "ngx-toastr": "^12.0.1", - "npm": "7.0.15", - "path": "0.12.7", - "rxjs": "^6.5.5", - "rxjs-compat": "^6.6.0", - "yargs": "^15.4.1", - "zone.js": "^0.11.3" - }, - "optionalDependencies": { - "macos-native-processlist": "^2.0.0", - "serialport": "^9.0.4", - "windows-blurbehind": "^1.0.1", - "windows-native-registry": "^3.0.0", - "windows-process-tree": "^0.2.4" - }, - "peerDependencies": { - "terminus-core": "*", - "terminus-settings": "*", - "terminus-serial": "*", - "terminus-plugin-manager": "*", - "terminus-community-color-schemes": "*", - "terminus-ssh": "*", - "terminus-terminal": "*" - } -} \ No newline at end of file diff --git a/tmp/src/app.module.ts b/tmp/src/app.module.ts deleted file mode 100644 index d02296de..00000000 --- a/tmp/src/app.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { NgModule } from '@angular/core' -import { BrowserModule } from '@angular/platform-browser' -import { NgbModule } from '@ng-bootstrap/ng-bootstrap' -import { ToastrModule } from 'ngx-toastr' - -export function getRootModule (plugins: any[]) { - const imports = [ - BrowserModule, - ...plugins, - NgbModule, - ToastrModule.forRoot({ - positionClass: 'toast-bottom-center', - toastClass: 'toast', - preventDuplicates: true, - extendedTimeOut: 5000, - }), - ] - const bootstrap = [ - ...plugins.filter(x => x.bootstrap).map(x => x.bootstrap), - ] - - if (bootstrap.length === 0) { - throw new Error('Did not find any bootstrap components. Are there any plugins installed?') - } - - @NgModule({ - imports, - bootstrap, - }) class RootModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class - - return RootModule -} diff --git a/tmp/src/entry.preload.ts b/tmp/src/entry.preload.ts deleted file mode 100644 index ff76ec64..00000000 --- a/tmp/src/entry.preload.ts +++ /dev/null @@ -1,9 +0,0 @@ -import '../lib/lru' -import 'source-sans-pro/source-sans-pro.css' -import 'source-code-pro/source-code-pro.css' -import '@fortawesome/fontawesome-free/css/solid.css' -import '@fortawesome/fontawesome-free/css/brands.css' -import '@fortawesome/fontawesome-free/css/regular.css' -import '@fortawesome/fontawesome-free/css/fontawesome.css' -import 'ngx-toastr/toastr.css' -import './preload.scss' diff --git a/tmp/src/entry.ts b/tmp/src/entry.ts deleted file mode 100644 index b44cd153..00000000 --- a/tmp/src/entry.ts +++ /dev/null @@ -1,65 +0,0 @@ -import 'zone.js' -import 'core-js/proposals/reflect-metadata' -import 'rxjs' - -import * as isDev from 'electron-is-dev' - -import './global.scss' -import './toastr.scss' - -import { enableProdMode, NgModuleRef, ApplicationRef } from '@angular/core' -import { enableDebugTools } from '@angular/platform-browser' -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' - -import { getRootModule } from './app.module' -import { findPlugins, loadPlugins, PluginInfo } from './plugins' - -// Always land on the start view -location.hash = '' - -;(process as any).enablePromiseAPI = true - -if (process.platform === 'win32' && !('HOME' in process.env)) { - process.env.HOME = `${process.env.HOMEDRIVE}${process.env.HOMEPATH}` -} - -if (isDev) { - console.warn('Running in debug mode') -} else { - enableProdMode() -} - -async function bootstrap (plugins: PluginInfo[], safeMode = false): Promise> { - if (safeMode) { - plugins = plugins.filter(x => x.isBuiltin) - } - const pluginsModules = await loadPlugins(plugins, (current, total) => { - (document.querySelector('.progress .bar') as HTMLElement).style.width = `${100 * current / total}%` // eslint-disable-line - }) - const module = getRootModule(pluginsModules) - window['rootModule'] = module - return platformBrowserDynamic().bootstrapModule(module).then(moduleRef => { - if (isDev) { - const applicationRef = moduleRef.injector.get(ApplicationRef) - const componentRef = applicationRef.components[0] - enableDebugTools(componentRef) - } - return moduleRef - }) -} - -findPlugins().then(async plugins => { - console.log('Starting with plugins:', plugins) - try { - await bootstrap(plugins) - } catch (error) { - console.error('Angular bootstrapping error:', error) - console.warn('Trying safe mode') - window['safeModeReason'] = error - try { - await bootstrap(plugins, true) - } catch (error) { - console.error('Bootstrap failed:', error) - } - } -}) diff --git a/tmp/src/global.scss b/tmp/src/global.scss deleted file mode 100644 index 6f316ea7..00000000 --- a/tmp/src/global.scss +++ /dev/null @@ -1,97 +0,0 @@ -body { - min-height: 100vh; - overflow: hidden; - background: #1D272D; -} - -.modal-dialog, .modal-backdrop, .no-drag { - -webkit-app-region: no-drag; -} - -.selectable { - user-select: text; -} - -[ngbradiogroup] input[type="radio"] { - display: none; -} - -.btn { - & > svg { - pointer-events: none; - } -} - -.form-line { - display: flex; - border-top: 1px solid rgba(0, 0, 0, 0.2); - align-items: center; - padding: 10px 0; - margin: 0; - min-height: 64px; - - .header { - margin-right: auto; - - .title { - } - - .description { - font-size: 13px; - opacity: .5; - } - } - - &>.form-control, &>.input-group { - width: 33%; - } -} - -input[type=range] { - -webkit-appearance: none; - background: transparent; - outline: none; - padding: 0; - - &:focus { - border-color: transparent; - } - - @mixin thumb() { - -webkit-appearance: none; - display: block; - height: 12px; - width: 12px; - background: #aaa; - border-radius: 6px; - cursor: pointer; - margin-top: -4px; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.95); - transition: 0.25s background; - - &:hover { - background: #777; - } - - &:active { - background: #666; - } - } - - &::-webkit-slider-thumb { @include thumb(); } - &::-moz-range-thumb { @include thumb(); } - &::-ms-thumb { @include thumb(); } - &::thumb { @include thumb(); } - - @mixin track() { - height: 4px; - background: #111; - margin: 3px 0 0; - box-sizing: border-box; - } - - &::-webkit-slider-runnable-track { @include track(); } - &:focus::-webkit-slider-runnable-track { @include track(); } - &::-moz-range-track { @include track(); } - &::-ms-track { @include track(); } -} diff --git a/tmp/src/plugins.ts b/tmp/src/plugins.ts deleted file mode 100644 index 3ab58ec5..00000000 --- a/tmp/src/plugins.ts +++ /dev/null @@ -1,188 +0,0 @@ -import * as fs from 'mz/fs' -import * as path from 'path' -const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires -const nodeRequire = (global as any).require - -function normalizePath (path: string): string { - const cygwinPrefix = '/cygdrive/' - if (path.startsWith(cygwinPrefix)) { - path = path.substring(cygwinPrefix.length).replace('/', '\\') - path = path[0] + ':' + path.substring(1) - } - return path -} - -global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x))) - -if (process.env.TERMINUS_DEV) { - nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath())) -} - -const builtinPluginsPath = process.env.TERMINUS_DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins') - -const userPluginsPath = path.join( - require('electron').remote.app.getPath('userData'), - 'plugins', -) - -if (!fs.existsSync(userPluginsPath)) { - fs.mkdir(userPluginsPath) -} - -Object.assign(window, { builtinPluginsPath, userPluginsPath }) -nodeModule.globalPaths.unshift(builtinPluginsPath) -nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules')) -// nodeModule.globalPaths.unshift(path.join((process as any).resourcesPath, 'app.asar', 'node_modules')) -if (process.env.TERMINUS_PLUGINS) { - process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x))) -} - -export type ProgressCallback = (current: number, total: number) => void // eslint-disable-line @typescript-eslint/no-type-alias - -export interface PluginInfo { - name: string - description: string - packageName: string - isBuiltin: boolean - version: string - author: string - homepage?: string - path?: string - info?: any -} - -const builtinModules = [ - '@angular/animations', - '@angular/common', - '@angular/compiler', - '@angular/core', - '@angular/forms', - '@angular/platform-browser', - '@angular/platform-browser-dynamic', - '@ng-bootstrap/ng-bootstrap', - 'ngx-toastr', - 'rxjs', - 'rxjs/operators', - 'rxjs-compat/Subject', - 'terminus-core', - 'terminus-settings', - 'terminus-terminal', - 'zone.js/dist/zone.js', -] - -const cachedBuiltinModules = {} -builtinModules.forEach(m => { - const label = 'Caching ' + m - console.time(label) - cachedBuiltinModules[m] = nodeRequire(m) - console.timeEnd(label) -}) - -const originalRequire = (global as any).require -;(global as any).require = function (query: string) { - if (cachedBuiltinModules[query]) { - return cachedBuiltinModules[query] - } - return originalRequire.apply(this, [query]) -} - -const originalModuleRequire = nodeModule.prototype.require -nodeModule.prototype.require = function (query: string) { - if (cachedBuiltinModules[query]) { - return cachedBuiltinModules[query] - } - return originalModuleRequire.call(this, query) -} - -export async function findPlugins (): Promise { - const paths = nodeModule.globalPaths - let foundPlugins: PluginInfo[] = [] - const candidateLocations: { pluginDir: string, packageName: string }[] = [] - const PREFIX = 'terminus-' - - for (let pluginDir of paths) { - pluginDir = normalizePath(pluginDir) - if (!await fs.exists(pluginDir)) { - continue - } - const pluginNames = await fs.readdir(pluginDir) - if (await fs.exists(path.join(pluginDir, 'package.json'))) { - candidateLocations.push({ - pluginDir: path.dirname(pluginDir), - packageName: path.basename(pluginDir), - }) - } - for (const packageName of pluginNames) { - if (packageName.startsWith(PREFIX)) { - candidateLocations.push({ pluginDir, packageName }) - } - } - } - - for (const { pluginDir, packageName } of candidateLocations) { - const pluginPath = path.join(pluginDir, packageName) - const infoPath = path.join(pluginPath, 'package.json') - if (!await fs.exists(infoPath)) { - continue - } - - const name = packageName.substring(PREFIX.length) - - if (foundPlugins.some(x => x.name === name)) { - console.info(`Plugin ${packageName} already exists, overriding`) - foundPlugins = foundPlugins.filter(x => x.name !== name) - } - - try { - const info = JSON.parse(await fs.readFile(infoPath, { encoding: 'utf-8' })) - if (!info.keywords || !(info.keywords.includes('terminus-plugin') || info.keywords.includes('terminus-builtin-plugin'))) { - continue - } - let author = info.author - author = author.name || author - foundPlugins.push({ - name: name, - packageName: packageName, - isBuiltin: pluginDir === builtinPluginsPath, - version: info.version, - description: info.description, - author, - path: pluginPath, - info, - }) - } catch (error) { - console.error('Cannot load package info for', packageName) - } - } - - foundPlugins.sort((a, b) => a.name > b.name ? 1 : -1) - - ;(window as any).installedPlugins = foundPlugins - return foundPlugins -} - -export async function loadPlugins (foundPlugins: PluginInfo[], progress: ProgressCallback): Promise { - const plugins: any[] = [] - progress(0, 1) - let index = 0 - for (const foundPlugin of foundPlugins) { - console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`) - progress(index, foundPlugins.length) - try { - const label = 'Loading ' + foundPlugin.name - console.time(label) - const packageModule = nodeRequire(foundPlugin.path) - const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default - pluginModule['pluginName'] = foundPlugin.name - pluginModule['bootstrap'] = packageModule.bootstrap - plugins.push(pluginModule) - console.timeEnd(label) - await new Promise(x => setTimeout(x, 50)) - } catch (error) { - console.error(`Could not load ${foundPlugin.name}:`, error) - } - index++ - } - progress(1, 1) - return plugins -} diff --git a/tmp/src/preload.scss b/tmp/src/preload.scss deleted file mode 100644 index d7664cf5..00000000 --- a/tmp/src/preload.scss +++ /dev/null @@ -1,60 +0,0 @@ -.preload-logo { - -webkit-app-region: drag; - position: fixed; - left: 0; - top: 0; - width: 100vw; - height: 100vh; - display: flex; - animation: 0.5s ease-out fadeIn; - - &>div { - width: 200px; - height: 200px; - margin: auto; - flex: none; - - .progress { - background: rgba(0,0,0,.25); - height: 3px; - margin: 10px 50px; - - .bar { - transition: 1s ease-out width; - background: #a1c5e4; - height: 3px; - } - } - } -} - - -@keyframes fadeIn { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - - - -.terminus-logo { - width: 160px; - height: 160px; - background: url('../assets/logo.svg'); - background-repeat: none; - background-size: contain; - margin: auto; -} - - -.terminus-title { - color: #a1c5e4; - font-family: 'Source Sans Pro'; - text-align: center; - font-weight: normal; - font-size: 42px; - margin: 0; - - sup { - color: #842fe0; - } -} diff --git a/tmp/src/root.component.ts b/tmp/src/root.component.ts deleted file mode 100644 index 8d2bd18c..00000000 --- a/tmp/src/root.component.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Component } from '@angular/core' - -@Component({ - template: '', -}) -export class RootComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class diff --git a/tmp/src/toastr.scss b/tmp/src/toastr.scss deleted file mode 100644 index eaa1c715..00000000 --- a/tmp/src/toastr.scss +++ /dev/null @@ -1,21 +0,0 @@ -#toast-container { - display: flex; - flex-direction: column; - align-items: center; - padding: 20px; - - .toast { - box-shadow: 0 1px 0 rgba(0,0,0,.25); - padding: 10px; - background-image: none; - width: auto; - - &.toast-error { - background-color: #BD362F; - } - - &.toast-info { - background-color: #555; - } - } -} diff --git a/tmp/tsconfig.json b/tmp/tsconfig.json deleted file mode 100644 index cf51608a..00000000 --- a/tmp/tsconfig.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "./src", - "module": "commonjs", - "target": "es2015", - "declaration": false, - "noImplicitAny": false, - "removeComments": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "sourceMap": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUnusedParameters": true, - "noUnusedLocals": true, - "lib": [ - "dom", - "es2015", - "es2015.iterable", - "es2017", - "es7" - ] - }, - "compileOnSave": false, - "exclude": [ - "dist", - "node_modules", - "*/node_modules", - "terminus*", - "platforms" - ] -} diff --git a/tmp/tsconfig.main.json b/tmp/tsconfig.main.json deleted file mode 100644 index 50d8744b..00000000 --- a/tmp/tsconfig.main.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "./lib", - "module": "commonjs", - "target": "es2017", - "declaration": false, - "noImplicitAny": false, - "removeComments": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "sourceMap": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUnusedLocals": true, - "lib": [ - "dom", - "es2015", - "es2015.iterable", - "es2017", - "es7" - ] - }, - "compileOnSave": false, - "exclude": [ - "dist", - "node_modules", - "*/node_modules" - ] -} diff --git a/tmp/webpack.config.js b/tmp/webpack.config.js deleted file mode 100644 index 315204ad..00000000 --- a/tmp/webpack.config.js +++ /dev/null @@ -1,86 +0,0 @@ -const path = require('path') -const webpack = require('webpack') - -module.exports = { - name: 'terminus', - target: 'node', - entry: { - 'index.ignore': 'file-loader?name=index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'), - sentry: path.resolve(__dirname, 'lib/sentry.ts'), - preload: path.resolve(__dirname, 'src/entry.preload.ts'), - bundle: path.resolve(__dirname, 'src/entry.ts'), - }, - mode: process.env.TERMINUS_DEV ? 'development' : 'production', - optimization:{ - minimize: false, - }, - context: __dirname, - devtool: 'source-map', - output: { - path: path.join(__dirname, 'dist'), - pathinfo: true, - filename: '[name].js', - }, - resolve: { - modules: ['src/', 'node_modules', '../node_modules', 'assets/'].map(x => path.join(__dirname, x)), - extensions: ['.ts', '.js'], - }, - module: { - rules: [ - { - test: /\.ts$/, - use: { - loader: 'awesome-typescript-loader', - options: { - configFileName: path.resolve(__dirname, 'tsconfig.json'), - }, - }, - }, - { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, - { test: /\.css$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, - { - test: /\.(png|svg)$/, - use: { - loader: 'file-loader', - options: { - name: 'images/[name].[ext]', - }, - }, - }, - { - test: /\.(ttf|eot|otf|woff|woff2)(\?v=[0-9]\.[0-9]\.[0-9])?$/, - use: { - loader: 'file-loader', - options: { - name: 'fonts/[name].[ext]', - }, - }, - }, - ], - }, - externals: { - '@angular/core': 'commonjs @angular/core', - '@angular/compiler': 'commonjs @angular/compiler', - '@angular/platform-browser': 'commonjs @angular/platform-browser', - '@angular/platform-browser-dynamic': 'commonjs @angular/platform-browser-dynamic', - '@angular/forms': 'commonjs @angular/forms', - '@angular/common': 'commonjs @angular/common', - '@ng-bootstrap/ng-bootstrap': 'commonjs @ng-bootstrap/ng-bootstrap', - child_process: 'commonjs child_process', - electron: 'commonjs electron', - 'electron-is-dev': 'commonjs electron-is-dev', - fs: 'commonjs fs', - 'ngx-toastr': 'commonjs ngx-toastr', - module: 'commonjs module', - mz: 'commonjs mz', - path: 'commonjs path', - rxjs: 'commonjs rxjs', - 'zone.js': 'commonjs zone.js/dist/zone.js', - }, - plugins: [ - new webpack.optimize.ModuleConcatenationPlugin(), - new webpack.DefinePlugin({ - 'process.type': '"renderer"' - }), - ], -} diff --git a/tmp/webpack.main.config.js b/tmp/webpack.main.config.js deleted file mode 100644 index 7631609f..00000000 --- a/tmp/webpack.main.config.js +++ /dev/null @@ -1,53 +0,0 @@ -const path = require('path') -const webpack = require('webpack') - -module.exports = { - name: 'terminus-main', - target: 'node', - entry: { - main: path.resolve(__dirname, 'lib/index.ts'), - }, - mode: process.env.TERMINUS_DEV ? 'development' : 'production', - context: __dirname, - devtool: 'source-map', - output: { - path: path.join(__dirname, 'dist'), - pathinfo: true, - filename: '[name].js', - }, - resolve: { - modules: ['lib/', 'node_modules', '../node_modules'].map(x => path.join(__dirname, x)), - extensions: ['.ts', '.js'], - }, - module: { - rules: [ - { - test: /\.ts$/, - use: { - loader: 'awesome-typescript-loader', - options: { - configFileName: path.resolve(__dirname, 'tsconfig.main.json'), - }, - }, - }, - ], - }, - externals: { - electron: 'commonjs electron', - 'electron-config': 'commonjs electron-config', - 'electron-vibrancy': 'commonjs electron-vibrancy', - fs: 'commonjs fs', - glasstron: 'commonjs glasstron', - mz: 'commonjs mz', - path: 'commonjs path', - yargs: 'commonjs yargs', - 'windows-swca': 'commonjs windows-swca', - 'windows-blurbehind': 'commonjs windows-blurbehind', - }, - plugins: [ - new webpack.optimize.ModuleConcatenationPlugin(), - new webpack.DefinePlugin({ - 'process.type': '"main"', - }), - ], -}