You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Nothing/src/app/plan-display/plan-display.component.ts

315 lines
9.0 KiB

import { Component, Input, NgZone, OnInit } from '@angular/core';
import { ConfigService } from '../_services/config.service';
import { ShortcutService } from '../_services/shortcut.service';
import { CarouselComponent } from '../carousel/carousel.component';
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 { Subscription, from } from 'rxjs';
import { OverlayService, StateEvent } from '../_services/overlay.service';
import { webviewWindow as appWindow} from '@tauri-apps/api';
// import { appWindow } from 'webviewWindow';
import { EventsService } from '../_services/events.service';
import { Event } from '@tauri-apps/api/event';
import { MatDialog } from '@angular/material/dialog';
import { TimeTrackerService } from '../_services/time-tracker.service';
import { RunStatService } from '../_services/run-stat.service';
@Component({
selector: 'plan-display',
templateUrl: './plan-display.component.html',
styleUrls: ['./plan-display.component.scss']
})
export class PlanDisplayComponent implements OnInit {
@Input() backgroundColor?: string;
slideIndex: number = 0;
zoneSlides?: CarouselComponent<PlanElement>;
currentSlides?: CarouselComponent<PlanElement>;
worldAreaMap?: Map<String, WorldArea>;
settingsOpen: boolean = false;
hasAttachedOnce: boolean = false;
overlayStateChangeHandle?: Subscription;
bindsAreSetup: boolean = false;
nextBind?: Subscription;
prevBind?: Subscription;
currentPlan?: Plan;
constructor(
public configService: ConfigService,
public planService: PlanService,
public worldAreaService: WorldAreaService,
public overlayService: OverlayService,
public dialog: MatDialog,
public timeTrackerService: TimeTrackerService,
private events: EventsService,
private shortcut: ShortcutService,
private zone: NgZone,
private runStatService: RunStatService,
) {
this.planService.getCurrentPlan().subscribe(plan => {
this.currentPlan = plan;
if (this.configService.config.enableStopwatch) {
this.loadComparisonData(this.currentPlan);
}
this.timeTrackerService.onNewRun(plan);
//Close settings anytime we get a new current plan.
this.settingsOpen = false;
setTimeout(() => this.setIndex(plan.current), 0);
})
this.registerOnZoneEnter();
}
loadComparisonData(plan: Plan) {
if (!this.configService.config.runCompareHistory) {
return;
}
this.timeTrackerService.loadHistory(this.configService.config.runCompareHistory).subscribe(history => {
if (history) {
this.runStatService.insertTimesAtCheckpoints(history, plan);
}
});
}
registerOnZoneEnter() {
appWindow.getCurrent().listen("entered", (entered) => {
if (this.currentPlan && typeof entered.payload == "string") {
if (this.currentPlan.isNext(entered.payload)) {
this.zone.run(() => this.next());
}
}
});
}
ngOnInit() {
this.worldAreaService.getFullWorldAreas().subscribe(a => this.worldAreaMap = a);
this.overlayStateChangeHandle = this.events.listen<StateEvent>("OverlayStateChange").subscribe(this.onOverlayStateChange.bind(this));
this.events.listen<boolean>("overlay_or_target_focus").subscribe((event: Event<boolean>) => {
if (!event.payload) {
this.destroyBinds();
} else {
this.setupBinds();
}
});
}
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) {
return Math.abs(v);
}
hasWaypoint(key?: string): boolean {
if (!key) {
key = this.currentPlan!.plan[this.currentPlan!.current].area_key;
}
const world_area = this.worldAreaMap?.get(key);
return world_area!.has_waypoint;
}
hasTrial(key?: string): boolean {
if (!key) {
key = this.currentPlan!.plan[this.currentPlan!.current].area_key;
}
return this.worldAreaService.hasTrial(key);
}
registerZoneSlides(carousel: CarouselComponent<PlanElement>) {
this.zoneSlides = carousel;
this.zoneSlides.setIndex(this.slideIndex);
}
setupBinds() {
if (this.currentSlides && !this.bindsAreSetup) {
this.nextBind = this.shortcut.register(this.configService.config.prev).subscribe((_shortcut) => {
this.prev();
if (this.configService.config.enableStopwatch) {
this.timeTrackerService.onForcePrev(this.currentPlan!.plan[this.currentPlan!.current].area_key);
this.checkCheckpoint();
}
});
this.prevBind = this.shortcut.register(this.configService.config.next).subscribe((_shortcut) => {
this.next();
if (this.configService.config.enableStopwatch) {
this.timeTrackerService.onForceNext(this.currentPlan!.plan[this.currentPlan!.current].area_key);
this.checkCheckpoint();
}
});
this.bindsAreSetup = true;
}
}
registerCurrentSlides(carousel: CarouselComponent<PlanElement>) {
this.currentSlides = carousel;
this.currentSlides.setIndex(this.slideIndex);
this.setupBinds();
}
next() {
if (this.overlayService.visible) {
this.currentPlan!.next();
this.checkCheckpoint();
this.currentSlides?.next();
this.zoneSlides?.next();
}
}
checkCheckpoint() {
if (!this.currentPlan || !this.timeTrackerService.isActive) return;
const currentElem = this.currentPlan.plan[this.currentPlan.current];
if (currentElem.checkpoint && !currentElem.checkpoint_your_millis) {
currentElem.checkpoint_your_millis = this.timeTrackerService.elapsedTimeMillis;
this.timeTrackerService.reportCheckpoint(currentElem.uuid!);
}
}
yourDiff(element: PlanElement) {
if (!element.checkpoint || !element.checkpoint_your_millis || !element.checkpoint_millis) return "";
const diff = element.checkpoint_your_millis - element.checkpoint_millis;
const neg = diff <= 0;
const abs = Math.abs(diff);
if (diff == 0) {
return `${neg ? "-" : "+"}00:00:00`;
} else {
return `${neg ? "-" : "+"}${this.timeTrackerService.hmsTimestamp(abs)}`;
}
}
yourDiffClass(element: PlanElement): string {
if (!element.checkpoint || !element.checkpoint_your_millis || !element.checkpoint_millis) return "";
const diff = element.checkpoint_your_millis - element.checkpoint_millis;
const neg = diff <= 0;
return neg ? "negative-diff" : "positive-diff";
}
showDiff(element: PlanElement) {
return element.checkpoint && element.checkpoint_your_millis && element.checkpoint_millis;
}
cpMillis(element: PlanElement) {
if (!element.checkpoint) return "";
if (!element.checkpoint_millis) return "N/A";
return this.timeTrackerService.hmsTimestamp(element.checkpoint_millis);
}
prev() {
if (this.overlayService.visible) {
this.currentPlan!.prev();
this.currentSlides?.prev();
this.zoneSlides?.prev();
}
}
setIndex(index: number) {
this.slideIndex = index;
if (this.currentSlides) {
this.currentSlides.setIndex(index);
}
if (this.zoneSlides) {
this.zoneSlides.setIndex(index);
}
}
settingsClick(event: any) {
this.settingsOpen = !this.settingsOpen;
event.stopPropagation();
}
onScroll(event: WheelEvent) {
if (event.deltaY < 0) {
this.prev();
this.timeTrackerService.onForcePrev(this.currentPlan!.plan[this.currentPlan!.current].area_key);
this.checkCheckpoint();
} else {
this.next();
this.timeTrackerService.onForceNext(this.currentPlan!.plan[this.currentPlan!.current].area_key);
this.checkCheckpoint();
}
}
specialClasses() {
const waypoint = this.hasWaypoint() ? 'active' : '';
const trial = this.hasTrial() ? 'trial-active' : '';
return `${waypoint} ${trial}`;
}
clampedOffset(): number {
return Math.min(this.configService.config.numVisible - 1, this.configService.config.offset);
}
zonesStyle() {
return {
'min-height': `${this.configService.config.numVisible * 18}px`,
'max-height': `${this.configService.config.numVisible * 40}px`
}
}
shouldDisplayTimer(): boolean {
if (!this.configService.config.enableStopwatch) return false;
return this.timeTrackerService.isActive;
}
displayZoneName(zoneName: string) {
if (this.configService.config.shortenZoneNames) {
return this.trim(this.trimUnneccesaryWords(zoneName));
} else {
return zoneName;
}
}
trimUnneccesaryWords(zoneName: string) {
if (zoneName.toLowerCase().startsWith("the ")) {
return zoneName.substring(4);
} else {
return zoneName;
}
}
trim(zoneName: string, letters: number = 12) {
if (zoneName.length > letters + 3) {
return zoneName.substring(0, letters) + "...";
}
return zoneName;
}
}