summaryrefslogtreecommitdiff
path: root/extension/react-app
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-06-26 16:39:07 -0700
committerNate Sesti <sestinj@gmail.com>2023-06-26 16:39:07 -0700
commitf3c6533d4054de5a71c8867c2b76fc8b0747447c (patch)
tree8e53ce9533aa42ee5d0a31504aa07be691d87157 /extension/react-app
parentf403bbe26b8864ff5367eab08afe4a01fdde8e72 (diff)
parent292d4d10ce28d720d61f97918c490b0d9cdae9e7 (diff)
downloadsncontinue-f3c6533d4054de5a71c8867c2b76fc8b0747447c.tar.gz
sncontinue-f3c6533d4054de5a71c8867c2b76fc8b0747447c.tar.bz2
sncontinue-f3c6533d4054de5a71c8867c2b76fc8b0747447c.zip
Merge branch 'main' into styled-code
Diffstat (limited to 'extension/react-app')
-rw-r--r--extension/react-app/package-lock.json32
-rw-r--r--extension/react-app/package.json1
-rw-r--r--extension/react-app/public/continue.gifbin0 -> 5242 bytes
-rw-r--r--extension/react-app/public/continue_arrow.pngbin1350 -> 0 bytes
-rw-r--r--extension/react-app/public/play_button.pngbin0 -> 1017 bytes
-rw-r--r--extension/react-app/src/components/CodeBlock.tsx7
-rw-r--r--extension/react-app/src/components/ComboBox.tsx29
-rw-r--r--extension/react-app/src/components/ContinueButton.tsx13
-rw-r--r--extension/react-app/src/components/DebugPanel.tsx2
-rw-r--r--extension/react-app/src/components/HeaderButtonWithText.tsx10
-rw-r--r--extension/react-app/src/components/LoadingCover.tsx50
-rw-r--r--extension/react-app/src/components/StepContainer.tsx40
-rw-r--r--extension/react-app/src/components/TextDialog.tsx2
-rw-r--r--extension/react-app/src/hooks/ContinueGUIClientProtocol.ts2
-rw-r--r--extension/react-app/src/hooks/useContinueGUIProtocol.ts4
-rw-r--r--extension/react-app/src/redux/slices/configSlice.ts16
-rw-r--r--extension/react-app/src/redux/store.ts1
-rw-r--r--extension/react-app/src/tabs/gui.tsx149
18 files changed, 292 insertions, 66 deletions
diff --git a/extension/react-app/package-lock.json b/extension/react-app/package-lock.json
index 18ef3ee6..fa624b3f 100644
--- a/extension/react-app/package-lock.json
+++ b/extension/react-app/package-lock.json
@@ -18,6 +18,7 @@
"react-markdown": "^8.0.5",
"react-redux": "^8.0.5",
"react-syntax-highlighter": "^15.5.0",
+ "react-switch": "^7.0.0",
"styled-components": "^5.3.6",
"vscode-webview": "^1.0.1-beta.1"
},
@@ -2921,19 +2922,16 @@
}
}
},
- "node_modules/react-syntax-highlighter": {
- "version": "15.5.0",
- "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz",
- "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==",
+ "node_modules/react-switch": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz",
+ "integrity": "sha512-KkDeW+cozZXI6knDPyUt3KBN1rmhoVYgAdCJqAh7st7tk8YE6N0iR89zjCWO8T8dUTeJGTR0KU+5CHCRMRffiA==",
"dependencies": {
- "@babel/runtime": "^7.3.1",
- "highlight.js": "^10.4.1",
- "lowlight": "^1.17.0",
- "prismjs": "^1.27.0",
- "refractor": "^3.6.0"
+ "prop-types": "^15.7.2"
},
"peerDependencies": {
- "react": ">= 0.14.0"
+ "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/read-cache": {
@@ -5351,16 +5349,12 @@
"use-sync-external-store": "^1.0.0"
}
},
- "react-syntax-highlighter": {
- "version": "15.5.0",
- "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz",
- "integrity": "sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg==",
+ "react-switch": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz",
+ "integrity": "sha512-KkDeW+cozZXI6knDPyUt3KBN1rmhoVYgAdCJqAh7st7tk8YE6N0iR89zjCWO8T8dUTeJGTR0KU+5CHCRMRffiA==",
"requires": {
- "@babel/runtime": "^7.3.1",
- "highlight.js": "^10.4.1",
- "lowlight": "^1.17.0",
- "prismjs": "^1.27.0",
- "refractor": "^3.6.0"
+ "prop-types": "^15.7.2"
}
},
"read-cache": {
diff --git a/extension/react-app/package.json b/extension/react-app/package.json
index d43ec55e..5fe27916 100644
--- a/extension/react-app/package.json
+++ b/extension/react-app/package.json
@@ -19,6 +19,7 @@
"react-markdown": "^8.0.5",
"react-redux": "^8.0.5",
"react-syntax-highlighter": "^15.5.0",
+ "react-switch": "^7.0.0",
"styled-components": "^5.3.6",
"vscode-webview": "^1.0.1-beta.1"
},
diff --git a/extension/react-app/public/continue.gif b/extension/react-app/public/continue.gif
new file mode 100644
index 00000000..daed6663
--- /dev/null
+++ b/extension/react-app/public/continue.gif
Binary files differ
diff --git a/extension/react-app/public/continue_arrow.png b/extension/react-app/public/continue_arrow.png
deleted file mode 100644
index 3b16ddf9..00000000
--- a/extension/react-app/public/continue_arrow.png
+++ /dev/null
Binary files differ
diff --git a/extension/react-app/public/play_button.png b/extension/react-app/public/play_button.png
new file mode 100644
index 00000000..af379375
--- /dev/null
+++ b/extension/react-app/public/play_button.png
Binary files differ
diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx
index a720a6ce..9438ab23 100644
--- a/extension/react-app/src/components/CodeBlock.tsx
+++ b/extension/react-app/src/components/CodeBlock.tsx
@@ -22,7 +22,7 @@ const StyledCopyButton = styled.button<{ visible: boolean }>`
/* position: relative; */
float: right;
border: none;
- background-color: transparent;
+ background-color: ${secondaryDark};
cursor: pointer;
padding: 0;
/* margin: 4px; */
@@ -77,7 +77,10 @@ function CodeBlock(props: { language?: string; children: string }) {
setHovered(false);
}}
>
- <CopyButton visible={hovered} textToCopy={props.children} />
+ <CopyButton
+ visible={hovered}
+ textToCopy={(props.children as any).props.children[0]}
+ />
<StyledCode>{props.children}</StyledCode>
</StyledPre>
);
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index ddc9d5dc..3816cee8 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -116,6 +116,15 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
disabled={props.disabled}
placeholder="Type '/' to see available slash commands."
{...getInputProps({
+ onChange: (e) => {
+ const target = e.target as HTMLTextAreaElement;
+ // Update the height of the textarea to match the content, up to a max of 200px.
+ target.style.height = "auto";
+ target.style.height = `${Math.min(
+ target.scrollHeight,
+ 300
+ ).toString()}px`;
+ },
onKeyDown: (event) => {
if (event.key === "Enter" && event.shiftKey) {
// Prevent Downshift's default 'Enter' behavior.
@@ -136,14 +145,24 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
} else if (event.key === "Tab" && items.length > 0) {
setInputValue(items[0].name);
event.preventDefault();
- } else if (event.key === "ArrowUp") {
+ } else if (
+ event.key === "ArrowUp" ||
+ (event.key === "ArrowDown" &&
+ event.currentTarget.value.split("\n").length > 1)
+ ) {
+ (event.nativeEvent as any).preventDownshiftDefault = true;
+ } else if (
+ event.key === "ArrowUp" &&
+ event.currentTarget.value.split("\n").length > 1
+ ) {
if (positionInHistory == 0) return;
setInputValue(history[positionInHistory - 1]);
setPositionInHistory((prev) => prev - 1);
- } else if (event.key === "ArrowDown") {
- if (positionInHistory >= history.length - 1) {
- setInputValue("");
- } else {
+ } else if (
+ event.key === "ArrowDown" &&
+ event.currentTarget.value.split("\n").length > 1
+ ) {
+ if (positionInHistory < history.length - 1) {
setInputValue(history[positionInHistory + 1]);
}
setPositionInHistory((prev) =>
diff --git a/extension/react-app/src/components/ContinueButton.tsx b/extension/react-app/src/components/ContinueButton.tsx
index c6117bf9..ef6719b7 100644
--- a/extension/react-app/src/components/ContinueButton.tsx
+++ b/extension/react-app/src/components/ContinueButton.tsx
@@ -1,6 +1,8 @@
import styled, { keyframes } from "styled-components";
import { Button } from ".";
import { Play } from "@styled-icons/heroicons-outline";
+import { useSelector } from "react-redux";
+import { RootStore } from "../redux/store";
let StyledButton = styled(Button)`
margin: auto;
@@ -25,14 +27,21 @@ let StyledButton = styled(Button)`
`;
function ContinueButton(props: { onClick?: () => void; hidden?: boolean }) {
+ const vscMediaUrl = useSelector(
+ (state: RootStore) => state.config.vscMediaUrl
+ );
+
return (
<StyledButton
hidden={props.hidden}
className="m-auto"
onClick={props.onClick}
>
- <Play />
- {/* <img src={"/continue_arrow.png"} width="16px"></img> */}
+ {vscMediaUrl ? (
+ <img src={`${vscMediaUrl}/play_button.png`} width="22px" />
+ ) : (
+ <Play />
+ )}
Continue
</StyledButton>
);
diff --git a/extension/react-app/src/components/DebugPanel.tsx b/extension/react-app/src/components/DebugPanel.tsx
index 30f38779..94dbac9e 100644
--- a/extension/react-app/src/components/DebugPanel.tsx
+++ b/extension/react-app/src/components/DebugPanel.tsx
@@ -6,6 +6,7 @@ import {
setApiUrl,
setVscMachineId,
setSessionId,
+ setVscMediaUrl,
} from "../redux/slices/configSlice";
import { setHighlightedCode } from "../redux/slices/miscSlice";
import { updateFileSystem } from "../redux/slices/debugContexSlice";
@@ -37,6 +38,7 @@ function DebugPanel(props: DebugPanelProps) {
dispatch(setApiUrl(event.data.apiUrl));
dispatch(setVscMachineId(event.data.vscMachineId));
dispatch(setSessionId(event.data.sessionId));
+ dispatch(setVscMediaUrl(event.data.vscMediaUrl));
break;
case "highlightedCode":
dispatch(setHighlightedCode(event.data.rangeInFile));
diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx
index f9483f0f..30931f86 100644
--- a/extension/react-app/src/components/HeaderButtonWithText.tsx
+++ b/extension/react-app/src/components/HeaderButtonWithText.tsx
@@ -6,14 +6,20 @@ interface HeaderButtonWithTextProps {
text: string;
onClick?: (e: any) => void;
children: React.ReactNode;
+ disabled?: boolean;
}
const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => {
const [hover, setHover] = useState(false);
return (
<HeaderButton
- style={{ padding: "3px" }}
- onMouseEnter={() => setHover(true)}
+ disabled={props.disabled}
+ style={{ padding: "1px", paddingLeft: hover ? "4px" : "1px" }}
+ onMouseEnter={() => {
+ if (!props.disabled) {
+ setHover(true);
+ }
+ }}
onMouseLeave={() => {
setHover(false);
}}
diff --git a/extension/react-app/src/components/LoadingCover.tsx b/extension/react-app/src/components/LoadingCover.tsx
new file mode 100644
index 00000000..a0f8f7a2
--- /dev/null
+++ b/extension/react-app/src/components/LoadingCover.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import styled from "styled-components";
+
+const StyledDiv = styled.div`
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100vh;
+ background: linear-gradient(
+ 101.79deg,
+ #12887a 0%,
+ #87245c 32%,
+ #e12637 63%,
+ #ffb215 100%
+ );
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ z-index: 10;
+`;
+
+const StyledImg = styled.img`
+ /* add your styles here */
+`;
+
+const StyledDiv2 = styled.div`
+ width: 50%;
+ height: 5px;
+ background: white;
+ margin-top: 20px;
+`;
+
+interface LoadingCoverProps {
+ message: string;
+ hidden?: boolean;
+}
+
+const LoadingCover = (props: LoadingCoverProps) => {
+ return (
+ <StyledDiv style={{ display: props.hidden ? "none" : "inherit" }}>
+ <StyledImg src="continue.gif" alt="centered image" width="50%" />
+ <StyledDiv2></StyledDiv2>
+ <p>{props.message}</p>
+ </StyledDiv>
+ );
+};
+
+export default LoadingCover;
diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx
index 1eb1d1fd..827d2d5f 100644
--- a/extension/react-app/src/components/StepContainer.tsx
+++ b/extension/react-app/src/components/StepContainer.tsx
@@ -49,9 +49,13 @@ const StepContainerDiv = styled.div<{ open: boolean }>`
/* padding: 8px; */
`;
-const HeaderDiv = styled.div<{ error: boolean }>`
+const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>`
background-color: ${(props) =>
- props.error ? "#522" : vscBackgroundTransparent};
+ props.error
+ ? "#522"
+ : props.loading
+ ? vscBackgroundTransparent
+ : vscBackground};
display: grid;
grid-template-columns: 1fr auto auto;
grid-gap: 8px;
@@ -76,12 +80,22 @@ const StyledCode = styled.code`
color: lightgray;
`;
+const gradient = keyframes`
+ 0% {
+ background-position: 0px 0;
+ }
+ 100% {
+ background-position: 100em 0;
+ }
+`;
+
const GradientBorder = styled.div<{
borderWidth?: number;
borderRadius?: string;
borderColor?: string;
isFirst: boolean;
isLast: boolean;
+ loading: boolean;
}>`
border-radius: ${(props) => props.borderRadius || "0"};
padding-top: ${(props) =>
@@ -91,13 +105,18 @@ const GradientBorder = styled.div<{
background: ${(props) =>
props.borderColor
? props.borderColor
- : `linear-gradient(
+ : `repeating-linear-gradient(
101.79deg,
#12887a 0%,
- #87245c 37.64%,
- #e12637 65.98%,
- #ffb215 110.45%
+ #87245c 16%,
+ #e12637 33%,
+ #ffb215 55%,
+ #e12637 67%,
+ #87245c 85%,
+ #12887a 99%
)`};
+ animation: ${(props) => (props.loading ? gradient : "")} 6s linear infinite;
+ background-size: 200% 200%;
`;
function StepContainer(props: StepContainerProps) {
@@ -138,10 +157,15 @@ function StepContainer(props: StepContainerProps) {
>
<StepContainerDiv open={props.open}>
<GradientBorder
+ loading={props.historyNode.active as boolean | false}
isFirst={props.isFirst}
isLast={props.isLast}
borderColor={
- props.historyNode.observation?.error ? "#f00" : undefined
+ props.historyNode.observation?.error
+ ? "#f00"
+ : props.historyNode.active
+ ? undefined
+ : "white"
}
className="overflow-hidden cursor-pointer"
onClick={(e) => {
@@ -153,6 +177,7 @@ function StepContainer(props: StepContainerProps) {
}}
>
<HeaderDiv
+ loading={props.historyNode.active as boolean | false}
error={props.historyNode.observation?.error ? true : false}
>
<h4 className="m-2">
@@ -175,6 +200,7 @@ function StepContainer(props: StepContainerProps) {
<>
<HeaderButtonWithText
+ disabled={props.historyNode.active as boolean}
onClick={(e) => {
e.stopPropagation();
props.onDelete();
diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx
index e50a7686..2632e572 100644
--- a/extension/react-app/src/components/TextDialog.tsx
+++ b/extension/react-app/src/components/TextDialog.tsx
@@ -15,6 +15,7 @@ const DialogContainer = styled.div`
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
+ width: 75%;
`;
const Dialog = styled.div`
@@ -76,7 +77,6 @@ const TextDialog = (props: {
<Dialog>
<P>Thanks for your feedback. We'll get back to you soon!</P>
<TextArea
- cols={50}
rows={10}
ref={textAreaRef}
onKeyDown={(e) => {
diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts
index 824bb086..3d8e0a38 100644
--- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts
+++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts
@@ -13,6 +13,8 @@ abstract class AbstractContinueGUIClientProtocol {
callback: (commands: { name: string; description: string }[]) => void
): void;
+ abstract changeDefaultModel(model: string): void;
+
abstract sendClear(): void;
abstract retryAtIndex(index: number): void;
diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts
index 59397742..f43a66ff 100644
--- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts
+++ b/extension/react-app/src/hooks/useContinueGUIProtocol.ts
@@ -55,6 +55,10 @@ class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol {
});
}
+ changeDefaultModel(model: string) {
+ this.messenger.send("change_default_model", { model });
+ }
+
sendClear() {
this.messenger.send("clear_history", {});
}
diff --git a/extension/react-app/src/redux/slices/configSlice.ts b/extension/react-app/src/redux/slices/configSlice.ts
index a6a641e6..1b107bed 100644
--- a/extension/react-app/src/redux/slices/configSlice.ts
+++ b/extension/react-app/src/redux/slices/configSlice.ts
@@ -37,9 +37,21 @@ export const configSlice = createSlice({
...state,
sessionId: action.payload,
}),
+ setVscMediaUrl: (
+ state: RootStore["config"],
+ action: { type: string; payload: string }
+ ) => ({
+ ...state,
+ vscMediaUrl: action.payload,
+ }),
},
});
-export const { setVscMachineId, setApiUrl, setWorkspacePath, setSessionId } =
- configSlice.actions;
+export const {
+ setVscMachineId,
+ setApiUrl,
+ setWorkspacePath,
+ setSessionId,
+ setVscMediaUrl,
+} = configSlice.actions;
export default configSlice.reducer;
diff --git a/extension/react-app/src/redux/store.ts b/extension/react-app/src/redux/store.ts
index f9eb0517..a5eef4ba 100644
--- a/extension/react-app/src/redux/store.ts
+++ b/extension/react-app/src/redux/store.ts
@@ -21,6 +21,7 @@ export interface RootStore {
vscMachineId: string | undefined;
sessionId: string | undefined;
sessionStarted: number | undefined;
+ vscMediaUrl: string | undefined;
};
chat: {
messages: ChatMessage[];
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index 624d22d5..13b74423 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -1,11 +1,5 @@
import styled from "styled-components";
-import {
- defaultBorderRadius,
- vscBackground,
- Loader,
- MainTextInput,
- HeaderButton,
-} from "../components";
+import { defaultBorderRadius, Loader } from "../components";
import ContinueButton from "../components/ContinueButton";
import { useCallback, useEffect, useRef, useState } from "react";
import { History } from "../../../schema/History";
@@ -20,6 +14,11 @@ import {
import ComboBox from "../components/ComboBox";
import TextDialog from "../components/TextDialog";
import HeaderButtonWithText from "../components/HeaderButtonWithText";
+import ReactSwitch from "react-switch";
+import { usePostHog } from "posthog-js/react";
+import { useSelector } from "react-redux";
+import { RootStore } from "../redux/store";
+import LoadingCover from "../components/LoadingCover";
const TopGUIDiv = styled.div`
overflow: hidden;
@@ -33,7 +32,7 @@ const UserInputQueueItem = styled.div`
text-align: center;
`;
-const Footer = styled.footer`
+const Footer = styled.footer<{ dataSwitchChecked: boolean }>`
display: flex;
flex-direction: row;
gap: 8px;
@@ -42,6 +41,8 @@ const Footer = styled.footer`
align-items: center;
margin-top: 8px;
border-top: 0.1px solid gray;
+ background-color: ${(props) =>
+ props.dataSwitchChecked ? "#12887a33" : "transparent"};
`;
interface GUIProps {
@@ -49,14 +50,22 @@ interface GUIProps {
}
function GUI(props: GUIProps) {
+ const posthog = usePostHog();
+ const vscMachineId = useSelector(
+ (state: RootStore) => state.config.vscMachineId
+ );
+
+ const [usingFastModel, setUsingFastModel] = useState(false);
const [waitingForSteps, setWaitingForSteps] = useState(false);
const [userInputQueue, setUserInputQueue] = useState<string[]>([]);
const [availableSlashCommands, setAvailableSlashCommands] = useState<
{ name: string; description: string }[]
>([]);
+ const [dataSwitchChecked, setDataSwitchChecked] = useState(false);
+ const [showDataSharingInfo, setShowDataSharingInfo] = useState(false);
const [stepsOpen, setStepsOpen] = useState<boolean[]>([]);
const [history, setHistory] = useState<History | undefined>();
- // {
+ // {
// timeline: [
// {
// step: {
@@ -144,6 +153,7 @@ function GUI(props: GUIProps) {
// ],
// },
// {
+ // active: false,
// step: {
// name: "SolveTracebackStep",
// traceback: {
@@ -204,24 +214,41 @@ function GUI(props: GUIProps) {
}, [topGuiDivRef.current, scrollTimeout]);
useEffect(() => {
+ const listener = (e: any) => {
+ // Cmd + J to toggle fast model
+ if (e.key === "i" && e.metaKey && e.shiftKey) {
+ setUsingFastModel((prev) => !prev);
+ }
+ };
+ window.addEventListener("keydown", listener);
+
+ return () => {
+ window.removeEventListener("keydown", listener);
+ };
+ }, []);
+
+ useEffect(() => {
console.log("CLIENT ON STATE UPDATE: ", client, client?.onStateUpdate);
client?.onStateUpdate((state) => {
// Scroll only if user is at very bottom of the window.
+ setUsingFastModel(state.default_model === "gpt-3.5-turbo");
const shouldScrollToBottom =
topGuiDivRef.current &&
topGuiDivRef.current?.offsetHeight - window.scrollY < 100;
setWaitingForSteps(state.active);
setHistory(state.history);
setUserInputQueue(state.user_input_queue);
- const nextStepsOpen = [...stepsOpen];
- for (
- let i = nextStepsOpen.length;
- i < state.history.timeline.length;
- i++
- ) {
- nextStepsOpen.push(true);
- }
- setStepsOpen(nextStepsOpen);
+ setStepsOpen((prev) => {
+ const nextStepsOpen = [...prev];
+ for (
+ let i = nextStepsOpen.length;
+ i < state.history.timeline.length;
+ i++
+ ) {
+ nextStepsOpen.push(true);
+ }
+ return nextStepsOpen;
+ });
if (shouldScrollToBottom) {
scrollToBottom();
@@ -263,8 +290,9 @@ function GUI(props: GUIProps) {
const onMainTextInput = () => {
if (mainTextInputRef.current) {
- if (!client) return;
let input = mainTextInputRef.current.value;
+ mainTextInputRef.current.value = "";
+ if (!client) return;
if (
history?.timeline.length &&
@@ -301,6 +329,7 @@ function GUI(props: GUIProps) {
// const iterations = useSelector(selectIterations);
return (
<>
+ <LoadingCover hidden={true} message="Downloading local model..." />
<TextDialog
showDialog={showFeedbackDialog}
onEnter={(text) => {
@@ -323,9 +352,7 @@ function GUI(props: GUIProps) {
{typeof client === "undefined" && (
<>
<Loader></Loader>
- <p style={{ textAlign: "center" }}>
- Trying to reconnect with server...
- </p>
+ <p style={{ textAlign: "center" }}>Loading Continue server...</p>
</>
)}
{history?.timeline.map((node: HistoryNode, index: number) => {
@@ -340,7 +367,7 @@ function GUI(props: GUIProps) {
setStepsOpen(nextStepsOpen);
}}
onToggleAll={() => {
- setStepsOpen((prev) => prev.map(() => !prev[index]));
+ setStepsOpen((prev) => prev.map((_, index) => !prev[index]));
}}
key={index}
onUserInput={(input: string) => {
@@ -390,17 +417,87 @@ function GUI(props: GUIProps) {
/>
<ContinueButton onClick={onMainTextInput} />
</TopGUIDiv>
- <Footer>
+ <div
+ style={{
+ position: "fixed",
+ bottom: "50px",
+ backgroundColor: "white",
+ color: "black",
+ borderRadius: defaultBorderRadius,
+ padding: "16px",
+ margin: "16px",
+ }}
+ hidden={!showDataSharingInfo}
+ >
+ By turning on this switch, you signal that you would contribute this
+ software development data to a publicly accessible, open-source dataset
+ in the future.
+ <br />
+ <br />
+ <b>
+ {dataSwitchChecked
+ ? "No data is being collected. In the future, you would be contributing data"
+ : "No data is being collected. In the future, your data would not be shared"}
+ </b>
+ </div>
+ <Footer dataSwitchChecked={dataSwitchChecked}>
+ <div
+ style={{
+ display: "flex",
+ gap: "4px",
+ marginRight: "auto",
+ alignItems: "center",
+ }}
+ onMouseEnter={() => {
+ setShowDataSharingInfo(true);
+ }}
+ onMouseLeave={() => {
+ setShowDataSharingInfo(false);
+ }}
+ >
+ <ReactSwitch
+ height={20}
+ handleDiameter={20}
+ width={40}
+ onChange={() => {
+ posthog?.capture("data_switch_toggled", {
+ vscMachineId: vscMachineId,
+ dataSwitchChecked: !dataSwitchChecked,
+ });
+ setDataSwitchChecked((prev) => !prev);
+ }}
+ onColor="#12887a"
+ checked={dataSwitchChecked}
+ />
+ <span style={{ cursor: "help", fontSize: "14px" }}>
+ Contribute Data
+ </span>
+ </div>
+ <HeaderButtonWithText
+ onClick={() => {
+ client?.changeDefaultModel(
+ usingFastModel ? "gpt-4" : "gpt-3.5-turbo"
+ );
+ setUsingFastModel((prev) => !prev);
+ }}
+ text={usingFastModel ? "gpt-3.5-turbo" : "gpt-4"}
+ >
+ <div
+ style={{ fontSize: "18px", marginLeft: "2px", marginRight: "2px" }}
+ >
+ {usingFastModel ? "⚡" : "🧠"}
+ </div>
+ </HeaderButtonWithText>
<HeaderButtonWithText
onClick={() => {
client?.sendClear();
}}
- text="Clear History"
+ text="Clear All"
>
<Trash size="1.6em" />
</HeaderButtonWithText>
<a href="https://continue.dev/docs" className="no-underline">
- <HeaderButtonWithText text="Continue Docs">
+ <HeaderButtonWithText text="Docs">
<BookOpen size="1.6em" />
</HeaderButtonWithText>
</a>