From 84695203ea124e1c190602b9da3ffd457b3d2dec Mon Sep 17 00:00:00 2001 From: isark Date: Sat, 23 Mar 2024 17:08:16 +0100 Subject: [PATCH] Reworked to reduce some unnecessary re-rendering but still laggy on linux!! --- src-tauri/tauri.conf.json | 2 +- src/app/_models/plan.ts | 8 +- src/app/editor/editor.component.html | 31 +++-- src/app/editor/editor.component.scss | 13 +- src/app/editor/editor.component.ts | 120 +++++++++++------- .../editor/notes/edit-notes.component.html | 26 ++-- .../editor/notes/edit-notes.component.scss | 24 ++++ src/app/editor/notes/notes.component.html | 2 +- src/app/editor/notes/notes.component.scss | 52 ++++---- src/app/editor/notes/notes.component.ts | 14 +- 10 files changed, 185 insertions(+), 107 deletions(-) create mode 100644 src/app/editor/notes/edit-notes.component.scss diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5557061..2a8da0e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Nothing", - "version": "1.8.4" + "version": "1.8.5" }, "tauri": { "systemTray": { diff --git a/src/app/_models/plan.ts b/src/app/_models/plan.ts index 48faef5..5ed3030 100644 --- a/src/app/_models/plan.ts +++ b/src/app/_models/plan.ts @@ -34,7 +34,13 @@ export class Plan { private selfSaveSubject: Subject = new Subject(); - constructor(plan: PlanInterface) { + constructor(plan?: PlanInterface) { + if(!plan) { + this.plan = []; + this.current = 0; + return; + }; + this.plan = plan.plan; this.current = plan.current; if (plan.stored_path) { diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 6ed09e4..02c510b 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -5,7 +5,7 @@ -
+
@@ -28,13 +28,13 @@
Area filter - +
Act filter - + {{item.name}} @@ -45,7 +45,8 @@ Auto scroll to latest - + Reverse display
@@ -56,26 +57,31 @@
-
+
-
+

Campaign zones

-
-
+
{{item.name}}
Act {{item.act}}
+
-
+

Plan

