-
-
Notifications
You must be signed in to change notification settings - Fork 259
feat: add server-synced user preferences infrastructure (#484) #1189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b14595c
f4cfbea
8102b7c
6108722
7bd9568
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,8 @@ | |
| const { backgroundThemes, selectedBackgroundTheme, setBackgroundTheme } = useBackgroundTheme() | ||
|
|
||
| onPrehydrate(el => { | ||
| const settings = JSON.parse(localStorage.getItem('npmx-settings') || '{}') | ||
| const id = settings.preferredBackgroundTheme | ||
| const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here too we should try/catch the |
||
| const id = preferences.preferredBackgroundTheme | ||
| if (id) { | ||
| const input = el.querySelector<HTMLInputElement>(`input[value="${id}"]`) | ||
| if (input) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { createDefu } from 'defu' | ||
| import { createLocalStorageProvider } from '~/utils/storage' | ||
|
|
||
| const defu = createDefu((object, key, value) => { | ||
| if (Array.isArray(object[key]) && Array.isArray(value)) { | ||
| object[key] = value | ||
| return true | ||
| } | ||
| }) | ||
|
|
||
| export function useLocalStorageHashProvider<T extends object>(key: string, defaultValue: T) { | ||
| const provider = createLocalStorageProvider<T>(key) | ||
| const data = ref<T>(defaultValue) | ||
|
|
||
| onMounted(() => { | ||
| const stored = provider.get() | ||
| if (stored) { | ||
| data.value = defu(stored, defaultValue) | ||
| } | ||
| }) | ||
|
|
||
| function save() { | ||
| provider.set(data.value) | ||
| } | ||
|
|
||
| function reset() { | ||
| data.value = { ...defaultValue } | ||
| provider.remove() | ||
| } | ||
|
|
||
| function update<K extends keyof T>(key: K, value: T[K]) { | ||
| data.value[key] = value | ||
| save() | ||
|
Comment on lines
+11
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent shared default mutations in the storage provider
🛠️ Suggested fix export function useLocalStorageHashProvider<T extends object>(key: string, defaultValue: T) {
const provider = createLocalStorageProvider<T>(key)
- const data = ref<T>(defaultValue)
+ const data = ref<T>(structuredClone(defaultValue))
onMounted(() => {
const stored = provider.get()
if (stored) {
- data.value = defu(stored, defaultValue)
+ data.value = defu(stored, structuredClone(defaultValue))
}
})
function reset() {
- data.value = { ...defaultValue }
+ data.value = structuredClone(defaultValue)
provider.remove()
} |
||
| } | ||
|
|
||
| return { | ||
| data, | ||
| save, | ||
| reset, | ||
| update, | ||
| } | ||
| } | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard JSON.parse in onPrehydrate to prevent crashes.
If
localStorage.getItem('npmx-user-preferences')contains malformed JSON, the parse will throw and break the prehydrate logic. Wrap in try/catch for resilience.🛠️ Suggested fix
onPrehydrate(el => { - const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}') - const id = preferences.accentColorId + let id = null + try { + const preferences = JSON.parse(localStorage.getItem('npmx-user-preferences') || '{}') + id = preferences?.accentColorId + } catch { + // Ignore malformed JSON + } if (id) {As per coding guidelines, "Use error handling patterns consistently".
📝 Committable suggestion