Updates channel prefixes, log messages, comments, and configuration values across daemon, mcp-server, and related packages to complete the rebrand from gsd to sf-run naming. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
"use client"
|
|
|
|
import { useState, useEffect, useCallback } from "react"
|
|
|
|
const STORAGE_KEY = "sf-editor-font-size"
|
|
const DEFAULT_SIZE = 14
|
|
const CHANGE_EVENT = "editor-font-size-changed"
|
|
|
|
/**
|
|
* Persists editor font size to localStorage and syncs across components/tabs.
|
|
*
|
|
* Observability:
|
|
* - `localStorage.getItem('sf-editor-font-size')` → current persisted value
|
|
* - Window event `editor-font-size-changed` fires on every local change
|
|
* - `storage` events sync across tabs
|
|
*/
|
|
export function useEditorFontSize(): [number, (size: number) => void] {
|
|
const [fontSize, setFontSizeState] = useState<number>(() => {
|
|
if (typeof window === "undefined") return DEFAULT_SIZE
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY)
|
|
if (stored) {
|
|
const parsed = Number(stored)
|
|
if (Number.isFinite(parsed) && parsed >= 8 && parsed <= 24) return parsed
|
|
}
|
|
} catch {
|
|
// localStorage may be unavailable
|
|
}
|
|
return DEFAULT_SIZE
|
|
})
|
|
|
|
const setFontSize = useCallback((size: number) => {
|
|
const clamped = Math.max(8, Math.min(24, Math.round(size)))
|
|
setFontSizeState(clamped)
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, String(clamped))
|
|
} catch {
|
|
// localStorage may be unavailable
|
|
}
|
|
// Notify other hook instances within the same tab
|
|
window.dispatchEvent(new CustomEvent(CHANGE_EVENT, { detail: clamped }))
|
|
}, [])
|
|
|
|
// Sync from other tabs via storage event
|
|
useEffect(() => {
|
|
const handleStorage = (e: StorageEvent) => {
|
|
if (e.key !== STORAGE_KEY) return
|
|
const parsed = Number(e.newValue)
|
|
if (Number.isFinite(parsed) && parsed >= 8 && parsed <= 24) {
|
|
setFontSizeState(parsed)
|
|
}
|
|
}
|
|
window.addEventListener("storage", handleStorage)
|
|
return () => window.removeEventListener("storage", handleStorage)
|
|
}, [])
|
|
|
|
// Sync from other hook instances in the same tab via custom event
|
|
useEffect(() => {
|
|
const handleChange = (e: Event) => {
|
|
const detail = (e as CustomEvent<number>).detail
|
|
if (Number.isFinite(detail) && detail >= 8 && detail <= 24) {
|
|
setFontSizeState(detail)
|
|
}
|
|
}
|
|
window.addEventListener(CHANGE_EVENT, handleChange)
|
|
return () => window.removeEventListener(CHANGE_EVENT, handleChange)
|
|
}, [])
|
|
|
|
return [fontSize, setFontSize]
|
|
}
|