From 2ec0b4118bd092a528a1171df6ae4ffcd7cfb33b Mon Sep 17 00:00:00 2001 From: Nate Sesti Date: Tue, 4 Jul 2023 12:47:28 -0700 Subject: better control over context --- extension/react-app/src/components/ComboBox.tsx | 57 +++++++++++++++++++--- .../src/components/HeaderButtonWithText.tsx | 2 + extension/react-app/src/components/PillButton.tsx | 9 ++-- extension/react-app/src/components/index.ts | 13 +++-- extension/react-app/src/tabs/gui.tsx | 23 +++++++-- 5 files changed, 82 insertions(+), 22 deletions(-) (limited to 'extension/react-app') 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) => void; - highlightedCodeSections?: (RangeInFile & { contents: string })[]; - deleteContextItem?: (idx: number) => void; + onEnter: (e: React.KeyboardEvent) => 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) => {
+ {highlightedCodeSections.length > 0 && ( + <> + { + props.deleteContextItems( + highlightedCodeSections.map((_, idx) => idx) + ); + }} + > + + + { + setPinned((prev) => !prev); + props.onTogglePin(); + }} + > + {pinned ? ( + + ) : ( + + )} + + + )} {highlightedCodeSections.map((section, idx) => ( { - 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 ( { 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) => {
- {props.title} + {props.title}
); 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([]); - 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([ true, @@ -185,9 +188,9 @@ function GUI(props: GUIProps) { const mainTextInputRef = useRef(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); + }} /> -- cgit v1.2.3-70-g09d2