diff --git a/tabby-core/src/services/hotkeys.service.ts b/tabby-core/src/services/hotkeys.service.ts index 671178b2..d93ffa09 100644 --- a/tabby-core/src/services/hotkeys.service.ts +++ b/tabby-core/src/services/hotkeys.service.ts @@ -3,6 +3,7 @@ import { Observable, Subject } from 'rxjs' import { HotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider' import { stringifyKeySequence, EventData } from './hotkeys.util' import { ConfigService } from './config.service' +import { HostAppService, Platform } from '../api/hostApp' import { deprecate } from 'util' export interface PartialHotkeyMatch { @@ -35,6 +36,7 @@ export class HotkeysService { private zone: NgZone, private config: ConfigService, @Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[], + hostApp: HostAppService, ) { const events = ['keydown', 'keyup'] events.forEach(event => { @@ -43,6 +45,10 @@ export class HotkeysService { this.pushKeystroke(event, nativeEvent) this.processKeystrokes() this.emitKeyEvent(nativeEvent) + if (hostApp.platform === Platform.Web) { + nativeEvent.preventDefault() + nativeEvent.stopPropagation() + } } }) }) diff --git a/tabby-settings/src/components/windowSettingsTab.component.pug b/tabby-settings/src/components/windowSettingsTab.component.pug index 394305f4..39fe27df 100644 --- a/tabby-settings/src/components/windowSettingsTab.component.pug +++ b/tabby-settings/src/components/windowSettingsTab.component.pug @@ -9,6 +9,17 @@ h3.mb-3 Window ) option(*ngFor='let theme of themes', [ngValue]='theme.name') {{theme.name}} + +.form-line(*ngIf='hostApp.platform === Platform.Web') + .header + .title Ask before closing the browser tab + .description Prevents accidental closing + toggle( + [(ngModel)]='config.store.web.preventAccidentalTabClosure', + (ngModelChange)='saveConfiguration()', + ) + + .form-line(*ngIf='platform.supportsWindowControls') .header .title(*ngIf='hostApp.platform !== Platform.macOS') Acrylic background diff --git a/tabby-web/package.json b/tabby-web/package.json index 407ff604..d4294c1c 100644 --- a/tabby-web/package.json +++ b/tabby-web/package.json @@ -22,6 +22,7 @@ "devDependencies": { "@vaadin/vaadin-context-menu": "^5.0.0", "bootstrap": "^4.1.3", + "bowser": "^2.11.0", "copy-text-to-clipboard": "^3.0.1" } } diff --git a/tabby-web/src/config.ts b/tabby-web/src/config.ts new file mode 100644 index 00000000..78530cf5 --- /dev/null +++ b/tabby-web/src/config.ts @@ -0,0 +1,10 @@ +import { ConfigProvider } from 'tabby-core' + +/** @hidden */ +export class WebConfigProvider extends ConfigProvider { + defaults = { + web: { + preventAccidentalTabClosure: true, + }, + } +} diff --git a/tabby-web/src/index.ts b/tabby-web/src/index.ts index fc846641..6fda15e4 100644 --- a/tabby-web/src/index.ts +++ b/tabby-web/src/index.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core' import { CommonModule } from '@angular/common' -import { HostAppService, HostWindowService, LogService, PlatformService, UpdaterService } from 'tabby-core' +import { ConfigProvider, HostAppService, HostWindowService, LogService, PlatformService, UpdaterService } from 'tabby-core' import { WebPlatformService } from './platform' import { ConsoleLogService } from './services/log.service' @@ -8,6 +8,7 @@ import { NullUpdaterService } from './services/updater.service' import { WebHostWindow } from './services/hostWindow.service' import { WebHostApp } from './services/hostApp.service' import { MessageBoxModalComponent } from './components/messageBoxModal.component' +import { WebConfigProvider } from './config' import './styles.scss' @@ -21,6 +22,7 @@ import './styles.scss' { provide: UpdaterService, useClass: NullUpdaterService }, { provide: HostWindowService, useClass: WebHostWindow }, { provide: HostAppService, useClass: WebHostApp }, + { provide: ConfigProvider, useClass: WebConfigProvider, multi: true }, ], declarations: [ MessageBoxModalComponent, diff --git a/tabby-web/src/services/hostApp.service.ts b/tabby-web/src/services/hostApp.service.ts index e3fb8c9a..a95982c8 100644 --- a/tabby-web/src/services/hostApp.service.ts +++ b/tabby-web/src/services/hostApp.service.ts @@ -1,3 +1,4 @@ +import Bowser from 'bowser' import { Injectable, Injector } from '@angular/core' import { HostAppService, Platform } from 'tabby-core' @@ -8,7 +9,8 @@ export class WebHostApp extends HostAppService { } get configPlatform (): Platform { - return Platform.Windows // TODO + const os = Bowser.parse(window.navigator.userAgent).os + return Platform[os.name ?? 'Windows'] ?? Platform.Windows } // Needed for injector metadata diff --git a/tabby-web/src/services/hostWindow.service.ts b/tabby-web/src/services/hostWindow.service.ts index 5e1c2267..c14b9a3c 100644 --- a/tabby-web/src/services/hostWindow.service.ts +++ b/tabby-web/src/services/hostWindow.service.ts @@ -1,14 +1,23 @@ import { Injectable } from '@angular/core' -import { HostWindowService } from 'tabby-core' +import { ConfigService, HostWindowService } from 'tabby-core' @Injectable({ providedIn: 'root' }) export class WebHostWindow extends HostWindowService { get isFullscreen (): boolean { return !!document.fullscreenElement } - constructor () { + constructor ( + config: ConfigService, + ) { super() this.windowShown.next() this.windowFocused.next() + + window.addEventListener('beforeunload', (event) => { + if (config.store.web.preventAccidentalTabClosure) { + event.preventDefault() + event.returnValue = 'Are you sure you want to close Tabby? You can disable this prompt in Settings -> Window.' + } + } } reload (): void { diff --git a/tabby-web/yarn.lock b/tabby-web/yarn.lock index e22b3d46..68e64557 100644 --- a/tabby-web/yarn.lock +++ b/tabby-web/yarn.lock @@ -160,6 +160,11 @@ bootstrap@^4.1.3: resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7" integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + copy-text-to-clipboard@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c"