Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sheets-hyper-link-ui): link & doc markSelection error on merged cell #3615

Merged
merged 1 commit into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading