mirror of
https://github.com/Eugeny/tabby.git
synced 2025-03-25 15:40:32 +08:00
more platform changes
This commit is contained in:
parent
faa9a1269c
commit
c0bd008f40
3
.github/workflows/linux.yml
vendored
3
.github/workflows/linux.yml
vendored
@ -28,6 +28,9 @@ jobs:
|
||||
cd app
|
||||
../node_modules/.bin/patch-package
|
||||
cd ..
|
||||
cd terminus-terminal
|
||||
../node_modules/.bin/patch-package
|
||||
cd ..
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
|
3
.github/workflows/macos.yml
vendored
3
.github/workflows/macos.yml
vendored
@ -32,6 +32,9 @@ jobs:
|
||||
cd app
|
||||
../node_modules/.bin/patch-package
|
||||
cd ..
|
||||
cd terminus-terminal
|
||||
../node_modules/.bin/patch-package
|
||||
cd ..
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
|
5
.github/workflows/windows.yml
vendored
5
.github/workflows/windows.yml
vendored
@ -21,6 +21,11 @@ jobs:
|
||||
npm i -g yarn@1.19.1
|
||||
yarn
|
||||
node scripts/build-native.js
|
||||
|
||||
cd terminus-terminal
|
||||
../node_modules/.bin/patch-package
|
||||
cd ..
|
||||
|
||||
yarn run build
|
||||
node scripts/prepackage-plugins.js
|
||||
|
||||
|
@ -309,20 +309,6 @@ export class Window {
|
||||
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
|
||||
|
12
terminus-core/src/api/hostWindow.ts
Normal file
12
terminus-core/src/api/hostWindow.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Observable } from 'rxjs'
|
||||
|
||||
export abstract class HostWindowService {
|
||||
abstract readonly closeRequest$: Observable<void>
|
||||
abstract readonly isFullscreen: boolean
|
||||
abstract reload (): void
|
||||
abstract setTitle (title?: string): void
|
||||
abstract toggleFullscreen (): void
|
||||
abstract minimize (): void
|
||||
abstract toggleMaximize (): void
|
||||
abstract close (): void
|
||||
}
|
@ -10,9 +10,10 @@ export { Theme } from './theme'
|
||||
export { TabContextMenuItemProvider } from './tabContextMenuProvider'
|
||||
export { SelectorOption } from './selector'
|
||||
export { CLIHandler, CLIEvent } from './cli'
|
||||
export { PlatformService, ClipboardContent } from './platform'
|
||||
export { PlatformService, ClipboardContent, MessageBoxResult, MessageBoxOptions } from './platform'
|
||||
export { MenuItemOptions } from './menu'
|
||||
export { BootstrapData, BOOTSTRAP_DATA } from './mainProcess'
|
||||
export { HostWindowService } from './hostWindow'
|
||||
|
||||
export { AppService } from '../services/app.service'
|
||||
export { ConfigService } from '../services/config.service'
|
||||
|
@ -6,9 +6,22 @@ export interface ClipboardContent {
|
||||
html?: string
|
||||
}
|
||||
|
||||
export interface MessageBoxOptions {
|
||||
type: 'warning'|'error'
|
||||
message: string
|
||||
detail?: string
|
||||
buttons: string[]
|
||||
defaultId?: number
|
||||
}
|
||||
|
||||
export interface MessageBoxResult {
|
||||
response: number
|
||||
}
|
||||
|
||||
export abstract class PlatformService {
|
||||
supportsWindowControls = false
|
||||
|
||||
abstract readClipboard (): string
|
||||
abstract setClipboard (content: ClipboardContent): void
|
||||
abstract loadConfig (): Promise<string>
|
||||
abstract saveConfig (content: string): Promise<void>
|
||||
@ -66,4 +79,5 @@ export abstract class PlatformService {
|
||||
abstract openExternal (url: string): void
|
||||
abstract listFonts (): Promise<string[]>
|
||||
abstract popupContextMenu (menu: MenuItemOptions[], event?: MouseEvent): void
|
||||
abstract showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult>
|
||||
}
|
||||
|
@ -1,15 +1,16 @@
|
||||
title-bar(
|
||||
*ngIf='!hostApp.isFullScreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
||||
[class.inset]='hostApp.platform == Platform.macOS && !hostApp.isFullScreen'
|
||||
*ngIf='ready && !hostWindow.isFullScreen && config.store.appearance.frame == "full" && config.store.appearance.dock == "off"',
|
||||
[class.inset]='hostApp.platform == Platform.macOS && !hostWindow.isFullScreen'
|
||||
)
|
||||
|
||||
.content(
|
||||
*ngIf='ready',
|
||||
[class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
|
||||
[class.tabs-on-side]='hasVerticalTabs()',
|
||||
)
|
||||
.tab-bar
|
||||
.inset.background(*ngIf='hostApp.platform == Platform.macOS \
|
||||
&& !hostApp.isFullScreen \
|
||||
&& !hostWindow.isFullScreen \
|
||||
&& config.store.appearance.frame == "thin" \
|
||||
&& (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")')
|
||||
.tabs(
|
||||
|
@ -12,7 +12,7 @@ import { UpdaterService } from '../services/updater.service'
|
||||
|
||||
import { BaseTabComponent } from './baseTab.component'
|
||||
import { SafeModeModalComponent } from './safeModeModal.component'
|
||||
import { AppService, PlatformService, ToolbarButton, ToolbarButtonProvider } from '../api'
|
||||
import { AppService, HostWindowService, PlatformService, ToolbarButton, ToolbarButtonProvider } from '../api'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@ -66,6 +66,7 @@ export class AppRootComponent {
|
||||
private constructor (
|
||||
private hotkeys: HotkeysService,
|
||||
private updater: UpdaterService,
|
||||
public hostWindow: HostWindowService,
|
||||
public hostApp: HostAppService,
|
||||
public config: ConfigService,
|
||||
public app: AppService,
|
||||
@ -78,9 +79,6 @@ export class AppRootComponent {
|
||||
this.logger = log.create('main')
|
||||
this.logger.info('v', platform.getAppVersion())
|
||||
|
||||
this.leftToolbarButtons = this.getToolbarButtons(false)
|
||||
this.rightToolbarButtons = this.getToolbarButtons(true)
|
||||
|
||||
this.updateIcon = require('../icons/gift.svg')
|
||||
|
||||
this.hotkeys.matchedHotkey.subscribe((hotkey: string) => {
|
||||
@ -114,7 +112,7 @@ export class AppRootComponent {
|
||||
}
|
||||
}
|
||||
if (hotkey === 'toggle-fullscreen') {
|
||||
this.hostApp.toggleFullscreen()
|
||||
hostWindow.toggleFullscreen()
|
||||
}
|
||||
})
|
||||
|
||||
@ -126,14 +124,6 @@ export class AppRootComponent {
|
||||
ngbModal.open(SafeModeModalComponent)
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
if (this.config.store.enableAutomaticUpdates) {
|
||||
this.updater.check().then(available => {
|
||||
this.updatesAvailable = available
|
||||
})
|
||||
}
|
||||
}, 3600 * 12 * 1000)
|
||||
|
||||
this.app.tabOpened$.subscribe(tab => {
|
||||
this.unsortedTabs.push(tab)
|
||||
this.noTabs = false
|
||||
@ -143,12 +133,26 @@ export class AppRootComponent {
|
||||
this.unsortedTabs = this.unsortedTabs.filter(x => x !== tab)
|
||||
this.noTabs = app.tabs.length === 0
|
||||
})
|
||||
|
||||
config.ready$.toPromise().then(() => {
|
||||
this.leftToolbarButtons = this.getToolbarButtons(false)
|
||||
this.rightToolbarButtons = this.getToolbarButtons(true)
|
||||
|
||||
setInterval(() => {
|
||||
if (this.config.store.enableAutomaticUpdates) {
|
||||
this.updater.check().then(available => {
|
||||
this.updatesAvailable = available
|
||||
})
|
||||
}
|
||||
}, 3600 * 12 * 1000)
|
||||
})
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
this.ready = true
|
||||
|
||||
this.app.emitReady()
|
||||
this.config.ready$.toPromise().then(() => {
|
||||
this.ready = true
|
||||
this.app.emitReady()
|
||||
})
|
||||
}
|
||||
|
||||
@HostListener('dragover')
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { BaseTabComponent } from './baseTab.component'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { HostAppService } from '../services/hostApp.service'
|
||||
import { HostWindowService } from '../api/hostWindow'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
@ -16,7 +16,7 @@ export class WelcomeTabComponent extends BaseTabComponent {
|
||||
enableGlobalHotkey = true
|
||||
|
||||
constructor (
|
||||
private hostApp: HostAppService,
|
||||
private hostWindow: HostWindowService,
|
||||
public config: ConfigService,
|
||||
) {
|
||||
super()
|
||||
@ -38,6 +38,6 @@ export class WelcomeTabComponent extends BaseTabComponent {
|
||||
this.config.store.hotkeys['toggle-window'] = []
|
||||
}
|
||||
this.config.save()
|
||||
this.hostApp.getWindow().reload()
|
||||
this.hostWindow.reload()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core'
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
@ -38,10 +38,6 @@ import { LastCLIHandler } from './cli'
|
||||
import 'perfect-scrollbar/css/perfect-scrollbar.css'
|
||||
import 'ng2-dnd/bundles/style.css'
|
||||
|
||||
function initialize (config: ConfigService) {
|
||||
return () => config.ready$.toPromise()
|
||||
}
|
||||
|
||||
const PROVIDERS = [
|
||||
{ provide: HotkeyProvider, useClass: AppHotkeyProvider, multi: true },
|
||||
{ provide: Theme, useClass: StandardTheme, multi: true },
|
||||
@ -54,7 +50,6 @@ const PROVIDERS = [
|
||||
{ provide: TabRecoveryProvider, useClass: SplitTabRecoveryProvider, multi: true },
|
||||
{ provide: CLIHandler, useClass: LastCLIHandler, multi: true },
|
||||
{ provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true } },
|
||||
{ provide: APP_INITIALIZER, useFactory: initialize, deps: [ConfigService], multi: true },
|
||||
]
|
||||
|
||||
/** @hidden */
|
||||
|
@ -10,6 +10,7 @@ import { SelectorModalComponent } from '../components/selectorModal.component'
|
||||
import { SelectorOption } from '../api/selector'
|
||||
import { RecoveryToken } from '../api/tabRecovery'
|
||||
import { BootstrapData, BOOTSTRAP_DATA } from '../api/mainProcess'
|
||||
import { HostWindowService } from '../api/hostWindow'
|
||||
|
||||
import { ConfigService } from './config.service'
|
||||
import { HostAppService } from './hostApp.service'
|
||||
@ -73,6 +74,7 @@ export class AppService {
|
||||
private constructor (
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private hostWindow: HostWindowService,
|
||||
private tabRecovery: TabRecoveryService,
|
||||
private tabsService: TabsService,
|
||||
private ngbModal: NgbModal,
|
||||
@ -127,7 +129,7 @@ export class AppService {
|
||||
|
||||
tab.titleChange$.subscribe(title => {
|
||||
if (tab === this._activeTab) {
|
||||
this.hostApp.setTitle(title)
|
||||
this.hostWindow.setTitle(title)
|
||||
}
|
||||
})
|
||||
|
||||
@ -205,7 +207,7 @@ export class AppService {
|
||||
setImmediate(() => {
|
||||
this._activeTab?.emitFocused()
|
||||
})
|
||||
this.hostApp.setTitle(this._activeTab?.title)
|
||||
this.hostWindow.setTitle(this._activeTab?.title)
|
||||
}
|
||||
|
||||
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
||||
@ -332,7 +334,7 @@ export class AppService {
|
||||
this.tabRecovery.enabled = false
|
||||
await this.tabRecovery.saveTabs(this.tabs)
|
||||
if (await this.closeAllTabs()) {
|
||||
this.hostApp.closeWindow()
|
||||
this.hostWindow.close()
|
||||
} else {
|
||||
this.tabRecovery.enabled = true
|
||||
}
|
||||
|
@ -89,9 +89,9 @@ export class ConfigService {
|
||||
restartRequested: boolean
|
||||
|
||||
/** Fires once when the config is loaded */
|
||||
get ready$ (): Observable<void> { return this.ready }
|
||||
get ready$ (): Observable<boolean> { return this.ready }
|
||||
|
||||
private ready = new AsyncSubject<void>()
|
||||
private ready = new AsyncSubject<boolean>()
|
||||
private changed = new Subject<void>()
|
||||
private _store: any
|
||||
private defaults: any
|
||||
@ -213,7 +213,7 @@ export class ConfigService {
|
||||
|
||||
private async init () {
|
||||
await this.load()
|
||||
this.ready.next()
|
||||
this.ready.next(true)
|
||||
this.ready.complete()
|
||||
|
||||
this.hostApp.configChangeBroadcast$.subscribe(() => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, Remote, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, NativeImage, MessageBoxOptions } from 'electron'
|
||||
import { App, IpcRenderer, Shell, Dialog, Clipboard, GlobalShortcut, Screen, Remote, AutoUpdater, TouchBar, BrowserWindow, Menu, MenuItem, NativeImage } from 'electron'
|
||||
import * as remote from '@electron/remote'
|
||||
|
||||
export interface MessageBoxResponse {
|
||||
@ -44,11 +44,4 @@ export class ElectronService {
|
||||
this.Menu = remote.Menu
|
||||
this.MenuItem = remote.MenuItem
|
||||
}
|
||||
|
||||
async showMessageBox (
|
||||
browserWindow: BrowserWindow,
|
||||
options: MessageBoxOptions
|
||||
): Promise<MessageBoxResponse> {
|
||||
return this.dialog.showMessageBox(browserWindow, options)
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ export class HostAppService {
|
||||
* Fired once the window is visible
|
||||
*/
|
||||
shown = new EventEmitter<any>()
|
||||
isFullScreen = false
|
||||
isPortable = !!process.env.PORTABLE_EXECUTABLE_FILE
|
||||
|
||||
private preferencesMenu = new Subject<void>()
|
||||
@ -92,14 +91,6 @@ export class HostAppService {
|
||||
this.logger.error('Unhandled exception:', err)
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:window-enter-full-screen', () => this.zone.run(() => {
|
||||
this.isFullScreen = true
|
||||
}))
|
||||
|
||||
electron.ipcRenderer.on('host:window-leave-full-screen', () => this.zone.run(() => {
|
||||
this.isFullScreen = false
|
||||
}))
|
||||
|
||||
electron.ipcRenderer.on('host:window-shown', () => {
|
||||
this.zone.run(() => this.shown.emit())
|
||||
})
|
||||
@ -163,11 +154,6 @@ export class HostAppService {
|
||||
this.electron.ipcRenderer.send('app:new-window')
|
||||
}
|
||||
|
||||
toggleFullscreen (): void {
|
||||
const window = this.getWindow()
|
||||
window.setFullScreen(!this.isFullScreen)
|
||||
}
|
||||
|
||||
openDevTools (): void {
|
||||
this.getWindow().webContents.openDevTools({ mode: 'undocked' })
|
||||
}
|
||||
@ -176,22 +162,6 @@ export class HostAppService {
|
||||
this.electron.ipcRenderer.send('window-focus')
|
||||
}
|
||||
|
||||
minimize (): void {
|
||||
this.electron.ipcRenderer.send('window-minimize')
|
||||
}
|
||||
|
||||
maximize (): void {
|
||||
this.electron.ipcRenderer.send('window-maximize')
|
||||
}
|
||||
|
||||
unmaximize (): void {
|
||||
this.electron.ipcRenderer.send('window-unmaximize')
|
||||
}
|
||||
|
||||
toggleMaximize (): void {
|
||||
this.electron.ipcRenderer.send('window-toggle-maximize')
|
||||
}
|
||||
|
||||
setBounds (bounds: Bounds): void {
|
||||
this.electron.ipcRenderer.send('window-set-bounds', bounds)
|
||||
}
|
||||
@ -200,10 +170,6 @@ export class HostAppService {
|
||||
this.electron.ipcRenderer.send('window-set-always-on-top', flag)
|
||||
}
|
||||
|
||||
setTitle (title?: string): void {
|
||||
this.electron.ipcRenderer.send('window-set-title', title ?? 'Terminus')
|
||||
}
|
||||
|
||||
setTouchBar (touchBar: TouchBar): void {
|
||||
this.getWindow().setTouchBar(touchBar)
|
||||
}
|
||||
@ -223,10 +189,6 @@ export class HostAppService {
|
||||
this.electron.ipcRenderer.send('window-bring-to-front')
|
||||
}
|
||||
|
||||
closeWindow (): void {
|
||||
this.electron.ipcRenderer.send('window-close')
|
||||
}
|
||||
|
||||
registerGlobalHotkey (specs: string[]): void {
|
||||
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { PlatformService, LogService, UpdaterService, DockingService, HostAppService, ThemesService, Platform, AppService, ConfigService, ElectronService, WIN_BUILD_FLUENT_BG_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||
import { PlatformService, LogService, UpdaterService, DockingService, HostAppService, ThemesService, Platform, AppService, ConfigService, ElectronService, WIN_BUILD_FLUENT_BG_SUPPORTED, isWindowsBuild, HostWindowService } from 'terminus-core'
|
||||
import { TerminalColorSchemeProvider } from 'terminus-terminal'
|
||||
|
||||
import { HyperColorSchemes } from './colorSchemes'
|
||||
import { ElectronPlatformService } from './services/platform'
|
||||
import { ElectronPlatformService } from './services/platform.service'
|
||||
import { ElectronLogService } from './services/log.service'
|
||||
import { ElectronUpdaterService } from './services/updater.service'
|
||||
import { TouchbarService } from './services/touchbar.service'
|
||||
import { ElectronDockingService } from './services/docking.service'
|
||||
import { ElectronHostWindow } from './services/hostWindow.service'
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{ provide: TerminalColorSchemeProvider, useClass: HyperColorSchemes, multi: true },
|
||||
{ provide: PlatformService, useClass: ElectronPlatformService },
|
||||
{ provide: HostWindowService, useClass: ElectronHostWindow },
|
||||
{ provide: LogService, useClass: ElectronLogService },
|
||||
{ provide: UpdaterService, useClass: ElectronUpdaterService },
|
||||
{ provide: DockingService, useClass: ElectronDockingService },
|
||||
|
51
terminus-electron/src/services/hostWindow.service.ts
Normal file
51
terminus-electron/src/services/hostWindow.service.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { Injectable, NgZone } from '@angular/core'
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { ElectronService, HostAppService, HostWindowService } from 'terminus-core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ElectronHostWindow extends HostWindowService {
|
||||
get closeRequest$ (): Observable<void> { return this.closeRequest }
|
||||
get isFullscreen (): boolean { return this._isFullScreen}
|
||||
|
||||
private closeRequest = new Subject<void>()
|
||||
private _isFullScreen = false
|
||||
|
||||
constructor (
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
zone: NgZone,
|
||||
) {
|
||||
super()
|
||||
electron.ipcRenderer.on('host:window-enter-full-screen', () => zone.run(() => {
|
||||
this._isFullScreen = true
|
||||
}))
|
||||
|
||||
electron.ipcRenderer.on('host:window-leave-full-screen', () => zone.run(() => {
|
||||
this._isFullScreen = false
|
||||
}))
|
||||
}
|
||||
|
||||
reload (): void {
|
||||
this.hostApp.getWindow().reload()
|
||||
}
|
||||
|
||||
setTitle (title?: string): void {
|
||||
this.electron.ipcRenderer.send('window-set-title', title ?? 'Terminus')
|
||||
}
|
||||
|
||||
toggleFullscreen (): void {
|
||||
this.hostApp.getWindow().setFullScreen(!this._isFullScreen)
|
||||
}
|
||||
|
||||
minimize (): void {
|
||||
this.electron.ipcRenderer.send('window-minimize')
|
||||
}
|
||||
|
||||
toggleMaximize (): void {
|
||||
this.electron.ipcRenderer.send('window-toggle-maximize')
|
||||
}
|
||||
|
||||
close (): void {
|
||||
this.electron.ipcRenderer.send('window-close')
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import * as os from 'os'
|
||||
import promiseIpc from 'electron-promise-ipc'
|
||||
import { execFile } from 'mz/child_process'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { PlatformService, ClipboardContent, HostAppService, Platform, ElectronService, MenuItemOptions } from 'terminus-core'
|
||||
import { PlatformService, ClipboardContent, HostAppService, Platform, ElectronService, MenuItemOptions, MessageBoxOptions, MessageBoxResult } from 'terminus-core'
|
||||
const fontManager = require('fontmanager-redux') // eslint-disable-line
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
@ -30,6 +30,10 @@ export class ElectronPlatformService extends PlatformService {
|
||||
this.configPath = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||
}
|
||||
|
||||
readClipboard (): string {
|
||||
return this.electron.clipboard.readText()
|
||||
}
|
||||
|
||||
setClipboard (content: ClipboardContent): void {
|
||||
require('@electron/remote').clipboard.write(content)
|
||||
}
|
||||
@ -86,7 +90,7 @@ export class ElectronPlatformService extends PlatformService {
|
||||
|
||||
async loadConfig (): Promise<string> {
|
||||
if (await fs.exists(this.configPath)) {
|
||||
return fs.readFileSync(this.configPath, 'utf8')
|
||||
return fs.readFile(this.configPath, 'utf8')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
@ -141,6 +145,12 @@ export class ElectronPlatformService extends PlatformService {
|
||||
}
|
||||
|
||||
popupContextMenu (menu: MenuItemOptions[], _event?: MouseEvent): void {
|
||||
this.electron.Menu.buildFromTemplate(menu).popup({})
|
||||
this.electron.Menu.buildFromTemplate(menu.map(item => ({
|
||||
...item,
|
||||
}))).popup({})
|
||||
}
|
||||
|
||||
async showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult> {
|
||||
return this.electron.dialog.showMessageBox(this.hostApp.getWindow(), options)
|
||||
}
|
||||
}
|
@ -2,8 +2,7 @@ import * as path from 'path'
|
||||
import * as fs from 'mz/fs'
|
||||
import { exec } from 'mz/child_process'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ElectronService } from '../../../terminus-core/src/services/electron.service'
|
||||
import { HostAppService, Platform } from '../../../terminus-core/src/services/hostApp.service'
|
||||
import { ElectronService, HostAppService, Platform } from 'terminus-core'
|
||||
|
||||
/* eslint-disable block-scoped-var */
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import axios from 'axios'
|
||||
|
||||
import { Logger, LogService, ElectronService, ConfigService, HostAppService, UpdaterService } from 'terminus-core'
|
||||
import { Logger, LogService, ElectronService, ConfigService, UpdaterService, PlatformService } from 'terminus-core'
|
||||
|
||||
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
|
||||
|
||||
@ -15,8 +15,8 @@ export class ElectronUpdaterService extends UpdaterService {
|
||||
constructor (
|
||||
log: LogService,
|
||||
config: ConfigService,
|
||||
private platform: PlatformService,
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
super()
|
||||
this.logger = log.create('updater')
|
||||
@ -42,18 +42,21 @@ export class ElectronUpdaterService extends UpdaterService {
|
||||
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||
})
|
||||
|
||||
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||
this.logger.debug('Checking for updates')
|
||||
try {
|
||||
electron.autoUpdater.setFeedURL({
|
||||
url: `https://update.electronjs.org/eugeny/terminus/${process.platform}-${process.arch}/${electron.app.getVersion()}`,
|
||||
})
|
||||
electron.autoUpdater.checkForUpdates()
|
||||
} catch (e) {
|
||||
this.electronUpdaterAvailable = false
|
||||
this.logger.info('Electron updater unavailable, falling back', e)
|
||||
|
||||
config.ready$.toPromise().then(() => {
|
||||
if (config.store.enableAutomaticUpdates && this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
|
||||
this.logger.debug('Checking for updates')
|
||||
try {
|
||||
electron.autoUpdater.setFeedURL({
|
||||
url: `https://update.electronjs.org/eugeny/terminus/${process.platform}-${process.arch}/${electron.app.getVersion()}`,
|
||||
})
|
||||
electron.autoUpdater.checkForUpdates()
|
||||
} catch (e) {
|
||||
this.electronUpdaterAvailable = false
|
||||
this.logger.info('Electron updater unavailable, falling back', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async check (): Promise<boolean> {
|
||||
@ -117,8 +120,7 @@ export class ElectronUpdaterService extends UpdaterService {
|
||||
if (!this.electronUpdaterAvailable) {
|
||||
this.electron.shell.openExternal(this.updateURL)
|
||||
} else {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: 'Installing the update will close all tabs and restart Terminus.',
|
||||
|
@ -90,8 +90,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
||||
if (!children?.length) {
|
||||
return true
|
||||
}
|
||||
return (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
return (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `"${children[0].command}" is still running. Close?`,
|
||||
|
@ -4,7 +4,7 @@ import { TerminalService } from './services/terminal.service'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class TerminalHotkeyProvider extends HotkeyProvider {
|
||||
export class LocalTerminalHotkeyProvider extends HotkeyProvider {
|
||||
hotkeys: HotkeyDescription[] = [
|
||||
{
|
||||
id: 'new-tab',
|
||||
|
@ -21,7 +21,7 @@ import { RecoveryProvider } from './recoveryProvider'
|
||||
import { ShellProvider } from './api'
|
||||
import { ShellSettingsTabProvider } from './settings'
|
||||
import { TerminalConfigProvider } from './config'
|
||||
import { TerminalHotkeyProvider } from './hotkeys'
|
||||
import { LocalTerminalHotkeyProvider } from './hotkeys'
|
||||
import { NewTabContextMenu, SaveAsProfileContextMenu } from './tabContextMenu'
|
||||
|
||||
import { CmderShellProvider } from './shells/cmder'
|
||||
@ -55,7 +55,7 @@ import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from '.
|
||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
|
||||
{ provide: ConfigProvider, useClass: TerminalConfigProvider, multi: true },
|
||||
{ provide: HotkeyProvider, useClass: TerminalHotkeyProvider, multi: true },
|
||||
{ provide: HotkeyProvider, useClass: LocalTerminalHotkeyProvider, multi: true },
|
||||
|
||||
{ provide: ShellProvider, useClass: WindowsDefaultShellProvider, multi: true },
|
||||
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
|
||||
import { ElectronService, HostAppService } from 'terminus-core'
|
||||
import { PlatformService } from 'terminus-core'
|
||||
import { SerialConnection, LoginScript, SerialPortInfo, BAUD_RATES } from '../api'
|
||||
import { SerialService } from '../services/serial.service'
|
||||
|
||||
@ -32,8 +32,7 @@ export class EditConnectionModalComponent {
|
||||
|
||||
constructor (
|
||||
private modalInstance: NgbActiveModal,
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
private platform: PlatformService,
|
||||
private serial: SerialService,
|
||||
) {
|
||||
}
|
||||
@ -100,8 +99,7 @@ export class EditConnectionModalComponent {
|
||||
}
|
||||
|
||||
async deleteScript (script: LoginScript) {
|
||||
if (this.connection.scripts && (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if (this.connection.scripts && (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: 'Delete this script?',
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ConfigService, ElectronService, HostAppService } from 'terminus-core'
|
||||
import { ConfigService, PlatformService } from 'terminus-core'
|
||||
import { SerialConnection } from '../api'
|
||||
import { EditConnectionModalComponent } from './editConnectionModal.component'
|
||||
|
||||
@ -14,8 +14,7 @@ export class SerialSettingsTabComponent {
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private electron: ElectronService,
|
||||
private hostApp: HostAppService,
|
||||
private platform: PlatformService,
|
||||
private ngbModal: NgbModal,
|
||||
) {
|
||||
this.connections = this.config.store.serial.connections
|
||||
@ -62,8 +61,7 @@ export class SerialSettingsTabComponent {
|
||||
}
|
||||
|
||||
async deleteConnection (connection: SerialConnection) {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `Delete "${connection.name}"?`,
|
||||
|
@ -4,7 +4,7 @@ import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Observable } from 'rxjs'
|
||||
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
|
||||
|
||||
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
|
||||
import { ElectronService, HostAppService, ConfigService, PlatformService } from 'terminus-core'
|
||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||
import { SSHConnection, LoginScript, ForwardedPortConfig, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
|
||||
import { PromptModalComponent } from './promptModal.component'
|
||||
@ -29,6 +29,7 @@ export class EditConnectionModalComponent {
|
||||
public config: ConfigService,
|
||||
private modalInstance: NgbActiveModal,
|
||||
private electron: ElectronService,
|
||||
private platform: PlatformService,
|
||||
private hostApp: HostAppService,
|
||||
private passwordStorage: PasswordStorageService,
|
||||
private ngbModal: NgbModal,
|
||||
@ -153,8 +154,7 @@ export class EditConnectionModalComponent {
|
||||
}
|
||||
|
||||
async deleteScript (script: LoginScript) {
|
||||
if (this.connection.scripts && (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if (this.connection.scripts && (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: 'Delete this script?',
|
||||
|
@ -2,7 +2,7 @@
|
||||
import deepClone from 'clone-deep'
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ConfigService, ElectronService, HostAppService, Platform } from 'terminus-core'
|
||||
import { ConfigService, HostAppService, Platform, PlatformService } from 'terminus-core'
|
||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||
import { SSHConnection } from '../api'
|
||||
import { EditConnectionModalComponent } from './editConnectionModal.component'
|
||||
@ -28,7 +28,7 @@ export class SSHSettingsTabComponent {
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
public hostApp: HostAppService,
|
||||
private electron: ElectronService,
|
||||
private platform: PlatformService,
|
||||
private ngbModal: NgbModal,
|
||||
private passwordStorage: PasswordStorageService,
|
||||
) {
|
||||
@ -81,8 +81,7 @@ export class SSHSettingsTabComponent {
|
||||
}
|
||||
|
||||
async deleteConnection (connection: SSHConnection) {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `Delete "${connection.name}"?`,
|
||||
@ -115,8 +114,7 @@ export class SSHSettingsTabComponent {
|
||||
}
|
||||
|
||||
async deleteGroup (group: SSHConnectionGroup) {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `Delete "${group.name}"?`,
|
||||
|
@ -210,8 +210,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
if (!(this.connection?.warnOnClose ?? this.config.store.ssh.warnOnClose)) {
|
||||
return true
|
||||
}
|
||||
return (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
return (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `Disconnect from ${this.connection?.host}?`,
|
||||
|
@ -3,7 +3,7 @@ import { first } from 'rxjs/operators'
|
||||
import colors from 'ansi-colors'
|
||||
import { NgZone, OnInit, OnDestroy, Injector, ViewChild, HostBinding, Input, ElementRef, InjectFlags } from '@angular/core'
|
||||
import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
|
||||
import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, NotificationsService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent, SubscriptionContainer, MenuItemOptions, PlatformService } from 'terminus-core'
|
||||
import { AppService, ConfigService, BaseTabComponent, HostAppService, HotkeysService, NotificationsService, Platform, LogService, Logger, TabContextMenuItemProvider, SplitTabComponent, SubscriptionContainer, MenuItemOptions, PlatformService } from 'terminus-core'
|
||||
|
||||
import { BaseSession } from '../session'
|
||||
import { TerminalFrontendService } from '../services/terminalFrontend.service'
|
||||
@ -82,7 +82,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
protected app: AppService
|
||||
protected hostApp: HostAppService
|
||||
protected hotkeys: HotkeysService
|
||||
protected electron: ElectronService
|
||||
protected platform: PlatformService
|
||||
protected terminalContainersService: TerminalFrontendService
|
||||
protected notifications: NotificationsService
|
||||
@ -135,7 +134,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
this.app = injector.get(AppService)
|
||||
this.hostApp = injector.get(HostAppService)
|
||||
this.hotkeys = injector.get(HotkeysService)
|
||||
this.electron = injector.get(ElectronService)
|
||||
this.platform = injector.get(PlatformService)
|
||||
this.terminalContainersService = injector.get(TerminalFrontendService)
|
||||
this.notifications = injector.get(NotificationsService)
|
||||
@ -359,7 +357,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
}
|
||||
|
||||
async paste (): Promise<void> {
|
||||
let data = this.electron.clipboard.readText()
|
||||
let data = this.platform.readClipboard()
|
||||
if (this.config.store.terminal.bracketedPaste) {
|
||||
data = `\x1b[200~${data}\x1b[201~`
|
||||
}
|
||||
@ -374,15 +372,13 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
|
||||
if (data.includes('\r') && this.config.store.terminal.warnOnMultilinePaste) {
|
||||
const buttons = ['Paste', 'Cancel']
|
||||
const result = (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
const result = (await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
detail: data,
|
||||
message: `Paste multiple lines?`,
|
||||
buttons,
|
||||
defaultId: 0,
|
||||
cancelId: 1,
|
||||
}
|
||||
)).response
|
||||
if (result === 1) {
|
||||
@ -463,7 +459,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
cwd = await this.session.getWorkingDirectory()
|
||||
}
|
||||
if (cwd) {
|
||||
this.electron.clipboard.writeText(cwd)
|
||||
this.platform.setClipboard({ text: cwd })
|
||||
this.notifications.notice('Copied')
|
||||
} else {
|
||||
this.notifications.error('Shell does not support current path detection')
|
||||
|
@ -2,7 +2,7 @@
|
||||
import deepEqual from 'deep-equal'
|
||||
|
||||
import { Component, Inject, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'
|
||||
import { ConfigService, HostAppService, ElectronService } from 'terminus-core'
|
||||
import { ConfigService, PlatformService } from 'terminus-core'
|
||||
import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
|
||||
import { TerminalColorScheme } from '../api/interfaces'
|
||||
|
||||
@ -26,8 +26,7 @@ export class ColorSchemeSettingsTabComponent {
|
||||
constructor (
|
||||
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private hostApp: HostAppService,
|
||||
private electron: ElectronService,
|
||||
private platform: PlatformService,
|
||||
public config: ConfigService,
|
||||
) { }
|
||||
|
||||
@ -76,8 +75,7 @@ export class ColorSchemeSettingsTabComponent {
|
||||
}
|
||||
|
||||
async deleteScheme (scheme: TerminalColorScheme) {
|
||||
if ((await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
if ((await this.platform.showMessageBox(
|
||||
{
|
||||
type: 'warning',
|
||||
message: `Delete "${scheme.name}"?`,
|
||||
|
@ -2,13 +2,14 @@ import * as fs from 'fs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { TerminalDecorator } from '../api/decorator'
|
||||
import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
|
||||
import { ElectronService, HostAppService } from 'terminus-core'
|
||||
import { ElectronService, HostAppService, PlatformService } from 'terminus-core'
|
||||
|
||||
/** @hidden */
|
||||
@Injectable()
|
||||
export class DebugDecorator extends TerminalDecorator {
|
||||
constructor (
|
||||
private electron: ElectronService,
|
||||
private platform: PlatformService,
|
||||
private hostApp: HostAppService,
|
||||
) {
|
||||
super()
|
||||
@ -93,7 +94,7 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
|
||||
private async doCopyState (terminal: BaseTerminalTabComponent) {
|
||||
const data = '```' + JSON.stringify(terminal.frontend!.saveState()) + '```'
|
||||
this.electron.clipboard.writeText(data)
|
||||
this.platform.setClipboard({ text: data })
|
||||
}
|
||||
|
||||
private async doLoadState (terminal: BaseTerminalTabComponent) {
|
||||
@ -104,7 +105,7 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
}
|
||||
|
||||
private async doPasteState (terminal: BaseTerminalTabComponent) {
|
||||
let data = this.electron.clipboard.readText()
|
||||
let data = this.platform.readClipboard()
|
||||
if (data) {
|
||||
if (data.startsWith('`')) {
|
||||
data = data.substring(3, data.length - 3)
|
||||
@ -119,7 +120,7 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
|
||||
private async doCopyOutput (buffer: string) {
|
||||
const data = '```' + JSON.stringify(buffer) + '```'
|
||||
this.electron.clipboard.writeText(data)
|
||||
this.platform.setClipboard({ text: data })
|
||||
}
|
||||
|
||||
private async doLoadOutput (terminal: BaseTerminalTabComponent) {
|
||||
@ -130,7 +131,7 @@ export class DebugDecorator extends TerminalDecorator {
|
||||
}
|
||||
|
||||
private async doPasteOutput (terminal: BaseTerminalTabComponent) {
|
||||
let data = this.electron.clipboard.readText()
|
||||
let data = this.platform.readClipboard()
|
||||
if (data) {
|
||||
if (data.startsWith('`')) {
|
||||
data = data.substring(3, data.length - 3)
|
||||
|
13
terminus-web/src/components/messageBoxModal.component.pug
Normal file
13
terminus-web/src/components/messageBoxModal.component.pug
Normal file
@ -0,0 +1,13 @@
|
||||
.modal-body
|
||||
div {{options.message}}
|
||||
small {{options.detail}}
|
||||
|
||||
.modal-footer
|
||||
.ml-auto
|
||||
button.btn(
|
||||
*ngFor='let button of options.buttons; index as i',
|
||||
[autofocus]='i === options.defaultId',
|
||||
[class.btn-primary]='i === options.defaultId',
|
||||
[class.btn-secondary]='i !== options.defaultId',
|
||||
(click)='onButton(i)',
|
||||
) {{button}}
|
34
terminus-web/src/components/messageBoxModal.component.ts
Normal file
34
terminus-web/src/components/messageBoxModal.component.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { Component, Input, ElementRef, } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { BaseComponent, HotkeysService, MessageBoxOptions } from 'terminus-core'
|
||||
|
||||
/** @hidden */
|
||||
@Component({
|
||||
template: require('./messageBoxModal.component.pug'),
|
||||
})
|
||||
export class MessageBoxModalComponent extends BaseComponent {
|
||||
@Input() options: MessageBoxOptions
|
||||
|
||||
constructor (
|
||||
hotkeys: HotkeysService,
|
||||
private element: ElementRef,
|
||||
private modalInstance: NgbActiveModal,
|
||||
) {
|
||||
super()
|
||||
this.subscribeUntilDestroyed(hotkeys.key, (event: KeyboardEvent) => {
|
||||
if (event.type === 'keydown') {
|
||||
if (event.key === 'Enter' && this.options.defaultId !== undefined) {
|
||||
this.modalInstance.close(this.options.defaultId)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ngAfterViewInit (): void {
|
||||
this.element.nativeElement.querySelector('button[autofocus]').focus()
|
||||
}
|
||||
|
||||
onButton (index: number): void {
|
||||
this.modalInstance.close(index)
|
||||
}
|
||||
}
|
@ -1,17 +1,30 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { LogService, PlatformService, UpdaterService } from 'terminus-core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { HostWindowService, LogService, PlatformService, UpdaterService } from 'terminus-core'
|
||||
|
||||
import { WebPlatformService } from './platform'
|
||||
import { ConsoleLogService } from './services/log.service'
|
||||
import { NullUpdaterService } from './services/updater.service'
|
||||
import { WebHostWindow } from './services/hostWindow.service'
|
||||
import { MessageBoxModalComponent } from './components/messageBoxModal.component'
|
||||
|
||||
import './styles.scss'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: PlatformService, useClass: WebPlatformService },
|
||||
{ provide: LogService, useClass: ConsoleLogService },
|
||||
{ provide: UpdaterService, useClass: NullUpdaterService },
|
||||
{ provide: HostWindowService, useClass: WebHostWindow },
|
||||
],
|
||||
declarations: [
|
||||
MessageBoxModalComponent,
|
||||
],
|
||||
entryComponents: [
|
||||
MessageBoxModalComponent,
|
||||
],
|
||||
})
|
||||
export default class WebModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
|
@ -1,11 +1,13 @@
|
||||
import '@vaadin/vaadin-context-menu/vaadin-context-menu.js'
|
||||
import copyToClipboard from 'copy-text-to-clipboard'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { PlatformService, ClipboardContent, MenuItemOptions } from 'terminus-core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { PlatformService, ClipboardContent, MenuItemOptions, MessageBoxOptions, MessageBoxResult } from 'terminus-core'
|
||||
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import type { ContextMenuElement, ContextMenuItem } from '@vaadin/vaadin-context-menu/vaadin-context-menu.js'
|
||||
|
||||
import { MessageBoxModalComponent } from './components/messageBoxModal.component'
|
||||
import './styles.scss'
|
||||
|
||||
@Injectable()
|
||||
@ -13,14 +15,19 @@ export class WebPlatformService extends PlatformService {
|
||||
private menu: ContextMenuElement
|
||||
private contextMenuHandlers = new Map<ContextMenuItem, () => void>()
|
||||
|
||||
constructor () {
|
||||
constructor (
|
||||
private ngbModal: NgbModal,
|
||||
) {
|
||||
super()
|
||||
this.menu = window.document.createElement('vaadin-context-menu')
|
||||
this.menu.addEventListener('item-selected', e => {
|
||||
this.contextMenuHandlers.get(e.detail.value)?.()
|
||||
})
|
||||
document.body.appendChild(this.menu)
|
||||
console.log(require('./styles.scss'))
|
||||
}
|
||||
|
||||
readClipboard (): string {
|
||||
return ''
|
||||
}
|
||||
|
||||
setClipboard (content: ClipboardContent): void {
|
||||
@ -73,4 +80,19 @@ export class WebPlatformService extends PlatformService {
|
||||
}
|
||||
return cmi
|
||||
}
|
||||
|
||||
async showMessageBox (options: MessageBoxOptions): Promise<MessageBoxResult> {
|
||||
console.log(options)
|
||||
const modal = this.ngbModal.open(MessageBoxModalComponent, {
|
||||
backdrop: 'static',
|
||||
})
|
||||
const instance: MessageBoxModalComponent = modal.componentInstance
|
||||
instance.options = options
|
||||
try {
|
||||
const response = await modal.result
|
||||
return { response }
|
||||
} catch {
|
||||
return { response: 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
terminus-web/src/services/hostWindow.service.ts
Normal file
39
terminus-web/src/services/hostWindow.service.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Observable, Subject } from 'rxjs'
|
||||
import { HostWindowService } from 'terminus-core'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WebHostWindow extends HostWindowService {
|
||||
get closeRequest$ (): Observable<void> { return this.closeRequest }
|
||||
get isFullscreen (): boolean { return !!document.fullscreenElement }
|
||||
|
||||
private closeRequest = new Subject<void>()
|
||||
|
||||
reload (): void {
|
||||
location.reload()
|
||||
}
|
||||
|
||||
setTitle (title?: string): void {
|
||||
document.title = title ?? 'Terminus'
|
||||
}
|
||||
|
||||
toggleFullscreen (): void {
|
||||
if (this.isFullscreen) {
|
||||
document.exitFullscreen()
|
||||
} else {
|
||||
document.body.requestFullscreen({ navigationUI: 'hide' })
|
||||
}
|
||||
}
|
||||
|
||||
minimize (): void {
|
||||
throw new Error('Unavailable')
|
||||
}
|
||||
|
||||
toggleMaximize (): void {
|
||||
throw new Error('Unavailable')
|
||||
}
|
||||
|
||||
close (): void {
|
||||
window.close()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user