diff --git a/src-tauri/src/plan.rs b/src-tauri/src/plan.rs index 093f1e5..926036a 100644 --- a/src-tauri/src/plan.rs +++ b/src-tauri/src/plan.rs @@ -1,9 +1,5 @@ -use std::{ - collections::HashMap, - path::{Path, PathBuf}, -}; +use std::collections::HashMap; -use poe_data::world_area::WorldArea; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] @@ -36,7 +32,9 @@ struct OldArea { } pub fn convert_old(path: &str) -> Option { - let plan: OldPlan = serde_json::from_str(&std::fs::read_to_string(path).expect("Could not convert old")).expect("could not convert old"); + let plan: OldPlan = + serde_json::from_str(&std::fs::read_to_string(path).expect("Could not convert old")) + .expect("could not convert old"); let map = poe_data::world_area::load_world_areas_map(include_str!( "../../data/processed_world_areas.json" @@ -47,10 +45,14 @@ pub fn convert_old(path: &str) -> Option { .collect::>(); Some(Plan { - current: 0, - plan: plan.elements.into_iter().map(|plan_element| PlanElement { - area_key: map[&plan_element.area._rid].to_owned(), - notes: plan_element.note, - }).collect::>(), + current: plan.position, + plan: plan + .elements + .into_iter() + .map(|plan_element| PlanElement { + area_key: map[&plan_element.area._rid].to_owned(), + notes: plan_element.note, + }) + .collect::>(), }) } diff --git a/src-tauri/src/storage.rs b/src-tauri/src/storage.rs index 1f5db5a..3ae16a2 100644 --- a/src-tauri/src/storage.rs +++ b/src-tauri/src/storage.rs @@ -22,8 +22,18 @@ fn proj_dir() -> Option { ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION) } +fn mkdir() { + if let Some(proj_dir) = proj_dir() { + let dir_structure = proj_dir.data_dir().join(SAVED_PLANS); + std::fs::create_dir_all(dir_structure) + .map_err(|e| log::error!("Could not create directory for storing config and saves")) + .ok(); + } +} + impl Default for Storage { fn default() -> Self { + mkdir(); let storage = Self::load(); match storage { Some(storage) => storage, @@ -38,7 +48,7 @@ impl Default for Storage { impl Storage { fn load() -> Option { let storage: Option = serde_json::from_str( - &std::fs::read_to_string(proj_dir()?.data_dir().with_file_name(CONFIG_FILE)).ok()?, + &std::fs::read_to_string(proj_dir()?.data_dir().join(CONFIG_FILE)).ok()?, ) .ok(); @@ -50,9 +60,9 @@ impl Storage { pub fn save(&self) { if let Ok(content) = serde_json::to_string_pretty(&self) { if let Some(dir) = proj_dir() { - match std::fs::write(dir.data_dir().with_file_name(CONFIG_FILE), content) { + match std::fs::write(dir.data_dir().join(CONFIG_FILE), content) { Ok(_) => { - if let Some(c) = dir.data_dir().with_file_name(CONFIG_FILE).to_str() { + if let Some(c) = dir.data_dir().join(CONFIG_FILE).to_str() { log::info!("Saved config to {}", c) } } @@ -70,22 +80,11 @@ impl Storage { if !path.ends_with(SAVED_PLANS) { if let Some(proj_dir) = proj_dir() { if let Some(file_name) = plan_file.file_name() { - let copy_result = std::fs::copy( - &file, - proj_dir - .data_dir() - .join(SAVED_PLANS) - .with_file_name(file_name), - ); + let dest = proj_dir.data_dir().join(SAVED_PLANS).join(file_name); + let copy_result = std::fs::copy(&file, &dest); match copy_result { Ok(_) => { - file = proj_dir - .data_dir() - .join(SAVED_PLANS) - .with_file_name(file_name) - .to_str() - .unwrap() - .to_string() + file = dest.to_str()?.to_string(); } Err(e) => log::error!("Could not store plan file {e:?}"), } @@ -95,13 +94,19 @@ impl Storage { } log::info!("Loading plan: {file:?}"); - if let Some(plan) = serde_json::from_str(&std::fs::read_to_string(&file).ok()?).ok() - { + if let Some(plan) = serde_json::from_str(&std::fs::read_to_string(&file).ok()?).ok() { plan } else { log::info!("Attempting to convert old"); let plan = convert_old(&file)?; - std::fs::write(&file, serde_json::to_string(&plan).ok()?).ok(); + std::fs::write( + &file, + serde_json::to_string(&plan) + .map_err(|e| log::error!("Could not serialize converted plan to json {e:?}")) + .ok()?, + ) + .map_err(|e| "Could not write converted plan to storage") + .ok(); Some(plan) } } diff --git a/src/app/carousel/carousel.component.scss b/src/app/carousel/carousel.component.scss index 0f2615c..46cb34f 100644 --- a/src/app/carousel/carousel.component.scss +++ b/src/app/carousel/carousel.component.scss @@ -11,33 +11,23 @@ .slide { background-color: green; - grid-template-rows: 1; + grid-row-start: 1; } .slide-vertical { background-color: green; - grid-template-columns: 1; + grid-column-start: 1; + + } - - .window { display: grid; width: 100%; height: 100%; } -// .window { -// grid-template-columns: repeat(3, 1fr); -// grid-auto-flow: column; -// } - -// .window-vertical { -// grid-template-rows: repeat(3, 1fr); -// grid-auto-flow: row; -// } - .current { background-color: magenta; } diff --git a/src/app/carousel/carousel.component.ts b/src/app/carousel/carousel.component.ts index 014e7bc..83f96fc 100644 --- a/src/app/carousel/carousel.component.ts +++ b/src/app/carousel/carousel.component.ts @@ -37,9 +37,7 @@ export class CarouselComponent implements OnInit, AfterViewInit { @Output() changedIndex: EventEmitter = new EventEmitter(); @Input() slides?: any[]; @ContentChild(TemplateRef) template?: TemplateRef; - @ViewChild('carouselWindow') window!: ElementRef; - @ViewChildren('slideElement') slideElements!: QueryList; current: number = 0; @@ -50,6 +48,7 @@ export class CarouselComponent implements OnInit, AfterViewInit { angularAnimating: boolean = false; animation: string = 'vertical'; directionTime: number = 0; + @Input() numVisible: number = 1; private debouncedOnchange: Subject = new Subject(); @@ -91,6 +90,14 @@ export class CarouselComponent implements OnInit, AfterViewInit { } + numExtraNext() { + return Math.floor((this.numVisible - 1) / 2); + } + + numExtraPrev() { + return Math.ceil((this.numVisible - 1) / 2); + } + ngAfterViewInit(): void { this.slideElements.changes.subscribe((comps: QueryList) => { @@ -104,16 +111,13 @@ export class CarouselComponent implements OnInit, AfterViewInit { } initialize() { - this.visibleSlides?.push({ - index: 0, - hasBeenVisible: false, - currentlyIntersecting: false, - }) - this.visibleSlides?.push({ - index: 1, - hasBeenVisible: false, - currentlyIntersecting: false, - }) + for(let i = 0; i <= this.numExtraNext() && i < this.slides!.length; i++) { + this.visibleSlides?.push({ + index: i, + hasBeenVisible: false, + currentlyIntersecting: false, + }) + } } handleNewDomSlide(ref: ElementRef) { @@ -125,11 +129,11 @@ export class CarouselComponent implements OnInit, AfterViewInit { if (this.slides && this.current + 1 < this.slides?.length) { this.current += 1; this.changedIndex.emit(this.current); - - if (this.current + 1 < this.slides.length) { - if (!this.visibleSlides?.find(e => e.index == this.current + 1)) { + console.log("numextra", this.numExtraNext()); + if (this.current + this.numExtraNext() < this.slides.length) { + if (!this.visibleSlides?.find(e => e.index == this.current + this.numExtraNext() )) { this.visibleSlides?.push({ - index: this.current + 1, + index: this.current + this.numExtraNext(), hasBeenVisible: false, currentlyIntersecting: false, }); @@ -145,10 +149,10 @@ export class CarouselComponent implements OnInit, AfterViewInit { this.current -= 1; this.changedIndex.emit(this.current); - if (this.current - 1 >= 0) { - if (!this.visibleSlides?.find(e => e.index == this.current - 1)) { + if (this.current - this.numExtraPrev() >= 0) { + if (!this.visibleSlides?.find(e => e.index == this.current - this.numExtraPrev())) { this.visibleSlides?.push({ - index: this.current - 1, + index: this.current - this.numExtraPrev(), hasBeenVisible: false, currentlyIntersecting: false, }); @@ -163,22 +167,23 @@ export class CarouselComponent implements OnInit, AfterViewInit { } realOnChange() { + const safetyFactor = this.numVisible == 1 ? 1 : 2; { const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index); const lowestIntersecting = intersecting![0]; - this.visibleSlides = this.visibleSlides?.filter(e => e.index + 2 >= lowestIntersecting!.index && e.index >= this.current - 2); + this.visibleSlides = this.visibleSlides?.filter(e => e.index + safetyFactor >= lowestIntersecting!.index && e.index >= this.current - this.numExtraPrev()); } { const intersecting = this.visibleSlides?.filter(e => e.currentlyIntersecting).sort((e1, e2) => e1.index - e2.index).reverse(); const highestIntersecting = intersecting![0] - this.visibleSlides = this.visibleSlides?.filter(e => e.index - 2 <= highestIntersecting!.index && e.index <= this.current + 2); + this.visibleSlides = this.visibleSlides?.filter(e => e.index - safetyFactor <= highestIntersecting!.index && e.index <= this.current + this.numExtraNext()); } } translation() { - let num = (this.current - 1) * (-1 / 3) * 100; + let num = (this.current - this.numExtraNext() - (this.numVisible % 2 == 0 ? 1 : 0)) * (-1 / this.numVisible) * 100; if (this.vertical) { return `0 ${num}%` } else { @@ -189,7 +194,7 @@ export class CarouselComponent implements OnInit, AfterViewInit { templateValue() { const len = this.slides?.length; - return `repeat(${len}, minmax(calc(100% / 3), 1fr))`; + return `repeat(${len}, minmax(calc(100% / ${this.numVisible}), 1fr))`; } style() { diff --git a/src/app/plan-display/plan-display.component.html b/src/app/plan-display/plan-display.component.html index 268558f..ba06b05 100644 --- a/src/app/plan-display/plan-display.component.html +++ b/src/app/plan-display/plan-display.component.html @@ -4,26 +4,23 @@ #targetRef> - + - {{slide}} + ZONE{{slide}} + + + + + CURRENT{{slide}} -
- Notes:{{plan.elements[slideIndex].note}} -
-
- - - -
- Direction change time: {{carouselComponent.directionTime}}
- -
+
+ +
{ - this.carouselComponent?.prev(); - }); - this.shortcut.register("F8", () => { - this.carouselComponent?.next(); - }); - } else { + registerZoneSlides(carousel: CarouselComponent) { + this.zoneSlides = carousel; + console.log("zone slides"); + } + registerCurrentSlides(carousel: CarouselComponent) { + this.currentSlides = carousel; + + if (this.currentSlides) { + this.shortcut.register("F7", this.prev.bind(this)); + this.shortcut.register("F8", this.next.bind(this)); } } + + next() { + this.currentSlides?.next(); + this.zoneSlides?.next(); + } + + prev() { + this.currentSlides?.prev(); + this.zoneSlides?.prev(); + } } diff --git a/src/app/services/shortcut.service.ts b/src/app/services/shortcut.service.ts index 22802c8..d607b84 100644 --- a/src/app/services/shortcut.service.ts +++ b/src/app/services/shortcut.service.ts @@ -1,7 +1,6 @@ import { Injectable, NgZone } from '@angular/core'; import { ShortcutHandler, register, unregister } from '@tauri-apps/api/globalShortcut'; -import { EMPTY, Observable, catchError, empty, from } from 'rxjs'; -import { ConfigService } from './config.service'; +import { EMPTY, from } from 'rxjs'; @Injectable({ providedIn: 'root' @@ -12,7 +11,6 @@ export class ShortcutService { constructor(private zone: NgZone) { } register(shortcut: string, handler: ShortcutHandler) { - console.log("binding key:", shortcut, "to handler", handler); this.bound.set(handler, shortcut); return from(register(shortcut, (s) => { @@ -28,12 +26,14 @@ export class ShortcutService { } rebind(shortcut: string, handler: ShortcutHandler) { - const prevShortcut = this.bound.get(handler)!; + const prevShortcut = this.bound.get(handler); this.register(shortcut, handler).subscribe( { error: (_err) => { - this.register(prevShortcut, handler); - console.log("Got error during binding, rebinding previous"); + if (prevShortcut) { + console.log("Got error during binding, rebinding previous"); + this.register(prevShortcut, handler); + } return EMPTY; } });