FIX: Enable scrollbars in CodeMirror editors and complete missing i18n
CodeMirror Scrollbar Fixes:
- Add EditorView.theme configurations with overflow: auto for .cm-scroller
- Configure scrollPastEnd: false in basicSetup for all CodeMirror instances
- Fix FileViewer, CredentialEditor, HostManagerEditor, and FileManagerFileEditor
- Ensure proper height: 100% styling for editor containers
i18n Completion:
- Add missing "movedItems" translation key for file move operations
- English: "Moved {{count}} items"
- Chinese: "已移动 {{count}} 个项目"
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -737,6 +737,7 @@
|
|||||||
"deleteFiles": "Delete {{count}} items",
|
"deleteFiles": "Delete {{count}} items",
|
||||||
"filesCopiedToClipboard": "{{count}} items copied to clipboard",
|
"filesCopiedToClipboard": "{{count}} items copied to clipboard",
|
||||||
"filesCutToClipboard": "{{count}} items cut to clipboard",
|
"filesCutToClipboard": "{{count}} items cut to clipboard",
|
||||||
|
"movedItems": "Moved {{count}} items",
|
||||||
"failedToDeleteItem": "Failed to delete item",
|
"failedToDeleteItem": "Failed to delete item",
|
||||||
"itemRenamedSuccessfully": "{{type}} renamed successfully",
|
"itemRenamedSuccessfully": "{{type}} renamed successfully",
|
||||||
"failedToRenameItem": "Failed to rename item",
|
"failedToRenameItem": "Failed to rename item",
|
||||||
|
|||||||
@@ -760,6 +760,7 @@
|
|||||||
"deleteFiles": "删除 {{count}} 个项目",
|
"deleteFiles": "删除 {{count}} 个项目",
|
||||||
"filesCopiedToClipboard": "{{count}} 个项目已复制到剪贴板",
|
"filesCopiedToClipboard": "{{count}} 个项目已复制到剪贴板",
|
||||||
"filesCutToClipboard": "{{count}} 个项目已剪切到剪贴板",
|
"filesCutToClipboard": "{{count}} 个项目已剪切到剪贴板",
|
||||||
|
"movedItems": "已移动 {{count}} 个项目",
|
||||||
"failedToDeleteItem": "删除项目失败",
|
"failedToDeleteItem": "删除项目失败",
|
||||||
"itemRenamedSuccessfully": "{{type}}重命名成功",
|
"itemRenamedSuccessfully": "{{type}}重命名成功",
|
||||||
"failedToRenameItem": "重命名项目失败",
|
"failedToRenameItem": "重命名项目失败",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import CodeMirror from "@uiw/react-codemirror";
|
import CodeMirror from "@uiw/react-codemirror";
|
||||||
import { oneDark } from "@codemirror/theme-one-dark";
|
import { oneDark } from "@codemirror/theme-one-dark";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
import type {
|
import type {
|
||||||
Credential,
|
Credential,
|
||||||
CredentialEditorProps,
|
CredentialEditorProps,
|
||||||
@@ -934,7 +935,15 @@ export function CredentialEditor({
|
|||||||
allowMultipleSelections: false,
|
allowMultipleSelections: false,
|
||||||
highlightSelectionMatches: false,
|
highlightSelectionMatches: false,
|
||||||
searchKeymap: false,
|
searchKeymap: false,
|
||||||
|
scrollPastEnd: false,
|
||||||
}}
|
}}
|
||||||
|
extensions={[
|
||||||
|
EditorView.theme({
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
{detectedKeyType && (
|
{detectedKeyType && (
|
||||||
@@ -1089,7 +1098,15 @@ export function CredentialEditor({
|
|||||||
allowMultipleSelections: false,
|
allowMultipleSelections: false,
|
||||||
highlightSelectionMatches: false,
|
highlightSelectionMatches: false,
|
||||||
searchKeymap: false,
|
searchKeymap: false,
|
||||||
|
scrollPastEnd: false,
|
||||||
}}
|
}}
|
||||||
|
extensions={[
|
||||||
|
EditorView.theme({
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<div className="text-xs text-muted-foreground mt-1">
|
<div className="text-xs text-muted-foreground mt-1">
|
||||||
|
|||||||
@@ -320,16 +320,26 @@ export function FileManagerFileEditor({
|
|||||||
EditorView.theme({
|
EditorView.theme({
|
||||||
"&": {
|
"&": {
|
||||||
backgroundColor: "var(--color-dark-bg-darkest) !important",
|
backgroundColor: "var(--color-dark-bg-darkest) !important",
|
||||||
|
height: "100%",
|
||||||
},
|
},
|
||||||
".cm-gutters": {
|
".cm-gutters": {
|
||||||
backgroundColor: "var(--color-dark-bg) !important",
|
backgroundColor: "var(--color-dark-bg) !important",
|
||||||
},
|
},
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
".cm-editor": {
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
onChange={(value: any) => onContentChange(value)}
|
onChange={(value: any) => onContentChange(value)}
|
||||||
theme={undefined}
|
theme={undefined}
|
||||||
height="100%"
|
height="100%"
|
||||||
basicSetup={{ lineNumbers: true }}
|
basicSetup={{
|
||||||
|
lineNumbers: true,
|
||||||
|
scrollPastEnd: false,
|
||||||
|
}}
|
||||||
className="min-h-full min-w-full flex-1"
|
className="min-h-full min-w-full flex-1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import { Input } from "@/components/ui/input";
|
|||||||
import CodeMirror from "@uiw/react-codemirror";
|
import CodeMirror from "@uiw/react-codemirror";
|
||||||
import { oneDark } from "@codemirror/theme-one-dark";
|
import { oneDark } from "@codemirror/theme-one-dark";
|
||||||
import { languages, loadLanguage } from "@uiw/codemirror-extensions-langs";
|
import { languages, loadLanguage } from "@uiw/codemirror-extensions-langs";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
|
|
||||||
interface FileItem {
|
interface FileItem {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -769,11 +770,22 @@ export function FileViewer({
|
|||||||
<CodeMirror
|
<CodeMirror
|
||||||
value={editedContent}
|
value={editedContent}
|
||||||
onChange={(value) => handleContentChange(value)}
|
onChange={(value) => handleContentChange(value)}
|
||||||
extensions={
|
extensions={[
|
||||||
getLanguageExtension(file.name)
|
...(getLanguageExtension(file.name)
|
||||||
? [getLanguageExtension(file.name)!]
|
? [getLanguageExtension(file.name)!]
|
||||||
: []
|
: []),
|
||||||
}
|
EditorView.theme({
|
||||||
|
"&": {
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
".cm-editor": {
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
theme="dark"
|
theme="dark"
|
||||||
basicSetup={{
|
basicSetup={{
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
@@ -785,6 +797,7 @@ export function FileViewer({
|
|||||||
closeBrackets: true,
|
closeBrackets: true,
|
||||||
autocompletion: true,
|
autocompletion: true,
|
||||||
highlightSelectionMatches: false,
|
highlightSelectionMatches: false,
|
||||||
|
scrollPastEnd: false,
|
||||||
}}
|
}}
|
||||||
className="h-full overflow-auto"
|
className="h-full overflow-auto"
|
||||||
readOnly={!isEditable}
|
readOnly={!isEditable}
|
||||||
@@ -806,11 +819,22 @@ export function FileViewer({
|
|||||||
<CodeMirror
|
<CodeMirror
|
||||||
value={editedContent}
|
value={editedContent}
|
||||||
onChange={(value) => handleContentChange(value)}
|
onChange={(value) => handleContentChange(value)}
|
||||||
extensions={
|
extensions={[
|
||||||
getLanguageExtension(file.name)
|
...(getLanguageExtension(file.name)
|
||||||
? [getLanguageExtension(file.name)!]
|
? [getLanguageExtension(file.name)!]
|
||||||
: []
|
: []),
|
||||||
}
|
EditorView.theme({
|
||||||
|
"&": {
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
".cm-editor": {
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
theme={oneDark}
|
theme={oneDark}
|
||||||
editable={isEditable}
|
editable={isEditable}
|
||||||
placeholder={t("fileManager.startTyping")}
|
placeholder={t("fileManager.startTyping")}
|
||||||
@@ -822,6 +846,7 @@ export function FileViewer({
|
|||||||
allowMultipleSelections: false,
|
allowMultipleSelections: false,
|
||||||
highlightSelectionMatches: false,
|
highlightSelectionMatches: false,
|
||||||
searchKeymap: true,
|
searchKeymap: true,
|
||||||
|
scrollPastEnd: false,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { CredentialSelector } from "@/ui/Desktop/Apps/Credentials/CredentialSelector.tsx";
|
import { CredentialSelector } from "@/ui/Desktop/Apps/Credentials/CredentialSelector.tsx";
|
||||||
import CodeMirror from "@uiw/react-codemirror";
|
import CodeMirror from "@uiw/react-codemirror";
|
||||||
import { oneDark } from "@codemirror/theme-one-dark";
|
import { oneDark } from "@codemirror/theme-one-dark";
|
||||||
|
import { EditorView } from "@codemirror/view";
|
||||||
|
|
||||||
interface SSHHost {
|
interface SSHHost {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -1000,7 +1001,15 @@ export function HostManagerEditor({
|
|||||||
allowMultipleSelections: false,
|
allowMultipleSelections: false,
|
||||||
highlightSelectionMatches: false,
|
highlightSelectionMatches: false,
|
||||||
searchKeymap: false,
|
searchKeymap: false,
|
||||||
|
scrollPastEnd: false,
|
||||||
}}
|
}}
|
||||||
|
extensions={[
|
||||||
|
EditorView.theme({
|
||||||
|
".cm-scroller": {
|
||||||
|
overflow: "auto",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
Reference in New Issue
Block a user