ultisuite-client/lib/drive/docs-view-settings.ts
R3D347HR4Y 2a7c153748
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
wrap page
2026-06-10 12:48:27 +02:00

204 lines
5.5 KiB
TypeScript

"use client"
import { useCallback, useEffect, useState } from "react"
import {
DEFAULT_PAGE_FORMAT_ID,
type PageFormatId,
} from "@/lib/drive/page-formats"
export type DocsEditorMode = "edit" | "suggest" | "view"
export type DocsCommentsDisplay = "hidden" | "collapsed" | "expanded" | "all"
export type DocsViewSettings = {
pageFormatId: PageFormatId
zoom: number
spellcheck: boolean
chromeCollapsed: boolean
editorMode: DocsEditorMode
commentsDisplay: DocsCommentsDisplay
outlineSidebarExpanded: boolean
showLayout: boolean
showRuler: boolean
showEquationToolbar: boolean
showNonPrintableChars: boolean
}
const STORAGE_KEY = "ultidrive-docs-view-settings"
const DEFAULT_SETTINGS: DocsViewSettings = {
pageFormatId: DEFAULT_PAGE_FORMAT_ID,
zoom: 100,
spellcheck: true,
chromeCollapsed: false,
editorMode: "edit",
commentsDisplay: "expanded",
outlineSidebarExpanded: false,
showLayout: true,
showRuler: true,
showEquationToolbar: false,
showNonPrintableChars: false,
}
const ZOOM_MIN = 50
const ZOOM_MAX = 200
const ZOOM_STEP = 10
export function clampZoom(value: number): number {
return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, Math.round(value / ZOOM_STEP) * ZOOM_STEP))
}
function readSettings(): DocsViewSettings {
if (typeof localStorage === "undefined") return DEFAULT_SETTINGS
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (!raw) return DEFAULT_SETTINGS
const parsed = JSON.parse(raw) as Partial<DocsViewSettings>
return {
pageFormatId: parsed.pageFormatId ?? DEFAULT_PAGE_FORMAT_ID,
zoom: clampZoom(parsed.zoom ?? DEFAULT_SETTINGS.zoom),
spellcheck: parsed.spellcheck ?? DEFAULT_SETTINGS.spellcheck,
chromeCollapsed: parsed.chromeCollapsed ?? DEFAULT_SETTINGS.chromeCollapsed,
editorMode: parsed.editorMode ?? DEFAULT_SETTINGS.editorMode,
commentsDisplay: parsed.commentsDisplay ?? DEFAULT_SETTINGS.commentsDisplay,
outlineSidebarExpanded:
parsed.outlineSidebarExpanded ?? DEFAULT_SETTINGS.outlineSidebarExpanded,
showLayout: parsed.showLayout ?? DEFAULT_SETTINGS.showLayout,
showRuler: parsed.showRuler ?? DEFAULT_SETTINGS.showRuler,
showEquationToolbar:
parsed.showEquationToolbar ?? DEFAULT_SETTINGS.showEquationToolbar,
showNonPrintableChars:
parsed.showNonPrintableChars ?? DEFAULT_SETTINGS.showNonPrintableChars,
}
} catch {
return DEFAULT_SETTINGS
}
}
function writeSettings(settings: DocsViewSettings) {
if (typeof localStorage === "undefined") return
localStorage.setItem(STORAGE_KEY, JSON.stringify(settings))
}
export function useDocsViewSettings() {
const [settings, setSettings] = useState<DocsViewSettings>(DEFAULT_SETTINGS)
useEffect(() => {
setSettings(readSettings())
}, [])
const setPageFormatId = useCallback((pageFormatId: PageFormatId) => {
setSettings((prev) => {
const next = { ...prev, pageFormatId }
writeSettings(next)
return next
})
}, [])
const setZoom = useCallback((zoom: number) => {
setSettings((prev) => {
const next = { ...prev, zoom: clampZoom(zoom) }
writeSettings(next)
return next
})
}, [])
const setSpellcheck = useCallback((spellcheck: boolean) => {
setSettings((prev) => {
const next = { ...prev, spellcheck }
writeSettings(next)
return next
})
}, [])
const toggleSpellcheck = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, spellcheck: !prev.spellcheck }
writeSettings(next)
return next
})
}, [])
const toggleChromeCollapsed = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, chromeCollapsed: !prev.chromeCollapsed }
writeSettings(next)
return next
})
}, [])
const setEditorMode = useCallback((editorMode: DocsEditorMode) => {
setSettings((prev) => {
const next = { ...prev, editorMode }
writeSettings(next)
return next
})
}, [])
const setCommentsDisplay = useCallback((commentsDisplay: DocsCommentsDisplay) => {
setSettings((prev) => {
const next = { ...prev, commentsDisplay }
writeSettings(next)
return next
})
}, [])
const toggleOutlineSidebarExpanded = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, outlineSidebarExpanded: !prev.outlineSidebarExpanded }
writeSettings(next)
return next
})
}, [])
const toggleShowLayout = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, showLayout: !prev.showLayout }
writeSettings(next)
return next
})
}, [])
const toggleShowRuler = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, showRuler: !prev.showRuler }
writeSettings(next)
return next
})
}, [])
const toggleShowEquationToolbar = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, showEquationToolbar: !prev.showEquationToolbar }
writeSettings(next)
return next
})
}, [])
const toggleShowNonPrintableChars = useCallback(() => {
setSettings((prev) => {
const next = { ...prev, showNonPrintableChars: !prev.showNonPrintableChars }
writeSettings(next)
return next
})
}, [])
return {
settings,
setPageFormatId,
setZoom,
setSpellcheck,
toggleSpellcheck,
toggleChromeCollapsed,
setEditorMode,
setCommentsDisplay,
toggleOutlineSidebarExpanded,
toggleShowLayout,
toggleShowRuler,
toggleShowEquationToolbar,
toggleShowNonPrintableChars,
zoomMin: ZOOM_MIN,
zoomMax: ZOOM_MAX,
}
}