(Unreleased) Should now ignore next/prev hotkeys if the overlay isn't visible. Also improved binding/unbinding to be more rxjs-ish

cleanup
isark 1 year ago
parent a8334cbd03
commit 21333908ec

@ -5,6 +5,7 @@ import { Event } from "@tauri-apps/api/event";
import { invoke } from '@tauri-apps/api';
import { ConfigService } from './config.service';
import { appWindow } from '@tauri-apps/api/window';
import { Subscription } from 'rxjs';
export class StateEvent {
Visible?: any;
@ -23,11 +24,18 @@ export class OverlayService {
constructor(private shortcuts: ShortcutService, private events: EventsService, private configService: ConfigService) {
if (appWindow.label == "Overlay") {
this.shortcuts.register(this.configService.config.toggleOverlay, this.onToggleOverlay.bind(this));
this.registerInitialBinds();
this.events.listen<StateEvent>("OverlayStateChange").subscribe(this.onOverlayStateChange.bind(this));
}
this.isOverlay = appWindow.label === "Overlay";
}
registerInitialBinds() {
this.shortcuts.register(this.configService.config.toggleOverlay).subscribe((_shortcut) => {
this.onToggleOverlay()
});
}
onOverlayStateChange(event: Event<StateEvent>) {
@ -48,16 +56,4 @@ export class OverlayService {
invoke("set_interactable", { interactable: this.interactable }).then();
}
onBindToggleOverlayFinish(keys: string[]) {
this.isBinding = false;
let chord = keys.reduce((acc, curr) => {
if (acc === '') return curr;
return acc.concat('+').concat(curr);
}, '');
this.shortcuts.rebind(chord, this.onToggleOverlay);
this.configService.config.toggleOverlay = chord;
}
}

@ -1,45 +1,53 @@
import { Injectable, NgZone } from '@angular/core';
import { ShortcutHandler, register, unregister } from '@tauri-apps/api/globalShortcut';
import { EMPTY, from } from 'rxjs';
import { EMPTY, Observable, Subscriber, TeardownLogic, from } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ShortcutService {
bound: Map<ShortcutHandler, string> = new Map<ShortcutHandler, string>();
private internalHandlers: Map<string, [ShortcutHandler, Subscriber<string>, () => void]> = new Map<string, [ShortcutHandler, Subscriber<string>, () => void]>();
constructor(private zone: NgZone) {
}
register(shortcut: string, handler: ShortcutHandler) {
this.bound.set(handler, shortcut);
return from(register(shortcut, (s) => {
this.zone.run(() => handler(s));
}));
}
register(shortcut: string) {
return new Observable<string>((subscriber) => {
let originalHandler: ShortcutHandler = (s) => this.zone.run(() => subscriber.next(s));
const teardown = () => {
unregister(shortcut);
this.internalHandlers.delete(shortcut);
};
unregister(handler: ShortcutHandler) {
const shortcut = this.bound.get(handler);
this.bound.delete(handler);
this.internalHandlers.set(shortcut, [originalHandler, subscriber, teardown]);
return shortcut ? from(unregister(shortcut)) : EMPTY;
register(shortcut, originalHandler)
return teardown;
});
}
rebind(shortcut: string, handler: ShortcutHandler) {
const prevShortcut = this.bound.get(handler);
this.register(shortcut, handler).subscribe(
{
error: (_err) => {
if (prevShortcut) {
this.register(prevShortcut, handler);
}
return EMPTY;
}
});
unregister(shortcut: string) {
this.internalHandlers.get(shortcut)?.[1].complete();
this.internalHandlers.delete(shortcut);
}
rebind_from_to(previousShortcut: string, nextShortcut: string) {
const oldHandler = [...this.bound.entries()].find((entry: [ShortcutHandler, string]) => entry[1] === previousShortcut)?.[0];
this.rebind(nextShortcut, oldHandler!);
let [oldHandler, subscriber, teardown] = this.internalHandlers.get(previousShortcut)!;
subscriber.remove(teardown);
teardown();
teardown = () => {
unregister(nextShortcut);
this.internalHandlers.delete(nextShortcut);
};
register(nextShortcut, oldHandler);
this.internalHandlers.set(nextShortcut, [oldHandler, subscriber, teardown]);
}
}

@ -74,8 +74,9 @@
<h2>Plan</h2>
<div cdkDropList #planList [cdkDropListData]="filterPlanElements()" class="list"
(cdkDropListDropped)="dropHandler($event)" [cdkDropListDisabled]="disabledPlanDD"
[cdkDropListEnterPredicate]="canDrop">
<div class="box" *ngFor="let item of filterPlanElements()" cdkDrag (contextmenu)="addNote($event, item)">
[cdkDropListEnterPredicate]="canDrop"
[cdkDropListSortPredicate]="sortPredicate.bind(this)">
<div class="box" *ngFor="let item of filterPlanElements(); index as boxIndex" cdkDrag [cdkDragDisabled]="(!!this.planFilterAct.value) && boxIndex == 0" (contextmenu)="addNote($event, item)">
<div class="content">
<div class="zone-name">{{areasMap?.get(item.area_key)?.name}}</div>
<div class="act">Act {{areasMap?.get(item.area_key)?.act}}</div>

@ -107,6 +107,10 @@ export class EditorComponent implements OnInit {
});
}
sortPredicate(index: number, _item: CdkDrag<WorldArea> | CdkDrag<PlanElement>) {
return !(this.planElemFilterBounds() && index == 0)
}
dropHandler(event: CdkDragDrop<WorldArea[]> | CdkDragDrop<PlanElement[]>) {
if (event.previousContainer === event.container && !isWorldAreaEvent(event)) {
const realCurrent = this.plan.plan.indexOf(event.previousContainer.data[event.currentIndex]);
@ -117,7 +121,13 @@ export class EditorComponent implements OnInit {
if (event.container.data.length > 0 && 'connections_world_areas_keys' in event.container.data[0]) {
return;
}
this.plan.plan.splice(event.currentIndex, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex]));
const bounds = this.planElemFilterBounds();
let index = event.currentIndex;
if(bounds) {
index += bounds[0];
}
this.plan.plan.splice(index, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex]));
}
}

