diff options
Diffstat (limited to 'extension/react-app')
-rw-r--r-- | extension/react-app/src/App.tsx | 2 | ||||
-rw-r--r-- | extension/react-app/src/pages/gui.tsx | 75 | ||||
-rw-r--r-- | extension/react-app/src/pages/history.tsx | 13 | ||||
-rw-r--r-- | extension/react-app/src/redux/hooks.ts | 21 | ||||
-rw-r--r-- | extension/react-app/src/redux/selectors/debugContextSelectors.ts | 29 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/debugContexSlice.ts | 149 | ||||
-rw-r--r-- | extension/react-app/src/redux/slices/serverStateReducer.ts | 53 | ||||
-rw-r--r-- | extension/react-app/src/redux/store.ts | 12 |
8 files changed, 102 insertions, 252 deletions
diff --git a/extension/react-app/src/App.tsx b/extension/react-app/src/App.tsx index 48ecebaa..879373a0 100644 --- a/extension/react-app/src/App.tsx +++ b/extension/react-app/src/App.tsx @@ -12,7 +12,6 @@ import { setVscMediaUrl, setDataSwitchOn, } from "./redux/slices/configSlice"; -import { updateFileSystem } from "./redux/slices/debugContexSlice"; import { setHighlightedCode } from "./redux/slices/miscSlice"; import { postVscMessage } from "./vscode"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; @@ -60,7 +59,6 @@ function App() { break; case "highlightedCode": dispatch(setHighlightedCode(event.data.rangeInFile)); - dispatch(updateFileSystem(event.data.filesystem)); break; } }; diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx index e2e3431a..e96ffe65 100644 --- a/extension/react-app/src/pages/gui.tsx +++ b/extension/react-app/src/pages/gui.tsx @@ -2,9 +2,8 @@ import styled from "styled-components"; import { defaultBorderRadius } from "../components"; import Loader from "../components/Loader"; import ContinueButton from "../components/ContinueButton"; -import { ContextItem, FullState } from "../../../schema/FullState"; +import { FullState } from "../../../schema/FullState"; import { useCallback, useEffect, useRef, useState, useContext } from "react"; -import { History } from "../../../schema/History"; import { HistoryNode } from "../../../schema/HistoryNode"; import StepContainer from "../components/StepContainer"; import { GUIClientContext } from "../App"; @@ -23,6 +22,10 @@ import { setShowDialog, } from "../redux/slices/uiStateSlice"; import RingLoader from "../components/RingLoader"; +import { + setServerState, + temporarilySetUserInputQueue, +} from "../redux/slices/serverStateReducer"; const UserInputQueueItem = styled.div` border-radius: ${defaultBorderRadius}; @@ -44,13 +47,18 @@ function GUI(props: GUIProps) { // #endregion + // #region Selectors + const { + history, + user_input_queue, + adding_highlighted_code, + selected_context_items, + } = useSelector((state: RootStore) => state.serverState); + + // #endregion + // #region State const [waitingForSteps, setWaitingForSteps] = useState(false); - const [userInputQueue, setUserInputQueue] = useState<string[]>([]); - const [addingHighlightedCode, setAddingHighlightedCode] = useState(false); - const [selectedContextItems, setSelectedContextItems] = useState< - ContextItem[] - >([]); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); @@ -60,27 +68,6 @@ function GUI(props: GUIProps) { true, true, ]); - const [history, setHistory] = useState<History | undefined>({ - timeline: [ - { - step: { - name: "Welcome to Continue", - hide: false, - description: `- Highlight code section and ask a question or give instructions -- Use \`cmd+m\` (Mac) / \`ctrl+m\` (Windows) to open Continue -- Use \`/help\` to ask questions about how to use Continue`, - system_message: null, - chat_context: [], - manage_own_chat_context: false, - message: "", - }, - depth: 0, - deleted: false, - active: false, - }, - ], - current_index: 3, - } as any); const [waitingForClient, setWaitingForClient] = useState(true); const [showLoading, setShowLoading] = useState(false); @@ -163,11 +150,9 @@ function GUI(props: GUIProps) { state.history.current_index ].step.description?.trim() === ""; + dispatch(setServerState(state)); + setWaitingForSteps(waitingForSteps); - setHistory(state.history); - setSelectedContextItems(state.selected_context_items || []); - setUserInputQueue(state.user_input_queue); - setAddingHighlightedCode(state.adding_highlighted_code); setAvailableSlashCommands( state.slash_commands.map((c: any) => { return { @@ -203,11 +188,11 @@ function GUI(props: GUIProps) { useEffect(() => { if (client && waitingForClient) { setWaitingForClient(false); - for (const input of userInputQueue) { + for (const input of user_input_queue) { client.sendMainInput(input); } } - }, [client, userInputQueue, waitingForClient]); + }, [client, user_input_queue, waitingForClient]); const onMainTextInput = (event?: any) => { if (mainTextInputRef.current) { @@ -218,9 +203,11 @@ function GUI(props: GUIProps) { } (mainTextInputRef.current as any).setInputValue(""); if (!client) { - setUserInputQueue((queue) => { - return [...queue, input]; - }); + dispatch( + temporarilySetUserInputQueue((queue: string[]) => { + return [...queue, input]; + }) + ); return; } @@ -249,9 +236,11 @@ function GUI(props: GUIProps) { if (input.trim() === "") return; client.sendMainInput(input); - setUserInputQueue((queue) => { - return [...queue, input]; - }); + dispatch( + temporarilySetUserInputQueue((queue: string[]) => { + return [...queue, input]; + }) + ); // Increment localstorage counter const counter = localStorage.getItem("mainTextEntryCounter"); @@ -435,7 +424,7 @@ function GUI(props: GUIProps) { {waitingForSteps && <Loader />} <div> - {userInputQueue.map((input) => { + {user_input_queue.map((input) => { return <UserInputQueueItem>{input}</UserInputQueueItem>; })} </div> @@ -450,11 +439,11 @@ function GUI(props: GUIProps) { }} onInputValueChange={() => {}} items={availableSlashCommands} - selectedContextItems={selectedContextItems} + selectedContextItems={selected_context_items} onToggleAddContext={() => { client?.toggleAddingHighlightedCode(); }} - addingHighlightedCode={addingHighlightedCode} + addingHighlightedCode={adding_highlighted_code} /> <ContinueButton onClick={onMainTextInput} /> </div> diff --git a/extension/react-app/src/pages/history.tsx b/extension/react-app/src/pages/history.tsx index f925d52c..a553c6ae 100644 --- a/extension/react-app/src/pages/history.tsx +++ b/extension/react-app/src/pages/history.tsx @@ -69,7 +69,18 @@ function History() { }} > <div className="text-lg">{session.title}</div> - <div className="text-gray-400">{session.date_created}</div> + <div className="text-gray-400"> + {new Date( + parseInt(session.date_created) * 1000 + ).toLocaleString("en-US", { + weekday: "short", + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + })} + </div> </TdDiv> </td> </Tr> diff --git a/extension/react-app/src/redux/hooks.ts b/extension/react-app/src/redux/hooks.ts deleted file mode 100644 index a6aef869..00000000 --- a/extension/react-app/src/redux/hooks.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { RootStore } from "./store"; -import { selectDebugContextValue } from "./selectors/debugContextSelectors"; -import { updateValue } from "./slices/debugContexSlice"; -import { SerializedDebugContext } from "../../../src/client"; - -export function useDebugContextValue( - key: keyof SerializedDebugContext, - defaultValue: any -): [any, (value: any) => void] { - const dispatch = useDispatch(); - const state = - useSelector((state: RootStore) => selectDebugContextValue(state, key)) || - defaultValue; - const boundAction = useCallback( - (value: any) => dispatch(updateValue({ key, value })), - [dispatch, key] - ); - return [state, boundAction]; -} diff --git a/extension/react-app/src/redux/selectors/debugContextSelectors.ts b/extension/react-app/src/redux/selectors/debugContextSelectors.ts deleted file mode 100644 index 89201bb7..00000000 --- a/extension/react-app/src/redux/selectors/debugContextSelectors.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { RootStore } from "../store"; - -const selectDebugContext = (state: RootStore) => { - return { - ...state.debugState.debugContext, - rangesInFiles: state.debugState.debugContext.rangesInFiles.filter( - (_, index) => state.debugState.rangesMask[index] - ), - }; -}; - -const selectAllRangesInFiles = (state: RootStore) => { - return state.debugState.debugContext.rangesInFiles; -}; - -const selectRangesMask = (state: RootStore) => { - return state.debugState.rangesMask; -}; - -const selectDebugContextValue = (state: RootStore, key: string) => { - return (state.debugState.debugContext as any)[key]; -}; - -export { - selectDebugContext, - selectDebugContextValue, - selectAllRangesInFiles, - selectRangesMask, -}; diff --git a/extension/react-app/src/redux/slices/debugContexSlice.ts b/extension/react-app/src/redux/slices/debugContexSlice.ts deleted file mode 100644 index 647440d5..00000000 --- a/extension/react-app/src/redux/slices/debugContexSlice.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { createSlice } from "@reduxjs/toolkit"; -import { RangeInFile, SerializedDebugContext } from "../../../../src/client"; -import { RootStore } from "../store"; - -export const debugStateSlice = createSlice({ - name: "debugState", - initialState: { - debugContext: { - rangesInFiles: [], - filesystem: {}, - traceback: undefined, - description: undefined, - }, - rangesMask: [], - } as RootStore["debugState"], - reducers: { - updateValue: ( - state: RootStore["debugState"], - action: { - type: string; - payload: { key: keyof SerializedDebugContext; value: any }; - } - ) => { - return { - ...state, - debugContext: { - ...state.debugContext, - [action.payload.key]: action.payload.value, - }, - }; - }, - addRangeInFile: ( - state: RootStore["debugState"], - action: { - type: string; - payload: { - rangeInFile: RangeInFile; - canUpdateLast: boolean; - }; - } - ) => { - let rangesInFiles = state.debugContext.rangesInFiles; - // If identical to existing range, don't add. Ideally you check for overlap of ranges. - for (let range of rangesInFiles) { - if ( - range.filepath === action.payload.rangeInFile.filepath && - range.range.start.line === - action.payload.rangeInFile.range.start.line && - range.range.end.line === action.payload.rangeInFile.range.end.line - ) { - return state; - } - } - - if ( - action.payload.canUpdateLast && - rangesInFiles.length > 0 && - rangesInFiles[rangesInFiles.length - 1].filepath === - action.payload.rangeInFile.filepath - ) { - return { - ...state, - debugContext: { - ...state.debugContext, - rangesInFiles: [ - ...rangesInFiles.slice(0, rangesInFiles.length - 1), - action.payload.rangeInFile, - ], - }, - }; - } else { - return { - ...state, - debugContext: { - ...state.debugContext, - rangesInFiles: [ - ...state.debugContext.rangesInFiles, - action.payload.rangeInFile, - ], - }, - rangesMask: [...state.rangesMask, true], - }; - } - }, - deleteRangeInFileAt: ( - state: RootStore["debugState"], - action: { - type: string; - payload: number; - } - ) => { - return { - ...state, - debugContext: { - ...state.debugContext, - rangesInFiles: state.debugContext.rangesInFiles.filter( - (_, index) => index !== action.payload - ), - }, - rangesMask: state.rangesMask.filter( - (_, index) => index !== action.payload - ), - }; - }, - toggleSelectionAt: ( - state: RootStore["debugState"], - action: { - type: string; - payload: number; - } - ) => { - return { - ...state, - rangesMask: state.rangesMask.map((_, index) => - index === action.payload - ? !state.rangesMask[index] - : state.rangesMask[index] - ), - }; - }, - updateFileSystem: ( - state: RootStore["debugState"], - action: { - type: string; - payload: { [filepath: string]: string }; - } - ) => { - return { - ...state, - debugContext: { - ...state.debugContext, - filesystem: { - ...state.debugContext.filesystem, - ...action.payload, - }, - }, - }; - }, - }, -}); - -export const { - updateValue, - updateFileSystem, - addRangeInFile, - deleteRangeInFileAt, - toggleSelectionAt, -} = debugStateSlice.actions; -export default debugStateSlice.reducer; diff --git a/extension/react-app/src/redux/slices/serverStateReducer.ts b/extension/react-app/src/redux/slices/serverStateReducer.ts new file mode 100644 index 00000000..4d9dc326 --- /dev/null +++ b/extension/react-app/src/redux/slices/serverStateReducer.ts @@ -0,0 +1,53 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { FullState } from "../../../../schema/FullState"; + +const initialState: FullState = { + history: { + timeline: [ + { + step: { + name: "Welcome to Continue", + hide: false, + description: `- Highlight code section and ask a question or give instructions + - Use \`cmd+m\` (Mac) / \`ctrl+m\` (Windows) to open Continue + - Use \`/help\` to ask questions about how to use Continue`, + system_message: null, + chat_context: [], + manage_own_chat_context: false, + message: "", + }, + depth: 0, + deleted: false, + active: false, + }, + ], + current_index: 3, + } as any, + user_input_queue: [], + active: false, + slash_commands: [], + adding_highlighted_code: false, + selected_context_items: [], +}; + +export const serverStateSlice = createSlice({ + name: "serverState", + initialState, + reducers: { + setServerState: (state, action) => { + return { + ...action.payload, + selected_context_items: action.payload.selected_context_items || [], + user_input_queue: action.payload.user_input_queue || [], + slash_commands: action.payload.slash_commands || [], + }; + }, + temporarilySetUserInputQueue: (state, action) => { + state.user_input_queue = action.payload; + }, + }, +}); + +export const { setServerState, temporarilySetUserInputQueue } = + serverStateSlice.actions; +export default serverStateSlice.reducer; diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts index aa8f5e7b..59339060 100644 --- a/extension/react-app/src/redux/store.ts +++ b/extension/react-app/src/redux/store.ts @@ -1,10 +1,11 @@ import { configureStore } from "@reduxjs/toolkit"; -import debugStateReducer from "./slices/debugContexSlice"; import chatReducer from "./slices/chatSlice"; import configReducer from "./slices/configSlice"; import miscReducer from "./slices/miscSlice"; import uiStateReducer from "./slices/uiStateSlice"; -import { RangeInFile, SerializedDebugContext } from "../../../src/client"; +import { RangeInFile } from "../../../src/client"; +import { FullState } from "../../../schema/FullState"; +import serverStateReducer from "./slices/serverStateReducer"; export interface ChatMessage { role: "system" | "user" | "assistant"; @@ -12,10 +13,6 @@ export interface ChatMessage { } export interface RootStore { - debugState: { - debugContext: SerializedDebugContext; - rangesMask: boolean[]; - }; config: { workspacePath: string | undefined; apiUrl: string; @@ -40,15 +37,16 @@ export interface RootStore { dialogMessage: string | JSX.Element; dialogEntryOn: boolean; }; + serverState: FullState; } const store = configureStore({ reducer: { - debugState: debugStateReducer, chat: chatReducer, config: configReducer, misc: miscReducer, uiState: uiStateReducer, + serverState: serverStateReducer, }, }); |