-
-
@@ -93,7 +99,8 @@
+
-
Place at end of list diff --git a/src/app/editor/editor.component.scss b/src/app/editor/editor.component.scss index 30d405f..96e041a 100644 --- a/src/app/editor/editor.component.scss +++ b/src/app/editor/editor.component.scss @@ -30,6 +30,11 @@ width: 100%; } +.grow { + flex-grow: 1; + +} + .box { position: relative; border-bottom: solid 1px map.get(palette.$nothing-dark-map, 50); @@ -44,9 +49,12 @@ padding: 20px 20px 20px 5px; width: 100%; overflow-x: hidden; + &:hover { background-color: rgba(0, 0, 0, 0.1); } + + height: 80px; } .buttons { @@ -70,8 +78,8 @@ width: 15px; height: 15px; overflow: visible; - - &:hover { + + &:hover { cursor: pointer; } } @@ -106,6 +114,7 @@ .list.cdk-drop-list-dragging .box:not(.cdk-drag-placeholder) { transition: transform 125ms cubic-bezier(0, 0, 0.2, 1); } + .right-settings { gap: 8px; } \ No newline at end of file diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index 7c35934..7f1b83c 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnChanges, OnInit, QueryList, SimpleChanges, ViewChild, ViewChildren } from '@angular/core'; import { CdkDrag, @@ -14,7 +14,7 @@ import { Plan, PlanElement } from '../_models/plan'; import { WorldAreaService } from '../_services/world-area.service'; import { FormsModule } from '@angular/forms'; import { Fuzzr } from '../fuzzr/fuzzr'; -import { from } from 'rxjs'; +import { BehaviorSubject, first, from, skip } from 'rxjs'; import { save } from '@tauri-apps/api/dialog'; import { PlanService } from '../_services/plan.service'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; @@ -47,12 +47,11 @@ interface Act { MatInputModule, MatSelectModule, MatButtonModule, - MatSlideToggleModule + MatSlideToggleModule, ], + providers: [] }) export class EditorComponent implements OnInit { - planInEditing: Plan; - areas?: WorldArea[]; planAreas: WorldArea[]; areasMap?: Map; @@ -62,22 +61,22 @@ export class EditorComponent implements OnInit { filterAct: Act; planFilterAct: Act; acts: Act[]; - @ViewChild('planList') planListElement!: ElementRef; + @ViewChild('planListElement') planListElement!: ElementRef; autoScrollToEnd: boolean; reverseDisplay: boolean; disabledPlanDD: boolean; + original: PlanElement[] = []; + latestList: BehaviorSubject = new BehaviorSubject([]); constructor(public worldAreaService: WorldAreaService, private cdr: ChangeDetectorRef, private planService: PlanService, public dialog: MatDialog) { - this.planInEditing = new Plan({ - plan: [], - current: 0 - }); this.disabledPlanDD = false; this.autoScrollToEnd = false; - this.planFuzzer = new Fuzzr(this.planInEditing.plan, { + this.latestList = new BehaviorSubject([]); + + this.planFuzzer = new Fuzzr(this.original, { toString: (e: PlanElement) => { return this.areasMap?.get(e.area_key)?.name; } @@ -100,6 +99,19 @@ export class EditorComponent implements OnInit { this.planFilterAct = this.acts[0]; } + planSearchStringChange(value: string) { + this.planSearchString = value; + this.filterPlanElements(); + } + planFilterActChange(value: Act) { + this.planFilterAct = value; + this.filterPlanElements(); + } + reverseDisplayChange(value: boolean) { + this.reverseDisplay = value; + this.filterPlanElements(); + } + ngOnInit(): void { this.worldAreaService.getWorldAreas().subscribe(worldAreas => { this.areas = [...worldAreas.values()]; @@ -113,32 +125,45 @@ export class EditorComponent implements OnInit { dropHandler(event: CdkDragDrop | CdkDragDrop) { if (event.previousContainer === event.container && !isWorldAreaEvent(event)) { - const realCurrent = this.planInEditing.plan.indexOf(event.previousContainer.data[event.currentIndex]); - const realPrev = this.planInEditing.plan.indexOf(event.previousContainer.data[event.previousIndex]); - moveItemInArray(this.planInEditing.plan, realPrev, realCurrent); - } else - if (this.planInEditing && this.areas && isWorldAreaEvent(event)) { + const realCurrent = this.original.indexOf(event.previousContainer.data[event.currentIndex]); + const realPrev = this.original.indexOf(event.previousContainer.data[event.previousIndex]); + moveItemInArray(this.original, realPrev, realCurrent); + } else { + if (this.areas && isWorldAreaEvent(event)) { if (event.container.data.length > 0 && 'connections_world_areas_keys' in event.container.data[0]) { return; } const bounds = this.planElemFilterBounds(); - let index = event.currentIndex; + let index = event.item.data; if (bounds) { index += bounds[0]; } - this.planInEditing.plan.splice(index, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex])); + this.original.splice(index, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex])); } + } + + this.latestList.pipe(skip(1)).pipe(first()).subscribe(() => { + this.scrollToEnd(); + }); + + this.filterPlanElements(); } - dropEndHandler(event: CdkDragDrop | CdkDragDrop) { + dropEndHandler(event: CdkDragDrop | CdkDragDrop | null) { + if (event == null) return; + if (isWorldAreaEvent(event) && this.areas) { - this.planInEditing.plan.splice(this.getEnd(), 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex])); + this.original.splice(this.getEnd(), 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex])); } else { - moveItemInArray(this.planInEditing.plan, event.previousIndex, this.getEnd()); + moveItemInArray(this.original, event.previousIndex, this.getEnd()); } - this.scrollToEnd(); + this.latestList.pipe(skip(1)).pipe(first()).subscribe(() => { + this.scrollToEnd(); + }); + + this.filterPlanElements(); } getEnd() { @@ -146,12 +171,14 @@ export class EditorComponent implements OnInit { if (bounds) { return bounds[1]; } else { - return this.planInEditing.plan.length; + return this.original.length; } } remove(item: PlanElement) { - this.planInEditing.plan.splice(this.planIndexOf(item), 1); + this.original.splice(this.planIndexOf(item), 1); + + this.filterPlanElements(); } canDrop = () => { @@ -181,28 +208,36 @@ export class EditorComponent implements OnInit { if (!this.autoScrollToEnd) { return; } + this.cdr.detectChanges(); + if (!this.reverseDisplay) { this.planListElement.nativeElement.scrollTop = this.planListElement.nativeElement.scrollHeight; } else { this.planListElement.nativeElement.scrollTop = 0; } + } doubleClickArea(item: WorldArea) { - this.planInEditing.plan.splice(this.planInEditing.plan.length, 0, this.planItemFromArea(item)); - this.scrollToEnd(); + this.original.splice(this.original.length, 0, this.planItemFromArea(item)); + + this.latestList.pipe(skip(1)).pipe(first()).subscribe((_) => { + this.scrollToEnd(); + }); + + this.filterPlanElements(); } planElemFilterBounds() { if (this.planFilterAct.value !== 0) { - let bounds = this.planInEditing.plan.filter(item => item.anchor_act === this.planFilterAct.value || this.planFilterAct.value + 1 === item.anchor_act).map((value) => this.planIndexOf(value)); + let bounds = this.original.filter(item => item.anchor_act === this.planFilterAct.value || this.planFilterAct.value + 1 === item.anchor_act).map((value) => this.planIndexOf(value)); if (bounds.length == 2) { return bounds; } if (bounds.length == 1 && this.planFilterAct.value == 10) { - bounds[1] = this.planInEditing.plan.length; + bounds[1] = this.original.length; return bounds; } } @@ -218,7 +253,6 @@ export class EditorComponent implements OnInit { this.disabledPlanDD = false; } - if (this.planSearchString !== "" || this.planFilterAct.value != 0) { let bounds = this.planElemFilterBounds(); @@ -237,24 +271,22 @@ export class EditorComponent implements OnInit { } } else { - return this.planInEditing.plan; + return this.original; } } - if (this.reverseDisplay) { - return value().slice().reverse(); - } else { - return value(); - } + this.latestList.next([... (this.reverseDisplay ? value().slice().reverse() : value())]); } planIndexOf(planElement: PlanElement) { - const index = this.planInEditing.plan.indexOf(planElement); - return index; + return this.original.indexOf(planElement); } clearPlan() { - this.planInEditing.plan.length = 0; + while (this.original.length > 0) { + this.original.pop(); + } + this.filterPlanElements(); this.cdr.detectChanges(); } @@ -266,7 +298,9 @@ export class EditorComponent implements OnInit { }] })).subscribe(file => { if (file) { - this.planService.savePlanAtPath(file, this.planInEditing).subscribe(); + const plan = new Plan(); + plan.plan = [...this.original]; + this.planService.savePlanAtPath(file, plan).subscribe(); } }); } @@ -284,8 +318,8 @@ export class EditorComponent implements OnInit { if (file) { // We disallow multiple but interface still says it can be multiple, thus the cast. this.planService.loadPlanFromPath(file as string, false).subscribe(plan => { - this.planInEditing.plan.length = 0; - plan.plan.forEach(p => this.planInEditing.plan.push(p)); + plan.plan.forEach(item => this.original.push(item)); + this.filterPlanElements(); }); } }); @@ -293,8 +327,8 @@ export class EditorComponent implements OnInit { loadBasePlan() { this.planService.getBasePlan().subscribe(plan => { - this.planInEditing.plan.length = 0; - plan.plan.forEach(p => this.planInEditing.plan.push(p)); + plan.plan.forEach(item => this.original.push(item)); + this.filterPlanElements(); }) } diff --git a/src/app/editor/notes/edit-notes.component.html b/src/app/editor/notes/edit-notes.component.html index 11dd70d..9f746e4 100644 --- a/src/app/editor/notes/edit-notes.component.html +++ b/src/app/editor/notes/edit-notes.component.html @@ -1,17 +1,15 @@ -
-
- Edit note (supports markdown) -
- -
- - Preview (Unscaled) -
- -
+
+ Edit note (supports markdown) +
+
-
- - + + Preview (Unscaled) +
+
+
+
+ +
\ No newline at end of file diff --git a/src/app/editor/notes/edit-notes.component.scss b/src/app/editor/notes/edit-notes.component.scss new file mode 100644 index 0000000..303a938 --- /dev/null +++ b/src/app/editor/notes/edit-notes.component.scss @@ -0,0 +1,24 @@ +.container { + display: flex; + flex-direction: column; + height: 700px; + width: 500px; + align-items: center; +} + +img { + display: block; + width: 100%; + height: 100%; + max-height: 100%; + object-fit: contain; +} + +.display-component { + max-height: 100%; + height: 100%; + display: grid; + grid-auto-flow: row; + grid-template-rows: repeat(auto-fit, minmax(50px, 1fr)); + width: 100%; +} \ No newline at end of file diff --git a/src/app/editor/notes/notes.component.html b/src/app/editor/notes/notes.component.html index 4fd42f4..a81a089 100644 --- a/src/app/editor/notes/notes.component.html +++ b/src/app/editor/notes/notes.component.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/src/app/editor/notes/notes.component.scss b/src/app/editor/notes/notes.component.scss index 4f4d42b..41b53b9 100644 --- a/src/app/editor/notes/notes.component.scss +++ b/src/app/editor/notes/notes.component.scss @@ -1,30 +1,30 @@ -.NOTES_COMPONENT { - .container { - display: flex; - flex-direction: column; - } - - img { - display: block; - width: 100%; - height: 100%; - max-height: 100%; - object-fit: contain; - } +.container { + display: flex; + flex-direction: column; + height: 800px; + width: 1200px; +} - &.display-component { - max-height: 100%; - height: 100%; - display: grid; - grid-auto-flow: row; - grid-template-rows: repeat(auto-fit, minmax(50px, 1fr)); - } +img { + display: block; + width: 100%; + height: 100%; + max-height: 100%; + object-fit: contain; +} - & { - font-size: 1.3em; - } +.display-component { + max-height: 100%; + height: 100%; + display: grid; + grid-auto-flow: row; + grid-template-rows: repeat(auto-fit, minmax(50px, 1fr)); + font-size: 1.3em; +} - .note-preview { - min-height: 400px; - } +.note-preview { + min-height: 400px; + max-height: 400px; + min-width: 600px; + max-width: 600px; } diff --git a/src/app/editor/notes/notes.component.ts b/src/app/editor/notes/notes.component.ts index 3a441ad..4052c2b 100644 --- a/src/app/editor/notes/notes.component.ts +++ b/src/app/editor/notes/notes.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, Inject, Input, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Component, ElementRef, Inject, Input, ViewChild, } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { CommonModule } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; @@ -19,26 +19,25 @@ interface DialogData { styleUrls: ['./notes.component.scss'], standalone: true, imports: [CommonModule, FormsModule, MatButtonModule], - encapsulation: ViewEncapsulation.None, }) -export class NotesComponent implements AfterViewInit { +export class NotesComponent { @Input() note?: string; @ViewChild("ref") ref?: ElementRef - constructor(public md: MarkdownService) {} - ngAfterViewInit(): void { - } + realValue: any; + + constructor(public md: MarkdownService) {} } @Component({ selector: 'notes-editor', templateUrl: 'edit-notes.component.html', + styleUrls: ['./edit-notes.component.scss'], standalone: true, imports: [CommonModule, FormsModule, MatDialogModule, MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, NotesComponent, ScalableComponent], - encapsulation: ViewEncapsulation.None, }) export class EditNotesComponentDialog { note?: string; @@ -46,6 +45,7 @@ export class EditNotesComponentDialog { constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: DialogData, + public md: MarkdownService ) { if (data.note) { this.note = `${data.note}`;