From 5c03dd4775845c559a1f6298f7577609ba907bb1 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Wed, 5 Jul 2023 23:49:37 -0700
Subject: ui overhaul

---
 extension/react-app/src/components/ComboBox.tsx | 191 +++++++++++++-----------
 1 file changed, 100 insertions(+), 91 deletions(-)

(limited to 'extension/react-app/src/components/ComboBox.tsx')

diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index 81b148b9..7ee5dc24 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -4,6 +4,7 @@ import styled from "styled-components";
 import {
   buttonColor,
   defaultBorderRadius,
+  lightGray,
   secondaryDark,
   vscBackground,
 } from ".";
@@ -16,11 +17,32 @@ import {
   LockClosed,
   LockOpen,
   Plus,
+  DocumentPlus,
 } from "@styled-icons/heroicons-outline";
+import { HighlightedRangeContext } from "../../../schema/FullState";
 
 // #region styled components
 const mainInputFontSize = 16;
 
+const EmptyPillDiv = styled.div`
+  padding: 8px;
+  border-radius: ${defaultBorderRadius};
+  border: 1px dashed ${lightGray};
+  color: ${lightGray};
+  background-color: ${vscBackground};
+  overflow: hidden;
+  display: flex;
+  align-items: center;
+  text-align: center;
+  cursor: pointer;
+  font-size: 13px;
+
+  &:hover {
+    background-color: ${lightGray};
+    color: ${vscBackground};
+  }
+`;
+
 const ContextDropdown = styled.div`
   position: absolute;
   padding: 4px;
@@ -41,17 +63,19 @@ const MainTextInput = styled.textarea`
 
   padding: 8px;
   font-size: ${mainInputFontSize}px;
+  font-family: inherit;
+  border: 1px solid transparent;
   border-radius: ${defaultBorderRadius};
-  border: 1px solid white;
   margin: 8px auto;
+  height: auto;
   width: 100%;
-  background-color: ${vscBackground};
+  background-color: ${secondaryDark};
   color: white;
   z-index: 1;
 
   &:focus {
+    outline: 1px solid #ff000066;
     border: 1px solid transparent;
-    outline: 1px solid orange;
   }
 `;
 
@@ -69,7 +93,6 @@ const Ul = styled.ul<{
   background: ${vscBackground};
   background-color: ${secondaryDark};
   color: white;
-  font-family: "Fira Code", monospace;
   max-height: ${UlMaxHeight}px;
   overflow: scroll;
   padding: 0;
@@ -102,7 +125,7 @@ interface ComboBoxProps {
   onInputValueChange: (inputValue: string) => void;
   disabled?: boolean;
   onEnter: (e: React.KeyboardEvent<HTMLInputElement>) => void;
-  highlightedCodeSections: (RangeInFile & { contents: string })[];
+  highlightedCodeSections: HighlightedRangeContext[];
   deleteContextItems: (indices: number[]) => void;
   onTogglePin: () => void;
   onToggleAddContext: () => void;
@@ -119,16 +142,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
     React.useState(false);
   const [pinned, setPinned] = useState(false);
   const [highlightedCodeSections, setHighlightedCodeSections] = React.useState(
-    props.highlightedCodeSections || [
-      {
-        filepath: "test.ts",
-        range: {
-          start: { line: 0, character: 0 },
-          end: { line: 0, character: 0 },
-        },
-        contents: "import * as a from 'a';",
-      },
-    ]
+    props.highlightedCodeSections || []
   );
 
   useEffect(() => {
@@ -169,6 +183,71 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
 
   return (
     <>
+      <div className="px-2 flex gap-2 items-center flex-wrap mt-2">
+        {highlightedCodeSections.length > 1 && (
+          <>
+            <HeaderButtonWithText
+              text="Clear Context"
+              onClick={() => {
+                props.deleteContextItems(
+                  highlightedCodeSections.map((_, idx) => idx)
+                );
+              }}
+            >
+              <Trash size="1.6em" />
+            </HeaderButtonWithText>
+          </>
+        )}
+        {highlightedCodeSections.map((section, idx) => (
+          <PillButton
+            editing={section.editing}
+            pinned={section.pinned}
+            index={idx}
+            key={`${section.filepath}${idx}`}
+            title={`${section.range.filepath} (${
+              section.range.range.start.line + 1
+            }-${section.range.range.end.line + 1})`}
+            onDelete={() => {
+              if (props.deleteContextItems) {
+                props.deleteContextItems([idx]);
+              }
+              setHighlightedCodeSections((prev) => {
+                const newSections = [...prev];
+                newSections.splice(idx, 1);
+                return newSections;
+              });
+            }}
+            onHover={(val: boolean) => {
+              if (val) {
+                setHoveringButton(val);
+              } else {
+                setTimeout(() => {
+                  setHoveringButton(val);
+                }, 100);
+              }
+            }}
+          />
+        ))}
+        {props.highlightedCodeSections.length > 0 &&
+          (props.addingHighlightedCode ? (
+            <EmptyPillDiv
+              onClick={() => {
+                props.onToggleAddContext();
+              }}
+            >
+              Highlight to Add Context
+            </EmptyPillDiv>
+          ) : (
+            <HeaderButtonWithText
+              text="Add to Context"
+              onClick={() => {
+                props.onToggleAddContext();
+              }}
+            >
+              <DocumentPlus width="1.6em"></DocumentPlus>
+            </HeaderButtonWithText>
+          ))}
+      </div>
       <div className="flex px-2" ref={divRef} hidden={!isOpen}>
         <MainTextInput
           disabled={props.disabled}
@@ -260,80 +339,10 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
             ))}
         </Ul>
       </div>
-      <div className="px-2 flex gap-2 items-center flex-wrap">
-        {highlightedCodeSections.length === 0 && (
-          <HeaderButtonWithText
-            text={
-              props.addingHighlightedCode ? "Adding Context" : "Add Context"
-            }
-            onClick={() => {
-              props.onToggleAddContext();
-            }}
-            inverted={props.addingHighlightedCode}
-          >
-            <Plus size="1.6em" />
-          </HeaderButtonWithText>
-        )}
-        {highlightedCodeSections.length > 0 && (
-          <>
-            <HeaderButtonWithText
-              text="Clear Context"
-              onClick={() => {
-                props.deleteContextItems(
-                  highlightedCodeSections.map((_, idx) => idx)
-                );
-              }}
-            >
-              <Trash size="1.6em" />
-            </HeaderButtonWithText>
-            <HeaderButtonWithText
-              text={pinned ? "Unpin Context" : "Pin Context"}
-              inverted={pinned}
-              onClick={() => {
-                setPinned((prev) => !prev);
-                props.onTogglePin();
-              }}
-            >
-              {pinned ? (
-                <LockClosed size="1.6em"></LockClosed>
-              ) : (
-                <LockOpen size="1.6em"></LockOpen>
-              )}
-            </HeaderButtonWithText>
-          </>
-        )}
-        {highlightedCodeSections.map((section, idx) => (
-          <PillButton
-            title={`${section.filepath} (${section.range.start.line + 1}-${
-              section.range.end.line + 1
-            })`}
-            onDelete={() => {
-              if (props.deleteContextItems) {
-                props.deleteContextItems([idx]);
-              }
-              setHighlightedCodeSections((prev) => {
-                const newSections = [...prev];
-                newSections.splice(idx, 1);
-                return newSections;
-              });
-            }}
-            onHover={(val: boolean) => {
-              if (val) {
-                setHoveringButton(val);
-              } else {
-                setTimeout(() => {
-                  setHoveringButton(val);
-                }, 100);
-              }
-            }}
-          />
-        ))}
-
-        <span className="text-trueGray-400 ml-auto mr-4 text-xs text-right">
-          Highlight code to include as context. Currently open file included by
-          default. {highlightedCodeSections.length === 0 && ""}
-        </span>
-      </div>
+      {/* <span className="text-trueGray-400 ml-auto m-auto text-xs text-right">
+        Highlight code to include as context. Currently open file included by
+        default. {highlightedCodeSections.length === 0 && ""}
+      </span> */}
       <ContextDropdown
         onMouseEnter={() => {
           setHoveringContextDropdown(true);
@@ -345,9 +354,9 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
       >
         {highlightedCodeSections.map((section, idx) => (
           <>
-            <p>{section.filepath}</p>
+            <p>{section.range.filepath}</p>
             <CodeBlock showCopy={false} key={idx}>
-              {section.contents}
+              {section.range.contents}
             </CodeBlock>
           </>
         ))}
-- 
cgit v1.2.3-70-g09d2


From 1f4878f89549e6c9ccc3483a47b9f3a95c6ee9f4 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Thu, 6 Jul 2023 00:25:41 -0700
Subject: fixing command history and dropdown

---
 extension/package-lock.json                        |  4 +-
 extension/package.json                             |  2 +-
 extension/react-app/src/components/ComboBox.tsx    | 53 +++++++++++++---------
 .../react-app/src/components/StepContainer.tsx     |  2 +-
 extension/react-app/src/tabs/gui.tsx               | 11 ++++-
 5 files changed, 44 insertions(+), 28 deletions(-)

(limited to 'extension/react-app/src/components/ComboBox.tsx')

diff --git a/extension/package-lock.json b/extension/package-lock.json
index b322acb7..b34d1c61 100644
--- a/extension/package-lock.json
+++ b/extension/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "continue",
-  "version": "0.0.113",
+  "version": "0.0.114",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "continue",
-      "version": "0.0.113",
+      "version": "0.0.114",
       "license": "Apache-2.0",
       "dependencies": {
         "@electron/rebuild": "^3.2.10",
diff --git a/extension/package.json b/extension/package.json
index 09703da4..4c972e86 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -14,7 +14,7 @@
   "displayName": "Continue",
   "pricing": "Free",
   "description": "The open-source coding autopilot",
-  "version": "0.0.113",
+  "version": "0.0.114",
   "publisher": "Continue",
   "engines": {
     "vscode": "^1.67.0"
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx
index 7ee5dc24..af673b42 100644
--- a/extension/react-app/src/components/ComboBox.tsx
+++ b/extension/react-app/src/components/ComboBox.tsx
@@ -79,7 +79,7 @@ const MainTextInput = styled.textarea`
   }
 `;
 
-const UlMaxHeight = 400;
+const UlMaxHeight = 300;
 const Ul = styled.ul<{
   hidden: boolean;
   showAbove: boolean;
@@ -94,13 +94,20 @@ const Ul = styled.ul<{
   background-color: ${secondaryDark};
   color: white;
   max-height: ${UlMaxHeight}px;
-  overflow: scroll;
+  overflow-y: scroll;
+  overflow-x: hidden;
   padding: 0;
   ${({ hidden }) => hidden && "display: none;"}
   border-radius: ${defaultBorderRadius};
-  overflow: hidden;
   border: 0.5px solid gray;
   z-index: 2;
+  // Get rid of scrollbar and its padding
+  scrollbar-width: none;
+  -ms-overflow-style: none;
+  &::-webkit-scrollbar {
+    width: 0px;
+    background: transparent; /* make scrollbar transparent */
+  }
 `;
 
 const Li = styled.li<{
@@ -108,7 +115,7 @@ const Li = styled.li<{
   selected: boolean;
   isLastItem: boolean;
 }>`
-  ${({ highlighted }) => highlighted && "background: #aa0000;"}
+  ${({ highlighted }) => highlighted && "background: #ff000066;"}
   ${({ selected }) => selected && "font-weight: bold;"}
     padding: 0.5rem 0.75rem;
   display: flex;
@@ -272,6 +279,12 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
                 event.key === "Enter" &&
                 (!isOpen || items.length === 0)
               ) {
+                setInputValue("");
+                const value = event.currentTarget.value;
+                if (value !== "") {
+                  setPositionInHistory(history.length + 1);
+                  setHistory([...history, value]);
+                }
                 // Prevent Downshift's default 'Enter' behavior.
                 (event.nativeEvent as any).preventDownshiftDefault = true;
 
@@ -280,33 +293,28 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
                   event.currentTarget.value = `/edit ${event.currentTarget.value}`;
                 }
                 if (props.onEnter) props.onEnter(event);
-                setInputValue("");
-                const value = event.currentTarget.value;
-                if (value !== "") {
-                  setPositionInHistory(history.length + 1);
-                  setHistory([...history, value]);
-                }
               } else if (event.key === "Tab" && items.length > 0) {
                 setInputValue(items[0].name);
                 event.preventDefault();
               } 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.key === "ArrowUp" || event.key === "ArrowDown") &&
                 event.currentTarget.value.split("\n").length > 1
               ) {
+                (event.nativeEvent as any).preventDownshiftDefault = true;
+              } else if (event.key === "ArrowUp") {
+                console.log("OWJFOIJO");
                 if (positionInHistory == 0) return;
+                else if (
+                  positionInHistory == history.length &&
+                  (history.length === 0 ||
+                    history[history.length - 1] !== event.currentTarget.value)
+                ) {
+                  setHistory([...history, event.currentTarget.value]);
+                }
                 setInputValue(history[positionInHistory - 1]);
                 setPositionInHistory((prev) => prev - 1);
-              } else if (
-                event.key === "ArrowDown" &&
-                event.currentTarget.value.split("\n").length > 1
-              ) {
-                if (positionInHistory < history.length - 1) {
+              } else if (event.key === "ArrowDown") {
+                if (positionInHistory < history.length) {
                   setInputValue(history[positionInHistory + 1]);
                 }
                 setPositionInHistory((prev) =>
@@ -327,6 +335,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {
           {isOpen &&
             items.map((item, index) => (
               <Li
+                style={{ borderTop: index === 0 ? "none" : undefined }}
                 key={`${item.name}${index}`}
                 {...getItemProps({ item, index })}
                 highlighted={highlightedIndex === index}
diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx
index 91d7b8ef..590b1166 100644
--- a/extension/react-app/src/components/StepContainer.tsx
+++ b/extension/react-app/src/components/StepContainer.tsx
@@ -206,7 +206,7 @@ function StepContainer(props: StepContainerProps) {
                   e.stopPropagation();
                   props.onDelete();
                 }}
-                text={props.historyNode.active ? "Stop" : "Delete"}
+                text={props.historyNode.active ? "Stop (⌘⌫)" : "Delete"}
               >
                 {props.historyNode.active ? (
                   <StopCircle size="1.6em" onClick={props.onDelete} />
diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx
index 3cce30de..ca369547 100644
--- a/extension/react-app/src/tabs/gui.tsx
+++ b/extension/react-app/src/tabs/gui.tsx
@@ -139,9 +139,16 @@ function GUI(props: GUIProps) {
 
   useEffect(() => {
     const listener = (e: any) => {
-      // Cmd + J to toggle fast model
+      // Cmd + i to toggle fast model
       if (e.key === "i" && e.metaKey && e.shiftKey) {
         setUsingFastModel((prev) => !prev);
+        // Cmd + backspace to stop currently running step
+      } else if (
+        e.key === "Backspace" &&
+        e.metaKey &&
+        typeof history?.current_index !== "undefined"
+      ) {
+        client?.deleteAtIndex(history.current_index);
       }
     };
     window.addEventListener("keydown", listener);
@@ -149,7 +156,7 @@ function GUI(props: GUIProps) {
     return () => {
       window.removeEventListener("keydown", listener);
     };
-  }, []);
+  }, [client, history]);
 
   useEffect(() => {
     client?.onStateUpdate((state: FullState) => {
-- 
cgit v1.2.3-70-g09d2

