mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(client): add storage service and persist display settings
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import { ref, watch } from 'vue'
|
||||
import { storage } from '@/services/storage'
|
||||
|
||||
export function useDisplaySettings() {
|
||||
const coverSize = ref(storage.get('coverSize', 150))
|
||||
const gridGap = ref(storage.get('gridGap', 16))
|
||||
const viewMode = ref<'grid' | 'list'>(storage.get('viewMode', 'grid'))
|
||||
|
||||
watch(coverSize, (v) => storage.set('coverSize', v))
|
||||
watch(gridGap, (v) => storage.set('gridGap', v))
|
||||
watch(viewMode, (v) => storage.set('viewMode', v))
|
||||
|
||||
return { coverSize, gridGap, viewMode }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
function get<T>(key: string, fallback: T): T {
|
||||
const raw = localStorage.getItem(key)
|
||||
if (raw === null) return fallback
|
||||
try {
|
||||
return JSON.parse(raw) as T
|
||||
} catch {
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
function set<T>(key: string, value: T): void {
|
||||
localStorage.setItem(key, JSON.stringify(value))
|
||||
}
|
||||
|
||||
function remove(key: string): void {
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
|
||||
export const storage = { get, set, remove }
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, watch } from 'vue'
|
||||
import { storage } from '@/services/storage'
|
||||
|
||||
type Theme = 'light' | 'dark'
|
||||
export type Accent = 'neutral' | 'violet' | 'blue' | 'cyan' | 'green' | 'amber' | 'orange' | 'rose'
|
||||
@@ -26,15 +27,14 @@ const ACCENT_IDS = ACCENT_OPTIONS.map((a) => a.id)
|
||||
const RADIUS_IDS = RADIUS_OPTIONS.map((r) => r.id)
|
||||
|
||||
export const useThemeStore = defineStore('theme', () => {
|
||||
const storedTheme = localStorage.getItem('theme') as Theme | null
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
const theme = ref<Theme>(storedTheme ?? (prefersDark ? 'dark' : 'light'))
|
||||
const theme = ref<Theme>(storage.get<Theme>('theme', prefersDark ? 'dark' : 'light'))
|
||||
|
||||
const storedAccent = localStorage.getItem('accent') as Accent | null
|
||||
const accent = ref<Accent>(storedAccent && ACCENT_IDS.includes(storedAccent) ? storedAccent : 'neutral')
|
||||
const storedAccent = storage.get<Accent>('accent', 'neutral')
|
||||
const accent = ref<Accent>(ACCENT_IDS.includes(storedAccent) ? storedAccent : 'neutral')
|
||||
|
||||
const storedRadius = localStorage.getItem('radius') as Radius | null
|
||||
const radius = ref<Radius>(storedRadius && RADIUS_IDS.includes(storedRadius) ? storedRadius : 'default')
|
||||
const storedRadius = storage.get<Radius>('radius', 'default')
|
||||
const radius = ref<Radius>(RADIUS_IDS.includes(storedRadius) ? storedRadius : 'default')
|
||||
|
||||
function applyTheme(t: Theme) {
|
||||
document.documentElement.classList.toggle('dark', t === 'dark')
|
||||
@@ -66,7 +66,7 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
theme,
|
||||
(t) => {
|
||||
applyTheme(t)
|
||||
localStorage.setItem('theme', t)
|
||||
storage.set('theme', t)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
@@ -74,7 +74,7 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
accent,
|
||||
(a) => {
|
||||
applyAccent(a)
|
||||
localStorage.setItem('accent', a)
|
||||
storage.set('accent', a)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
@@ -82,7 +82,7 @@ export const useThemeStore = defineStore('theme', () => {
|
||||
radius,
|
||||
(r) => {
|
||||
applyRadius(r)
|
||||
localStorage.setItem('radius', r)
|
||||
storage.set('radius', r)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
@@ -5,10 +5,9 @@ import AppHeader from '@/components/AppHeader.vue'
|
||||
import AppSidebar from '@/components/AppSidebar.vue'
|
||||
import { SidebarProvider, SidebarInset } from '@/components/ui/sidebar'
|
||||
import { useBooks } from '@/features/book/composables/useBooks'
|
||||
import { useDisplaySettings } from '@/composables/useDisplaySettings'
|
||||
|
||||
const coverSize = ref(150)
|
||||
const gridGap = ref(16)
|
||||
const viewMode = ref<'grid' | 'list'>('grid')
|
||||
const { coverSize, gridGap, viewMode } = useDisplaySettings()
|
||||
const libraryId = ref<number | null>(null)
|
||||
|
||||
async function loadLibrary() {
|
||||
|
||||
Reference in New Issue
Block a user