fix(sheets-formula-ui): can't drag selections when edit formula (#5512)

This commit is contained in:
WEI ZHANG
2025-07-10 22:13:14 +08:00
committed by GitHub
parent a4e177a140
commit cd39795932
3 changed files with 39 additions and 12 deletions
@@ -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<Workbook>(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 };
}
@@ -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(() => {
@@ -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) {