From e56b31de97d4592bdb1fc179faeacd54352838c4 Mon Sep 17 00:00:00 2001 From: r59q Date: Wed, 9 Oct 2024 21:30:26 +0200 Subject: [PATCH 1/2] Remove storeutil --- src/i18n.ts | 4 +- src/script/stores/connectionStore.ts | 10 +- src/script/stores/knnConfig.ts | 6 +- src/script/stores/storeUtil.ts | 155 --------------------------- 4 files changed, 10 insertions(+), 165 deletions(-) delete mode 100644 src/script/stores/storeUtil.ts diff --git a/src/i18n.ts b/src/i18n.ts index 206da7ae5..71de0cb1c 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -7,8 +7,8 @@ import { init, locale, register } from 'svelte-i18n'; export { t } from 'svelte-i18n'; import { get } from 'svelte/store'; -import { persistantWritable } from './script/stores/storeUtil'; import browserLang from 'browser-lang'; +import PersistantWritable from './script/repository/PersistantWritable'; register('en', () => import('./messages/ui.en.json')); register('da', () => import('./messages/ui.da.json')); @@ -18,7 +18,7 @@ const initialLocale = browserLang({ fallback: 'en', }); -const persistantLocale = persistantWritable('lang', initialLocale); +const persistantLocale = new PersistantWritable(initialLocale, "lang"); locale.subscribe(newLocal => { if (newLocal) { diff --git a/src/script/stores/connectionStore.ts b/src/script/stores/connectionStore.ts index 398b63293..d5634bbda 100644 --- a/src/script/stores/connectionStore.ts +++ b/src/script/stores/connectionStore.ts @@ -5,19 +5,19 @@ */ import { get, type Writable } from 'svelte/store'; -import { persistantWritable } from './storeUtil'; import { MBSpecs } from 'microbyte'; +import PersistantWritable from '../repository/PersistantWritable'; // Todo: Rename file to a more appropriate name // Pattern for connecting to input microbit -export const btPatternInput: Writable = persistantWritable( - 'btPatternInput', +export const btPatternInput: Writable = new PersistantWritable( Array(25).fill(false), + 'btPatternInput', ); // Pattern for connecting to output microbit -export const btPatternOutput: Writable = persistantWritable( - 'btPatternOutput', +export const btPatternOutput: Writable = new PersistantWritable( Array(25).fill(false), + 'btPatternOutput', ); export const isInputPatternValid = () => { diff --git a/src/script/stores/knnConfig.ts b/src/script/stores/knnConfig.ts index bb7256633..6b68dae94 100644 --- a/src/script/stores/knnConfig.ts +++ b/src/script/stores/knnConfig.ts @@ -3,13 +3,13 @@ * * SPDX-License-Identifier: MIT */ -import { persistantWritable } from './storeUtil'; import StaticConfiguration from '../../StaticConfiguration'; +import PersistantWritable from '../repository/PersistantWritable'; export type KNNSettings = { k: number; }; -export const knnConfig = persistantWritable('knnConfig', { +export const knnConfig = new PersistantWritable({ k: StaticConfiguration.defaultKnnNeighbourCount, -}); +}, 'knnConfig'); diff --git a/src/script/stores/storeUtil.ts b/src/script/stores/storeUtil.ts deleted file mode 100644 index 6417d8088..000000000 --- a/src/script/stores/storeUtil.ts +++ /dev/null @@ -1,155 +0,0 @@ -/** - * (c) 2023, Center for Computational Thinking and Design at Aarhus University and contributors - * - * SPDX-License-Identifier: MIT - */ - -import { writable, type Writable } from 'svelte/store'; - -// Version of saved information. -// Increment if stored information types are changed -// or if a localstorage data needs to be wiped -// (incrementing it, will overwrite all persistantWritable data stored in localstorage) -const persistVersion = 1; - -// Creates a svelte store which automatically loads from localstorage, and -// keeps localstorage up to date -export function persistantWritable(key: string, initValue: T): Writable { - if (initValue === null || initValue === undefined) { - throw new Error( - "Do not use 'null' or 'undefined' values as initial value. Later checking for changes, will result in stored changes being deleted", - ); - } - const storedJson: string | null = localStorage.getItem(key); - - let storedObject: unknown; - try { - const parseSets = (key: string | number, value: unknown) => { - if (value instanceof Array && key === 'includedFilters') { - const setWithFilters = new Set(value); - return setWithFilters; - } - return value; - }; - storedObject = storedJson != null ? JSON.parse(storedJson, parseSets) : null; - } catch (error) { - console.warn(error); - storedObject = null; - } - - const useStored = shouldUseStored(storedObject, initValue); - initValue = useStored - ? (storedObject as { version: number; value: T }).value - : initValue; - const store: Writable = writable(initValue); - store.subscribe(val => - localStorage.setItem( - key, - JSON.stringify( - { version: persistVersion, value: val }, - (key: string | number, value: unknown) => { - if (value instanceof Set && key === 'includedFilters') - return [...value] as unknown[]; - return value; - }, - ), - ), - ); - - return store; -} - -function shouldUseStored(storedObject: unknown, initValue: T): boolean { - if (storedObject == null) { - return false; - } - if (typeof storedObject !== 'object') { - return false; - } - if (!('value' in storedObject) || !('version' in storedObject)) { - return false; - } - const storedPersistObject = storedObject as { version: unknown; value: unknown }; // This should not be needed, but the typescript rollup plugin complains if we keep working directly on 'storedObject' - if (storedPersistObject.version !== persistVersion) { - return false; - } - - return areMatchingTypes(initValue, storedPersistObject.value); -} - -// Recursively checks if to variables of unknown type matches each -// other type and structure wise -// Due to javascript being a dumb language without proper typing, this cannot check -// properly if something in the initial values are null or undefined or if something gets set to null -// or undefined -function areMatchingTypes(value1: unknown, value2: unknown): boolean { - if (value1 === value2) { - return true; - } - if (value1 === null) { - // This makes the type-checking incomplete, but otherwise we need to completely ban 'null' values in pesistant storage - return true; - } - const type1 = typeof value1; - const type2 = typeof value2; - if (type1 !== type2) { - return false; - } - - if (['boolean', 'number', 'string', 'null'].includes(type1)) { - // value is a primitive - return true; // We know from previous check that type1 === type2 - } - if (type1 === 'undefined') { - throw new Error('You should never use "undefined" as values for persistant storage'); - } - if (type1 !== 'object') { - throw new Error('Unrecognised type: ' + type1); - } - - const isType1Array = Array.isArray(value1); - const isType2Array = Array.isArray(value2); - - if (isType1Array !== isType2Array) { - return false; - } - - if (isType1Array) { - const array1 = value1 as unknown[]; - const array2 = value2 as unknown[]; - if (array1.length === 0 || array2.length === 0) { - return true; // Either array is empty -> no type conflict - } - for (const item of array2) { - const isValidItem = areMatchingTypes(array1[0], item); - if (!isValidItem) { - return false; - } - } - return true; - } - - // Both parameters are 'object's and not arrays - - const obj1 = value1 as object; - const obj2 = value2 as object; - - const obj1Properties = Object.entries(obj1); - - for (const [key, value] of obj1Properties) { - if (!(key in obj2) && value != null) { - return false; // A property existing on one object does not exist on the other - } - } - - // The two objects have the same properties - - for (const [key, value] of obj1Properties) { - const obj2Property: unknown = obj2[key as keyof object]; // A bit hacky, but we have already checked to two objects have the same keys - const isMatch = areMatchingTypes(value as unknown, obj2Property); - if (!isMatch) { - return false; - } - } - return true; -} From 57aeb4bda04d43f0eb8a4f9c4b92d737b983b81b Mon Sep 17 00:00:00 2001 From: r59q Date: Wed, 9 Oct 2024 21:31:39 +0200 Subject: [PATCH 2/2] Prettier --- src/i18n.ts | 2 +- src/script/stores/knnConfig.ts | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/i18n.ts b/src/i18n.ts index 71de0cb1c..f669668f0 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -18,7 +18,7 @@ const initialLocale = browserLang({ fallback: 'en', }); -const persistantLocale = new PersistantWritable(initialLocale, "lang"); +const persistantLocale = new PersistantWritable(initialLocale, 'lang'); locale.subscribe(newLocal => { if (newLocal) { diff --git a/src/script/stores/knnConfig.ts b/src/script/stores/knnConfig.ts index 6b68dae94..e4a10bf90 100644 --- a/src/script/stores/knnConfig.ts +++ b/src/script/stores/knnConfig.ts @@ -10,6 +10,9 @@ export type KNNSettings = { k: number; }; -export const knnConfig = new PersistantWritable({ - k: StaticConfiguration.defaultKnnNeighbourCount, -}, 'knnConfig'); +export const knnConfig = new PersistantWritable( + { + k: StaticConfiguration.defaultKnnNeighbourCount, + }, + 'knnConfig', +);