Ability to detach notes. Generic "window" component since I'm now at 3 windows and it is getting cumbersome duplicating all that code all over the place.

main
isark 1 year ago
parent 7c3e739f8d
commit 5c2d03272f

@ -28,6 +28,8 @@ pub struct Config {
pub initial_plan_window_position: Rect,
#[serde(default = "Config::default_initial_agg_window_position")]
pub initial_agg_window_position: Rect,
#[serde(default = "Config::default_initial_notes_window_position")]
pub initial_notes_window_position: Rect,
#[serde(default = "Config::default_hide_on_unfocus")]
pub hide_on_unfocus: bool,
#[serde(default = "Config::default_toggle_overlay")]
@ -55,6 +57,8 @@ pub struct Config {
#[serde(default = "Config::default_run_compare_history")]
pub run_compare_history: Option<String>,
#[serde(default = "Config::default_detach_notes")]
detach_notes: bool,
#[serde(default = "Config::default_show_livesplit")]
show_livesplit: bool,
@ -69,6 +73,7 @@ impl Default for Config {
Self {
initial_plan_window_position: Self::default_initial_plan_window_position(),
initial_agg_window_position: Self::default_initial_agg_window_position(),
initial_notes_window_position: Self::default_initial_agg_window_position(),
hide_on_unfocus: Self::default_hide_on_unfocus(),
toggle_overlay: Self::default_toggle_overlay(),
prev: Self::default_prev(),
@ -83,6 +88,7 @@ impl Default for Config {
num_visible: Self::default_plan_num_visible(),
offset: Self::default_plan_offset(),
run_compare_history: Self::default_run_compare_history(),
detach_notes: Self::default_detach_notes(),
enable_stopwatch: Self::default_enable_stopwatch(),
show_livesplit: Self::default_show_livesplit(),
show_live_aggregate: Self::default_show_live_aggregate(),
@ -100,6 +106,10 @@ impl Config {
Default::default()
}
fn default_initial_notes_window_position() -> Rect {
Default::default()
}
fn default_hide_on_unfocus() -> bool {
true
}
@ -159,4 +169,7 @@ impl Config {
fn default_shorten_zone_names() -> bool {
false
}
fn default_detach_notes() -> bool {
false
}
}

@ -112,8 +112,9 @@ export class TimeTrackerService {
this.currentRunHistory = history;
this.newCurrentRunHistorySubject.next(history);
}
get elapsedTimeMillis() {
this.latest = new Date();
return this.latest!.valueOf() - this.start!.valueOf();
}

@ -0,0 +1,15 @@
<ng-container *ngIf="init">
<ng-container *ngIf="rect">
<div class="target" [style.transform]="transform()" [style.width]="rect.width + 'px'"
[style.height]="rect.height + 'px'"
[style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'" #targetRef>
<ng-content></ng-content>
</div>
<ngx-moveable #moveable [target]="targetRef" [draggable]="configurable" [resizable]="configurable"
(drag)="onDrag($event)" (resize)="onResize($event)" (dragEnd)="onDragEnd($event)"
(resizeEnd)="onResizeEnd($event)" [bounds]="bounds" [snappable]="true"
[style.visibility]="configurable ? 'visible' : 'hidden'">
</ngx-moveable>
</ng-container>
</ng-container>

@ -0,0 +1,9 @@
:host {
overflow: visible;
}
.target {
position: absolute;
min-width: 50px;
min-height: 50px;
}

@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DraggableWindowComponent } from './draggable-window.component';
describe('DraggableWindowComponent', () => {
let component: DraggableWindowComponent;
let fixture: ComponentFixture<DraggableWindowComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [DraggableWindowComponent]
});
fixture = TestBed.createComponent(DraggableWindowComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,88 @@
import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, NgZone, OnInit, Output, ViewChild } from '@angular/core';
import { Rect } from '../_models/generated/Rect';
import { NgxMoveableComponent, NgxMoveableModule, OnDrag, OnDragEnd, OnResize, OnResizeEnd } from 'ngx-moveable';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-draggable-window',
templateUrl: './draggable-window.component.html',
styleUrls: ['./draggable-window.component.scss'],
standalone: true,
imports: [CommonModule, NgxMoveableModule]
})
export class DraggableWindowComponent implements AfterViewInit {
rect?: Rect;
bounds: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" };
@Input() public backgroundColor: string = "rgba(0, 0, 0, 0.1)";
@Input() public configurable: boolean = true;
@Input() public initialRect?: Rect;
@Output() savedRect: EventEmitter<Rect> = new EventEmitter();
@ViewChild("moveable") moveable?: NgxMoveableComponent;
init = false;
constructor(private cdr: ChangeDetectorRef, private zone: NgZone) {
window.addEventListener("resize", () => {
this.zone.run(() => {
this.windowInitHandler()
})
});
}
windowInitHandler() {
if (window.innerWidth > 0) {
const cfgRect = this.initialRect || { x: 0, y: 0, width: 0.1, height: 0.1 };
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;
}
}
ngAfterViewInit(): void {
this.windowInitHandler();
}
transform() {
return `translate(${this.rect!.x}px, ${this.rect!.y}px)`;
}
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() {
if (this.rect) {
this.savedRect.emit({
x: this.rect.x / window.innerWidth,
y: this.rect.y / window.innerHeight,
width: this.rect.width / window.innerWidth,
height: this.rect.height / window.innerHeight,
});
}
}
}

@ -1,154 +1,157 @@
<ng-container *ngIf="init">
<div #globalTopLeft style="position: fixed; top: 0; left: 0; z-index: -1;"></div>
<div class=""></div>
<ng-container *ngIf="rect && currentPlan">
<div style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none;">
<div class="target waypoint trial"
[style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'"
[style.transform]="transform()" [style.width]="rect.width + 'px'" [style.height]="rect.height + 'px'"
[class]="specialClasses()" (wheel)="onScroll($event)" #targetRef>
<ng-container *ngIf="currentPlan">
<carousel class="zones" [initIndex]="currentPlan.current"
[numVisible]="configService.config.numVisible" [offset]="clampedOffset()"
[slides]="currentPlan.plan" (afterInitSelf)="registerZoneSlides($event)"
[ngStyle]="zonesStyle()">
<ng-template let-slide let-index="index">
<div class="zone-slide" [style.color]="configService.config.noteDefaultFg"
[style.border]="index == currentPlan.current ? '1px white solid' : 'none'">
<div class="text-marker-left d-flex flex-row"
*ngIf="configService.config.showLivesplit && showDiff(slide)">
<div style="margin: 0 3px;" [class]="yourDiffClass(slide)">{{yourDiff(slide)}}</div>
<div #globalTopLeft style="position: fixed; top: 0; left: 0; z-index: -1;"></div>
<div class=""></div>
<ng-container *ngIf="currentPlan">
<app-draggable-window [initialRect]="configService.config.initialPlanWindowPosition"
[configurable]="overlayService.interactable"
(savedRect)="configService.config.initialPlanWindowPosition = $event"
[backgroundColor]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'" (wheel)="onScroll($event)">
<div class="plan-window waypoint trial" [class]="specialClasses()">
<ng-container *ngIf="currentPlan">
<carousel class="zones" [initIndex]="currentPlan.current" [numVisible]="configService.config.numVisible"
[offset]="clampedOffset()" [slides]="currentPlan.plan" (afterInitSelf)="registerZoneSlides($event)"
[ngStyle]="zonesStyle()">
<ng-template let-slide let-index="index">
<div class="zone-slide" [style.color]="configService.config.noteDefaultFg"
[style.border]="index == currentPlan.current ? '1px white solid' : 'none'">
<div class="text-marker-left d-flex flex-row"
*ngIf="configService.config.showLivesplit && showDiff(slide)">
<div style="margin: 0 3px;" [class]="yourDiffClass(slide)">{{yourDiff(slide)}}
</div>
</div>
<div style="margin: 0 5px">{{displayZoneName(worldAreaMap!.get(slide.area_key)!.name)}}
</div>
<div style="margin: 0 5px">
{{displayZoneName(worldAreaMap!.get(slide.area_key)!.name)}}
</div>
<div class="text-marker d-flex flex-row">
<div *ngIf="configService.config.showLivesplit" style="margin: 0 3px;">
{{cpMillis(slide)}}</div>
<div class="waypoint-text" *ngIf="hasWaypoint(slide.area_key)">(W)</div>
<div class="trial-text" *ngIf="hasTrial(slide.area_key)">(T)</div>
</div>
<div class="text-marker d-flex flex-row">
<div *ngIf="configService.config.showLivesplit" style="margin: 0 3px;">
{{cpMillis(slide)}}</div>
<div class="waypoint-text" *ngIf="hasWaypoint(slide.area_key)">(W)</div>
<div class="trial-text" *ngIf="hasTrial(slide.area_key)">(T)</div>
</div>
</ng-template>
</carousel>
<carousel [initIndex]="currentPlan.current" [slides]="currentPlan.plan"
(afterInitSelf)="registerCurrentSlides($event)">
<ng-template let-slide>
<scalable [clamp]="2">
<notes class="p-1" [note]="slide.notes"
[style.color]="configService.config.noteDefaultFg" #noteSlide></notes>
</scalable>
</ng-template>
</carousel>
</div>
</ng-template>
</carousel>
<carousel *ngIf="!configService.config.detachNotes" [initIndex]="currentPlan.current"
[slides]="currentPlan.plan" (afterInitSelf)="registerCurrentSlides($event)">
<ng-template let-slide>
<scalable [clamp]="2">
<notes class="p-1" [note]="slide.notes" [style.color]="configService.config.noteDefaultFg"
#noteSlide></notes>
</scalable>
</ng-template>
</carousel>
</ng-container>
<button mat-icon-button *ngIf="overlayService.interactable" class="settings-button"
(click)="settingsClick($event)" (mousedown)="$event.stopPropagation()"><img
src="assets/material-settings.svg"></button>
<tooltip *ngIf="overlayService.interactable" class="help">
<div class="d-flex flex-column help-area">
<span><span class="waypoint-text">(W)</span> = Waypoint</span>
<span><span class="trial-text">(T)</span> = Trial</span>
<span>The plan window's will have a glow in the corresponding color(s) above to help indicate if
the
current zone has any of those.</span>
<span>You can scroll in the plan window (while it is in 'interactable' mode) to quickly switch
many
zones</span>
</div>
</tooltip>
<span *ngIf="shouldDisplayTimer()"
class="timer">{{timeTrackerService.hmsTimestamp(timeTrackerService.elapsedTimeMillis)}}</span>
</div>
</ng-container>
<button mat-icon-button *ngIf="overlayService.interactable" class="settings-button"
(click)="settingsClick($event)" (mousedown)="$event.stopPropagation()"><img
src="assets/material-settings.svg"></button>
<tooltip *ngIf="overlayService.interactable" class="help">
<div class="d-flex flex-column help-area">
<span><span class="waypoint-text">(W)</span> = Waypoint</span>
<span><span class="trial-text">(T)</span> = Trial</span>
<span>The plan window's will have a glow in the corresponding color(s) above to help
indicate if
the
current zone has any of those.</span>
<span>You can scroll in the plan window (while it is in 'interactable' mode) to quickly
switch
many
zones</span>
</div>
</tooltip>
<span *ngIf="shouldDisplayTimer()"
class="timer">{{timeTrackerService.hmsTimestamp(timeTrackerService.elapsedTimeMillis)}}</span>
<!-- </div> -->
</div>
</app-draggable-window>
<app-draggable-window *ngIf="configService.config.showLiveAggregate"
[initialRect]="configService.config.initialAggWindowPosition" [configurable]="overlayService.interactable"
(savedRect)="configService.config.initialAggWindowPosition = $event"
[backgroundColor]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'">
<app-aggregate-display></app-aggregate-display>
isark
</app-draggable-window>
<ngx-moveable #moveable [target]="targetRef" [draggable]="draggable && overlayService.interactable"
[resizable]="true && overlayService.interactable" (drag)="onDrag($event)" (resize)="onResize($event)"
(dragEnd)="onDragEnd($event)" (resizeEnd)="onResizeEnd($event)" [bounds]="bounds" [snappable]="true"
[style.visibility]="overlayService.interactable ? 'visible' : 'hidden'"></ngx-moveable>
<app-draggable-window [hidden]="!configService.config.detachNotes"
[initialRect]="configService.config.initialNotesWindowPosition" [configurable]="overlayService.interactable"
(savedRect)="configService.config.initialNotesWindowPosition = $event"
[backgroundColor]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'">
<div *ngIf="configService.config.detachNotes" class="standalone-notes">
<carousel [initIndex]="currentPlan.current" [slides]="currentPlan.plan"
(afterInitSelf)="registerCurrentSlides($event)">
<ng-template let-slide>
<scalable [clamp]="2">
<notes class="p-1" [note]="slide.notes" [style.color]="configService.config.noteDefaultFg"
#noteSlide></notes>
</scalable>
</ng-template>
</carousel>
</div>
<ng-container *ngIf="configService.config.showLiveAggregate && rectAgg">
<div style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none;">
<div class="target-aggregate" [style.transform]="transformAgg()" [style.width]="rectAgg.width + 'px'"
[style.height]="rectAgg.height + 'px'"
[style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'"
#aggregateTargetRef>
<app-aggregate-display></app-aggregate-display>
</div>
<ngx-moveable #moveable2 [target]="aggregateTargetRef"
[draggable]="draggable && overlayService.interactable"
[resizable]="true && overlayService.interactable" (drag)="onDragAgg($event)"
(resize)="onResizeAgg($event)" (dragEnd)="onDragEndAgg($event)" (resizeEnd)="onResizeEndAgg($event)"
[bounds]="boundsAgg" [snappable]="true"
[style.visibility]="overlayService.interactable && configService.config.showLiveAggregate ? 'visible' : 'hidden'"></ngx-moveable>
</div>
</ng-container>
</app-draggable-window>
</ng-container>
<ng-template cdkConnectedOverlay
[cdkConnectedOverlayOpen]="(settingsOpen || !currentPlan) && overlayService.interactable"
[cdkConnectedOverlayOrigin]="globalTopLeft" (detach)="settingsOpen = false">
<div class="overlay container-fluid vw-100">
<div class="row row-cols-2 h-100">
<div class="planChooser col-xs-6 col-sm-6 col-md-6 col-lg-4 col-xl-4 d-flex flex-column">
<div class="d-flex justify-content-evenly">
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="openDialog()">Browse
Plans
</button>
</div>
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="loadBasePlan()">
Load base plan
</button>
</div>
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="loadFromUrl()">
Import from url
</button>
</div>
</ng-container>
<ng-template cdkConnectedOverlay
[cdkConnectedOverlayOpen]="(settingsOpen || !currentPlan) && overlayService.interactable"
[cdkConnectedOverlayOrigin]="globalTopLeft" (detach)="settingsOpen = false">
<div class="overlay container-fluid vw-100">
<div class="row row-cols-2 h-100">
<div class="planChooser col-xs-6 col-sm-6 col-md-6 col-lg-4 col-xl-4 d-flex flex-column">
<div class="d-flex justify-content-evenly">
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="openDialog()">Browse
Plans
</button>
</div>
<div class="enumerated d-flex flex-column">
<mat-list role="list" class="d-flex flex-column h-100">
<cdk-virtual-scroll-viewport itemSize="10" class="h-100">
<mat-list-item class="d-flex flex-column" role="listitem"
*cdkVirtualFor="let plan of previousPlans">
<span>
<button [disabled]="disablePlans" (click)="loadPrevious(plan.stored_path!)">
<img *ngIf="plan.update_url" src="assets/public.svg">{{plan.name}}
</button><button *ngIf="plan.update_url" class="planActionButton"
[disabled]="disablePlans" (click)="checkForPlanUpdate(plan)"
[title]="recentPlanTitle(plan)">
<svg-icon *ngIf="!hasUpdate(plan)" src="assets/material-sync.svg" />
<svg-icon *ngIf="hasUpdate(plan) && !isErr(plan)"
src="assets/material-check.svg" class="nice" />
<svg-icon *ngIf="hasUpdate(plan) && isErr(plan)"
src="assets/material-warning.svg" class="notnice" />
</button>
</span>
</mat-list-item>
</cdk-virtual-scroll-viewport>
</mat-list>
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="loadBasePlan()">
Load base plan
</button>
</div>
<div class="col-xs-4">
<button class="" mat-raised-button color="accent" (click)="loadFromUrl()">
Import from url
</button>
</div>
</div>
<div class="enumerated d-flex flex-column">
<mat-list role="list" class="d-flex flex-column h-100">
<cdk-virtual-scroll-viewport itemSize="10" class="h-100">
<mat-list-item class="d-flex flex-column" role="listitem"
*cdkVirtualFor="let plan of previousPlans">
<span>
<button [disabled]="disablePlans" (click)="loadPrevious(plan.stored_path!)">
<img *ngIf="plan.update_url" src="assets/public.svg">{{plan.name}}
</button><button *ngIf="plan.update_url" class="planActionButton"
[disabled]="disablePlans" (click)="checkForPlanUpdate(plan)"
[title]="recentPlanTitle(plan)">
<svg-icon *ngIf="!hasUpdate(plan)" src="assets/material-sync.svg" />
<svg-icon *ngIf="hasUpdate(plan) && !isErr(plan)"
src="assets/material-check.svg" class="nice" />
<svg-icon *ngIf="hasUpdate(plan) && isErr(plan)"
src="assets/material-warning.svg" class="notnice" />
</button>
</span>
</mat-list-item>
</cdk-virtual-scroll-viewport>
</mat-list>
</div>
</div>
<settings class="col-xs-6 col-sm-6 offset-md-1 col-md-5 offset-lg-4 col-lg-4 offset-xl-4 col-xl-4">
</settings>
</div>
<button mat-icon-button class="exit" *ngIf="currentPlan"
(click)="settingsOpen = false"><span>+</span></button>
<settings class="col-xs-6 col-sm-6 offset-md-1 col-md-5 offset-lg-4 col-lg-4 offset-xl-4 col-xl-4">
</settings>
</div>
</ng-template>
<button mat-icon-button class="exit" *ngIf="currentPlan" (click)="settingsOpen = false"><span>+</span></button>
</div>
</ng-template>
<ng-container *ngIf="overlayService.interactable">
<button class="stop-stopwatch" mat-raised-button color="warn" *ngIf="timeTrackerService.isActive"
(click)="stopStopwatch()">Force stop stopwatch</button>
<button class="stop-stopwatch" mat-raised-button color="warn"

@ -7,9 +7,11 @@
}
}
.target {
.plan-window {
min-width: 50px;
min-height: 50px;
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
user-select: none;
@ -25,6 +27,12 @@
}
}
.standalone-notes {
height: 100%;
width: 100%;
overflow: hidden;
}
.target-aggregate {
min-width: 50px;
min-height: 50px;

@ -1,15 +1,12 @@
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 { ChangeDetectorRef, Component, Input, NgZone, OnInit } from '@angular/core';
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, UrlError } 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, config, from } from 'rxjs';
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';
@ -17,29 +14,21 @@ 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 { AggregateRunStat, RunStatService, UnformattedAggregateRunStat, UnformattedAggregationData } from '../_services/run-stat.service';
import { RunStatService, UnformattedAggregationData } from '../_services/run-stat.service';
@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;
rectAgg?: Rect;
bounds: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" };
boundsAgg: any = { "left": 0, "top": 0, "right": 0, "bottom": 0, "position": "css" };
@ViewChild("moveable") moveable?: NgxMoveableComponent;
@ViewChild("moveable2") moveable2?: NgxMoveableComponent;
export class PlanDisplayComponent implements OnInit {
@Input() backgroundColor?: string;
slideIndex: number = 0;
zoneSlides?: CarouselComponent<PlanElement>;
currentSlides?: CarouselComponent<PlanElement>;
worldAreaMap?: Map<String, WorldArea>;
settingsOpen: boolean = false;
init: boolean = false;
hasAttachedOnce: boolean = false;
overlayStateChangeHandle?: Subscription;
@ -70,12 +59,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
private zone: NgZone,
private runStatService: RunStatService,
) {
window.addEventListener("resize", () => {
this.zone.run(() => {
this.windowInitHandler()
})
});
this.planService.getStoredPlans().subscribe(plans => {
this.previousPlans = plans;
})
@ -105,6 +89,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.timeTrackerService.loadHistory(this.configService.config.runCompareHistory).subscribe(history => {
if (history) {
this.runStatService.insertTimesAtCheckpoints(history, plan);
this.aggregatedRunHistory = this.runStatService.calcAggregated(history)
}
});
}
@ -124,11 +109,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
});
}
windowInitHandler() {
if (window.innerWidth > 0) {
this.ngAfterViewInit();
}
}
ngOnInit() {
this.worldAreaService.getFullWorldAreas().subscribe(a => this.worldAreaMap = a);
@ -155,30 +135,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
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`;
}
transformAgg() {
return `translate(${this.rectAgg!.x}px, ${this.rectAgg!.y}px)`;
}
widthAgg() {
return `${this.rectAgg!.width}px`;
}
heightAgg() {
return `${this.rectAgg!.height}px`;
}
hasWaypoint(key?: string): boolean {
if (!key) {
key = this.currentPlan!.plan[this.currentPlan!.current].area_key;
@ -195,91 +151,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
return this.worldAreaService.hasTrial(key);
}
ngAfterViewInit(): void {
if (window.innerWidth > 0) {
const cfgRect = this.configService.config.initialPlanWindowPosition;
const cfgRectAgg = this.configService.config.initialAggWindowPosition;
this.rect = {
x: cfgRect.x * window.innerWidth,
y: cfgRect.y * window.innerHeight,
width: cfgRect.width * window.innerWidth,
height: cfgRect.height * window.innerHeight,
}
this.rectAgg = {
x: cfgRectAgg.x * window.innerWidth,
y: cfgRectAgg.y * window.innerHeight,
width: cfgRectAgg.width * window.innerWidth,
height: cfgRectAgg.height * window.innerHeight,
}
this.moveable?.updateRect();
this.moveable2?.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();
}
onDragAgg(e: OnDrag) {
this.rectAgg!.x = e.translate[0];
this.rectAgg!.y = e.translate[1];
}
onDragEndAgg(e: OnDragEnd) {
this.saveRectAgg();
}
onResizeAgg(e: OnResize) {
this.rectAgg!.width = e.width;
this.rectAgg!.height = e.height;
this.onDragAgg(e.drag);
}
onResizeEndAgg(e: OnResizeEnd) {
this.saveRectAgg();
}
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,
}
}
saveRectAgg() {
const toCfgRect = this.rectAgg!;
this.configService.config.initialAggWindowPosition = {
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);

@ -12,13 +12,14 @@ import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatListModule } from '@angular/material/list';
import { ScalableComponent } from '../Scalable/scalable.component';
import {MatTooltipModule} from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TooltipComponent } from '../tooltip/tooltip.component';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { MatDialogModule } from '@angular/material/dialog';
import { ResumeDialog } from './resume-dialog.component';
import { AggregateDisplayComponent } from '../aggregate-display/aggregate-display.component';
import { DraggableWindowComponent } from '../draggable-window/draggable-window.component';
@NgModule({
declarations: [
PlanDisplayComponent
@ -43,7 +44,8 @@ import { AggregateDisplayComponent } from '../aggregate-display/aggregate-displa
ScrollingModule,
MatDialogModule,
ResumeDialog,
AggregateDisplayComponent
AggregateDisplayComponent,
DraggableWindowComponent
],
exports: [

@ -66,6 +66,12 @@
[(ngModel)]="configService.config.shortenZoneNames"></mat-slide-toggle>
</div>
<div class="d-flex flex-row justify-content-between">
<span class="d-block">Detach zones</span>
<mat-slide-toggle [color]="overlayService.isOverlay ? 'primary-on-dark' : 'primary'"
[(ngModel)]="configService.config.detachNotes"></mat-slide-toggle>
</div>
<div class="d-flex flex-row justify-content-between">
<span class="d-block">Enable stopwatch</span>
<mat-slide-toggle [color]="overlayService.isOverlay ? 'primary-on-dark' : 'primary'"

Loading…
Cancel
Save