diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-06 16:59:54 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-06 16:59:54 +1100 |
| commit | 50fc47e6e387c3b278526ef773badf63913389d6 (patch) | |
| tree | 71be9fa001ce6848e298bdabe400eb9dbd26848c /src/store.ts | |
| parent | 559902e0211a06b349c4c2f50b0882a8d314f8b7 (diff) | |
Add settings modal
Add saving, loading, default vals, and device-detection, to store.ts.
Add setting for hiding minor tick labels.
Diffstat (limited to 'src/store.ts')
| -rw-r--r-- | src/store.ts | 244 |
1 files changed, 200 insertions, 44 deletions
diff --git a/src/store.ts b/src/store.ts index 393e4b8..19a184b 100644 --- a/src/store.ts +++ b/src/store.ts @@ -3,52 +3,208 @@ */ import {defineStore} from 'pinia'; -import {CalDate} from './lib'; +import {HistDate, CalDate} from './lib'; +import {getBreakpoint, Breakpoint, onTouchDevice} from './lib'; + +export type StoreState = { + // Device info + touchDevice: boolean, + breakpoint: Breakpoint, + // Tick display + tickLen: number, //px + largeTickLen: number, + endTickSz: number // Size for start/end ticks + tickLabelHeight: number, + minTickSep: number, // Smallest gap between ticks + minLastTicks: number // When at smallest scale, don't zoom further into less than this many ticks + defaultEndTickOffset: number, // Default fraction of a unit to offset start/end ticks + showMinorTicks: boolean, + // Mainline and event display + mainlineBreadth: number, // Breadth of mainline area (incl ticks and labels) + eventImgSz: number, // Width/height of event images + eventLabelHeight: number, + spacing: number, // Spacing between display edge, events, and mainline area + // User input + scrollRatio: number, // Fraction of timeline length to move by upon scroll + zoomRatio: number, // Ratio of timeline expansion upon zooming out (eg: 1.5) + dragInertia: number, // Multiplied by final-drag-speed (pixels-per-sec) to get extra scroll distance + disableShortcuts: boolean, + // Other feature-specific + showEventCounts: boolean, + searchSuggLimit: number, + ctgs: { // Specifies event categories, and which ones should be visible + event: boolean, + place: boolean, + organism: boolean, + person: boolean, + work: boolean, + discovery: boolean, + }, + // Other + initialStartDate: HistDate, + initialEndDate: HistDate, // Must be later than initialStartDate + color: { + text: string, // CSS color + textDark: string, + bg: string, + bgLight: string, + bgDark: string, + bgLight2: string, + bgDark2: string, + alt: string, + altDark: string, + altDark2: string, + altBg: string, + bgAlt: string, + bgAltDark: string, + }, + borderRadius: number, // px + transitionDuration: number, // ms +}; +function getDefaultState(): StoreState { + const breakpoint = getBreakpoint(); + const color = { + text: '#fafaf9', // stone-50 + textDark: '#a8a29e', // stone-400 + bg: '#292524', // stone-800 + bgLight: '#44403c', // stone-700 + bgDark: '#1c1917', // stone-900 + bgLight2: '#57534e', // stone-600 + bgDark2: '#0e0c0b', // darker version of stone-900 + alt: '#fde047', // yellow-300 + altDark: '#eab308', // yellow-500 + altDark2: '#ca8a04', // yellow-600 + altBg: '#6a5e2e', + bgAlt: '#f5f5f4', // stone-100 + bgAltDark: '#d6d3d1', // stone-300 + }; + return { + // Device info + touchDevice: onTouchDevice(), + breakpoint: breakpoint, + // Tick display + tickLen: 16, + largeTickLen: 32, + endTickSz: 8, + tickLabelHeight: 10, + minTickSep: 30, + minLastTicks: 3, + defaultEndTickOffset: 0.5, + showMinorTicks: true, + // Mainline and event display + mainlineBreadth: 80, + eventImgSz: 100, + eventLabelHeight: 20, + spacing: 10, + // User input + scrollRatio: 0.2, + zoomRatio: 1.5, + dragInertia: 0.1, + disableShortcuts: false, + // Other feature-specific + showEventCounts: true, + searchSuggLimit: 10, + ctgs: { + event: true, + place: true, + organism: true, + person: true, + work: true, + discovery: true, + }, + // Other + initialStartDate: new CalDate(1900, 1, 1), + initialEndDate: new CalDate(2000, 1, 1), + color, + borderRadius: 5, + transitionDuration: 300, + }; +} + +// Gets 'composite keys' which have the form 'key1' or 'key1.key2' (usable to specify properties of store objects) +function getCompositeKeys(state: StoreState){ + const compKeys = []; + for (const key of Object.getOwnPropertyNames(state) as (keyof StoreState)[]){ + if (typeof state[key] != 'object'){ + compKeys.push(key); + } else { + for (const subkey of Object.getOwnPropertyNames(state[key])){ + compKeys.push(`${key}.${subkey}`); + } + } + } + return compKeys; +} +const STORE_COMP_KEYS = getCompositeKeys(getDefaultState()); +// For getting/setting values in store +function getStoreVal(state: StoreState, compKey: string): any { + if (compKey in state){ + return state[compKey as keyof StoreState]; + } + const [s1, s2] = compKey.split('.', 2); + if (s1 in state){ + const key1 = s1 as keyof StoreState; + if (typeof state[key1] == 'object' && s2 in (state[key1] as any)){ + return (state[key1] as any)[s2]; + } + } + return null; +} +function setStoreVal(state: StoreState, compKey: string, val: any): void { + if (compKey in state){ + (state[compKey as keyof StoreState] as any) = val; + return; + } + const [s1, s2] = compKey.split('.', 2); + if (s1 in state){ + const key1 = s1 as keyof StoreState; + if (typeof state[key1] == 'object' && s2 in (state[key1] as any)){ + (state[key1] as any)[s2] = val; + return; + } + } +} +// For loading settings into [initial] store state +function loadFromLocalStorage(state: StoreState){ + for (const key of STORE_COMP_KEYS){ + const item = localStorage.getItem(key) + if (item != null){ + setStoreVal(state, key, JSON.parse(item)); + } + } +} export const useStore = defineStore('store', { state: () => { - const color = { // Note: For scrollbar colors on chrome, edit ./index.css - text: '#fafaf9', // stone-50 - textDark: '#a8a29e', // stone-400 - bg: '#292524', // stone-800 - bgLight: '#44403c', // stone-700 - bgDark: '#1c1917', // stone-900 - bgLight2: '#57534e', // stone-600 - bgDark2: '#0e0c0b', // darker version of stone-900 - alt: '#fde047', // yellow-300 - altDark: '#eab308', // yellow-500 - altDark2: '#ca8a04', // yellow-600 - altBg: '#6a5e2e', - alt2: '#2563eb', // sky-600 - bgAlt: '#f5f5f4', // stone-100 - bgAltDark: '#d6d3d1', // stone-300 - }; - return { - tickLen: 16, - largeTickLen: 32, - endTickSz: 8, // Size for start/end ticks - tickLabelHeight: 10, - minTickSep: 30, // Smallest px separation between ticks - minLastTicks: 3, // When at smallest scale, don't zoom further into less than this many ticks - defaultEndTickOffset: 0.5, // Default fraction of a unit to offset start/end ticks - // - mainlineBreadth: 80, // Breadth of mainline area (including ticks and labels) - eventImgSz: 100, // Width/height of event images - eventLabelHeight: 20, - spacing: 10, // Spacing between display edge, events, and mainline area - // - scrollRatio: 0.2, // Fraction of timeline length to move by upon scroll - zoomRatio: 1.5, // Ratio of timeline expansion upon zooming out - dragInertia: 0.1, // Multiplied by final-drag-speed (pixels-per-sec) to get extra scroll distance - // - initialStartDate: new CalDate(1900, 1, 1), - initialEndDate: new CalDate(2000, 1, 1), - color, - showEventCounts: true, - transitionDuration: 300, - borderRadius: 5, // px - searchSuggLimit: 10, - disableShortcuts: false, - }; + const state = getDefaultState(); + loadFromLocalStorage(state); + return state; + }, + actions: { + reset(): void { + Object.assign(this, getDefaultState()); + }, + resetOne(key: string){ + const val = getStoreVal(this, key); + if (val != null){ + const val2 = getStoreVal(getDefaultState(), key); + if (val != val2){ + setStoreVal(this, key, val2); + } + } + }, + save(key: string){ + if (STORE_COMP_KEYS.includes(key)){ + localStorage.setItem(key, JSON.stringify(getStoreVal(this, key))); + } + }, + load(): void { + loadFromLocalStorage(this); + }, + clear(): void { + for (const key of STORE_COMP_KEYS){ + localStorage.removeItem(key); + } + }, }, }); |
