Skip to content
Source
Sign inSign up
Open History to see the last commit

ThemeEditorHost.tsx

91 lines2.7 KB

1import { lazy, Suspense, useSyncExternalStore } from "react";
2​
3import { useTheme } from "../../hooks/useTheme";
4import {
5 getThemeDefinition,
6 subscribeToCustomThemes,
7 type ThemeAppearance,
8 type ThemeDefinition,
9} from "../../themePalette";
10import { stackedThreadToast, toastManager } from "../ui/toast";
11import { useThemeEditorStore } from "./themeEditorStore";
12​
13const ThemeEditorPanel = lazy(() =>
14 import("./ThemeEditorPanel").then((module) => ({ default: module.ThemeEditorPanel })),
15);
16​
17function useThemeDefinition(id: string | null | undefined) {
18 return useSyncExternalStore(
19 subscribeToCustomThemes,
20 () => (id ? (getThemeDefinition(id) ?? null) : null),
21 () => null,
22 );
24​
25export function ThemeEditorHost() {
26 const session = useThemeEditorStore((store) => store.session);
27 const closeThemeEditor = useThemeEditorStore((store) => store.closeThemeEditor);
28 const { theme, setTheme, themeHalves, refreshTheme } = useTheme();
29 const editingTheme = useThemeDefinition(session?.editingThemeId);
30 const seedTheme = useThemeDefinition(session?.seedThemeId);
31​
32 const handleSaved = (
33 savedTheme: ThemeDefinition,
34 { created, mergedAppearance }: { created: boolean; mergedAppearance?: ThemeAppearance },
35 ) => {
36 if (mergedAppearance) {
37 if (!setTheme(savedTheme.id)) {
38 toastManager.add(
39 stackedThreadToast({
40 type: "error",
41 title: "Could not save your theme",
42 description: "Browser storage is unavailable, so the change was not kept.",
43 }),
44 );
45 return false;
46 }
47 return true;
48 }
49 if (!created) {
50 // Reapply the palette without setTheme, which would clear a mix containing the edited theme.
51 const wasActive =
52 getThemeDefinition(theme)?.id === savedTheme.id ||
53 themeHalves?.light === savedTheme.id ||
54 themeHalves?.dark === savedTheme.id;
55 if (wasActive) refreshTheme();
56 return true;
57 }
58​
59 if (!setTheme(savedTheme.id)) {
60 toastManager.add(
61 stackedThreadToast({
62 type: "error",
63 title: "Could not save your theme",
64 description: "Browser storage is unavailable, so the change was not kept.",
65 }),
66 );
67 return false;
68 }
69 return true;
70 };
71​
72 if (!session) return null;
73​
74 return (
75 <Suspense fallback={null}>
76 <ThemeEditorPanel
77 editingTheme={editingTheme}
78 initialAppearance={session.initialAppearance}
79 key={session.id}
80 onOpenChange={(open) => {
81 if (!open) closeThemeEditor();
82 }}
83 onSaved={handleSaved}
84 open
85 restoreTheme={refreshTheme}
86 seedName={session.seedName ?? undefined}
87 seedTheme={seedTheme}
88 />
89 </Suspense>
90 );