Initial first version post cleanup, need to test it out

cleanup
isark 1 year ago
parent 6282f12ce9
commit a1249b46ab

@ -72,9 +72,12 @@ fn enumerate_stored_plans() -> Vec<PlanMetadata> {
Storage::enumerate_plans() Storage::enumerate_plans()
} }
#[tauri::command] #[tauri::command]
fn load_plan_at_path(path: PathBuf, state: tauri::State<Mutex<Storage>>) -> Option<Plan> { fn load_plan_at_path(
path: PathBuf,
save_local: Option<bool>,
state: tauri::State<Mutex<Storage>>,
) -> Option<Plan> {
if !path.exists() { if !path.exists() {
return None; return None;
} }
@ -84,8 +87,10 @@ fn load_plan_at_path(path: PathBuf, state: tauri::State<Mutex<Storage>>) -> Opti
Err(_) => return None, Err(_) => return None,
}; };
let save_local = save_local.unwrap_or(true);
storage.last_plan = Some(path.clone()); storage.last_plan = Some(path.clone());
Storage::load_plan_at_path(path) Storage::load_plan_at_path(path, save_local)
} }
#[tauri::command] #[tauri::command]

@ -12,29 +12,29 @@ pub struct Plan {
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct PlanMetadata { pub struct PlanMetadata {
#[serde(skip)]
stored_path: Option<PathBuf>, stored_path: Option<PathBuf>,
update_url: Option<String>, update_url: Option<String>,
} }
impl From<PlanMetadata> for Option<Plan> { impl PlanMetadata {
fn from(metadata: PlanMetadata) -> Self { pub fn set_stored_path(&mut self, file: Option<PathBuf>) {
Some(serde_json::from_slice(&std::fs::read(metadata.stored_path?).ok()?).ok()?) self.stored_path = file;
} }
} }
impl Serialize for PlanMetadata { impl Serialize for PlanMetadata {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: serde::Serializer, S: serde::Serializer,
{ {
let mut state = serializer.serialize_struct("PlanMetadata", 2)?; let mut state = serializer.serialize_struct("PlanMetadata", 3)?;
state.serialize_field("update_url", &self.update_url)?; state.serialize_field("update_url", &self.update_url)?;
state.serialize_field("stored_path", &self.stored_path)?;
if let Some(path) = &self.stored_path { if let Some(path) = &self.stored_path {
if let Some(name) = path.file_name() { if let Some(name) = path.file_name() {
state.serialize_field("name", name)?; state.serialize_field("name", &name.to_str())?;
} }
} }
@ -42,9 +42,15 @@ impl Serialize for PlanMetadata {
} }
} }
impl From<PlanMetadata> for Option<Plan> {
fn from(metadata: PlanMetadata) -> Self {
Some(serde_json::from_slice(&std::fs::read(metadata.stored_path?).ok()?).ok()?)
}
}
impl Plan { impl Plan {
pub fn set_stored_path(&mut self, file: PathBuf) { pub fn set_stored_path(&mut self, file: Option<PathBuf>) {
self.metadata.stored_path = Some(file); self.metadata.stored_path = file;
} }
} }

@ -82,24 +82,26 @@ impl Storage {
Ok(()) Ok(())
} }
pub fn load_plan_at_path(path: PathBuf) -> Option<Plan> { pub fn load_plan_at_path(path: PathBuf, save_local: bool) -> Option<Plan> {
log::trace!("Loading plan: {path:?}"); log::trace!("Loading plan: {path:?}");
let plan: Plan = match serde_json::from_str(&std::fs::read_to_string(&path).ok()?).ok() { let plan: Plan = match serde_json::from_str(&std::fs::read_to_string(&path).ok()?).ok() {
Some(plan) => plan, Some(plan) => plan,
None => convert_old(path.clone())?, None => convert_old(path.clone())?,
}; };
match Self::save_plan_at_store_path(path.file_name()?.to_str()?, plan.clone()) { if save_local {
Ok(_) => (), match Self::save_plan_at_store_path(path.file_name()?.to_str()?, plan.clone()) {
Err(_e) => { Ok(_) => (),
log::error!("Could not save plan at store path during load"); Err(_e) => {
}, log::error!("Could not save plan at store path during load");
}
}
} }
Some(plan) Some(plan)
} }
pub fn save_plan_at_store_path(file_name: &str, mut plan: Plan) -> Result<(), Box<dyn Error>> { pub fn save_plan_at_store_path(file_name: &str, plan: Plan) -> Result<(), Box<dyn Error>> {
let plan_dir = match Self::plan_dir() { let plan_dir = match Self::plan_dir() {
Some(dir) => dir, Some(dir) => dir,
None => return Err("No plan dir".into()), None => return Err("No plan dir".into()),
@ -112,7 +114,8 @@ impl Storage {
return Err("File already exists".into()); return Err("File already exists".into());
} }
plan.set_stored_path(file_path.clone()); //TODO: Determine necessity
// plan.set_stored_path(file_path.clone());
std::fs::write(file_path, serde_json::to_string(&plan)?)?; std::fs::write(file_path, serde_json::to_string(&plan)?)?;
@ -162,6 +165,9 @@ impl Storage {
} }
fn load_metadata_at_path(path: PathBuf) -> Option<PlanMetadata> { fn load_metadata_at_path(path: PathBuf) -> Option<PlanMetadata> {
serde_json::from_str(&std::fs::read_to_string(&path).ok()?).ok() let mut plan: PlanMetadata =
serde_json::from_str(&std::fs::read_to_string(&path).ok()?).ok()?;
plan.set_stored_path(Some(path));
Some(plan)
} }
} }

@ -10,7 +10,9 @@ export interface PlanInterface {
} }
export interface PlanMetadata { export interface PlanMetadata {
stored_path?: string;
update_url?: string;
name: string;
} }
export class Plan { export class Plan {
@ -56,7 +58,6 @@ export class Plan {
} }
private directSelfSave() { private directSelfSave() {
console.log("Underlying save");
invoke('save_plan', { invoke('save_plan', {
plan: { plan: {
plan: this.plan, plan: this.plan,

@ -65,7 +65,7 @@ export class ConfigService {
} }
private underlyingSync() { private underlyingSync() {
invoke('set_config', { config: this.config }); invoke('update_config', { config: this.config });
} }
} }

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { invoke } from '@tauri-apps/api'; import { invoke } from '@tauri-apps/api';
import { Observable, ReplaySubject, Subject, from, map, switchMap, tap } from 'rxjs'; import { Observable, ReplaySubject, Subject, from, map, switchMap, tap } from 'rxjs';
import { Plan, PlanInterface } from '../_models/plan'; import { Plan, PlanInterface, PlanMetadata } from '../_models/plan';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { UrlDialog } from '../plan-display/url-dialog.component'; import { UrlDialog } from '../plan-display/url-dialog.component';
import { fetch } from '@tauri-apps/api/http'; import { fetch } from '@tauri-apps/api/http';
@ -30,16 +30,12 @@ export class PlanService {
this._currentPlanSubject.next(plan); this._currentPlanSubject.next(plan);
} }
public enumerateStoredPlans(): Observable<string[]> { public enumerateStoredPlans(): Observable<PlanMetadata[]> {
return from(invoke<string[]>('enumerate_stored_plans')); return from(invoke<PlanMetadata[]>('enumerate_stored_plans'));
} }
public getPathFromKnownName(name: string): Observable<string> { public loadPlanFromPath(path: string, save_local: boolean = true): Observable<Plan> {
return from(invoke<string>('path_from_name', { name })); return from(invoke<PlanInterface>('load_plan_at_path', { path, save_local })).pipe(map(plan => {return new Plan(plan)}));
}
public loadPlanFromPath(path: string): Observable<Plan> {
return from(invoke<Plan>('load_plan_at_path', { path }));
} }
public loadFromUrl(url?: string, name?: string): Observable<Plan> { public loadFromUrl(url?: string, name?: string): Observable<Plan> {
@ -65,7 +61,7 @@ export class PlanService {
} }
public savePlanAtPath(path: string, plan: Plan) { public savePlanAtPath(path: string, plan: Plan) {
invoke('save_plan_at_path', { path, plan: plan }); return from(invoke('save_plan_at_path', { path, plan: plan }));
} }
private _loadFromUrl(url: string, name: string): Observable<Plan> { private _loadFromUrl(url: string, name: string): Observable<Plan> {

@ -86,7 +86,7 @@
<div class="delete" (click)="remove(item)">+</div> <div class="delete" (click)="remove(item)">+</div>
</div> </div>
</div> </div>
<div cdkDropList [cdkDropListData]="plan.plan" class="list end" <div cdkDropList [cdkDropListData]="planInEditing.plan" class="list end"
style="position: relative;display: flex; flex-direction: column; justify-content: center;" style="position: relative;display: flex; flex-direction: column; justify-content: center;"
(cdkDropListDropped)="dropEndHandler($event)"> (cdkDropListDropped)="dropEndHandler($event)">
<span style="position: absolute; ">Place at end of list</span> <span style="position: absolute; ">Place at end of list</span>

@ -124,7 +124,7 @@ export class EditorComponent implements OnInit {
const bounds = this.planElemFilterBounds(); const bounds = this.planElemFilterBounds();
let index = event.currentIndex; let index = event.currentIndex;
if(bounds) { if (bounds) {
index += bounds[0]; index += bounds[0];
} }
this.planInEditing.plan.splice(index, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex])); this.planInEditing.plan.splice(index, 0, this.planItemFromArea(event.previousContainer.data[event.previousIndex]));
@ -195,15 +195,13 @@ export class EditorComponent implements OnInit {
} }
planElemFilterBounds() { planElemFilterBounds() {
if(this.planFilterAct.value !== 0) { 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.planInEditing.plan.filter(item => item.anchor_act === this.planFilterAct.value || this.planFilterAct.value + 1 === item.anchor_act).map((value) => this.planIndexOf(value));
console.log("bounds, ", bounds);
if (bounds.length == 2) { if (bounds.length == 2) {
return bounds; return bounds;
} }
if(bounds.length == 1 && this.planFilterAct.value == 10) { if (bounds.length == 1 && this.planFilterAct.value == 10) {
console.log("Setting bound to last index");
bounds[1] = this.planInEditing.plan.length; bounds[1] = this.planInEditing.plan.length;
return bounds; return bounds;
} }
@ -268,7 +266,7 @@ export class EditorComponent implements OnInit {
}] }]
})).subscribe(file => { })).subscribe(file => {
if (file) { if (file) {
this.planService.savePlan(file as string, this.planInEditing); this.planService.savePlanAtPath(file, this.planInEditing).subscribe();
} }
}); });
} }
@ -284,7 +282,8 @@ export class EditorComponent implements OnInit {
] ]
})).subscribe(file => { })).subscribe(file => {
if (file) { if (file) {
this.planService.loadPlanNoSave(file as string).subscribe(plan => { // 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; this.planInEditing.plan.length = 0;
plan.plan.forEach(p => this.planInEditing.plan.push(p)); plan.plan.forEach(p => this.planInEditing.plan.push(p));
}); });
@ -293,7 +292,7 @@ export class EditorComponent implements OnInit {
} }
loadBasePlan() { loadBasePlan() {
this.planService.loadBasePlan().subscribe(plan => { this.planService.getBasePlan().subscribe(plan => {
this.planInEditing.plan.length = 0; this.planInEditing.plan.length = 0;
plan.plan.forEach(p => this.planInEditing.plan.push(p)); plan.plan.forEach(p => this.planInEditing.plan.push(p));
}) })

@ -1,4 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Rect } from "./Rect";
export interface Config { initialPlanWindowPosition: Rect, hideOnUnfocus: boolean, toggleOverlay: string, prev: string, next: string, planBg: string, backdropBg: string, noteDefaultFg: string, poeClientLogPath: string | null, }

@ -1,3 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export interface Rect { x: number, y: number, width: number, height: number, }

@ -1,18 +1,18 @@
<ng-container *ngIf="init"> <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>
<ng-container *ngIf="rect && planService.currentPlan"> <ng-container *ngIf="rect && currentPlan">
<div class="target waypoint trial" <div class="target waypoint trial"
[style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'" [style.background-color]="backgroundColor ? backgroundColor : 'rgba(0, 0, 0, 0.1)'"
[style.transform]="transform()" [style.width]="rect.width + 'px'" [style.height]="rect.height + 'px'" [style.transform]="transform()" [style.width]="rect.width + 'px'" [style.height]="rect.height + 'px'"
[class]="specialClasses()" (wheel)="onScroll($event)" #targetRef> [class]="specialClasses()" (wheel)="onScroll($event)" #targetRef>
<ng-container *ngIf="planService.currentPlan"> <ng-container *ngIf="currentPlan">
<carousel class="zones" [initIndex]="planService.currentPlan.current" <carousel class="zones" [initIndex]="currentPlan.current"
[numVisible]="configService.config.numVisible" [offset]="clampedOffset()" [numVisible]="configService.config.numVisible" [offset]="clampedOffset()"
[slides]="planService.currentPlan.plan" (afterInitSelf)="registerZoneSlides($event)" [slides]="currentPlan.plan" (afterInitSelf)="registerZoneSlides($event)"
[ngStyle]="zonesStyle()"> [ngStyle]="zonesStyle()">
<ng-template let-slide let-index="index"> <ng-template let-slide let-index="index">
<div class="zone-slide" [style.color]="configService.config.noteDefaultFg" <div class="zone-slide" [style.color]="configService.config.noteDefaultFg"
[style.border]="index == planService.currentPlan.current ? '1px white solid' : 'none'"> [style.border]="index == currentPlan.current ? '1px white solid' : 'none'">
{{worldAreaMap!.get(slide.area_key)!.name}} {{worldAreaMap!.get(slide.area_key)!.name}}
@ -23,7 +23,7 @@
</div> </div>
</ng-template> </ng-template>
</carousel> </carousel>
<carousel [initIndex]="planService.currentPlan.current" [slides]="planService.currentPlan.plan" <carousel [initIndex]="currentPlan.current" [slides]="currentPlan.plan"
(afterInitSelf)="registerCurrentSlides($event)"> (afterInitSelf)="registerCurrentSlides($event)">
<ng-template let-slide> <ng-template let-slide>
<scalable [clamp]="2"> <scalable [clamp]="2">
@ -57,7 +57,7 @@
</ng-container> </ng-container>
<ng-template cdkConnectedOverlay <ng-template cdkConnectedOverlay
[cdkConnectedOverlayOpen]="(settingsOpen || !planService.currentPlan) && overlayService.interactable" [cdkConnectedOverlayOpen]="(settingsOpen || !currentPlan) && overlayService.interactable"
[cdkConnectedOverlayOrigin]="globalTopLeft" (detach)="settingsOpen = false"> [cdkConnectedOverlayOrigin]="globalTopLeft" (detach)="settingsOpen = false">
<div class="overlay container-fluid vw-100"> <div class="overlay container-fluid vw-100">
<div class="row row-cols-2"> <div class="row row-cols-2">
@ -82,9 +82,9 @@
<div class="enumerated"> <div class="enumerated">
<mat-list role="list"> <mat-list role="list">
<mat-list-item class="d-flex flex-column" role="listitem" <mat-list-item class="d-flex flex-column" role="listitem"
*ngFor="let plan of planService.planStore | keyvalue"> *ngFor="let plan of previousPlans">
<button (click)="setPrevious(plan.key)"> <button (click)="loadPrevious(plan.stored_path!)">
<img *ngIf="plan.value.update_url" src="assets/public.svg">{{plan.key}} <img *ngIf="plan.update_url" src="assets/public.svg">{{plan.name}}
</button> </button>
</mat-list-item> </mat-list-item>
</mat-list> </mat-list>
@ -94,7 +94,7 @@
<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 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> </settings>
</div> </div>
<button mat-icon-button class="exit" *ngIf="planService.currentPlan" <button mat-icon-button class="exit" *ngIf="currentPlan"
(click)="settingsOpen = false"><span>+</span></button> (click)="settingsOpen = false"><span>+</span></button>
</div> </div>
</ng-template> </ng-template>

@ -6,15 +6,14 @@ 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 } from '../_services/plan.service'; import { PlanService } from '../_services/plan.service';
import { Plan, PlanElement } 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 { Observable, Subscription, 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';
import { EventsService } from '../_services/events.service'; import { EventsService } from '../_services/events.service';
import { UnlistenFn } from '@tauri-apps/api/event';
import { Event } from '@tauri-apps/api/event'; import { Event } from '@tauri-apps/api/event';
@Component({ @Component({
@ -43,6 +42,9 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
nextBind?: Subscription; nextBind?: Subscription;
prevBind?: 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) { 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", () => { window.addEventListener("resize", () => {
this.zone.run(() => { this.zone.run(() => {
@ -50,21 +52,32 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
}) })
}); });
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) => { appWindow.listen("entered", (entered) => {
if (this.planService.currentPlan) { if (this.currentPlan) {
const current = this.planService.currentPlan.current; const current = this.currentPlan.current;
const length = this.planService.currentPlan.plan.length; const length = this.currentPlan.plan.length;
if (current + 1 < length) { if (current + 1 < length) {
if (entered.payload === this.planService.currentPlan.plan[current + 1].area_key) { if (entered.payload === this.currentPlan.plan[current + 1].area_key) {
this.zone.run(() => this.next()); this.zone.run(() => this.next());
} }
} }
} }
}); });
this.planService.getPreviousPlans();
} }
windowInitHandler() { windowInitHandler() {
if (window.innerWidth > 0) { if (window.innerWidth > 0) {
this.ngAfterViewInit(); this.ngAfterViewInit();
@ -110,7 +123,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
hasWaypoint(key?: string): boolean { hasWaypoint(key?: string): boolean {
if (!key) { if (!key) {
key = this.planService.currentPlan!.plan[this.planService.currentPlan!.current].area_key; key = this.currentPlan!.plan[this.currentPlan!.current].area_key;
} }
const world_area = this.worldAreaMap?.get(key); const world_area = this.worldAreaMap?.get(key);
return world_area!.has_waypoint; return world_area!.has_waypoint;
@ -118,7 +131,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
hasTrial(key?: string): boolean { hasTrial(key?: string): boolean {
if (!key) { if (!key) {
key = this.planService.currentPlan!.plan[this.planService.currentPlan!.current].area_key; key = this.currentPlan!.plan[this.currentPlan!.current].area_key;
} }
return this.worldAreaService.hasTrial(key); return this.worldAreaService.hasTrial(key);
@ -192,7 +205,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
next() { next() {
if (this.overlayService.visible) { if (this.overlayService.visible) {
this.planService.currentPlan!.next(); this.currentPlan!.next();
this.currentSlides?.next(); this.currentSlides?.next();
this.zoneSlides?.next(); this.zoneSlides?.next();
} }
@ -200,7 +213,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
prev() { prev() {
if (this.overlayService.visible) { if (this.overlayService.visible) {
this.planService.currentPlan!.prev(); this.currentPlan!.prev();
this.currentSlides?.prev(); this.currentSlides?.prev();
this.zoneSlides?.prev(); this.zoneSlides?.prev();
} }
@ -216,9 +229,9 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
} }
} }
setPrevious(plan: string) { loadPrevious(path: string) {
this.planService.loadPrevious(plan).subscribe(plan => { this.planService.loadPlanFromPath(path, false).subscribe(plan => {
setTimeout(() => this.setIndex(plan.current), 0); this.planService.setCurrentPlan(plan);
}); });
} }
@ -238,7 +251,7 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
] ]
})).subscribe(file => { })).subscribe(file => {
if (file) { if (file) {
this.planService.loadPlan(file as string).subscribe(plan => { this.planService.loadPlanFromPath(file as string).subscribe(plan => {
if (plan) { if (plan) {
this.settingsOpen = false; this.settingsOpen = false;
} }
@ -248,8 +261,8 @@ export class PlanDisplayComponent implements AfterViewInit, OnInit {
} }
loadBasePlan() { loadBasePlan() {
this.planService.loadBasePlan().subscribe(plan => { this.planService.getBasePlan().subscribe(plan => {
this.planService.currentPlan = new Plan(plan); this.currentPlan = new Plan(plan);
if (this.zoneSlides) { if (this.zoneSlides) {
this.zoneSlides.setIndex(0); this.zoneSlides.setIndex(0);
} }

Loading…
Cancel
Save