aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-06-12 22:06:31 -0700
committerFuwn <[email protected]>2025-06-12 22:06:31 -0700
commite8612618fb20f779ebe2e85edf32d71961d2f1d4 (patch)
treefa8565afb8584bbf55f4f4d496c2c350a5a25210
parentrefactor(List): Simplify get-set structure of stateBin usage (diff)
downloaddue.moe-e8612618fb20f779ebe2e85edf32d71961d2f1d4.tar.xz
due.moe-e8612618fb20f779ebe2e85edf32d71961d2f1d4.zip
feat: Move remaining localStorage usages to localforage
-rw-r--r--src/app.html205
-rw-r--r--src/lib/Error/LogInRestricted.svelte5
-rw-r--r--src/lib/Landing.svelte5
-rw-r--r--src/lib/List/Anime/AnimeListTemplate.svelte8
-rw-r--r--src/lib/List/Anime/CleanAnimeList.svelte5
-rw-r--r--src/lib/List/Manga/CleanMangaList.svelte8
-rw-r--r--src/lib/List/Manga/MangaListTemplate.svelte5
-rw-r--r--src/lib/Settings/Categories/Debug.svelte6
-rw-r--r--src/routes/+layout.svelte28
-rw-r--r--src/routes/user/+page.svelte26
-rw-r--r--src/routes/user/[user]/badges/+page.svelte7
-rw-r--r--src/stores/announcementHash.ts17
-rw-r--r--src/stores/identity.ts43
-rw-r--r--src/stores/lastPruneTimes.ts46
-rw-r--r--src/stores/settings.ts61
-rw-r--r--src/stores/stateBin.ts15
16 files changed, 273 insertions, 217 deletions
diff --git a/src/app.html b/src/app.html
index 498e3f9c..d485fc70 100644
--- a/src/app.html
+++ b/src/app.html
@@ -84,99 +84,124 @@
document.addEventListener('DOMContentLoaded', () => {
const mai = document.getElementById('mai');
+ const openRequest = indexedDB.open('localforage');
- aoButa = JSON.parse(localStorage.getItem('settings')).displayAoButa;
- mai.style.display = 'block';
-
- if (aoButa === 'random') {
- const random = Math.floor(Math.random() * 8);
-
- switch (random) {
- case 0:
- aoButa = 'mai';
- break;
- case 1:
- aoButa = 'nodoka';
- break;
- case 2:
- aoButa = 'kaede';
- break;
- case 3:
- aoButa = 'rio';
- break;
- case 4:
- aoButa = 'sakuta';
- break;
- case 5:
- aoButa = 'shouko';
- break;
- case 6:
- aoButa = 'tomoe';
- break;
- case 6:
- default:
- aoButa = 'mai_2';
- break;
- }
- }
-
- switch (aoButa) {
- case 'mai_2':
- {
- mai.src = '/aobuta/mai.png';
- mai.alt = 'Mai Sakurajima';
- }
- break;
- case 'mai':
- {
- mai.src = '/aobuta/mai_2.webp';
- mai.alt = 'Mai Sakurajima';
- }
- break;
- case 'nodoka':
- {
- mai.src = '/aobuta/nodoka.webp';
- mai.alt = 'Nodoka Toyohama';
- }
- break;
- case 'kaede':
- {
- mai.src = '/aobuta/kaede.png';
- mai.alt = 'Kaede Azusagawa';
- }
- break;
- case 'rio':
- {
- mai.src = '/aobuta/rio.webp';
- mai.alt = 'Rio Futaba';
- }
- break;
- case 'sakuta':
- {
- mai.src = '/aobuta/sakuta.webp';
- mai.alt = 'Sakuta Azusagawa';
- }
- break;
- case 'shouko':
- {
- mai.src = '/aobuta/shouko.webp';
- mai.alt = 'Shouko Makinohara';
- }
- break;
- case 'tomoe':
- {
- mai.src = '/aobuta/tomoe.webp';
- mai.alt = 'Tomoe Koga';
+ openRequest.onsuccess = (event) => {
+ const database = event.target.result;
+ const transaction = database.transaction(['keyvaluepairs'], 'readonly');
+ const objectStore = transaction.objectStore('keyvaluepairs');
+ const getRequest = objectStore.get('settings');
+
+ getRequest.onsuccess = () => {
+ const settings = getRequest.result;
+
+ aoButa = settings?.displayAoButa || 'none';
+ mai.style.display = 'block';
+
+ if (aoButa === 'random') {
+ const random = Math.floor(Math.random() * 8);
+
+ switch (random) {
+ case 0:
+ aoButa = 'mai';
+
+ break;
+
+ case 1:
+ aoButa = 'nodoka';
+
+ break;
+
+ case 2:
+ aoButa = 'kaede';
+
+ break;
+
+ case 3:
+ aoButa = 'rio';
+
+ break;
+
+ case 4:
+ aoButa = 'sakuta';
+
+ break;
+
+ case 5:
+ aoButa = 'shouko';
+
+ break;
+
+ case 6:
+ aoButa = 'tomoe';
+
+ break;
+
+ default:
+ aoButa = 'mai_2';
+
+ break;
+ }
}
- break;
- case 'none': {
- {
- mai.style.display = 'none';
- mai.alt = 'No one';
+
+ switch (aoButa) {
+ case 'mai_2':
+ mai.src = '/aobuta/mai.png';
+ mai.alt = 'Mai Sakurajima';
+
+ break;
+
+ case 'mai':
+ mai.src = '/aobuta/mai_2.webp';
+ mai.alt = 'Mai Sakurajima';
+
+ break;
+
+ case 'nodoka':
+ mai.src = '/aobuta/nodoka.webp';
+ mai.alt = 'Nodoka Toyohama';
+
+ break;
+
+ case 'kaede':
+ mai.src = '/aobuta/kaede.png';
+ mai.alt = 'Kaede Azusagawa';
+
+ break;
+
+ case 'rio':
+ mai.src = '/aobuta/rio.webp';
+ mai.alt = 'Rio Futaba';
+
+ break;
+
+ case 'sakuta':
+ mai.src = '/aobuta/sakuta.webp';
+ mai.alt = 'Sakuta Azusagawa';
+
+ break;
+
+ case 'shouko':
+ mai.src = '/aobuta/shouko.webp';
+ mai.alt = 'Shouko Makinohara';
+
+ break;
+
+ case 'tomoe':
+ mai.src = '/aobuta/tomoe.webp';
+ mai.alt = 'Tomoe Koga';
+
+ break;
+
+ case 'none':
+ default:
+ mai.style.display = 'none';
+ mai.alt = 'No one';
+
+ break;
}
- break;
- }
- }
+ };
+ };
});
</script>
diff --git a/src/lib/Error/LogInRestricted.svelte b/src/lib/Error/LogInRestricted.svelte
index 07a9adec..54ea5ee1 100644
--- a/src/lib/Error/LogInRestricted.svelte
+++ b/src/lib/Error/LogInRestricted.svelte
@@ -1,14 +1,15 @@
<script>
import Popup from '$lib/Layout/Popup.svelte';
import { env } from '$env/dynamic/public';
+ import localforage from 'localforage';
</script>
<Popup fullscreen locked>
<div class="message">
Please <a
href={`https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`}
- on:click={() => {
- localStorage.setItem(
+ on:click={async () => {
+ await localforage.setItem(
'redirect',
window.location.origin + window.location.pathname + window.location.search
);
diff --git a/src/lib/Landing.svelte b/src/lib/Landing.svelte
index 9986d1b9..f688eacf 100644
--- a/src/lib/Landing.svelte
+++ b/src/lib/Landing.svelte
@@ -4,6 +4,7 @@
import tooltip from './Tooltip/tooltip';
import CompletedAnimeList from './List/Anime/CompletedAnimeList.svelte';
import MangaListTemplate from './List/Manga/MangaListTemplate.svelte';
+ import localforage from 'localforage';
</script>
<div class="example-item card">
@@ -92,8 +93,8 @@
<span class="medium-text">
<a
href={`https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`}
- on:click={() => {
- localStorage.setItem(
+ on:click={async () => {
+ await localforage.setItem(
'redirect',
window.location.origin + window.location.pathname + window.location.search
);
diff --git a/src/lib/List/Anime/AnimeListTemplate.svelte b/src/lib/List/Anime/AnimeListTemplate.svelte
index 08583d7c..99d2e888 100644
--- a/src/lib/List/Anime/AnimeListTemplate.svelte
+++ b/src/lib/List/Anime/AnimeListTemplate.svelte
@@ -13,6 +13,7 @@
import { onMount } from 'svelte';
import subsPlease from '$stores/subsPlease';
import identity from '$stores/identity';
+ import localforage from 'localforage';
export let endTime: number;
export let cleanMedia: (
@@ -35,13 +36,14 @@
let pendingUpdate: number | null = null;
let lastListSize = 8;
- onMount(() => {
+ onMount(async () => {
if (browser) {
- const lastStoredList = localStorage.getItem(
+ const lastStoredList = (await localforage.getItem(
`last${
notYetReleased ? 'NotYetReleased' : upcoming ? 'Upcoming' : completed ? 'Completed' : ''
}AnimeListLength`
- );
+ )) as string | null;
+
if (lastStoredList) lastListSize = parseInt(lastStoredList);
}
});
diff --git a/src/lib/List/Anime/CleanAnimeList.svelte b/src/lib/List/Anime/CleanAnimeList.svelte
index 22e8f581..a9026d1d 100644
--- a/src/lib/List/Anime/CleanAnimeList.svelte
+++ b/src/lib/List/Anime/CleanAnimeList.svelte
@@ -16,6 +16,7 @@
import CleanGrid from '$lib/List/CleanGrid.svelte';
import CleanList from '../CleanList.svelte';
import stateBin from '$stores/stateBin';
+ import localforage from 'localforage';
export let media: Media[];
export let title: any;
@@ -74,7 +75,7 @@
? media
: media.filter((m) => m.mediaListEntry?.customLists?.[selectedList]);
- onMount(() => {
+ onMount(async () => {
if (dummy) return;
keyCacher = setInterval(
@@ -105,7 +106,7 @@
);
if (browser)
- localStorage.setItem(
+ await localforage.setItem(
`last${
notYetReleased ? 'NotYetReleased' : upcoming ? 'Upcoming' : completed ? 'Completed' : ''
}AnimeListLength`,
diff --git a/src/lib/List/Manga/CleanMangaList.svelte b/src/lib/List/Manga/CleanMangaList.svelte
index eb54df8c..aeb1bc7e 100644
--- a/src/lib/List/Manga/CleanMangaList.svelte
+++ b/src/lib/List/Manga/CleanMangaList.svelte
@@ -14,6 +14,7 @@
import CleanGrid from '../CleanGrid.svelte';
import CleanList from '../CleanList.svelte';
import stateBin from '$stores/stateBin';
+ import localforage from 'localforage';
export let media: Media[];
export let cleanCache: () => void;
@@ -58,11 +59,14 @@
? media
: media.filter((m) => m.mediaListEntry?.customLists?.[selectedList]);
- onMount(() => {
+ onMount(async () => {
serviceStatusResponse = fetch(proxy('https://api.mangadex.org/ping'));
if (browser)
- localStorage.setItem(`last${due ? '' : 'Completed'}MangaListLength`, media.length.toString());
+ await localforage.setItem(
+ `last${due ? '' : 'Completed'}MangaListLength`,
+ media.length.toString()
+ );
});
const increment = (manga: Media) => {
diff --git a/src/lib/List/Manga/MangaListTemplate.svelte b/src/lib/List/Manga/MangaListTemplate.svelte
index 0b38158b..d7f00616 100644
--- a/src/lib/List/Manga/MangaListTemplate.svelte
+++ b/src/lib/List/Manga/MangaListTemplate.svelte
@@ -20,6 +20,7 @@
import { browser } from '$app/environment';
import identity from '$stores/identity';
import privilegedUser from '$lib/Utility/privilegedUser';
+ import localforage from 'localforage';
export let user: AniListAuthorisation = {
accessToken: '',
@@ -57,7 +58,9 @@
onMount(async () => {
if (browser) {
- const lastStoredList = localStorage.getItem(`last${due ? '' : 'Completed'}MangaListLength`);
+ const lastStoredList = (await localforage.getItem(
+ `last${due ? '' : 'Completed'}MangaListLength`
+ )) as number | null;
if (lastStoredList) lastListSize = parseInt(lastStoredList);
}
diff --git a/src/lib/Settings/Categories/Debug.svelte b/src/lib/Settings/Categories/Debug.svelte
index 8ba6ade9..c21edb44 100644
--- a/src/lib/Settings/Categories/Debug.svelte
+++ b/src/lib/Settings/Categories/Debug.svelte
@@ -13,8 +13,6 @@
const clearCaches = async () => {
if (!browser) return;
- localStorage.removeItem('anime');
- localStorage.removeItem('manga');
await localforage.removeItem('anime');
await localforage.removeItem('manga');
addNotification(
@@ -50,8 +48,8 @@
<p />
<button
- on:click={() => {
- localStorage.clear();
+ on:click={async () => {
+ await localforage.clear();
addNotification(
options({
heading: '<code>localStorage</code> successfully cleared'
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 1dd069a0..d9caca74 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -76,22 +76,22 @@
onMount(async () => {
if (browser) {
- if (localStorage.getItem('redirect')) {
- window.location.href = localStorage.getItem('redirect') ?? '/';
+ if (await localforage.getItem('redirect')) {
+ window.location.href = (await localforage.getItem('redirect')) ?? '/';
- localStorage.removeItem('redirect');
+ await localforage.removeItem('redirect');
}
window.addEventListener('scroll', handleScroll);
- if (localStorage.getItem('commit') !== data.commit) {
- localStorage.removeItem('identity');
- localStorage.removeItem('anime');
- localStorage.removeItem('manga');
+ if ((await localforage.getItem('commit')) !== data.commit) {
+ await localforage.removeItem('identity');
await localforage.removeItem('anime');
await localforage.removeItem('manga');
- localStorage.removeItem('lastPruneTimes');
- localStorage.setItem('commit', data.commit);
+ await localforage.removeItem('anime');
+ await localforage.removeItem('manga');
+ await localforage.removeItem('lastPruneTimes');
+ await localforage.setItem('commit', data.commit);
}
}
@@ -213,9 +213,9 @@
name: $locale().navigation.logOut,
url: '#',
preventDefault: true,
- onClick: () => {
- localStorage.removeItem('identity');
- localStorage.removeItem('commit');
+ onClick: async () => {
+ await localforage.removeItem('identity');
+ await localforage.removeItem('commit');
document.cookie = 'user=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
@@ -235,8 +235,8 @@
<a
class="header-item"
href={`https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`}
- on:click={() => {
- localStorage.setItem(
+ on:click={async () => {
+ await localforage.setItem(
'redirect',
window.location.origin + window.location.pathname + window.location.search
);
diff --git a/src/routes/user/+page.svelte b/src/routes/user/+page.svelte
index 29bd132b..eab089c6 100644
--- a/src/routes/user/+page.svelte
+++ b/src/routes/user/+page.svelte
@@ -7,23 +7,23 @@
import HeadTitle from '$lib/Home/HeadTitle.svelte';
import root from '$lib/Utility/root';
import { page } from '$app/stores';
+ import localforage from 'localforage';
- const user =
- browser && localStorage.getItem('identity')
- ? (JSON.parse(localStorage.getItem('identity') || '') as UserIdentity).name
- : null;
+ onMount(async () => {
+ if (browser) {
+ const user = ((await localforage.getItem('identity')) as UserIdentity).name;
- onMount(() => {
- if (user) {
- if (browser && $page.url.searchParams.get('badges') !== null) {
- goto(root(`/user/${user}/badges`));
+ if (user) {
+ if (browser && $page.url.searchParams.get('badges') !== null) {
+ goto(root(`/user/${user}/badges`));
+ } else {
+ goto(root(`/user/${user}`));
+ }
} else {
- goto(root(`/user/${user}`));
+ goto(
+ `https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`
+ );
}
- } else {
- goto(
- `https://anilist.co/api/v2/oauth/authorize?client_id=${env.PUBLIC_ANILIST_CLIENT_ID}&redirect_uri=${env.PUBLIC_ANILIST_REDIRECT_URI}&response_type=code`
- );
}
});
</script>
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
index 9fca60b2..43beddea 100644
--- a/src/routes/user/[user]/badges/+page.svelte
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -23,6 +23,7 @@
import type { IndexedBadge } from '$lib/User/BadgeWall/badge';
import { graphql } from '$houdini';
import type { Preferences } from '../../../../graphql/user/$types';
+ import localforage from 'localforage';
export let data;
@@ -205,7 +206,7 @@
});
onMount(async () => {
- if (browser && localStorage.getItem('badgeWallNoticeDismissed')) noticeDismissed = true;
+ if (browser && (await localforage.getItem('badgeWallNoticeDismissed'))) noticeDismissed = true;
badger = isId
? {
@@ -573,10 +574,10 @@
of all badges from your Badge Wall.
<p />
<button
- on:click={() => {
+ on:click={async () => {
noticeDismissed = true;
- localStorage.setItem('badgeWallNoticeDismissed', 'true');
+ await localforage.setItem('badgeWallNoticeDismissed', 'true');
}}
>
Dismiss
diff --git a/src/stores/announcementHash.ts b/src/stores/announcementHash.ts
index 0ff57b3b..d14c305e 100644
--- a/src/stores/announcementHash.ts
+++ b/src/stores/announcementHash.ts
@@ -1,12 +1,17 @@
import { browser } from '$app/environment';
import { writable } from 'svelte/store';
+import localforage from 'localforage';
-const announcementHash = writable<number>(
- browser ? parseInt(localStorage.getItem('announcementHash') || '1') : 0
-);
+const announcementHash = writable<number>(1);
-announcementHash.subscribe((value) => {
- if (browser) localStorage.setItem('announcementHash', value.toString());
-});
+if (browser) {
+ localforage.getItem<number>('announcementHash').then((value) => {
+ if (typeof value === 'number') announcementHash.set(value);
+ });
+
+ announcementHash.subscribe((value) => {
+ localforage.setItem('announcementHash', value);
+ });
+}
export default announcementHash;
diff --git a/src/stores/identity.ts b/src/stores/identity.ts
index 2618d744..596c7176 100644
--- a/src/stores/identity.ts
+++ b/src/stores/identity.ts
@@ -1,6 +1,7 @@
import { browser } from '$app/environment';
import type { UserIdentity } from '$lib/Data/AniList/identity';
import { writable } from 'svelte/store';
+import localforage from 'localforage';
export const defaultIdentity: UserIdentity = {
name: '',
@@ -9,22 +10,26 @@ export const defaultIdentity: UserIdentity = {
};
const createStore = () => {
- const { subscribe, set, update } = writable<UserIdentity>(
- JSON.parse(
- browser
- ? (localStorage.getItem('identity') ?? JSON.stringify(defaultIdentity))
- : JSON.stringify(defaultIdentity)
- )
- );
- let state: UserIdentity;
+ const store = writable<UserIdentity>(defaultIdentity);
+ let state: UserIdentity = defaultIdentity;
- subscribe((value) => (state = value));
+ if (browser)
+ localforage.getItem<UserIdentity>('identity').then((value) => {
+ if (value && typeof value === 'object') store.set(value);
+ });
+
+ store.subscribe((value) => {
+ state = value;
+
+ if (browser) localforage.setItem('identity', value);
+ });
return {
- subscribe,
- set,
- update,
- reset: () => set(defaultIdentity),
+ subscribe: store.subscribe,
+ set: store.set,
+ update: store.update,
+ reset: () => store.set(defaultIdentity),
+
get: () => {
const keys = Object.keys(defaultIdentity);
const identityKeys = Object.keys(state);
@@ -32,22 +37,18 @@ const createStore = () => {
for (const key of keys)
if (!identityKeys.includes(key))
- (updatedIdentity[key as keyof UserIdentity] as unknown) =
- defaultIdentity[key as keyof UserIdentity];
+ updatedIdentity[key as keyof UserIdentity] = defaultIdentity[key as keyof UserIdentity];
- if (browser) localStorage.setItem('identity', JSON.stringify(updatedIdentity));
+ if (browser) localforage.setItem('identity', updatedIdentity);
return updatedIdentity;
},
+
setKey: (key: keyof UserIdentity, value: unknown) =>
- update((identity) => ({ ...identity, [key]: value }))
+ store.update((identity) => ({ ...identity, [key]: value }))
};
};
const identity = createStore();
-identity.subscribe((value) => {
- if (browser) localStorage.setItem('identity', JSON.stringify(value));
-});
-
export default identity;
diff --git a/src/stores/lastPruneTimes.ts b/src/stores/lastPruneTimes.ts
index 9c4afc5b..212f2bc9 100644
--- a/src/stores/lastPruneTimes.ts
+++ b/src/stores/lastPruneTimes.ts
@@ -1,5 +1,6 @@
import { browser } from '$app/environment';
import { writable } from 'svelte/store';
+import localforage from 'localforage';
interface LastPruneTimes {
anime: number;
@@ -14,41 +15,42 @@ const defaultTimes: LastPruneTimes = {
};
const createStore = () => {
- const { subscribe, set, update } = writable<LastPruneTimes>(
- JSON.parse(
- browser
- ? (localStorage.getItem('lastPruneTimes') ?? JSON.stringify(defaultTimes))
- : JSON.stringify(defaultTimes)
- )
- );
- let state: LastPruneTimes;
+ const store = writable<LastPruneTimes>(defaultTimes);
+ let state: LastPruneTimes = defaultTimes;
- subscribe((value) => (state = value));
+ if (browser)
+ localforage.getItem<LastPruneTimes>('lastPruneTimes').then((value) => {
+ if (value && Object.keys(value).length === Object.keys(defaultTimes).length) store.set(value);
+ });
+
+ store.subscribe((value) => {
+ state = value;
+
+ if (browser) localforage.setItem('lastPruneTimes', value);
+ });
return {
- subscribe,
- set,
- update,
- reset: () => set(defaultTimes),
+ subscribe: store.subscribe,
+ set: store.set,
+ update: store.update,
+ reset: () => store.set(defaultTimes),
+
get: () => {
const keys = Object.keys(defaultTimes);
- const lastPruneTimesKeys = Object.keys(state);
+ const stateKeys = Object.keys(state);
- if (keys.length !== lastPruneTimesKeys.length) return defaultTimes;
+ if (keys.length !== stateKeys.length) return defaultTimes;
- for (const key of keys) if (!lastPruneTimesKeys.includes(key)) return defaultTimes;
+ for (const key of keys) if (!stateKeys.includes(key)) return defaultTimes;
return state;
},
- setKey: (key: keyof LastPruneTimes, value: unknown) =>
- update((lastPruneTimes) => ({ ...lastPruneTimes, [key]: value }))
+
+ setKey: (key: keyof LastPruneTimes, value: number) =>
+ store.update((times) => ({ ...times, [key]: value }))
};
};
const lastPruneTimes = createStore();
-lastPruneTimes.subscribe((value) => {
- if (browser) localStorage.setItem('lastPruneTimes', JSON.stringify(value));
-});
-
export default lastPruneTimes;
diff --git a/src/stores/settings.ts b/src/stores/settings.ts
index fef0debf..c8ae9c94 100644
--- a/src/stores/settings.ts
+++ b/src/stores/settings.ts
@@ -4,6 +4,7 @@ import { get, writable } from 'svelte/store';
import settingsSyncPulled from './settingsSyncPulled';
import settingsSyncTimes from './settingsSyncTimes';
import identity from './identity';
+import localforage from 'localforage';
const VERSION = '1.0.1';
@@ -135,22 +136,26 @@ const defaultSettings: Settings = {
};
const createStore = () => {
- const { subscribe, set, update } = writable<Settings>(
- JSON.parse(
- browser
- ? (localStorage.getItem('settings') ?? JSON.stringify(defaultSettings))
- : JSON.stringify(defaultSettings)
- )
- );
- let state: Settings;
+ const store = writable<Settings>(defaultSettings);
+ let state: Settings = defaultSettings;
- subscribe((value) => (state = value));
+ if (browser)
+ localforage.getItem<Settings>('settings').then((value) => {
+ if (value && typeof value === 'object') store.set(value);
+ });
+
+ store.subscribe((value) => {
+ state = value;
+
+ if (browser) localforage.setItem('settings', value);
+ });
return {
- subscribe,
- set,
- update,
- reset: () => set(defaultSettings),
+ subscribe: store.subscribe,
+ set: store.set,
+ update: store.update,
+ reset: () => store.set(defaultSettings),
+
get: () => {
const keys = Object.keys(defaultSettings);
const settingsKeys = Object.keys(state);
@@ -158,51 +163,53 @@ const createStore = () => {
for (const key of keys)
if (!settingsKeys.includes(key))
- (updatedSettings[key as keyof Settings] as unknown) =
- defaultSettings[key as keyof Settings];
+ updatedSettings[key as keyof Settings] = defaultSettings[key as keyof Settings];
- if (browser) localStorage.setItem('settings', JSON.stringify(updatedSettings));
+ if (browser) localforage.setItem('settings', updatedSettings);
return updatedSettings;
},
+
setKey: (key: keyof Settings, value: unknown) =>
- update((settings) => ({ ...settings, [key]: value }))
+ store.update((settings) => ({ ...settings, [key]: value }))
};
};
const settings = createStore();
settings.subscribe((value) => {
- if (browser) localStorage.setItem('settings', JSON.stringify(value));
+ if (!browser) return;
- if (value.settingsSync && get(settingsSyncPulled) == true)
+ if (value.settingsSync && get(settingsSyncPulled) === true) {
fetch(root(`/api/configuration?id=${get(identity).id}`)).then((response) => {
if (response.ok)
response.json().then((data) => {
- const isEqualsJson = (object1: Settings, object2: Settings) => {
+ const isEqualsJson = (firstObject: Settings, secondObject: Settings) => {
type AnyObject = { [key: string]: unknown };
return (
- Object.keys(object1).length === Object.keys(object2).length &&
- Object.keys(object1).every(
- (key) =>
- (object1 as unknown as AnyObject)[key] == (object2 as unknown as AnyObject)[key]
+ Object.keys(firstObject).length === Object.keys(secondObject).length &&
+ Object.keys(firstObject).every(
+ (key) => (firstObject as AnyObject)[key] === (secondObject as AnyObject)[key]
)
);
};
- if (data && data.configuration && !isEqualsJson(data.configuration, value)) {
+ if (data?.configuration && !isEqualsJson(data.configuration, value))
fetch(root(`/api/configuration`), {
method: 'PUT',
body: JSON.stringify(value)
}).then((response) => {
if (response.ok) console.log('Pushed local configuration');
- settingsSyncTimes.update((times) => ({ ...times, lastPush: new Date() }));
+ settingsSyncTimes.update((times) => ({
+ ...times,
+ lastPush: new Date()
+ }));
});
- }
});
});
+ }
});
export default settings;
diff --git a/src/stores/stateBin.ts b/src/stores/stateBin.ts
index 74ea510f..082a07dc 100644
--- a/src/stores/stateBin.ts
+++ b/src/stores/stateBin.ts
@@ -1,17 +1,22 @@
import { browser } from '$app/environment';
import { writable, get, type Writable } from 'svelte/store';
+import localforage from 'localforage';
type StateBin = Record<string, unknown>;
const STORAGE_KEY = 'stateBin';
-const initialState = browser ? JSON.parse(localStorage.getItem(STORAGE_KEY) ?? '{}') : {};
-const baseStore = writable<StateBin>(initialState);
+const baseStore = writable<StateBin>({});
-if (browser)
- baseStore.subscribe((val) => {
- localStorage.setItem(STORAGE_KEY, JSON.stringify(val));
+if (browser) {
+ localforage.getItem<StateBin>(STORAGE_KEY).then((value) => {
+ if (value && typeof value === 'object') baseStore.set(value);
});
+ baseStore.subscribe((value) => {
+ localforage.setItem(STORAGE_KEY, value);
+ });
+}
+
const createProxyStore = (store: Writable<StateBin>) => {
return new Proxy(store, {
get(target, prop: string) {