Skip to content

Commit

Permalink
fix(sheets-hyper-link-ui): link & doc markSelection error on merged c…
Browse files Browse the repository at this point in the history
…ell (#3615)
  • Loading branch information
weird94 authored Sep 28, 2024
1 parent 1964a4c commit 21853cc
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

import type { DocumentDataModel, IUnitRangeWithName, Nullable, Workbook } from '@univerjs/core';
import type { ISetSelectionsOperationParams } from '@univerjs/sheets';
import { BuildTextUtils, createInternalEditorID, CustomRangeType, DisposableCollection, DOCS_ZEN_EDITOR_UNIT_ID_KEY, FOCUSING_SHEET, generateRandomId, getOriginCellValue, ICommandService, IContextService, isValidRange, IUniverInstanceService, LocaleService, Tools, UniverInstanceType, useDependency } from '@univerjs/core';
import { Button, FormLayout, Input, Select } from '@univerjs/design';
import { DocSelectionManagerService } from '@univerjs/docs';
Expand All @@ -25,8 +27,6 @@ import { SheetHyperLinkType } from '@univerjs/sheets-hyper-link';
import { IEditorBridgeService, IMarkSelectionService, ScrollToRangeOperation } from '@univerjs/sheets-ui';
import { IZenZoneService, KeyCode, useEvent, useObservable } from '@univerjs/ui';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import type { DocumentDataModel, IUnitRangeWithName, Nullable, Workbook } from '@univerjs/core';
import type { ISetSelectionsOperationParams } from '@univerjs/sheets';
import { AddHyperLinkCommand, AddRichHyperLinkCommand } from '../../commands/commands/add-hyper-link.command';
import { UpdateHyperLinkCommand, UpdateRichHyperLinkCommand } from '../../commands/commands/update-hyper-link.command';
import { CloseHyperLinkPopupOperation } from '../../commands/operations/popup.operations';
Expand Down Expand Up @@ -171,9 +171,11 @@ export const CellLinkEdit = () => {
useEffect(() => {
let id: Nullable<string> = null;
if (editing && editing.type === HyperLinkEditSourceType.VIEWING && Tools.isDefine(editing.row) && Tools.isDefine(editing.col)) {
const worksheet = univerInstanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET)?.getSheetBySheetId(editing.subUnitId);
const mergeInfo = worksheet?.getMergedCell(editing.row, editing.col);
id = markSelectionService.addShape(
{
range: {
range: mergeInfo ?? {
startColumn: editing.col,
endColumn: editing.col,
startRow: editing.row,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
*/

import { Disposable, Inject, LifecycleStages, OnLifecycle } from '@univerjs/core';
import { RangeProtectionPermissionViewPoint, WorkbookCommentPermission, WorksheetViewPermission } from '@univerjs/sheets';
import { SheetsThreadCommentModel } from '@univerjs/sheets-thread-comment-base';
import { HoverManagerService, SheetPermissionInterceptorBaseController } from '@univerjs/sheets-ui';
import { debounceTime } from 'rxjs';
import { SheetsThreadCommentModel } from '@univerjs/sheets-thread-comment-base';
import { RangeProtectionPermissionViewPoint, WorkbookCommentPermission, WorksheetViewPermission } from '@univerjs/sheets';
import { SheetsThreadCommentPopupService } from '../services/sheets-thread-comment-popup.service';

@OnLifecycle(LifecycleStages.Rendered, SheetsThreadCommentHoverController)
Expand All @@ -40,6 +40,7 @@ export class SheetsThreadCommentHoverController extends Disposable {
if (cell && ((currentPopup && currentPopup.temp) || !currentPopup)) {
const { location } = cell;
const { unitId, subUnitId, row, col } = location;

const commentId = this._sheetsThreadCommentModel.getByLocation(unitId, subUnitId, row, col);

if (commentId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
*/

import type { Nullable, Workbook } from '@univerjs/core';
import { Disposable, ICommandService, Inject, IUniverInstanceService, LifecycleStages, OnLifecycle, RANGE_TYPE, UniverInstanceType } from '@univerjs/core';
import { SetActiveCommentOperation, ThreadCommentPanelService } from '@univerjs/thread-comment-ui';
import type { ISelectionWithStyle } from '@univerjs/sheets';
import { RangeProtectionPermissionViewPoint, SetWorksheetActiveOperation, SheetsSelectionsService, WorkbookCommentPermission, WorksheetViewPermission } from '@univerjs/sheets';
import { singleReferenceToGrid } from '@univerjs/engine-formula';
import type { IDeleteCommentMutationParams } from '@univerjs/thread-comment';
import { DeleteCommentMutation } from '@univerjs/thread-comment';
import { IEditorBridgeService, IMarkSelectionService, ScrollToRangeOperation, SheetPermissionInterceptorBaseController } from '@univerjs/sheets-ui';
import { Disposable, ICommandService, Inject, IUniverInstanceService, LifecycleStages, OnLifecycle, RANGE_TYPE, UniverInstanceType } from '@univerjs/core';
import { singleReferenceToGrid } from '@univerjs/engine-formula';
import { RangeProtectionPermissionViewPoint, SetWorksheetActiveOperation, SheetsSelectionsService, WorkbookCommentPermission, WorksheetViewPermission } from '@univerjs/sheets';
import { SheetsThreadCommentModel } from '@univerjs/sheets-thread-comment-base';
import { IEditorBridgeService, IMarkSelectionService, ScrollToRangeOperation, SheetPermissionInterceptorBaseController } from '@univerjs/sheets-ui';
import { DeleteCommentMutation } from '@univerjs/thread-comment';
import { SetActiveCommentOperation, ThreadCommentPanelService } from '@univerjs/thread-comment-ui';
import { debounceTime } from 'rxjs';
import { SheetsThreadCommentPopupService } from '../services/sheets-thread-comment-popup.service';

Expand Down Expand Up @@ -227,15 +227,19 @@ export class SheetsThreadCommentPopupController extends Disposable {
return null;
}

const worksheet = this._univerInstanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET)?.getSheetBySheetId(subUnitId);

const mergeInfo = worksheet?.getMergedCell(row, column) ?? {
startColumn: column,
endColumn: column,
startRow: row,
endRow: row,
};

// TODO: use evented: false to solve this problem later
const shapeId = this._markSelectionService.addShape(
{
range: {
startColumn: column,
endColumn: column,
startRow: row,
endRow: row,
},
range: mergeInfo,
style: {
hasAutoFill: false,
fill: 'rgb(255, 189, 55, 0.35)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
* limitations under the License.
*/

import type { Workbook } from '@univerjs/core';
import type { IThreadComment } from '@univerjs/thread-comment';
import { ICommandService, IUniverInstanceService, UniverInstanceType, useDependency } from '@univerjs/core';
import { singleReferenceToGrid } from '@univerjs/engine-formula';
import { IMarkSelectionService } from '@univerjs/sheets-ui';
import { ThreadCommentPanel, ThreadCommentPanelService } from '@univerjs/thread-comment-ui';
import { useObservable } from '@univerjs/ui';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { map } from 'rxjs';
import type { Workbook } from '@univerjs/core';
import type { IThreadComment } from '@univerjs/thread-comment';
import { ShowAddSheetCommentModalOperation } from '../../commands/operations/comment.operation';
import { SheetsThreadCommentPopupService } from '../../services/sheets-thread-comment-popup.service';

Expand Down Expand Up @@ -72,14 +72,16 @@ export const SheetsThreadCommentPanel = () => {
const showShape = useCallback((comment: IThreadComment) => {
if (comment.unitId === unitId && comment.subUnitId === subUnitId && !comment.resolved) {
const { row, column } = singleReferenceToGrid(comment.ref);
const worksheet = workbook.getSheetBySheetId(comment.subUnitId);
const mergeInfo = worksheet?.getMergedCell(row, column) ?? {
startColumn: column,
endColumn: column,
startRow: row,
endRow: row,
};
if (!Number.isNaN(row) && !Number.isNaN(column)) {
return markSelectionService.addShape({
range: {
startColumn: column,
endColumn: column,
startRow: row,
endRow: row,
},
range: mergeInfo,
style: {
hasAutoFill: false,
fill: 'rgb(255, 189, 55, 0.35)',
Expand Down
12 changes: 6 additions & 6 deletions packages/sheets-ui/src/services/canvas-pop-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@
*/

import type { INeedCheckDisposable, IRange, Nullable, Workbook, Worksheet } from '@univerjs/core';
import { Disposable, DisposableCollection, ICommandService, Inject, IUniverInstanceService, toDisposable, UniverInstanceType } from '@univerjs/core';
import { IRenderManagerService } from '@univerjs/engine-render';
import type { BaseObject, IBoundRectNoAngle, IRender, SpreadsheetSkeleton, Viewport } from '@univerjs/engine-render';
import type { ISetWorksheetRowAutoHeightMutationParams } from '@univerjs/sheets';
import type { IPopup } from '@univerjs/ui';
import { Disposable, DisposableCollection, ICommandService, Inject, IUniverInstanceService, toDisposable, UniverInstanceType } from '@univerjs/core';
import { IRenderManagerService } from '@univerjs/engine-render';
import { COMMAND_LISTENER_SKELETON_CHANGE, RefRangeService, SetWorksheetRowAutoHeightMutation } from '@univerjs/sheets';
import { ICanvasPopupService } from '@univerjs/ui';
import { BehaviorSubject } from 'rxjs';
import type { ISetWorksheetRowAutoHeightMutationParams } from '@univerjs/sheets';
import { COMMAND_LISTENER_SKELETON_CHANGE, RefRangeService, SetWorksheetRowAutoHeightMutation } from '@univerjs/sheets';
import { getViewportByCell, transformBound2OffsetBound } from '../common/utils';
import { SetScrollOperation } from '../commands/operations/scroll.operation';
import { SetZoomRatioOperation } from '../commands/operations/set-zoom-ratio.operation';
import { SheetSkeletonManagerService } from './sheet-skeleton-manager.service';
import { getViewportByCell, transformBound2OffsetBound } from '../common/utils';
import { ISheetSelectionRenderService } from './selection/base-selection-render.service';
import { SheetSkeletonManagerService } from './sheet-skeleton-manager.service';

export interface ICanvasPopup extends Pick<IPopup, 'direction' | 'excludeOutside' | 'componentKey' | 'offset' | 'onClickOutside' | 'hideOnInvisible' | 'hiddenType' | 'onClick'> {
mask?: boolean;
Expand Down
47 changes: 5 additions & 42 deletions packages/sheets-ui/src/services/hover-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
* limitations under the License.
*/

import { Disposable, HorizontalAlign, IUniverInstanceService, UniverInstanceType, VerticalAlign } from '@univerjs/core';
import type { ICustomRange, IParagraph, IPosition, Nullable, Workbook } from '@univerjs/core';
import type { IBoundRectNoAngle, SpreadsheetSkeleton } from '@univerjs/engine-render';
import type { ISheetLocation } from '@univerjs/sheets';
import { Disposable, IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
import { IRenderManagerService } from '@univerjs/engine-render';
import { BehaviorSubject, distinctUntilChanged, map, Subject } from 'rxjs';
import type { ICustomRange, IParagraph, IPosition, ISelectionCellWithMergeInfo, Nullable, Workbook } from '@univerjs/core';
import type { IBoundRectNoAngle, IFontCacheItem, SpreadsheetSkeleton } from '@univerjs/engine-render';
import type { ISheetLocation } from '@univerjs/sheets';
import { getHoverCellPosition } from '../common/utils';
import { SheetScrollManagerService } from './scroll-manager.service';
import { SheetSkeletonManagerService } from './sheet-skeleton-manager.service';
import { calculateDocSkeletonRects } from './utils/doc-skeleton-util';
import { calcPadding, calculateDocSkeletonRects } from './utils/doc-skeleton-util';

export interface IHoverCellPosition {
position: IPosition;
Expand All @@ -48,43 +48,6 @@ export interface IHoverRichTextPosition extends IHoverCellPosition {
rect?: Nullable<IBoundRectNoAngle>;
}

function calcPadding(cell: ISelectionCellWithMergeInfo, font: IFontCacheItem) {
const height = font.documentSkeleton.getSkeletonData()?.pages[0].height ?? 0;
const width = font.documentSkeleton.getSkeletonData()?.pages[0].width ?? 0;
const vt = font.verticalAlign;
const ht = font.horizontalAlign;

let paddingTop = 0;
switch (vt) {
case VerticalAlign.UNSPECIFIED:
case VerticalAlign.BOTTOM:
paddingTop = cell.mergeInfo.endY - cell.mergeInfo.startY - height;
break;
case VerticalAlign.MIDDLE:
paddingTop = (cell.mergeInfo.endY - cell.mergeInfo.startY - height) / 2;
break;
default:
break;
}

let paddingLeft = 0;
switch (ht) {
case HorizontalAlign.RIGHT:
paddingLeft = cell.mergeInfo.endX - cell.mergeInfo.startX - width;
break;
case HorizontalAlign.CENTER:
paddingLeft = (cell.mergeInfo.endX - cell.mergeInfo.startX - width) / 2;
break;
default:
break;
}

return {
paddingLeft,
paddingTop,
};
}

export class HoverManagerService extends Disposable {
private _currentCell$ = new BehaviorSubject<Nullable<IHoverCellPosition>>(null);
private _currentRichText$ = new BehaviorSubject<Nullable<IHoverRichTextPosition>>(null);
Expand Down
84 changes: 68 additions & 16 deletions packages/sheets-ui/src/services/utils/doc-skeleton-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
* limitations under the License.
*/

import type { ICustomRange, Injector, IParagraph, ITextRangeParam, Workbook } from '@univerjs/core';
import { CustomRangeType, IUniverInstanceService, PresetListType, UniverInstanceType } from '@univerjs/core';
import type { DocumentSkeleton, IBoundRectNoAngle, IDocumentSkeletonGlyph } from '@univerjs/engine-render';
import { IRenderManagerService } from '@univerjs/engine-render';
import type { ICustomRange, Injector, IParagraph, ISelectionCellWithMergeInfo, ITextRangeParam, Workbook } from '@univerjs/core';
import type { DocumentSkeleton, IBoundRectNoAngle, IDocumentSkeletonGlyph, IFontCacheItem } from '@univerjs/engine-render';
import { CustomRangeType, HorizontalAlign, IUniverInstanceService, PresetListType, UniverInstanceType, VerticalAlign } from '@univerjs/core';
import { DocSkeletonManagerService } from '@univerjs/docs';
import { DOC_VERTICAL_PADDING, getLineBounding, NodePositionConvertToCursor } from '@univerjs/docs-ui';
import { SheetSkeletonManagerService } from '../sheet-skeleton-manager.service';
import { IRenderManagerService } from '@univerjs/engine-render';
import { IEditorBridgeService } from '../editor-bridge.service';
import { SheetSkeletonManagerService } from '../sheet-skeleton-manager.service';

const calcDocRangePositions = (range: ITextRangeParam, skeleton: DocumentSkeleton): IBoundRectNoAngle[] | undefined => {
const pageIndex = -1;
Expand Down Expand Up @@ -144,6 +144,43 @@ export const calculateDocSkeletonRects = (docSkeleton: DocumentSkeleton, padding
};
};

export function calcPadding(cell: ISelectionCellWithMergeInfo, font: IFontCacheItem) {
const height = font.documentSkeleton.getSkeletonData()?.pages[0].height ?? 0;
const width = font.documentSkeleton.getSkeletonData()?.pages[0].width ?? 0;
const vt = font.verticalAlign;
const ht = font.horizontalAlign;

let paddingTop = 0;
switch (vt) {
case VerticalAlign.UNSPECIFIED:
case VerticalAlign.BOTTOM:
paddingTop = cell.mergeInfo.endY - cell.mergeInfo.startY - height;
break;
case VerticalAlign.MIDDLE:
paddingTop = (cell.mergeInfo.endY - cell.mergeInfo.startY - height) / 2;
break;
default:
break;
}

let paddingLeft = 0;
switch (ht) {
case HorizontalAlign.RIGHT:
paddingLeft = cell.mergeInfo.endX - cell.mergeInfo.startX - width;
break;
case HorizontalAlign.CENTER:
paddingLeft = (cell.mergeInfo.endX - cell.mergeInfo.startX - width) / 2;
break;
default:
break;
}

return {
paddingLeft,
paddingTop,
};
}

export const getCustomRangePosition = (injector: Injector, unitId: string, subUnitId: string, row: number, col: number, rangeId: string) => {
const univerInstanceService = injector.get(IUniverInstanceService);
const renderManagerService = injector.get(IRenderManagerService);
Expand All @@ -164,28 +201,43 @@ export const getCustomRangePosition = (injector: Injector, unitId: string, subUn

if (!skeleton || !currentRender) return;

const font = skeleton.getFont(row, col)?.documentSkeleton;

if (!font) {
const font = skeleton.getFont(row, col);
const docSkeleton = font?.documentSkeleton;
if (!docSkeleton) {
return null;
}
const customRange = font.getViewModel().getBody()?.customRanges?.find((range) => range.rangeId === rangeId);
const customRange = docSkeleton.getViewModel().getBody()?.customRanges?.find((range) => range.rangeId === rangeId);
if (!customRange) {
return null;
}

const PADDING = DOC_VERTICAL_PADDING;
const rects = calcDocRangePositions({ startOffset: customRange.startIndex, endOffset: customRange.endIndex, collapsed: false }, font);
const cell = skeleton.getCellByIndex(row, col);

const cellIndex = skeleton.getCellByIndex(row, col);
let { actualColumn, actualRow } = cellIndex;

skeleton.overflowCache.forValue((r, c, range) => {
if (range.startRow <= actualRow && range.endRow >= actualRow && range.startColumn <= actualColumn && range.endColumn >= actualColumn) {
actualColumn = c;
actualRow = r;
}
});

const actualCell = skeleton.getCellByIndex(actualRow, actualColumn);
const cellData = worksheet.getCell(actualCell.actualRow, actualCell.actualColumn);
const { topOffset = 0, leftOffset = 0 } = cellData?.fontRenderExtension ?? {};
const { paddingLeft, paddingTop } = calcPadding(actualCell, font);
const rects = calcDocRangePositions({ startOffset: customRange.startIndex, endOffset: customRange.endIndex, collapsed: false }, docSkeleton);

return {
rects: rects?.map((rect) => ({
top: rect.top + cell.startY - PADDING,
bottom: rect.bottom + cell.startY + PADDING,
left: rect.left + cell.startX,
right: rect.right + cell.startX,
top: rect.top + actualCell.mergeInfo.startY + paddingTop + topOffset + PADDING,
bottom: rect.bottom + actualCell.mergeInfo.startY + paddingTop + topOffset + PADDING,
left: rect.left + actualCell.mergeInfo.startX + paddingLeft + leftOffset,
right: rect.right + actualCell.mergeInfo.startX + paddingLeft + leftOffset,
})),
customRange,
label: font.getViewModel().getBody()!.dataStream.slice(customRange.startIndex + 1, customRange.endIndex),
label: docSkeleton.getViewModel().getBody()!.dataStream.slice(customRange.startIndex + 1, customRange.endIndex),
};
};

Expand Down

0 comments on commit 21853cc

Please sign in to comment.