| 1 | import { app } from "../lib/bridge"; |
| 2 | import { clearLegacyLangPref, normalizeLangPref, readLegacyLangPref } from "../lib/i18n"; |
| 3 | import { clearLegacyThemePreference, normalizeThemePreference, normalizeThemeStyleForTheme, readLegacyThemePreference } from "../lib/theme"; |
| 4 | import { applyConfiguredBaseAppearance, applyThemePack, clearThemePack } from "../lib/themePack"; |
| 5 | import { applyTerminalThemePreference } from "../lib/terminalTheme"; |
| 6 | import { applyConversationWidth } from "../lib/conversationWidth"; |
| 7 | import { hydrateReasoningDisplayMode } from "../lib/reasoningDisplayPreference"; |
| 8 | import { hydrateSessionExperience } from "../lib/sessionExperience"; |
| 9 | import { loadBotRuntimeStatus } from "./botRuntimeAdapter"; |
| 10 | import type { CommandAuthority } from "../lib/commandOutcome"; |
| 11 | import type { BotRuntimeStatusView, DesktopStartupSettingsView, SettingsView } from "../lib/types"; |
| 12 | |
| 13 | export type DesktopPreferencesSnapshot = DesktopStartupSettingsView | SettingsView; |
| 14 | export function applyPreferencesAppearance(settings: DesktopPreferencesSnapshot) { |
| 15 | const theme = normalizeThemePreference(settings.desktopTheme); |
| 16 | applyConfiguredBaseAppearance(theme, normalizeThemeStyleForTheme(settings.desktopThemeStyle, theme)); |
| 17 | applyTerminalThemePreference(settings.desktopTerminalTheme); |
| 18 | applyConversationWidth(settings.conversationWidth); |
| 19 | hydrateSessionExperience(settings.sessionExperience); |
| 20 | hydrateReasoningDisplayMode(settings.sessionExperience === "deep" ? "expanded" : "auto", settings.sessionExperience === "deep"); |
| 21 | return normalizeLangPref(settings.desktopLanguage); |
| 22 | } |
| 23 | type Input = { |
| 24 | provided?: DesktopPreferencesSnapshot | null; |
| 25 | loadTheme: boolean; |
| 26 | publish: (settings: DesktopPreferencesSnapshot, runtime: BotRuntimeStatusView | null) => void; |
| 27 | }; |
| 28 | |
| 29 | /** Every async boundary is fenced before publishing preferences or theme DOM. */ |
| 30 | export async function synchronizeDesktopPreferences(input: Input, authority: CommandAuthority) { |
| 31 | authority.checkpoint(); |
| 32 | const language = readLegacyLangPref(); |
| 33 | const theme = readLegacyThemePreference(); |
| 34 | if (language || theme.hasValue) { |
| 35 | await app.MigrateDesktopPreferences(language, theme.theme, theme.style); |
| 36 | authority.checkpoint(); |
| 37 | clearLegacyLangPref(); |
| 38 | clearLegacyThemePreference(); |
| 39 | } |
| 40 | const [settings, runtime] = await Promise.all([ |
| 41 | input.provided ?? app.DesktopStartupSettings(), loadBotRuntimeStatus(), |
| 42 | ]); |
| 43 | authority.checkpoint(); |
| 44 | input.publish(settings, runtime); |
| 45 | if (!input.loadTheme) return; |
| 46 | try { |
| 47 | const { loadThemeExperience, applyExperienceToDOM } = await import("../lib/themeExperience"); |
| 48 | authority.checkpoint(); |
| 49 | const experience = await loadThemeExperience(); |
| 50 | authority.checkpoint(); |
| 51 | applyExperienceToDOM(experience); |
| 52 | } catch { |
| 53 | authority.checkpoint(); |
| 54 | try { |
| 55 | const active = await app.GetActiveThemePack(); |
| 56 | authority.checkpoint(); |
| 57 | if (active?.pack) applyThemePack(active.pack); |
| 58 | else clearThemePack(); |
| 59 | } catch { |
| 60 | authority.checkpoint(); |
| 61 | clearThemePack(); |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 |