Custom keyboard shortcuts

This commit is contained in:
jliddev
2020-11-25 12:02:39 -06:00
parent e9bcf8fd10
commit efbc869c43
6 changed files with 136 additions and 60 deletions

View File

@@ -299,9 +299,9 @@ function getAppMenu(): Array<MenuItemConstructorOptions | MenuItem> {
{ role: "forceReload" },
{ role: "toggleDevTools", accelerator: "CommandOrControl+Shift+I" },
{ type: "separator" },
{ role: "resetZoom" },
{ role: "zoomIn", accelerator: "CommandOrControl+=" },
{ role: "zoomOut" },
// { role: "resetZoom" },
// { role: "zoomIn", accelerator: "CommandOrControl+=" },
// { role: "zoomOut" },
{ type: "separator" },
{ role: "togglefullscreen" },
],
@@ -312,10 +312,10 @@ function getAppMenu(): Array<MenuItemConstructorOptions | MenuItem> {
{
label: "View",
submenu: [
{ role: "resetZoom" },
// { role: "resetZoom" },
{ role: "toggleDevTools" },
{ role: "zoomIn", accelerator: "CommandOrControl+=" },
{ role: "zoomOut" },
// { role: "zoomIn", accelerator: "CommandOrControl+=" },
// { role: "zoomOut" },
{ type: "separator" },
{ role: "togglefullscreen" },
],
@@ -346,9 +346,9 @@ function getAppMenu(): Array<MenuItemConstructorOptions | MenuItem> {
{ role: "forceReload" },
{ role: "toggleDevTools" },
{ type: "separator" },
{ role: "resetZoom" },
{ role: "zoomIn", accelerator: "CommandOrControl+=" },
{ role: "zoomOut" },
// { role: "resetZoom" },
// { role: "zoomIn", accelerator: "CommandOrControl+=" },
// { role: "zoomOut" },
{ type: "separator" },
{ role: "togglefullscreen" },
],

View File

@@ -1,7 +1,8 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, OnInit } from "@angular/core";
import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, OnInit } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { TranslateService } from "@ngx-translate/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import { filter } from "rxjs/operators";
import {
ALLIANCE_LIGHT_THEME,
ALLIANCE_THEME,
@@ -21,7 +22,7 @@ import { FileService } from "./services/files/file.service";
import { WowUpService } from "./services/wowup/wowup.service";
import { IconService } from "./services/icons/icon.service";
import { SessionService } from "./services/session/session.service";
import { filter } from "rxjs/operators";
import { getZoomDirection, ZoomDirection } from "./utils/zoom.utils";
const AUTO_UPDATE_PERIOD_MS = 60 * 60 * 1000; // 1 hour
@@ -34,6 +35,12 @@ const AUTO_UPDATE_PERIOD_MS = 60 * 60 * 1000; // 1 hour
export class AppComponent implements OnInit, AfterViewInit {
private _autoUpdateInterval?: number;
@HostListener("document:keydown", ["$event"])
handleKeyboardEvent(event: KeyboardEvent) {
const zoomDirection = getZoomDirection(event);
this._electronService.applyZoom(zoomDirection);
}
public get quitEnabled() {
return this._electronService.appOptions.quit;
}

View File

@@ -76,10 +76,8 @@
{{ "PAGES.OPTIONS.APPLICATION.ENABLE_SYSTEM_NOTIFICATIONS_LABEL" | translate }}
</div>
</div>
<mat-slide-toggle
[checked]="wowupService.enableSystemNotifications"
(change)="onEnableSystemNotifications($event)"
>
<mat-slide-toggle [checked]="wowupService.enableSystemNotifications"
(change)="onEnableSystemNotifications($event)">
</mat-slide-toggle>
</div>
<small class="text-2">
@@ -108,11 +106,8 @@
</div>
<small class="text-2">{{ "PAGES.OPTIONS.APPLICATION.START_WITH_SYSTEM_DESCRIPTION" | translate }}</small>
</div>
<mat-slide-toggle
[(ngModel)]="startWithSystem"
[(checked)]="startWithSystem"
(change)="onStartWithSystemChange($event)"
>
<mat-slide-toggle [(ngModel)]="startWithSystem" [(checked)]="startWithSystem"
(change)="onStartWithSystemChange($event)">
</mat-slide-toggle>
</div>
</div>
@@ -125,12 +120,8 @@
</div>
<small class="text-2">{{ "PAGES.OPTIONS.APPLICATION.START_MINIMIZED_DESCRIPTION" | translate }}</small>
</div>
<mat-slide-toggle
[(ngModel)]="startMinimized"
[(disabled)]="!startWithSystem"
[(checked)]="startMinimized"
(change)="onStartMinimizedChange($event)"
>
<mat-slide-toggle [(ngModel)]="startMinimized" [(disabled)]="!startWithSystem" [(checked)]="startMinimized"
(change)="onStartMinimizedChange($event)">
</mat-slide-toggle>
</div>
</div>
@@ -141,14 +132,11 @@
<small class="text-2">{{ "PAGES.OPTIONS.APPLICATION.SCALE_DESCRIPTION" | translate }}</small>
</div>
<mat-form-field class="light-select">
<mat-select
[(value)]="currentScale"
(selectionChange)="onScaleChange($event)"
>
<mat-option *ngFor="let value of allowedScales" [value]="value">
<mat-select [(value)]="currentScale" (selectionChange)="onScaleChange($event)">
<mat-option *ngFor="let value of zoomScale" [value]="value">
{{ value * 100 | number:'1.0-0' }} %
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from "@angular/core";
import { ChangeDetectorRef, Component, OnInit } from "@angular/core";
import { MatDialog } from "@angular/material/dialog";
import { MatSelectChange } from "@angular/material/select";
import { MatSlideToggleChange } from "@angular/material/slide-toggle";
@@ -17,6 +17,7 @@ import {
HORDE_LIGHT_THEME,
HORDE_THEME,
} from "../../../common/constants";
import { ZOOM_SCALE } from "../../utils/zoom.utils";
interface LocaleListItem {
localeId: string;
@@ -36,6 +37,8 @@ export class OptionsAppSectionComponent implements OnInit {
public telemetryEnabled = false;
public useHardwareAcceleration = true;
public currentLanguage: string = "";
public zoomScale = ZOOM_SCALE;
public currentScale = 1;
public languages: LocaleListItem[] = [
{ localeId: "en", label: "English" },
{ localeId: "de", label: "Deutsch" },
@@ -52,31 +55,29 @@ export class OptionsAppSectionComponent implements OnInit {
public themeGroups: ThemeGroup[] = [
{
name: 'APP.THEME.GROUP_DARK', themes: [
name: "APP.THEME.GROUP_DARK",
themes: [
{ display: "APP.THEME.DEFAULT", class: DEFAULT_THEME },
{ display: "APP.THEME.ALLIANCE", class: ALLIANCE_THEME },
{ display: "APP.THEME.HORDE", class: HORDE_THEME },
]
],
},
{
name: 'APP.THEME.GROUP_LIGHT', themes: [
name: "APP.THEME.GROUP_LIGHT",
themes: [
{ display: "APP.THEME.DEFAULT", class: DEFAULT_LIGHT_THEME },
{ display: "APP.THEME.ALLIANCE", class: ALLIANCE_LIGHT_THEME },
{ display: "APP.THEME.HORDE", class: HORDE_LIGHT_THEME },
]
],
},
]
public allowedScales = [-2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6].map(
(x) => Math.pow(1.2, x)
);
public currentScale = 1;
];
constructor(
private _analyticsService: AnalyticsService,
private _dialog: MatDialog,
private _electronService: ElectronService,
private _translateService: TranslateService,
private _cdRef: ChangeDetectorRef,
public electronService: ElectronService,
public sessionService: SessionService,
public wowupService: WowUpService
) {}
@@ -86,7 +87,7 @@ export class OptionsAppSectionComponent implements OnInit {
this.telemetryEnabled = enabled;
});
const minimizeOnCloseKey = this._electronService.isWin
const minimizeOnCloseKey = this.electronService.isWin
? "PAGES.OPTIONS.APPLICATION.MINIMIZE_ON_CLOSE_DESCRIPTION_WINDOWS"
: "PAGES.OPTIONS.APPLICATION.MINIMIZE_ON_CLOSE_DESCRIPTION_MAC";
@@ -101,13 +102,18 @@ export class OptionsAppSectionComponent implements OnInit {
this.startMinimized = this.wowupService.startMinimized;
this.currentLanguage = this.wowupService.currentLanguage;
if (window.require("electron").remote) {
if (this.electronService.remote) {
this.updateScale();
const currentWindow = window.require("electron").remote.getCurrentWindow();
currentWindow.webContents.on('zoom-changed', (event, arg) => {
this.updateScale()
const currentWindow = this.electronService.remote.getCurrentWindow();
currentWindow.webContents.on("zoom-changed", (event, arg) => {
this.updateScale();
});
}
this.electronService.zoomFactor$.subscribe((zoomFactor) => {
this.currentScale = zoomFactor;
this._cdRef.detectChanges();
});
}
onEnableSystemNotifications = (evt: MatSlideToggleChange) => {
@@ -154,7 +160,7 @@ export class OptionsAppSectionComponent implements OnInit {
}
this.wowupService.useHardwareAcceleration = evt.checked;
this._electronService.restartApplication();
this.electronService.restartApplication();
});
};
@@ -173,19 +179,17 @@ export class OptionsAppSectionComponent implements OnInit {
}
this.wowupService.currentLanguage = evt.value;
this._electronService.restartApplication();
this.electronService.restartApplication();
});
};
onScaleChange = (evt: MatSelectChange) => {
let newScale = evt.value;
const currentWindow = window.require("electron").remote.getCurrentWindow();
currentWindow.webContents.zoomFactor = newScale;
public onScaleChange = (evt: MatSelectChange) => {
const newScale = evt.value;
this.electronService.setZoomFactor(newScale);
this.currentScale = newScale;
};
updateScale() {
const currentWindow = window.require("electron").remote.getCurrentWindow();
this.currentScale = currentWindow.webContents.zoomFactor;
};
private updateScale() {
this.currentScale = this.electronService.getZoomFactor();
}
}

View File

@@ -6,6 +6,7 @@ import {
APP_UPDATE_DOWNLOADED,
APP_UPDATE_START_DOWNLOAD,
} from "../../../common/constants";
import * as minimist from "minimist";
// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer, remote, Settings, shell, webFrame } from "electron";
@@ -17,7 +18,7 @@ import { IpcResponse } from "../../../common/models/ipc-response";
import { ValueRequest } from "../../../common/models/value-request";
import { ValueResponse } from "../../../common/models/value-response";
import { AppOptions } from "../../../common/wowup/app-options";
import * as minimist from "minimist";
import { ZoomDirection, ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from "../../utils/zoom.utils";
@Injectable({
providedIn: "root",
@@ -26,6 +27,7 @@ export class ElectronService {
private readonly _windowMaximizedSrc = new BehaviorSubject(false);
private readonly _windowMinimizedSrc = new BehaviorSubject(false);
private readonly _ipcEventReceivedSrc = new BehaviorSubject("");
private readonly _zoomFactorChangeSrc = new BehaviorSubject(1.0);
ipcRenderer: typeof ipcRenderer;
webFrame: typeof webFrame;
@@ -37,6 +39,7 @@ export class ElectronService {
public readonly windowMaximized$ = this._windowMaximizedSrc.asObservable();
public readonly windowMinimized$ = this._windowMinimizedSrc.asObservable();
public readonly ipcEventReceived$ = this._ipcEventReceivedSrc.asObservable();
public readonly zoomFactor$ = this._zoomFactorChangeSrc.asObservable();
public readonly isWin = process.platform === "win32";
public readonly isMac = process.platform === "darwin";
public readonly isLinux = process.platform === "linux";
@@ -128,6 +131,8 @@ export class ElectronService {
}
});
this._zoomFactorChangeSrc.next(this.getZoomFactor());
this.appOptions = (<any>minimist(this.remote.process.argv.slice(1), {
boolean: ["hidden", "quit"],
})) as AppOptions;
@@ -214,4 +219,36 @@ export class ElectronService {
public async invoke(channel: string, ...args: any[]): Promise<any> {
return await this.ipcRenderer.invoke(channel, ...args);
}
public applyZoom = (zoomDirection: ZoomDirection) => {
const zoomFactor = this.getZoomFactor();
const zoomInFactor = Math.min(ZOOM_MAX, zoomFactor + ZOOM_STEP);
const zoomOutFactor = Math.max(ZOOM_MIN, zoomFactor - ZOOM_STEP);
switch (zoomDirection) {
case ZoomDirection.ZoomIn:
this.setZoomFactor(zoomInFactor);
break;
case ZoomDirection.ZoomOut:
this.setZoomFactor(zoomOutFactor);
break;
case ZoomDirection.ZoomReset:
this.setZoomFactor(1.0);
break;
case ZoomDirection.ZoomUnknown:
default:
break;
}
};
public setZoomFactor = (zoomFactor: number) => {
const currentWindow = this.remote.getCurrentWindow();
currentWindow.webContents.zoomFactor = zoomFactor;
this._zoomFactorChangeSrc.next(zoomFactor);
};
public getZoomFactor(): number {
const currentWindow = this.remote.getCurrentWindow();
return currentWindow.webContents.zoomFactor;
}
}

View File

@@ -0,0 +1,40 @@
// See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
const ZOOM_IN_CODE = "Equal";
const ZOOM_OUT_CODE = "Minus";
const ZOOM_RESET_CODE = "Digit0";
export const ZOOM_SCALE = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0];
export const ZOOM_MIN = ZOOM_SCALE[0];
export const ZOOM_MAX = ZOOM_SCALE[ZOOM_SCALE.length - 1];
export const ZOOM_STEP = 0.25;
export enum ZoomDirection {
ZoomIn,
ZoomOut,
ZoomReset,
ZoomUnknown,
}
export function isZoomInShortcut(event: KeyboardEvent) {
return event.ctrlKey && event.code === ZOOM_IN_CODE;
}
export function isZoomOutShortcut(event: KeyboardEvent) {
return event.ctrlKey && event.code === ZOOM_OUT_CODE;
}
export function isZoomResetShortcut(event: KeyboardEvent) {
return event.ctrlKey && event.code === ZOOM_RESET_CODE;
}
export function getZoomDirection(event: KeyboardEvent): ZoomDirection {
if (isZoomInShortcut(event)) {
return ZoomDirection.ZoomIn;
} else if (isZoomOutShortcut(event)) {
return ZoomDirection.ZoomOut;
} else if (isZoomResetShortcut(event)) {
return ZoomDirection.ZoomReset;
}
return ZoomDirection.ZoomUnknown;
}