Added some basic chortcut handling

merge-notes
isark 2 years ago
parent ec7523f9b0
commit f764048f23

@ -14,8 +14,10 @@
<input type="checkbox" [(ngModel)]="auto_hide" (change)="toggleAutoHide()"> <input type="checkbox" [(ngModel)]="auto_hide" (change)="toggleAutoHide()">
<input type="checkbox" [(ngModel)]="interactable"><span>{{interactable}}</span> <input type="checkbox" [(ngModel)]="interactable"><span>{{interactable}}</span>
<input type="checkbox" [(ngModel)]="test"> <input type="checkbox" [(ngModel)]="isBinding">
<ng-container *ngIf="test"> <ng-container *ngIf="isBinding">
<span RecordKeyChord></span> <span RecordKeyChord (finishedKeyChord)="onBindFinish($event)"></span>
</ng-container> </ng-container>
<input>
</div> </div>

@ -1,7 +1,9 @@
import { Component, Directive, HostListener, OnInit } from "@angular/core"; import { Component, Directive, HostListener, OnDestroy, OnInit } from "@angular/core";
import { invoke } from "@tauri-apps/api/tauri"; import { invoke } from "@tauri-apps/api/tauri";
import { ShortcutService } from "./services/shortcut.service"; import { ShortcutService } from "./services/shortcut.service";
import { EventsService } from "./services/events.service"; import { EventsService } from "./services/events.service";
import { Event } from "@tauri-apps/api/event";
import { catchError } from "rxjs";
class StateEvent { class StateEvent {
Visible?: any; Visible?: any;
@ -14,33 +16,53 @@ class StateEvent {
templateUrl: "./app.component.html", templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"], styleUrls: ["./app.component.css"],
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit, OnDestroy {
auto_hide: boolean = true; auto_hide: boolean = true;
interactable: boolean = false; interactable: boolean = false;
test: boolean = false; isBinding: boolean = false;
constructor(private shortcuts: ShortcutService, private events: EventsService) { } constructor(private shortcuts: ShortcutService, private events: EventsService) { }
ngOnDestroy(): void {
this.shortcuts.unregister(this.onToggleOverlay);
}
ngOnInit(): void { ngOnInit(): void {
invoke("set_auto_hide", { auto_hide: this.auto_hide }).then(); invoke("set_auto_hide", { auto_hide: this.auto_hide }).then();
this.shortcuts.register('F6', this.onToggleOverlay);
this.events.listen<StateEvent>("OverlayStateChange").subscribe(this.onOverlayStateChange)
}
onOverlayStateChange(event: Event<StateEvent>) {
this.interactable = event.payload.Interactable != null;
}
this.shortcuts.register('F6').subscribe((s) => { onToggleOverlay = () => {
if (this.interactable) { console.log(this);
this.interactable = false; if (this.interactable) {
} else { this.interactable = false;
this.interactable = true; } else {
} this.interactable = true;
}
invoke("set_interactable", { interactable: this.interactable }).then();
})
this.events.listen<StateEvent>("OverlayStateChange").subscribe(event => { invoke("set_interactable", { interactable: this.interactable }).then();
this.interactable = event.payload.Interactable != null;
})
} }
toggleAutoHide() { toggleAutoHide() {
console.log("toggle auto hide!!"); console.log("toggle auto hide!!");
invoke("set_auto_hide", { autoHide: this.auto_hide }).then(); invoke("set_auto_hide", { autoHide: this.auto_hide }).then();
} }
onBindFinish(keys: string[]) {
this.isBinding = false;
let chord = keys.reduce((acc, curr) => {
if (acc === '') return curr;
return acc.concat('+').concat(curr);
}, '');
console.log(chord);
this.shortcuts.rebind(chord, this.onToggleOverlay);
}
} }

@ -1,20 +1,26 @@
import { Directive, HostListener, Input } from '@angular/core'; import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
@Directive({ @Directive({
selector: '[RecordKeyChord]' selector: '[RecordKeyChord]'
}) })
export class RecordKeyChord { export class RecordKeyChord {
@Input('enable') enable: boolean = false; @Output() finishedKeyChord = new EventEmitter<string[]>;
chordStack: string[] = [];
@HostListener('window:keydown', ['$event']) @HostListener('window:keydown', ['$event'])
handleKeyDown(event: KeyboardEvent) { handleKeyDown(event: KeyboardEvent) {
console.log("keydown:", event); console.log("keydown:", event);
this.chordStack.push(event.key);
} }
@HostListener('window:keyup', ['$event']) @HostListener('window:keyup', ['$event'])
handleKeyUp(event: KeyboardEvent) { handleKeyUp(event: KeyboardEvent) {
console.log("keydown:", event); console.log("keyup:", event);
this.finishedKeyChord.next(this.chordStack);
this.chordStack = [];
} }
} }

@ -19,4 +19,4 @@ export class EventsService {
emit<T>(name: string, event: T): Observable<void> { emit<T>(name: string, event: T): Observable<void> {
return from(emit(name, event)); return from(emit(name, event));
} }
} }

@ -1,19 +1,39 @@
import { Injectable, NgZone } from '@angular/core'; import { Injectable, NgZone } from '@angular/core';
import { register } from '@tauri-apps/api/globalShortcut'; import { ShortcutHandler, register, unregister } from '@tauri-apps/api/globalShortcut';
import { Observable } from 'rxjs'; import { EMPTY, Observable, catchError, empty, from } from 'rxjs';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ShortcutService { export class ShortcutService {
bound: Map<ShortcutHandler, string> = new Map<ShortcutHandler, string>();
constructor(private zone: NgZone) { } constructor(private zone: NgZone) { }
register(shortcut: string) { register(shortcut: string, handler: ShortcutHandler) {
this.bound.set(handler, shortcut);
return from(register(shortcut, (s) => {
this.zone.run(() => handler(s));
}));
}
unregister(handler: ShortcutHandler) {
const shortcut = this.bound.get(handler);
this.bound.delete(handler);
return shortcut ? from(unregister(shortcut)) : EMPTY;
}
rebind(shortcut: string, handler: ShortcutHandler) {
const prevShortcut = this.bound.get(handler)!;
this.register(shortcut, handler).subscribe(
{
error: (_err) => {
this.register(prevShortcut, handler);
console.log("Got error during binding, rebinding previous");
return EMPTY;
return new Observable((subscriber) => { }
register(shortcut, (s) => { });
this.zone.run(() => subscriber.next(s));
})
});
} }
} }

Loading…
Cancel
Save