diff options
Diffstat (limited to 'extension/react-app')
-rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 57 | ||||
-rw-r--r-- | extension/react-app/src/components/HeaderButtonWithText.tsx | 2 | ||||
-rw-r--r-- | extension/react-app/src/components/PillButton.tsx | 9 | ||||
-rw-r--r-- | extension/react-app/src/components/index.ts | 13 | ||||
-rw-r--r-- | extension/react-app/src/tabs/gui.tsx | 23 |
5 files changed, 82 insertions, 22 deletions
diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 742c643b..bdb8850d 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { useCombobox } from "downshift"; import styled from "styled-components"; import { @@ -10,7 +10,10 @@ import { import CodeBlock from "./CodeBlock"; import { RangeInFile } from "../../../src/client"; import PillButton from "./PillButton"; +import HeaderButtonWithText from "./HeaderButtonWithText"; +import { Trash, LockClosed, LockOpen } from "@styled-icons/heroicons-outline"; +// #region styled components const mainInputFontSize = 16; const ContextDropdown = styled.div` @@ -87,13 +90,16 @@ const Li = styled.li<{ cursor: pointer; `; +// #endregion + interface ComboBoxProps { items: { name: string; description: string }[]; onInputValueChange: (inputValue: string) => void; disabled?: boolean; - onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void; - highlightedCodeSections?: (RangeInFile & { contents: string })[]; - deleteContextItem?: (idx: number) => void; + onEnter: (e: React.KeyboardEvent<HTMLInputElement>) => void; + highlightedCodeSections: (RangeInFile & { contents: string })[]; + deleteContextItems: (indices: number[]) => void; + onTogglePin: () => void; } const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { @@ -104,6 +110,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { const [hoveringButton, setHoveringButton] = React.useState(false); const [hoveringContextDropdown, setHoveringContextDropdown] = React.useState(false); + const [pinned, setPinned] = useState(false); const [highlightedCodeSections, setHighlightedCodeSections] = React.useState( props.highlightedCodeSections || [ { @@ -242,12 +249,46 @@ 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="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} + title={ + hoveringButton + ? `${section.filepath} (${section.range.start.line + 1}-${ + section.range.end.line + 1 + })` + : section.filepath + } onDelete={() => { - if (props.deleteContextItem) { - props.deleteContextItem(idx); + if (props.deleteContextItems) { + props.deleteContextItems([idx]); } setHighlightedCodeSections((prev) => { const newSections = [...prev]; @@ -280,7 +321,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { onMouseLeave={() => { setHoveringContextDropdown(false); }} - hidden={!hoveringContextDropdown && !hoveringButton} + hidden={true || (!hoveringContextDropdown && !hoveringButton)} > {highlightedCodeSections.map((section, idx) => ( <> diff --git a/extension/react-app/src/components/HeaderButtonWithText.tsx b/extension/react-app/src/components/HeaderButtonWithText.tsx index 30931f86..3ddac93c 100644 --- a/extension/react-app/src/components/HeaderButtonWithText.tsx +++ b/extension/react-app/src/components/HeaderButtonWithText.tsx @@ -7,12 +7,14 @@ interface HeaderButtonWithTextProps { onClick?: (e: any) => void; children: React.ReactNode; disabled?: boolean; + inverted?: boolean; } const HeaderButtonWithText = (props: HeaderButtonWithTextProps) => { const [hover, setHover] = useState(false); return ( <HeaderButton + inverted={props.inverted} disabled={props.disabled} style={{ padding: "1px", paddingLeft: hover ? "4px" : "1px" }} onMouseEnter={() => { diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 33451db5..55fe1ac6 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import styled from "styled-components"; import { defaultBorderRadius } from "."; +import { XMark } from "@styled-icons/heroicons-outline"; const Button = styled.button` border: none; @@ -42,13 +43,12 @@ const PillButton = (props: PillButtonProps) => { <div style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: "4px" }} > - <span>{props.title}</span> <span style={{ cursor: "pointer", color: "red", - borderLeft: "1px solid black", - paddingLeft: "4px", + borderRight: "1px solid black", + paddingRight: "4px", }} hidden={!isHovered} onClick={() => { @@ -56,8 +56,9 @@ const PillButton = (props: PillButtonProps) => { props.onHover?.(false); }} > - X + <XMark style={{ padding: "0px" }} size="1.2em" strokeWidth="2px" /> </span> + <span>{props.title}</span> </div> </Button> ); diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 429a7df5..db1925ed 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -124,16 +124,19 @@ export const appear = keyframes` } `; -export const HeaderButton = styled.button` - background-color: transparent; +export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` + background-color: ${({ inverted }) => (inverted ? "white" : "transparent")}; + color: ${({ inverted }) => (inverted ? "black" : "white")}; + border: 1px solid white; border-radius: ${defaultBorderRadius}; cursor: pointer; - color: white; &:hover { - background-color: white; - color: black; + background-color: ${({ inverted }) => + typeof inverted === "undefined" || inverted ? "white" : "transparent"}; + color: ${({ inverted }) => + typeof inverted === "undefined" || inverted ? "black" : "white"}; } display: flex; align-items: center; diff --git a/extension/react-app/src/tabs/gui.tsx b/extension/react-app/src/tabs/gui.tsx index 0a9e48fb..c2ff101a 100644 --- a/extension/react-app/src/tabs/gui.tsx +++ b/extension/react-app/src/tabs/gui.tsx @@ -70,10 +70,13 @@ function GUI(props: GUIProps) { const [usingFastModel, setUsingFastModel] = useState(false); const [waitingForSteps, setWaitingForSteps] = useState(false); const [userInputQueue, setUserInputQueue] = useState<string[]>([]); - const [highlightedRanges, setHighlightedRanges] = useState([]); + const [highlightedRanges, setHighlightedRanges] = useState([ + { filepath: "abc.txt", range: { start: { line: 2 }, end: { line: 4 } } }, + ]); const [availableSlashCommands, setAvailableSlashCommands] = useState< { name: string; description: string }[] >([]); + const [pinned, setPinned] = useState(false); const [showDataSharingInfo, setShowDataSharingInfo] = useState(false); const [stepsOpen, setStepsOpen] = useState<boolean[]>([ true, @@ -185,9 +188,9 @@ function GUI(props: GUIProps) { const mainTextInputRef = useRef<HTMLInputElement>(null); - const deleteContextItem = useCallback( - (idx: number) => { - client?.deleteContextAtIndices([idx]); + const deleteContextItems = useCallback( + (indices: number[]) => { + client?.deleteContextAtIndices(indices); }, [client] ); @@ -241,6 +244,13 @@ function GUI(props: GUIProps) { setUserInputQueue((queue) => { return [...queue, input]; }); + + // Delete all context items unless locked + if (!pinned) { + client?.deleteContextAtIndices( + highlightedRanges.map((_, index) => index) + ); + } } }; @@ -345,7 +355,10 @@ function GUI(props: GUIProps) { onInputValueChange={() => {}} items={availableSlashCommands} highlightedCodeSections={highlightedRanges} - deleteContextItem={deleteContextItem} + deleteContextItems={deleteContextItems} + onTogglePin={() => { + setPinned((prev: boolean) => !prev); + }} /> <ContinueButton onClick={onMainTextInput} /> </TopGUIDiv> |