From cd3979593285c7cbc79ebfb3c1f7b2e39c38dab1 Mon Sep 17 00:00:00 2001 From: WEI ZHANG Date: Thu, 10 Jul 2025 22:13:14 +0800 Subject: [PATCH] fix(sheets-formula-ui): can't drag selections when edit formula (#5512) --- .../hooks/use-formula-selection.ts | 28 +++++++++++++------ .../formula-editor/hooks/use-highlight.ts | 8 +++++- .../hooks/use-sheet-selection-change.ts | 15 ++++++++-- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-formula-selection.ts b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-formula-selection.ts index fd4cea13ce..d874571c11 100644 --- a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-formula-selection.ts +++ b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-formula-selection.ts @@ -45,6 +45,7 @@ export enum FormulaSelectingType { CAN_EDIT = 2, // editing cross sheet reference EDIT_OTHER_SHEET_REFERENCE = 3, + EDIT_OTHER_WORKBOOK_REFERENCE = 4, } // eslint-disable-next-line max-lines-per-function @@ -67,7 +68,7 @@ export function useFormulaSelecting(opts: { editorId: string; isFocus: boolean; const setIsSelecting = useEvent((v: FormulaSelectingType) => { if (refSelectionsRenderService) { - refSelectionsRenderService.setSkipLastEnabled(v === FormulaSelectingType.NEED_ADD || v === FormulaSelectingType.EDIT_OTHER_SHEET_REFERENCE); + refSelectionsRenderService.setSkipLastEnabled(v === FormulaSelectingType.NEED_ADD || v === FormulaSelectingType.EDIT_OTHER_SHEET_REFERENCE || v === FormulaSelectingType.EDIT_OTHER_WORKBOOK_REFERENCE); } isSelectingRef.current = v; innerSetIsSelecting(v); @@ -75,8 +76,9 @@ export function useFormulaSelecting(opts: { editorId: string; isFocus: boolean; // eslint-disable-next-line complexity const calculateSelectingType = useEvent(() => { - if (!workbook) return; - const currentSheet = workbook.getActiveSheet(); + const currentWorkbook = univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_SHEET); + if (!currentWorkbook) return; + const currentSheet = currentWorkbook.getActiveSheet(); const activeRange = docSelectionRenderService?.getActiveTextRange(); const index = activeRange?.collapsed ? activeRange.startOffset! : -1; const config = getCurrentBodyDataStreamAndOffset(injector); @@ -110,9 +112,13 @@ export function useFormulaSelecting(opts: { editorId: string; isFocus: boolean; if (isDisabledByPointer.current) { return; } - if ( - (!focusingNode.range.sheetName && currentSheet.getSheetId() === sourceSheet?.getSheetId()) || - focusingNode.range.sheetName === currentSheet.getName() + + const { sheetName, unitId } = focusingNode.range; + if (unitId !== univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_SHEET)?.getUnitId()) { + setIsSelecting(FormulaSelectingType.EDIT_OTHER_WORKBOOK_REFERENCE); + } else if ( + (!sheetName && currentSheet.getSheetId() === sourceSheet?.getSheetId()) || + sheetName === currentSheet.getName() ) { setIsSelecting(FormulaSelectingType.CAN_EDIT); } else { @@ -159,9 +165,15 @@ export function useFormulaSelecting(opts: { editorId: string; isFocus: boolean; const sub = workbook?.activeSheet$.subscribe(() => { calculateSelectingType(); }); + const sub2 = univerInstanceService.getCurrentTypeOfUnit$(UniverInstanceType.UNIVER_SHEET).subscribe(() => { + calculateSelectingType(); + }); - return () => sub?.unsubscribe(); - }, [calculateSelectingType, isFocus, workbook?.activeSheet$]); + return () => { + sub?.unsubscribe(); + sub2?.unsubscribe(); + }; + }, [calculateSelectingType, isFocus, workbook?.activeSheet$, univerInstanceService.getCurrentTypeOfUnit$]); return { isSelecting, isSelectingRef }; } diff --git a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-highlight.ts b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-highlight.ts index 5b88595d48..31195b8064 100644 --- a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-highlight.ts +++ b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-highlight.ts @@ -161,7 +161,13 @@ export function useSheetHighlight(unitId: string, subUnitId: string) { }); if (!selectionWithStyle) return; - refSelectionsService.setSelections(selectionWithStyle); + const allControls = refSelectionsRenderService?.getSelectionControls() || []; + // If the number are same, try to reuse the current controls + if (allControls.length === selectionWithStyle.length) { + refSelectionsRenderService?.resetSelectionsByModelData(selectionWithStyle); + } else { + refSelectionsService.setSelections(selectionWithStyle); + } }); useEffect(() => { diff --git a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-sheet-selection-change.ts b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-sheet-selection-change.ts index 763d36bb6b..f36e7490e6 100644 --- a/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-sheet-selection-change.ts +++ b/packages/sheets-formula-ui/src/views/formula-editor/hooks/use-sheet-selection-change.ts @@ -23,7 +23,7 @@ import type { RefObject } from 'react'; import type { IRefSelection } from './use-highlight'; import { DisposableCollection, ICommandService, IUniverInstanceService, ThemeService, UniverInstanceType } from '@univerjs/core'; import { DocSelectionManagerService } from '@univerjs/docs'; -import { deserializeRangeWithSheet, generateStringWithSequence, LexerTreeBuilder, sequenceNodeType, serializeRange, serializeRangeWithSheet } from '@univerjs/engine-formula'; +import { deserializeRangeWithSheet, generateStringWithSequence, LexerTreeBuilder, sequenceNodeType, serializeRange, serializeRangeWithSheet, serializeRangeWithSpreadsheet } from '@univerjs/engine-formula'; import { IRenderManagerService } from '@univerjs/engine-render'; import { IRefSelectionsService, SetSelectionsOperation } from '@univerjs/sheets'; import { SheetSkeletonManagerService } from '@univerjs/sheets-ui'; @@ -130,13 +130,18 @@ export const useSheetSelectionChange = ( const result = sequenceNodeToText(sequenceNodes); handleRangeChange(result, refRanges[0].length, isEnd); } - } else if (isSelectingRef.current === FormulaSelectingType.EDIT_OTHER_SHEET_REFERENCE) { + } else if (isSelectingRef.current === FormulaSelectingType.EDIT_OTHER_SHEET_REFERENCE || isSelectingRef.current === FormulaSelectingType.EDIT_OTHER_WORKBOOK_REFERENCE) { const last = selections.pop(); if (!last) return; const node = sequenceNodes[nodeIndex]; if (typeof node === 'object' && node.nodeType === sequenceNodeType.REFERENCE) { const oldToken = node.token; - node.token = sheetName === activeSheet?.getName() ? serializeRange(last) : serializeRangeWithSheet(activeSheet!.getName(), last); + const isAcrossWorkbook = currentUnit?.getUnitId() !== unitId; + if (isAcrossWorkbook) { + node.token = serializeRangeWithSpreadsheet(currentUnit?.getUnitId() ?? '', sheetName, last); + } else { + node.token = sheetName === activeSheet?.getName() ? serializeRange(last) : serializeRangeWithSheet(activeSheet!.getName(), last); + } const newOffset = offset + (node.token.length - oldToken.length); handleRangeChange(generateStringWithSequence(sequenceNodes), newOffset, isEnd); } @@ -158,6 +163,10 @@ export const useSheetSelectionChange = ( nodeRange.sheetName = sheetName; } + if (((nodeRange.unitId || unitId) !== currentUnit?.getUnitId())) { + return item.token; + } + if (isSupportAcrossSheet) { // 直接跳过非当前表的 node 节点 if (contextRef.current.activeSheet?.getName() !== nodeRange.sheetName) {