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.
316 lines
8.4 KiB
316 lines
8.4 KiB
import { AfterViewInit, ChangeDetectorRef, Component, Input, NgZone, OnInit, ViewChild } from '@angular/core';
|
|
import { NgxMoveableComponent, OnDragEnd, OnResize, OnResizeEnd } from 'ngx-moveable';
|
|
import { OnDrag } from 'ngx-moveable';
|
|
import { ConfigService } from '../_services/config.service';
|
|
import { Rect } from '../_models/generated/Rect';
|
|
import { ShortcutService } from '../_services/shortcut.service';
|
|
import { CarouselComponent } from '../carousel/carousel.component';
|
|
import { PlanService } from '../_services/plan.service';
|
|
import { Plan, PlanElement, PlanMetadata } from '../_models/plan';
|
|
import { WorldAreaService } from '../_services/world-area.service';
|
|
import { WorldArea } from '../_models/world-area';
|
|
import { Subscription, from } from 'rxjs';
|
|
import { open } from '@tauri-apps/api/dialog';
|
|
import { OverlayService, StateEvent } from '../_services/overlay.service';
|
|
import { appWindow } from '@tauri-apps/api/window';
|
|
import { EventsService } from '../_services/events.service';
|
|
import { Event } from '@tauri-apps/api/event';
|
|
|
|
@Component({
|
|
selector: 'plan-display',
|
|
templateUrl: './plan-display.component.html',
|
|
styleUrls: ['./plan-display.component.scss']
|
|
})
|
|
export class PlanDisplayComponent implements AfterViewInit, OnInit {
|
|
|
|
@Input() backgroundColor?: String;
|
|
draggable: boolean = true;
|
|
rect?: Rect;
|
|
bounds: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" };
|
|
@ViewChild("moveable") moveable?: NgxMoveableComponent;
|
|
|
|
slideIndex: number = 0;
|
|
zoneSlides?: CarouselComponent<PlanElement>;
|
|
currentSlides?: CarouselComponent<PlanElement>;
|
|
worldAreaMap?: Map<String, WorldArea>;
|
|
settingsOpen: boolean = false;
|
|
init: boolean = false;
|
|
hasAttachedOnce: boolean = false;
|
|
|
|
overlayStateChangeHandle?: Subscription;
|
|
bindsAreSetup: boolean = false;
|
|
nextBind?: Subscription;
|
|
prevBind?: Subscription;
|
|
|
|
currentPlan?: Plan;
|
|
previousPlans: PlanMetadata[] = [];
|
|
|
|
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(() => {
|
|
this.windowInitHandler()
|
|
})
|
|
});
|
|
|
|
|
|
this.planService.enumerateStoredPlans().subscribe(plans => {
|
|
this.previousPlans = plans;
|
|
})
|
|
|
|
this.planService.getCurrentPlan().subscribe(plan => {
|
|
this.currentPlan = plan;
|
|
setTimeout(() => this.setIndex(plan.current), 0);
|
|
})
|
|
}
|
|
|
|
registerOnZoneEnter() {
|
|
appWindow.listen("entered", (entered) => {
|
|
if (this.currentPlan) {
|
|
const current = this.currentPlan.current;
|
|
const length = this.currentPlan.plan.length;
|
|
if (current + 1 < length) {
|
|
if (entered.payload === this.currentPlan.plan[current + 1].area_key) {
|
|
this.zone.run(() => this.next());
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
windowInitHandler() {
|
|
if (window.innerWidth > 0) {
|
|
this.ngAfterViewInit();
|
|
}
|
|
}
|
|
|
|
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) {
|
|
return Math.abs(v);
|
|
}
|
|
|
|
transform() {
|
|
return `translate(${this.rect!.x}px, ${this.rect!.y}px)`;
|
|
}
|
|
|
|
width() {
|
|
return `${this.rect!.width}px`;
|
|
}
|
|
|
|
height() {
|
|
return `${this.rect!.height}px`;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
ngAfterViewInit(): void {
|
|
if (window.innerWidth > 0) {
|
|
const cfgRect = this.configService.config.initialPlanWindowPosition;
|
|
|
|
this.rect = {
|
|
x: cfgRect.x * window.innerWidth,
|
|
y: cfgRect.y * window.innerHeight,
|
|
width: cfgRect.width * window.innerWidth,
|
|
height: cfgRect.height * window.innerHeight,
|
|
}
|
|
this.moveable?.updateRect();
|
|
|
|
setTimeout(() => this.cdr.detectChanges(), 0);
|
|
this.init = true;
|
|
}
|
|
}
|
|
|
|
onDrag(e: OnDrag) {
|
|
this.rect!.x = e.translate[0];
|
|
this.rect!.y = e.translate[1];
|
|
}
|
|
|
|
onDragEnd(e: OnDragEnd) {
|
|
this.saveRect();
|
|
}
|
|
|
|
onResize(e: OnResize) {
|
|
this.rect!.width = e.width;
|
|
this.rect!.height = e.height;
|
|
this.onDrag(e.drag);
|
|
}
|
|
|
|
onResizeEnd(e: OnResizeEnd) {
|
|
this.saveRect();
|
|
}
|
|
|
|
saveRect() {
|
|
const toCfgRect = this.rect!;
|
|
this.configService.config.initialPlanWindowPosition = {
|
|
x: toCfgRect.x / window.innerWidth,
|
|
y: toCfgRect.y / window.innerHeight,
|
|
width: toCfgRect.width / window.innerWidth,
|
|
height: toCfgRect.height / window.innerHeight,
|
|
}
|
|
}
|
|
|
|
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());
|
|
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);
|
|
|
|
this.setupBinds();
|
|
}
|
|
|
|
next() {
|
|
if (this.overlayService.visible) {
|
|
this.currentPlan!.next();
|
|
this.currentSlides?.next();
|
|
this.zoneSlides?.next();
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
loadPrevious(path: string) {
|
|
this.planService.loadPlanFromPath(path, false).subscribe(plan => {
|
|
this.planService.setCurrentPlan(plan);
|
|
});
|
|
}
|
|
|
|
settingsClick(event: any) {
|
|
this.settingsOpen = !this.settingsOpen;
|
|
event.stopPropagation();
|
|
}
|
|
|
|
openDialog() {
|
|
from(open({
|
|
multiple: false,
|
|
filters: [
|
|
{
|
|
name: "JSON (.json)",
|
|
extensions: ['json']
|
|
}
|
|
]
|
|
})).subscribe(file => {
|
|
if (file) {
|
|
this.planService.loadPlanFromPath(file as string).subscribe(plan => {
|
|
if (plan) {
|
|
this.planService.setCurrentPlan(plan);
|
|
this.settingsOpen = false;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
loadBasePlan() {
|
|
this.planService.getBasePlan().subscribe(plan => {
|
|
this.currentPlan = new Plan(plan);
|
|
if (this.zoneSlides) {
|
|
this.zoneSlides.setIndex(0);
|
|
}
|
|
if (this.currentSlides) {
|
|
this.currentSlides.setIndex(0);
|
|
}
|
|
})
|
|
}
|
|
|
|
onScroll(event: WheelEvent) {
|
|
if (event.deltaY < 0) {
|
|
this.prev();
|
|
} else {
|
|
this.next();
|
|
}
|
|
}
|
|
|
|
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`
|
|
}
|
|
}
|
|
|
|
loadFromUrl() {
|
|
this.planService.loadFromUrl().subscribe(plan => {
|
|
console.log("plan", plan);
|
|
if (plan) {
|
|
this.planService.savePlanAtStore(plan.name!, plan).subscribe((path) => {
|
|
console.log("path", path);
|
|
if(path) {
|
|
plan.setPath(path);
|
|
}
|
|
});
|
|
this.planService.setCurrentPlan(plan);
|
|
}
|
|
});
|
|
}
|
|
}
|