functional with immer

This commit is contained in:
vcoppe
2024-05-07 18:14:47 +02:00
parent d35b702011
commit 0bdd3e7d8a
6 changed files with 45 additions and 21 deletions

View File

@@ -14,11 +14,11 @@
"clsx": "^2.1.0",
"dexie": "^4.0.4",
"gpx": "file:../gpx",
"immer": "^10.1.1",
"lucide-svelte": "^0.365.0",
"mapbox-gl": "^3.2.0",
"mode-watcher": "^0.3.0",
"sortablejs": "^1.15.2",
"structurajs": "^0.12.0",
"svelte-i18n": "^4.0.0",
"svelte-sonner": "^0.3.22",
"tailwind-merge": "^2.2.2",
@@ -3363,6 +3363,15 @@
"node": ">= 4"
}
},
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -5132,11 +5141,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/structurajs": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/structurajs/-/structurajs-0.12.0.tgz",
"integrity": "sha512-vadDl3zCv6OM2dXfzelUH3RLhNu9pmIEZU7zS0jIgMR3BDKIk44fDd/X9KK9LE27MMU+/aw3ibBTQQgBH0zfiw=="
},
"node_modules/subtag": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/subtag/-/subtag-0.5.0.tgz",

View File

@@ -47,11 +47,11 @@
"clsx": "^2.1.0",
"dexie": "^4.0.4",
"gpx": "file:../gpx",
"immer": "^10.1.1",
"lucide-svelte": "^0.365.0",
"mapbox-gl": "^3.2.0",
"mode-watcher": "^0.3.0",
"sortablejs": "^1.15.2",
"structurajs": "^0.12.0",
"svelte-i18n": "^4.0.0",
"svelte-sonner": "^0.3.22",
"tailwind-merge": "^2.2.2",

View File

@@ -1,15 +1,18 @@
import Dexie, { liveQuery } from 'dexie';
import { GPXFile } from 'gpx';
import { type FreezedObject, type Patch, produceWithPatches, applyPatches } from 'structurajs';
import { enableMapSet, enablePatches, produceWithPatches, applyPatches, type Patch } from 'immer';
import { writable, get, derived, type Readable, type Writable } from 'svelte/store';
import { fileOrder, selectedFiles } from './stores';
import { mode } from 'mode-watcher';
import { defaultBasemap, defaultBasemapTree, defaultOverlayTree, defaultOverlays } from './assets/layers';
enableMapSet();
enablePatches();
class Database extends Dexie {
fileids!: Dexie.Table<string, string>;
files!: Dexie.Table<FreezedObject<GPXFile>, string>;
files!: Dexie.Table<GPXFile, string>;
patches!: Dexie.Table<{ patch: Patch[], inversePatch: Patch[], index: number }, number>;
settings!: Dexie.Table<any, string>;
@@ -103,7 +106,7 @@ function dexieStore<T>(querier: () => T | Promise<T>, initial?: T): Readable<T>
}
// Wrap Dexie live queries in a Svelte store to avoid triggering the query for every subscriber, also takes care of the conversion to a GPXFile object
function dexieGPXFileStore(querier: () => FreezedObject<GPXFile> | undefined | Promise<FreezedObject<GPXFile> | undefined>): Readable<GPXFile> {
function dexieGPXFileStore(querier: () => GPXFile | undefined | Promise<GPXFile | undefined>): Readable<GPXFile> {
let store = writable<GPXFile>(undefined);
liveQuery(querier).subscribe(value => {
if (value !== undefined) {
@@ -118,8 +121,8 @@ function dexieGPXFileStore(querier: () => FreezedObject<GPXFile> | undefined | P
}
// Add/update the files to the database
function updateDbFiles(files: (FreezedObject<GPXFile> | undefined)[], add: boolean = false) {
let filteredFiles = files.filter(file => file !== undefined) as FreezedObject<GPXFile>[];
function updateDbFiles(files: (GPXFile | undefined)[], add: boolean = false) {
let filteredFiles = files.filter(file => file !== undefined) as GPXFile[];
let fileIds = filteredFiles.map(file => file._data.id);
if (add) {
return db.transaction('rw', db.fileids, db.files, async () => {
@@ -140,7 +143,7 @@ function deleteDbFiles(fileIds: string[]) {
}
// Commit the changes to the file state to the database
function commitFileStateChange(newFileState: ReadonlyMap<string, FreezedObject<GPXFile>>, patch: Patch[]) {
function commitFileStateChange(newFileState: ReadonlyMap<string, GPXFile>, patch: Patch[]) {
if (newFileState.size > fileState.size) {
return updateDbFiles(getChangedFileIds(patch).map((fileId) => newFileState.get(fileId)), true);
} else if (newFileState.size === fileState.size) {
@@ -238,15 +241,12 @@ function applyPatch(patch: Patch[]) {
}
// Get the file ids of the files that have changed in the patch
function getChangedFileIds(patch: Patch[]) {
let changedFileIds = [];
function getChangedFileIds(patch: Patch[]): string[] {
let changedFileIds = new Set();
for (let p of patch) {
let fileId = p.p?.toString();
if (fileId) {
changedFileIds.push(fileId);
}
changedFileIds.add(p.path[0]);
}
return changedFileIds;
return Array.from(changedFileIds);
}
// Generate unique file ids, different from the ones in the database