From b712966cf7cc8bcf04b487d727e96bc16e4f67c4 Mon Sep 17 00:00:00 2001 From: Jannik Date: Sat, 27 Sep 2025 12:13:44 +0200 Subject: [PATCH] feat: reactive stores --- .../sidebar/settings/DeveloperSidebar.svelte | 20 +++++++- .../services/{stores.ts => stores.svelte.ts} | 51 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) rename src/lib/services/{stores.ts => stores.svelte.ts} (66%) diff --git a/src/lib/components/lnv/sidebar/settings/DeveloperSidebar.svelte b/src/lib/components/lnv/sidebar/settings/DeveloperSidebar.svelte index f4f87ff..defc67a 100644 --- a/src/lib/components/lnv/sidebar/settings/DeveloperSidebar.svelte +++ b/src/lib/components/lnv/sidebar/settings/DeveloperSidebar.svelte @@ -3,6 +3,7 @@ CloudUploadIcon, HandIcon, MapIcon, + PackageMinusIcon, PackagePlusIcon, RefreshCcwIcon, SpeechIcon, @@ -16,9 +17,11 @@ import { view } from "../../view.svelte"; import { m } from "$lang/messages"; import { setOnboardingState } from "$lib/onboarding.svelte"; - import { syncStores, updateStore } from "$lib/services/stores"; + import { stores, syncStores, updateStore } from "$lib/services/stores.svelte"; const dev = getDeveloperToggle(); + + const locationStores = stores("location"); {m["sidebar.developer.header"]()} @@ -91,6 +94,21 @@ await updateStore({ name, type }, JSON.parse(data)); }} /> + { + const name = prompt("Store Name?"); + if (!name) return; + const type = prompt("Store Type? (route, location, vehicle)"); + if (type !== "route" && type !== "location" && type !== "vehicle") { + alert("Invalid type"); + return; + } + await updateStore({ name, type }, null); + }} + /> + LOCATION STORES: {JSON.stringify(locationStores.current)}
diff --git a/src/lib/services/stores.ts b/src/lib/services/stores.svelte.ts similarity index 66% rename from src/lib/services/stores.ts rename to src/lib/services/stores.svelte.ts index f63325a..38d682f 100644 --- a/src/lib/services/stores.ts +++ b/src/lib/services/stores.svelte.ts @@ -53,6 +53,8 @@ export const db = await openDB("tc", 1, { } }) +const eventTarget = new EventTarget(); + export async function syncStores() { const changes = await Promise.all(await db.getAll("changes").then(changes => changes.map(async change => { const storeData = await db.get("stores", change.id); @@ -82,6 +84,7 @@ export async function syncStores() { } else { await tx.objectStore("stores").put(store); } + eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) ); } // Delete all changes await tx.objectStore("changes").clear(); @@ -102,12 +105,14 @@ async function createStore(info: StoreInfo, data: object) { await tx.objectStore("stores").add(store); await tx.objectStore("changes").add({ id, operation: "create" }); await tx.done; + eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) ); return store; } -export async function updateStore(info: StoreInfo, data: object) { +export async function updateStore(info: StoreInfo, data: object | null) { const store = await db.getFromIndex("stores", "by-name-and-type", [info.name, info.type]); if (!store) { + if(data === null) return; return await createStore(info, data); } // Update the store data @@ -117,5 +122,49 @@ export async function updateStore(info: StoreInfo, data: object) { await tx.objectStore("stores").put(store); await tx.objectStore("changes").add({ id: store.id, operation: "update" }); await tx.done; + eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) ); return store; } + +// export async function store(info: StoreInfo) { +// const store = await db.getFromIndex("stores", "by-name-and-type", [info.name, info.type]); +// if (!store) { +// return null; +// } +// const state = $state(JSON.parse(store.data) as T); +// $effect(() => { +// updateStore(info, state); +// }) +// eventTarget.addEventListener("store-updated", (event) => { +// const customEvent = event as CustomEvent; +// if(customEvent.detail.id === store.id) { +// const updatedStore = customEvent.detail as Store; +// Object.assign(state, JSON.parse(updatedStore.data)); +// } +// }); +// return state; +// } + +export function stores(type: StoreType) { + const state = $state([]); + eventTarget.addEventListener("store-updated", async (event) => { + const customEvent = event as CustomEvent; + const updatedStore = customEvent.detail as Store; + if(updatedStore.type === type) { + const stores = await db.getAllFromIndex("stores", "by-type", type); + state.splice(0, state.length, ...(stores.map(store => JSON.parse(store.data) as T).filter(store => store !== null))); + } + }); + (async () => { + const stores = await db.getAllFromIndex("stores", "by-type", type); + state.splice(0, state.length, ...(stores.map(store => JSON.parse(store.data) as T).filter(store => store !== null))); + })(); + return { + get current() { + return state; + }, + set current(newValue: T[]) { + state.splice(0, state.length, ...newValue); + } + } +}