diff --git a/package.json b/package.json index 090f1cb..bf4d69a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "@angular/platform-browser": "^16.1.4", "@angular/platform-browser-dynamic": "^16.1.4", "@tauri-apps/api": "^1.2.0", + "@types/natural-compare": "^1.4.1", "fuzzr": "github:isark2/fuzzr#v0.3.1", + "natural-compare": "^1.4.0", "ngx-moveable": "^0.48.1", "rxjs": "~7.8.1", "tslib": "^2.6.0", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 4ec0f5e..f97538b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -93,9 +93,9 @@ fn main() { app.manage(tx); app.manage(Mutex::new(Storage::default())); - // app.get_window("Overlay") - // .expect("Could not get main overlay window") - // .open_devtools(); + app.get_window("Overlay") + .expect("Could not get main overlay window") + .open_devtools(); Ok(()) }) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 56f7d31..ec4e1dc 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,6 +10,7 @@ import { ConfigService } from "./services/config.service"; import { ColorPickerComponent } from './color-picker/color-picker.component'; import { MatButtonModule } from "@angular/material/button"; import { EditorComponent } from "./editor/editor.component"; +import { initFuzzr } from "./fuzzr/fuzzr"; export function initializeApp(configService: ConfigService) { return (): Promise => { diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index 0f6b7d4..f7e32bd 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -1,6 +1,7 @@
-
-

available items

+
+ +

Campaign zones

-
Name: {{item.name}}
in act {{item.act}}
+
+ Name: {{item.name}}
in act {{item.act}} +
- +
-

Shopping basket

+ +

Plan

-
{{item.area_key}}
+
+
{{areasMap?.get(item.area_key)?.name}}
+
#{{index}}
+
diff --git a/src/app/editor/editor.component.scss b/src/app/editor/editor.component.scss index 575dd73..7388d2b 100644 --- a/src/app/editor/editor.component.scss +++ b/src/app/editor/editor.component.scss @@ -1,68 +1,68 @@ :host { - height: 100%; + height: 100%; } .container { - width: 400px; - max-width: 100%; - margin: 0 25px 25px 0; - display: inline-block; - vertical-align: top; - flex-grow: 1 1 auto; - } - - .list { - border: solid 1px #ccc; - min-height: 60px; - background: white; - border-radius: 4px; - display: block; - padding-bottom: 50px; - overflow: auto; - max-height: 100%; - } - - .box { - padding: 20px 10px; - border-bottom: solid 1px #ccc; - color: rgba(0, 0, 0, 0.87); - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - box-sizing: border-box; - cursor: move; - background: white; - font-size: 14px; - } - - .cdk-drag-preview { - box-sizing: border-box; - border-radius: 4px; - box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), - 0 8px 10px 1px rgba(0, 0, 0, 0.14), - 0 3px 14px 2px rgba(0, 0, 0, 0.12); - } - - .cdk-drag-placeholder { - opacity: 0; - } - - .cdk-drag-animating { - transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); - } - - .box:last-child { - border: none; - } - - .list.cdk-drop-list-dragging .box:not(.cdk-drag-placeholder) { - transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); - } - + width: 400px; + max-width: 100%; + margin: 0 25px 25px 0; + display: inline-block; + vertical-align: top; + flex-grow: 1 1 auto; +} + +.list { + border: solid 1px #ccc; + min-height: 60px; + background: white; + border-radius: 4px; + display: block; + padding-bottom: 50px; + overflow: auto; + max-height: 100%; +} + +.box { + padding: 10px 5px; + border-bottom: solid 1px #ccc; + color: rgba(0, 0, 0, 0.87); + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + box-sizing: border-box; + cursor: move; + background: white; + font-size: 14px; +} + +.cdk-drag-preview { + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); +} + +.cdk-drag-placeholder { + opacity: 0; +} + +.cdk-drag-animating { + transition: transform 75ms cubic-bezier(0, 0, 0.2, 1); +} + +.box:last-child { + border: none; +} + +.list.cdk-drop-list-dragging .box:not(.cdk-drag-placeholder) { + transition: transform 125ms cubic-bezier(0, 0, 0.2, 1); +} + .editor-container { - display: flex; - flex-direction: row; - height: 100%; + display: flex; + flex-direction: row; + height: 100%; } \ No newline at end of file diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts index 62c30f6..4bce600 100644 --- a/src/app/editor/editor.component.ts +++ b/src/app/editor/editor.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { CdkDrag, @@ -6,13 +6,14 @@ import { CdkDropList, CdkDropListGroup, moveItemInArray, - transferArrayItem, } from '@angular/cdk/drag-drop'; import { CommonModule } from '@angular/common'; import { WorldArea } from '../models/world-area'; import { Plan, PlanElement } from '../models/plan'; import { WorldAreaService } from '../services/world-area.service'; +import { FormsModule } from '@angular/forms'; +import { Fuzzr } from '../fuzzr/fuzzr'; @Component({ selector: 'plan-editor', @@ -21,6 +22,7 @@ import { WorldAreaService } from '../services/world-area.service'; standalone: true, imports: [ CommonModule, + FormsModule, CdkDropListGroup, CdkDropList, CdkDrag @@ -30,6 +32,10 @@ export class EditorComponent implements OnInit { areas?: WorldArea[]; planAreas: WorldArea[]; plan: Plan; + areasMap?: Map; + areaSearchString: string = ""; + planSearchString: string = ""; + planFuzzer: Fuzzr; constructor(public worldAreaService: WorldAreaService) { this.plan = { @@ -37,13 +43,19 @@ export class EditorComponent implements OnInit { current: 0, } + this.planFuzzer = new Fuzzr(this.plan.plan, { + toString: (e: PlanElement) => { + return this.areasMap?.get(e.area_key)?.name; + } + }); + this.planAreas = []; } ngOnInit(): void { this.worldAreaService.getWorldAreas().subscribe(worldAreas => { this.areas = [...worldAreas.values()]; - console.log(this.areas); + this.areasMap = worldAreas; }); } @@ -62,4 +74,23 @@ export class EditorComponent implements OnInit { notes: undefined, }; } + + filterAreas(searchString: string) { + if (searchString !== "") { + + return this.worldAreaService.matcher?.search(searchString).map(({ item }) => { + return item[1]; + }); + } else { + return this.areas; + } + } + + filterPlanElements(searchString: string) { + if (searchString !== "") { + return this.planFuzzer.search(searchString).map(({item}) => item); + } else { + return this.plan.plan; + } + } } diff --git a/src/app/fuzzr/fuzzr.ts b/src/app/fuzzr/fuzzr.ts new file mode 100644 index 0000000..54e0c42 --- /dev/null +++ b/src/app/fuzzr/fuzzr.ts @@ -0,0 +1,8 @@ +import init, { Fuzzr } from 'fuzzr/pkg'; + + +export function initFuzzr() { + return init("/fuzzr/pkg/fuzzr_bg.wasm") +} + +export { Fuzzr }; \ No newline at end of file diff --git a/src/app/models/plan.ts b/src/app/models/plan.ts index 78f7373..4775501 100644 --- a/src/app/models/plan.ts +++ b/src/app/models/plan.ts @@ -8,4 +8,5 @@ export interface Plan { export interface PlanElement { area_key: string; notes?: string; + index?: number; } \ No newline at end of file diff --git a/src/app/services/world-area.service.ts b/src/app/services/world-area.service.ts index 2c6358b..070de32 100644 --- a/src/app/services/world-area.service.ts +++ b/src/app/services/world-area.service.ts @@ -1,30 +1,27 @@ import { Injectable, NgZone } from '@angular/core'; -import init, { Fuzzr } from 'fuzzr/pkg'; import { WorldArea } from '../models/world-area'; import { invoke } from '@tauri-apps/api'; import { Observable, ReplaySubject, Subject, filter, from, map } from 'rxjs'; - +import naturalCompare from 'natural-compare'; +import { Fuzzr } from '../fuzzr/fuzzr'; @Injectable({ providedIn: 'root' }) export class WorldAreaService { private worldAreas?: Map; - private matcher?: Fuzzr; + public matcher?: Fuzzr; private worldAreasSubject = new ReplaySubject>(); - private matcherSubject = new ReplaySubject(); constructor(private zone: NgZone) { from(invoke>('load_world_areas')).subscribe((data) => { - this.worldAreas = new Map(Object.entries(data)); - console.log("pre next worldareas"); + const entries = Object.entries(data).sort((a, b) => naturalCompare(a[1].named_id, b[1].named_id)); + this.worldAreas = new Map(entries); this.zone.run(() => this.worldAreasSubject.next(this.worldAreas!)); - console.log("post next worldareas"); - from(init("/fuzzr/pkg/fuzzr_bg.wasm")).subscribe(() => { - this.matcher = new Fuzzr(this.worldAreas); - this.zone.run(() => this.matcherSubject.next(this.matcher!)); - }); + this.matcher = new Fuzzr(this.worldAreas, { + toString: (e: [string, WorldArea]) => e[1].name + }) }); } @@ -32,11 +29,5 @@ export class WorldAreaService { return this.worldAreasSubject.asObservable().pipe( filter(worldAreas => !!worldAreas), ); - } - - getMatcher(): Observable { - return this.matcherSubject.asObservable().pipe( - filter(matcher => !!matcher), - ); - } + } } diff --git a/src/main.ts b/src/main.ts index c8de310..95bd95b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,10 @@ import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; import { AppModule } from "./app/app.module"; +import { initFuzzr } from "./app/fuzzr/fuzzr"; + +initFuzzr().then(() => { + platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); +}); -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch((err) => console.error(err)); diff --git a/tsconfig.json b/tsconfig.json index 1301bf2..6d1515d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,8 @@ "target": "ES2022", "module": "ES2022", "useDefineForClassFields": false, - "lib": ["ES2022", "dom"] + "lib": ["ES2022", "dom"], + "esModuleInterop": true }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, diff --git a/yarn.lock b/yarn.lock index 1980769..b4a736f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2555,6 +2555,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/natural-compare@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@types/natural-compare/-/natural-compare-1.4.1.tgz#fc2b11ea100d380b0de7af15768bef209157bfb9" + integrity sha512-9dr4UakpvN0QUvwNefk9+o14Sr1pPPIDWkgCxPkHcg3kyjtc9eKK1ng6dZ23vRwByloCqXYtZ1T5nJxkk3Ib3A== + "@types/node@*", "@types/node@>=10.0.0": version "20.4.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" @@ -5339,6 +5344,11 @@ nanoid@^3.3.6: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + needle@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/needle/-/needle-3.2.0.tgz#07d240ebcabfd65c76c03afae7f6defe6469df44"