From 18656372f8f8e6548f868fb9c43abe659b18b140 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 20 Oct 2024 23:24:40 -0700 Subject: [PATCH] add ctrlk, autofocus chatbar --- extensions/void/package.json | 2 +- extensions/void/src/SidebarWebviewProvider.ts | 5 +- extensions/void/src/common/shared_types.ts | 1 + extensions/void/src/extension.ts | 47 ++++++++++---- extensions/void/src/sidebar/CtrlK.tsx | 20 ++++++ extensions/void/src/sidebar/Sidebar.tsx | 37 ++++------- extensions/void/src/sidebar/SidebarChat.tsx | 3 +- extensions/void/src/sidebar/getVscodeApi.ts | 2 + extensions/void/src/sidebar/index.tsx | 63 ++++++++++++++++--- .../void/src/sidebar/metrics/posthog.tsx | 21 +++---- 10 files changed, 136 insertions(+), 65 deletions(-) create mode 100644 extensions/void/src/sidebar/CtrlK.tsx diff --git a/extensions/void/package.json b/extensions/void/package.json index 531357e1..acbf0266 100644 --- a/extensions/void/package.json +++ b/extensions/void/package.json @@ -24,7 +24,7 @@ }, { "command": "void.ctrl+k", - "title": "Show Selection Lens" + "title": "Make Inline Edit" }, { "command": "void.acceptDiff", diff --git a/extensions/void/src/SidebarWebviewProvider.ts b/extensions/void/src/SidebarWebviewProvider.ts index c8aaffba..0c2ed5a5 100644 --- a/extensions/void/src/SidebarWebviewProvider.ts +++ b/extensions/void/src/SidebarWebviewProvider.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; -function getNonce() { +function generateNonce() { let text = ""; const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (let i = 0; i < 32; i++) { @@ -39,7 +39,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider { const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/index.js')); const stylesUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/styles.css')); const rootUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri)); - const nonce = getNonce(); + const nonce = generateNonce(); const webviewHTML = ` @@ -53,6 +53,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
+
`; diff --git a/extensions/void/src/common/shared_types.ts b/extensions/void/src/common/shared_types.ts index ae8363d6..e7373266 100644 --- a/extensions/void/src/common/shared_types.ts +++ b/extensions/void/src/common/shared_types.ts @@ -41,6 +41,7 @@ type Diff = { // editor -> sidebar type MessageToSidebar = ( | { type: 'ctrl+l', selection: CodeSelection } // user presses ctrl+l in the editor + | { type: 'ctrl+k', selection: CodeSelection } | { type: 'files', files: { filepath: vscode.Uri, content: string }[] } | { type: 'partialVoidConfig', partialVoidConfig: PartialVoidConfig } | { type: 'allThreads', threads: ChatThreads } diff --git a/extensions/void/src/extension.ts b/extensions/void/src/extension.ts index 7a55caa8..edd2f993 100644 --- a/extensions/void/src/extension.ts +++ b/extensions/void/src/extension.ts @@ -9,37 +9,60 @@ const readFileContentOfUri = async (uri: vscode.Uri) => { .replace(/\r\n/g, '\n') // replace windows \r\n with \n } +const roundRangeToLines = (selection: vscode.Selection) => { + return new vscode.Range(selection.start.line, 0, selection.end.line, Number.MAX_SAFE_INTEGER) +} + export function activate(context: vscode.ExtensionContext) { // 1. Mount the chat sidebar - const webviewProvider = new SidebarWebviewProvider(context); + const sidebarWebviewProvider = new SidebarWebviewProvider(context); context.subscriptions.push( - vscode.window.registerWebviewViewProvider(SidebarWebviewProvider.viewId, webviewProvider, { webviewOptions: { retainContextWhenHidden: true } }) + vscode.window.registerWebviewViewProvider(SidebarWebviewProvider.viewId, sidebarWebviewProvider, { webviewOptions: { retainContextWhenHidden: true } }) ); - // 2. Activate the sidebar on ctrl+l + // 2. ctrl+l context.subscriptions.push( vscode.commands.registerCommand('void.ctrl+l', () => { - const editor = vscode.window.activeTextEditor - if (!editor) - return + if (!editor) return // show the sidebar vscode.commands.executeCommand('workbench.view.extension.voidViewContainer'); // vscode.commands.executeCommand('vscode.moveViewToPanel', CustomViewProvider.viewId); // move to aux bar - // get the text the user is selecting - const selectionStr = editor.document.getText(editor.selection); - // get the range of the selection - const selectionRange = editor.selection; + const selectionRange = roundRangeToLines(editor.selection); + + // get the text the user is selecting + const selectionStr = editor.document.getText(selectionRange); // get the file the user is in const filePath = editor.document.uri; // send message to the webview (Sidebar.tsx) - webviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+l', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); + sidebarWebviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+l', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); + }) + ); + + // 2.5: ctrl+k + context.subscriptions.push( + vscode.commands.registerCommand('void.ctrl+k', () => { + console.log('CTRLK PRESSED') + const editor = vscode.window.activeTextEditor + if (!editor) return + + // get the range of the selection + const selectionRange = roundRangeToLines(editor.selection); + + // get the text the user is selecting + const selectionStr = editor.document.getText(selectionRange); + + // get the file the user is in + const filePath = editor.document.uri; + + // send message to the webview (Sidebar.tsx) + sidebarWebviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+k', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); }) ); @@ -56,7 +79,7 @@ export function activate(context: vscode.ExtensionContext) { })); // 5. Receive messages from sidebar - webviewProvider.webview.then( + sidebarWebviewProvider.webview.then( webview => { // top navigation bar commands diff --git a/extensions/void/src/sidebar/CtrlK.tsx b/extensions/void/src/sidebar/CtrlK.tsx new file mode 100644 index 00000000..89797e3e --- /dev/null +++ b/extensions/void/src/sidebar/CtrlK.tsx @@ -0,0 +1,20 @@ +import React, { useState } from 'react'; +import { useOnVSCodeMessage } from './getVscodeApi'; + + +export const CtrlK = () => { + + const [x, sx] = useState('abc') + + useOnVSCodeMessage('ctrl+k', () => { + console.log('Ctrl+K pressed') + sx('Pressed ctrl+k') + }) + + return <> +
+ {x} +
+ +}; + diff --git a/extensions/void/src/sidebar/Sidebar.tsx b/extensions/void/src/sidebar/Sidebar.tsx index d27283c8..0e226574 100644 --- a/extensions/void/src/sidebar/Sidebar.tsx +++ b/extensions/void/src/sidebar/Sidebar.tsx @@ -5,29 +5,26 @@ import { awaitVSCodeResponse, getVSCodeAPI, onMessageFromVSCode, useOnVSCodeMess import { SidebarThreadSelector } from "./SidebarThreadSelector"; import { SidebarChat } from "./SidebarChat"; import { SidebarSettings } from './SidebarSettings'; -import { identifyUser, useMetrics } from "./metrics/posthog"; +import { identifyUser } from "./metrics/posthog"; const Sidebar = () => { - useMetrics() - - // when we get the deviceid, identify the user - useEffect(() => { - getVSCodeAPI().postMessage({ type: 'getDeviceId' }); - awaitVSCodeResponse('deviceId').then((m => { - identifyUser(m.deviceId) - })) - }, []) - + const chatInputRef = useRef(null) const [tab, setTab] = useState<'threadSelector' | 'chat' | 'settings'>('chat') // if they pressed the + to add a new chat - useOnVSCodeMessage('startNewThread', (m) => { setTab('chat') }) + useOnVSCodeMessage('startNewThread', (m) => { + setTab('chat'); + chatInputRef.current?.focus(); + }) // ctrl+l should switch back to chat - useOnVSCodeMessage('ctrl+l', (m) => { setTab('chat') }) + useOnVSCodeMessage('ctrl+l', (m) => { + setTab('chat'); + chatInputRef.current?.focus(); + }) // if they toggled thread selector useOnVSCodeMessage('toggleThreadSelector', (m) => { @@ -45,18 +42,6 @@ const Sidebar = () => { setTab('settings') }) - // Receive messages from the VSCode extension - useEffect(() => { - const listener = (event: MessageEvent) => { - const m = event.data as MessageToSidebar; - onMessageFromVSCode(m) - } - window.addEventListener('message', listener); - return () => { window.removeEventListener('message', listener) } - }, []) - - - return <>
@@ -65,7 +50,7 @@ const Sidebar = () => {
- +
diff --git a/extensions/void/src/sidebar/SidebarChat.tsx b/extensions/void/src/sidebar/SidebarChat.tsx index be668c40..b7280b33 100644 --- a/extensions/void/src/sidebar/SidebarChat.tsx +++ b/extensions/void/src/sidebar/SidebarChat.tsx @@ -144,7 +144,7 @@ const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { -export const SidebarChat = () => { +export const SidebarChat = ({ chatInputRef }: { chatInputRef: React.RefObject }) => { // state of current message @@ -329,6 +329,7 @@ export const SidebarChat = () => { {/* input */}