diff --git a/TODO.md b/TODO.md index e0ad9a3a..fccebc17 100644 --- a/TODO.md +++ b/TODO.md @@ -122,6 +122,10 @@ [x] bug: add text, add file go back and edit the text fixed by prepending the command to the value [x] ctrl-z then enter, cursor is at wrong position [x] @, enter, enter, ctrl-z, enter +[x] allow paste when no code is selected (A convenient way to insert code from the chat into the active tab (where the cursor is) is needed.) +[ ] combobox theme not working in vscode +[x] use a different way to disable attach than if context file is there +[ ] remove snippet ### EVENTS TODO FOR IDEs diff --git a/src/components/Buttons/Buttons.tsx b/src/components/Buttons/Buttons.tsx index 7c81a049..ad285634 100644 --- a/src/components/Buttons/Buttons.tsx +++ b/src/components/Buttons/Buttons.tsx @@ -40,12 +40,11 @@ export const RightButton: React.FC = ( ); }; -export const RightButtonGroup: React.FC< - React.PropsWithChildren & { - className?: string; - direction?: "row" | "column"; - } -> = (props) => { +type FlexProps = React.ComponentProps; + +export const RightButtonGroup: React.FC = ( + props, +) => { return ( > = (props) => { requestCommandsCompletion: noop, attachFile: { name: "", + line1: null, + line2: null, can_paste: false, attach: false, }, diff --git a/src/components/ChatForm/ChatForm.stories.tsx b/src/components/ChatForm/ChatForm.stories.tsx index 5ad75b5b..daed7020 100644 --- a/src/components/ChatForm/ChatForm.stories.tsx +++ b/src/components/ChatForm/ChatForm.stories.tsx @@ -75,6 +75,8 @@ const meta = { name: "todo.md", can_paste: true, attach: false, + line1: 1, + line2: 100, }, filesInPreview: [ { diff --git a/src/components/ChatForm/ChatForm.tsx b/src/components/ChatForm/ChatForm.tsx index 63063dfd..cf271033 100644 --- a/src/components/ChatForm/ChatForm.tsx +++ b/src/components/ChatForm/ChatForm.tsx @@ -77,7 +77,6 @@ export const ChatForm: React.FC = ({ canChangeModel, isStreaming, onStopStreaming, - hasContextFile, commands, attachFile, requestCommandsCompletion, @@ -129,26 +128,34 @@ export const ChatForm: React.FC = ({ ); } - const checked = value.includes(`@file ${attachFile.name}`); + // TODO: handle multiple files? + const commandUpToWhiteSpace = /@file ([^\s]+)/; + const checked = commandUpToWhiteSpace.test(value); + const lines = + attachFile.line1 !== null && attachFile.line2 !== null + ? `:${attachFile.line1}-${attachFile.line2}` + : ""; + const nameWithLines = `${attachFile.name}${lines}`; return ( {!isOnline && Offline} - {config.host !== "web" && !hasContextFile && ( + {config.host !== "web" && ( setValue((preValue) => { - const command = `@file ${attachFile.name}${ - value.length > 0 ? "\n" : "" - }`; if (checked) { - return preValue.replace(command, ""); + return preValue.replace(commandUpToWhiteSpace, ""); } + const command = `@file ${nameWithLines}${ + value.length > 0 ? "\n" : "" + }`; return `${command}${preValue}`; }) } checked={checked} + disabled={!attachFile.can_paste} /> )} diff --git a/src/components/FileUpload/FileUpload.tsx b/src/components/FileUpload/FileUpload.tsx index db5a9ad0..7ab588c7 100644 --- a/src/components/FileUpload/FileUpload.tsx +++ b/src/components/FileUpload/FileUpload.tsx @@ -5,14 +5,15 @@ export const FileUpload: React.FC<{ onClick: (value: boolean) => void; fileName?: string; checked: boolean; -}> = ({ onClick, fileName, checked }) => { + disabled?: boolean; +}> = ({ onClick, fileName, ...props }) => { return ( { - onClick(!checked); + onClick(!props.checked); }} />{" "} Attach {fileName ?? "a file"} diff --git a/src/components/Markdown/Pre.tsx b/src/components/Markdown/Pre.tsx index d61b6db9..1518d03a 100644 --- a/src/components/Markdown/Pre.tsx +++ b/src/components/Markdown/Pre.tsx @@ -28,20 +28,30 @@ const PreTagWithButtons: React.FC< {config.host === "web" ? ( Copy ) : ( - - + + + {canPaste && ( + + )} - {canPaste && ( - - )} )} {children} diff --git a/src/events/chat.ts b/src/events/chat.ts index 1db57b9c..4f6b42e9 100644 --- a/src/events/chat.ts +++ b/src/events/chat.ts @@ -232,7 +232,16 @@ export function isToggleActiveFile( } export interface ActiveFileInfo extends ActionToChat { type: EVENT_NAMES_TO_CHAT.ACTIVE_FILE_INFO; - payload: { id: string; name: string; can_paste: boolean }; + payload: { + id: string; + file: Partial<{ + name: string; + line1: number | null; + line2: number | null; + can_paste: boolean; + attach: boolean; + }>; + }; } export function isActiveFileInfo(action: unknown): action is ActiveFileInfo { @@ -286,7 +295,9 @@ export function isBackupMessages(action: unknown): action is BackUpMessages { export interface RestoreChat extends ActionToChat { type: EVENT_NAMES_TO_CHAT.RESTORE_CHAT; - payload: ChatThread & { snippet?: Snippet }; + payload: (ChatThread & { snippet?: Snippet }) & { + messages: ChatThread["messages"] | [string, string][]; + }; } export function isRestoreChat(action: unknown): action is RestoreChat { diff --git a/src/hooks/useEventBusForChat.ts b/src/hooks/useEventBusForChat.ts index 346ed0f7..9c598706 100644 --- a/src/hooks/useEventBusForChat.ts +++ b/src/hooks/useEventBusForChat.ts @@ -240,13 +240,11 @@ function reducer(state: ChatState, action: ActionToChat): ChatState { } if (isThisChat && isActiveFileInfo(action)) { - const { name, can_paste } = action.payload; return { ...state, active_file: { - name, - can_paste, - attach: state.active_file.attach, + ...state.active_file, + ...action.payload.file, }, }; } @@ -355,6 +353,8 @@ export type ChatState = { name: string; attach: boolean; can_paste: boolean; + line1: null | number; + line2: null | number; }; selected_snippet: Snippet; }; @@ -390,6 +390,8 @@ function createInitialState(): ChatState { active_file: { name: "", + line1: null, + line2: null, attach: false, can_paste: false, },