stash
This commit is contained in:
parent
18a3e40435
commit
15dad8e3be
6 changed files with 130 additions and 153 deletions
89
frontend/src/preferences.js
Normal file
89
frontend/src/preferences.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// Preference schema catalog, device/account resolution, and device-local (localStorage)
|
||||
// persistence. See docs/implementation.md#preferences for account vs device precedence.
|
||||
|
||||
export const DEVICE_STORAGE_KEY = 'toolshed.preferences.device'
|
||||
|
||||
export const defaultPreferenceDefinitions = [
|
||||
{
|
||||
key: 'ui.compact_mode',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
label: 'Compact mode',
|
||||
description: 'Show denser item rows and reduce spacing in lists.'
|
||||
},
|
||||
{
|
||||
key: 'ui.default_search_scope',
|
||||
type: 'enum',
|
||||
options: ['inventory', 'friends', 'all'],
|
||||
default: 'inventory',
|
||||
label: 'Default search scope',
|
||||
description: 'Choose where the global search starts.'
|
||||
},
|
||||
{
|
||||
key: 'notifications.desktop_enabled',
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
label: 'Desktop notifications',
|
||||
description: 'Enable in-browser notifications for important updates.'
|
||||
},
|
||||
{
|
||||
key: 'files.max_upload_mb',
|
||||
type: 'integer',
|
||||
default: 25,
|
||||
label: 'Default upload size limit (MB)',
|
||||
description: 'Used as a prefill hint in upload dialogs.'
|
||||
},
|
||||
{
|
||||
key: 'ui.experimental_flags',
|
||||
type: 'json',
|
||||
default: {},
|
||||
label: 'Experimental flags',
|
||||
description: 'Optional JSON toggles for feature previews.'
|
||||
},
|
||||
]
|
||||
|
||||
export function loadDevicePreferences(storageKey = DEVICE_STORAGE_KEY) {
|
||||
try {
|
||||
const raw = localStorage.getItem(storageKey)
|
||||
if (!raw) {
|
||||
return {}
|
||||
}
|
||||
const parsed = JSON.parse(raw)
|
||||
return parsed && typeof parsed === 'object' ? parsed : {}
|
||||
} catch (_error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
// Best-effort - a disabled/full localStorage shouldn't break whatever triggered the save (see
|
||||
// e.g. Print.vue's rememberLayout).
|
||||
export function saveDevicePreferences(preferences, storageKey = DEVICE_STORAGE_KEY) {
|
||||
try {
|
||||
localStorage.setItem(storageKey, JSON.stringify(preferences))
|
||||
} catch (error) {
|
||||
console.error('Failed to save device preferences:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Resolution order: device -> account -> schema default -> fallbackDefault.
|
||||
export function resolvePreference(key, {devicePreferences = {}, accountPreferences = {}, definitions = []} = {}, fallbackDefault = null) {
|
||||
if (Object.prototype.hasOwnProperty.call(devicePreferences, key) && devicePreferences[key] !== null) {
|
||||
return devicePreferences[key]
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(accountPreferences, key) && accountPreferences[key] !== null) {
|
||||
return accountPreferences[key]
|
||||
}
|
||||
const definition = definitions.find((pref) => pref.key === key)
|
||||
if (definition) {
|
||||
return definition.default
|
||||
}
|
||||
return fallbackDefault
|
||||
}
|
||||
|
||||
export default {
|
||||
DEVICE_STORAGE_KEY,
|
||||
defaultPreferenceDefinitions,
|
||||
loadDevicePreferences,
|
||||
saveDevicePreferences,
|
||||
resolvePreference,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue