diff --git a/packages/sheets-formula-ui/src/views/formula-editor/hooks/useHighlight.ts b/packages/sheets-formula-ui/src/views/formula-editor/hooks/useHighlight.ts index c1fd725cc3b..26d90e02b59 100644 --- a/packages/sheets-formula-ui/src/views/formula-editor/hooks/useHighlight.ts +++ b/packages/sheets-formula-ui/src/views/formula-editor/hooks/useHighlight.ts @@ -91,7 +91,7 @@ export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: st useEffect(() => { const skeleton = sheetSkeletonManagerService?.getCurrentSkeleton(); - if (skeleton) { + if (skeleton && isNeed) { const allControls = refSelectionsRenderService?.getSelectionControls() || []; if (allControls.length === ranges.length) { allControls.forEach((control, index) => { @@ -103,11 +103,7 @@ export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: st refSelectionsService.setSelections(ranges); } } - }, [ranges, sheetSkeletonManagerService]); - - useEffect(() => () => { - refSelectionsService.setSelections([]); - }, []); + }, [ranges, isNeed]); } export function useDocHight(editorId: string, sequenceNodes: (string | ISequenceNode)[]) { diff --git a/packages/sheets-formula-ui/src/views/formula-editor/index.tsx b/packages/sheets-formula-ui/src/views/formula-editor/index.tsx index a6364d0910d..59a56a52191 100644 --- a/packages/sheets-formula-ui/src/views/formula-editor/index.tsx +++ b/packages/sheets-formula-ui/src/views/formula-editor/index.tsx @@ -23,7 +23,6 @@ import { operatorToken } from '@univerjs/engine-formula'; import { EMBEDDING_FORMULA_EDITOR } from '@univerjs/sheets-ui'; import clsx from 'clsx'; import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; -import { useBlur } from '../range-selector/hooks/useBlur'; import { useFocus } from '../range-selector/hooks/useFocus'; import { useFormulaToken } from '../range-selector/hooks/useFormulaToken'; import { useLeftAndRightArrow } from '../range-selector/hooks/useLeftAndRightArrow'; @@ -100,16 +99,21 @@ export function FormulaEditor(props: IFormulaEditorProps) { useVerify(isFocus, onVerify, formulaText); const focus = useFocus(editor); - useEffect(() => { - const time = setTimeout(() => { + useLayoutEffect(() => { + // 在进行多个 input 切换的时候,失焦必须快于获得焦点. + if (_isFocus) { + const time = setTimeout(() => { + isFocusSet(_isFocus); + if (_isFocus) { + focus(); + } + }, 30); + return () => { + clearTimeout(time); + }; + } else { isFocusSet(_isFocus); - if (_isFocus) { - focus(); - } - }, 300); - return () => { - clearTimeout(time); - }; + } }, [_isFocus, focus]); const handleSelectionChange = (refString: string, offset: number) => { @@ -128,7 +132,6 @@ export function FormulaEditor(props: IFormulaEditorProps) { useRefactorEffect(isFocus, unitId); useLeftAndRightArrow(isFocus, editor); useSheetSelectionChange(isFocus, unitId, subUnitId, sequenceNodes, isSupportAcrossSheet, editor, handleSelectionChange); - useBlur(editorId, isFocusSet); useRefocus(); const { searchList, searchText, handlerFormulaReplace, reset: resetFormulaSearch } = useFormulaSearch(isFocus, sequenceNodes, editor); @@ -188,12 +191,17 @@ export function FormulaEditor(props: IFormulaEditorProps) { } }; - const handleClick = () => { - if (editor) { + const handleMouseUp = () => { + // 在进行多个 input 切换的时候,失焦必须快于获得焦点. + // 即使失焦是 mousedown 事件, + // 聚焦是 mouseup 事件, + // 但是 react 的 useEffect 无法保证顺序,无法确保失焦在聚焦之前. + + setTimeout(() => { isFocusSet(true); onFocus(); focus(); - } + }, 30); }; return (
@@ -207,7 +215,7 @@ export function FormulaEditor(props: IFormulaEditorProps) {
{errorText !== undefined ?
{errorText}
: null} diff --git a/packages/sheets-formula-ui/src/views/range-selector/hooks/useBlur.ts b/packages/sheets-formula-ui/src/views/range-selector/hooks/useBlur.ts deleted file mode 100644 index 7483b73c7f0..00000000000 --- a/packages/sheets-formula-ui/src/views/range-selector/hooks/useBlur.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2023-present DreamNum Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { useDependency } from '@univerjs/core'; -import { IEditorService } from '@univerjs/docs-ui'; -import { useEffect } from 'react'; - -export const useBlur = (editorId: string, isFocusSet: (v: boolean) => void) => { - const editorService = useDependency(IEditorService); - useEffect(() => { - const handleBlur = (_focusEditorId?: string) => { - const focusEditorId = _focusEditorId || editorService.getFocusEditor()?.getEditorId(); - if (focusEditorId && editorId !== focusEditorId) { - isFocusSet(false); - } - }; - const d = editorService.focus$.subscribe(() => handleBlur()); - const d2 = editorService.focusStyle$.subscribe((e) => handleBlur(e!)); - return () => { - d.unsubscribe(); - d2.unsubscribe(); - }; - }, [editorService, editorId]); -}; diff --git a/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts b/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts index 739a0ac2606..c0912eaf733 100644 --- a/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts +++ b/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts @@ -90,7 +90,7 @@ export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: st useEffect(() => { const skeleton = sheetSkeletonManagerService?.getCurrentSkeleton(); - if (skeleton) { + if (skeleton && isNeed) { const allControls = refSelectionsRenderService?.getSelectionControls() || []; if (allControls.length === ranges.length) { allControls.forEach((control, index) => { @@ -102,11 +102,7 @@ export function useSheetHighlight(isNeed: boolean, unitId: string, subUnitId: st refSelectionsService.setSelections(ranges); } } - }, [ranges, sheetSkeletonManagerService]); - - useEffect(() => () => { - refSelectionsService.setSelections([]); - }, []); + }, [ranges, isNeed]); } export function useDocHight(editorId: string, sequenceNodes: (string | ISequenceNode)[]) { diff --git a/packages/sheets-formula-ui/src/views/range-selector/hooks/useRefactorEffect.ts b/packages/sheets-formula-ui/src/views/range-selector/hooks/useRefactorEffect.ts index 425442a0abf..5c1cb9ba8a3 100644 --- a/packages/sheets-formula-ui/src/views/range-selector/hooks/useRefactorEffect.ts +++ b/packages/sheets-formula-ui/src/views/range-selector/hooks/useRefactorEffect.ts @@ -17,7 +17,7 @@ import type { Workbook } from '@univerjs/core'; import { EDITOR_ACTIVATED, IContextService, IUniverInstanceService, UniverInstanceType, useDependency } from '@univerjs/core'; import { IRenderManagerService } from '@univerjs/engine-render'; -import { DISABLE_NORMAL_SELECTIONS, SheetsSelectionsService } from '@univerjs/sheets'; +import { DISABLE_NORMAL_SELECTIONS, IRefSelectionsService, SheetsSelectionsService } from '@univerjs/sheets'; import { IContextMenuService } from '@univerjs/ui'; import { useEffect, useLayoutEffect } from 'react'; @@ -29,19 +29,20 @@ export const useRefactorEffect = (isNeed: boolean, unitId: string) => { const contextService = useDependency(IContextService); const sheetsSelectionsService = useDependency(SheetsSelectionsService); const contextMenuService = useDependency(IContextMenuService); + const refSelectionsService = useDependency(IRefSelectionsService); const render = renderManagerService.getRenderById(unitId); const refSelectionsRenderService = render?.with(RefSelectionsRenderService); - useEffect(() => { + useLayoutEffect(() => { if (isNeed) { const d1 = refSelectionsRenderService?.enableSelectionChanging(); contextService.setContextValue(DISABLE_NORMAL_SELECTIONS, true); contextService.setContextValue(EDITOR_ACTIVATED, true); return () => { - d1?.dispose(); - contextService.setContextValue(DISABLE_NORMAL_SELECTIONS, false); contextService.setContextValue(EDITOR_ACTIVATED, false); + contextService.setContextValue(DISABLE_NORMAL_SELECTIONS, false); + d1?.dispose(); }; } }, [isNeed]); @@ -53,6 +54,7 @@ export const useRefactorEffect = (isNeed: boolean, unitId: string) => { const sheet = workbook?.getActiveSheet(); const selections = [...sheetsSelectionsService.getCurrentSelections()]; return () => { + refSelectionsService.clear(); const workbook = univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET); const currentSheet = workbook?.getActiveSheet(); if (currentSheet && currentSheet === sheet) { diff --git a/packages/sheets-formula-ui/src/views/range-selector/index.tsx b/packages/sheets-formula-ui/src/views/range-selector/index.tsx index 3254bf0cd1f..9a54bf43614 100644 --- a/packages/sheets-formula-ui/src/views/range-selector/index.tsx +++ b/packages/sheets-formula-ui/src/views/range-selector/index.tsx @@ -31,7 +31,6 @@ import cl from 'clsx'; import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { filter } from 'rxjs'; import { RefSelectionsRenderService } from '../../services/render-services/ref-selections.render-service'; -import { useBlur } from './hooks/useBlur'; import { useEditorInput } from './hooks/useEditorInput'; import { useFocus } from './hooks/useFocus'; @@ -185,16 +184,22 @@ export function RangeSelector(props: IRangeSelectorProps) { const focus = useFocus(editor); - useEffect(() => { - const time = setTimeout(() => { + useLayoutEffect(() => { + // 如果是失去焦点的话,需要立刻执行 + // 在进行多个 input 切换的时候,失焦必须立刻执行. + if (_isFocus) { + const time = setTimeout(() => { + isFocusSet(_isFocus); + if (_isFocus) { + focus(); + } + }, 30); + return () => { + clearTimeout(time); + }; + } else { isFocusSet(_isFocus); - if (_isFocus) { - focus(); - } - }, 300); - return () => { - clearTimeout(time); - }; + } }, [_isFocus, focus]); const { checkScrollBar } = useResize(editor); @@ -231,8 +236,6 @@ export function RangeSelector(props: IRangeSelectorProps) { useVerify(!rangeDialogVisible && isFocus, onVerify, sequenceNodes); - useBlur(editorId, isFocusSet); - useLeftAndRightArrow(!rangeDialogVisible && isFocus, editor); useRefocus(); @@ -309,9 +312,15 @@ export function RangeSelector(props: IRangeSelectorProps) { }, []); const handleClick = () => { - onFocus(); - focus(); - isFocusSet(true); + // 在进行多个 input 切换的时候,失焦必须快于获得焦点. + // 即使失焦是 mousedown 事件, + // 聚焦是 mouseup 事件, + // 但是 react 的 useEffect 无法保证顺序,无法确保失焦在聚焦之前. + setTimeout(() => { + onFocus(); + focus(); + isFocusSet(true); + }, 30); }; return (