@ -9,11 +9,13 @@ import { PlanService } from '../_services/plan.service';
import { Plan, PlanElement } from '../_models/plan';
import { WorldAreaService } from '../_services/world-area.service';
import { WorldArea } from '../_models/world-area';
import { from } from 'rxjs';
import { Observable, Subscription, from } from 'rxjs';
import { open } from '@tauri-apps/api/dialog';
import { OverlayService } from '../_services/overlay.service';
import { OverlayService, StateEvent } from '../_services/overlay.service';
import { appWindow } from '@tauri-apps/api/window';
import { EventsService } from '../_services/events.service';
import { UnlistenFn } from '@tauri-apps/api/event';
import { Event } from '@tauri-apps/api/event';
@Component({
selector: 'plan-display',
@ -35,6 +37,11 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
init: boolean = false;
hasAttachedOnce: boolean = false;
overlayStateChangeHandle?: Subscription;
bindsAreSetup: boolean = false;
nextBind?: Subscription;
prevBind?: Subscription;
constructor(private events: EventsService, public configService: ConfigService, private cdr: ChangeDetectorRef, private shortcut: ShortcutService, public planService: PlanService, public worldAreaService: WorldAreaService, public overlayService: OverlayService, private zone: NgZone) {
window.addEventListener("resize", () => {
this.zone.run(() => {
@ -42,6 +49,11 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
})
});
appWindow.listen("entered", (entered) => {
if (this.planService.currentPlan) {
const current = this.planService.currentPlan.current;
@ -65,7 +77,23 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
ngOnInit() {
this.worldAreaService.getWorldAreas().subscribe(a => this.worldAreaMap = a);
this.overlayStateChangeHandle = this.events.listen<StateEvent>("OverlayStateChange").subscribe(this.onOverlayStateChange.bind(this));
}
onOverlayStateChange(event: Event<StateEvent>) {
if (event.payload.Hidden) {
this.destroyBinds();
} else {
this.setupBinds();
}
}
destroyBinds() {
if (this.bindsAreSetup) {
this.nextBind?.unsubscribe();
this.prevBind?.unsubscribe();
this.bindsAreSetup = false;
}
}
abs(v: number) {
@ -151,26 +179,35 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.zoneSlides.setIndex(this.slideIndex);
}
setupBinds() {
if (this.currentSlides && !this.bindsAreSetup) {
this.nextBind = this.shortcut.register(this.configService.config.prev).subscribe((_shortcut) => this.prev());
this.prevBind = this.shortcut.register(this.configService.config.next).subscribe((_shortcut) => this.next());
this.bindsAreSetup = true;
}
}
registerCurrentSlides(carousel: CarouselComponent<PlanElement>) {
this.currentSlides = carousel;
this.currentSlides.setIndex(this.slideIndex);
if (this.currentSlides) {
this.shortcut.register(this.configService.config.prev, this.prev.bind(this));
this.shortcut.register(this.configService.config.next, this.next.bind(this));
}
this.setupBinds();
}
next() {
this.planService.currentPlan!.next();
this.currentSlides?.next();
this.zoneSlides?.next();
if(this.overlayService.visible) {
this.planService.currentPlan!.next();
this.currentSlides?.next();
this.zoneSlides?.next();
}
}
prev() {
this.planService.currentPlan!.prev();
this.currentSlides?.prev();
this.zoneSlides?.prev();
if(this.overlayService.visible) {
this.planService.currentPlan!.prev();
this.currentSlides?.prev();
this.zoneSlides?.prev();
}
}
setIndex(index: number) {

Loading…
Cancel
Save