Introduce the Electron desktop app with a split app/chat/settings structure and shared nanostore state so UI areas own their state instead of routing it through the root.
58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
export function storedBoolean(key: string, fallback: boolean): boolean {
|
|
try {
|
|
const value = window.localStorage.getItem(key)
|
|
|
|
return value === null ? fallback : value === 'true'
|
|
} catch {
|
|
return fallback
|
|
}
|
|
}
|
|
|
|
export function persistBoolean(key: string, value: boolean) {
|
|
try {
|
|
window.localStorage.setItem(key, String(value))
|
|
} catch {
|
|
// Local storage is a convenience; ignore failures in restricted contexts.
|
|
}
|
|
}
|
|
|
|
export function storedStringArray(key: string): string[] {
|
|
try {
|
|
const value = window.localStorage.getItem(key)
|
|
|
|
if (!value) {
|
|
return []
|
|
}
|
|
|
|
const parsed = JSON.parse(value)
|
|
|
|
if (!Array.isArray(parsed)) {
|
|
return []
|
|
}
|
|
|
|
return parsed.filter((item): item is string => typeof item === 'string' && item.length > 0)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
export function persistStringArray(key: string, value: string[]) {
|
|
try {
|
|
window.localStorage.setItem(key, JSON.stringify(value))
|
|
} catch {
|
|
// Pins are a local preference; restricted storage should not break chat.
|
|
}
|
|
}
|
|
|
|
export function arraysEqual(left: string[], right: string[]) {
|
|
return left.length === right.length && left.every((item, index) => item === right[index])
|
|
}
|
|
|
|
export function insertUniqueId(ids: string[], id: string, index: number) {
|
|
const next = ids.filter(item => item !== id)
|
|
const boundedIndex = Math.min(Math.max(index, 0), next.length)
|
|
next.splice(boundedIndex, 0, id)
|
|
|
|
return next
|
|
}
|