refactor(CodeEditor): add blur extension, move some extensions to hooks (#7882)

This commit is contained in:
one 2025-07-07 10:51:56 +08:00 committed by GitHub
parent 463ca6185b
commit 9fd2583fd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 20 deletions

View File

@ -1,7 +1,8 @@
import { linter } from '@codemirror/lint' // statically imported by @uiw/codemirror-extensions-basic-setup
import { EditorView } from '@codemirror/view'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { Extension } from '@uiw/react-codemirror'
import { useEffect, useState } from 'react'
import { Extension, keymap } from '@uiw/react-codemirror'
import { useEffect, useMemo, useState } from 'react'
// 语言对应的 linter 加载器
const linterLoaders: Record<string, () => Promise<any>> = {
@ -53,3 +54,55 @@ export const useLanguageExtensions = (language: string, lint?: boolean) => {
return extensions
}
interface UseSaveKeymapProps {
onSave?: (content: string) => void
enabled?: boolean
}
/**
* CodeMirror (Cmd/Ctrl + S)
* @param onSave
* @param enabled
* @returns
*/
export function useSaveKeymap({ onSave, enabled = true }: UseSaveKeymapProps) {
return useMemo(() => {
if (!enabled || !onSave) {
return []
}
return keymap.of([
{
key: 'Mod-s',
run: (view: EditorView) => {
onSave(view.state.doc.toString())
return true
},
preventDefault: true
}
])
}, [onSave, enabled])
}
interface UseBlurHandlerProps {
onBlur?: (content: string) => void
}
/**
* CodeMirror blur
* @param onBlur blur
* @returns
*/
export function useBlurHandler({ onBlur }: UseBlurHandlerProps) {
return useMemo(() => {
if (!onBlur) {
return []
}
return EditorView.domEventHandlers({
blur: (_event, view) => {
onBlur(view.state.doc.toString())
}
})
}, [onBlur])
}

View File

@ -1,7 +1,7 @@
import { CodeTool, TOOL_SPECS, useCodeTool } from '@renderer/components/CodeToolbar'
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
import { useSettings } from '@renderer/hooks/useSettings'
import CodeMirror, { Annotation, BasicSetupOptions, EditorView, Extension, keymap } from '@uiw/react-codemirror'
import CodeMirror, { Annotation, BasicSetupOptions, EditorView, Extension } from '@uiw/react-codemirror'
import diff from 'fast-diff'
import {
ChevronsDownUp,
@ -14,7 +14,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import { useLanguageExtensions } from './hook'
import { useBlurHandler, useLanguageExtensions, useSaveKeymap } from './hooks'
// 标记非用户编辑的变更
const External = Annotation.define<boolean>()
@ -25,6 +25,7 @@ interface Props {
language: string
onSave?: (newContent: string) => void
onChange?: (newContent: string) => void
onBlur?: (newContent: string) => void
setTools?: (value: React.SetStateAction<CodeTool[]>) => void
height?: string
minHeight?: string
@ -54,6 +55,7 @@ const CodeEditor = ({
language,
onSave,
onChange,
onBlur,
setTools,
height,
minHeight,
@ -166,28 +168,18 @@ const CodeEditor = ({
setIsUnwrapped(!wrappable)
}, [wrappable])
// 保存功能的快捷键
const saveKeymap = useMemo(() => {
return keymap.of([
{
key: 'Mod-s',
run: () => {
handleSave()
return true
},
preventDefault: true
}
])
}, [handleSave])
const saveKeymapExtension = useSaveKeymap({ onSave, enabled: enableKeymap })
const blurExtension = useBlurHandler({ onBlur })
const customExtensions = useMemo(() => {
return [
...(extensions ?? []),
...langExtensions,
...(isUnwrapped ? [] : [EditorView.lineWrapping]),
...(enableKeymap ? [saveKeymap] : [])
]
}, [extensions, langExtensions, isUnwrapped, enableKeymap, saveKeymap])
saveKeymapExtension,
blurExtension
].flat()
}, [extensions, langExtensions, isUnwrapped, saveKeymapExtension, blurExtension])
return (
<CodeMirror