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

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

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

@ -1,15 +1,12 @@
import { AfterViewInit, ChangeDetectorRef, Component, Input, NgZone, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, Input, NgZone, OnInit } from '@angular/core';
import { NgxMoveableComponent, OnDragEnd, OnResize, OnResizeEnd } from 'ngx-moveable';
import { OnDrag } from 'ngx-moveable';
import { ConfigService } from '../_services/config.service'; import { ConfigService } from '../_services/config.service';
import { Rect } from '../_models/generated/Rect';
import { ShortcutService } from '../_services/shortcut.service'; import { ShortcutService } from '../_services/shortcut.service';
import { CarouselComponent } from '../carousel/carousel.component'; import { CarouselComponent } from '../carousel/carousel.component';
import { PlanService, UrlError } from '../_services/plan.service'; import { PlanService, UrlError } from '../_services/plan.service';
import { Plan, PlanElement, PlanMetadata } from '../_models/plan'; import { Plan, PlanElement, PlanMetadata } from '../_models/plan';
import { WorldAreaService } from '../_services/world-area.service'; import { WorldAreaService } from '../_services/world-area.service';
import { WorldArea } from '../_models/world-area'; 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 { open } from '@tauri-apps/api/dialog';
import { OverlayService, StateEvent } from '../_services/overlay.service'; import { OverlayService, StateEvent } from '../_services/overlay.service';
import { appWindow } from '@tauri-apps/api/window'; 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 { Event } from '@tauri-apps/api/event';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { TimeTrackerService } from '../_services/time-tracker.service'; 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({ @Component({
selector: 'plan-display', selector: 'plan-display',
templateUrl: './plan-display.component.html', templateUrl: './plan-display.component.html',
styleUrls: ['./plan-display.component.scss'] styleUrls: ['./plan-display.component.scss']
}) })
export class PlanDisplayComponent implements AfterViewInit, OnInit { export class PlanDisplayComponent implements OnInit {
@Input() backgroundColor?: String; @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;
slideIndex: number = 0; slideIndex: number = 0;
zoneSlides?: CarouselComponent<PlanElement>; zoneSlides?: CarouselComponent<PlanElement>;
currentSlides?: CarouselComponent<PlanElement>; currentSlides?: CarouselComponent<PlanElement>;
worldAreaMap?: Map<String, WorldArea>; worldAreaMap?: Map<String, WorldArea>;
settingsOpen: boolean = false; settingsOpen: boolean = false;
init: boolean = false;
hasAttachedOnce: boolean = false; hasAttachedOnce: boolean = false;
overlayStateChangeHandle?: Subscription; overlayStateChangeHandle?: Subscription;
@ -70,12 +59,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
private zone: NgZone, private zone: NgZone,
private runStatService: RunStatService, private runStatService: RunStatService,
) { ) {
window.addEventListener("resize", () => {
this.zone.run(() => {
this.windowInitHandler()
})
});
this.planService.getStoredPlans().subscribe(plans => { this.planService.getStoredPlans().subscribe(plans => {
this.previousPlans = plans; this.previousPlans = plans;
}) })
@ -105,6 +89,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
this.timeTrackerService.loadHistory(this.configService.config.runCompareHistory).subscribe(history => { this.timeTrackerService.loadHistory(this.configService.config.runCompareHistory).subscribe(history => {
if (history) { if (history) {
this.runStatService.insertTimesAtCheckpoints(history, plan); 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() { ngOnInit() {
this.worldAreaService.getFullWorldAreas().subscribe(a => this.worldAreaMap = a); this.worldAreaService.getFullWorldAreas().subscribe(a => this.worldAreaMap = a);
@ -155,30 +135,6 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
return Math.abs(v); 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 { hasWaypoint(key?: string): boolean {
if (!key) { if (!key) {
key = this.currentPlan!.plan[this.currentPlan!.current].area_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); 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>) { registerZoneSlides(carousel: CarouselComponent<PlanElement>) {
this.zoneSlides = carousel; this.zoneSlides = carousel;
this.zoneSlides.setIndex(this.slideIndex); this.zoneSlides.setIndex(this.slideIndex);

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

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

Loading…
Cancel
Save