From 9cf4980004569175ffc7485d062751bd9ddacce8 Mon Sep 17 00:00:00 2001 From: mp Date: Sat, 21 Dec 2024 22:37:08 -0800 Subject: [PATCH] selection --- .../browser/react/src/markdown/BlockCode.tsx | 60 +++++++++++++++++++ .../react/src/sidebar-tsx/SidebarChat.tsx | 39 +++++++++--- .../void/browser/react/src/util/inputs.tsx | 29 ++++++--- .../src/void-settings-tsx/ModelDropdown.tsx | 17 ++++-- 4 files changed, 126 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/BlockCode.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/BlockCode.tsx index 479ea70b..46f9e086 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/BlockCode.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/BlockCode.tsx @@ -9,6 +9,66 @@ import { atomOneDarkReasonable } from "react-syntax-highlighter/dist/esm/styles/ import { VoidCodeEditor } from '../util/inputs.js'; + +export function getLanguageFromFileName(fileName: string): string { + if (!fileName) return 'plaintext'; + + const ext = fileName.toLowerCase().split('.').pop(); + if (!ext) return 'plaintext'; + + const extensionMap: { [key: string]: string } = { + // Web + 'html': 'html', + 'htm': 'html', + 'css': 'css', + 'scss': 'scss', + 'less': 'less', + 'js': 'javascript', + 'jsx': 'javascript', + 'ts': 'typescript', + 'tsx': 'typescript', + 'json': 'json', + 'jsonc': 'json', + + // Programming Languages + 'py': 'python', + 'java': 'java', + 'cpp': 'cpp', + 'cc': 'cpp', + 'h': 'cpp', + 'hpp': 'cpp', + 'cs': 'csharp', + 'go': 'go', + 'rs': 'rust', + 'rb': 'ruby', + 'php': 'php', + 'sh': 'shell', + 'bash': 'shell', + 'zsh': 'shell', + + // Markup/Config + 'md': 'markdown', + 'markdown': 'markdown', + 'xml': 'xml', + 'svg': 'xml', + 'yaml': 'yaml', + 'yml': 'yaml', + 'ini': 'ini', + 'toml': 'ini', + + // Other + 'sql': 'sql', + 'graphql': 'graphql', + 'gql': 'graphql', + 'dockerfile': 'dockerfile', + 'docker': 'dockerfile' + }; + + return extensionMap[ext] || 'plaintext'; +} + + + export const BlockCode = ({ text, buttonsOnHover, language }: { text: string, buttonsOnHover?: ReactNode, language?: string }) => { const customStyle = { diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx index b00954f9..73d3ae1e 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx @@ -9,7 +9,7 @@ import React, { ButtonHTMLAttributes, FormEvent, FormHTMLAttributes, Fragment, u import { useAccessor, useThreadsState } from '../util/services.js'; import { ChatMessage, CodeSelection, CodeStagingSelection, IThreadHistoryService } from '../../../threadHistoryService.js'; -import { BlockCode } from '../markdown/BlockCode.js'; +import { BlockCode, getLanguageFromFileName } from '../markdown/BlockCode.js'; import { ChatMarkdownRender } from '../markdown/ChatMarkdownRender.js'; import { URI } from '../../../../../../../base/common/uri.js'; import { EndOfLinePreference } from '../../../../../../../editor/common/model.js'; @@ -86,6 +86,29 @@ const IconSquare = ({ size, className = '' }: { size: number, className?: string ); }; + +export const IconWarning = ({ size, className = '' }: { size: number, className?: string }) => { + return ( + + {/* Warning triangle */} + + + {/* Exclamation mark */} + + + + ); +}; + type ButtonProps = ButtonHTMLAttributes export const ButtonSubmit = ({ className, disabled, ...props }: ButtonProps & Required>) => { return } @@ -192,7 +215,7 @@ export const SelectedFiles = ( > {selections.map((selection, i) => { - const showSelectionText = selection.selectionStr && selectionIsOpened[i] + const showSelectionText = !!(selection.selectionStr && selectionIsOpened[i]) return (
{ @@ -222,7 +247,7 @@ export const SelectedFiles = ( {/* type of selection */} - {selection.selectionStr !== null ? 'Selection' : 'File'} + {selection.selectionStr !== null ? 'Selection' : 'File'} {/* X button */} {type === 'staging' && // hoveredIdx === i @@ -241,7 +266,7 @@ export const SelectedFiles = ( {/* selection text */} {showSelectionText &&
- +
}
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 5995ea78..557d4dca 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 @@ -286,6 +286,9 @@ const normalizeIndentation = (code: string): string => { } export const VoidCodeEditor = ({ initValue, language }: { initValue: string, language: string | undefined }) => { + + const MAX_HEIGHT = 200; + const divRef = useRef(null) const accessor = useAccessor() @@ -302,10 +305,11 @@ export const VoidCodeEditor = ({ initValue, language }: { initValue: string, lan container, { automaticLayout: true, - wordWrap: 'on', + wordWrap: 'off', scrollbar: { - vertical: 'hidden', + vertical: 'auto', horizontal: 'auto', + alwaysConsumeMouseWheel: false }, lineNumbers: 'off', folding: false, @@ -326,26 +330,35 @@ export const VoidCodeEditor = ({ initValue, language }: { initValue: string, lan } onCreateInstance={useCallback((editor: CodeEditorWidget) => { - const model = modelService.createModel(initValue, null) editor.setModel(model); model.setLanguage(language ?? 'plaintext') const container = editor.getDomNode() const parentNode = container?.parentElement - if (parentNode) - parentNode.style.height = `${editor.getScrollHeight() + 1}px` // the +1 is if there's a half pixel issue + if (parentNode) { + const height = Math.min(editor.getScrollHeight() + 1, MAX_HEIGHT); + parentNode.style.height = `${height}px`; + editor.layout(); + } - return [] + // Listen for content changes and update height + const disposable = editor.onDidContentSizeChange(() => { + if (parentNode) { + const height = Math.min(editor.getScrollHeight() + 1, MAX_HEIGHT); + parentNode.style.height = `${height}px`; + editor.layout(); + } + }); + + return [disposable] }, [modelService, initValue, language])} dispose={useCallback((editor: CodeEditorWidget) => { editor.dispose(); }, [])} - // ignored propsFn={useCallback(() => { return [] }, [])} - /> diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx index edb55f90..2ec2db72 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/ModelDropdown.tsx @@ -8,6 +8,7 @@ import { FeatureName, featureNames, ModelSelection, modelSelectionsEqual, Provid import { useSettingsState, useRefreshModelState, useAccessor } from '../util/services.js' import { VoidSelectBox } from '../util/inputs.js' import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js' +import { IconWarning } from '../sidebar-tsx/SidebarChat.js' const ModelSelectBox = ({ featureName }: { featureName: FeatureName }) => { @@ -42,10 +43,18 @@ const ModelSelectBox = ({ featureName }: { featureName: FeatureName }) => { } const DummySelectBox = () => { - return { }} - /> + + return
+ + Add a model +
+ // return { }} + // /> } export const ModelDropdown = ({ featureName }: { featureName: FeatureName }) => {