refactor(ui): keep bootstrap config in global cache
This commit is contained in:
@@ -4,7 +4,6 @@ import { serverEvents } from "./server-events"
|
|||||||
import { getLogger } from "./logger"
|
import { getLogger } from "./logger"
|
||||||
|
|
||||||
const log = getLogger("actions")
|
const log = getLogger("actions")
|
||||||
const UI_CONFIG_CACHE_KEY = "codenomad:config-owner:ui"
|
|
||||||
|
|
||||||
export type OwnerBucket = Record<string, any>
|
export type OwnerBucket = Record<string, any>
|
||||||
|
|
||||||
@@ -58,23 +57,6 @@ export class ServerStorage {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
readCachedConfigOwner(owner: string): OwnerBucket | undefined {
|
|
||||||
if (owner !== "ui" || typeof window === "undefined" || !window.localStorage) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const raw = window.localStorage.getItem(UI_CONFIG_CACHE_KEY)
|
|
||||||
if (!raw) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
const parsed = JSON.parse(raw) as OwnerBucket
|
|
||||||
return parsed && typeof parsed === "object" ? parsed : undefined
|
|
||||||
} catch {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadConfigOwner(owner: string): Promise<OwnerBucket> {
|
async loadConfigOwner(owner: string): Promise<OwnerBucket> {
|
||||||
const cached = this.configOwnerCache.get(owner)
|
const cached = this.configOwnerCache.get(owner)
|
||||||
if (cached) return cached
|
if (cached) return cached
|
||||||
@@ -236,9 +218,6 @@ export class ServerStorage {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.set(owner, value)
|
cache.set(owner, value)
|
||||||
if (kind === "config" && owner === "ui") {
|
|
||||||
this.persistUiConfigCache(value)
|
|
||||||
}
|
|
||||||
const bucket = listeners.get(owner)
|
const bucket = listeners.get(owner)
|
||||||
if (!bucket) return
|
if (!bucket) return
|
||||||
for (const listener of bucket) {
|
for (const listener of bucket) {
|
||||||
@@ -246,18 +225,6 @@ export class ServerStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private persistUiConfigCache(value: OwnerBucket) {
|
|
||||||
if (typeof window === "undefined" || !window.localStorage) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem(UI_CONFIG_CACHE_KEY, JSON.stringify(value))
|
|
||||||
} catch {
|
|
||||||
/* noop */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private normalizeInstanceData(data?: InstanceData | null): InstanceData {
|
private normalizeInstanceData(data?: InstanceData | null): InstanceData {
|
||||||
const source = data ?? DEFAULT_INSTANCE_DATA
|
const source = data ?? DEFAULT_INSTANCE_DATA
|
||||||
const messageHistory = Array.isArray(source.messageHistory) ? [...source.messageHistory] : []
|
const messageHistory = Array.isArray(source.messageHistory) ? [...source.messageHistory] : []
|
||||||
|
|||||||
28
packages/ui/src/lib/ui-config-bootstrap-sync.tsx
Normal file
28
packages/ui/src/lib/ui-config-bootstrap-sync.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { createEffect } from "solid-js"
|
||||||
|
import { useGlobalCache } from "./hooks/use-global-cache"
|
||||||
|
import { useConfig } from "../stores/preferences"
|
||||||
|
import type { UiBootstrapConfig } from "./ui-config-bootstrap"
|
||||||
|
|
||||||
|
export function UiConfigBootstrapSync() {
|
||||||
|
const { isLoaded, preferences, themePreference } = useConfig()
|
||||||
|
const cache = useGlobalCache({
|
||||||
|
scope: "ui-bootstrap",
|
||||||
|
cacheId: "ui-config",
|
||||||
|
version: "1",
|
||||||
|
})
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (!isLoaded()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const next: UiBootstrapConfig = {
|
||||||
|
theme: themePreference(),
|
||||||
|
locale: preferences().locale,
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.set(next)
|
||||||
|
})
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
20
packages/ui/src/lib/ui-config-bootstrap.ts
Normal file
20
packages/ui/src/lib/ui-config-bootstrap.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getCacheEntry } from "./global-cache"
|
||||||
|
|
||||||
|
export interface UiBootstrapConfig {
|
||||||
|
theme?: "light" | "dark" | "system"
|
||||||
|
locale?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const UI_BOOTSTRAP_CACHE_ENTRY = {
|
||||||
|
scope: "ui-bootstrap",
|
||||||
|
cacheId: "ui-config",
|
||||||
|
version: "1",
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export function readUiBootstrapConfig(): UiBootstrapConfig {
|
||||||
|
return getCacheEntry<UiBootstrapConfig>(UI_BOOTSTRAP_CACHE_ENTRY) ?? {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUiBootstrapCacheEntry() {
|
||||||
|
return UI_BOOTSTRAP_CACHE_ENTRY
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ import { InstanceConfigProvider } from "./stores/instance-config"
|
|||||||
import { runtimeEnv } from "./lib/runtime-env"
|
import { runtimeEnv } from "./lib/runtime-env"
|
||||||
import { I18nProvider, preloadLocaleMessages } from "./lib/i18n"
|
import { I18nProvider, preloadLocaleMessages } from "./lib/i18n"
|
||||||
import { storage } from "./lib/storage"
|
import { storage } from "./lib/storage"
|
||||||
|
import { readUiBootstrapConfig } from "./lib/ui-config-bootstrap"
|
||||||
|
import { UiConfigBootstrapSync } from "./lib/ui-config-bootstrap-sync"
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
import "@git-diff-view/solid/styles/diff-view-pure.css"
|
import "@git-diff-view/solid/styles/diff-view-pure.css"
|
||||||
|
|
||||||
@@ -29,14 +31,26 @@ async function bootstrap() {
|
|||||||
// (and then refine once persisted config loads).
|
// (and then refine once persisted config loads).
|
||||||
document.documentElement.removeAttribute("data-theme")
|
document.documentElement.removeAttribute("data-theme")
|
||||||
|
|
||||||
const cachedUiConfig = storage.readCachedConfigOwner("ui")
|
const cachedUiConfig = readUiBootstrapConfig()
|
||||||
const theme =
|
let theme = cachedUiConfig.theme
|
||||||
cachedUiConfig?.theme === "light" || cachedUiConfig?.theme === "dark" || cachedUiConfig?.theme === "system"
|
let locale = cachedUiConfig.locale
|
||||||
? cachedUiConfig.theme
|
|
||||||
: "system"
|
|
||||||
const locale = typeof cachedUiConfig?.settings?.locale === "string" ? cachedUiConfig.settings.locale : undefined
|
|
||||||
|
|
||||||
if (theme === "system") {
|
if (theme === undefined || locale === undefined) {
|
||||||
|
try {
|
||||||
|
const uiConfig = await storage.loadConfigOwner("ui")
|
||||||
|
if (theme === undefined) {
|
||||||
|
const nextTheme = (uiConfig as any)?.theme
|
||||||
|
theme = nextTheme === "light" || nextTheme === "dark" || nextTheme === "system" ? nextTheme : undefined
|
||||||
|
}
|
||||||
|
if (locale === undefined) {
|
||||||
|
locale = typeof (uiConfig as any)?.settings?.locale === "string" ? (uiConfig as any).settings.locale : undefined
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// If config fails to load, fall back to CSS defaults.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!theme || theme === "system") {
|
||||||
document.documentElement.removeAttribute("data-theme")
|
document.documentElement.removeAttribute("data-theme")
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.setAttribute("data-theme", theme)
|
document.documentElement.setAttribute("data-theme", theme)
|
||||||
@@ -48,6 +62,7 @@ async function bootstrap() {
|
|||||||
render(
|
render(
|
||||||
() => (
|
() => (
|
||||||
<ConfigProvider>
|
<ConfigProvider>
|
||||||
|
<UiConfigBootstrapSync />
|
||||||
<InstanceConfigProvider>
|
<InstanceConfigProvider>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user