forked from nexu-io/html-anything
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpage.tsx
More file actions
121 lines (114 loc) · 4.16 KB
/
Copy pathpage.tsx
File metadata and controls
121 lines (114 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"use client";
import { useEffect, useRef, useState } from "react";
import { Toolbar } from "@/components/toolbar";
import { EditorPane } from "@/components/editor-pane";
import { PreviewPane } from "@/components/preview-pane";
import { TasksSidebar } from "@/components/tasks-sidebar";
import { HistoryPane } from "@/components/history-pane";
import { WelcomeModal } from "@/components/welcome-modal";
import { SettingsModal, type SectionId } from "@/components/settings-modal";
import { ConvertChip } from "@/components/convert-chip";
import { useStore, type AgentInfo } from "@/lib/store";
export default function Home() {
const iframeRef = useRef<HTMLIFrameElement | null>(null);
const welcomeAck = useStore((s) => s.welcomeAck);
const selectedAgent = useStore((s) => s.selectedAgent);
const setAgents = useStore((s) => s.setAgents);
const locale = useStore((s) => s.locale);
const layoutMode = useStore((s) => s.layoutMode);
const [welcomeOpen, setWelcomeOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [settingsInitialSection, setSettingsInitialSection] = useState<
SectionId | undefined
>(undefined);
const [deployConfigRev, setDeployConfigRev] = useState(0);
const [hydrated, setHydrated] = useState(false);
useEffect(() => {
setHydrated(true);
}, []);
// Detect agents on mount so the toolbar's agent chip can resolve the
// persisted `selectedAgent` to a label without waiting for the user to
// open Settings or Welcome. Without this, after a hard reload the chip
// briefly (or permanently) shows "Select agent" even though selection
// is intact in localStorage.
useEffect(() => {
if (!hydrated) return;
let cancelled = false;
(async () => {
try {
const res = await fetch("/api/agents", { cache: "no-store" });
if (!res.ok) return;
const data = (await res.json()) as { agents: AgentInfo[] };
if (!cancelled) setAgents(data.agents);
} catch {
// Settings / Welcome modals will retry on open.
}
})();
return () => {
cancelled = true;
};
}, [hydrated, setAgents]);
// Keep <html lang="…"> in sync with the user's locale so screen readers
// and browser features (autotranslate, hyphenation) pick the right language.
useEffect(() => {
if (typeof document !== "undefined") {
document.documentElement.setAttribute("lang", locale);
}
}, [locale]);
useEffect(() => {
if (!hydrated) return;
if (!welcomeAck || !selectedAgent) setWelcomeOpen(true);
}, [hydrated, welcomeAck, selectedAgent]);
return (
<main className="relative flex h-screen flex-col">
<Toolbar
iframeRef={iframeRef}
onOpenAgentPicker={() => setSettingsOpen(true)}
onOpenSettings={() => setSettingsOpen(true)}
onRequestConfigureDeploy={() => {
setSettingsInitialSection("deploy");
setSettingsOpen(true);
}}
deployConfigRev={deployConfigRev}
/>
<div
className="flex flex-1 min-h-0"
style={{ borderTop: "1px solid var(--line-faint)" }}
>
<TasksSidebar />
<HistoryPane />
<div className="relative flex flex-1 min-w-0">
{layoutMode !== "preview" && (
<section
className="flex min-w-0 flex-1 basis-0 flex-col"
style={
layoutMode === "split"
? { borderRight: "1px solid var(--line-faint)" }
: undefined
}
>
<EditorPane />
</section>
)}
{layoutMode !== "editor" && (
<section className="flex min-w-0 flex-1 basis-0 flex-col">
<PreviewPane iframeRef={iframeRef} />
</section>
)}
<ConvertChip />
</div>
</div>
{welcomeOpen && <WelcomeModal onClose={() => setWelcomeOpen(false)} />}
{settingsOpen && (
<SettingsModal
initialSection={settingsInitialSection}
onClose={() => {
setSettingsOpen(false);
setSettingsInitialSection(undefined);
setDeployConfigRev((r) => r + 1);
}}
/>
)}
</main>
);
}