This commit is contained in:
j3d1 2026-07-23 04:41:04 +02:00
parent 7c91661be2
commit 796fef81be
37 changed files with 3404 additions and 108 deletions

View file

@ -7,12 +7,65 @@ import {parseIdentityRecord, serializeIdentityRecord} from "@/identity";
//import sharedStatePlugin from "@/../extras/shared-state-plugin";
//import persistentStatePlugin from "@/../extras/persistent-state-plugin";
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.'
},
]
const parseStoredPreferences = (storageKey) => {
try {
const raw = localStorage.getItem(storageKey)
if (!raw) {
return {}
}
const parsed = JSON.parse(raw)
return parsed && typeof parsed === 'object' ? parsed : {}
} catch (_error) {
return {}
}
}
export default createStore({
state: {
local_loaded: false,
last_load: {},
user: null,
user_profile: null,
token: null,
keypair: null,
remember: false,
@ -31,6 +84,10 @@ export default createStore({
domains: [],
storage_locations: [],
active_workflows: [],
preferenceDefinitions: [],
accountPreferences: {},
devicePreferences: {},
preferencesLoaded: false,
},
mutations: {
setInventoryItems(state, {url, items}) {
@ -69,11 +126,42 @@ export default createStore({
setActiveWorkflows(state, workflows) {
state.active_workflows = workflows;
},
setPreferenceDefinitions(state, definitions) {
state.preferenceDefinitions = definitions;
},
setAccountPreferences(state, preferences) {
state.accountPreferences = preferences;
},
setDevicePreferences(state, preferences) {
state.devicePreferences = preferences;
},
setAccountPreference(state, {key, value}) {
state.accountPreferences = {...state.accountPreferences, [key]: value};
},
setDevicePreference(state, {key, value}) {
state.devicePreferences = {...state.devicePreferences, [key]: value};
},
deleteAccountPreference(state, key) {
const prefs = {...state.accountPreferences};
delete prefs[key];
state.accountPreferences = prefs;
},
deleteDevicePreference(state, key) {
const prefs = {...state.devicePreferences};
delete prefs[key];
state.devicePreferences = prefs;
},
setPreferencesLoaded(state, loaded) {
state.preferencesLoaded = loaded;
},
setUser(state, user) {
state.user = user;
if (state.remember)
localStorage.setItem('user', user);
},
setUserProfile(state, profile) {
state.user_profile = profile;
},
setToken(state, token) {
state.token = token;
if (state.remember)
@ -110,6 +198,7 @@ export default createStore({
},
logout(state) {
state.user = null;
state.user_profile = null;
state.token = null;
state.keypair = null;
localStorage.removeItem('user');
@ -136,6 +225,33 @@ export default createStore({
}
},
actions: {
async loadUserPreferences({state, commit}) {
const accountKey = 'toolshed.preferences.account.' + (state.user || 'anonymous')
const deviceKey = 'toolshed.preferences.device'
commit('setPreferenceDefinitions', defaultPreferenceDefinitions)
commit('setAccountPreferences', parseStoredPreferences(accountKey))
commit('setDevicePreferences', parseStoredPreferences(deviceKey))
commit('setPreferencesLoaded', true)
},
async setAccountPreference({state, commit}, {key, value}) {
commit('setAccountPreference', {key, value})
const accountKey = 'toolshed.preferences.account.' + (state.user || 'anonymous')
localStorage.setItem(accountKey, JSON.stringify(state.accountPreferences))
},
async resetAccountPreference({state, commit}, key) {
commit('deleteAccountPreference', key)
const accountKey = 'toolshed.preferences.account.' + (state.user || 'anonymous')
localStorage.setItem(accountKey, JSON.stringify(state.accountPreferences))
},
async setDevicePreference({state, commit}, {key, value}) {
commit('setDevicePreference', {key, value})
localStorage.setItem('toolshed.preferences.device', JSON.stringify(state.devicePreferences))
},
async resetDevicePreference({state, commit}, key) {
commit('deleteDevicePreference', key)
localStorage.setItem('toolshed.preferences.device', JSON.stringify(state.devicePreferences))
},
async login({commit, dispatch, state, getters}, {username, password, remember}) {
commit('setRemember', remember);
const data = await dispatch('lookupServer', {username}).then(servers => new ServerSet(servers, state.unreachable_neighbors))
@ -146,11 +262,33 @@ export default createStore({
commit('setKey', data.key);
const s = await dispatch('lookupServer', {username}).then(servers => new ServerSet(servers, state.unreachable_neighbors))
commit('setHomeServers', s)
await dispatch('fetchUserProfile', {force: true})
return true;
} else {
return false;
}
},
async fetchUserProfile({state, commit, dispatch, getters}, {force = false} = {}) {
if (!force && state.user_profile && state.last_load.user_profile > Date.now() - 1000 * 60) {
return state.user_profile
}
const servers = await dispatch('getHomeServers')
const data = await servers.get(getters.signAuth, '/auth/user/')
commit('setUserProfile', data)
state.last_load.user_profile = Date.now()
return data
},
async updateUserProfilePicture({state, commit, dispatch, getters}, {file = null} = {}) {
const servers = await dispatch('getHomeServers')
const payload = file ? {profile_picture: {data: file.data, mime_type: file.mime_type}} : {profile_picture: null}
const data = await servers.patch(getters.signAuth, '/auth/user/', payload)
commit('setUserProfile', data)
state.last_load.user_profile = Date.now()
if (data.profile_picture) {
state.last_load.files = 0
}
return data
},
async lookupServer({state}, {username}) {
const domain = username.split('@')[1]
const request = '_toolshed-server._tcp.' + domain + '.'
@ -510,5 +648,18 @@ export default createStore({
time: Date.now() - 1000 * 60 * 60 * 24
}]
},
getPreference: (state) => (key, fallbackDefault = null) => {
if (Object.prototype.hasOwnProperty.call(state.devicePreferences, key) && state.devicePreferences[key] !== null) {
return state.devicePreferences[key]
}
if (Object.prototype.hasOwnProperty.call(state.accountPreferences, key) && state.accountPreferences[key] !== null) {
return state.accountPreferences[key]
}
const definition = state.preferenceDefinitions.find((pref) => pref.key === key)
if (definition) {
return definition.default
}
return fallbackDefault
},
}
})