feat: reactive stores
This commit is contained in:
@ -3,6 +3,7 @@
|
|||||||
CloudUploadIcon,
|
CloudUploadIcon,
|
||||||
HandIcon,
|
HandIcon,
|
||||||
MapIcon,
|
MapIcon,
|
||||||
|
PackageMinusIcon,
|
||||||
PackagePlusIcon,
|
PackagePlusIcon,
|
||||||
RefreshCcwIcon,
|
RefreshCcwIcon,
|
||||||
SpeechIcon,
|
SpeechIcon,
|
||||||
@ -16,9 +17,11 @@
|
|||||||
import { view } from "../../view.svelte";
|
import { view } from "../../view.svelte";
|
||||||
import { m } from "$lang/messages";
|
import { m } from "$lang/messages";
|
||||||
import { setOnboardingState } from "$lib/onboarding.svelte";
|
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 dev = getDeveloperToggle();
|
||||||
|
|
||||||
|
const locationStores = stores("location");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SidebarHeader>{m["sidebar.developer.header"]()}</SidebarHeader>
|
<SidebarHeader>{m["sidebar.developer.header"]()}</SidebarHeader>
|
||||||
@ -91,6 +94,21 @@
|
|||||||
await updateStore({ name, type }, JSON.parse(data));
|
await updateStore({ name, type }, JSON.parse(data));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<SettingsButton
|
||||||
|
icon={PackageMinusIcon}
|
||||||
|
text="Delete Store"
|
||||||
|
onclick={async () => {
|
||||||
|
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);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span>LOCATION STORES: {JSON.stringify(locationStores.current)}</span>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@ -53,6 +53,8 @@ export const db = await openDB<TCDB>("tc", 1, {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const eventTarget = new EventTarget();
|
||||||
|
|
||||||
export async function syncStores() {
|
export async function syncStores() {
|
||||||
const changes = await Promise.all(await db.getAll("changes").then(changes => changes.map(async change => {
|
const changes = await Promise.all(await db.getAll("changes").then(changes => changes.map(async change => {
|
||||||
const storeData = await db.get("stores", change.id);
|
const storeData = await db.get("stores", change.id);
|
||||||
@ -82,6 +84,7 @@ export async function syncStores() {
|
|||||||
} else {
|
} else {
|
||||||
await tx.objectStore("stores").put(store);
|
await tx.objectStore("stores").put(store);
|
||||||
}
|
}
|
||||||
|
eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) );
|
||||||
}
|
}
|
||||||
// Delete all changes
|
// Delete all changes
|
||||||
await tx.objectStore("changes").clear();
|
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("stores").add(store);
|
||||||
await tx.objectStore("changes").add({ id, operation: "create" });
|
await tx.objectStore("changes").add({ id, operation: "create" });
|
||||||
await tx.done;
|
await tx.done;
|
||||||
|
eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) );
|
||||||
return 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]);
|
const store = await db.getFromIndex("stores", "by-name-and-type", [info.name, info.type]);
|
||||||
if (!store) {
|
if (!store) {
|
||||||
|
if(data === null) return;
|
||||||
return await createStore(info, data);
|
return await createStore(info, data);
|
||||||
}
|
}
|
||||||
// Update the store 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("stores").put(store);
|
||||||
await tx.objectStore("changes").add({ id: store.id, operation: "update" });
|
await tx.objectStore("changes").add({ id: store.id, operation: "update" });
|
||||||
await tx.done;
|
await tx.done;
|
||||||
|
eventTarget.dispatchEvent(new CustomEvent("store-updated", { detail: store }) );
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export async function store<T extends object>(info: StoreInfo) {
|
||||||
|
// const store = await db.getFromIndex("stores", "by-name-and-type", [info.name, info.type]);
|
||||||
|
// if (!store) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// const state = $state<T>(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<T extends object>(type: StoreType) {
|
||||||
|
const state = $state<T[]>([]);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user