From 98e07e1c7fcc0c5fe85145ac9ef7b6a591d3bcc1 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Thu, 29 May 2025 17:23:55 -0700 Subject: [PATCH] misc ui --- .voidrules | 2 + .../void/browser/react/src/util/inputs.tsx | 107 +++++++++++++----- .../react/src/void-settings-tsx/Settings.tsx | 4 +- 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/.voidrules b/.voidrules index 0c9e6204..59586971 100644 --- a/.voidrules +++ b/.voidrules @@ -8,3 +8,5 @@ Look for services and built-in functions that you might need to use to solve the In typescript, do NOT cast to types if not neccessary. NEVER lazily cast to 'any'. Find the correct type to apply and use it. Do not add or remove semicolons to any of my files. Just go with convention and make the least number of changes. + +Never modify files outside src/vs/workbench/contrib/void without consulting with the user first. diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx index a8e411ec..a2239f85 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/util/inputs.tsx @@ -21,7 +21,7 @@ import { getBasename, getFolderName } from '../sidebar-tsx/SidebarChat.js'; import { ChevronRight, File, Folder, FolderClosed, LucideProps } from 'lucide-react'; import { StagingSelectionItem } from '../../../../common/chatThreadServiceTypes.js'; import { DiffEditorWidget } from '../../../../../../../editor/browser/widget/diffEditor/diffEditorWidget.js'; -import { extractSearchReplaceBlocks } from '../../../../common/helpers/extractCodeFromResult.js'; +import { extractSearchReplaceBlocks, ExtractedSearchReplaceBlock } from '../../../../common/helpers/extractCodeFromResult.js'; import { IAccessibilitySignalService } from '../../../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js'; import { IEditorProgressService } from '../../../../../../../platform/progress/common/progress.js'; import { detectLanguage } from '../../../../common/helpers/languageHelpers.js'; @@ -1844,33 +1844,16 @@ export const VoidButtonBgDarken = ({ children, disabled, onClick, className }: { // return
; // }; -/** - * ToolDiffEditor mounts a native VSCode DiffEditorWidget to show a diff between original and modified code blocks. - * Props: - * - uri: URI of the file (for language detection, etc) - * - searchReplaceBlocks: string in search/replace format (from LLM) - * - language?: string (optional, fallback to 'plaintext') - */ -export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: any, searchReplaceBlocks: string, language?: string }) => { + + + +const SingleDiffEditor = ({ block, lang }: { block: ExtractedSearchReplaceBlock, lang: string | undefined }) => { const accessor = useAccessor(); const modelService = accessor.get('IModelService'); const instantiationService = accessor.get('IInstantiationService'); const languageService = accessor.get('ILanguageService'); - const contextKeyService = accessor.get('IContextKeyService'); - const codeEditorService = accessor.get('ICodeEditorService'); - // Extract the first block (if present) - const blocks = extractSearchReplaceBlocks(searchReplaceBlocks); - const block = blocks[0] || { orig: '', final: '' }; - - // Use detectLanguage for language detection if not provided - let lang = language; - if (!lang) { - lang = detectLanguage(languageService, { uri: uri ?? null, fileContents: block.orig }); - } - - // Use ILanguageSelection for model creation - const languageSelection = useMemo(() => languageService.createById(lang!), [lang, languageService]); + const languageSelection = useMemo(() => languageService.createById(lang), [lang, languageService]); // Create models for original and modified const originalModel = useMemo(() => @@ -1906,7 +1889,7 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a renderSideBySide: true, minimap: { enabled: false }, lineNumbers: 'off', - scrollbar: { vertical: 'auto', horizontal: 'auto', verticalScrollbarSize: 8, horizontalScrollbarSize: 8 }, + scrollbar: { vertical: 'hidden', horizontal: 'auto', verticalScrollbarSize: 0, horizontalScrollbarSize: 8 }, hover: { enabled: false }, folding: false, selectionHighlight: false, @@ -1916,20 +1899,92 @@ export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: a overviewRulerBorder: false, glyphMargin: false, stickyScroll: { enabled: false }, + scrollBeyondLastLine: false, + renderGutterMenu: false, + renderIndicators: false, }, { originalEditor: { isSimpleWidget: true }, modifiedEditor: { isSimpleWidget: true } } ); editor.setModel({ original: originalModel, modified: modifiedModel }); - editor.layout(); + + // Calculate the height based on content + const updateHeight = () => { + const contentHeight = Math.max( + originalModel.getLineCount() * 19, // approximate line height + modifiedModel.getLineCount() * 19 + ) + 19 * 2 + 1; // add padding + + // Set reasonable min/max heights + const height = Math.min(Math.max(contentHeight, 100), 300); + if (divRef.current) { + divRef.current.style.height = `${height}px`; + editor.layout(); + } + }; + + updateHeight(); editorRef.current = editor; + + // Update height when content changes + const disposable1 = originalModel.onDidChangeContent(() => updateHeight()); + const disposable2 = modifiedModel.onDidChangeContent(() => updateHeight()); + return () => { + disposable1.dispose(); + disposable2.dispose(); editor.dispose(); editorRef.current = null; }; }, [originalModel, modifiedModel, instantiationService]); return ( -
+
+ ); +}; + + + + + +/** + * ToolDiffEditor mounts a native VSCode DiffEditorWidget to show a diff between original and modified code blocks. + * Props: + * - uri: URI of the file (for language detection, etc) + * - searchReplaceBlocks: string in search/replace format (from LLM) + * - language?: string (optional, fallback to 'plaintext') + */ +export const VoidDiffEditor = ({ uri, searchReplaceBlocks, language }: { uri?: any, searchReplaceBlocks: string, language?: string }) => { + const accessor = useAccessor(); + const languageService = accessor.get('ILanguageService'); + + // Extract all blocks + const blocks = extractSearchReplaceBlocks(searchReplaceBlocks); + + // Use detectLanguage for language detection if not provided + let lang = language; + if (!lang && blocks.length > 0) { + lang = detectLanguage(languageService, { uri: uri ?? null, fileContents: blocks[0].orig }); + } + + // If no blocks, show empty state + if (blocks.length === 0) { + return
No changes found
; + } + + // Display all blocks + return ( +
+ {blocks.map((block, index) => ( +
+ {blocks.length > 1 && ( +
+ Change {index + 1} of {blocks.length} +
+ )} + +
+ ))} +
); }; diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx index 8b2cffbb..8cef3295 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx @@ -456,7 +456,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN {/* left part is width:full */}
{isNewProviderName ? providerTitle : ''} - {modelName} + {modelName}
{/* right part is anything that fits */} @@ -495,7 +495,7 @@ export const ModelDump = ({ filteredProviders }: { filteredProviders?: ProviderN {/* X button */}
- {type === 'default' || type === 'autodetected' ? null :