import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import {nodesSettings} from "./config/nodesSettings"; import { networkSettings } from './config/networkSettings'; import {appearanceSettings} from "./config/appearanceSettings"; type SettingValue = any; type SettingsDictionary = Record; export type Setting = { readonly id: string; readonly type: 'boolean' | 'select' | 'text' | 'number' | 'button' | 'hidden'; readonly label: string; readonly defaultValue: any; value?: string; readonly min?: number; readonly max?: number; readonly options?: any; readonly sectionId: string; readonly required?: boolean; readonly action?: () => void; }; type SettingsState = { settingsConfig: Setting[]; settingsValues: SettingsDictionary; activeSection: string | null; pendingChanges: SettingsDictionary; setActiveSection: (sectionId: string | null) => void; updateSetting: (id: string, value: any) => void; initializeSettings: () => void; getSetting: (id: string) => Setting & { currentValue: any }; resetSettings: () => void; applyChanges: () => void; discardChanges: () => void; getSettingValue: (id: string) => T; getNumberSetting: (id: string, fallback?: number) => number; }; const defaultSettings: Setting[] = [ ...nodesSettings, ...networkSettings, ...appearanceSettings, ]; export const useSettingsStore = create()( persist( (set, get) => ({ settingsConfig: defaultSettings, settingsValues: {}, activeSection: null, pendingChanges: {}, setActiveSection: (sectionId) => set({ activeSection: sectionId }), updateSetting: (id, value) => set((state) => ({ pendingChanges: { ...state.pendingChanges, [id]: value } })), applyChanges: () => set((state) => ({ settingsValues: { ...state.settingsValues, ...state.pendingChanges }, pendingChanges: {} })), discardChanges: () => set({ pendingChanges: {} }), initializeSettings: () => { const { settingsValues, settingsConfig } = get(); const newValues = { ...settingsValues }; settingsConfig.forEach(setting => { if (newValues[setting.id] === undefined) { newValues[setting.id] = setting.defaultValue; } }); set({ settingsValues: newValues }); }, getSetting: (id) => { const state = get(); const setting = state.settingsConfig.find(s => s.id === id); if (!setting) throw new Error(`Setting ${id} not found`); const hasPendingChange = Object.prototype.hasOwnProperty.call(state.pendingChanges, id); const hasSavedValue = Object.prototype.hasOwnProperty.call(state.settingsValues, id); const currentValue = hasPendingChange ? state.pendingChanges[id] : hasSavedValue ? state.settingsValues[id] : setting.defaultValue; return { ...setting, currentValue }; }, getSettingValue: (id: string) => { const state = get(); return state.settingsValues[id] ?? state.settingsConfig.find(s => s.id === id)?.defaultValue; }, getNumberSetting: (id: string, fallback = 0) => { const value = get().getSettingValue(id); return Number(value) || fallback; }, resetSettings: () => set({ settingsValues: {}, pendingChanges: {} }), }), { name: 'app-settings', partialize: (state) => ({ settingsValues: state.settingsValues }), onRehydrateStorage: () => (state) => { state?.initializeSettings(); } } ) );