Skip to content

Commit 6e136e6

Browse files
committed
Further simplify editor context by separating states and persist settings
1 parent 6ebb856 commit 6e136e6

13 files changed

+265
-265
lines changed

app/layout.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Metadata } from "next";
22
import localFont from "next/font/local";
33
import "./globals.css";
44
import { WrappedNextUIProvider } from "../components/providers/wrapped-next-ui-provider";
5-
import EditorStatesProvider from "@/components/providers/editor-states-provider";
5+
import EditorContextProvider from "@/components/providers/editor-context-provider";
66
import { Toaster } from "react-hot-toast";
77
import { EditorStates } from "@/lib/types";
88
import "material-icons/iconfont/material-icons.css";
@@ -50,10 +50,10 @@ export default function RootLayout({
5050
>
5151
<CapacitorProvider>
5252
<WrappedNextUIProvider>
53-
<EditorStatesProvider defaultEditorStates={editorStates}>
53+
<EditorContextProvider defaultEditorStates={editorStates}>
5454
<Toaster />
5555
<Nav>{children}</Nav>
56-
</EditorStatesProvider>
56+
</EditorContextProvider>
5757
</WrappedNextUIProvider>
5858
</CapacitorProvider>
5959
</body>

app/page.tsx

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
import CodeEditorView, {
44
CodeEditorViewRef,
55
} from "@/components/views/code-editor-view";
6-
import useEditorStatesContext from "@/lib/hooks/use-editor-states-context";
76
import { useMicVAD, utils } from "@/lib/hooks/use-mic-vad";
87
import { BaseLLM, getModelLLM } from "@/lib/llm/llm";
98
import { BaseSTT, getModelSTT } from "@/lib/stt/stt";
10-
import { useEffect, useRef, useState } from "react";
9+
import { useContext, useEffect, useRef, useState } from "react";
1110
import toast from "react-hot-toast";
1211
import { CodeEditorAgent } from "@/lib/agent/code-editor-agent";
1312
import { BaseTTS, getModelTTS } from "@/lib/tts/tts";
@@ -16,12 +15,13 @@ import { AnimatePresence, motion } from "framer-motion";
1615
import { ViewRef } from "@/lib/types";
1716
import EditorToolbar from "@/components/editor-toolbar";
1817
import { getPlatform } from "@/lib/platforms/platform-checker";
18+
import { EditorContext } from "@/components/providers/editor-context-provider";
1919

2020
export default function Home() {
2121
const [isCanvasReady, setIsCanvasReady] = useState(false);
2222

2323
const viewMap = useRef<Map<string, ViewRef | null>>(new Map());
24-
const { editorStates, updateEditorStates } = useEditorStatesContext();
24+
const editorContext = useContext(EditorContext);
2525

2626
const sttModelRef = useRef<BaseSTT | undefined>(undefined);
2727
const llmModelRef = useRef<BaseLLM | undefined>(undefined);
@@ -39,7 +39,10 @@ export default function Home() {
3939
modelURL: "/vad/silero_vad.onnx",
4040
onSpeechStart: () => {
4141
if (!isProcessing) {
42-
updateEditorStates({ isListening: true });
42+
editorContext?.setEditorStates((prev) => ({
43+
...prev,
44+
isListening: true,
45+
}));
4346
}
4447
},
4548
onSpeechEnd: (audio) => {
@@ -60,7 +63,11 @@ export default function Home() {
6063
);
6164
const codeEditor = viewMap.current.get("1") as CodeEditorViewRef;
6265
const viewDocument = codeEditor?.getViewDocument();
63-
updateEditorStates({ isListening: false, isThinking: true });
66+
editorContext?.setEditorStates((prev) => ({
67+
...prev,
68+
isListening: false,
69+
isThinking: true,
70+
}));
6471
agent
6572
.generateAgentCompletion(
6673
viewDocument?.fileContent || "",
@@ -71,7 +78,10 @@ export default function Home() {
7178
)
7279
.then((result) => {
7380
const changes = agent.getLineChanges(result.text.codeCompletion);
74-
updateEditorStates({ isThinking: false });
81+
editorContext?.setEditorStates((prev) => ({
82+
...prev,
83+
isThinking: false,
84+
}));
7585

7686
// Apply changes
7787
const codeEditor = viewMap.current.get("1") as CodeEditorViewRef;
@@ -82,10 +92,16 @@ export default function Home() {
8292
const audio = new Audio(URL.createObjectURL(result.audio));
8393
audio.onended = () => {
8494
console.log("Audio ended");
85-
updateEditorStates({ isSpeaking: false });
95+
editorContext?.setEditorStates((prev) => ({
96+
...prev,
97+
isSpeaking: false,
98+
}));
8699
setIsProcessing(false);
87100
};
88-
updateEditorStates({ isSpeaking: true });
101+
editorContext?.setEditorStates((prev) => ({
102+
...prev,
103+
isSpeaking: true,
104+
}));
89105
audio.play();
90106
return;
91107
}
@@ -103,17 +119,17 @@ export default function Home() {
103119

104120
// Load models
105121
useEffect(() => {
106-
if (editorStates?.settings) {
122+
if (editorContext?.persistSettings) {
107123
// Load STT
108124
if (
109-
editorStates.settings.sttAPIKey &&
110-
editorStates.settings.sttProvider &&
111-
editorStates.settings.sttModel
125+
editorContext?.persistSettings.sttAPIKey &&
126+
editorContext?.persistSettings.sttProvider &&
127+
editorContext?.persistSettings.sttModel
112128
) {
113129
const model = getModelSTT(
114-
editorStates.settings.sttAPIKey,
115-
editorStates.settings.sttProvider,
116-
editorStates.settings.sttModel,
130+
editorContext?.persistSettings.sttAPIKey,
131+
editorContext?.persistSettings.sttProvider,
132+
editorContext?.persistSettings.sttModel,
117133
);
118134
sttModelRef.current = model;
119135
} else {
@@ -122,14 +138,14 @@ export default function Home() {
122138

123139
// Load LLM
124140
if (
125-
editorStates.settings.llmAPIKey &&
126-
editorStates.settings.llmProvider &&
127-
editorStates.settings.llmModel
141+
editorContext?.persistSettings.llmAPIKey &&
142+
editorContext?.persistSettings.llmProvider &&
143+
editorContext?.persistSettings.llmModel
128144
) {
129145
const model = getModelLLM(
130-
editorStates.settings.llmAPIKey,
131-
editorStates.settings.llmProvider,
132-
editorStates.settings.llmModel,
146+
editorContext?.persistSettings.llmAPIKey,
147+
editorContext?.persistSettings.llmProvider,
148+
editorContext?.persistSettings.llmModel,
133149
0.85,
134150
);
135151
llmModelRef.current = model;
@@ -139,32 +155,32 @@ export default function Home() {
139155

140156
// Load TTS
141157
if (
142-
editorStates.settings.ttsAPIKey &&
143-
editorStates.settings.ttsProvider &&
144-
editorStates.settings.ttsModel &&
145-
editorStates.settings.ttsVoice
158+
editorContext?.persistSettings.ttsAPIKey &&
159+
editorContext?.persistSettings.ttsProvider &&
160+
editorContext?.persistSettings.ttsModel &&
161+
editorContext?.persistSettings.ttsVoice
146162
) {
147163
const model = getModelTTS(
148-
editorStates.settings.ttsAPIKey,
149-
editorStates.settings.ttsProvider,
150-
editorStates.settings.ttsModel,
151-
editorStates.settings.ttsVoice,
164+
editorContext?.persistSettings.ttsAPIKey,
165+
editorContext?.persistSettings.ttsProvider,
166+
editorContext?.persistSettings.ttsModel,
167+
editorContext?.persistSettings.ttsVoice,
152168
);
153169
ttsModelRef.current = model;
154170
} else {
155171
toast.error("Please set TTS Provider, Model and API key in settings");
156172
}
157173
}
158-
}, [editorStates]);
174+
}, [editorContext?.persistSettings]);
159175

160176
// Toggle recording
161177
useEffect(() => {
162-
if (editorStates?.isRecording) {
178+
if (editorContext?.editorStates?.isRecording) {
163179
vad.start();
164180
} else {
165181
vad.stop();
166182
}
167-
}, [editorStates, vad]);
183+
}, [editorContext?.editorStates, vad]);
168184

169185
return (
170186
<div className="flex h-full w-full flex-col">
@@ -176,7 +192,7 @@ export default function Home() {
176192
className={`min-h-0 w-full flex-grow`}
177193
style={{
178194
cursor:
179-
editorStates?.isDrawing && !isCanvasReady ? "wait" : "auto",
195+
editorContext?.editorStates?.isDrawing && !isCanvasReady ? "wait" : "auto",
180196
}}
181197
>
182198
<CodeEditorView
@@ -186,14 +202,14 @@ export default function Home() {
186202
width="100%"
187203
height="100%"
188204
url="/test.tsx"
189-
isDrawingMode={editorStates?.isDrawing}
190-
isDownloadClip={editorStates?.isDownloadClip}
191-
isDrawHulls={editorStates?.isDrawHulls}
205+
isDrawingMode={editorContext?.editorStates?.isDrawing}
206+
isDownloadClip={editorContext?.editorStates?.isDownloadClip}
207+
isDrawHulls={editorContext?.editorStates?.isDrawHulls}
192208
setIsCanvasReady={setIsCanvasReady}
193209
/>
194210
</div>
195211
<AnimatePresence>
196-
{editorStates?.isOpenChatView && (
212+
{editorContext?.editorStates?.isOpenChatView && (
197213
<motion.div
198214
className="h-full min-h-[60%] w-full pb-14"
199215
// Enter from bottom and exit to bottom

components/editor-toolbar.tsx

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"use client";
22

33
import { Button, Divider, Tooltip } from "@nextui-org/react";
4-
import useEditorStatesContext from "@/lib/hooks/use-editor-states-context";
5-
import { useEffect, useState } from "react";
4+
import { useContext, useEffect, useState } from "react";
65
import Icon from "@/components/icon";
76
import SettingModal from "@/components/modals/settings-modal";
87
import { AnimatePresence, motion } from "framer-motion";
8+
import { EditorContext } from "./providers/editor-context-provider";
99

1010
export default function EditorToolbar() {
11-
const { editorStates, updateEditorStates } = useEditorStatesContext();
11+
const editorContext = useContext(EditorContext);
12+
1213
const [isOpen, setIsOpen] = useState(false);
1314
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
1415

@@ -41,13 +42,16 @@ export default function EditorToolbar() {
4142
isIconOnly
4243
className="h-8 w-8 min-w-8 px-1 py-1 text-default-foreground"
4344
onPress={() => {
44-
if (editorStates) {
45-
updateEditorStates({
46-
isDrawing: !editorStates.isDrawing,
47-
});
45+
if (editorContext?.editorStates) {
46+
editorContext?.setEditorStates((prev) => ({
47+
...prev,
48+
isDrawing: !editorContext?.editorStates.isDrawing,
49+
}));
4850
}
4951
}}
50-
variant={editorStates?.isDrawing ? "solid" : "light"}
52+
variant={
53+
editorContext?.editorStates?.isDrawing ? "solid" : "light"
54+
}
5155
>
5256
<Icon name="edit" variant="round" />
5357
</Button>
@@ -75,10 +79,12 @@ export default function EditorToolbar() {
7579
isIconOnly
7680
className="h-8 w-8 min-w-8 px-1 py-1 text-default-foreground"
7781
onPress={() => {
78-
if (editorStates) {
79-
updateEditorStates({
80-
isOpenChatView: !editorStates.isOpenChatView,
81-
});
82+
if (editorContext?.editorStates) {
83+
editorContext?.setEditorStates((prev) => ({
84+
...prev,
85+
isOpenChatView:
86+
!editorContext?.editorStates.isOpenChatView,
87+
}));
8288
}
8389
}}
8490
>
@@ -91,13 +97,16 @@ export default function EditorToolbar() {
9197
isIconOnly
9298
className="h-8 w-8 min-w-8 px-1 py-1 text-default-foreground"
9399
onPress={() => {
94-
if (editorStates) {
95-
updateEditorStates({
96-
isRecording: !editorStates.isRecording,
97-
});
100+
if (editorContext?.editorStates) {
101+
editorContext?.setEditorStates((prev) => ({
102+
...prev,
103+
isRecording: !editorContext?.editorStates.isRecording,
104+
}));
98105
}
99106
}}
100-
variant={editorStates?.isRecording ? "solid" : "light"}
107+
variant={
108+
editorContext?.editorStates?.isRecording ? "solid" : "light"
109+
}
101110
>
102111
<Icon name="mic" variant="outlined" />
103112
</Button>

0 commit comments

Comments
 (0)