/*
* Copyright 2025 The Ray Optics Simulation authors and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ref, computed, onMounted } from 'vue'
import { jsonEditorService } from '../services/jsonEditor'
import { app } from '../services/app.js'
// Define default preferences and their callbacks
const PREFERENCES_DEFAULTS = {
autoSyncUrl: false,
showJsonEditor: false,
showStatus: false,
help: true,
}
// Callbacks for preference changes
const PREFERENCES_CALLBACKS = {
help: (value) => {
window.popoversEnabled = value
},
autoSyncUrl: (value) => {
if (!app.autoSyncUrl && value) {
app.autoSyncUrl = value
app.syncUrl()
}
app.autoSyncUrl = value
},
showJsonEditor: (value) => {
if (value) {
// Initialize JSON editor
jsonEditorService.initialize()
} else {
// Clean up JSON editor
jsonEditorService.cleanup()
}
}
}
// Create a single instance of the store
let storeInstance = null
/**
* Create a Vue store for application preferences that persist to localStorage
*
* @returns {Object} A Vue store for application preferences
*/
export const usePreferencesStore = () => {
if (storeInstance) return storeInstance
// Create refs for all preferences
const refs = Object.fromEntries(
Object.entries(PREFERENCES_DEFAULTS).map(([key]) => [
`_${key}`,
ref((() => {
const storedValue = localStorage.getItem(`rayOptics${key.charAt(0).toUpperCase()}${key.slice(1)}`)
if (storedValue === null) return PREFERENCES_DEFAULTS[key]
if (storedValue === "on") return true
if (storedValue === "off") return false
try {
return JSON.parse(storedValue)
} catch {
return PREFERENCES_DEFAULTS[key]
}
})())
])
)
// Create computed properties for all preferences
const computedProps = Object.fromEntries(
Object.keys(PREFERENCES_DEFAULTS).map(key => [
key,
computed({
get: () => refs[`_${key}`].value,
set: (newValue) => {
refs[`_${key}`].value = newValue
localStorage.setItem(
`rayOptics${key.charAt(0).toUpperCase()}${key.slice(1)}`,
newValue ? "on" : "off"
)
PREFERENCES_CALLBACKS[key]?.(newValue)
}
})
])
)
// Set up listeners and trigger initial callbacks
onMounted(() => {
// Trigger callbacks for initial values
Object.keys(PREFERENCES_DEFAULTS).forEach(key => {
PREFERENCES_CALLBACKS[key]?.(refs[`_${key}`].value)
})
})
storeInstance = {
...computedProps
}
return storeInstance
}