diff --git a/packages-experimental/uni-docs-ui/src/controllers/menu.ts b/packages-experimental/uni-docs-ui/src/controllers/menu.ts index d16f6a3f318..833ecf88135 100644 --- a/packages-experimental/uni-docs-ui/src/controllers/menu.ts +++ b/packages-experimental/uni-docs-ui/src/controllers/menu.ts @@ -16,7 +16,8 @@ import type { IAccessor } from '@univerjs/core'; import { BooleanNumber, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, ICommandService, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import { DocSkeletonManagerService, SetInlineFormatCommand, SetTextSelectionsOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService, SetTextSelectionsOperation } from '@univerjs/docs'; +import { SetInlineFormatCommand } from '@univerjs/docs-ui'; import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render'; import { getHeaderFooterMenuHiddenObservable, getMenuHiddenObservable, type IMenuButtonItem, type IMenuItem, MenuItemType } from '@univerjs/ui'; @@ -180,7 +181,7 @@ export function DocTableMenuFactory(accessor: IAccessor): IMenuItem { function getFontStyleAtCursor(accessor: IAccessor) { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const editorDataModel = univerInstanceService.getUniverDocInstance(DOCS_NORMAL_EDITOR_UNIT_ID_KEY); const activeTextRange = textSelectionService.getActiveTextRange(); @@ -196,10 +197,10 @@ function getFontStyleAtCursor(accessor: IAccessor) { } function getTableDisabledObservable(accessor: IAccessor): Observable { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); return new Observable((subscriber) => { - const subscription = textSelectionManagerService.textSelection$.subscribe((selection) => { + const subscription = docSelectionManagerService.textSelection$.subscribe((selection) => { if (selection == null) { subscriber.next(true); return; @@ -213,15 +214,15 @@ function getTableDisabledObservable(accessor: IAccessor): Observable { } const textRange = textRanges[0]; - const { collapsed, anchorNodePosition } = textRange; + const { collapsed, startNodePosition } = textRange; if (!collapsed) { subscriber.next(true); return; } - if (anchorNodePosition != null) { - const { path } = anchorNodePosition; + if (startNodePosition != null) { + const { path } = startNodePosition; // TODO: Not support insert table in table cell now. if (path.indexOf('cells') !== -1) { diff --git a/packages-experimental/uni-docs-ui/src/controllers/uni-docs-ui.controller.tsx b/packages-experimental/uni-docs-ui/src/controllers/uni-docs-ui.controller.tsx index 7be727d9189..986290aa3f3 100644 --- a/packages-experimental/uni-docs-ui/src/controllers/uni-docs-ui.controller.tsx +++ b/packages-experimental/uni-docs-ui/src/controllers/uni-docs-ui.controller.tsx @@ -17,8 +17,7 @@ import { ICommandService, IConfigService, Inject, Injector, IUniverInstanceService, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; import { ComponentManager, ILayoutService, IMenuManagerService, IShortcutService, IUIPartsService } from '@univerjs/ui'; import { BuiltinUniToolbarItemId, generateCloneMutation, UniToolbarService } from '@univerjs/uniui'; -import { DocCreateTableOperation, DocUIController } from '@univerjs/docs-ui'; -import { BulletListCommand, OrderListCommand, SetInlineFormatBoldCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '@univerjs/docs'; +import { BulletListCommand, DocCreateTableOperation, DocUIController, OrderListCommand, SetInlineFormatBoldCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '@univerjs/docs-ui'; import { IMAGE_MENU_ID as DocsImageMenuId } from '@univerjs/docs-drawing-ui'; import { DOC_BOLD_MUTATION_ID, DOC_ITALIC_MUTATION_ID, DOC_STRIKE_MUTATION_ID, DOC_TABLE_MUTATION_ID, DOC_UNDERLINE_MUTATION_ID } from './menu'; import { menuSchema } from './menu.schema'; diff --git a/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts b/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts index b9614323142..930518c9f9e 100644 --- a/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts +++ b/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts @@ -16,7 +16,7 @@ import type { ICommand, IDocumentBody, IMutationInfo } from '@univerjs/core'; import { CommandType, CustomRangeType, generateRandomId, ICommandService, LocaleService, makeCustomRangeStream, sequenceExecute } from '@univerjs/core'; -import { makeSelection, replaceSelectionFactory } from '@univerjs/docs'; +import { makeSelection, replaceSelectionFactory } from '@univerjs/docs-ui'; import type { IAddDocUniFormulaMutationParams, IRemoveDocUniFormulaMutationParams, IUpdateDocUniFormulaMutationParams } from '@univerjs/uni-formula'; import { AddDocUniFormulaMutation, RemoveDocUniFormulaMutation, UpdateDocUniFormulaMutation } from '@univerjs/uni-formula'; diff --git a/packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts b/packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts index d8ebb2cb161..f36a4771c76 100644 --- a/packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts +++ b/packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts @@ -17,7 +17,7 @@ import type { ICommand, IDocumentBody } from '@univerjs/core'; import { CommandType, CustomRangeType, generateRandomId, ICommandService, LocaleService, makeCustomRangeStream } from '@univerjs/core'; import { SLIDE_EDITOR_ID } from '@univerjs/slides-ui'; -import { makeSelection, replaceSelectionFactory } from '@univerjs/docs'; +import { makeSelection, replaceSelectionFactory } from '@univerjs/docs-ui'; import { SlideUIFormulaCacheService } from '../../services/slide-ui-formula-cache.service'; export interface IAddSlideUniFormulaCommandParams { diff --git a/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts b/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts index fe325e4d16b..032673dbf4a 100644 --- a/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts +++ b/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts @@ -16,10 +16,10 @@ import type { DocumentDataModel } from '@univerjs/core'; import { CustomRangeType, Disposable, ICommandService, ILogService, Inject, IUniverInstanceService, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; -import type { IInsertCommandParams } from '@univerjs/docs'; -import { DeleteLeftCommand, InsertCommand, MoveCursorOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { IEditorService } from '@univerjs/ui'; -import { DocEventManagerService } from '@univerjs/docs-ui'; +import type { IInsertCommandParams } from '@univerjs/docs-ui'; +import { DeleteLeftCommand, DocEventManagerService, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui'; import { filter, map, mergeMap } from 'rxjs'; import { IRenderManagerService } from '@univerjs/engine-render'; @@ -39,8 +39,8 @@ export class DocUniFormulaInputController extends Disposable { @IEditorService private readonly _editorService: IEditorService, @ILogService private readonly _logService: ILogService, @Inject(UniFormulaPopupService) private readonly _formulaPopupSrv: UniFormulaPopupService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, - @IRenderManagerService private readonly _renderManagerService: IRenderManagerService + @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); diff --git a/packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts b/packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts index 53c98560791..75488d395b5 100644 --- a/packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts +++ b/packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts @@ -16,9 +16,10 @@ import { Disposable, ICommandService, Inject, Injector, IUniverInstanceService, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; import { IEditorService } from '@univerjs/ui'; -import type { IInsertCommandParams } from '@univerjs/docs'; -import { InsertCommand, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { ISlideEditorBridgeService } from '@univerjs/slides-ui'; +import type { IInsertCommandParams } from '@univerjs/docs-ui'; +import { InsertCommand } from '@univerjs/docs-ui'; import { AddSlideUniFormulaCommand } from '../commands/commands/slide.command'; import { UNI_FORMULA_EDITOR_ID } from '../views/components/DocFormulaPopup'; import { UniFormulaPopupService } from '../services/formula-popup.service'; @@ -34,7 +35,7 @@ export class SlideUniFormulaInputController extends Disposable { @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, @ICommandService private readonly _commandSrv: ICommandService, @IEditorService private readonly _editorSrv: IEditorService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @Inject(UniFormulaPopupService) private readonly _formulaPopupSrv: UniFormulaPopupService ) { super(); diff --git a/packages-experimental/uni-formula-ui/src/services/formula-popup.service.ts b/packages-experimental/uni-formula-ui/src/services/formula-popup.service.ts index feecdebadd5..430e9e23441 100644 --- a/packages-experimental/uni-formula-ui/src/services/formula-popup.service.ts +++ b/packages-experimental/uni-formula-ui/src/services/formula-popup.service.ts @@ -16,8 +16,7 @@ import type { IDisposable, Nullable } from '@univerjs/core'; import { Disposable, FORMULA_EDITOR_ACTIVATED, ICommandService, IContextService, ILogService, Inject } from '@univerjs/core'; -import { makeSelection } from '@univerjs/docs'; -import { DocCanvasPopManagerService } from '@univerjs/docs-ui'; +import { DocCanvasPopManagerService, makeSelection } from '@univerjs/docs-ui'; import { BehaviorSubject, Subject } from 'rxjs'; import type { IShortcutItem } from '@univerjs/ui'; import { IShortcutService, KeyCode } from '@univerjs/ui'; diff --git a/packages-experimental/uni-formula-ui/src/services/uni-formula.service.ts b/packages-experimental/uni-formula-ui/src/services/uni-formula.service.ts index b5b30c38d0f..bfbae039779 100644 --- a/packages-experimental/uni-formula-ui/src/services/uni-formula.service.ts +++ b/packages-experimental/uni-formula-ui/src/services/uni-formula.service.ts @@ -36,7 +36,6 @@ import { toDisposable, UniverInstanceType, } from '@univerjs/core'; -import { makeSelection, replaceSelectionFactory } from '@univerjs/docs'; import { DataSyncPrimaryController } from '@univerjs/rpc'; import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; import type { IDocFormulaCache, ISlideFormulaCache } from '@univerjs/uni-formula'; @@ -44,6 +43,7 @@ import { DumbUniFormulaService, IUniFormulaService } from '@univerjs/uni-formula import { take } from 'rxjs'; import { RichText } from '@univerjs/engine-render'; import { CanvasView } from '@univerjs/slides-ui'; +import { makeSelection, replaceSelectionFactory } from '@univerjs/docs-ui'; import { type IDocPopupPosition, type ISlidePopupPosition, isSlidePosition } from '../commands/operations/operation'; const PSEUDO_SUBUNIT = 'PSEUDO_SUBUNIT'; diff --git a/packages-experimental/uni-sheets-ui/src/controllers/menu.ts b/packages-experimental/uni-sheets-ui/src/controllers/menu.ts index 0219a12654e..e441bafd959 100644 --- a/packages-experimental/uni-sheets-ui/src/controllers/menu.ts +++ b/packages-experimental/uni-sheets-ui/src/controllers/menu.ts @@ -16,7 +16,7 @@ import type { IAccessor } from '@univerjs/core'; import { BooleanNumber, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, EDITOR_ACTIVATED, FOCUSING_SHEET, FontItalic, FontWeight, ICommandService, IContextService, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import { SetInlineFormatCommand, SetTextSelectionsOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, SetTextSelectionsOperation } from '@univerjs/docs'; import { RangeProtectionPermissionEditPoint, SetRangeValuesMutation, @@ -27,6 +27,7 @@ import { WorksheetEditPermission, WorksheetSetCellStylePermission, } from '@univerjs/sheets'; +import { SetInlineFormatCommand } from '@univerjs/docs-ui'; import { deriveStateFromActiveSheet$, getCurrentRangeDisable$ } from '@univerjs/sheets-ui'; import { getMenuHiddenObservable, type IMenuButtonItem, MenuItemType } from '@univerjs/ui'; import { Observable } from 'rxjs'; @@ -266,7 +267,7 @@ export function SheetStrikeThroughMenuItemFactory(accessor: IAccessor): IMenuBut function getFontStyleAtCursor(accessor: IAccessor) { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const editorDataModel = univerInstanceService.getUniverDocInstance(DOCS_NORMAL_EDITOR_UNIT_ID_KEY); const activeTextRange = textSelectionService.getActiveRectRange(); diff --git a/packages/core/src/sheets/typedef.ts b/packages/core/src/sheets/typedef.ts index 7843bc5d132..d62816f6b73 100644 --- a/packages/core/src/sheets/typedef.ts +++ b/packages/core/src/sheets/typedef.ts @@ -566,8 +566,8 @@ export interface ISelection { } /** - * Selection range Info, contains selectionrange & primaryrange - * primaryrange is the range of the highlighted cell. + * Selection range Info, contains selection range & primary range + * primary range is the range of the highlighted cell. */ export interface ISelectionWithCoord { rangeWithCoord: IRangeWithCoord; @@ -578,15 +578,28 @@ export interface ITextRangeStart { startOffset: number; } +export enum RANGE_DIRECTION { + NONE = 'none', + BACKWARD = 'backward', + FORWARD = 'forward', +} + export interface ITextRange extends ITextRangeStart { endOffset: number; collapsed: boolean; + direction?: RANGE_DIRECTION; +} + +export enum DOC_RANGE_TYPE { + RECT = 'RECT', + TEXT = 'TEXT', } export interface ITextRangeParam extends ITextRange { segmentId?: string; //The ID of the header, footer or footnote the location is in. An empty segment ID signifies the document's body. segmentPage?: number; //The page number of the header, footer or footnote the location is in. An empty segment ID signifies the document's body. isActive?: boolean; // Whether the text range is active or current range. + rangeType?: DOC_RANGE_TYPE; } /** diff --git a/packages/docs-drawing-ui/src/commands/commands/insert-doc-drawing.command.ts b/packages/docs-drawing-ui/src/commands/commands/insert-doc-drawing.command.ts index 59aeb2ca8f9..40337285d32 100644 --- a/packages/docs-drawing-ui/src/commands/commands/insert-doc-drawing.command.ts +++ b/packages/docs-drawing-ui/src/commands/commands/insert-doc-drawing.command.ts @@ -24,7 +24,8 @@ import { TextXActionType, } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { getCustomBlockIdsInSelections, getRetainAndDeleteFromReplace, getRichTextEditPath, RichTextEditingMutation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import { getCustomBlockIdsInSelections, getRetainAndDeleteFromReplace, getRichTextEditPath } from '@univerjs/docs-ui'; import type { IInsertDrawingCommandParams } from './interfaces'; /** @@ -42,10 +43,10 @@ export const InsertDocDrawingCommand: ICommand = { } const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const activeTextRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const documentDataModel = univerInstanceService.getCurrentUniverDocInstance(); if (activeTextRange == null || documentDataModel == null) { return false; diff --git a/packages/docs-drawing-ui/src/commands/commands/remove-doc-drawing.command.ts b/packages/docs-drawing-ui/src/commands/commands/remove-doc-drawing.command.ts index 23660024064..b4da059b7a1 100644 --- a/packages/docs-drawing-ui/src/commands/commands/remove-doc-drawing.command.ts +++ b/packages/docs-drawing-ui/src/commands/commands/remove-doc-drawing.command.ts @@ -25,8 +25,9 @@ import { TextXActionType, } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { getRichTextEditPath, RichTextEditingMutation } from '@univerjs/docs'; -import { type ITextRangeWithStyle, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { RichTextEditingMutation } from '@univerjs/docs'; +import { IRenderManagerService, type ITextRangeWithStyle } from '@univerjs/engine-render'; +import { DocSelectionRenderService, getRichTextEditPath } from '@univerjs/docs-ui'; import type { IDeleteDrawingCommandParams } from './interfaces'; /** @@ -39,16 +40,18 @@ export const RemoveDocDrawingCommand: ICommand = { handler: (accessor: IAccessor, params?: IDeleteDrawingCommandParams) => { const commandService = accessor.get(ICommandService); const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionRenderManager = accessor.get(ITextSelectionRenderManager); + const renderManagerService = accessor.get(IRenderManagerService); const documentDataModel = univerInstanceService.getCurrentUniverDocInstance(); if (params == null || documentDataModel == null) { return false; } + const docSelectionRenderService = renderManagerService.getRenderById(params.unitId)!.with(DocSelectionRenderService)!; + const { drawings: removeDrawings } = params; - const segmentId = textSelectionRenderManager.getSegment() ?? ''; + const segmentId = docSelectionRenderService.getSegment() ?? ''; const textX = new TextX(); const jsonX = JSONX.getInstance(); diff --git a/packages/docs-drawing-ui/src/commands/commands/update-doc-drawing.command.ts b/packages/docs-drawing-ui/src/commands/commands/update-doc-drawing.command.ts index abb7665d0cf..4d23094c896 100644 --- a/packages/docs-drawing-ui/src/commands/commands/update-doc-drawing.command.ts +++ b/packages/docs-drawing-ui/src/commands/commands/update-doc-drawing.command.ts @@ -29,9 +29,10 @@ import { Tools, } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { DocSkeletonManagerService, getRichTextEditPath, RichTextEditingMutation } from '@univerjs/docs'; +import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; import type { IDocDrawing } from '@univerjs/docs-drawing'; -import { DocumentEditArea, IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService, getRichTextEditPath } from '@univerjs/docs-ui'; import { DocRefreshDrawingsService } from '../../services/doc-refresh-drawings.service'; export enum TextWrappingStyle { @@ -58,7 +59,7 @@ function getDeleteAndInsertCustomBlockActions( offset: number, drawingId: string, documentDataModel: DocumentDataModel, - textSelectionRenderManager: ITextSelectionRenderManager + docSelectionRenderManager: DocSelectionRenderService ) { const textX = new TextX(); const jsonX = JSONX.getInstance(); @@ -210,8 +211,8 @@ function getDeleteAndInsertCustomBlockActions( action = jsonX.editOp(textX.serialize(), path); rawActions.push(action!); - textSelectionRenderManager.setSegment(segmentId); - textSelectionRenderManager.setSegmentPage(segmentPage); + docSelectionRenderManager.setSegment(segmentId); + docSelectionRenderManager.setSegmentPage(segmentPage); } return rawActions; @@ -669,12 +670,13 @@ export const IMoveInlineDrawingCommand: ICommand = { } const renderManagerService = accessor.get(IRenderManagerService); - const textSelectionRenderManager = accessor.get(ITextSelectionRenderManager); + const docSelectionRenderService = renderManagerService.getRenderById(params.unitId)?.with(DocSelectionRenderService); + const docRefreshDrawingsService = accessor.get(DocRefreshDrawingsService); const renderObject = renderManagerService.getRenderById(params.unitId); const scene = renderObject?.scene; const skeleton = renderObject?.with(DocSkeletonManagerService).getSkeleton(); - if (scene == null) { + if (scene == null || docSelectionRenderService == null) { return false; } const transformer = scene.getTransformerByCreate(); @@ -699,7 +701,7 @@ export const IMoveInlineDrawingCommand: ICommand = { const rawActions: JSONXActions = []; const { drawingId } = drawing; - const segmentId = textSelectionRenderManager.getSegment() ?? ''; + const segmentId = docSelectionRenderService.getSegment() ?? ''; const actions = getDeleteAndInsertCustomBlockActions( newSegmentId, @@ -708,7 +710,7 @@ export const IMoveInlineDrawingCommand: ICommand = { offset, drawingId, documentDataModel, - textSelectionRenderManager + docSelectionRenderService ); if (actions == null || actions.length === 0) { @@ -767,12 +769,13 @@ export const ITransformNonInlineDrawingCommand: ICommand = { return false; } - const textSelectionRenderManager = accessor.get(ITextSelectionRenderManager); - const renderManagerService = accessor.get(IRenderManagerService); + + const docSelectionRenderService = renderManagerService.getRenderById(params.unitId)?.with(DocSelectionRenderService); + const renderObject = renderManagerService.getRenderById(params.unitId); const scene = renderObject?.scene; - if (scene == null) { + if (scene == null || docSelectionRenderService == null) { return false; } const transformer = scene.getTransformerByCreate(); @@ -790,7 +793,7 @@ export const ITransformNonInlineDrawingCommand: ICommand = { const { drawingId } = drawing; - const segmentId = textSelectionRenderManager.getSegment() ?? ''; + const segmentId = docSelectionRenderService.getSegment() ?? ''; const actions = getDeleteAndInsertCustomBlockActions( newSegmentId, @@ -799,7 +802,7 @@ export const ITransformNonInlineDrawingCommand: ICommand = { offset, drawingId, documentDataModel, - textSelectionRenderManager + docSelectionRenderService ); if (actions == null) { diff --git a/packages/docs-drawing-ui/src/controllers/doc-drawing-transformer-update.controller.ts b/packages/docs-drawing-ui/src/controllers/doc-drawing-transformer-update.controller.ts index fda9eac1148..fb8a06f4f87 100644 --- a/packages/docs-drawing-ui/src/controllers/doc-drawing-transformer-update.controller.ts +++ b/packages/docs-drawing-ui/src/controllers/doc-drawing-transformer-update.controller.ts @@ -20,11 +20,12 @@ import { Disposable, ICommandService, IUniverInstanceService, LifecycleStages, ObjectRelativeFromH, ObjectRelativeFromV, OnLifecycle, PositionedObjectLayoutType, throttle, toDisposable, Tools, } from '@univerjs/core'; -import { DocSkeletonManagerService, getDocObject } from '@univerjs/docs'; +import { DocSkeletonManagerService } from '@univerjs/docs'; import { IDrawingManagerService } from '@univerjs/drawing'; -import { DocumentSkeletonPageType, getAnchorBounding, getColor, getOneTextSelectionRange, IRenderManagerService, ITextSelectionRenderManager, Liquid, NodePositionConvertToCursor, PageLayoutType, Rect, TEXT_RANGE_LAYER_INDEX, Vector2 } from '@univerjs/engine-render'; import type { IDocDrawingBase, IDocDrawingPosition, Nullable } from '@univerjs/core'; import type { BaseObject, Documents, IDocumentSkeletonGlyph, IDocumentSkeletonPage, Image, INodeSearch, IPoint, Viewport } from '@univerjs/engine-render'; +import { DocumentSkeletonPageType, getColor, IRenderManagerService, Liquid, PageLayoutType, Rect, Vector2 } from '@univerjs/engine-render'; +import { DocSelectionRenderService, getAnchorBounding, getDocObject, getOneTextSelectionRange, NodePositionConvertToCursor, TEXT_RANGE_LAYER_INDEX } from '@univerjs/docs-ui'; import { IMoveInlineDrawingCommand, ITransformNonInlineDrawingCommand, UpdateDrawingDocTransformCommand } from '../commands/commands/update-doc-drawing.command'; import type { IDrawingDocTransform } from '../commands/commands/update-doc-drawing.command'; @@ -67,8 +68,7 @@ export class DocDrawingTransformerController extends Disposable { @ICommandService private readonly _commandService: ICommandService, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @IDrawingManagerService private readonly _drawingManagerService: IDrawingManagerService, - @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager + @IRenderManagerService private readonly _renderManagerService: IRenderManagerService ) { super(); @@ -390,12 +390,19 @@ export class DocDrawingTransformerController extends Disposable { if (coord == null) { return; } + + const docSelectionRenderService = this._renderManagerService.getRenderById(drawing.unitId)?.with(DocSelectionRenderService); + + if (docSelectionRenderService == null) { + return; + } + const nodeInfo = skeleton?.findNodeByCoord( coord, pageLayoutType, pageMarginLeft, pageMarginTop, { strict: false, - segmentId: this._textSelectionRenderManager.getSegment(), - segmentPage: this._textSelectionRenderManager.getSegmentPage(), + segmentId: docSelectionRenderService.getSegment(), + segmentPage: docSelectionRenderService.getSegmentPage(), } ); if (nodeInfo) { @@ -484,10 +491,16 @@ export class DocDrawingTransformerController extends Disposable { return; } + const docSelectionRenderService = this._renderManagerService.getRenderById(drawing.unitId)?.with(DocSelectionRenderService); + + if (docSelectionRenderService == null) { + return; + } + const nodeInfo = skeleton?.findNodeByCoord(coord, pageLayoutType, pageMarginLeft, pageMarginTop, { strict: false, - segmentId: this._textSelectionRenderManager.getSegment(), - segmentPage: this._textSelectionRenderManager.getSegmentPage(), + segmentId: docSelectionRenderService.getSegment(), + segmentPage: docSelectionRenderService.getSegmentPage(), }); if (nodeInfo) { const { node, segmentPage: segmentPageIndex, segmentId: nodeSegmentId } = nodeInfo; diff --git a/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-transform-update.controller.ts b/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-transform-update.controller.ts index 61bdb1e0492..791b8eaefc1 100644 --- a/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-transform-update.controller.ts +++ b/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-transform-update.controller.ts @@ -27,12 +27,13 @@ import { PositionedObjectLayoutType, } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { DocSkeletonManagerService, RichTextEditingMutation, SetDocZoomRatioOperation } from '@univerjs/docs'; +import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { IDrawingManagerService } from '@univerjs/drawing'; import type { Documents, DocumentSkeleton, IDocumentSkeletonHeaderFooter, IDocumentSkeletonPage, Image, IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { Liquid, TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; import { debounceTime, filter } from 'rxjs'; +import { SetDocZoomRatioOperation } from '@univerjs/docs-ui'; import { DocRefreshDrawingsService } from '../../services/doc-refresh-drawings.service'; interface IDrawingParamsWithBehindText { diff --git a/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-update.render-controller.ts b/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-update.render-controller.ts index 73865e153af..ba4eac44c76 100644 --- a/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-update.render-controller.ts +++ b/packages/docs-drawing-ui/src/controllers/render-controllers/doc-drawing-update.render-controller.ts @@ -14,32 +14,32 @@ * limitations under the License. */ -import type { DocumentDataModel, ICommandInfo, IDocDrawingPosition, Nullable } from '@univerjs/core'; import { BooleanNumber, Disposable, FOCUSING_COMMON_DRAWINGS, ICommandService, IContextService, Inject, LocaleService, ObjectRelativeFromH, ObjectRelativeFromV, PositionedObjectLayoutType, WrapTextType } from '@univerjs/core'; -import type { IImageIoServiceParam } from '@univerjs/drawing'; +import { MessageType } from '@univerjs/design'; +import { DocSelectionManagerService, DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import { IDocDrawingService } from '@univerjs/docs-drawing'; +import { docDrawingPositionToTransform, DocSelectionRenderService } from '@univerjs/docs-ui'; import { DRAWING_IMAGE_ALLOW_IMAGE_LIST, DRAWING_IMAGE_ALLOW_SIZE, DRAWING_IMAGE_COUNT_LIMIT, DRAWING_IMAGE_HEIGHT_LIMIT, DRAWING_IMAGE_WIDTH_LIMIT, DrawingTypeEnum, getDrawingShapeKeyByDrawingSearch, getImageSize, IDrawingManagerService, IImageIoService, ImageUploadStatusType } from '@univerjs/drawing'; +import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render'; import { ILocalFileService, IMessageService } from '@univerjs/ui'; -import { MessageType } from '@univerjs/design'; +import type { DocumentDataModel, ICommandInfo, IDocDrawingPosition, Nullable } from '@univerjs/core'; import type { IDocDrawing } from '@univerjs/docs-drawing'; -import { IDocDrawingService } from '@univerjs/docs-drawing'; -import { DocSkeletonManagerService, RichTextEditingMutation, TextSelectionManagerService } from '@univerjs/docs'; -import { docDrawingPositionToTransform } from '@univerjs/docs-ui'; +import type { IImageIoServiceParam } from '@univerjs/drawing'; import type { Documents, Image, IRenderContext, IRenderModule } from '@univerjs/engine-render'; -import { DocumentEditArea, IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; -import type { IInsertDrawingCommandParams } from '../../commands/commands/interfaces'; -import { type ISetDrawingArrangeCommandParams, SetDocDrawingArrangeCommand } from '../../commands/commands/set-drawing-arrange.command'; -import { InsertDocDrawingCommand } from '../../commands/commands/insert-doc-drawing.command'; import { GroupDocDrawingCommand } from '../../commands/commands/group-doc-drawing.command'; +import { InsertDocDrawingCommand } from '../../commands/commands/insert-doc-drawing.command'; +import { type ISetDrawingArrangeCommandParams, SetDocDrawingArrangeCommand } from '../../commands/commands/set-drawing-arrange.command'; import { UngroupDocDrawingCommand } from '../../commands/commands/ungroup-doc-drawing.command'; import { DocRefreshDrawingsService } from '../../services/doc-refresh-drawings.service'; +import type { IInsertDrawingCommandParams } from '../../commands/commands/interfaces'; export class DocDrawingUpdateRenderController extends Disposable implements IRenderModule { constructor( private readonly _context: IRenderContext, @ICommandService private readonly _commandService: ICommandService, @ILocalFileService private readonly _fileOpenerService: ILocalFileService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _docSelectionManagerService: DocSelectionManagerService, @IRenderManagerService private readonly _renderManagerSrv: IRenderManagerService, @IImageIoService private readonly _imageIoService: IImageIoService, @IDocDrawingService private readonly _docDrawingService: IDocDrawingService, @@ -47,13 +47,11 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen @IContextService private readonly _contextService: IContextService, @IMessageService private readonly _messageService: IMessageService, @Inject(LocaleService) private readonly _localeService: LocaleService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManager: TextSelectionManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, @Inject(DocRefreshDrawingsService) private readonly _docRefreshDrawingsService: DocRefreshDrawingsService ) { super(); - this._updateDrawingListener(); this._updateOrderListener(); this._groupDrawingListener(); this._focusDrawingListener(); @@ -191,7 +189,7 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen private _getImagePosition( imageWidth: number, imageHeight: number ): Nullable { - const activeTextRange = this._textSelectionManagerService.getActiveTextRange(); + const activeTextRange = this._docSelectionRenderService.getActiveTextRange(); const position = activeTextRange?.getAbsolutePosition() || { left: 0, top: 0, @@ -227,13 +225,6 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen }); } - private _updateDrawingListener() { - this._drawingManagerService.featurePluginUpdate$.subscribe((params) => { - // REFACTOR: @JOCS 需要修改,移除 transformer 修改,不需要跟新了,单独处理了。 - // 确认下还需要监听这个吗? - }); - } - private _groupDrawingListener() { this._drawingManagerService.featurePluginGroupUpdate$.subscribe((params) => { this._commandService.executeCommand(GroupDocDrawingCommand.id, params); @@ -276,18 +267,17 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen this._contextService.setContextValue(FOCUSING_COMMON_DRAWINGS, true); this._docDrawingService.focusDrawing(params); // Need to remove text selections when focus drawings. - const activeTextRange = this._textSelectionManager.getActiveTextRange(); + const activeTextRange = this._docSelectionManagerService.getActiveTextRange(); if (activeTextRange) { - this._textSelectionManager.replaceTextRanges([]); + this._docSelectionManagerService.replaceTextRanges([]); } - // this._textSelectionRenderManager.blur(); - const prevSegmentId = this._textSelectionRenderManager.getSegment(); + const prevSegmentId = this._docSelectionRenderService.getSegment(); const segmentId = this._findSegmentIdByDrawingId(params[0].drawingId); // Change segmentId when click drawing in different segment. if (prevSegmentId !== segmentId) { - this._textSelectionRenderManager.setSegment(segmentId); + this._docSelectionRenderService.setSegment(segmentId); } if (transformer) { @@ -332,7 +322,8 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen const { unit: docDataModel, scene, unitId } = this._context; const viewModel = this._renderManagerSrv .getRenderById(unitId) - ?.with(DocSkeletonManagerService).getViewModel(); + ?.with(DocSkeletonManagerService) + .getViewModel(); if (viewModel == null || docDataModel == null) { return; @@ -367,7 +358,8 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen const { unitId } = this._context; const viewModel = this._renderManagerSrv .getRenderById(unitId) - ?.with(DocSkeletonManagerService).getViewModel(); + ?.with(DocSkeletonManagerService) + .getViewModel(); if (viewModel == null) { return; diff --git a/packages/docs-drawing-ui/src/views/doc-image-panel/DocDrawingPosition.tsx b/packages/docs-drawing-ui/src/views/doc-image-panel/DocDrawingPosition.tsx index 7c286e67db6..a1c2e67b643 100644 --- a/packages/docs-drawing-ui/src/views/doc-image-panel/DocDrawingPosition.tsx +++ b/packages/docs-drawing-ui/src/views/doc-image-panel/DocDrawingPosition.tsx @@ -19,12 +19,13 @@ import { ICommandService, IUniverInstanceService, LocaleService, ObjectRelativeF import React, { useEffect, useState } from 'react'; import clsx from 'clsx'; import type { IDocumentSkeletonDrawing } from '@univerjs/engine-render'; -import { IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; import type { IDocDrawing } from '@univerjs/docs-drawing'; import { IDrawingManagerService, type IDrawingParam } from '@univerjs/drawing'; import { Checkbox, InputNumber, Select } from '@univerjs/design'; import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import { DocSelectionRenderService } from '@univerjs/docs-ui'; import { UpdateDrawingDocTransformCommand } from '../../commands/commands/update-doc-drawing.command'; import styles from './index.module.less'; @@ -41,7 +42,6 @@ export const DocDrawingPosition = (props: IDocDrawingPositionProps) => { const drawingManagerService = useDependency(IDrawingManagerService); const renderManagerService = useDependency(IRenderManagerService); const univerInstanceService = useDependency(IUniverInstanceService); - const textSelectionRenderService = useDependency(ITextSelectionRenderManager); const { drawings } = props; @@ -132,7 +132,11 @@ export const DocDrawingPosition = (props: IDocDrawingPositionProps) => { })), }); - textSelectionRenderService.blur(); + const docSelectionRenderService = renderManagerService.getRenderById(unitId)?.with(DocSelectionRenderService); + + if (docSelectionRenderService) { + docSelectionRenderService.blur(); + } transformer.refreshControls(); } @@ -237,12 +241,15 @@ export const DocDrawingPosition = (props: IDocDrawingPositionProps) => { const documentDataModel = univerInstanceService.getUniverDocInstance(unitId); const skeleton = renderManagerService.getRenderById(unitId) ?.with(DocSkeletonManagerService).getSkeleton(); - const segmentId = textSelectionRenderService.getSegment(); - const segmentPage = textSelectionRenderService.getSegmentPage(); + + const docSelectionRenderService = renderManagerService.getRenderById(unitId)?.with(DocSelectionRenderService); + + const segmentId = docSelectionRenderService?.getSegment(); + const segmentPage = docSelectionRenderService?.getSegmentPage(); const drawing = documentDataModel?.getSelfOrHeaderFooterModel(segmentId).getBody()?.customBlocks?.find((c) => c.blockId === drawingId); - if (drawing == null || skeleton == null) { + if (drawing == null || skeleton == null || docSelectionRenderService == null) { return; } diff --git a/packages/docs-drawing-ui/src/views/menu/image.menu.ts b/packages/docs-drawing-ui/src/views/menu/image.menu.ts index 606513901f7..0f727c97763 100644 --- a/packages/docs-drawing-ui/src/views/menu/image.menu.ts +++ b/packages/docs-drawing-ui/src/views/menu/image.menu.ts @@ -17,7 +17,8 @@ import { getMenuHiddenObservable, type IMenuItem, MenuItemType } from '@univerjs/ui'; import { IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; import type { IAccessor } from '@univerjs/core'; -import { TextSelectionManagerService } from '@univerjs/docs'; + +import { DocSelectionManagerService } from '@univerjs/docs'; import { Observable } from 'rxjs'; import { InsertDocImageCommand } from '../../commands/commands/insert-image.command'; @@ -27,12 +28,12 @@ export const IMAGE_MENU_UPLOAD_FLOAT_ID = InsertDocImageCommand.id; // TODO: @Jocs, remove this when cell support drawing. const getDisableWhenSelectionInTableObservable = (accessor: IAccessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); return new Observable((subscriber) => { - const observable = textSelectionManagerService.textSelection$.subscribe(() => { - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const observable = docSelectionManagerService.textSelection$.subscribe(() => { + const activeRange = docSelectionManagerService.getActiveTextRange(); if (activeRange) { const { segmentId, startOffset, endOffset } = activeRange; diff --git a/packages/docs-hyper-link-ui/src/commands/commands/add-link.command.ts b/packages/docs-hyper-link-ui/src/commands/commands/add-link.command.ts index 35175503797..b6b4f2bcdd6 100644 --- a/packages/docs-hyper-link-ui/src/commands/commands/add-link.command.ts +++ b/packages/docs-hyper-link-ui/src/commands/commands/add-link.command.ts @@ -15,7 +15,7 @@ */ import { CommandType, CustomRangeType, generateRandomId, type ICommand, ICommandService } from '@univerjs/core'; -import { addCustomRangeBySelectionFactory } from '@univerjs/docs'; +import { addCustomRangeBySelectionFactory } from '@univerjs/docs-ui'; export interface IAddDocHyperLinkCommandParams { payload: string; @@ -30,7 +30,7 @@ export const AddDocHyperLinkCommand: ICommand = { return false; } - const { payload, unitId } = params; + const { payload } = params; const commandService = accessor.get(ICommandService); const id = generateRandomId(); const doMutation = addCustomRangeBySelectionFactory( diff --git a/packages/docs-hyper-link-ui/src/commands/commands/delete-link.command.ts b/packages/docs-hyper-link-ui/src/commands/commands/delete-link.command.ts index a9156fbc9b8..19feb11da9a 100644 --- a/packages/docs-hyper-link-ui/src/commands/commands/delete-link.command.ts +++ b/packages/docs-hyper-link-ui/src/commands/commands/delete-link.command.ts @@ -16,7 +16,7 @@ import type { ICommand } from '@univerjs/core'; import { CommandType, ICommandService } from '@univerjs/core'; -import { deleteCustomRangeFactory } from '@univerjs/docs'; +import { deleteCustomRangeFactory } from '@univerjs/docs-ui'; export interface IDeleteDocHyperLinkMutationParams { unitId: string; diff --git a/packages/docs-hyper-link-ui/src/commands/commands/update-link.command.ts b/packages/docs-hyper-link-ui/src/commands/commands/update-link.command.ts index 713d429cf1c..3270d56db25 100644 --- a/packages/docs-hyper-link-ui/src/commands/commands/update-link.command.ts +++ b/packages/docs-hyper-link-ui/src/commands/commands/update-link.command.ts @@ -15,7 +15,8 @@ */ import { CommandType, CustomRangeType, DataStreamTreeTokenType, generateRandomId, type ICommand, ICommandService } from '@univerjs/core'; -import { replaceSelectionFactory, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import { replaceSelectionFactory } from '@univerjs/docs-ui'; export interface IUpdateDocHyperLinkCommandParams { unitId: string; @@ -34,8 +35,8 @@ export const UpdateDocHyperLinkCommand: ICommand { - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const textRanges = textSelectionService.getDocRanges(); if (!textRanges.length || textRanges.length > 1) { diff --git a/packages/docs-hyper-link-ui/src/controllers/menu.ts b/packages/docs-hyper-link-ui/src/controllers/menu.ts index edbdd96a12b..ad112f21156 100644 --- a/packages/docs-hyper-link-ui/src/controllers/menu.ts +++ b/packages/docs-hyper-link-ui/src/controllers/menu.ts @@ -19,7 +19,7 @@ import { UniverInstanceType } from '@univerjs/core'; import type { IMenuButtonItem, IShortcutItem } from '@univerjs/ui'; import { getMenuHiddenObservable, KeyCode, MenuItemType, MetaKeys } from '@univerjs/ui'; import { debounceTime, Observable } from 'rxjs'; -import { TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { whenDocAndEditorFocused } from '@univerjs/docs-ui'; import { shouldDisableAddLink, ShowDocHyperLinkEditPopupOperation } from '../commands/operations/popup.operation'; @@ -34,7 +34,7 @@ export function AddHyperLinkMenuItemFactory(accessor: IAccessor): IMenuButtonIte tooltip: 'docLink.menu.tooltip', hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_DOC), disabled$: new Observable(function (subscribe) { - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const observer = textSelectionService.textSelection$.pipe(debounceTime(16)).subscribe(() => { subscribe.next(shouldDisableAddLink(accessor)); }); diff --git a/packages/docs-hyper-link-ui/src/controllers/render-controllers/hyper-link-event.render-controller.ts b/packages/docs-hyper-link-ui/src/controllers/render-controllers/hyper-link-event.render-controller.ts index b1e1176a659..639b6aef78a 100644 --- a/packages/docs-hyper-link-ui/src/controllers/render-controllers/hyper-link-event.render-controller.ts +++ b/packages/docs-hyper-link-ui/src/controllers/render-controllers/hyper-link-event.render-controller.ts @@ -18,7 +18,7 @@ import type { DocumentDataModel } from '@univerjs/core'; import { CustomRangeType, Disposable, ICommandService, Inject } from '@univerjs/core'; import { DocEventManagerService } from '@univerjs/docs-ui'; import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; -import { DocSkeletonManagerService, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import { ClickDocHyperLinkOperation, ToggleDocHyperLinkInfoPopupOperation } from '../../commands/operations/popup.operation'; import { DocHyperLinkPopupService } from '../../services/hyper-link-popup.service'; @@ -33,7 +33,7 @@ export class DocHyperLinkEventRenderController extends Disposable implements IRe @ICommandService private readonly _commandService: ICommandService, @Inject(DocHyperLinkPopupService) private readonly _hyperLinkPopupService: DocHyperLinkPopupService, @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _docSelectionManagerService: DocSelectionManagerService ) { super(); @@ -53,7 +53,8 @@ export class DocHyperLinkEventRenderController extends Disposable implements IRe this.disposeWithMe( this._docEventManagerService.hoverCustomRanges$.subscribe((ranges) => { const link = ranges.find((range) => range.range.rangeType === CustomRangeType.HYPERLINK); - const activeRanges = this._textSelectionManagerService.getCurrentTextRanges(); + const activeRanges = this._docSelectionManagerService.getCurrentTextRanges(); + const currentSegmentId = activeRanges?.[0].segmentId; if ((link?.segmentId ?? '') !== currentSegmentId) { this._hideInfoPopup(); diff --git a/packages/docs-hyper-link-ui/src/services/hyper-link-popup.service.ts b/packages/docs-hyper-link-ui/src/services/hyper-link-popup.service.ts index fef60c7c421..801b671e5ec 100644 --- a/packages/docs-hyper-link-ui/src/services/hyper-link-popup.service.ts +++ b/packages/docs-hyper-link-ui/src/services/hyper-link-popup.service.ts @@ -16,9 +16,9 @@ import type { DocumentDataModel, IDisposable, ITextRangeParam, Nullable } from '@univerjs/core'; import { Disposable, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import { TextSelectionManagerService } from '@univerjs/docs'; import { DocCanvasPopManagerService } from '@univerjs/docs-ui'; import { BehaviorSubject } from 'rxjs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { DocHyperLinkEdit } from '../views/hyper-link-edit'; import { DocLinkPopup } from '../views/hyper-link-popup'; @@ -45,7 +45,7 @@ export class DocHyperLinkPopupService extends Disposable { constructor( @Inject(DocCanvasPopManagerService) private readonly _docCanvasPopupManagerService: DocCanvasPopManagerService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService ) { super(); @@ -69,7 +69,7 @@ export class DocHyperLinkPopupService extends Disposable { this._editPopup.dispose(); } this._editingLink$.next(linkInfo); - let activeRange: Nullable = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + let activeRange: Nullable = this._textSelectionManagerService.getActiveTextRange(); if (linkInfo) { const { unitId, linkId, segmentId, segmentPage } = linkInfo; const doc = this._univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC); diff --git a/packages/docs-hyper-link-ui/src/views/hyper-link-edit/index.tsx b/packages/docs-hyper-link-ui/src/views/hyper-link-edit/index.tsx index 9b48711a52f..e138f133186 100644 --- a/packages/docs-hyper-link-ui/src/views/hyper-link-edit/index.tsx +++ b/packages/docs-hyper-link-ui/src/views/hyper-link-edit/index.tsx @@ -18,9 +18,10 @@ import { Button, FormLayout, Input } from '@univerjs/design'; import React, { useEffect, useState } from 'react'; import { getBodySlice, ICommandService, IUniverInstanceService, LocaleService, Tools, UniverInstanceType, useDependency, useObservable } from '@univerjs/core'; import type { DocumentDataModel } from '@univerjs/core'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; -import { getPlainTextFormBody, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { KeyCode } from '@univerjs/ui'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService, getPlainTextFormBody } from '@univerjs/docs-ui'; import { DocHyperLinkPopupService } from '../../services/hyper-link-popup.service'; import { AddDocHyperLinkCommand } from '../../commands/commands/add-link.command'; import { UpdateDocHyperLinkCommand } from '../../commands/commands/update-link.command'; @@ -46,8 +47,9 @@ export const DocHyperLinkEdit = () => { const editing = useObservable(hyperLinkService.editingLink$); const commandService = useDependency(ICommandService); const univerInstanceService = useDependency(IUniverInstanceService); - const textSelectionRenderManager = useDependency(ITextSelectionRenderManager); - const textSelectionManagerService = useDependency(TextSelectionManagerService); + const renderManagerService = useDependency(IRenderManagerService); + + const docSelectionManagerService = useDependency(DocSelectionManagerService); const [link, setLink] = useState(''); const [label, setLabel] = useState(''); const [showError, setShowError] = useState(false); @@ -56,8 +58,10 @@ export const DocHyperLinkEdit = () => { ? univerInstanceService.getUnit(editing.unitId, UniverInstanceType.UNIVER_DOC) : univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_DOC); + const docSelectionRenderService = renderManagerService.getRenderById(doc!.getUnitId())?.with(DocSelectionRenderService); + useEffect(() => { - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (!activeRange) { return; } @@ -76,14 +80,20 @@ export const DocHyperLinkEdit = () => { if (doc && matchedRange) { setLink(matchedRange?.properties?.url ?? ''); } - }, [doc, editing, textSelectionManagerService, univerInstanceService]); + }, [doc, editing, docSelectionManagerService, univerInstanceService]); + // TODO: @zhangwei, do not use docSelectionRenderService in this component. useEffect(() => { - textSelectionRenderManager.blurEditor(); + if (docSelectionRenderService) { + docSelectionRenderService.blurEditor(); + } + return () => { - textSelectionRenderManager.focusEditor(); + if (docSelectionRenderService) { + docSelectionRenderService.focusEditor(); + } }; - }, [textSelectionRenderManager]); + }, [docSelectionRenderService]); const handleCancel = () => { hyperLinkService.hideEditPopup(); diff --git a/packages/docs-mention-ui/src/commands/commands/doc-mention.command.ts b/packages/docs-mention-ui/src/commands/commands/doc-mention.command.ts index ea4ad6ba2ba..9fba9c3a4d1 100644 --- a/packages/docs-mention-ui/src/commands/commands/doc-mention.command.ts +++ b/packages/docs-mention-ui/src/commands/commands/doc-mention.command.ts @@ -16,7 +16,8 @@ import type { ICommand, IDocumentBody } from '@univerjs/core'; import { CommandType, CustomRangeType, DataStreamTreeTokenType, ICommandService } from '@univerjs/core'; -import { deleteCustomRangeFactory, replaceSelectionFactory, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import { deleteCustomRangeFactory, replaceSelectionFactory } from '@univerjs/docs-ui'; import type { IDocMention } from '../../types/interfaces/i-mention'; export interface IAddDocMentionCommandParams { @@ -35,8 +36,8 @@ export const AddDocMentionCommand: ICommand = { const { mention, unitId, startIndex } = params; const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (!activeRange) { return false; } diff --git a/packages/docs-mention-ui/src/controllers/doc-mention-trigger.controller.ts b/packages/docs-mention-ui/src/controllers/doc-mention-trigger.controller.ts index ea25d2f63d6..21f3062b3c1 100644 --- a/packages/docs-mention-ui/src/controllers/doc-mention-trigger.controller.ts +++ b/packages/docs-mention-ui/src/controllers/doc-mention-trigger.controller.ts @@ -15,8 +15,9 @@ */ import { Disposable, ICommandService, Inject, LifecycleStages, OnLifecycle, Tools } from '@univerjs/core'; -import type { IInsertCommandParams } from '@univerjs/docs'; -import { DeleteLeftCommand, InsertCommand, MoveCursorOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import type { IInsertCommandParams } from '@univerjs/docs-ui'; +import { DeleteLeftCommand, InsertCommand, MoveCursorOperation } from '@univerjs/docs-ui'; import { DocMentionPopupService } from '../services/doc-mention-popup.service'; import { CloseMentionEditPopupOperation, ShowMentionEditPopupOperation } from '../commands/operations/mention-popup.operation'; import { DocMentionService } from '../services/doc-mention.service'; @@ -26,7 +27,7 @@ export class DocMentionTriggerController extends Disposable { constructor( @ICommandService private readonly _commandService: ICommandService, @Inject(DocMentionService) private readonly _docMentionService: DocMentionService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @Inject(DocMentionPopupService) private readonly _docMentionPopupService: DocMentionPopupService ) { super(); @@ -39,7 +40,7 @@ export class DocMentionTriggerController extends Disposable { this._commandService.onCommandExecuted((commandInfo) => { if (commandInfo.id === InsertCommand.id) { const params = commandInfo.params as IInsertCommandParams; - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._textSelectionManagerService.getActiveTextRange(); if (params.body.dataStream === '@' && activeRange && !Tools.isDefine(this._docMentionService.editing)) { this._commandService.executeCommand(ShowMentionEditPopupOperation.id, { startIndex: activeRange.startOffset - 1, @@ -56,7 +57,7 @@ export class DocMentionTriggerController extends Disposable { if (this._docMentionPopupService.editPopup == null) { return; } - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._textSelectionManagerService.getActiveTextRange(); if (activeRange && activeRange.endOffset <= this._docMentionPopupService.editPopup.anchor) { this._commandService.executeCommand(CloseMentionEditPopupOperation.id); } diff --git a/packages/docs-mention-ui/src/views/mention-edit-popup/index.tsx b/packages/docs-mention-ui/src/views/mention-edit-popup/index.tsx index 2ef6015dcee..cd2fd0d71d3 100644 --- a/packages/docs-mention-ui/src/views/mention-edit-popup/index.tsx +++ b/packages/docs-mention-ui/src/views/mention-edit-popup/index.tsx @@ -16,7 +16,8 @@ import { ICommandService, IUniverInstanceService, Tools, UniverInstanceType, useDependency, useObservable, UserManagerService } from '@univerjs/core'; import React, { useEffect } from 'react'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService } from '@univerjs/docs-ui'; import { DocMentionPopupService } from '../../services/doc-mention-popup.service'; import { MentionList } from '../mention-list'; import { AddDocMentionCommand } from '../../commands/commands/doc-mention.command'; @@ -27,7 +28,6 @@ export const MentionEditPopup = () => { const popupService = useDependency(DocMentionPopupService); const commandService = useDependency(ICommandService); const univerInstanceService = useDependency(IUniverInstanceService); - const textSelectionRenderService = useDependency(ITextSelectionRenderManager); const editPopup = useObservable(popupService.editPopup$); const userService = useDependency(UserManagerService); @@ -40,12 +40,16 @@ export const MentionEditPopup = () => { }, })); + const renderManagerService = useDependency(IRenderManagerService); + + const docSelectionRenderService = renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); + useEffect(() => { - textSelectionRenderService.blur(); + docSelectionRenderService?.blur(); return () => { - textSelectionRenderService.focus(); + docSelectionRenderService?.focus(); }; - }, [textSelectionRenderService]); + }, [docSelectionRenderService]); if (!editPopup) { return null; diff --git a/packages/docs-thread-comment-ui/src/commands/commands/add-doc-comment.command.ts b/packages/docs-thread-comment-ui/src/commands/commands/add-doc-comment.command.ts index 86c214097fa..14dfa1d6d75 100644 --- a/packages/docs-thread-comment-ui/src/commands/commands/add-doc-comment.command.ts +++ b/packages/docs-thread-comment-ui/src/commands/commands/add-doc-comment.command.ts @@ -16,10 +16,10 @@ import type { ICommand, ITextRange } from '@univerjs/core'; import { CommandType, CustomDecorationType, ICommandService, sequenceExecuteAsync } from '@univerjs/core'; -import { addCustomDecorationBySelectionFactory } from '@univerjs/docs'; import type { IThreadComment } from '@univerjs/thread-comment'; import { AddCommentMutation, IThreadCommentDataSourceService } from '@univerjs/thread-comment'; import { SetActiveCommentOperation } from '@univerjs/thread-comment-ui'; +import { addCustomDecorationBySelectionFactory } from '@univerjs/docs-ui'; import { DEFAULT_DOC_SUBUNIT_ID } from '../../common/const'; export interface IAddDocCommentComment { diff --git a/packages/docs-thread-comment-ui/src/commands/commands/delete-doc-comment.command.ts b/packages/docs-thread-comment-ui/src/commands/commands/delete-doc-comment.command.ts index a22cec61161..844d8fcf633 100644 --- a/packages/docs-thread-comment-ui/src/commands/commands/delete-doc-comment.command.ts +++ b/packages/docs-thread-comment-ui/src/commands/commands/delete-doc-comment.command.ts @@ -16,7 +16,7 @@ import type { ICommand } from '@univerjs/core'; import { CommandType, ICommandService, sequenceExecute } from '@univerjs/core'; -import { deleteCustomDecorationFactory } from '@univerjs/docs'; +import { deleteCustomDecorationFactory } from '@univerjs/docs-ui'; export interface IDeleteDocCommentComment { unitId: string; diff --git a/packages/docs-thread-comment-ui/src/commands/operations/show-comment-panel.operation.ts b/packages/docs-thread-comment-ui/src/commands/operations/show-comment-panel.operation.ts index ac9cb2bfdc4..f1389d68c18 100644 --- a/packages/docs-thread-comment-ui/src/commands/operations/show-comment-panel.operation.ts +++ b/packages/docs-thread-comment-ui/src/commands/operations/show-comment-panel.operation.ts @@ -19,8 +19,9 @@ import { CommandType, ICommandService, IUniverInstanceService, UniverInstanceTyp import type { ActiveCommentInfo } from '@univerjs/thread-comment-ui'; import { getDT, ThreadCommentPanelService } from '@univerjs/thread-comment-ui'; import { ISidebarService } from '@univerjs/ui'; -import { getSelectionText, TextSelectionManagerService } from '@univerjs/docs'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService, getSelectionText } from '@univerjs/docs-ui'; import { DocThreadCommentPanel } from '../../views/doc-thread-comment-panel'; import { DEFAULT_DOC_SUBUNIT_ID } from '../../common/const'; import { DocThreadCommentService } from '../../services/doc-thread-comment.service'; @@ -85,17 +86,19 @@ export const StartAddCommentOperation: ICommand = { const panelService = accessor.get(ThreadCommentPanelService); const univerInstanceService = accessor.get(IUniverInstanceService); const doc = univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_DOC); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); - const textSelectionRenderService = accessor.get(ITextSelectionRenderManager); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); + const renderManagerService = accessor.get(IRenderManagerService); const userManagerService = accessor.get(UserManagerService); const docCommentService = accessor.get(DocThreadCommentService); const commandService = accessor.get(ICommandService); const sidebarService = accessor.get(ISidebarService); - const textRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const textRange = docSelectionManagerService.getActiveTextRange(); if (!doc || !textRange) { return false; } + const docSelectionRenderManager = renderManagerService.getRenderById(doc.getUnitId())?.with(DocSelectionRenderService); + if (textRange.collapsed) { if (panelService.panelVisible) { panelService.setPanelVisible(false); @@ -127,7 +130,7 @@ export const StartAddCommentOperation: ICommand = { threadId: commentId, }; - textSelectionRenderService.blurEditor(); + docSelectionRenderManager?.blurEditor(); docCommentService.startAdd(comment); panelService.setActiveComment({ unitId, diff --git a/packages/docs-thread-comment-ui/src/controllers/menu.ts b/packages/docs-thread-comment-ui/src/controllers/menu.ts index b5c4aa83c50..e221236abfc 100644 --- a/packages/docs-thread-comment-ui/src/controllers/menu.ts +++ b/packages/docs-thread-comment-ui/src/controllers/menu.ts @@ -18,14 +18,14 @@ import type { IAccessor } from '@univerjs/core'; import { UniverInstanceType } from '@univerjs/core'; import type { IMenuButtonItem } from '@univerjs/ui'; import { getMenuHiddenObservable, MenuItemType } from '@univerjs/ui'; -import { DocSkeletonManagerService, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render'; import { debounceTime, Observable } from 'rxjs'; import { StartAddCommentOperation, ToggleCommentPanelOperation } from '../commands/operations/show-comment-panel.operation'; export const shouldDisableAddComment = (accessor: IAccessor) => { const renderManagerService = accessor.get(IRenderManagerService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const render = renderManagerService.getCurrent(); const skeleton = render?.with(DocSkeletonManagerService).getSkeleton(); const editArea = skeleton?.getViewModel().getEditArea(); @@ -33,7 +33,7 @@ export const shouldDisableAddComment = (accessor: IAccessor) => { return true; } - const range = textSelectionManagerService.getActiveTextRangeWithStyle(); + const range = docSelectionManagerService.getActiveTextRange(); if (range == null || range.collapsed) { return true; @@ -51,7 +51,7 @@ export function AddDocCommentMenuItemFactory(accessor: IAccessor): IMenuButtonIt tooltip: 'threadCommentUI.panel.addComment', hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_DOC), disabled$: new Observable(function (subscribe) { - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const observer = textSelectionService.textSelection$.pipe(debounceTime(16)).subscribe(() => { subscribe.next(shouldDisableAddComment(accessor)); }); diff --git a/packages/docs-thread-comment-ui/src/views/doc-thread-comment-panel/index.tsx b/packages/docs-thread-comment-ui/src/views/doc-thread-comment-panel/index.tsx index ca558fa12c3..3cb3f5b81cf 100644 --- a/packages/docs-thread-comment-ui/src/views/doc-thread-comment-panel/index.tsx +++ b/packages/docs-thread-comment-ui/src/views/doc-thread-comment-panel/index.tsx @@ -19,7 +19,7 @@ import { ICommandService, Injector, IUniverInstanceService, UniverInstanceType, import { ThreadCommentPanel } from '@univerjs/thread-comment-ui'; import React, { useEffect, useMemo, useState } from 'react'; import { debounceTime, Observable } from 'rxjs'; -import { RichTextEditingMutation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { DEFAULT_DOC_SUBUNIT_ID } from '../../common/const'; import { StartAddCommentOperation } from '../../commands/operations/show-comment-panel.operation'; import { DocThreadCommentService } from '../../services/doc-thread-comment.service'; @@ -34,10 +34,10 @@ export const DocThreadCommentPanel = () => { const doc$ = useMemo(() => univerInstanceService.getCurrentTypeOfUnit$(UniverInstanceType.UNIVER_DOC), [univerInstanceService]); const doc = useObservable(doc$); const subUnitId$ = useMemo(() => new Observable((sub) => sub.next(DEFAULT_DOC_SUBUNIT_ID)), []); - const textSelectionManagerService = useDependency(TextSelectionManagerService); + const docSelectionManagerService = useDependency(DocSelectionManagerService); const selectionChange$ = useMemo( - () => textSelectionManagerService.textSelection$.pipe(debounceTime(16)), - [textSelectionManagerService.textSelection$] + () => docSelectionManagerService.textSelection$.pipe(debounceTime(16)), + [docSelectionManagerService.textSelection$] ); useObservable(selectionChange$); const commandService = useDependency(ICommandService); diff --git a/packages/docs/src/basics/__tests__/plain-text.spec.ts b/packages/docs-ui/src/basics/__tests__/plain-text.spec.ts similarity index 100% rename from packages/docs/src/basics/__tests__/plain-text.spec.ts rename to packages/docs-ui/src/basics/__tests__/plain-text.spec.ts diff --git a/packages/docs/src/basics/component-tools.ts b/packages/docs-ui/src/basics/component-tools.ts similarity index 100% rename from packages/docs/src/basics/component-tools.ts rename to packages/docs-ui/src/basics/component-tools.ts diff --git a/packages/docs/src/basics/custom-decoration-factory.ts b/packages/docs-ui/src/basics/custom-decoration-factory.ts similarity index 90% rename from packages/docs/src/basics/custom-decoration-factory.ts rename to packages/docs-ui/src/basics/custom-decoration-factory.ts index 79c13c0220b..46dfeaa252e 100644 --- a/packages/docs/src/basics/custom-decoration-factory.ts +++ b/packages/docs-ui/src/basics/custom-decoration-factory.ts @@ -14,15 +14,15 @@ * limitations under the License. */ -import type { CustomDecorationType, DocumentDataModel, IAccessor, IMutationInfo, ITextRange } from '@univerjs/core'; +import type { CustomDecorationType, DocumentDataModel, IAccessor, IMutationInfo } from '@univerjs/core'; import { getBodySlice, IUniverInstanceService, JSONX, TextX, TextXActionType, Tools, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core'; -import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../commands/mutations/core-editing.mutation'; -import { serializeDocRange, TextSelectionManagerService } from '../services/text-selection-manager.service'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; interface IAddCustomDecorationParam { unitId: string; - ranges: ITextRange[]; + ranges: ITextRangeWithStyle[]; segmentId?: string; id: string; type: CustomDecorationType; @@ -85,10 +85,10 @@ interface IAddCustomDecorationFactoryParam { export function addCustomDecorationBySelectionFactory(accessor: IAccessor, param: IAddCustomDecorationFactoryParam) { const { segmentId, id, type } = param; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const selections = textSelectionManagerService.getCurrentTextRanges(); + const selections = docSelectionManagerService.getCurrentTextRanges(); if (!selections) { return false; } @@ -106,7 +106,7 @@ export function addCustomDecorationBySelectionFactory(accessor: IAccessor, param const doMutation = addCustomDecorationFactory( { unitId, - ranges: selections.map(serializeDocRange), + ranges: selections as ITextRangeWithStyle[], id, type, segmentId, diff --git a/packages/docs/src/basics/custom-range-factory.ts b/packages/docs-ui/src/basics/custom-range-factory.ts similarity index 95% rename from packages/docs/src/basics/custom-range-factory.ts rename to packages/docs-ui/src/basics/custom-range-factory.ts index 2b63a5abf9e..2e46fd28d7d 100644 --- a/packages/docs/src/basics/custom-range-factory.ts +++ b/packages/docs-ui/src/basics/custom-range-factory.ts @@ -16,9 +16,8 @@ import type { CustomRangeType, DocumentDataModel, IAccessor, IDocumentBody, IMutationInfo, ITextRange } from '@univerjs/core'; import { DataStreamTreeTokenType, IUniverInstanceService, JSONX, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core'; -import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../commands/mutations/core-editing.mutation'; -import { TextSelectionManagerService } from '../services/text-selection-manager.service'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getRichTextEditPath } from '../commands/util'; import { getSelectionForAddCustomRange, normalizeSelection } from './selection'; @@ -124,10 +123,10 @@ interface IAddCustomRangeFactoryParam { // eslint-disable-next-line max-lines-per-function export function addCustomRangeBySelectionFactory(accessor: IAccessor, param: IAddCustomRangeFactoryParam) { const { rangeId, rangeType, wholeEntity, properties } = param; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const selection = textSelectionManagerService.getActiveTextRangeWithStyle(); + const selection = docSelectionManagerService.getActiveTextRange(); const segmentId = selection?.segmentId; if (!selection) { return false; diff --git a/packages/docs/src/basics/custom-range.ts b/packages/docs-ui/src/basics/custom-range.ts similarity index 100% rename from packages/docs/src/basics/custom-range.ts rename to packages/docs-ui/src/basics/custom-range.ts diff --git a/packages/docs/src/basics/docs-view-key.ts b/packages/docs-ui/src/basics/docs-view-key.ts similarity index 100% rename from packages/docs/src/basics/docs-view-key.ts rename to packages/docs-ui/src/basics/docs-view-key.ts diff --git a/packages/docs/src/basics/paragraph.ts b/packages/docs-ui/src/basics/paragraph.ts similarity index 100% rename from packages/docs/src/basics/paragraph.ts rename to packages/docs-ui/src/basics/paragraph.ts diff --git a/packages/docs/src/basics/plain-text.ts b/packages/docs-ui/src/basics/plain-text.ts similarity index 100% rename from packages/docs/src/basics/plain-text.ts rename to packages/docs-ui/src/basics/plain-text.ts diff --git a/packages/docs/src/basics/replace.ts b/packages/docs-ui/src/basics/replace.ts similarity index 92% rename from packages/docs/src/basics/replace.ts rename to packages/docs-ui/src/basics/replace.ts index 2f60fc5eaa2..fdb10a9885e 100644 --- a/packages/docs/src/basics/replace.ts +++ b/packages/docs-ui/src/basics/replace.ts @@ -17,9 +17,8 @@ import type { DocumentDataModel, IAccessor, IDeleteAction, IDocumentBody, IMutationInfo, IRetainAction, ITextRange, ITextRangeParam } from '@univerjs/core'; import { IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; import type { ITextRangeWithStyle } from '@univerjs/engine-render'; -import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../commands/mutations/core-editing.mutation'; -import { TextSelectionManagerService } from '../services/text-selection-manager.service'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getRichTextEditPath } from '../commands/util'; import { isIntersecting, shouldDeleteCustomRange } from './custom-range'; import { getDeleteSelection } from './selection'; @@ -142,8 +141,8 @@ export function replaceSelectionFactory(accessor: IAccessor, params: IReplaceSel } if (!body) return false; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); - const selection = params.selection ?? textSelectionManagerService.getActiveTextRangeWithStyle(); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); + const selection = params.selection ?? docSelectionManagerService.getActiveTextRange(); if (!selection || !body) { return false; } diff --git a/packages/docs/src/basics/retain-delete-params.ts b/packages/docs-ui/src/basics/retain-delete-params.ts similarity index 100% rename from packages/docs/src/basics/retain-delete-params.ts rename to packages/docs-ui/src/basics/retain-delete-params.ts diff --git a/packages/docs-ui/src/basics/selection.ts b/packages/docs-ui/src/basics/selection.ts new file mode 100644 index 00000000000..8b5c1c78232 --- /dev/null +++ b/packages/docs-ui/src/basics/selection.ts @@ -0,0 +1,245 @@ +/** + * 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 type { IDocumentBody, ITextRange, Nullable } from '@univerjs/core'; +import { DataStreamTreeTokenType } from '@univerjs/core'; +import { isSegmentIntersects } from '@univerjs/docs'; +import { DeleteDirection } from '../../../docs-ui/src/types/delete-direction'; +import { isCustomRangeSplitSymbol } from './custom-range'; + +export function makeSelection(startOffset: number, endOffset?: number): ITextRange { + if (typeof endOffset === 'undefined') { + return { startOffset, endOffset: startOffset, collapsed: true }; + } + + if (endOffset < startOffset) { + throw new Error(`Cannot make a doc selection when endOffset ${endOffset} is less than startOffset ${startOffset}.`); + } + + return { startOffset, endOffset, collapsed: startOffset === endOffset }; +} + +export function normalizeSelection(selection: ITextRange): ITextRange { + const { startOffset, endOffset, collapsed } = selection; + const start = Math.min(startOffset, endOffset); + const end = Math.max(startOffset, endOffset); + + return { + startOffset: start, + endOffset: end, + collapsed, + }; +} + +export function getSelectionWithSymbolMax(selection: ITextRange, body: IDocumentBody) { + let { startOffset, endOffset } = normalizeSelection(selection); + while (body.dataStream[startOffset - 1] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { + startOffset -= 1; + } + + while (body.dataStream[endOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { + endOffset += 1; + } + + return { + startOffset, + endOffset, + }; +} + +export function getSelectionWithNoSymbolSide(selection: ITextRange, body: IDocumentBody) { + let { startOffset, endOffset } = normalizeSelection(selection); + while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { + startOffset += 1; + } + + while (isCustomRangeSplitSymbol(body.dataStream[endOffset - 1])) { + endOffset -= 1; + } + + return { + startOffset, + endOffset, + }; +} + +export function getDeleteSelection(selection: T, body: IDocumentBody, direction = DeleteDirection.LEFT): T { + let { startOffset, endOffset, collapsed } = normalizeSelection(selection); + + if (collapsed) { + if (direction === DeleteDirection.LEFT) { + while (isCustomRangeSplitSymbol(body.dataStream[startOffset - 1])) { + endOffset -= 1; + startOffset -= 1; + } + } else { + while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { + endOffset += 1; + startOffset += 1; + } + } + } else { + const selectionWithSymbolMax = getSelectionWithSymbolMax(selection, body); + startOffset = selectionWithSymbolMax.startOffset; + endOffset = selectionWithSymbolMax.endOffset; + } + + collapsed = (startOffset === endOffset); + + const customRanges = body.customRanges?.filter((range) => { + if (!range.wholeEntity) { + return false; + } + if (startOffset <= range.startIndex && endOffset > range.endIndex) { + return false; + } + return isSegmentIntersects(startOffset, collapsed ? endOffset : endOffset - 1, range.startIndex, range.endIndex); + }); + + if (customRanges?.length) { + customRanges.forEach((range) => { + startOffset = Math.min(range.startIndex, startOffset); + endOffset = Math.max(range.endIndex + 1, endOffset); + }); + } + + return { + ...selection, + startOffset, + endOffset, + collapsed: startOffset === endOffset, + }; +} + +export function getInsertSelection(selection: T, body: IDocumentBody): T { + let { startOffset, endOffset, collapsed } = normalizeSelection(selection); + + if (collapsed) { + while (body.dataStream[endOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { + endOffset += 1; + startOffset += 1; + } + + while (body.dataStream[endOffset - 1] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { + endOffset -= 1; + startOffset -= 1; + } + + return { + ...selection, + startOffset, + endOffset, + collapsed, + }; + } else { + return { + ...selection, + ...getSelectionWithSymbolMax(selection, body), + collapsed: false, + }; + } +} + +/** + * Ensure custom-range has a correct order, + * when range contains range, it won't be present as intersect.
+ * For Example `\s1\s2 text \s1\s2` is not allowed, expect `\s1\s2 text \s2\s1` + */ +export function getSelectionForAddCustomRange(selection: ITextRange, body: IDocumentBody): Nullable { + if (selection.startOffset === selection.endOffset) { + return null; + } + + const customRanges = body.customRanges; + if (!customRanges) { + return normalizeSelection(selection); + } + + let { startOffset, endOffset } = getSelectionWithSymbolMax(selection, body); + while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { + if (body.dataStream[startOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { + const customRange = customRanges.find((range) => range.startIndex === startOffset); + if (!customRange) { + throw new Error('No custom-range matched'); + } + if (customRange.endIndex === endOffset - 1) { + return { + startOffset, + endOffset, + collapsed: false, + }; + } else if (customRange.endIndex < endOffset - 1) { + break; + } + } + + startOffset += 1; + } + + while (isCustomRangeSplitSymbol(body.dataStream[endOffset - 1])) { + if (body.dataStream[startOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { + const customRange = customRanges.find((range) => range.endIndex === endOffset - 1); + if (!customRange) { + throw new Error('No custom-range matched'); + } + + // but actually not possible + if (customRange.startIndex === startOffset) { + return { + startOffset, + endOffset, + collapsed: false, + }; + } else if (customRange.startIndex > startOffset) { + break; + } + } + endOffset -= 1; + } + + if (endOffset <= startOffset) { + return null; + } + + return { + startOffset, + endOffset, + collapsed: false, + }; +} +const tags = [ + DataStreamTreeTokenType.PARAGRAPH, // 段落 + DataStreamTreeTokenType.SECTION_BREAK, // 章节 + DataStreamTreeTokenType.TABLE_START, // 表格开始 + DataStreamTreeTokenType.TABLE_ROW_START, // 表格开始 + DataStreamTreeTokenType.TABLE_CELL_START, // 表格开始 + DataStreamTreeTokenType.TABLE_CELL_END, // 表格开始 + DataStreamTreeTokenType.TABLE_ROW_END, // 表格开始 + DataStreamTreeTokenType.TABLE_END, // 表格结束 + DataStreamTreeTokenType.CUSTOM_RANGE_START, // 自定义范围开始 + DataStreamTreeTokenType.CUSTOM_RANGE_END, // 自定义范围结束 + DataStreamTreeTokenType.COLUMN_BREAK, // 换列 + DataStreamTreeTokenType.PAGE_BREAK, // 换页 + DataStreamTreeTokenType.DOCS_END, // 文档结尾 + DataStreamTreeTokenType.TAB, // 制表符 + DataStreamTreeTokenType.CUSTOM_BLOCK, // 图片 mention 等不参与文档流的场景 + +]; +export function getSelectionText(dataStream: string, start: number, end: number) { + const text = dataStream.slice(start, end); + return tags.reduce((res, curr) => res.replaceAll(curr, ''), text); +} + diff --git a/packages/docs/src/basics/table.ts b/packages/docs-ui/src/basics/table.ts similarity index 100% rename from packages/docs/src/basics/table.ts rename to packages/docs-ui/src/basics/table.ts diff --git a/packages/docs/src/commands/commands/__tests__/clipboard.command.spec.ts b/packages/docs-ui/src/commands/commands/__tests__/clipboard.command.spec.ts similarity index 89% rename from packages/docs/src/commands/commands/__tests__/clipboard.command.spec.ts rename to packages/docs-ui/src/commands/commands/__tests__/clipboard.command.spec.ts index f5f51f007a3..5008570b950 100644 --- a/packages/docs/src/commands/commands/__tests__/clipboard.command.spec.ts +++ b/packages/docs-ui/src/commands/commands/__tests__/clipboard.command.spec.ts @@ -16,28 +16,13 @@ import type { DocumentDataModel, ICommand, IDocumentData, Injector, IStyleBase, Univer } from '@univerjs/core'; import { BooleanNumber, ICommandService, IUniverInstanceService, UndoCommand, UniverInstanceType } from '@univerjs/core'; -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { RichTextEditingMutation } from '../../mutations/core-editing.mutation'; -import { SetTextSelectionsOperation } from '../../operations/text-selection.operation'; +import { DocSelectionManagerService, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs'; import type { IInnerCutCommandParams, IInnerPasteCommandParams } from '../clipboard.inner.command'; import { CutContentCommand, InnerPasteCommand } from '../clipboard.inner.command'; import { createCommandTestBed } from './create-command-test-bed'; -vi.mock('@univerjs/engine-render', async () => { - const actual = await vi.importActual('@univerjs/engine-render'); - const { ITextSelectionRenderManager, TextSelectionRenderManager } = await import( - './mock-text-selection-render-manager' - ); - - return { - ...actual, - ITextSelectionRenderManager, - TextSelectionRenderManager, - }; -}); - function getDocumentData() { const TEST_DOCUMENT_DATA_EN: IDocumentData = { id: 'test-doc', @@ -137,7 +122,7 @@ describe('test cases in clipboard', () => { commandService.registerCommand(SetTextSelectionsOperation); commandService.registerCommand(RichTextEditingMutation as unknown as ICommand); - const selectionManager = get(TextSelectionManagerService); + const selectionManager = get(DocSelectionManagerService); selectionManager.setCurrentSelection({ unitId: 'test-doc', @@ -148,6 +133,7 @@ describe('test cases in clipboard', () => { { startOffset: 0, endOffset: 5, + collapsed: false, }, ]); @@ -155,6 +141,7 @@ describe('test cases in clipboard', () => { { startOffset: 10, endOffset: 15, + collapsed: false, }, ]); }); diff --git a/packages/docs/src/commands/commands/__tests__/core-editing.command.spec.ts b/packages/docs-ui/src/commands/commands/__tests__/core-editing.command.spec.ts similarity index 100% rename from packages/docs/src/commands/commands/__tests__/core-editing.command.spec.ts rename to packages/docs-ui/src/commands/commands/__tests__/core-editing.command.spec.ts diff --git a/packages/docs/src/commands/commands/__tests__/create-command-test-bed.ts b/packages/docs-ui/src/commands/commands/__tests__/create-command-test-bed.ts similarity index 88% rename from packages/docs/src/commands/commands/__tests__/create-command-test-bed.ts rename to packages/docs-ui/src/commands/commands/__tests__/create-command-test-bed.ts index 3bb69ccf463..4e0446087a9 100644 --- a/packages/docs/src/commands/commands/__tests__/create-command-test-bed.ts +++ b/packages/docs-ui/src/commands/commands/__tests__/create-command-test-bed.ts @@ -23,6 +23,7 @@ import { ILogService, Inject, Injector, + IUndoRedoService, IUniverInstanceService, LogLevel, Plugin, @@ -34,11 +35,10 @@ import type { DocumentSkeleton, IRender, IRenderContext, IRenderModule } from '@ import { DocumentViewModel, IRenderManagerService } from '@univerjs/engine-render'; import { BehaviorSubject, takeUntil } from 'rxjs'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; +import { DocSelectionManagerService, DocSkeletonManagerService, DocStateEmitService } from '@univerjs/docs'; import { DocStateChangeManagerService } from '../../../services/doc-state-change-manager.service'; -import { IMEInputManagerService } from '../../../services/ime-input-manager.service'; -import { DocSkeletonManagerService } from '../../../services/doc-skeleton-manager.service'; -import { ITextSelectionRenderManager, TextSelectionRenderManager } from './mock-text-selection-render-manager'; +import { DocIMEInputManagerService } from '../../../services/doc-ime-input-manager.service'; +import { DocSelectionRenderService } from '../../../services/selection/doc-selection-render.service'; const TEST_DOCUMENT_DATA_EN: IDocumentData = { id: 'test-doc', @@ -95,7 +95,7 @@ const TEST_DOCUMENT_DATA_EN: IDocumentData = { }, }; -export function createCommandTestBed(workbookData?: IDocumentData, dependencies?: Dependency[]) { +export function createCommandTestBed(docData?: IDocumentData, dependencies?: Dependency[]) { const univer = new Univer(); const injector = univer.__getInjector(); const get = injector.get.bind(injector); @@ -112,10 +112,15 @@ export function createCommandTestBed(workbookData?: IDocumentData, dependencies? override onStarting(): void { const injector = this._injector; - injector.add([TextSelectionManagerService]); + injector.get(IUndoRedoService); + + injector.add([IRenderManagerService, { useClass: MockRenderManagerService as unknown as Ctor }]); + + injector.add([DocSelectionManagerService]); + injector.add([DocStateEmitService]); injector.add([DocStateChangeManagerService]); - injector.add([IMEInputManagerService]); - injector.add([ITextSelectionRenderManager, { useClass: TextSelectionRenderManager }]); + injector.add([DocIMEInputManagerService]); + injector.add([DocSelectionRenderService]); dependencies?.forEach((d) => injector.add(d)); } @@ -123,7 +128,7 @@ export function createCommandTestBed(workbookData?: IDocumentData, dependencies? univer.registerPlugin(TestPlugin); - const doc = univer.createUniverDoc(workbookData || TEST_DOCUMENT_DATA_EN); + const doc = univer.createUniverDoc(docData || TEST_DOCUMENT_DATA_EN); const univerInstanceService = get(IUniverInstanceService); @@ -142,7 +147,6 @@ export function createCommandTestBed(workbookData?: IDocumentData, dependencies? }, univerInstanceService); injector.add([DocSkeletonManagerService, { useValue: fakeDocSkeletonManager as unknown as DocSkeletonManagerService }]); - injector.add([IRenderManagerService, { useClass: MockRenderManagerService as unknown as Ctor }]); univerInstanceService.focusUnit('test-doc'); diff --git a/packages/docs/src/commands/commands/__tests__/inline-format.command.spec.ts b/packages/docs-ui/src/commands/commands/__tests__/inline-format.command.spec.ts similarity index 92% rename from packages/docs/src/commands/commands/__tests__/inline-format.command.spec.ts rename to packages/docs-ui/src/commands/commands/__tests__/inline-format.command.spec.ts index b6f577d1fea..d078e184678 100644 --- a/packages/docs/src/commands/commands/__tests__/inline-format.command.spec.ts +++ b/packages/docs-ui/src/commands/commands/__tests__/inline-format.command.spec.ts @@ -16,11 +16,9 @@ import type { DocumentDataModel, ICommand, Injector, IStyleBase, Univer } from '@univerjs/core'; import { BooleanNumber, ICommandService, IUniverInstanceService, RedoCommand, UndoCommand, UniverInstanceType } from '@univerjs/core'; -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { RichTextEditingMutation } from '../../mutations/core-editing.mutation'; -import { SetTextSelectionsOperation } from '../../operations/text-selection.operation'; +import { DocSelectionManagerService, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs'; import { SetInlineFormatBoldCommand, SetInlineFormatCommand, @@ -33,19 +31,6 @@ import { } from '../inline-format.command'; import { createCommandTestBed } from './create-command-test-bed'; -vi.mock('@univerjs/engine-render', async () => { - const actual = await vi.importActual('@univerjs/engine-render'); - const { ITextSelectionRenderManager, TextSelectionRenderManager } = await import( - './mock-text-selection-render-manager' - ); - - return { - ...actual, - ITextSelectionRenderManager, - TextSelectionRenderManager, - }; -}); - describe('Test inline format commands', () => { let univer: Univer; let get: Injector['get']; @@ -78,7 +63,7 @@ describe('Test inline format commands', () => { commandService.registerCommand(SetTextSelectionsOperation); commandService.registerCommand(RichTextEditingMutation as unknown as ICommand); - const selectionManager = get(TextSelectionManagerService); + const selectionManager = get(DocSelectionManagerService); selectionManager.setCurrentSelection({ unitId: 'test-doc', @@ -89,6 +74,7 @@ describe('Test inline format commands', () => { { startOffset: 0, endOffset: 5, + collapsed: false, }, ]); @@ -96,6 +82,7 @@ describe('Test inline format commands', () => { { startOffset: 20, endOffset: 30, + collapsed: false, }, ]); }); diff --git a/packages/docs/src/commands/commands/__tests__/replace-content.command.spec.ts b/packages/docs-ui/src/commands/commands/__tests__/replace-content.command.spec.ts similarity index 85% rename from packages/docs/src/commands/commands/__tests__/replace-content.command.spec.ts rename to packages/docs-ui/src/commands/commands/__tests__/replace-content.command.spec.ts index 1085e4f4f3e..13650970aae 100644 --- a/packages/docs/src/commands/commands/__tests__/replace-content.command.spec.ts +++ b/packages/docs-ui/src/commands/commands/__tests__/replace-content.command.spec.ts @@ -16,27 +16,12 @@ import type { DocumentDataModel, ICommand, IDocumentData, Injector, Univer } from '@univerjs/core'; import { ICommandService, IUniverInstanceService, RedoCommand, UndoCommand, UniverInstanceType } from '@univerjs/core'; -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { RichTextEditingMutation } from '../../mutations/core-editing.mutation'; -import { SetTextSelectionsOperation } from '../../operations/text-selection.operation'; +import { DocSelectionManagerService, RichTextEditingMutation, SetTextSelectionsOperation } from '@univerjs/docs'; import { CoverContentCommand, ReplaceContentCommand } from '../replace-content.command'; import { createCommandTestBed } from './create-command-test-bed'; -vi.mock('@univerjs/engine-render', async () => { - const actual = await vi.importActual('@univerjs/engine-render'); - const { ITextSelectionRenderManager, TextSelectionRenderManager } = await import( - './mock-text-selection-render-manager' - ); - - return { - ...actual, - ITextSelectionRenderManager, - TextSelectionRenderManager, - }; -}); - function getDocumentData() { const TEST_DOCUMENT_DATA_EN: IDocumentData = { id: 'test-doc', @@ -83,7 +68,7 @@ describe('replace or cover content of document', () => { commandService.registerCommand(SetTextSelectionsOperation); commandService.registerCommand(RichTextEditingMutation as unknown as ICommand); - const selectionManager = get(TextSelectionManagerService); + const selectionManager = get(DocSelectionManagerService); selectionManager.setCurrentSelection({ unitId: 'test-doc', @@ -94,6 +79,7 @@ describe('replace or cover content of document', () => { { startOffset: 5, endOffset: 5, + collapsed: true, }, ]); }); diff --git a/packages/docs/src/commands/commands/auto-format.command.ts b/packages/docs-ui/src/commands/commands/auto-format.command.ts similarity index 100% rename from packages/docs/src/commands/commands/auto-format.command.ts rename to packages/docs-ui/src/commands/commands/auto-format.command.ts diff --git a/packages/docs/src/commands/commands/break-line.command.ts b/packages/docs-ui/src/commands/commands/break-line.command.ts similarity index 92% rename from packages/docs/src/commands/commands/break-line.command.ts rename to packages/docs-ui/src/commands/commands/break-line.command.ts index bae4a7fc205..17fe400e111 100644 --- a/packages/docs/src/commands/commands/break-line.command.ts +++ b/packages/docs-ui/src/commands/commands/break-line.command.ts @@ -16,7 +16,7 @@ import type { ICommand, IParagraph } from '@univerjs/core'; import { BooleanNumber, CommandType, DataStreamTreeTokenType, getBodySlice, ICommandService, IUniverInstanceService, normalizeBody, PresetListType, Tools, updateAttributeByInsert } from '@univerjs/core'; -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { getInsertSelection } from '../../basics/selection'; import { copyCustomRange } from '../../basics/custom-range'; import { InsertCommand } from './core-editing.command'; @@ -66,12 +66,12 @@ export const BreakLineCommand: ICommand = { type: CommandType.COMMAND, handler: async (accessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeTextRange = textSelectionManagerService.getActiveTextRangeWithStyle(); - const rectRanges = textSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); + const rectRanges = docSelectionManagerService.getCurrentRectRanges(); if (activeTextRange == null) { return false; } @@ -80,7 +80,7 @@ export const BreakLineCommand: ICommand = { if (rectRanges && rectRanges.length) { const { startOffset } = activeTextRange; - textSelectionManagerService.replaceTextRanges([{ + docSelectionManagerService.replaceTextRanges([{ startOffset, endOffset: startOffset, }]); diff --git a/packages/docs/src/commands/commands/clipboard.inner.command.ts b/packages/docs-ui/src/commands/commands/clipboard.inner.command.ts similarity index 93% rename from packages/docs/src/commands/commands/clipboard.inner.command.ts rename to packages/docs-ui/src/commands/commands/clipboard.inner.command.ts index 9a2785a6ce1..75cdfabf417 100644 --- a/packages/docs/src/commands/commands/clipboard.inner.command.ts +++ b/packages/docs-ui/src/commands/commands/clipboard.inner.command.ts @@ -34,14 +34,12 @@ import { TextXActionType, Tools, } from '@univerjs/core'; -import type { DocumentViewModel, ITextRangeWithStyle, RectRange, TextRange } from '@univerjs/engine-render'; - -import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; -import { getCommandSkeleton, getRichTextEditPath } from '../util'; +import type { DocumentViewModel, IRectRangeWithStyle, ITextRangeWithStyle } from '@univerjs/engine-render'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getRetainAndDeleteAndExcludeLineBreak } from '../../basics/replace'; +import { getCommandSkeleton, getRichTextEditPath } from '../util'; +import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; import { getDeleteRowContentActionParams, getDeleteRowsActionsParams, getDeleteTableActionParams } from './table/table'; export function getCustomBlockIdsInSelections(body: IDocumentBody, selections: ITextRange[]): string[] { @@ -67,11 +65,11 @@ export function getCustomBlockIdsInSelections(body: IDocumentBody, selections: I return customBlockIds; } -function hasRangeInTable(ranges: TextRange[]): boolean { +function hasRangeInTable(ranges: ITextRangeWithStyle[]): boolean { return ranges.some((range) => { - const { anchorNodePosition } = range; + const { startNodePosition } = range; - return anchorNodePosition ? anchorNodePosition?.path.indexOf('cells') > -1 : false; + return startNodePosition ? startNodePosition?.path.indexOf('cells') > -1 : false; }); } @@ -90,9 +88,9 @@ export const InnerPasteCommand: ICommand = { handler: async (accessor, params: IInnerPasteCommandParams) => { const { segmentId, textRanges, doc } = params; const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const selections = textSelectionManagerService.getCurrentTextRanges(); + const selections = docSelectionManagerService.getCurrentTextRanges(); const { body, tableSource, drawings } = doc; if (!Array.isArray(selections) || selections.length === 0 || body == null) { return false; @@ -302,7 +300,7 @@ function getCutActionsFromTextRanges( // eslint-disable-next-line max-lines-per-function function getCutActionsFromRectRanges( - ranges: RectRange[], + ranges: IRectRangeWithStyle[], docDataModel: DocumentDataModel, viewModel: DocumentViewModel, segmentId: string @@ -424,8 +422,8 @@ function getCutActionsFromRectRanges( } export function getCutActionsFromDocRanges( - textRanges: Readonly>, - rectRanges: Readonly>, + textRanges: Readonly>, + rectRanges: Readonly>, docDataModel: DocumentDataModel, viewModel: DocumentViewModel, segmentId: string @@ -465,10 +463,10 @@ export const CutContentCommand: ICommand = { handler: async (accessor, params: IInnerCutCommandParams) => { const { segmentId, textRanges } = params; const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const selections = params.selections ?? textSelectionManagerService.getCurrentTextRanges(); - const rectRanges = textSelectionManagerService.getCurrentRectRanges(); + const selections = params.selections ?? docSelectionManagerService.getCurrentTextRanges(); + const rectRanges = docSelectionManagerService.getCurrentRectRanges(); if ( (!Array.isArray(selections) || selections.length === 0) diff --git a/packages/docs/src/commands/commands/core-editing.command.ts b/packages/docs-ui/src/commands/commands/core-editing.command.ts similarity index 95% rename from packages/docs/src/commands/commands/core-editing.command.ts rename to packages/docs-ui/src/commands/commands/core-editing.command.ts index a2e71dd7898..1c79edc5f0a 100644 --- a/packages/docs/src/commands/commands/core-editing.command.ts +++ b/packages/docs-ui/src/commands/commands/core-editing.command.ts @@ -24,15 +24,14 @@ import type { UpdateDocsAttributeType, } from '@univerjs/core'; import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType, UniverInstanceType } from '@univerjs/core'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import type { ITextRangeWithStyle } from '@univerjs/engine-render'; -import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; -import { isIntersecting, shouldDeleteCustomRange } from '../../basics/custom-range'; -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; import { getInsertSelection } from '../../basics/selection'; +import { isIntersecting, shouldDeleteCustomRange } from '../../basics/custom-range'; +import { DeleteDirection } from '../../types/delete-direction'; import { getRichTextEditPath } from '../util'; -import { DeleteDirection } from '../../types/enums/delete-direction'; +import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; export interface IInsertCommandParams { unitId: string; @@ -55,7 +54,7 @@ export const InsertCommand: ICommand = { const commandService = accessor.get(ICommandService); const { range, segmentId, body, unitId, cursorOffset } = params; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const docDataModel = univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC); @@ -63,7 +62,7 @@ export const InsertCommand: ICommand = { return false; } - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = docSelectionManagerService.getActiveTextRange(); const originBody = docDataModel.getSelfOrHeaderFooterModel(activeRange?.segmentId ?? '').getBody(); if (!originBody) { diff --git a/packages/docs/src/commands/commands/delete.command.ts b/packages/docs-ui/src/commands/commands/delete.command.ts similarity index 93% rename from packages/docs/src/commands/commands/delete.command.ts rename to packages/docs-ui/src/commands/commands/delete.command.ts index e4606aa6a2a..79c6f01cc01 100644 --- a/packages/docs/src/commands/commands/delete.command.ts +++ b/packages/docs-ui/src/commands/commands/delete.command.ts @@ -30,22 +30,20 @@ import { Tools, UpdateDocsAttributeType, } from '@univerjs/core'; -import type { IActiveTextRange, ITextRangeWithStyle, RectRange, TextRange } from '@univerjs/engine-render'; +import type { IRectRangeWithStyle, ITextRangeWithStyle } from '@univerjs/engine-render'; import { getParagraphByGlyph, hasListGlyph, isFirstGlyph, isIndentByGlyph } from '@univerjs/engine-render'; -import type { ITextActiveRange } from '../../services/text-selection-manager.service'; -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getDeleteSelection } from '../../basics/selection'; import { getCommandSkeleton, getRichTextEditPath } from '../util'; -import { DeleteDirection } from '../../types/enums/delete-direction'; +import { DeleteDirection } from '../../types/delete-direction'; import { CutContentCommand } from './clipboard.inner.command'; import { DeleteCommand, UpdateCommand } from './core-editing.command'; export interface IDeleteCustomBlockParams { direction: DeleteDirection; - range: IActiveTextRange; + range: ITextRangeWithStyle; unitId: string; drawingId: string; } @@ -55,11 +53,11 @@ export const DeleteCustomBlockCommand: ICommand = { id: 'doc.command.delete-custom-block', type: CommandType.COMMAND, handler: async (accessor, params: IDeleteCustomBlockParams) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = docSelectionManagerService.getActiveTextRange(); const documentDataModel = univerInstanceService.getCurrentUniverDocInstance(); if (activeRange == null || documentDataModel == null) { @@ -137,7 +135,7 @@ export const DeleteCustomBlockCommand: ICommand = { interface IMergeTwoParagraphParams { direction: DeleteDirection; - range: IActiveTextRange; + range: ITextRangeWithStyle; } export const MergeTwoParagraphCommand: ICommand = { @@ -146,14 +144,14 @@ export const MergeTwoParagraphCommand: ICommand = { type: CommandType.COMMAND, // eslint-disable-next-line max-lines-per-function handler: async (accessor, params: IMergeTwoParagraphParams) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); const { direction, range } = params; - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); - const ranges = textSelectionManagerService.getCurrentTextRanges(); + const activeRange = docSelectionManagerService.getActiveTextRange(); + const ranges = docSelectionManagerService.getCurrentTextRanges(); if (activeRange == null || ranges == null) { return false; @@ -241,7 +239,7 @@ export const MergeTwoParagraphCommand: ICommand = { }, }; -export function getCursorWhenDelete(textRanges: Readonly>, rectRanges: readonly RectRange[]): number { +export function getCursorWhenDelete(textRanges: Readonly>, rectRanges: readonly IRectRangeWithStyle[]): number { let cursor = 0; if (textRanges == null || textRanges.length === 0) { @@ -295,7 +293,7 @@ export const DeleteLeftCommand: ICommand = { type: CommandType.COMMAND, // eslint-disable-next-line max-lines-per-function, complexity handler: async (accessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); @@ -308,9 +306,9 @@ export const DeleteLeftCommand: ICommand = { const unitId = docDataModel.getUnitId(); const docSkeletonManagerService = getCommandSkeleton(accessor, unitId); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); - const rectRanges = textSelectionManagerService.getCurrentRectRanges(); - const ranges = textSelectionManagerService.getCurrentTextRanges(); + const activeRange = docSelectionManagerService.getActiveTextRange(); + const rectRanges = docSelectionManagerService.getCurrentRectRanges(); + const ranges = docSelectionManagerService.getCurrentTextRanges(); const skeleton = docSkeletonManagerService?.getSkeleton(); if (skeleton == null) { @@ -513,7 +511,7 @@ export const DeleteRightCommand: ICommand = { // eslint-disable-next-line max-lines-per-function, complexity handler: async (accessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); if (!docDataModel) { @@ -523,9 +521,9 @@ export const DeleteRightCommand: ICommand = { const docSkeletonManagerService = getCommandSkeleton(accessor, docDataModel.getUnitId()); const commandService = accessor.get(ICommandService); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); - const rectRanges = textSelectionManagerService.getCurrentRectRanges(); - const ranges = textSelectionManagerService.getCurrentTextRanges(); + const activeRange = docSelectionManagerService.getActiveTextRange(); + const rectRanges = docSelectionManagerService.getCurrentRectRanges(); + const ranges = docSelectionManagerService.getCurrentTextRanges(); const skeleton = docSkeletonManagerService?.getSkeleton(); if (rectRanges?.length) { @@ -724,7 +722,7 @@ function getParagraphBody( } // get cursor position when BACKSPACE/DELETE excuse the CutContentCommand. -function getTextRangesWhenDelete(activeRange: ITextActiveRange, ranges: readonly ITextRange[]) { +function getTextRangesWhenDelete(activeRange: ITextRangeWithStyle, ranges: readonly ITextRange[]) { let cursor = activeRange.endOffset; for (const range of ranges) { diff --git a/packages/docs-ui/src/commands/commands/doc-paragraph-setting.command.ts b/packages/docs-ui/src/commands/commands/doc-paragraph-setting.command.ts index f59b7f9188f..71e5025c47e 100644 --- a/packages/docs-ui/src/commands/commands/doc-paragraph-setting.command.ts +++ b/packages/docs-ui/src/commands/commands/doc-paragraph-setting.command.ts @@ -17,7 +17,9 @@ import type { DocumentDataModel, IAccessor, ICommand, IMutationInfo, IParagraphStyle } from '@univerjs/core'; import { CommandType, ICommandService, IUniverInstanceService, JSONX, MemoryCursor, TextX, TextXActionType, UniverInstanceType, UpdateDocsAttributeType } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { getParagraphsInRanges, getRichTextEditPath, RichTextEditingMutation, serializeDocRange, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import { getRichTextEditPath } from '../util'; +import { getParagraphsInRanges } from './list.command'; export interface IDocParagraphSettingCommandParams { paragraph: Partial>; @@ -27,13 +29,13 @@ export const DocParagraphSettingCommand: ICommand { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); const docDataModel = univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_DOC); - const docRanges = textSelectionManagerService.getDocRanges(); + const docRanges = docSelectionManagerService.getDocRanges(); if (!docDataModel || docRanges.length === 0 || !config) { return false; @@ -46,14 +48,12 @@ export const DocParagraphSettingCommand: ICommand = { id: RichTextEditingMutation.id, params: { unitId, actions: [], - textRanges: serializedSelections, + textRanges: docRanges, }, }; diff --git a/packages/docs/src/commands/commands/ime-input.command.ts b/packages/docs-ui/src/commands/commands/ime-input.command.ts similarity index 86% rename from packages/docs/src/commands/commands/ime-input.command.ts rename to packages/docs-ui/src/commands/commands/ime-input.command.ts index c1a0f5cf164..8afc28040c6 100644 --- a/packages/docs/src/commands/commands/ime-input.command.ts +++ b/packages/docs-ui/src/commands/commands/ime-input.command.ts @@ -16,14 +16,13 @@ import type { ICommand, ICommandInfo } from '@univerjs/core'; import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; -import type { ITextRangeWithStyle } from '@univerjs/engine-render'; - -import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; -import { IMEInputManagerService } from '../../services/ime-input-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; +import { IRenderManagerService, type ITextRangeWithStyle } from '@univerjs/engine-render'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { RichTextEditingMutation } from '@univerjs/docs'; +import { DocIMEInputManagerService } from '../../services/doc-ime-input-manager.service'; import { getInsertSelection } from '../../basics/selection'; import { getRichTextEditPath } from '../util'; +import { getRetainAndDeleteFromReplace } from '../../basics/retain-delete-params'; export interface IIMEInputCommandParams { unitId: string; @@ -42,11 +41,13 @@ export const IMEInputCommand: ICommand = { handler: async (accessor, params: IIMEInputCommandParams) => { const { unitId, newText, oldTextLen, isCompositionEnd, isCompositionStart } = params; const commandService = accessor.get(ICommandService); - const imeInputManagerService = accessor.get(IMEInputManagerService); + const renderManagerService = accessor.get(IRenderManagerService); + + const imeInputManagerService = renderManagerService.getRenderById(unitId)?.with(DocIMEInputManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - if (docDataModel == null) { + if (docDataModel == null || imeInputManagerService == null) { return false; } @@ -88,23 +89,20 @@ export const IMEInputCommand: ICommand = { const textX = new TextX(); const jsonX = JSONX.getInstance(); - let memoryCursor = 0; if (!previousActiveRange.collapsed && isCompositionStart) { - const { dos, retain, cursor } = getRetainAndDeleteFromReplace(previousActiveRange, segmentId, 0, body); + const { dos, retain } = getRetainAndDeleteFromReplace(previousActiveRange, segmentId, 0, body); textX.push(...dos); doMutation.params!.textRanges = [{ startOffset: startOffset + len + retain, endOffset: startOffset + len + retain, collapsed: true, }]; - memoryCursor = cursor; } else { textX.push({ t: TextXActionType.RETAIN, len: startOffset, segmentId, }); - memoryCursor = startOffset; } if (oldTextLen > 0) { diff --git a/packages/docs/src/commands/commands/inline-format.command.ts b/packages/docs-ui/src/commands/commands/inline-format.command.ts similarity index 95% rename from packages/docs/src/commands/commands/inline-format.command.ts rename to packages/docs-ui/src/commands/commands/inline-format.command.ts index 896b524dd0e..adf74e8530c 100644 --- a/packages/docs/src/commands/commands/inline-format.command.ts +++ b/packages/docs-ui/src/commands/commands/inline-format.command.ts @@ -23,10 +23,9 @@ import { JSONX, MemoryCursor, TextX, TextXActionType, } from '@univerjs/core'; -import type { IDocRange } from '@univerjs/engine-render'; -import { serializeDocRange, TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; import { getRichTextEditPath } from '../util'; function handleInlineFormat( @@ -232,10 +231,10 @@ export const SetInlineFormatCommand: ICommand = { handler: async (accessor, params: ISetInlineFormatCommandParams) => { const { value, preCommandId } = params; const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); - const docRanges = textSelectionManagerService.getDocRanges(); + const docRanges = docSelectionManagerService.getDocRanges(); if (docRanges.length === 0) { return false; @@ -299,7 +298,7 @@ export const SetInlineFormatCommand: ICommand = { params: { unitId, actions: [], - textRanges: docRanges.map(serializeDocRange), + textRanges: docRanges, }, }; @@ -375,7 +374,7 @@ function isTextDecoration(value: unknown | ITextDecoration): value is ITextDecor function getReverseFormatValueInSelection( textRuns: ITextRun[], preCommandId: string, - docRanges: IDocRange[] + docRanges: ITextRangeWithStyle[] ): BooleanNumber | ITextDecoration | BaselineOffset { let ti = 0; let si = 0; diff --git a/packages/docs/src/commands/commands/list.command.ts b/packages/docs-ui/src/commands/commands/list.command.ts similarity index 93% rename from packages/docs/src/commands/commands/list.command.ts rename to packages/docs-ui/src/commands/commands/list.command.ts index f142a93c698..7805223f8a8 100644 --- a/packages/docs/src/commands/commands/list.command.ts +++ b/packages/docs-ui/src/commands/commands/list.command.ts @@ -30,12 +30,10 @@ import { Tools, UpdateDocsAttributeType, } from '@univerjs/core'; -import type { IActiveTextRange, IDocRange } from '@univerjs/engine-render'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; import { getCharSpaceApply, getNumberUnitValue } from '@univerjs/engine-render'; - -import { serializeDocRange, TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; import { getRichTextEditPath } from '../util'; import { hasParagraphInTable } from '../../basics/paragraph'; @@ -48,14 +46,14 @@ export const ListOperationCommand: ICommand = { type: CommandType.COMMAND, // eslint-disable-next-line max-lines-per-function, complexity handler: (accessor, params: IListOperationCommandParams) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); let listType: string = params.listType; const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const docRanges = textSelectionManagerService.getDocRanges() ?? []; + const docRanges = docSelectionManagerService.getDocRanges() ?? []; if (docDataModel == null || docRanges.length === 0) { return false; @@ -64,7 +62,6 @@ export const ListOperationCommand: ICommand = { const segmentId = docRanges[0].segmentId; const paragraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs; - const serializedSelections = docRanges.map(serializeDocRange); if (paragraphs == null) { return false; @@ -105,7 +102,7 @@ export const ListOperationCommand: ICommand = { params: { unitId, actions: [], - textRanges: serializedSelections, + textRanges: docRanges, }, }; @@ -201,20 +198,19 @@ export const ChangeListTypeCommand: ICommand = { type: CommandType.COMMAND, // eslint-disable-next-line max-lines-per-function handler: (accessor, params: IChangeListTypeCommandParams) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); const { listType } = params; const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const activeRanges = textSelectionManagerService.getDocRanges(); + const activeRanges = docSelectionManagerService.getDocRanges(); if (docDataModel == null || activeRanges == null || !activeRanges.length) { return false; } const { segmentId } = activeRanges[0]; - const selections = textSelectionManagerService.getDocRanges() ?? []; + const selections = docSelectionManagerService.getDocRanges() ?? []; const paragraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs; - const serializedSelections = selections.map(serializeDocRange); if (paragraphs == null) { return false; @@ -231,7 +227,7 @@ export const ChangeListTypeCommand: ICommand = { params: { unitId, actions: [], - textRanges: serializedSelections, + textRanges: selections, }, }; @@ -333,20 +329,19 @@ export const ChangeListNestingLevelCommand: ICommand = { id: 'doc.command.toggle-check-list', type: CommandType.COMMAND, + // eslint-disable-next-line max-lines-per-function handler: (accessor, params) => { if (!params) { return false; @@ -611,11 +607,11 @@ export const QuickListCommand: ICommand = { if (!params) { return false; } - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const activeRange = textSelectionManagerService.getActiveTextRange(); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (docDataModel == null || activeRange == null) { return false; } @@ -718,7 +714,7 @@ export const QuickListCommand: ICommand = { }, }; -export function getParagraphsInRange(activeRange: IActiveTextRange, paragraphs: IParagraph[]) { +export function getParagraphsInRange(activeRange: ITextRangeWithStyle, paragraphs: IParagraph[]) { const { startOffset, endOffset } = activeRange; const results: IParagraph[] = []; @@ -739,7 +735,7 @@ export function getParagraphsInRange(activeRange: IActiveTextRange, paragraphs: return results; } -export function getParagraphsRelative(ranges: IDocRange[], paragraphs: IParagraph[]) { +export function getParagraphsRelative(ranges: ITextRangeWithStyle[], paragraphs: IParagraph[]) { const selectionParagraphs = getParagraphsInRanges(ranges, paragraphs); const startIndex = paragraphs.indexOf(selectionParagraphs[0]); const endIndex = paragraphs.indexOf(selectionParagraphs[selectionParagraphs.length - 1]); @@ -765,11 +761,11 @@ export function getParagraphsRelative(ranges: IDocRange[], paragraphs: IParagrap return selectionParagraphs; } -export function getParagraphsInRanges(ranges: IDocRange[], paragraphs: IParagraph[]) { +export function getParagraphsInRanges(ranges: ITextRangeWithStyle[], paragraphs: IParagraph[]) { const results: IParagraph[] = []; for (const range of ranges) { - const ps = getParagraphsInRange(range as unknown as IActiveTextRange, paragraphs); + const ps = getParagraphsInRange(range, paragraphs); results.push(...ps); } diff --git a/packages/docs/src/commands/commands/paragraph-align.command.ts b/packages/docs-ui/src/commands/commands/paragraph-align.command.ts similarity index 91% rename from packages/docs/src/commands/commands/paragraph-align.command.ts rename to packages/docs-ui/src/commands/commands/paragraph-align.command.ts index c292c9d6ba4..1044a824fa5 100644 --- a/packages/docs/src/commands/commands/paragraph-align.command.ts +++ b/packages/docs-ui/src/commands/commands/paragraph-align.command.ts @@ -26,9 +26,8 @@ import { UpdateDocsAttributeType, } from '@univerjs/core'; -import { serializeDocRange, TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getRichTextEditPath } from '../util'; import { getParagraphsInRanges } from './list.command'; @@ -43,7 +42,7 @@ export const AlignOperationCommand: ICommand = { // eslint-disable-next-line max-lines-per-function handler: (accessor, params: IAlignOperationCommandParams) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); @@ -54,7 +53,7 @@ export const AlignOperationCommand: ICommand = { return false; } - const allRanges = textSelectionManagerService.getDocRanges(); + const allRanges = docSelectionManagerService.getDocRanges(); if (allRanges.length === 0) { return false; } @@ -62,7 +61,6 @@ export const AlignOperationCommand: ICommand = { const segmentId = allRanges[0].segmentId; const paragraphs = docDataModel.getSelfOrHeaderFooterModel(segmentId).getBody()?.paragraphs; - const serializedSelections = allRanges.map(serializeDocRange); if (paragraphs == null) { return false; @@ -78,7 +76,7 @@ export const AlignOperationCommand: ICommand = { params: { unitId, actions: [], - textRanges: serializedSelections, + textRanges: allRanges, }, }; diff --git a/packages/docs/src/commands/commands/replace-content.command.ts b/packages/docs-ui/src/commands/commands/replace-content.command.ts similarity index 91% rename from packages/docs/src/commands/commands/replace-content.command.ts rename to packages/docs-ui/src/commands/commands/replace-content.command.ts index 5639c3f9e16..e235126edc1 100644 --- a/packages/docs/src/commands/commands/replace-content.command.ts +++ b/packages/docs-ui/src/commands/commands/replace-content.command.ts @@ -16,13 +16,11 @@ import type { DocumentDataModel, ICommand, IDocumentBody, IMutationInfo, ITextRange } from '@univerjs/core'; import { CommandType, ICommandService, IUndoRedoService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import type { ITextRangeWithStyle } from '@univerjs/engine-render'; - -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation'; -import { RichTextEditingMutation } from '../mutations/core-editing.mutation'; -import { getRichTextEditPath } from '../util'; import { getRetainAndDeleteAndExcludeLineBreak } from '../../basics/replace'; +import { getRichTextEditPath } from '../util'; interface IReplaceContentCommandParams { unitId: string; @@ -42,11 +40,11 @@ export const ReplaceContentCommand: ICommand = { const { unitId, body, textRanges, segmentId = '', options } = params; const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const docDataModel = univerInstanceService.getUniverDocInstance(unitId); const prevBody = docDataModel?.getSnapshot().body; - const selections = textSelectionManagerService.getCurrentTextRanges(); + const selections = docSelectionManagerService.getCurrentTextRanges(); if (docDataModel == null || prevBody == null) { return false; @@ -170,13 +168,13 @@ export const ReplaceSelectionCommand: ICommand = const { unitId, body: insertBody, textRanges } = params; const univerInstanceService = accessor.get(IUniverInstanceService); const docDataModel = univerInstanceService.getUnit(unitId); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); if (!docDataModel) { return false; } const body = docDataModel.getBody(); - const selection = params.selection ?? textSelectionManagerService.getActiveTextRangeWithStyle(); + const selection = params.selection ?? docSelectionManagerService.getActiveTextRange(); if (!selection || !body) { return false; } diff --git a/packages/docs/src/commands/commands/set-doc-zoom-ratio.command.ts b/packages/docs-ui/src/commands/commands/set-doc-zoom-ratio.command.ts similarity index 100% rename from packages/docs/src/commands/commands/set-doc-zoom-ratio.command.ts rename to packages/docs-ui/src/commands/commands/set-doc-zoom-ratio.command.ts diff --git a/packages/docs/src/commands/commands/table/doc-table-create.command.ts b/packages/docs-ui/src/commands/commands/table/doc-table-create.command.ts similarity index 93% rename from packages/docs/src/commands/commands/table/doc-table-create.command.ts rename to packages/docs-ui/src/commands/commands/table/doc-table-create.command.ts index e45d595dda9..b2d4fb2d942 100644 --- a/packages/docs/src/commands/commands/table/doc-table-create.command.ts +++ b/packages/docs-ui/src/commands/commands/table/doc-table-create.command.ts @@ -16,12 +16,12 @@ import { CommandType, DataStreamTreeTokenType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core'; -import type { ITextRangeWithStyle } from '@univerjs/engine-render'; import { getInsertSelection } from '../../../basics/selection'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { type IRichTextEditingMutationParams, RichTextEditingMutation } from '../../mutations/core-editing.mutation'; import { getCommandSkeleton, getRichTextEditPath } from '../../util'; import { generateParagraphs } from '../break-line.command'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; import { genEmptyTable, genTableSource } from './table'; export const CreateDocTableCommandId = 'doc.command.create-table'; @@ -37,14 +37,14 @@ export const CreateDocTableCommand: ICommand = { id: CreateDocTableCommandId, type: CommandType.COMMAND, - // eslint-disable-next-line max-lines-per-function + // eslint-disable-next-line max-lines-per-function, complexity handler: async (accessor, params: ICreateDocTableCommandParams) => { const { rowCount, colCount } = params; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { return false; } diff --git a/packages/docs/src/commands/commands/table/doc-table-delete.command.ts b/packages/docs-ui/src/commands/commands/table/doc-table-delete.command.ts similarity index 91% rename from packages/docs/src/commands/commands/table/doc-table-delete.command.ts rename to packages/docs-ui/src/commands/commands/table/doc-table-delete.command.ts index f56f3592568..f31f6a3a676 100644 --- a/packages/docs/src/commands/commands/table/doc-table-delete.command.ts +++ b/packages/docs-ui/src/commands/commands/table/doc-table-delete.command.ts @@ -17,8 +17,8 @@ import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core'; import type { ITextRangeWithStyle } from '@univerjs/engine-render'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { type IRichTextEditingMutationParams, RichTextEditingMutation } from '../../mutations/core-editing.mutation'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getCommandSkeleton, getRichTextEditPath } from '../../util'; import { getDeleteColumnsActionParams, getDeleteRowsActionsParams, getDeleteTableActionParams, getRangeInfoFromRanges } from './table'; @@ -29,12 +29,12 @@ export const DocTableDeleteRowsCommand: ICommand { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeTextRange = textSelectionManagerService.getActiveTextRange(); + const activeRectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const rangeInfo = getRangeInfoFromRanges(activeTextRange, activeRectRanges); @@ -135,12 +135,12 @@ export const DocTableDeleteColumnsCommand: ICommand { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeTextRange = textSelectionManagerService.getActiveTextRange(); + const activeRectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const rangeInfo = getRangeInfoFromRanges(activeTextRange, activeRectRanges); @@ -252,12 +252,12 @@ export const DocTableDeleteTableCommand: ICommand { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeTextRange = textSelectionManagerService.getActiveTextRange(); + const activeRectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const rangeInfo = getRangeInfoFromRanges(activeTextRange, activeRectRanges); diff --git a/packages/docs/src/commands/commands/table/doc-table-insert.command.ts b/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts similarity index 93% rename from packages/docs/src/commands/commands/table/doc-table-insert.command.ts rename to packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts index fd154ba4f03..0171df33456 100644 --- a/packages/docs/src/commands/commands/table/doc-table-insert.command.ts +++ b/packages/docs-ui/src/commands/commands/table/doc-table-insert.command.ts @@ -17,11 +17,10 @@ import { CommandType, ICommandService, IUniverInstanceService, JSONX, TextX, TextXActionType } from '@univerjs/core'; import type { ICommand, IMutationInfo, JSONXActions } from '@univerjs/core'; import type { ITextRangeWithStyle } from '@univerjs/engine-render'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; -import { RichTextEditingMutation } from '../../mutations/core-editing.mutation'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import { DocSelectionManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { getCommandSkeleton, getRichTextEditPath } from '../../util'; import { getColumnWidths, getEmptyTableCell, getEmptyTableRow, getInsertColumnActionsParams, getInsertColumnBody, getInsertRowActionsParams, getInsertRowBody, getRangeInfoFromRanges, getTableColumn, INSERT_COLUMN_POSITION, INSERT_ROW_POSITION } from './table'; -import type { IRichTextEditingMutationParams } from '../../mutations/core-editing.mutation'; // Insert rows and columns are in this file. @@ -98,12 +97,12 @@ export const DocTableInsertRowCommand: ICommand // eslint-disable-next-line max-lines-per-function handler: async (accessor, params: IDocTableInsertRowCommandParams) => { const { position } = params; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeTextRange = textSelectionManagerService.getActiveTextRange(); + const activeRectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const rangeInfo = getRangeInfoFromRanges(activeTextRange, activeRectRanges); @@ -209,12 +208,12 @@ export const DocTableInsertColumnCommand: ICommand { const { position } = params; - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); const commandService = accessor.get(ICommandService); - const activeRectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeTextRange = textSelectionManagerService.getActiveTextRange(); + const activeRectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); const rangeInfo = getRangeInfoFromRanges(activeTextRange, activeRectRanges); diff --git a/packages/docs/src/commands/commands/table/doc-table-tab.command.ts b/packages/docs-ui/src/commands/commands/table/doc-table-tab.command.ts similarity index 93% rename from packages/docs/src/commands/commands/table/doc-table-tab.command.ts rename to packages/docs-ui/src/commands/commands/table/doc-table-tab.command.ts index fde716ac2d4..44cdd8857d9 100644 --- a/packages/docs/src/commands/commands/table/doc-table-tab.command.ts +++ b/packages/docs-ui/src/commands/commands/table/doc-table-tab.command.ts @@ -16,7 +16,7 @@ import type { ICommand, Nullable } from '@univerjs/core'; import { CommandType, ICommandService, IUniverInstanceService } from '@univerjs/core'; -import { TextSelectionManagerService } from '../../../services/text-selection-manager.service'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { getCommandSkeleton } from '../../util'; import type { IOffsets } from './table'; import { CellPosition, getCellOffsets, INSERT_ROW_POSITION } from './table'; @@ -31,8 +31,8 @@ export const DocTableTabCommand: ICommand = { type: CommandType.COMMAND, handler: async (accessor, params: IDocTableTabCommandParams) => { const { shift } = params; - const textSelectionManager = accessor.get(TextSelectionManagerService); - const activeTextRange = textSelectionManager.getActiveTextRangeWithStyle(); + const textSelectionManager = accessor.get(DocSelectionManagerService); + const activeTextRange = textSelectionManager.getActiveTextRange(); const commandService = accessor.get(ICommandService); const univerInstanceService = accessor.get(IUniverInstanceService); diff --git a/packages/docs/src/commands/commands/table/table.ts b/packages/docs-ui/src/commands/commands/table/table.ts similarity index 98% rename from packages/docs/src/commands/commands/table/table.ts rename to packages/docs-ui/src/commands/commands/table/table.ts index e59c82853d8..22140c73bf7 100644 --- a/packages/docs/src/commands/commands/table/table.ts +++ b/packages/docs-ui/src/commands/commands/table/table.ts @@ -16,8 +16,7 @@ import type { IParagraph, ISectionBreak, ITable, ITableCell, ITableColumn, ITableRow, Nullable } from '@univerjs/core'; import { DataStreamTreeTokenType, generateRandomId, ObjectRelativeFromH, ObjectRelativeFromV, TableAlignmentType, TableCellHeightRule, TableSizeType, TableTextWrapType, Tools } from '@univerjs/core'; -import type { DataStreamTreeNode, DocumentViewModel, RectRange, TextRange } from '@univerjs/engine-render'; -import type { ITextActiveRange } from '../../../services/text-selection-manager.service'; +import type { DataStreamTreeNode, DocumentViewModel, ITextRangeWithStyle } from '@univerjs/engine-render'; export enum INSERT_ROW_POSITION { ABOVE, @@ -173,7 +172,7 @@ interface IRangeInfo { segmentId: string; } -export function getRangeInfoFromRanges(textRange: Nullable, rectRanges: Readonly>): Nullable { +export function getRangeInfoFromRanges(textRange: Nullable, rectRanges: Readonly>): Nullable { if (!textRange && !rectRanges) { return null; } @@ -702,7 +701,7 @@ export enum CellPosition { } // eslint-disable-next-line complexity, max-lines-per-function -export function getCellOffsets(viewModel: DocumentViewModel, range: ITextActiveRange, position: CellPosition): Nullable { +export function getCellOffsets(viewModel: DocumentViewModel, range: ITextRangeWithStyle, position: CellPosition): Nullable { const { startOffset } = range; let targetTable = null; diff --git a/packages/docs-ui/src/commands/operations/doc-create-table.operation.ts b/packages/docs-ui/src/commands/operations/doc-create-table.operation.ts index 442523e2000..ec58356b138 100644 --- a/packages/docs-ui/src/commands/operations/doc-create-table.operation.ts +++ b/packages/docs-ui/src/commands/operations/doc-create-table.operation.ts @@ -17,8 +17,8 @@ import type { IAccessor, ICommand } from '@univerjs/core'; import { CommandType, ICommandService, LocaleService } from '@univerjs/core'; import { IConfirmService } from '@univerjs/ui'; -import { CreateDocTableCommand } from '@univerjs/docs'; import { COMPONENT_DOC_CREATE_TABLE_CONFIRM } from '../../views/table/create/component-name'; +import { CreateDocTableCommand } from '../commands/table/doc-table-create.command'; const COMPONENT_DOC_CREATE_TABLE_CONFIRM_ID = 'doc.component.create-table-confirm'; diff --git a/packages/docs/src/commands/operations/cursor.operation.ts b/packages/docs-ui/src/commands/operations/doc-cursor.operation.ts similarity index 100% rename from packages/docs/src/commands/operations/cursor.operation.ts rename to packages/docs-ui/src/commands/operations/doc-cursor.operation.ts diff --git a/packages/docs/src/commands/operations/select-all.operation.ts b/packages/docs-ui/src/commands/operations/select-all.operation.ts similarity index 82% rename from packages/docs/src/commands/operations/select-all.operation.ts rename to packages/docs-ui/src/commands/operations/select-all.operation.ts index f796b524b17..d8b75a72650 100644 --- a/packages/docs/src/commands/operations/select-all.operation.ts +++ b/packages/docs-ui/src/commands/operations/select-all.operation.ts @@ -16,8 +16,7 @@ import type { ICommand } from '@univerjs/core'; import { CommandType, IUniverInstanceService } from '@univerjs/core'; - -import { TextSelectionManagerService } from '../../services/text-selection-manager.service'; +import { DocSelectionManagerService } from '@univerjs/docs'; interface ISelectAllOperationParams { } @@ -26,9 +25,9 @@ export const SelectAllOperation: ICommand = { type: CommandType.COMMAND, handler: async (accessor) => { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const activeTextRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeTextRange = docSelectionManagerService.getActiveTextRange(); if (docDataModel == null || activeTextRange == null) { return false; } @@ -46,7 +45,7 @@ export const SelectAllOperation: ICommand = { }, ]; - textSelectionManagerService.replaceTextRanges(textRanges, false); + docSelectionManagerService.replaceTextRanges(textRanges, false); return true; }, }; diff --git a/packages/docs/src/commands/operations/set-doc-zoom-ratio.operation.ts b/packages/docs-ui/src/commands/operations/set-doc-zoom-ratio.operation.ts similarity index 100% rename from packages/docs/src/commands/operations/set-doc-zoom-ratio.operation.ts rename to packages/docs-ui/src/commands/operations/set-doc-zoom-ratio.operation.ts diff --git a/packages/docs/src/commands/util.ts b/packages/docs-ui/src/commands/util.ts similarity index 95% rename from packages/docs/src/commands/util.ts rename to packages/docs-ui/src/commands/util.ts index 55450754598..0d846af5259 100644 --- a/packages/docs/src/commands/util.ts +++ b/packages/docs-ui/src/commands/util.ts @@ -16,7 +16,7 @@ import { IRenderManagerService } from '@univerjs/engine-render'; import type { DocumentDataModel, IAccessor } from '@univerjs/core'; -import { DocSkeletonManagerService } from '../services/doc-skeleton-manager.service'; +import { DocSkeletonManagerService } from '@univerjs/docs'; /** * Get the skeleton of the command's target. diff --git a/packages/docs-ui/src/controllers/app-ui-controller.ts b/packages/docs-ui/src/controllers/app-ui-controller.ts index dd37e8e3851..d83dd7f3ca6 100644 --- a/packages/docs-ui/src/controllers/app-ui-controller.ts +++ b/packages/docs-ui/src/controllers/app-ui-controller.ts @@ -14,9 +14,7 @@ * limitations under the License. */ -import { Inject, Injector, Optional, RxDisposable } from '@univerjs/core'; -import { ILayoutService } from '@univerjs/ui'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { Inject, Injector, RxDisposable } from '@univerjs/core'; import { DocContainerUIController } from './doc-container-ui-controller'; @@ -24,22 +22,9 @@ export class AppUIController extends RxDisposable { private _docContainerController: DocContainerUIController; constructor( - @Inject(Injector) private readonly _injector: Injector, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, - @Optional(ILayoutService) private readonly _layoutService?: ILayoutService + @Inject(Injector) private readonly _injector: Injector ) { super(); - this._docContainerController = this._injector.createInstance(DocContainerUIController); - this._registerContainer(); - } - - private _registerContainer() { - if (this._layoutService) { - this.disposeWithMe( - // the content editable div should be regarded as part of the applications container - this._layoutService.registerContainerElement(this._textSelectionRenderManager.__getEditorContainer()) - ); - } } } diff --git a/packages/docs-ui/src/controllers/doc-auto-format.controller.ts b/packages/docs-ui/src/controllers/doc-auto-format.controller.ts index babbda30128..63b43b92229 100644 --- a/packages/docs-ui/src/controllers/doc-auto-format.controller.ts +++ b/packages/docs-ui/src/controllers/doc-auto-format.controller.ts @@ -15,10 +15,14 @@ */ import { Disposable, Inject, LifecycleStages, OnLifecycle, QuickListTypeMap } from '@univerjs/core'; -import type { ITabCommandParams } from '@univerjs/docs'; -import { AfterSpaceCommand, BreakLineCommand, ChangeListNestingLevelCommand, ChangeListNestingLevelType, DocAutoFormatService, DocTableTabCommand, EnterCommand, ListOperationCommand, QuickListCommand, TabCommand } from '@univerjs/docs'; -import { isInSameTableCell } from '@univerjs/engine-render'; import type { Nullable } from 'vitest'; +import { DocAutoFormatService } from '../services/doc-auto-format.service'; +import type { ITabCommandParams } from '../commands/commands/auto-format.command'; +import { AfterSpaceCommand, EnterCommand, TabCommand } from '../commands/commands/auto-format.command'; +import { ChangeListNestingLevelCommand, ChangeListNestingLevelType, ListOperationCommand, QuickListCommand } from '../commands/commands/list.command'; +import { DocTableTabCommand } from '../commands/commands/table/doc-table-tab.command'; +import { isInSameTableCell } from '../services/selection/convert-rect-range'; +import { BreakLineCommand } from '../commands/commands/break-line.command'; @OnLifecycle(LifecycleStages.Rendered, DocAutoFormatController) export class DocAutoFormatController extends Disposable { diff --git a/packages/docs-ui/src/controllers/doc-header-footer.controller.ts b/packages/docs-ui/src/controllers/doc-header-footer.controller.ts index 5240f835fd1..df2c589be11 100644 --- a/packages/docs-ui/src/controllers/doc-header-footer.controller.ts +++ b/packages/docs-ui/src/controllers/doc-header-footer.controller.ts @@ -17,15 +17,17 @@ import type { DocumentDataModel } from '@univerjs/core'; import { BooleanNumber, Disposable, DocumentFlavor, ICommandService, Inject, IUniverInstanceService, LocaleService, toDisposable, Tools } from '@univerjs/core'; import type { Documents, DocumentViewModel, IMouseEvent, IPageRenderConfig, IPathProps, IPointerEvent, IRenderContext, IRenderModule, RenderComponentType } from '@univerjs/engine-render'; -import { DocumentEditArea, IRenderManagerService, ITextSelectionRenderManager, PageLayoutType, Path, Rect, Vector2 } from '@univerjs/engine-render'; +import { DocumentEditArea, IRenderManagerService, PageLayoutType, Path, Rect, Vector2 } from '@univerjs/engine-render'; import { ComponentManager, IEditorService } from '@univerjs/ui'; -import { DocSkeletonManagerService, neoGetDocObject } from '@univerjs/docs'; +import { DocSkeletonManagerService } from '@univerjs/docs'; import type { Nullable } from 'vitest'; import { TextBubbleShape } from '../views/header-footer/text-bubble'; import { CoreHeaderFooterCommand } from '../commands/commands/doc-header-footer.command'; import { COMPONENT_DOC_HEADER_FOOTER_PANEL } from '../views/header-footer/panel/component-name'; import { DocHeaderFooterPanel } from '../views/header-footer/panel/DocHeaderFooterPanel'; +import { DocSelectionRenderService } from '../services/selection/doc-selection-render.service'; +import { neoGetDocObject } from '../basics/component-tools'; const HEADER_FOOTER_STROKE_COLOR = 'rgba(58, 96, 247, 1)'; const HEADER_FOOTER_FILL_COLOR = 'rgba(58, 96, 247, 0.08)'; @@ -129,7 +131,7 @@ export class DocHeaderFooterController extends Disposable implements IRenderModu @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, @Inject(LocaleService) private readonly _localeService: LocaleService, @Inject(ComponentManager) private readonly _componentManager: ComponentManager ) { @@ -214,15 +216,15 @@ export class DocHeaderFooterController extends Disposable implements IRenderModu const { createType, headerFooterId } = checkCreateHeaderFooterType(viewModel, editArea, pageNumber); if (editArea === DocumentEditArea.BODY) { - this._textSelectionRenderManager.setSegment(''); - this._textSelectionRenderManager.setSegmentPage(-1); - this._textSelectionRenderManager.setCursorManually(offsetX, offsetY); + this._docSelectionRenderService.setSegment(''); + this._docSelectionRenderService.setSegmentPage(-1); + this._docSelectionRenderService.setCursorManually(offsetX, offsetY); } else { if (createType != null) { const SEGMENT_ID_LEN = 6; const segmentId = Tools.generateRandomId(SEGMENT_ID_LEN); - this._textSelectionRenderManager.setSegment(segmentId); - this._textSelectionRenderManager.setSegmentPage(pageNumber); + this._docSelectionRenderService.setSegment(segmentId); + this._docSelectionRenderService.setSegmentPage(pageNumber); await this._commandService.executeCommand(CoreHeaderFooterCommand.id, { unitId, @@ -230,9 +232,9 @@ export class DocHeaderFooterController extends Disposable implements IRenderModu segmentId, }); } else if (headerFooterId != null) { - this._textSelectionRenderManager.setSegment(headerFooterId); - this._textSelectionRenderManager.setSegmentPage(pageNumber); - this._textSelectionRenderManager.setCursorManually(offsetX, offsetY); + this._docSelectionRenderService.setSegment(headerFooterId); + this._docSelectionRenderService.setSegmentPage(pageNumber); + this._docSelectionRenderService.setCursorManually(offsetX, offsetY); } } })); diff --git a/packages/docs/src/controllers/move-cursor.controller.ts b/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts similarity index 96% rename from packages/docs/src/controllers/move-cursor.controller.ts rename to packages/docs-ui/src/controllers/doc-move-cursor.controller.ts index 6e508331c2f..c1ba4655630 100644 --- a/packages/docs/src/controllers/move-cursor.controller.ts +++ b/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts @@ -24,6 +24,7 @@ import { IUniverInstanceService, LifecycleStages, OnLifecycle, + RANGE_DIRECTION, } from '@univerjs/core'; import type { DocumentSkeleton, @@ -35,24 +36,24 @@ import type { INodePosition, INodeSearch, } from '@univerjs/engine-render'; -import { DocumentSkeletonPageType, IRenderManagerService, NodePositionConvertToCursor, RANGE_DIRECTION } from '@univerjs/engine-render'; +import { DocumentSkeletonPageType, IRenderManagerService } from '@univerjs/engine-render'; import type { Subscription } from 'rxjs'; -import { getDocObject } from '../basics/component-tools'; -import type { IMoveCursorOperationParams } from '../commands/operations/cursor.operation'; -import { MoveCursorOperation, MoveSelectionOperation } from '../commands/operations/cursor.operation'; -import { DocSkeletonManagerService } from '../services/doc-skeleton-manager.service'; -import { TextSelectionManagerService } from '../services/text-selection-manager.service'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; +import { NodePositionConvertToCursor } from '../services/selection/convert-text-range'; +import type { IMoveCursorOperationParams } from '../commands/operations/doc-cursor.operation'; +import { MoveCursorOperation, MoveSelectionOperation } from '../commands/operations/doc-cursor.operation'; import { findAboveCell, findBellowCell, findLineBeforeAndAfterTable, findTableAfterLine, findTableBeforeLine, firstLineInCell, firstLineInTable, lastLineInCell, lastLineInTable } from '../basics/table'; +import { getDocObject } from '../basics/component-tools'; -@OnLifecycle(LifecycleStages.Rendered, MoveCursorController) -export class MoveCursorController extends Disposable { +@OnLifecycle(LifecycleStages.Rendered, DocMoveCursorController) +export class DocMoveCursorController extends Disposable { private _onInputSubscription: Nullable; constructor( @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @ICommandService private readonly _commandService: ICommandService ) { super(); @@ -96,7 +97,7 @@ export class MoveCursorController extends Disposable { // eslint-disable-next-line max-lines-per-function, complexity private _handleShiftMoveSelection(direction: Direction) { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._textSelectionManagerService.getActiveTextRange(); const allRanges = this._textSelectionManagerService.getCurrentTextRanges()!; const docDataModel = this._univerInstanceService.getCurrentUniverDocInstance(); if (docDataModel == null) { @@ -209,7 +210,7 @@ export class MoveCursorController extends Disposable { // eslint-disable-next-line max-lines-per-function, complexity private _handleMoveCursor(direction: Direction) { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._textSelectionManagerService.getActiveTextRange(); const allRanges = this._textSelectionManagerService.getCurrentTextRanges(); const docDataModel = this._univerInstanceService.getCurrentUniverDocInstance(); if (docDataModel == null) { diff --git a/packages/docs-ui/src/controllers/doc-ui.controller.ts b/packages/docs-ui/src/controllers/doc-ui.controller.ts index a0d628d0db7..acba681f1c3 100644 --- a/packages/docs-ui/src/controllers/doc-ui.controller.ts +++ b/packages/docs-ui/src/controllers/doc-ui.controller.ts @@ -28,7 +28,7 @@ import { } from '@univerjs/core'; import { BuiltInUIPart, ComponentManager, ILayoutService, IMenuManagerService, IShortcutService, IUIPartsService } from '@univerjs/ui'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; import { TodoList } from '@univerjs/icons'; import { COLOR_PICKER_COMPONENT, ColorPicker } from '../components/color-picker'; import { @@ -57,6 +57,7 @@ import { } from '../shortcuts/toolbar.shortcut'; import { TabShortCut } from '../shortcuts/format.shortcut'; import { BULLET_LIST_TYPE_COMPONENT, BulletListTypePicker, ORDER_LIST_TYPE_COMPONENT, OrderListTypePicker } from '../components/list-type-picker'; +import { DocSelectionRenderService } from '../services/selection/doc-selection-render.service'; import { menuSchema } from './menu.schema'; import type { IUniverDocsUIConfig } from './config.schema'; import { PLUGIN_CONFIG_KEY } from './config.schema'; @@ -92,6 +93,7 @@ export class DocUIController extends Disposable { this.disposeWithMe(componentManager.register('TodoList', TodoList)); } + // TODO: @zhangwei, why add workbook to docs-ui? private _initUiParts() { const workbook = this._univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET); const config = this._configService.getConfig(PLUGIN_CONFIG_KEY); @@ -143,9 +145,11 @@ export class DocUIController extends Disposable { private _initFocusHandler(): void { this.disposeWithMe( - this._layoutService.registerFocusHandler(UniverInstanceType.UNIVER_DOC, () => { - const textSelectionManagerService = this._injector.get(ITextSelectionRenderManager); - textSelectionManagerService.focus(); + this._layoutService.registerFocusHandler(UniverInstanceType.UNIVER_DOC, (unitId: string) => { + const renderManagerService = this._injector.get(IRenderManagerService); + const docSelectionRenderService = renderManagerService.getRenderById(unitId)!.with(DocSelectionRenderService); + + docSelectionRenderService.focus(); }) ); } diff --git a/packages/docs-ui/src/controllers/menu.schema.ts b/packages/docs-ui/src/controllers/menu.schema.ts index 93cfcf7f1a3..bd220d88ed1 100644 --- a/packages/docs-ui/src/controllers/menu.schema.ts +++ b/packages/docs-ui/src/controllers/menu.schema.ts @@ -16,38 +16,35 @@ import type { MenuSchemaType } from '@univerjs/ui'; import { ContextMenuGroup, ContextMenuPosition, RibbonStartGroup } from '@univerjs/ui'; -import { - AlignCenterCommand, - AlignJustifyCommand, - AlignLeftCommand, - AlignRightCommand, - BulletListCommand, - CheckListCommand, - DeleteLeftCommand, - DocTableDeleteColumnsCommand, - DocTableDeleteRowsCommand, - DocTableDeleteTableCommand, - DocTableInsertColumnLeftCommand, - DocTableInsertColumnRightCommand, - DocTableInsertRowAboveCommand, - DocTableInsertRowBellowCommand, - OrderListCommand, - ResetInlineFormatTextBackgroundColorCommand, - SetInlineFormatBoldCommand, - SetInlineFormatFontFamilyCommand, - SetInlineFormatFontSizeCommand, - SetInlineFormatItalicCommand, - SetInlineFormatStrikethroughCommand, - SetInlineFormatSubscriptCommand, - SetInlineFormatSuperscriptCommand, - SetInlineFormatTextBackgroundColorCommand, - SetInlineFormatTextColorCommand, - SetInlineFormatUnderlineCommand, -} from '@univerjs/docs'; import { DocCreateTableOperation } from '../commands/operations/doc-create-table.operation'; import { OpenHeaderFooterPanelCommand } from '../commands/commands/doc-header-footer.command'; import { DocCopyCommand, DocCutCommand, DocPasteCommand } from '../commands/commands/clipboard.command'; import { DocParagraphSettingPanelOperation } from '../commands/operations/doc-paragraph-setting-panel.operation'; +import { ResetInlineFormatTextBackgroundColorCommand, SetInlineFormatBoldCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '../commands/commands/inline-format.command'; + +import { BulletListCommand, CheckListCommand, OrderListCommand } from '../commands/commands/list.command'; +import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignRightCommand } from '../commands/commands/paragraph-align.command'; +import { DeleteLeftCommand } from '../commands/commands/delete.command'; +import { DocTableInsertColumnLeftCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand } from '../commands/commands/table/doc-table-insert.command'; +import { DocTableDeleteColumnsCommand, DocTableDeleteRowsCommand, DocTableDeleteTableCommand } from '../commands/commands/table/doc-table-delete.command'; +import { + CopyMenuFactory, + CutMenuFactory, + DeleteColumnsMenuItemFactory, + DeleteMenuFactory, + DeleteRowsMenuItemFactory, + DeleteTableMenuItemFactory, + InsertColumnLeftMenuItemFactory, + InsertColumnRightMenuItemFactory, + InsertRowAfterMenuItemFactory, + InsertRowBeforeMenuItemFactory, + ParagraphSettingMenuFactory, + PasteMenuFactory, + TABLE_DELETE_MENU_ID, + TABLE_INSERT_MENU_ID, + TableDeleteMenuItemFactory, + TableInsertMenuItemFactory, +} from './menu/context-menu'; import { AlignCenterMenuItemFactory, AlignJustifyMenuItemFactory, @@ -72,24 +69,6 @@ import { TextColorSelectorMenuItemFactory, UnderlineMenuItemFactory, } from './menu/menu'; -import { - CopyMenuFactory, - CutMenuFactory, - DeleteColumnsMenuItemFactory, - DeleteMenuFactory, - DeleteRowsMenuItemFactory, - DeleteTableMenuItemFactory, - InsertColumnLeftMenuItemFactory, - InsertColumnRightMenuItemFactory, - InsertRowAfterMenuItemFactory, - InsertRowBeforeMenuItemFactory, - ParagraphSettingMenuFactory, - PasteMenuFactory, - TABLE_DELETE_MENU_ID, - TABLE_INSERT_MENU_ID, - TableDeleteMenuItemFactory, - TableInsertMenuItemFactory, -} from './menu/context-menu'; export const menuSchema: MenuSchemaType = { [RibbonStartGroup.FORMAT]: { diff --git a/packages/docs-ui/src/controllers/menu/context-menu.ts b/packages/docs-ui/src/controllers/menu/context-menu.ts index 3dd323f5b49..f72ae2d6e37 100644 --- a/packages/docs-ui/src/controllers/menu/context-menu.ts +++ b/packages/docs-ui/src/controllers/menu/context-menu.ts @@ -19,26 +19,19 @@ import { IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; import type { IMenuButtonItem, IMenuSelectorItem } from '@univerjs/ui'; import { getMenuHiddenObservable, MenuItemType } from '@univerjs/ui'; import { combineLatest, Observable } from 'rxjs'; -import { - DeleteLeftCommand, - DocTableDeleteColumnsCommand, - DocTableDeleteRowsCommand, - DocTableDeleteTableCommand, - DocTableInsertColumnLeftCommand, - DocTableInsertColumnRightCommand, - DocTableInsertRowAboveCommand, - DocTableInsertRowBellowCommand, - TextSelectionManagerService, -} from '@univerjs/docs'; -import type { RectRange } from '@univerjs/engine-render'; +import type { IRectRangeWithStyle } from '@univerjs/engine-render'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { DocCopyCommand, DocCutCommand, DocPasteCommand } from '../../commands/commands/clipboard.command'; import { DocParagraphSettingPanelOperation } from '../../commands/operations/doc-paragraph-setting-panel.operation'; +import { DeleteLeftCommand } from '../../commands/commands/delete.command'; +import { DocTableInsertColumnLeftCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand } from '../../commands/commands/table/doc-table-insert.command'; +import { DocTableDeleteColumnsCommand, DocTableDeleteRowsCommand, DocTableDeleteTableCommand } from '../../commands/commands/table/doc-table-delete.command'; const getDisableOnCollapsedObservable = (accessor: IAccessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); return new Observable((subscriber) => { - const observable = textSelectionManagerService.textSelection$.subscribe(() => { - const range = textSelectionManagerService.getActiveTextRangeWithStyle(); + const observable = docSelectionManagerService.textSelection$.subscribe(() => { + const range = docSelectionManagerService.getActiveTextRange(); if (range && !range.collapsed) { subscriber.next(false); } else { @@ -50,7 +43,7 @@ const getDisableOnCollapsedObservable = (accessor: IAccessor) => { }); }; -function inSameTable(rectRanges: Readonly) { +function inSameTable(rectRanges: Readonly) { if (rectRanges.length < 2) { return true; } @@ -60,13 +53,13 @@ function inSameTable(rectRanges: Readonly) { } const getDisableWhenSelectionNotInTableObservable = (accessor: IAccessor) => { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); return new Observable((subscriber) => { - const observable = textSelectionManagerService.textSelection$.subscribe(() => { - const rectRanges = textSelectionManagerService.getCurrentRectRanges(); - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const observable = docSelectionManagerService.textSelection$.subscribe(() => { + const rectRanges = docSelectionManagerService.getCurrentRectRanges(); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (rectRanges && rectRanges.length && inSameTable(rectRanges)) { subscriber.next(false); return; diff --git a/packages/docs-ui/src/controllers/menu/menu.ts b/packages/docs-ui/src/controllers/menu/menu.ts index f5def0b0c02..879eeee28c6 100644 --- a/packages/docs-ui/src/controllers/menu/menu.ts +++ b/packages/docs-ui/src/controllers/menu/menu.ts @@ -24,31 +24,10 @@ import { UniverInstanceType, } from '@univerjs/core'; import { - AlignCenterCommand, - AlignJustifyCommand, - AlignLeftCommand, - AlignOperationCommand, - AlignRightCommand, - BulletListCommand, - CheckListCommand, + DocSelectionManagerService, DocSkeletonManagerService, - getCommandSkeleton, - getParagraphsInRange, - OrderListCommand, - ResetInlineFormatTextBackgroundColorCommand, - SetInlineFormatBoldCommand, - SetInlineFormatCommand, - SetInlineFormatFontFamilyCommand, - SetInlineFormatFontSizeCommand, - SetInlineFormatItalicCommand, - SetInlineFormatStrikethroughCommand, - SetInlineFormatSubscriptCommand, - SetInlineFormatSuperscriptCommand, - SetInlineFormatTextBackgroundColorCommand, - SetInlineFormatTextColorCommand, - SetInlineFormatUnderlineCommand, SetTextSelectionsOperation, - TextSelectionManagerService } from '@univerjs/docs'; +} from '@univerjs/docs'; import type { IMenuButtonItem, IMenuItem, IMenuSelectorItem } from '@univerjs/ui'; import { FONT_FAMILY_LIST, @@ -68,6 +47,10 @@ import { FONT_SIZE_COMPONENT } from '../../components/font-size'; import { OpenHeaderFooterPanelCommand } from '../../commands/commands/doc-header-footer.command'; import { BULLET_LIST_TYPE_COMPONENT, ORDER_LIST_TYPE_COMPONENT } from '../../components/list-type-picker'; import { DocCreateTableOperation } from '../../commands/operations/doc-create-table.operation'; +import { getCommandSkeleton } from '../../commands/util'; +import { ResetInlineFormatTextBackgroundColorCommand, SetInlineFormatBoldCommand, SetInlineFormatCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '../../commands/commands/inline-format.command'; +import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignOperationCommand, AlignRightCommand } from '../../commands/commands/paragraph-align.command'; +import { BulletListCommand, CheckListCommand, getParagraphsInRange, OrderListCommand } from '../../commands/commands/list.command'; function getInsertTableHiddenObservable( accessor: IAccessor @@ -112,11 +95,11 @@ function getInsertTableHiddenObservable( } function getTableDisabledObservable(accessor: IAccessor): Observable { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); const univerInstanceService = accessor.get(IUniverInstanceService); return new Observable((subscriber) => { - const subscription = textSelectionManagerService.textSelection$.subscribe((selection) => { + const subscription = docSelectionManagerService.textSelection$.subscribe((selection) => { if (selection == null) { subscriber.next(true); return; @@ -130,7 +113,7 @@ function getTableDisabledObservable(accessor: IAccessor): Observable { } const textRange = textRanges[0]; - const { collapsed, anchorNodePosition, startOffset } = textRange; + const { collapsed, startNodePosition, startOffset } = textRange; if (!collapsed || startOffset == null) { subscriber.next(true); @@ -161,8 +144,8 @@ function getTableDisabledObservable(accessor: IAccessor): Observable { return; } - if (anchorNodePosition != null) { - const { path } = anchorNodePosition; + if (startNodePosition != null) { + const { path } = startNodePosition; // TODO: Not support insert table in table cell now. if (path.indexOf('cells') !== -1) { @@ -179,10 +162,10 @@ function getTableDisabledObservable(accessor: IAccessor): Observable { } function disableMenuWhenNoDocRange(accessor: IAccessor): Observable { - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); return new Observable((subscriber) => { - const subscription = textSelectionManagerService.textSelection$.subscribe((selection) => { + const subscription = docSelectionManagerService.textSelection$.subscribe((selection) => { if (selection == null) { subscriber.next(true); return; @@ -718,7 +701,7 @@ export function AlignJustifyMenuItemFactory(accessor: IAccessor): IMenuButtonIte const listValueFactory$ = (accessor: IAccessor) => { return new Observable((subscriber) => { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); + const docSelectionManagerService = accessor.get(DocSelectionManagerService); let textSubscription: Subscription | undefined; const subscription = univerInstanceService.focused$.subscribe((unitId) => { textSubscription?.unsubscribe(); @@ -731,8 +714,8 @@ const listValueFactory$ = (accessor: IAccessor) => { return; } - textSubscription = textSelectionManagerService.textSelection$.subscribe(() => { - const range = textSelectionManagerService.getActiveTextRangeWithStyle(); + textSubscription = docSelectionManagerService.textSelection$.subscribe(() => { + const range = docSelectionManagerService.getActiveTextRange(); if (range) { const doc = docDataModel.getSelfOrHeaderFooterModel(range?.segmentId); const paragraphs = getParagraphsInRange(range, doc.getBody()?.paragraphs ?? []); @@ -858,9 +841,9 @@ export function BackgroundColorSelectorMenuItemFactory(accessor: IAccessor): IMe function getFontStyleAtCursor(accessor: IAccessor) { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const activeTextRange = textSelectionService.getActiveTextRangeWithStyle(); + const activeTextRange = textSelectionService.getActiveTextRange(); if (docDataModel == null || activeTextRange == null) { return; @@ -890,9 +873,9 @@ function getFontStyleAtCursor(accessor: IAccessor) { function getParagraphStyleAtCursor(accessor: IAccessor) { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const docDataModel = univerInstanceService.getCurrentUniverDocInstance(); - const activeTextRange = textSelectionService.getActiveTextRangeWithStyle(); + const activeTextRange = textSelectionService.getActiveTextRange(); if (docDataModel == null || activeTextRange == null) { return; diff --git a/packages/docs-ui/src/controllers/render-controllers/back-scroll.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/back-scroll.render-controller.ts index 6ad9609eff0..c6b5263f681 100644 --- a/packages/docs-ui/src/controllers/render-controllers/back-scroll.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/back-scroll.render-controller.ts @@ -16,18 +16,22 @@ import type { DocumentDataModel, ITextRange, Nullable } from '@univerjs/core'; import { Inject, IUniverInstanceService, RxDisposable } from '@univerjs/core'; -import { DocSkeletonManagerService, getDocObject, TextSelectionManagerService, VIEWPORT_KEY } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import type { INodePosition, IRenderContext, IRenderModule } from '@univerjs/engine-render'; -import { getAnchorBounding, IRenderManagerService, NodePositionConvertToCursor } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; import { takeUntil } from 'rxjs'; +import { NodePositionConvertToCursor } from '../../services/selection/convert-text-range'; +import { getAnchorBounding } from '../../services/selection/text-range'; +import { VIEWPORT_KEY } from '../../basics/docs-view-key'; +import { getDocObject } from '../../basics/component-tools'; const ANCHOR_WIDTH = 1.5; export class DocBackScrollRenderController extends RxDisposable implements IRenderModule { constructor( private readonly _context: IRenderContext, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @IEditorService private readonly _editorService: IEditorService, @Inject(IUniverInstanceService) private readonly _univerInstanceService: IUniverInstanceService, @IRenderManagerService private readonly _renderManagerService: IRenderManagerService @@ -123,7 +127,7 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend // Let the selection show on the current screen. private _scrollToSelection(unitId: string) { - const activeTextRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeTextRange = this._textSelectionManagerService.getActiveTextRange(); if (activeTextRange == null) { return; } diff --git a/packages/docs-ui/src/controllers/render-controllers/doc-checklist.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-checklist.render-controller.ts index 0a1f29d0245..0dd14e910f3 100644 --- a/packages/docs-ui/src/controllers/render-controllers/doc-checklist.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-checklist.render-controller.ts @@ -18,8 +18,9 @@ import type { Documents, IRenderContext, IRenderModule, Viewport } from '@univer import { CURSOR_TYPE, Vector2 } from '@univerjs/engine-render'; import type { DocumentDataModel } from '@univerjs/core'; import { Disposable, ICommandService, Inject } from '@univerjs/core'; -import { DocSkeletonManagerService, TextSelectionManagerService, ToggleCheckListCommand } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import { DocEventManagerService } from '../../services/doc-event-manager.service'; +import { ToggleCheckListCommand } from '../../commands/commands/list.command'; export class DocChecklistRenderController extends Disposable implements IRenderModule { constructor( @@ -27,7 +28,7 @@ export class DocChecklistRenderController extends Disposable implements IRenderM @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, @ICommandService private readonly _commandService: ICommandService, @Inject(DocEventManagerService) private readonly _docEventManagerService: DocEventManagerService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); diff --git a/packages/docs-ui/src/controllers/clipboard.controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-clipboard.controller.ts similarity index 63% rename from packages/docs-ui/src/controllers/clipboard.controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-clipboard.controller.ts index 908fcc69cd4..537f500cc90 100644 --- a/packages/docs-ui/src/controllers/clipboard.controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-clipboard.controller.ts @@ -14,28 +14,26 @@ * limitations under the License. */ +import type { DocumentDataModel } from '@univerjs/core'; import { ICommandService, IContextService, - LifecycleStages, - OnLifecycle, + Inject, RxDisposable, } from '@univerjs/core'; -import { IClipboardInterfaceService } from '@univerjs/ui'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { takeUntil } from 'rxjs'; -import { CutContentCommand, InnerPasteCommand } from '@univerjs/docs'; -import { DocCopyCommand, DocCutCommand, DocPasteCommand, whenDocOrEditor, whenFocusEditor } from '../commands/commands/clipboard.command'; -import { IDocClipboardService } from '../services/clipboard/clipboard.service'; +import { whenDocOrEditor, whenFocusEditor } from '../../commands/commands/clipboard.command'; +import { IDocClipboardService } from '../../services/clipboard/clipboard.service'; +import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service'; -@OnLifecycle(LifecycleStages.Rendered, DocClipboardController) -export class DocClipboardController extends RxDisposable { +export class DocClipboardController extends RxDisposable implements IRenderModule { constructor( + private readonly _context: IRenderContext, @ICommandService private readonly _commandService: ICommandService, - @IClipboardInterfaceService private readonly _clipboardInterfaceService: IClipboardInterfaceService, @IDocClipboardService private readonly _docClipboardService: IDocClipboardService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, @IContextService private readonly _contextService: IContextService ) { super(); @@ -44,14 +42,11 @@ export class DocClipboardController extends RxDisposable { } private _init() { - [DocCopyCommand, DocCutCommand, DocPasteCommand].forEach((command) => this.disposeWithMe(this._commandService.registerMultipleCommand(command))); - [InnerPasteCommand, CutContentCommand].forEach((command) => this.disposeWithMe(this._commandService.registerCommand(command))); - this._initLegacyPasteCommand(); } private _initLegacyPasteCommand(): void { - this._textSelectionRenderManager?.onPaste$.pipe(takeUntil(this.dispose$)).subscribe((config) => { + this._docSelectionRenderService?.onPaste$.pipe(takeUntil(this.dispose$)).subscribe((config) => { if (!whenDocOrEditor(this._contextService)) { return; } diff --git a/packages/docs-ui/src/controllers/render-controllers/contextmenu.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-contextmenu.render-controller.ts similarity index 92% rename from packages/docs-ui/src/controllers/render-controllers/contextmenu.render-controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-contextmenu.render-controller.ts index 8e0d9d0540c..7970e19345f 100644 --- a/packages/docs-ui/src/controllers/render-controllers/contextmenu.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-contextmenu.render-controller.ts @@ -22,9 +22,8 @@ import { DOCS_NORMAL_EDITOR_UNIT_ID_KEY, DOCS_ZEN_EDITOR_UNIT_ID_KEY, ICommandService, - Inject, } from '@univerjs/core'; -import { RichTextEditingMutation, TextSelectionManagerService } from '@univerjs/docs'; +import { RichTextEditingMutation } from '@univerjs/docs'; import type { Documents, IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { ContextMenuPosition, IContextMenuService } from '@univerjs/ui'; @@ -43,7 +42,6 @@ export class DocContextMenuRenderController extends Disposable implements IRende constructor( private readonly _context: IRenderContext, @IContextMenuService private readonly _contextMenuService: IContextMenuService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, @ICommandService private readonly _commandService: ICommandService ) { super(); diff --git a/packages/docs-ui/src/controllers/doc-editor-bridge.controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts similarity index 77% rename from packages/docs-ui/src/controllers/doc-editor-bridge.controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts index bb0a4e29c9e..0dfa2d45dfa 100644 --- a/packages/docs-ui/src/controllers/doc-editor-bridge.controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts @@ -14,23 +14,28 @@ * limitations under the License. */ -import type { ICommandInfo, Nullable, Workbook } from '@univerjs/core'; -import { checkForSubstrings, Disposable, ICommandService, IUniverInstanceService, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; -import { IRenderManagerService, ITextSelectionRenderManager, ScrollBar } from '@univerjs/engine-render'; +import type { DocumentDataModel, ICommandInfo, Nullable, Workbook } from '@univerjs/core'; +import { checkForSubstrings, Disposable, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; +import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; +import { IRenderManagerService, ScrollBar } from '@univerjs/engine-render'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { CoverContentCommand, DocSkeletonManagerService, RichTextEditingMutation, VIEWPORT_KEY } from '@univerjs/docs'; +import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; import { IEditorService, SetEditorResizeOperation } from '@univerjs/ui'; import { fromEvent } from 'rxjs'; +import { VIEWPORT_KEY } from '../../basics/docs-view-key'; +import { CoverContentCommand } from '../../commands/commands/replace-content.command'; +import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service'; -@OnLifecycle(LifecycleStages.Rendered, DocEditorBridgeController) -export class DocEditorBridgeController extends Disposable { +export class DocEditorBridgeController extends Disposable implements IRenderModule { private _initialEditors = new Set(); constructor( + private readonly _context: IRenderContext, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @IEditorService private readonly _editorService: IEditorService, @ICommandService private readonly _commandService: ICommandService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, + @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, @IRenderManagerService private readonly _renderManagerService: IRenderManagerService ) { super(); @@ -40,12 +45,21 @@ export class DocEditorBridgeController extends Disposable { private _initialize() { this.disposeWithMe( this._editorService.resize$.subscribe((unitId: string) => { + if (unitId !== this._context.unitId) { + return; + } + this._resize(unitId); }) ); this._editorService.getAllEditor().forEach((editor) => { const unitId = editor.editorUnitId; + + if (unitId !== this._context.unitId) { + return; + } + if (this._initialEditors.has(unitId)) { return; } @@ -64,6 +78,7 @@ export class DocEditorBridgeController extends Disposable { this._initialValueChange(); } + // eslint-disable-next-line complexity private _resize(unitId: Nullable) { if (unitId == null) { return; @@ -80,8 +95,7 @@ export class DocEditorBridgeController extends Disposable { return; } - const skeleton = this._renderManagerService.getRenderById(editorDataModel.getUnitId()) - ?.with(DocSkeletonManagerService).getSkeleton(); + const skeleton = this._docSkeletonManagerService.getSkeleton(); if (editor == null || editor.render == null || skeleton == null || editorDataModel == null) { return; } @@ -145,6 +159,10 @@ export class DocEditorBridgeController extends Disposable { private _initialSetValue() { this.disposeWithMe( this._editorService.setValue$.subscribe((param) => { + if (param.editorUnitId !== this._context.unitId) { + return; + } + this._commandService.executeCommand(CoverContentCommand.id, { unitId: param.editorUnitId, body: param.body, @@ -157,18 +175,15 @@ export class DocEditorBridgeController extends Disposable { private _initialBlur() { this.disposeWithMe( this._editorService.blur$.subscribe(() => { - this._textSelectionRenderManager.removeAllRanges(); + this._docSelectionRenderService.removeAllRanges(); - this._textSelectionRenderManager.blur(); + this._docSelectionRenderService.blur(); }) ); this.disposeWithMe( - this._textSelectionRenderManager.onBlur$.subscribe(() => { - const unitId = this._univerInstanceService.getCurrentUniverDocInstance()?.getUnitId(); - if (unitId == null) { - return; - } + this._docSelectionRenderService.onBlur$.subscribe(() => { + const { unitId } = this._context; const editor = this._editorService.getEditor(unitId); @@ -186,8 +201,12 @@ export class DocEditorBridgeController extends Disposable { private _initialFocus() { this.disposeWithMe( this._editorService.focus$.subscribe((textRange) => { - this._textSelectionRenderManager.removeAllRanges(); - this._textSelectionRenderManager.addDocRanges([textRange]); + if (this._editorService.getFocusEditor()?.editorUnitId !== this._context.unitId) { + return; + } + + this._docSelectionRenderService.removeAllRanges(); + this._docSelectionRenderService.addDocRanges([textRange]); }) ); @@ -235,24 +254,21 @@ export class DocEditorBridgeController extends Disposable { private _initialValueChange() { this.disposeWithMe( - this._textSelectionRenderManager.onCompositionupdate$.subscribe(this._valueChange.bind(this)) + this._docSelectionRenderService.onCompositionupdate$.subscribe(this._valueChange.bind(this)) ); this.disposeWithMe( - this._textSelectionRenderManager.onInput$.subscribe(this._valueChange.bind(this)) + this._docSelectionRenderService.onInput$.subscribe(this._valueChange.bind(this)) ); this.disposeWithMe( - this._textSelectionRenderManager.onKeydown$.subscribe(this._valueChange.bind(this)) + this._docSelectionRenderService.onKeydown$.subscribe(this._valueChange.bind(this)) ); this.disposeWithMe( - this._textSelectionRenderManager.onPaste$.subscribe(this._valueChange.bind(this)) + this._docSelectionRenderService.onPaste$.subscribe(this._valueChange.bind(this)) ); } private _valueChange() { - const unitId = this._univerInstanceService.getCurrentUniverDocInstance()?.getUnitId(); - if (unitId == null) { - return; - } + const { unitId } = this._context; const editor = this._editorService.getEditor(unitId); @@ -275,7 +291,7 @@ export class DocEditorBridgeController extends Disposable { const params = command.params as IRichTextEditingMutationParams; const { unitId } = params; - if (this._editorService.isSheetEditor(unitId)) { + if (this._editorService.isSheetEditor(unitId) || unitId !== this._context.unitId) { return; } diff --git a/packages/docs/src/controllers/ime-input.controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-ime-input.controller.ts similarity index 69% rename from packages/docs/src/controllers/ime-input.controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-ime-input.controller.ts index 558cab87d1a..2281de03a73 100644 --- a/packages/docs/src/controllers/ime-input.controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-ime-input.controller.ts @@ -14,27 +14,25 @@ * limitations under the License. */ -import type { Nullable } from '@univerjs/core'; +import type { DocumentDataModel, Nullable } from '@univerjs/core'; import { Disposable, ICommandService, Inject, IUniverInstanceService, - LifecycleStages, - OnLifecycle, Tools, } from '@univerjs/core'; -import type { IEditorInputConfig } from '@univerjs/engine-render'; -import { IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; import type { Subscription } from 'rxjs'; -import { IMEInputCommand } from '../commands/commands/ime-input.command'; -import { DocSkeletonManagerService } from '../services/doc-skeleton-manager.service'; -import { IMEInputManagerService } from '../services/ime-input-manager.service'; -import { TextSelectionManagerService } from '../services/text-selection-manager.service'; +import { DocSkeletonManagerService } from '@univerjs/docs'; +import { IMEInputCommand } from '../../commands/commands/ime-input.command'; +import { DocIMEInputManagerService } from '../../services/doc-ime-input-manager.service'; +import type { IEditorInputConfig } from '../../services/selection/doc-selection-render.service'; +import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service'; -@OnLifecycle(LifecycleStages.Rendered, IMEInputController) -export class IMEInputController extends Disposable { +export class DocIMEInputController extends Disposable implements IRenderModule { private _previousIMEContent: string = ''; private _isCompositionStart: boolean = true; @@ -46,11 +44,11 @@ export class IMEInputController extends Disposable { private _onEndSubscription: Nullable; constructor( + private readonly _context: IRenderContext, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @IRenderManagerService private readonly _renderManagerSrv: IRenderManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, - @Inject(IMEInputManagerService) private readonly _imeInputManagerService: IMEInputManagerService, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, + @Inject(DocIMEInputManagerService) private readonly _docImeInputManagerService: DocIMEInputManagerService, @ICommandService private readonly _commandService: ICommandService ) { super(); @@ -73,7 +71,7 @@ export class IMEInputController extends Disposable { } private _initialOnCompositionstart() { - this._onStartSubscription = this._textSelectionRenderManager.onCompositionstart$.subscribe((config) => { + this._onStartSubscription = this._docSelectionRenderService.onCompositionstart$.subscribe((config) => { if (config == null) { return; } @@ -86,18 +84,18 @@ export class IMEInputController extends Disposable { return; } - this._imeInputManagerService.setActiveRange(Tools.deepClone(activeRange)); + this._docImeInputManagerService.setActiveRange(Tools.deepClone(activeRange)); }); } private _initialOnCompositionUpdate() { - this._onUpdateSubscription = this._textSelectionRenderManager.onCompositionupdate$.subscribe(async (config) => { + this._onUpdateSubscription = this._docSelectionRenderService.onCompositionupdate$.subscribe((config) => { this._updateContent(config, true); }); } private _initialOnCompositionend() { - this._onEndSubscription = this._textSelectionRenderManager.onCompositionend$.subscribe((config) => { + this._onEndSubscription = this._docSelectionRenderService.onCompositionend$.subscribe((config) => { this._updateContent(config, false); }); } @@ -153,8 +151,8 @@ export class IMEInputController extends Disposable { this._isCompositionStart = true; - this._imeInputManagerService.clearUndoRedoMutationParamsCache(); + this._docImeInputManagerService.clearUndoRedoMutationParamsCache(); - this._imeInputManagerService.setActiveRange(null); + this._docImeInputManagerService.setActiveRange(null); } } diff --git a/packages/docs/src/controllers/normal-input.controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-input.controller.ts similarity index 57% rename from packages/docs/src/controllers/normal-input.controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-input.controller.ts index b35641c0c1b..e93967d4c50 100644 --- a/packages/docs/src/controllers/normal-input.controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-input.controller.ts @@ -14,23 +14,22 @@ * limitations under the License. */ -import type { Nullable } from '@univerjs/core'; -import { Disposable, ICommandService, IUniverInstanceService, LifecycleStages, OnLifecycle } from '@univerjs/core'; -import { IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import type { DocumentDataModel, Nullable } from '@univerjs/core'; +import { Disposable, ICommandService, Inject } from '@univerjs/core'; +import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; import type { Subscription } from 'rxjs'; +import { DocSkeletonManagerService } from '@univerjs/docs'; +import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service'; +import { InsertCommand } from '../../commands/commands/core-editing.command'; +import { AfterSpaceCommand } from '../../commands/commands/auto-format.command'; -import { InsertCommand } from '../commands/commands/core-editing.command'; -import { DocSkeletonManagerService } from '../services/doc-skeleton-manager.service'; -import { AfterSpaceCommand } from '../commands/commands/auto-format.command'; - -@OnLifecycle(LifecycleStages.Rendered, NormalInputController) -export class NormalInputController extends Disposable { +export class DocInputController extends Disposable implements IRenderModule { private _onInputSubscription: Nullable; constructor( - @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, - @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + private readonly _context: IRenderContext, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, + @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, @ICommandService private readonly _commandService: ICommandService ) { super(); @@ -49,24 +48,18 @@ export class NormalInputController extends Disposable { } private _initialNormalInput() { - this._onInputSubscription = this._textSelectionRenderManager.onInput$.subscribe(async (config) => { + this._onInputSubscription = this._docSelectionRenderService.onInput$.subscribe(async (config) => { if (config == null) { return; } - const documentModel = this._univerInstanceService.getCurrentUniverDocInstance(); - if (!documentModel) { - return; - } - - const unitId = documentModel.getUnitId(); + const unitId = this._context.unitId; const { event, content = '', activeRange } = config; const e = event as InputEvent; - const skeleton = this._renderManagerService.getRenderById(documentModel.getUnitId()) - ?.with(DocSkeletonManagerService).getSkeleton(); + const skeleton = this._docSkeletonManagerService.getSkeleton(); if (e.data == null || skeleton == null) { return; diff --git a/packages/docs-ui/src/controllers/render-controllers/doc-resize.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-resize.render-controller.ts index ea684b1dc5d..57139c5c04c 100644 --- a/packages/docs-ui/src/controllers/render-controllers/doc-resize.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-resize.render-controller.ts @@ -18,14 +18,14 @@ import { Disposable, DOCS_ZEN_EDITOR_UNIT_ID_KEY, fromEventSubject, Inject, isIn import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render'; import { animationFrameScheduler, filter, throttleTime } from 'rxjs'; -import { TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { DocPageLayoutService } from '../../services/doc-page-layout.service'; export class DocResizeRenderController extends Disposable implements IRenderModule { constructor( private _context: IRenderContext, @Inject(DocPageLayoutService) private readonly _docPageLayoutService: DocPageLayoutService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); diff --git a/packages/docs-ui/src/controllers/render-controllers/text-selection.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-selection-render.controller.ts similarity index 75% rename from packages/docs-ui/src/controllers/render-controllers/text-selection.render-controller.ts rename to packages/docs-ui/src/controllers/render-controllers/doc-selection-render.controller.ts index fb2c3f42e60..7c908b84caf 100644 --- a/packages/docs-ui/src/controllers/render-controllers/text-selection.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-selection-render.controller.ts @@ -16,12 +16,15 @@ import type { DocumentDataModel, ICommandInfo } from '@univerjs/core'; import { Disposable, ICommandService, Inject, isInternalEditorID, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import type { Documents, IMouseEvent, IPointerEvent, IRenderContext, IRenderModule, RenderComponentType } from '@univerjs/engine-render'; -import { CURSOR_TYPE, DocumentEditArea, ITextSelectionRenderManager, PageLayoutType, Vector2 } from '@univerjs/engine-render'; +import type { IMouseEvent, IPointerEvent, IRenderContext, IRenderModule, RenderComponentType } from '@univerjs/engine-render'; +import { CURSOR_TYPE, DocumentEditArea, PageLayoutType, Vector2 } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; -import type { ISetDocZoomRatioOperationParams } from '@univerjs/docs'; -import { DocSkeletonManagerService, neoGetDocObject, SetDocZoomRatioOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; +import { DocSelectionRenderService } from '../../services/selection/doc-selection-render.service'; +import { neoGetDocObject } from '../../basics/component-tools'; +import type { ISetDocZoomRatioOperationParams } from '../../commands/operations/set-doc-zoom-ratio.operation'; +import { SetDocZoomRatioOperation } from '../../commands/operations/set-doc-zoom-ratio.operation'; export class DocTextSelectionRenderController extends Disposable implements IRenderModule { private _loadedMap = new WeakSet(); @@ -31,9 +34,9 @@ export class DocTextSelectionRenderController extends Disposable implements IRen @ICommandService private readonly _commandService: ICommandService, @IEditorService private readonly _editorService: IEditorService, @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, + @Inject(DocSelectionRenderService) private readonly _docSelectionRenderService: DocSelectionRenderService, @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _docSelectionManagerService: DocSelectionManagerService ) { super(); @@ -44,6 +47,8 @@ export class DocTextSelectionRenderController extends Disposable implements IRen this._init(); this._skeletonListener(); this._commandExecutedListener(); + this._refreshListener(); + this._syncSelection(); } private _init() { @@ -59,6 +64,40 @@ export class DocTextSelectionRenderController extends Disposable implements IRen } } + private _refreshListener() { + this.disposeWithMe( + this._docSelectionManagerService.refreshSelection$.subscribe((params) => { + if (params == null) { + return; + } + + const { unitId, docRanges, isEditing, options } = params; + + if (unitId !== this._context.unitId) { + return; + } + + this._docSelectionRenderService.removeAllRanges(); + if (docRanges.length) { + this._docSelectionRenderService.addDocRanges(docRanges, isEditing, options); + } + }) + ); + } + + private _syncSelection() { + this.disposeWithMe( + this._docSelectionRenderService.textSelectionInner$ + .subscribe((params) => { + if (params == null) { + return; + } + + this._docSelectionManagerService.replaceTextRangesWithNoRefresh(params); + }) + ); + } + // eslint-disable-next-line max-lines-per-function private _initialMain(unitId: string) { const docObject = neoGetDocObject(this._context); @@ -111,7 +150,7 @@ export class DocTextSelectionRenderController extends Disposable implements IRen } } - this._textSelectionRenderManager.onPointDown(evt); + this._docSelectionRenderService.onPointDown(evt); if (this._editorService.getEditor(unitId)) { /** @@ -127,7 +166,7 @@ export class DocTextSelectionRenderController extends Disposable implements IRen setTimeout(() => { this._setEditorFocus(unitId); - this._textSelectionRenderManager.setCursorManually(offsetX, offsetY); + this._docSelectionRenderService.setCursorManually(offsetX, offsetY); }, 0); } @@ -141,7 +180,7 @@ export class DocTextSelectionRenderController extends Disposable implements IRen return; } - this._textSelectionRenderManager.handleDblClick(evt); + this._docSelectionRenderService.handleDblClick(evt); })); this.disposeWithMe(document.onTripleClick$.subscribeEvent((evt: IPointerEvent | IMouseEvent) => { @@ -149,7 +188,7 @@ export class DocTextSelectionRenderController extends Disposable implements IRen return; } - this._textSelectionRenderManager.handleTripleClick(evt); + this._docSelectionRenderService.handleTripleClick(evt); })); } @@ -200,13 +239,13 @@ export class DocTextSelectionRenderController extends Disposable implements IRen const params = command.params as ISetDocZoomRatioOperationParams; const { unitId: documentId } = params; - const unitId = this._textSelectionManagerService.getCurrentSelection()?.unitId; + const unitId = this._docSelectionManagerService.getCurrentSelection()?.unitId; if (documentId !== unitId) { return; } - this._textSelectionManagerService.refreshSelection(); + this._docSelectionManagerService.refreshSelection(); } }) ); @@ -219,21 +258,21 @@ export class DocTextSelectionRenderController extends Disposable implements IRen this.disposeWithMe(this._docSkeletonManagerService.currentSkeleton$.subscribe((skeleton) => { if (!skeleton) return; - const { scene, mainComponent, unitId } = this._context; + const { unitId } = this._context; const isInternalEditor = isInternalEditorID(unitId); if (init || !isInternalEditorID(this._context.unitId)) { - this._textSelectionRenderManager.changeRuntime(skeleton, scene, mainComponent as Documents); - this._textSelectionManagerService.setCurrentSelectionNotRefresh({ + this._docSelectionRenderService.attachScrollEvent(); + this._docSelectionManagerService.setCurrentSelectionNotRefresh({ unitId, - subUnitId: '', + subUnitId: unitId, }); // The initial cursor is set at the beginning of the document, // and can be set to the previous cursor position in the future. // The skeleton of the editor has not been calculated at this moment, and it is determined whether it is an editor by its ID. if (!isInternalEditor) { - this._textSelectionManagerService.replaceTextRanges([ + this._docSelectionManagerService.replaceTextRanges([ { startOffset: 0, endOffset: 0, diff --git a/packages/docs-ui/src/controllers/render-controllers/doc.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc.render-controller.ts index 7b1e890b0c2..c72af43d369 100644 --- a/packages/docs-ui/src/controllers/render-controllers/doc.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc.render-controller.ts @@ -17,11 +17,12 @@ import type { DocumentDataModel, EventState, ICommandInfo, Nullable } from '@univerjs/core'; import { FOCUSING_DOC, ICommandService, IConfigService, IContextService, Inject, RxDisposable } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { DOCS_COMPONENT_BACKGROUND_LAYER_INDEX, DOCS_COMPONENT_DEFAULT_Z_INDEX, DOCS_COMPONENT_HEADER_LAYER_INDEX, DOCS_COMPONENT_MAIN_LAYER_INDEX, DOCS_VIEW_KEY, DocSkeletonManagerService, RichTextEditingMutation, VIEWPORT_KEY } from '@univerjs/docs'; +import { DocSkeletonManagerService, RichTextEditingMutation } from '@univerjs/docs'; import type { DocumentSkeleton, IRenderContext, IRenderModule, IWheelEvent } from '@univerjs/engine-render'; import { DocBackground, Documents, IRenderManagerService, Layer, PageLayoutType, ScrollBar, Viewport } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; import { takeUntil } from 'rxjs'; +import { DOCS_COMPONENT_BACKGROUND_LAYER_INDEX, DOCS_COMPONENT_DEFAULT_Z_INDEX, DOCS_COMPONENT_HEADER_LAYER_INDEX, DOCS_COMPONENT_MAIN_LAYER_INDEX, DOCS_VIEW_KEY, VIEWPORT_KEY } from '../../basics/docs-view-key'; export class DocRenderController extends RxDisposable implements IRenderModule { constructor( diff --git a/packages/docs-ui/src/controllers/render-controllers/zoom.render-controller.ts b/packages/docs-ui/src/controllers/render-controllers/zoom.render-controller.ts index c3fef154752..0231c0879f3 100644 --- a/packages/docs-ui/src/controllers/render-controllers/zoom.render-controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/zoom.render-controller.ts @@ -23,11 +23,15 @@ import { Inject, IUniverInstanceService, } from '@univerjs/core'; -import type { ISetDocZoomRatioOperationParams } from '@univerjs/docs'; -import { DocSkeletonManagerService, neoGetDocObject, SetDocZoomRatioCommand, SetDocZoomRatioOperation, TextSelectionManagerService } from '@univerjs/docs'; + +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import type { IRenderContext, IRenderModule, IWheelEvent } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; import { DocPageLayoutService } from '../../services/doc-page-layout.service'; +import { SetDocZoomRatioCommand } from '../../commands/commands/set-doc-zoom-ratio.command'; +import type { ISetDocZoomRatioOperationParams } from '../../commands/operations/set-doc-zoom-ratio.operation'; +import { SetDocZoomRatioOperation } from '../../commands/operations/set-doc-zoom-ratio.operation'; +import { neoGetDocObject } from '../../basics/component-tools'; export class DocZoomRenderController extends Disposable implements IRenderModule { constructor( @@ -36,7 +40,7 @@ export class DocZoomRenderController extends Disposable implements IRenderModule @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @ICommandService private readonly _commandService: ICommandService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @IEditorService private readonly _editorService: IEditorService, @Inject(DocPageLayoutService) private readonly _docPageLayoutService: DocPageLayoutService ) { diff --git a/packages/docs-ui/src/docs-ui-plugin.ts b/packages/docs-ui/src/docs-ui-plugin.ts index fe05f2f0486..903a063583d 100644 --- a/packages/docs-ui/src/docs-ui-plugin.ts +++ b/packages/docs-ui/src/docs-ui-plugin.ts @@ -14,17 +14,16 @@ * limitations under the License. */ -import type { - Dependency } from '@univerjs/core'; +import type { Dependency } from '@univerjs/core'; import { ICommandService, - IConfigService, ILogService, Inject, Injector, IUniverInstanceService, mergeOverrideWithDependencies, - Plugin, UniverInstanceType } from '@univerjs/core'; + Plugin, UniverInstanceType, +} from '@univerjs/core'; import { IEditorService, IShortcutService } from '@univerjs/ui'; import { IRenderManagerService } from '@univerjs/engine-render'; import { DocInterceptorService, DocSkeletonManagerService } from '@univerjs/docs'; @@ -44,16 +43,16 @@ import { AppUIController } from './controllers'; import { DocUIController } from './controllers/doc-ui.controller'; import { BreakLineShortcut, DeleteLeftShortcut, DeleteRightShortcut } from './shortcuts/core-editing.shortcut'; import { DocClipboardService, IDocClipboardService } from './services/clipboard/clipboard.service'; -import { DocClipboardController } from './controllers/clipboard.controller'; -import { DocEditorBridgeController } from './controllers/doc-editor-bridge.controller'; +import { DocClipboardController } from './controllers/render-controllers/doc-clipboard.controller'; +import { DocEditorBridgeController } from './controllers/render-controllers/doc-editor-bridge.controller'; import { DocRenderController } from './controllers/render-controllers/doc.render-controller'; import { DocZoomRenderController } from './controllers/render-controllers/zoom.render-controller'; -import { DocTextSelectionRenderController } from './controllers/render-controllers/text-selection.render-controller'; +import { DocTextSelectionRenderController } from './controllers/render-controllers/doc-selection-render.controller'; import { DocBackScrollRenderController } from './controllers/render-controllers/back-scroll.render-controller'; import { DocCanvasPopManagerService } from './services/doc-popup-manager.service'; import { DocsRenderService } from './services/docs-render.service'; import { DocHeaderFooterController } from './controllers/doc-header-footer.controller'; -import { DocContextMenuRenderController } from './controllers/render-controllers/contextmenu.render-controller'; +import { DocContextMenuRenderController } from './controllers/render-controllers/doc-contextmenu.render-controller'; import { DocPageLayoutService } from './services/doc-page-layout.service'; import { DocResizeRenderController } from './controllers/render-controllers/doc-resize.render-controller'; import { DocEventManagerService } from './services/doc-event-manager.service'; @@ -61,12 +60,37 @@ import { DocAutoFormatController } from './controllers/doc-auto-format.controlle import { ShiftTabShortCut } from './shortcuts/format.shortcut'; import { DocChecklistRenderController } from './controllers/render-controllers/doc-checklist.render-controller'; import { DocParagraphSettingController } from './controllers/doc-paragraph-setting.controller'; - import { DocParagraphSettingPanelOperation } from './commands/operations/doc-paragraph-setting-panel.operation'; import { DocParagraphSettingCommand } from './commands/commands/doc-paragraph-setting.command'; import { DocTableController } from './controllers/doc-table.controller'; import type { IUniverDocsUIConfig } from './controllers/config.schema'; import { defaultPluginConfig, PLUGIN_CONFIG_KEY } from './controllers/config.schema'; +import { DocSelectionRenderService } from './services/selection/doc-selection-render.service'; +import { DocIMEInputManagerService } from './services/doc-ime-input-manager.service'; +import { IMEInputCommand } from './commands/commands/ime-input.command'; +import { DocIMEInputController } from './controllers/render-controllers/doc-ime-input.controller'; +import { DocMoveCursorController } from './controllers/doc-move-cursor.controller'; +import { MoveCursorOperation, MoveSelectionOperation } from './commands/operations/doc-cursor.operation'; +import { DocCopyCommand, DocCutCommand, DocPasteCommand } from './commands/commands/clipboard.command'; +import { DeleteCustomBlockCommand, DeleteLeftCommand, DeleteRightCommand, MergeTwoParagraphCommand } from './commands/commands/delete.command'; +import { ResetInlineFormatTextBackgroundColorCommand, SetInlineFormatBoldCommand, SetInlineFormatCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatTextBackgroundColorCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from './commands/commands/inline-format.command'; +import { BreakLineCommand } from './commands/commands/break-line.command'; +import { DeleteCommand, InsertCommand, UpdateCommand } from './commands/commands/core-editing.command'; +import { SetDocZoomRatioOperation } from './commands/operations/set-doc-zoom-ratio.operation'; +import { BulletListCommand, ChangeListNestingLevelCommand, ChangeListTypeCommand, CheckListCommand, ListOperationCommand, OrderListCommand, QuickListCommand, ToggleCheckListCommand } from './commands/commands/list.command'; +import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignOperationCommand, AlignRightCommand } from './commands/commands/paragraph-align.command'; +import { CreateDocTableCommand } from './commands/commands/table/doc-table-create.command'; +import { DocTableInsertColumnCommand, DocTableInsertColumnLeftCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand, DocTableInsertRowCommand } from './commands/commands/table/doc-table-insert.command'; +import { DocTableDeleteColumnsCommand, DocTableDeleteRowsCommand, DocTableDeleteTableCommand } from './commands/commands/table/doc-table-delete.command'; +import { DocTableTabCommand } from './commands/commands/table/doc-table-tab.command'; +import { AfterSpaceCommand, EnterCommand, TabCommand } from './commands/commands/auto-format.command'; +import { CutContentCommand, InnerPasteCommand } from './commands/commands/clipboard.inner.command'; +import { CoverContentCommand, ReplaceContentCommand } from './commands/commands/replace-content.command'; +import { SetDocZoomRatioCommand } from './commands/commands/set-doc-zoom-ratio.command'; +import { SelectAllOperation } from './commands/operations/select-all.operation'; +import { DocAutoFormatService } from './services/doc-auto-format.service'; +import { DocStateChangeManagerService } from './services/doc-state-change-manager.service'; +import { DocInputController } from './controllers/render-controllers/doc-input.controller'; export class UniverDocsUIPlugin extends Plugin { static override pluginName = DOC_UI_PLUGIN_NAME; @@ -105,9 +129,71 @@ export class UniverDocsUIPlugin extends Plugin { } private _initCommand() { - [DocParagraphSettingCommand, DocParagraphSettingPanelOperation].forEach((e) => { + [ + DeleteLeftCommand, + DeleteRightCommand, + SetInlineFormatBoldCommand, + SetInlineFormatItalicCommand, + SetInlineFormatUnderlineCommand, + SetInlineFormatStrikethroughCommand, + SetInlineFormatSubscriptCommand, + SetInlineFormatSuperscriptCommand, + SetInlineFormatFontSizeCommand, + SetInlineFormatFontFamilyCommand, + SetInlineFormatTextColorCommand, + ResetInlineFormatTextBackgroundColorCommand, + SetInlineFormatTextBackgroundColorCommand, + SetInlineFormatCommand, + BreakLineCommand, + InsertCommand, + DeleteCommand, + DeleteCustomBlockCommand, + UpdateCommand, + MergeTwoParagraphCommand, + SetDocZoomRatioOperation, + OrderListCommand, + BulletListCommand, + ListOperationCommand, + AlignLeftCommand, + AlignCenterCommand, + AlignRightCommand, + AlignOperationCommand, + AlignJustifyCommand, + CreateDocTableCommand, + DocTableInsertRowCommand, + DocTableInsertRowAboveCommand, + DocTableInsertRowBellowCommand, + DocTableInsertColumnCommand, + DocTableInsertColumnLeftCommand, + DocTableInsertColumnRightCommand, + DocTableDeleteRowsCommand, + DocTableDeleteColumnsCommand, + DocTableDeleteTableCommand, + DocTableTabCommand, + TabCommand, + AfterSpaceCommand, + EnterCommand, + ChangeListNestingLevelCommand, + ChangeListTypeCommand, + CheckListCommand, + ToggleCheckListCommand, + QuickListCommand, + IMEInputCommand, + DocParagraphSettingCommand, + InnerPasteCommand, + CutContentCommand, + ReplaceContentCommand, + CoverContentCommand, + SetDocZoomRatioCommand, + SelectAllOperation, + DocParagraphSettingPanelOperation, + MoveCursorOperation, + MoveSelectionOperation, + ].forEach((e) => { this._commandService.registerCommand(e); }); + + [DocCopyCommand, DocCutCommand, DocPasteCommand].forEach((command) => this.disposeWithMe(this._commandService.registerMultipleCommand(command))); } private _initializeShortcut(): void { @@ -125,8 +211,6 @@ export class UniverDocsUIPlugin extends Plugin { DeleteRightShortcut, BreakLineShortcut, ShiftTabShortCut, - // TabShortcut, - // ShiftTabShortcut, ].forEach((shortcut) => { this._injector.get(IShortcutService).registerShortcut(shortcut); }); @@ -134,17 +218,22 @@ export class UniverDocsUIPlugin extends Plugin { private _initDependencies(injector: Injector) { const dependencies: Dependency[] = [ - [DocUIController], [DocClipboardController], [DocEditorBridgeController], + // Controller + [DocUIController], [DocAutoFormatController], - [DocTableController], - [DocsRenderService], + [DocMoveCursorController], [AppUIController], + [DocParagraphSettingController], + + // Services [IDocClipboardService, { useClass: DocClipboardService }], [DocCanvasPopManagerService], - [DocParagraphSettingController], + [DocsRenderService], + [DocStateChangeManagerService], + [DocAutoFormatService], ]; const dependency = mergeOverrideWithDependencies(dependencies, this._config.override); @@ -174,9 +263,13 @@ export class UniverDocsUIPlugin extends Plugin { private _initRenderBasics(): void { ([ + // Services. [DocSkeletonManagerService], + [DocSelectionRenderService], [DocInterceptorService], [DocPageLayoutService], + [DocIMEInputManagerService], + // Controllers. [DocRenderController], [DocZoomRenderController], ] as Dependency[]).forEach((m) => { @@ -186,13 +279,19 @@ export class UniverDocsUIPlugin extends Plugin { private _initRenderModules(): void { ([ + // Services [DocEventManagerService], + // Controllers. [DocBackScrollRenderController], [DocTextSelectionRenderController], [DocHeaderFooterController], [DocResizeRenderController], [DocContextMenuRenderController], [DocChecklistRenderController], + [DocClipboardController], + [DocInputController], + [DocIMEInputController], + [DocEditorBridgeController], ] as Dependency[]).forEach((m) => { this._renderManagerSrv.registerRenderModule(UniverInstanceType.UNIVER_DOC, m); }); diff --git a/packages/docs-ui/src/index.ts b/packages/docs-ui/src/index.ts index 2b24f91fc70..5d2f4fb2810 100644 --- a/packages/docs-ui/src/index.ts +++ b/packages/docs-ui/src/index.ts @@ -14,6 +14,18 @@ * limitations under the License. */ +export { getCustomRangesInterestsWithRange } from './basics/custom-range'; +export { makeSelection, getSelectionText, getDeleteSelection, getInsertSelection } from './basics/selection'; +export { hasParagraphInTable } from './basics/paragraph'; +export { replaceSelectionFactory } from './basics/replace'; +export type { IDocObjectParam } from './basics/component-tools'; +export { getDocObject, neoGetDocObject, getDocObjectById } from './basics/component-tools'; +export { getRichTextEditPath, getCommandSkeleton } from './commands/util'; +export { addCustomRangeFactory, addCustomRangeBySelectionFactory, deleteCustomRangeFactory } from './basics/custom-range-factory'; +export { addCustomDecorationBySelectionFactory, addCustomDecorationFactory, deleteCustomDecorationFactory } from './basics/custom-decoration-factory'; +export { getRetainAndDeleteFromReplace } from './basics/retain-delete-params'; +export { getPlainTextFormDocument, getPlainTextFormBody } from './basics/plain-text'; +export * from './basics/docs-view-key'; export { whenDocAndEditorFocused } from './shortcuts/utils'; export { IDocClipboardService } from './services/clipboard/clipboard.service'; export { DocBackScrollRenderController } from './controllers/render-controllers/back-scroll.render-controller'; @@ -30,6 +42,89 @@ export { DocUIController } from './controllers/doc-ui.controller'; export { menuSchema } from './controllers/menu.schema'; // #region - all commands +export { RectRange, convertPositionsToRectRanges } from './services/selection/rect-range'; +export { getCanvasOffsetByEngine } from './services/selection/selection-utils'; +export type { IEditorInputConfig } from './services/selection/doc-selection-render.service'; +export { getAnchorBounding, TEXT_RANGE_LAYER_INDEX, TextRange, getLineBounding } from './services/selection/text-range'; +export { NodePositionConvertToCursor } from './services/selection/convert-text-range'; +export { getOneTextSelectionRange } from './services/selection/convert-text-range'; +export type { IDocRange } from './services/selection/range-interface'; +export { isInSameTableCell, isValidRectRange, NodePositionConvertToRectRange } from './services/selection/convert-rect-range'; + +export { DocSelectionRenderService } from './services/selection/doc-selection-render.service'; +export { DocStateChangeManagerService } from './services/doc-state-change-manager.service'; +export { DocIMEInputManagerService } from './services/doc-ime-input-manager.service'; + +export { getParagraphsInRange, getParagraphsInRanges } from './commands/commands/list.command'; +export { BreakLineCommand } from './commands/commands/break-line.command'; +export { CutContentCommand, InnerPasteCommand } from './commands/commands/clipboard.inner.command'; +export { + InsertCommand, + DeleteCommand, + UpdateCommand, + EditorInsertTextCommandId, + type ICoverCommandParams, + type IDeleteCommandParams, + type IInsertCommandParams, + type IUpdateCommandParams, +} from './commands/commands/core-editing.command'; +export { DeleteLeftCommand, DeleteRightCommand, DeleteCustomBlockCommand, MergeTwoParagraphCommand, type IDeleteCustomBlockParams } from './commands/commands/delete.command'; +export { + SetInlineFormatBoldCommand, + SetInlineFormatItalicCommand, + SetInlineFormatUnderlineCommand, + SetInlineFormatStrikethroughCommand, + SetInlineFormatSubscriptCommand, + SetInlineFormatSuperscriptCommand, + SetInlineFormatFontSizeCommand, + SetInlineFormatFontFamilyCommand, + SetInlineFormatTextColorCommand, + SetInlineFormatTextBackgroundColorCommand, + ResetInlineFormatTextBackgroundColorCommand, + SetInlineFormatCommand, +} from './commands/commands/inline-format.command'; +export { + ListOperationCommand, + BulletListCommand, + OrderListCommand, + ChangeListNestingLevelCommand, + ChangeListTypeCommand, + CheckListCommand, + ToggleCheckListCommand, + QuickListCommand, +} from './commands/commands/list.command'; +export { + AlignOperationCommand, + AlignLeftCommand, + AlignCenterCommand, + AlignRightCommand, + AlignJustifyCommand, +} from './commands/commands/paragraph-align.command'; +export { IMEInputCommand } from './commands/commands/ime-input.command'; +export { ReplaceContentCommand, CoverContentCommand } from './commands/commands/replace-content.command'; +export { SetDocZoomRatioCommand } from './commands/commands/set-doc-zoom-ratio.command'; +export { AfterSpaceCommand, TabCommand, EnterCommand, type ITabCommandParams } from './commands/commands/auto-format.command'; +export { SetDocZoomRatioOperation, type ISetDocZoomRatioOperationParams } from './commands/operations/set-doc-zoom-ratio.operation'; +export { MoveSelectionOperation } from './commands/operations/doc-cursor.operation'; + +// #endregion +export { DocAutoFormatService } from '../../docs-ui/src/services/doc-auto-format.service'; +export { ChangeListNestingLevelType } from './commands/commands/list.command'; +export { generateParagraphs } from './commands/commands/break-line.command'; +export type { IInnerCutCommandParams } from './commands/commands/clipboard.inner.command'; +export { getCutActionsFromDocRanges, getCustomBlockIdsInSelections } from './commands/commands/clipboard.inner.command'; +export { CreateDocTableCommand, type ICreateDocTableCommandParams } from './commands/commands/table/doc-table-create.command'; +export { DocTableDeleteRowsCommand, DocTableDeleteColumnsCommand, DocTableDeleteTableCommand } from './commands/commands/table/doc-table-delete.command'; +export type { IDocTableDeleteRowsCommandParams, IDocTableDeleteColumnsCommandParams, IDocTableDeleteTableCommandParams } from './commands/commands/table/doc-table-delete.command'; +export type { IDocTableInsertColumnCommandParams, IDocTableInsertRowCommandParams, IDocTableInsertColumnRightCommandParams, IDocTableInsertRowAboveCommandParams, IDocTableInsertRowBellowCommandParams, IDocTableInsertColumnLeftCommandParams } from './commands/commands/table/doc-table-insert.command'; +export { DocTableInsertColumnCommand, DocTableInsertRowCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand, DocTableInsertColumnLeftCommand } from './commands/commands/table/doc-table-insert.command'; +export type { IDocTableTabCommandParams } from './commands/commands/table/doc-table-tab.command'; +export { DocTableTabCommand } from './commands/commands/table/doc-table-tab.command'; + +export { genTableSource, getEmptyTableRow, getEmptyTableCell, getTableColumn } from './commands/commands/table/table'; +export { getCursorWhenDelete } from './commands/commands/delete.command'; export { DocCopyCommand, DocCutCommand, DocPasteCommand } from './commands/commands/clipboard.command'; export { DocCreateTableOperation } from './commands/operations/doc-create-table.operation'; +export { SelectAllOperation } from './commands/operations/select-all.operation'; +export { MoveCursorOperation } from './commands/operations/doc-cursor.operation'; // #endregion diff --git a/packages/docs-ui/src/services/clipboard/clipboard.service.ts b/packages/docs-ui/src/services/clipboard/clipboard.service.ts index 5489e5a4c22..03a72534c94 100644 --- a/packages/docs-ui/src/services/clipboard/clipboard.service.ts +++ b/packages/docs-ui/src/services/clipboard/clipboard.service.ts @@ -15,12 +15,15 @@ */ import type { ICustomRange, IDisposable, IDocumentBody, IDocumentData, IParagraph, Nullable } from '@univerjs/core'; -import { createIdentifier, CustomRangeType, DataStreamTreeTokenType, Disposable, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, generateRandomId, getBodySlice, ICommandService, ILogService, Inject, IUniverInstanceService, normalizeBody, SliceBodyType, toDisposable, Tools, UniverInstanceType } from '@univerjs/core'; +import { createIdentifier, CustomRangeType, DataStreamTreeTokenType, Disposable, DOC_RANGE_TYPE, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, generateRandomId, getBodySlice, ICommandService, ILogService, Inject, IUniverInstanceService, normalizeBody, SliceBodyType, toDisposable, Tools, UniverInstanceType } from '@univerjs/core'; import { HTML_CLIPBOARD_MIME_TYPE, IClipboardInterfaceService, PLAIN_TEXT_CLIPBOARD_MIME_TYPE } from '@univerjs/ui'; -import { copyCustomRange, CutContentCommand, getCursorWhenDelete, getDeleteSelection, InnerPasteCommand, TextSelectionManagerService } from '@univerjs/docs'; -import type { RectRange, TextRange } from '@univerjs/engine-render'; -import { DOC_RANGE_TYPE } from '@univerjs/engine-render'; +import type { IRectRangeWithStyle, ITextRangeWithStyle } from '@univerjs/engine-render'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import { getCursorWhenDelete } from '../../commands/commands/delete.command'; +import { CutContentCommand, InnerPasteCommand } from '../../commands/commands/clipboard.inner.command'; +import { getDeleteSelection } from '../../basics/selection'; +import { copyCustomRange } from '../../basics/custom-range'; import { copyContentCache, extractId, genId } from './copy-content-cache'; import { HtmlToUDMService } from './html-to-udm/converter'; import PastePluginLark from './html-to-udm/paste-plugins/plugin-lark'; @@ -93,7 +96,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ @ILogService private readonly _logService: ILogService, @ICommandService private readonly _commandService: ICommandService, @IClipboardInterfaceService private readonly _clipboardInterfaceService: IClipboardInterfaceService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _docSelectionManagerService: DocSelectionManagerService ) { super(); } @@ -106,7 +109,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ } try { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); const isCopyInHeaderFooter = !!activeRange?.segmentId; this._setClipboardData(bodyList, snapshot, !isCopyInHeaderFooter && needCache); @@ -149,9 +152,9 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ segmentId, endOffset: activeEndOffset, style, - } = this._textSelectionManagerService.getActiveTextRangeWithStyle() ?? {}; - const textRanges = this._textSelectionManagerService.getCurrentTextRanges() ?? []; - const rectRanges = this._textSelectionManagerService.getCurrentRectRanges() ?? []; + } = this._docSelectionManagerService.getActiveTextRange() ?? {}; + const textRanges = this._docSelectionManagerService.getCurrentTextRanges() ?? []; + const rectRanges = this._docSelectionManagerService.getCurrentRectRanges() ?? []; if (segmentId == null) { this._logService.error('[DocClipboardController] segmentId is not existed'); @@ -168,7 +171,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ let cursor = 0; if (rectRanges.length > 0) { - cursor = getCursorWhenDelete(textRanges as Readonly, rectRanges); + cursor = getCursorWhenDelete(textRanges as Readonly, rectRanges); } else if (activeEndOffset != null) { cursor = activeEndOffset; for (const range of textRanges) { @@ -223,9 +226,9 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ // copy custom ranges body.customRanges = body.customRanges?.map(copyCustomRange); - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); const { segmentId, endOffset: activeEndOffset, style } = activeRange || {}; - const ranges = this._textSelectionManagerService.getCurrentTextRanges(); + const ranges = this._docSelectionManagerService.getCurrentTextRanges(); if (segmentId == null) { this._logService.error('[DocClipboardController] segmentId does not exist!'); @@ -330,7 +333,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ snapshot: IDocumentData; }> { const docDataModel = this._univerInstanceService.getCurrentUniverDocInstance(); - const allRanges = this._textSelectionManagerService.getDocRanges(); + const allRanges = this._docSelectionManagerService.getDocRanges(); const results: IDocumentBody[] = []; let needCache = true; @@ -359,7 +362,7 @@ export class DocClipboardService extends Disposable implements IDocClipboardServ if (rangeType === DOC_RANGE_TYPE.RECT) { needCache = false; - const { spanEntireRow } = range as unknown as RectRange; + const { spanEntireRow } = range as IRectRangeWithStyle; let bodySlice: IDocumentBody; if (!spanEntireRow) { bodySlice = getTableSlice(body, startOffset, endOffset); diff --git a/packages/docs-ui/src/services/clipboard/html-to-udm/converter.ts b/packages/docs-ui/src/services/clipboard/html-to-udm/converter.ts index 9d69df8ce31..fc56219b036 100644 --- a/packages/docs-ui/src/services/clipboard/html-to-udm/converter.ts +++ b/packages/docs-ui/src/services/clipboard/html-to-udm/converter.ts @@ -17,7 +17,7 @@ import type { IDocumentBody, IDocumentData, ITable, ITextStyle, Nullable } from '@univerjs/core'; import { CustomRangeType, DataStreamTreeTokenType, generateRandomId, skipParseTagNames, Tools } from '@univerjs/core'; -import { genTableSource, getEmptyTableCell, getEmptyTableRow, getTableColumn } from '@univerjs/docs'; +import { genTableSource, getEmptyTableCell, getEmptyTableRow, getTableColumn } from '../../../commands/commands/table/table'; import { extractNodeStyle } from './parse-node-style'; import parseToDom from './parse-to-dom'; import type { IAfterProcessRule, IPastePlugin, IStyleRule } from './paste-plugins/type'; diff --git a/packages/docs/src/services/doc-auto-format.service.ts b/packages/docs-ui/src/services/doc-auto-format.service.ts similarity index 93% rename from packages/docs/src/services/doc-auto-format.service.ts rename to packages/docs-ui/src/services/doc-auto-format.service.ts index b71aec492a9..74574d3eb27 100644 --- a/packages/docs/src/services/doc-auto-format.service.ts +++ b/packages/docs-ui/src/services/doc-auto-format.service.ts @@ -16,13 +16,13 @@ import type { DocumentDataModel, ICommandInfo, ICustomRange, IDisposable, IParagraph, IParagraphRange, ITextRange, Nullable } from '@univerjs/core'; import { Disposable, Inject, IUniverInstanceService, toDisposable, UniverInstanceType } from '@univerjs/core'; +import { DocSelectionManagerService } from '@univerjs/docs'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; import { getCustomRangesInterestsWithRange } from '../basics/custom-range'; -import type { ITextActiveRange } from './text-selection-manager.service'; -import { TextSelectionManagerService } from './text-selection-manager.service'; export interface IAutoFormatContext { unit: DocumentDataModel; - selection: ITextActiveRange; + selection: ITextRangeWithStyle; /** * is selection at doc body */ @@ -85,7 +85,7 @@ export class DocAutoFormatService extends Disposable { private _matches: Map = new Map(); constructor( @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); } @@ -113,7 +113,7 @@ export class DocAutoFormatService extends Disposable { onAutoFormat(id: string, params: Nullable): ICommandInfo[] { const autoFormats = this._matches.get(id) ?? []; const unit = this._univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_DOC); - const selection = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const selection = this._textSelectionManagerService.getActiveTextRange(); if (unit && selection) { const doc = unit.getSelfOrHeaderFooterModel(selection.segmentId); diff --git a/packages/docs-ui/src/services/doc-event-manager.service.ts b/packages/docs-ui/src/services/doc-event-manager.service.ts index 479eb730373..23f86c875ec 100644 --- a/packages/docs-ui/src/services/doc-event-manager.service.ts +++ b/packages/docs-ui/src/services/doc-event-manager.service.ts @@ -18,9 +18,11 @@ import type { DocumentDataModel, ICustomRange, IParagraph, ITextRangeParam, Null import { Disposable, fromEventSubject, Inject } from '@univerjs/core'; import { DocSkeletonManagerService } from '@univerjs/docs'; import type { Documents, DocumentSkeleton, IBoundRectNoAngle, IDocumentSkeletonGlyph, IMouseEvent, IPointerEvent, IRenderContext, IRenderModule } from '@univerjs/engine-render'; -import { CURSOR_TYPE, getLineBounding, NodePositionConvertToCursor, TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render'; +import { CURSOR_TYPE, TRANSFORM_CHANGE_OBSERVABLE_TYPE } from '@univerjs/engine-render'; import { distinctUntilChanged, filter, map, mergeMap, Subject, take, throttleTime } from 'rxjs'; import { transformOffset2Bound } from './doc-popup-manager.service'; +import { NodePositionConvertToCursor } from './selection/convert-text-range'; +import { getLineBounding } from './selection/text-range'; interface ICustomRangeBound { customRange: ICustomRange; diff --git a/packages/docs/src/services/ime-input-manager.service.ts b/packages/docs-ui/src/services/doc-ime-input-manager.service.ts similarity index 85% rename from packages/docs/src/services/ime-input-manager.service.ts rename to packages/docs-ui/src/services/doc-ime-input-manager.service.ts index 5d98a8d05a6..0da3d58ef52 100644 --- a/packages/docs/src/services/ime-input-manager.service.ts +++ b/packages/docs-ui/src/services/doc-ime-input-manager.service.ts @@ -14,11 +14,10 @@ * limitations under the License. */ -import { JSONX } from '@univerjs/core'; -import type { IDisposable, JSONXActions, Nullable } from '@univerjs/core'; -import type { ITextRangeWithStyle } from '@univerjs/engine-render'; - -import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation'; +import { JSONX, RxDisposable } from '@univerjs/core'; +import type { DocumentDataModel, JSONXActions, Nullable } from '@univerjs/core'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; +import type { IRenderContext, IRenderModule, ITextRangeWithStyle } from '@univerjs/engine-render'; interface ICacheParams { undoCache: IRichTextEditingMutationParams[]; @@ -27,11 +26,19 @@ interface ICacheParams { // Used to record all intermediate states when typing with IME, // and then output the entire undo and redo operations. -export class IMEInputManagerService implements IDisposable { +export class DocIMEInputManagerService extends RxDisposable implements IRenderModule { private _previousActiveRange: Nullable = null; + private _undoMutationParamsCache: IRichTextEditingMutationParams[] = []; + private _redoMutationParamsCache: IRichTextEditingMutationParams[] = []; + constructor( + private readonly _context: IRenderContext + ) { + super(); + } + clearUndoRedoMutationParamsCache() { this._undoMutationParamsCache = []; this._redoMutationParamsCache = []; @@ -88,9 +95,10 @@ export class IMEInputManagerService implements IDisposable { return { redoMutationParams, undoMutationParams, previousActiveRange: this._previousActiveRange }; } - dispose(): void { + override dispose(): void { this._undoMutationParamsCache = []; this._redoMutationParamsCache = []; + this._previousActiveRange = null; } } diff --git a/packages/docs-ui/src/services/doc-page-layout.service.ts b/packages/docs-ui/src/services/doc-page-layout.service.ts index 5f3daa930d0..15ac11a06c9 100644 --- a/packages/docs-ui/src/services/doc-page-layout.service.ts +++ b/packages/docs-ui/src/services/doc-page-layout.service.ts @@ -16,8 +16,9 @@ import type { DocumentDataModel } from '@univerjs/core'; import { Disposable } from '@univerjs/core'; -import { neoGetDocObject, VIEWPORT_KEY } from '@univerjs/docs'; import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; +import { neoGetDocObject } from '../basics/component-tools'; +import { VIEWPORT_KEY } from '../basics/docs-view-key'; export class DocPageLayoutService extends Disposable implements IRenderModule { constructor( diff --git a/packages/docs-ui/src/services/doc-popup-manager.service.ts b/packages/docs-ui/src/services/doc-popup-manager.service.ts index 9432fe1650f..cfd70d47410 100644 --- a/packages/docs-ui/src/services/doc-popup-manager.service.ts +++ b/packages/docs-ui/src/services/doc-popup-manager.service.ts @@ -16,12 +16,16 @@ import type { IDisposable, ITextRangeParam } from '@univerjs/core'; import { Disposable, DisposableCollection, ICommandService, Inject, IUniverInstanceService } from '@univerjs/core'; -import { getLineBounding, IRenderManagerService, NodePositionConvertToCursor, pxToNum } from '@univerjs/engine-render'; +import { IRenderManagerService, pxToNum } from '@univerjs/engine-render'; import type { BaseObject, Documents, IBoundRectNoAngle, IRender, Scene } from '@univerjs/engine-render'; import type { IPopup } from '@univerjs/ui'; import { ICanvasPopupService } from '@univerjs/ui'; import { BehaviorSubject, map } from 'rxjs'; -import { DocSkeletonManagerService, SetDocZoomRatioOperation, VIEWPORT_KEY } from '@univerjs/docs'; +import { DocSkeletonManagerService } from '@univerjs/docs'; +import { VIEWPORT_KEY } from '../basics/docs-view-key'; +import { SetDocZoomRatioOperation } from '../commands/operations/set-doc-zoom-ratio.operation'; +import { NodePositionConvertToCursor } from './selection/convert-text-range'; +import { getLineBounding } from './selection/text-range'; export function transformBound2OffsetBound(originBound: IBoundRectNoAngle, scene: Scene): IBoundRectNoAngle { const topLeft = transformPosition2Offset(originBound.left, originBound.top, scene); diff --git a/packages/docs/src/services/doc-state-change-manager.service.ts b/packages/docs-ui/src/services/doc-state-change-manager.service.ts similarity index 77% rename from packages/docs/src/services/doc-state-change-manager.service.ts rename to packages/docs-ui/src/services/doc-state-change-manager.service.ts index 36fecdb519b..239c098db06 100644 --- a/packages/docs/src/services/doc-state-change-manager.service.ts +++ b/packages/docs-ui/src/services/doc-state-change-manager.service.ts @@ -15,34 +15,20 @@ */ import type { JSONXActions, Nullable } from '@univerjs/core'; -import { ICommandService, Inject, IUndoRedoService, IUniverInstanceService, JSONX, RedoCommandId, RxDisposable, UndoCommandId } from '@univerjs/core'; -import type { ITextRangeWithStyle } from '@univerjs/engine-render'; -import { BehaviorSubject } from 'rxjs'; -import type { IRichTextEditingMutationParams } from '../commands/mutations/core-editing.mutation'; - -interface IDocChangeState { - actions: JSONXActions; - textRanges: Nullable; -} +import { ICommandService, Inject, IUndoRedoService, IUniverInstanceService, JSONX, LifecycleStages, OnLifecycle, RedoCommandId, RxDisposable, UndoCommandId } from '@univerjs/core'; +import { DocStateEmitService, type IDocStateChangeParams, type IRichTextEditingMutationParams } from '@univerjs/docs'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { BehaviorSubject, takeUntil } from 'rxjs'; +import { DocIMEInputManagerService } from './doc-ime-input-manager.service'; type ChangeStateCacheType = 'history' | 'collaboration'; -export interface IDocStateChangeParams { - commandId: string; - unitId: string; - trigger: Nullable; - redoState: IDocChangeState; - undoState: IDocChangeState; - segmentId?: string; - noHistory?: boolean; - debounce?: boolean; -} - const DEBOUNCE_DELAY = 300; // This class sends out state-changing events, what is the state, the data model, // and the cursor & selection, and this class mainly serves the History(undo/redo) module and // the collaboration module. +@OnLifecycle(LifecycleStages.Ready, DocStateChangeManagerService) export class DocStateChangeManagerService extends RxDisposable { private readonly _docStateChange$ = new BehaviorSubject>(null); readonly docStateChange$ = this._docStateChange$.asObservable(); @@ -56,14 +42,17 @@ export class DocStateChangeManagerService extends RxDisposable { constructor( @Inject(IUndoRedoService) private _undoRedoService: IUndoRedoService, @ICommandService private readonly _commandService: ICommandService, - @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService + @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, + @Inject(DocStateEmitService) private readonly _docStateEmitService: DocStateEmitService, + @IRenderManagerService private readonly _renderManagerService: IRenderManagerService ) { super(); this._initialize(); + this._listenDocStateChange(); } - setChangeState(changeState: IDocStateChangeParams) { + private _setChangeState(changeState: IDocStateChangeParams) { this._cacheChangeState(changeState, 'history'); // Mutations by user or historyService need collaboration. this._cacheChangeState(changeState, 'collaboration'); @@ -87,6 +76,37 @@ export class DocStateChangeManagerService extends RxDisposable { ); } + private _listenDocStateChange() { + this._docStateEmitService.docStateChangeParams$.pipe(takeUntil(this.dispose$)).subscribe((changeStateInfo) => { + if (changeStateInfo == null) { + return; + } + + const { isCompositionEnd, ...changeState } = changeStateInfo; + const imeInputManagerService = this._renderManagerService.getRenderById(changeStateInfo.unitId)?.with(DocIMEInputManagerService); + + if (imeInputManagerService == null) { + return; + } + + // Handle IME input. + if (isCompositionEnd) { + const historyParams = imeInputManagerService.fetchComposedUndoRedoMutationParams(); + + if (historyParams == null) { + throw new Error('historyParams is null in RichTextEditingMutation'); + } + + const { undoMutationParams, redoMutationParams, previousActiveRange } = historyParams; + changeState.redoState.actions = redoMutationParams.actions; + changeState.undoState.actions = undoMutationParams.actions; + changeState.undoState.textRanges = [previousActiveRange]; + } + + this._setChangeState(changeState); + }); + } + private _cacheChangeState(changeState: IDocStateChangeParams, type: ChangeStateCacheType = 'history') { const { trigger, unitId, noHistory, debounce = false } = changeState; diff --git a/packages/engine-render/src/components/docs/text-selection/convert-rect-range.ts b/packages/docs-ui/src/services/selection/convert-rect-range.ts similarity index 95% rename from packages/engine-render/src/components/docs/text-selection/convert-rect-range.ts rename to packages/docs-ui/src/services/selection/convert-rect-range.ts index ed6b972821e..6ba4ae098e5 100644 --- a/packages/engine-render/src/components/docs/text-selection/convert-rect-range.ts +++ b/packages/docs-ui/src/services/selection/convert-rect-range.ts @@ -15,13 +15,9 @@ */ import { type Nullable, Tools } from '@univerjs/core'; -import type { IDocumentSkeletonGlyph, IDocumentSkeletonPage, IDocumentSkeletonRow, IDocumentSkeletonTable, INodePosition, IPoint } from '../../../basics'; -import { DocumentSkeletonPageType } from '../../../basics'; -import type { IDocumentOffsetConfig } from '../document'; -import type { DocumentSkeleton } from '../layout/doc-skeleton'; -import { Liquid } from '../liquid'; -import { getTableIdAndSliceIndex } from '../layout/block/table'; -import { compareNodePositionLogic, getPageFromPath, pushToPoints } from './convert-text-range'; +import type { DocumentSkeleton, IDocumentOffsetConfig, IDocumentSkeletonGlyph, IDocumentSkeletonPage, IDocumentSkeletonRow, IDocumentSkeletonTable, INodePosition, IPoint } from '@univerjs/engine-render'; +import { DocumentSkeletonPageType, getPageFromPath, getTableIdAndSliceIndex, Liquid } from '@univerjs/engine-render'; +import { compareNodePositionLogic, pushToPoints } from './convert-text-range'; // The anchor and focus need to be in the same table, // and cannot be in the same cell, start node must be the first glyph in the cell, @@ -137,6 +133,7 @@ export class NodePositionConvertToRectRange { // super } + // eslint-disable-next-line max-lines-per-function getRangePointData(startNodePosition: INodePosition, endNodePosition: INodePosition) { const pointGroup: IPoint[][] = []; const docSkeleton = this._docSkeleton; diff --git a/packages/engine-render/src/components/docs/text-selection/convert-text-range.ts b/packages/docs-ui/src/services/selection/convert-text-range.ts similarity index 93% rename from packages/engine-render/src/components/docs/text-selection/convert-text-range.ts rename to packages/docs-ui/src/services/selection/convert-text-range.ts index 7e632e0b615..a4d413e9f2f 100644 --- a/packages/engine-render/src/components/docs/text-selection/convert-text-range.ts +++ b/packages/docs-ui/src/services/selection/convert-text-range.ts @@ -15,23 +15,8 @@ */ import type { IPosition, ITextRange, Nullable } from '@univerjs/core'; - -import type { - IDocumentSkeletonCached, - IDocumentSkeletonColumn, - IDocumentSkeletonDivide, - IDocumentSkeletonGlyph, - IDocumentSkeletonLine, - IDocumentSkeletonPage, - IDocumentSkeletonRow, - IDocumentSkeletonSection, -} from '../../../basics/i-document-skeleton-cached'; -import { DocumentSkeletonPageType, GlyphType } from '../../../basics/i-document-skeleton-cached'; -import type { INodePosition } from '../../../basics/interfaces'; -import type { IPoint } from '../../../basics/vector2'; -import type { DocumentSkeleton } from '../layout/doc-skeleton'; -import type { IDocumentOffsetConfig } from '../document'; -import { Liquid } from '../liquid'; +import type { DocumentSkeleton, IDocumentOffsetConfig, IDocumentSkeletonColumn, IDocumentSkeletonDivide, IDocumentSkeletonGlyph, IDocumentSkeletonLine, IDocumentSkeletonPage, IDocumentSkeletonRow, IDocumentSkeletonSection, INodePosition, IPoint } from '@univerjs/engine-render'; +import { DocumentSkeletonPageType, getPageFromPath, GlyphType, Liquid } from '@univerjs/engine-render'; export enum NodePositionStateType { NORMAL, @@ -213,30 +198,6 @@ export function pushToPoints(position: IPosition) { return points; } -export function getPageFromPath(skeletonData: IDocumentSkeletonCached, path: (string | number)[]): Nullable { - const pathCopy = [...path]; - let page: Nullable = null; - - while (pathCopy.length > 0) { - const field = pathCopy.shift(); - - if (field === 'pages') { - const pageIndex = pathCopy.shift() as number; - page = skeletonData.pages[pageIndex]; - } else if (field === 'skeTables') { - const tableId = pathCopy.shift() as string; - pathCopy.shift(); // rows - const rowIndex = pathCopy.shift() as number; - pathCopy.shift(); // cells - const cellIndex = pathCopy.shift() as number; - - page = page!.skeTables?.get(tableId)?.rows[rowIndex]?.cells[cellIndex]; - } - } - - return page; -} - export class NodePositionConvertToCursor { private _liquid = new Liquid(); @@ -265,6 +226,7 @@ export class NodePositionConvertToCursor { // super } + // eslint-disable-next-line max-lines-per-function getRangePointData(startOrigin: Nullable, endOrigin: Nullable) { const borderBoxPointGroup: IPoint[][] = []; const contentBoxPointGroup: IPoint[][] = []; @@ -289,6 +251,7 @@ export class NodePositionConvertToCursor { const { start, end } = compareNodePosition(startOrigin, endOrigin); + // eslint-disable-next-line complexity this._selectionIterator(start, end, (start_sp, end_sp, isFirst, isLast, divide, line) => { const { lineHeight, asc, paddingTop, marginTop, marginBottom } = line; const { glyphGroup, st } = divide; @@ -494,6 +457,7 @@ export class NodePositionConvertToCursor { }; } + // eslint-disable-next-line max-lines-per-function, complexity private _selectionIterator( startPosition: INodePosition, endPosition: INodePosition, diff --git a/packages/engine-render/src/components/docs/text-selection/text-selection-render-manager.ts b/packages/docs-ui/src/services/selection/doc-selection-render.service.ts similarity index 77% rename from packages/engine-render/src/components/docs/text-selection/text-selection-render-manager.ts rename to packages/docs-ui/src/services/selection/doc-selection-render.service.ts index bb36bc6b00c..57db450fae3 100644 --- a/packages/engine-render/src/components/docs/text-selection/text-selection-render-manager.ts +++ b/packages/docs-ui/src/services/selection/doc-selection-render.service.ts @@ -14,111 +14,26 @@ * limitations under the License. */ -import type { Nullable } from '@univerjs/core'; -import { createIdentifier, DataStreamTreeTokenType, ILogService, RxDisposable } from '@univerjs/core'; -import type { Observable, Subscription } from 'rxjs'; +import type { Documents, Engine, IDocSelectionInnerParam, IFindNodeRestrictions, IMouseEvent, INodeInfo, INodePosition, IPointerEvent, IRenderContext, IRenderModule, IScrollObserverParam, ISuccinctDocRangeParam, ITextRangeWithStyle, ITextSelectionStyle, Viewport } from '@univerjs/engine-render'; +import { CURSOR_TYPE, getSystemHighlightColor, NORMAL_TEXT_SELECTION_PLUGIN_STYLE, PageLayoutType, ScrollTimer, Vector2 } from '@univerjs/engine-render'; +import type { DocumentDataModel, Nullable } from '@univerjs/core'; +import { DataStreamTreeTokenType, DOC_RANGE_TYPE, ILogService, Inject, RxDisposable } from '@univerjs/core'; +import type { Subscription } from 'rxjs'; import { BehaviorSubject, fromEvent, Subject } from 'rxjs'; - -import { CURSOR_TYPE } from '../../../basics/const'; -import { PageLayoutType } from '../../../basics/i-document-skeleton-cached'; -import type { IMouseEvent, IPointerEvent } from '../../../basics/i-events'; -import type { INodeInfo, INodePosition } from '../../../basics/interfaces'; -import type { - ISuccinctDocRangeParam, - ITextRangeWithStyle, - ITextSelectionStyle, - RANGE_DIRECTION, -} from '../../../basics/range'; -import { NORMAL_TEXT_SELECTION_PLUGIN_STYLE } from '../../../basics/range'; -import { Vector2 } from '../../../basics/vector2'; -import type { Engine } from '../../../engine'; -import type { Scene } from '../../../scene'; -import { ScrollTimer } from '../../../scroll-timer'; -import type { IScrollObserverParam, Viewport } from '../../../viewport'; -import type { DocumentSkeleton, IFindNodeRestrictions } from '../layout/doc-skeleton'; -import type { Documents } from '../document'; -import { getSystemHighlightColor } from '../../../basics/tools'; -import { TextRange } from './text-range'; +import { ILayoutService } from '@univerjs/ui'; +import { DocSkeletonManagerService } from '@univerjs/docs'; import type { RectRange } from './rect-range'; -import { getCanvasOffsetByEngine, getParagraphInfoByGlyph, getRangeListFromCharIndex, getRangeListFromSelection, getRectRangeFromCharIndex, getTextRangeFromCharIndex } from './selection-utils'; -import { DOC_RANGE_TYPE } from './range-interface'; - -export interface ITextSelectionInnerParam { - textRanges: TextRange[]; - rectRanges: RectRange[]; - segmentId: string; - isEditing: boolean; - style: ITextSelectionStyle; - segmentPage: number; - options?: { [key: string]: boolean }; -} - -export interface IActiveTextRange { - startOffset: number; - endOffset: number; - collapsed: boolean; - startNodePosition: Nullable; - endNodePosition: Nullable; - direction: RANGE_DIRECTION; - segmentId: string; - segmentPage: number; - style: ITextSelectionStyle; -} - -export interface ITextSelectionRenderManager { - readonly onInputBefore$: Observable>; - readonly onKeydown$: Observable>; - readonly onInput$: Observable>; - readonly onPointerDown$: Observable; - readonly onCompositionstart$: Observable>; - readonly onCompositionupdate$: Observable>; - readonly onCompositionend$: Observable>; - readonly onSelectionStart$: Observable>; - readonly onPaste$: Observable>; - readonly onFocus$: Observable>; - readonly onBlur$: Observable>; - readonly textSelectionInner$: Observable>; - - __getEditorContainer(): HTMLElement; - getViewPort(): Viewport; - enableSelection(): void; - disableSelection(): void; - setSegment(id: string): void; - getSegment(): string; - setSegmentPage(pageIndex: number): void; - getSegmentPage(): number; - setStyle(style: ITextSelectionStyle): void; - resetStyle(): void; - - removeAllRanges(): void; - addDocRanges(ranges: ISuccinctDocRangeParam[], isEditing?: boolean, options?: { [key: string]: boolean }): void; - - sync(): void; - - activate(x: number, y: number): void; - deactivate(): void; - hasFocus(): boolean; - focus(): void; - blur(): void; - focusEditor(): void; - blurEditor(): void; - - changeRuntime(docSkeleton: DocumentSkeleton, scene: Scene, document: Documents): void; - dispose(): void; - handleDblClick(evt: IPointerEvent | IMouseEvent): void; - handleTripleClick(evt: IPointerEvent | IMouseEvent): void; - onPointDown(evt: IPointerEvent | IMouseEvent): void; - setCursorManually(evtOffsetX: number, evtOffsetY: number): void; -} +import { getCanvasOffsetByEngine, getParagraphInfoByGlyph, getRangeListFromCharIndex, getRangeListFromSelection, getRectRangeFromCharIndex, getTextRangeFromCharIndex, serializeRectRange, serializeTextRange } from './selection-utils'; +import { TextRange } from './text-range'; export interface IEditorInputConfig { event: Event | CompositionEvent | KeyboardEvent; content?: string; activeRange?: Nullable; - rangeList?: TextRange[]; + rangeList?: ITextRangeWithStyle[]; } -export class TextSelectionRenderManager extends RxDisposable implements ITextSelectionRenderManager { +export class DocSelectionRenderService extends RxDisposable implements IRenderModule { private readonly _onInputBefore$ = new Subject>(); readonly onInputBefore$ = this._onInputBefore$.asObservable(); @@ -143,7 +58,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel private readonly _onPaste$ = new Subject>(); readonly onPaste$ = this._onPaste$.asObservable(); - private readonly _textSelectionInner$ = new BehaviorSubject>(null); + private readonly _textSelectionInner$ = new BehaviorSubject>(null); readonly textSelectionInner$ = this._textSelectionInner$.asObservable(); private readonly _onFocus$ = new Subject>(); @@ -182,26 +97,24 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel >(); private _isIMEInputApply = false; - private _activeViewport!: Viewport; - private _docSkeleton: Nullable; - private _scene: Nullable; - private _document: Nullable; private _scenePointerMoveSubs: Array = []; private _scenePointerUpSubs: Array = []; private _editorFocusing = true; - constructor(@ILogService private readonly _logService: ILogService) { + constructor( + private readonly _context: IRenderContext, + @ILayoutService private readonly _layoutService: ILayoutService, + @ILogService private readonly _logService: ILogService, + @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService + ) { super(); this._initDOM(); + this._registerContainer(); this._setSystemHighlightColorToStyle(); } - __getEditorContainer(): HTMLElement { - return this._container; - } - - getViewPort() { - return this._activeViewport; + get activeViewPort() { + return this._context.scene.getViewports()[0]; } setSegment(id: string) { @@ -238,17 +151,21 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel addDocRanges(ranges: ISuccinctDocRangeParam[], isEditing = true, options?: { [key: string]: boolean }) { const { - _scene: scene, _docSkeleton: docSkeleton, _document: document, - _currentSegmentId: segmentId, _currentSegmentPage: segmentPage, + _currentSegmentId: segmentId, + _currentSegmentPage: segmentPage, _selectionStyle: style, } = this; + const { scene, mainComponent } = this._context; + const document = mainComponent as Documents; + const docSkeleton = this._docSkeletonManagerService.getSkeleton(); + for (const range of ranges) { const { startOffset, endOffset, rangeType } = range; if (rangeType === DOC_RANGE_TYPE.RECT) { const rectRange = getRectRangeFromCharIndex( - startOffset, endOffset, scene!, document!, docSkeleton!, style, segmentId, segmentPage + startOffset, endOffset, scene, document, docSkeleton, style, segmentId, segmentPage ); if (rectRange) { @@ -256,7 +173,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } } else if (rangeType === DOC_RANGE_TYPE.TEXT) { const textRange = getTextRangeFromCharIndex( - startOffset, endOffset, scene!, document!, docSkeleton!, style, segmentId, segmentPage + startOffset, endOffset, scene, document, docSkeleton, style, segmentId, segmentPage ); if (textRange) { @@ -264,7 +181,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } } else { const rangeList = getRangeListFromCharIndex( - startOffset, endOffset, scene!, document!, docSkeleton!, style, segmentId, segmentPage + startOffset, endOffset, scene, document, docSkeleton, style, segmentId, segmentPage ); if (rangeList == null) { @@ -369,26 +286,9 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this._container.style.top = '0px'; } - changeRuntime(docSkeleton: DocumentSkeleton, scene: Scene, document: Documents) { - // Need to empty text ranges when change doc. - if (docSkeleton !== this._docSkeleton) { - this.removeAllRanges(); - } - - this._docSkeleton = docSkeleton; - - this._scene = scene; - - this._activeViewport = scene.getViewports()[0]; - - this._document = document; - - this._attachScrollEvent(this._activeViewport); - } - // Handler double click. handleDblClick(evt: IPointerEvent | IMouseEvent) { - if (!this._scene || !this._isSelectionEnabled) { + if (!this._isSelectionEnabled) { return; } @@ -450,7 +350,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } handleTripleClick(evt: IPointerEvent | IMouseEvent) { - if (!this._scene || !this._isSelectionEnabled) { + if (!this._isSelectionEnabled) { return; } @@ -474,11 +374,10 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel const { st, ed } = paragraphInfo; - const textRanges: ITextRangeWithStyle[] = [ + const textRanges: ISuccinctDocRangeParam[] = [ { startOffset: st, endOffset: ed, - collapsed: st === ed, }, ]; @@ -486,12 +385,14 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } // Handle pointer down. + // eslint-disable-next-line max-lines-per-function, complexity onPointDown(evt: IPointerEvent | IMouseEvent) { - if (!this._scene || !this._isSelectionEnabled) { + if (!this._isSelectionEnabled) { return; } this._editorFocusing = true; - const scene = this._scene; + const { scene, mainComponent } = this._context; + const skeleton = this._docSkeletonManagerService.getSkeleton(); const { offsetX: evtOffsetX, offsetY: evtOffsetY } = evt; @@ -515,7 +416,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel const docSelection = this._textSelectionInner$.value; if (startNode && evt.button === 2 && docSelection) { - const nodeCharIndex = this._docSkeleton?.findCharIndexByPosition(position); + const nodeCharIndex = skeleton.findCharIndexByPosition(position); if (typeof nodeCharIndex === 'number' && docSelection.textRanges.some((textRange) => textRange.startOffset! <= nodeCharIndex && textRange.endOffset! > nodeCharIndex)) { return; } @@ -579,7 +480,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel // Add cursor. if (this._anchorNodePosition && !this._focusNodePosition) { - const textRange = new TextRange(this._scene!, this._document!, this._docSkeleton!, this._anchorNodePosition, undefined, this._selectionStyle, this._currentSegmentId); + const textRange = new TextRange(scene, mainComponent as Documents, skeleton, this._anchorNodePosition, undefined, this._selectionStyle, this._currentSegmentId, this._currentSegmentPage); this._addTextRange(textRange); } else if (this._anchorNodePosition && this._focusNodePosition) { @@ -622,6 +523,10 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this.deactivate(); } + getActiveTextRange() { + return this._getActiveRangeInstance(); + } + private _setSystemHighlightColorToStyle() { const { r, g, b, a } = getSystemHighlightColor(); @@ -637,37 +542,27 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } private _getAllTextRanges() { - return this._rangeList; + return this._rangeList.map(serializeTextRange); } private _getAllRectRanges() { - return this._rectRangeList; + return this._rectRangeList.map(serializeRectRange); } - private _getActiveRange(): Nullable { + private _getActiveRange(): Nullable { const activeRange = this._rangeList.find((range) => range.isActive()); if (activeRange == null) { return null; } - const { startOffset, endOffset, collapsed, startNodePosition, endNodePosition, direction } = activeRange; + const { startOffset, endOffset } = activeRange; if (startOffset == null || endOffset == null) { return null; } - return { - startOffset, - endOffset, - collapsed, - startNodePosition, - endNodePosition, - direction, - segmentId: this._currentSegmentId, - segmentPage: this._currentSegmentPage, - style: this._selectionStyle, - }; + return serializeTextRange(activeRange); } private _getActiveRangeInstance() { @@ -683,11 +578,14 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } private _initDOM() { + const { unitId } = this._context; const container = document.createElement('div'); container.style.position = 'fixed'; container.style.left = '0px'; container.style.top = '0px'; + container.id = `univer-doc-selection-container-${unitId}`; + const inputParent = document.createElement('div'); const inputDom = document.createElement('div'); @@ -704,6 +602,13 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel document.body.appendChild(container); } + private _registerContainer() { + this.disposeWithMe( + // the content editable div should be regarded as part of the applications container + this._layoutService.registerContainerElement(this._container) + ); + } + private _initInput() { this._inputParent.style.cssText = ` position:absolute; @@ -736,7 +641,8 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel const { node: glyph, ratioX, segmentPage } = node; - const position = this._docSkeleton?.findPositionByGlyph(glyph, segmentPage); + const skeleton = this._docSkeletonManagerService.getSkeleton(); + const position = skeleton.findPositionByGlyph(glyph, segmentPage); if (position == null) { return; @@ -854,29 +760,22 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } private _createTextRangeByAnchorPosition(position: INodePosition) { - if (!this._scene) { - return; - } - this._removeAllRanges(); - const lastRange = new TextRange(this._scene, this._document!, this._docSkeleton!, position, undefined, this._selectionStyle, this._currentSegmentId); + const { scene, mainComponent } = this._context; + const skeleton = this._docSkeletonManagerService.getSkeleton(); + + const lastRange = new TextRange(scene, mainComponent as Documents, skeleton, position, undefined, this._selectionStyle, this._currentSegmentId, this._currentSegmentPage); this._addTextRange(lastRange); } private _updateActiveRangePosition(position: INodePosition) { - if (!this._scene) { - this._logService.error('[TextSelectionRenderManager] _updateActiveRangeFocusPosition: scene is null'); - - return; - } - const activeTextRange = this._getActiveRangeInstance(); if (activeTextRange == null || activeTextRange.anchorNodePosition == null) { this._logService.error( - '[TextSelectionRenderManager] _updateActiveRangeFocusPosition: active range has no anchor' + '[DocSelectionRenderService] _updateActiveRangeFocusPosition: active range has no anchor' ); return; @@ -887,18 +786,21 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this._anchorNodePosition = activeTextRange.anchorNodePosition; this._focusNodePosition = position; - const { _anchorNodePosition, _focusNodePosition, _scene, _document, _docSkeleton, _selectionStyle, _currentSegmentId, _currentSegmentPage } = this; + const { scene, mainComponent } = this._context; + const skeleton = this._docSkeletonManagerService.getSkeleton(); + + const { _anchorNodePosition, _focusNodePosition, _selectionStyle, _currentSegmentId, _currentSegmentPage } = this; - if (_anchorNodePosition == null || _focusNodePosition == null || _scene == null || _document == null || _docSkeleton == null) { + if (_anchorNodePosition == null || _focusNodePosition == null || mainComponent == null) { return; } const ranges = getRangeListFromSelection( _anchorNodePosition, _focusNodePosition, - _scene, - _document, - _docSkeleton, + scene, + mainComponent as Documents, + skeleton, _selectionStyle, _currentSegmentId, _currentSegmentPage @@ -922,7 +824,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel private _getCanvasOffset() { // This is quiet ambiguous, when did the engine's canvas offset changes? - const engine = this._scene?.getEngine() as Engine; + const engine = this._context.scene?.getEngine() as Engine; return getCanvasOffsetByEngine(engine); } @@ -930,14 +832,14 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel const activeRangeInstance = this._getActiveRangeInstance(); const anchor = activeRangeInstance?.getAnchor(); - if (!anchor || (anchor && !anchor.visible) || this._activeViewport == null) { + if (!anchor || (anchor && !anchor.visible) || this.activeViewPort == null) { this.focus(); return; } const { left, top } = anchor; - const absoluteCoord = this._activeViewport.getAbsoluteVector(Vector2.FromArray([left, top])); + const absoluteCoord = this.activeViewPort.getAbsoluteVector(Vector2.FromArray([left, top])); const { x, y } = absoluteCoord; @@ -951,10 +853,6 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } private _moving(moveOffsetX: number, moveOffsetY: number) { - if (this._docSkeleton == null) { - return; - } - const focusNode = this._findNodeByCoord(moveOffsetX, moveOffsetY, { strict: true, segmentId: this._currentSegmentId, @@ -982,18 +880,20 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this._removeAllCacheRanges(); - const { _anchorNodePosition, _focusNodePosition, _scene, _document, _docSkeleton, _selectionStyle, _currentSegmentId, _currentSegmentPage } = this; + const { _anchorNodePosition, _focusNodePosition, _selectionStyle, _currentSegmentId, _currentSegmentPage } = this; + const { scene, mainComponent } = this._context; + const skeleton = this._docSkeletonManagerService.getSkeleton(); - if (_anchorNodePosition == null || _focusNodePosition == null || _scene == null || _document == null || _docSkeleton == null) { + if (_anchorNodePosition == null || _focusNodePosition == null || mainComponent == null) { return; } const ranges = getRangeListFromSelection( _anchorNodePosition, _focusNodePosition, - _scene, - _document, - _docSkeleton, + scene, + mainComponent as Documents, + skeleton, _selectionStyle, _currentSegmentId, _currentSegmentPage @@ -1018,14 +918,15 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this.deactivate(); - this._scene?.getEngine()?.setRemainCapture(); + this._context.scene?.getEngine()?.setRemainCapture(); } - private _attachScrollEvent(viewport: Nullable) { - if (viewport == null || this._docSkeleton == null) { + // TODO: @Jocs make this method as private. + attachScrollEvent(viewport: Nullable) { + if (viewport == null) { return; } - const unitId = this._docSkeleton.getViewModel().getDataModel().getUnitId(); + const { unitId } = this._context; const key = `${unitId}_${viewport.viewportKey}`; if (this._viewPortObserverMap.has(key)) { @@ -1078,6 +979,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } // FIXME: listeners here are not correctly disposed + // eslint-disable-next-line max-lines-per-function private _initInputEvents() { this.disposeWithMe( fromEvent(this._input, 'keydown').subscribe((e) => { @@ -1195,12 +1097,14 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel } private _getTransformCoordForDocumentOffset(evtOffsetX: number, evtOffsetY: number) { - const { documentTransform } = this._document!.getOffsetConfig(); - if (this._activeViewport == null || documentTransform == null) { + const document = this._context.mainComponent as Documents; + const { documentTransform } = document.getOffsetConfig(); + + if (this.activeViewPort == null || documentTransform == null) { return; } - const originCoord = this._activeViewport.transformVector2SceneCoord(Vector2.FromArray([evtOffsetX, evtOffsetY])); + const originCoord = this.activeViewPort.transformVector2SceneCoord(Vector2.FromArray([evtOffsetX, evtOffsetY])); if (!originCoord) { return; @@ -1216,13 +1120,16 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel return; } + const document = this._context.mainComponent as Documents; + const skeleton = this._docSkeletonManagerService.getSkeleton(); + const { pageLayoutType = PageLayoutType.VERTICAL, pageMarginLeft, pageMarginTop, - } = this._document!.getOffsetConfig(); + } = document.getOffsetConfig(); - const nodeInfo = this._docSkeleton?.findNodeByCoord( + const nodeInfo = skeleton.findNodeByCoord( coord, pageLayoutType, pageMarginLeft, pageMarginTop, restrictions ); @@ -1239,7 +1146,3 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel this._onSelectionStart$.complete(); } } - -export const ITextSelectionRenderManager = createIdentifier( - 'univer.doc.text-selection-render-manager' -); diff --git a/packages/engine-render/src/components/docs/text-selection/range-interface.ts b/packages/docs-ui/src/services/selection/range-interface.ts similarity index 79% rename from packages/engine-render/src/components/docs/text-selection/range-interface.ts rename to packages/docs-ui/src/services/selection/range-interface.ts index 8462b62afdc..4f5b1adeac5 100644 --- a/packages/engine-render/src/components/docs/text-selection/range-interface.ts +++ b/packages/docs-ui/src/services/selection/range-interface.ts @@ -14,13 +14,8 @@ * limitations under the License. */ -import type { Nullable } from '@univerjs/core'; -import type { INodePosition, ITextSelectionStyle, RANGE_DIRECTION } from '../../../basics'; - -export enum DOC_RANGE_TYPE { - RECT = 'RECT', - TEXT = 'TEXT', -} +import type { DOC_RANGE_TYPE, Nullable, RANGE_DIRECTION } from '@univerjs/core'; +import type { INodePosition, ITextSelectionStyle } from '@univerjs/engine-render'; export interface IDocRange { // RECT OR TEXT. @@ -40,7 +35,11 @@ export interface IDocRange { get startNodePosition(): Nullable; get endNodePosition(): Nullable; get direction(): RANGE_DIRECTION; - + // Get the segmentId of the range. + get segmentId(): string; + // Get the page number of the range when in header or footer. + get segmentPage(): number; + // Whether the range is active. isActive(): boolean; dispose(): void; diff --git a/packages/engine-render/src/components/docs/text-selection/rect-range.ts b/packages/docs-ui/src/services/selection/rect-range.ts similarity index 92% rename from packages/engine-render/src/components/docs/text-selection/rect-range.ts rename to packages/docs-ui/src/services/selection/rect-range.ts index d91297882ae..44a82f2e258 100644 --- a/packages/engine-render/src/components/docs/text-selection/rect-range.ts +++ b/packages/docs-ui/src/services/selection/rect-range.ts @@ -14,15 +14,10 @@ * limitations under the License. */ -import { COLORS, type Nullable, Rectangle, Tools } from '@univerjs/core'; -import type { INodePosition, IPoint, ITextSelectionStyle } from '../../../basics'; -import { getColor, NORMAL_TEXT_SELECTION_PLUGIN_STYLE, RANGE_DIRECTION } from '../../../basics'; -import type { ThinScene } from '../../../thin-scene'; -import type { Documents } from '../document'; -import type { DocumentSkeleton } from '../layout/doc-skeleton'; -import { RegularPolygon } from '../../../shape'; +import { COLORS, DOC_RANGE_TYPE, type Nullable, RANGE_DIRECTION, Rectangle, Tools } from '@univerjs/core'; +import type { Documents, DocumentSkeleton, INodePosition, IPoint, ITextSelectionStyle, ThinScene } from '@univerjs/engine-render'; +import { getColor, NORMAL_TEXT_SELECTION_PLUGIN_STYLE, RegularPolygon } from '@univerjs/engine-render'; import type { IDocRange } from './range-interface'; -import { DOC_RANGE_TYPE } from './range-interface'; import { compareNodePositionInTable, NodePositionConvertToRectRange } from './convert-rect-range'; import { TEXT_RANGE_LAYER_INDEX } from './text-range'; @@ -36,14 +31,15 @@ export function convertPositionsToRectRanges( anchorNodePosition: INodePosition, focusNodePosition: INodePosition, style: ITextSelectionStyle = NORMAL_TEXT_SELECTION_PLUGIN_STYLE, - segmentId: string = '' + segmentId: string = '', + segmentPage: number = -1 ): RectRange[] { const documentOffsetConfig = document.getOffsetConfig(); const convertor = new NodePositionConvertToRectRange(documentOffsetConfig, docSkeleton); const nodePositionGroup = convertor.getNodePositionGroup(anchorNodePosition, focusNodePosition); return (nodePositionGroup ?? []).map((position) => new RectRange( - scene, document, docSkeleton, position.anchor, position.focus, style, segmentId + scene, document, docSkeleton, position.anchor, position.focus, style, segmentId, segmentPage )); } @@ -71,7 +67,8 @@ export class RectRange implements IDocRange { public anchorNodePosition: INodePosition, public focusNodePosition: INodePosition, public style: ITextSelectionStyle = NORMAL_TEXT_SELECTION_PLUGIN_STYLE, - private _segmentId: string = '' + private _segmentId: string = '', + private _segmentPage: number = -1 ) { this.refresh(); } @@ -116,6 +113,10 @@ export class RectRange implements IDocRange { return this._segmentId; } + get segmentPage() { + return this._segmentPage; + } + get spanEntireRow(): boolean { const viewModel = this._docSkeleton.getViewModel(); const table = viewModel.getSnapshot().tableSource?.[this._tableId]; diff --git a/packages/engine-render/src/components/docs/text-selection/selection-utils.ts b/packages/docs-ui/src/services/selection/selection-utils.ts similarity index 79% rename from packages/engine-render/src/components/docs/text-selection/selection-utils.ts rename to packages/docs-ui/src/services/selection/selection-utils.ts index 78a60064eac..8ec81c2aeaf 100644 --- a/packages/engine-render/src/components/docs/text-selection/selection-utils.ts +++ b/packages/docs-ui/src/services/selection/selection-utils.ts @@ -14,17 +14,29 @@ * limitations under the License. */ -import { type Nullable, Tools } from '@univerjs/core'; -import type { IDocumentSkeletonGlyph, INodePosition, ITextSelectionStyle } from '../../../basics'; -import { RANGE_DIRECTION } from '../../../basics'; -import { getOffsetRectForDom } from '../../../basics/position'; -import type { DocumentSkeleton } from '../layout/doc-skeleton'; -import type { Engine } from '../../../engine'; -import type { Documents } from '../document'; -import type { Scene } from '../../../scene'; +/** + * 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 { type Nullable, RANGE_DIRECTION, Tools } from '@univerjs/core'; +import type { Documents, DocumentSkeleton, Engine, IDocumentSkeletonGlyph, INodePosition, IRectRangeWithStyle, ITextRangeWithStyle, ITextSelectionStyle, Scene } from '@univerjs/engine-render'; +import { getOffsetRectForDom } from '@univerjs/engine-render'; import { convertPositionsToRectRanges, RectRange } from './rect-range'; import { TextRange } from './text-range'; import { isInSameTableCell, isValidRectRange } from './convert-rect-range'; +import type { IDocRange } from './range-interface'; interface IDocRangeList { textRanges: TextRange[]; @@ -48,7 +60,7 @@ export function getTextRangeFromCharIndex( return; } - return new TextRange(scene, document, skeleton, startNodePosition, endNodePosition, style, segmentId); + return new TextRange(scene, document, skeleton, startNodePosition, endNodePosition, style, segmentId, segmentPage); } export function getRectRangeFromCharIndex( @@ -68,7 +80,7 @@ export function getRectRangeFromCharIndex( return; } - return new RectRange(scene, document, skeleton, startNodePosition, endNodePosition, style, segmentId); + return new RectRange(scene, document, skeleton, startNodePosition, endNodePosition, style, segmentId, segmentPage); } export function getRangeListFromCharIndex( @@ -100,6 +112,7 @@ export function getRangeListFromCharIndex( ); } +// eslint-disable-next-line max-lines-per-function, complexity export function getRangeListFromSelection( anchorPosition: INodePosition, focusPosition: INodePosition, @@ -119,8 +132,9 @@ export function getRangeListFromSelection( INodePosition, INodePosition, ITextSelectionStyle, - string - ] = [scene, document, skeleton, anchorPosition, focusPosition, style, segmentId]; + string, + number + ] = [scene, document, skeleton, anchorPosition, focusPosition, style, segmentId, segmentPage]; // TODO: @JOCS handle NEST table. // Handle selection in same table cell. @@ -199,7 +213,7 @@ export function getRangeListFromSelection( const ap = direction === RANGE_DIRECTION.FORWARD ? sp : ep; const fp = direction === RANGE_DIRECTION.FORWARD ? ep : sp; - textRanges.push(new TextRange(scene, document, skeleton, ap, fp, style, segmentId)); + textRanges.push(new TextRange(scene, document, skeleton, ap, fp, style, segmentId, segmentPage)); } start = tableEnd + 1; } @@ -215,7 +229,8 @@ export function getRangeListFromSelection( ap, fp, style, - segmentId + segmentId, + segmentPage )); } } @@ -231,7 +246,7 @@ export function getRangeListFromSelection( continue; } - textRanges.push(new TextRange(scene, document, skeleton, ap, fp, style, segmentId)); + textRanges.push(new TextRange(scene, document, skeleton, ap, fp, style, segmentId, segmentPage)); } } } @@ -296,3 +311,48 @@ export function getParagraphInfoByGlyph(node: IDocumentSkeletonGlyph) { nodeIndex, }; } + +export function serializeTextRange(textRange: IDocRange): ITextRangeWithStyle { + const { startOffset, endOffset, collapsed, rangeType, startNodePosition, endNodePosition, direction, segmentId, segmentPage } = textRange; + const serializedTextRange: ITextRangeWithStyle = { + startOffset: startOffset!, + endOffset: endOffset!, + collapsed, + rangeType, + startNodePosition, + endNodePosition, + direction, + segmentId, + segmentPage, + isActive: textRange.isActive(), + }; + + return serializedTextRange; +} + +export function serializeRectRange(rectRange: RectRange): IRectRangeWithStyle { + const serializedTextRange = serializeTextRange(rectRange); + + const { + startRow, + startColumn, + endRow, + endColumn, + tableId, + spanEntireRow, + spanEntireColumn, + spanEntireTable, + } = rectRange; + + return { + ...serializedTextRange, + startRow, + startColumn, + endRow, + endColumn, + tableId, + spanEntireRow, + spanEntireColumn, + spanEntireTable, + }; +} diff --git a/packages/engine-render/src/components/docs/text-selection/text-range.ts b/packages/docs-ui/src/services/selection/text-range.ts similarity index 93% rename from packages/engine-render/src/components/docs/text-selection/text-range.ts rename to packages/docs-ui/src/services/selection/text-range.ts index 7634b19ddbc..792b5078043 100644 --- a/packages/engine-render/src/components/docs/text-selection/text-range.ts +++ b/packages/docs-ui/src/services/selection/text-range.ts @@ -15,19 +15,9 @@ */ import type { ITextRange, Nullable } from '@univerjs/core'; -import { BooleanNumber, COLORS, Tools } from '@univerjs/core'; -import type { INodePosition } from '../../../basics/interfaces'; -import type { ISuccinctDocRangeParam, ITextSelectionStyle } from '../../../basics/range'; -import { NORMAL_TEXT_SELECTION_PLUGIN_STYLE, RANGE_DIRECTION } from '../../../basics/range'; -import { getColor } from '../../../basics/tools'; -import type { IPoint } from '../../../basics/vector2'; -import type { Scene } from '../../../scene'; -import { Rect } from '../../../shape/rect'; -import { RegularPolygon } from '../../../shape/regular-polygon'; -import type { ThinScene } from '../../../thin-scene'; -import type { DocumentSkeleton } from '../layout/doc-skeleton'; -import type { Documents } from '../document'; -import type { IDocumentSkeletonGlyph } from '../../../basics'; +import { BooleanNumber, COLORS, DOC_RANGE_TYPE, RANGE_DIRECTION, Tools } from '@univerjs/core'; +import type { Documents, DocumentSkeleton, IDocumentSkeletonGlyph, INodePosition, IPoint, ISuccinctDocRangeParam, ITextSelectionStyle, Scene, ThinScene } from '@univerjs/engine-render'; +import { getColor, NORMAL_TEXT_SELECTION_PLUGIN_STYLE, Rect, RegularPolygon } from '@univerjs/engine-render'; import { compareNodePosition, compareNodePositionLogic, @@ -36,7 +26,6 @@ import { NodePositionMap, } from './convert-text-range'; import type { IDocRange } from './range-interface'; -import { DOC_RANGE_TYPE } from './range-interface'; const TEXT_RANGE_KEY_PREFIX = '__TestSelectionRange__'; const TEXT_ANCHOR_KEY_PREFIX = '__TestSelectionAnchor__'; @@ -59,7 +48,7 @@ export function cursorConvertToTextRange( ? docSkeleton.findNodePositionByCharIndex(endOffset, true, segmentId, segmentPage) : null; const textRange = new TextRange( - scene, document, docSkeleton, anchorNodePosition, focusNodePosition, style, segmentId + scene, document, docSkeleton, anchorNodePosition, focusNodePosition, style, segmentId, segmentPage ); return textRange; @@ -123,7 +112,8 @@ export class TextRange implements IDocRange { public anchorNodePosition?: Nullable, public focusNodePosition?: Nullable, public style: ITextSelectionStyle = NORMAL_TEXT_SELECTION_PLUGIN_STYLE, - private _segmentId: string = '' + private _segmentId: string = '', + private _segmentPage: number = -1 ) { this._anchorBlink(); @@ -238,6 +228,10 @@ export class TextRange implements IDocRange { return this._segmentId; } + get segmentPage() { + return this._segmentPage; + } + getAbsolutePosition() { const anchor = this.anchorNodePosition; const focus = this.focusNodePosition; diff --git a/packages/docs-ui/src/shortcuts/core-editing.shortcut.ts b/packages/docs-ui/src/shortcuts/core-editing.shortcut.ts index 5b346340612..79efddc84c4 100644 --- a/packages/docs-ui/src/shortcuts/core-editing.shortcut.ts +++ b/packages/docs-ui/src/shortcuts/core-editing.shortcut.ts @@ -16,8 +16,8 @@ import type { IShortcutItem } from '@univerjs/ui'; import { KeyCode } from '@univerjs/ui'; - -import { DeleteLeftCommand, DeleteRightCommand, EnterCommand } from '@univerjs/docs'; +import { EnterCommand } from '../commands/commands/auto-format.command'; +import { DeleteLeftCommand, DeleteRightCommand } from '../commands/commands/delete.command'; import { whenDocAndEditorFocused, whenDocAndEditorFocusedWithBreakLine } from './utils'; export const BreakLineShortcut: IShortcutItem = { diff --git a/packages/docs-ui/src/shortcuts/cursor.shortcut.ts b/packages/docs-ui/src/shortcuts/cursor.shortcut.ts index 650088609a8..63b7f1c4a05 100644 --- a/packages/docs-ui/src/shortcuts/cursor.shortcut.ts +++ b/packages/docs-ui/src/shortcuts/cursor.shortcut.ts @@ -17,8 +17,8 @@ import { Direction, EDITOR_ACTIVATED, FOCUSING_DOC, FOCUSING_UNIVER_EDITOR } from '@univerjs/core'; import type { IShortcutItem } from '@univerjs/ui'; import { KeyCode, MetaKeys } from '@univerjs/ui'; - -import { MoveCursorOperation, MoveSelectionOperation, SelectAllOperation } from '@univerjs/docs'; +import { MoveCursorOperation, MoveSelectionOperation } from '../commands/operations/doc-cursor.operation'; +import { SelectAllOperation } from '../commands/operations/select-all.operation'; import { whenDocAndEditorFocused } from './utils'; export const MoveCursorUpShortcut: IShortcutItem = { diff --git a/packages/docs-ui/src/shortcuts/format.shortcut.ts b/packages/docs-ui/src/shortcuts/format.shortcut.ts index 9962939a50a..1610e7267ff 100644 --- a/packages/docs-ui/src/shortcuts/format.shortcut.ts +++ b/packages/docs-ui/src/shortcuts/format.shortcut.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { TabCommand } from '@univerjs/docs'; import { type IShortcutItem, KeyCode, MetaKeys } from '@univerjs/ui'; +import { TabCommand } from '../commands/commands/auto-format.command'; import { whenDocAndEditorFocused } from './utils'; export const TabShortCut: IShortcutItem = { diff --git a/packages/docs-ui/src/shortcuts/toolbar.shortcut.ts b/packages/docs-ui/src/shortcuts/toolbar.shortcut.ts index a830a6723a4..2017594c8c5 100644 --- a/packages/docs-ui/src/shortcuts/toolbar.shortcut.ts +++ b/packages/docs-ui/src/shortcuts/toolbar.shortcut.ts @@ -14,9 +14,11 @@ * limitations under the License. */ -import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignRightCommand, BulletListCommand, OrderListCommand, SetInlineFormatBoldCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatUnderlineCommand } from '@univerjs/docs'; import type { IShortcutItem } from '@univerjs/ui'; import { KeyCode, MetaKeys } from '@univerjs/ui'; +import { SetInlineFormatBoldCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatUnderlineCommand } from '../commands/commands/inline-format.command'; +import { AlignCenterCommand, AlignJustifyCommand, AlignLeftCommand, AlignRightCommand } from '../commands/commands/paragraph-align.command'; +import { BulletListCommand, OrderListCommand } from '../commands/commands/list.command'; import { whenDocAndEditorFocused } from './utils'; export const BoldShortCut: IShortcutItem = { diff --git a/packages/docs/src/types/enums/delete-direction.ts b/packages/docs-ui/src/types/delete-direction.ts similarity index 100% rename from packages/docs/src/types/enums/delete-direction.ts rename to packages/docs-ui/src/types/delete-direction.ts diff --git a/packages/docs-ui/src/views/count-bar/ZoomSlider.tsx b/packages/docs-ui/src/views/count-bar/ZoomSlider.tsx index 7f13bcada92..e52e90ef595 100644 --- a/packages/docs-ui/src/views/count-bar/ZoomSlider.tsx +++ b/packages/docs-ui/src/views/count-bar/ZoomSlider.tsx @@ -23,8 +23,8 @@ import { useObservable, } from '@univerjs/core'; import { Slider } from '@univerjs/design'; -import { SetDocZoomRatioOperation } from '@univerjs/docs'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { SetDocZoomRatioOperation } from '../../commands/operations/set-doc-zoom-ratio.operation'; const ZOOM_MAP = [50, 80, 100, 130, 150, 170, 200, 400]; const DOC_ZOOM_RANGE = [10, 400]; diff --git a/packages/docs-ui/src/views/header-footer/panel/DocHeaderFooterOptions.tsx b/packages/docs-ui/src/views/header-footer/panel/DocHeaderFooterOptions.tsx index 2327cad7d8a..a66710eb2cc 100644 --- a/packages/docs-ui/src/views/header-footer/panel/DocHeaderFooterOptions.tsx +++ b/packages/docs-ui/src/views/header-footer/panel/DocHeaderFooterOptions.tsx @@ -18,9 +18,10 @@ import { BooleanNumber, ICommandService, IUniverInstanceService, LocaleService, import React, { useEffect, useState } from 'react'; import { Button, Checkbox, InputNumber } from '@univerjs/design'; import clsx from 'clsx'; -import { DocumentEditArea, IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; -import { DocSkeletonManagerService, TextSelectionManagerService } from '@univerjs/docs'; +import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import { CoreHeaderFooterCommandId, type IHeaderFooterProps } from '../../../commands/commands/doc-header-footer.command'; +import { DocSelectionRenderService } from '../../../services/selection/doc-selection-render.service'; import styles from './index.module.less'; export interface IDocHeaderFooterOptionsProps { @@ -32,10 +33,11 @@ export const DocHeaderFooterOptions = (props: IDocHeaderFooterOptionsProps) => { const univerInstanceService = useDependency(IUniverInstanceService); const renderManagerService = useDependency(IRenderManagerService); const commandService = useDependency(ICommandService); - const textSelectionRenderService = useDependency(ITextSelectionRenderManager); - const textSelectionManagerService = useDependency(TextSelectionManagerService); + const docSelectionManagerService = useDependency(DocSelectionManagerService); const { unitId } = props; + const docSelectionRenderService = renderManagerService.getRenderById(unitId)!.with(DocSelectionRenderService)!; + const [options, setOptions] = useState({}); const handleCheckboxChange = (val: boolean, type: 'useFirstPageHeaderFooter' | 'evenAndOddHeaders') => { @@ -56,7 +58,7 @@ export const DocHeaderFooterOptions = (props: IDocHeaderFooterOptionsProps) => { const editArea = viewModel.getEditArea(); let needCreateHeaderFooter = false; - const segmentPage = textSelectionRenderService.getSegmentPage(); + const segmentPage = docSelectionRenderService.getSegmentPage(); let needChangeSegmentId = false; if (type === 'useFirstPageHeaderFooter' && val === true) { if (editArea === DocumentEditArea.HEADER && !documentStyle.firstPageHeaderId) { @@ -87,7 +89,7 @@ export const DocHeaderFooterOptions = (props: IDocHeaderFooterOptionsProps) => { const segmentId = Tools.generateRandomId(SEGMENT_ID_LEN); // Set segment id first, then exec command. if (needChangeSegmentId) { - textSelectionRenderService.setSegment(segmentId); + docSelectionRenderService.setSegment(segmentId); } commandService.executeCommand(CoreHeaderFooterCommandId, { @@ -121,8 +123,8 @@ export const DocHeaderFooterOptions = (props: IDocHeaderFooterOptionsProps) => { }); // To make sure input always has focus. - textSelectionRenderService.removeAllRanges(); - textSelectionRenderService.blur(); + docSelectionRenderService.removeAllRanges(); + docSelectionRenderService.blur(); }; const closeHeaderFooter = () => { @@ -143,10 +145,10 @@ export const DocHeaderFooterOptions = (props: IDocHeaderFooterOptionsProps) => { } // TODO: @JOCS, these codes bellow should be automatically executed? - textSelectionManagerService.replaceTextRanges([]); // Clear text selection. + docSelectionManagerService.replaceTextRanges([]); // Clear text selection. transformer.clearSelectedObjects(); - textSelectionRenderService.setSegment(''); - textSelectionRenderService.setSegmentPage(-1); + docSelectionRenderService.setSegment(''); + docSelectionRenderService.setSegmentPage(-1); viewModel.setEditArea(DocumentEditArea.BODY); skeleton.calculate(); render.mainComponent?.makeDirty(true); diff --git a/packages/docs-ui/src/views/paragraph-setting/hook/utils.ts b/packages/docs-ui/src/views/paragraph-setting/hook/utils.ts index 9b47d752abd..9ebfd4bd74a 100644 --- a/packages/docs-ui/src/views/paragraph-setting/hook/utils.ts +++ b/packages/docs-ui/src/views/paragraph-setting/hook/utils.ts @@ -16,7 +16,7 @@ import type { DocumentDataModel, IParagraph, ISectionBreak } from '@univerjs/core'; import { ICommandService, IUniverInstanceService, SpacingRule, UniverInstanceType, useDependency } from '@univerjs/core'; -import { DocSkeletonManagerService, findNearestSectionBreak, getParagraphsInRanges, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; import { useEffect, useMemo, useRef, useState } from 'react'; import { getNumberUnitValue, IRenderManagerService } from '@univerjs/engine-render'; import { BehaviorSubject } from 'rxjs'; @@ -24,17 +24,18 @@ import { bufferTime, filter, map } from 'rxjs/operators'; import type { IDocParagraphSettingCommandParams } from '../../../commands/commands/doc-paragraph-setting.command'; import { DocParagraphSettingCommand } from '../../../commands/commands/doc-paragraph-setting.command'; import { DocParagraphSettingController } from '../../../controllers/doc-paragraph-setting.controller'; +import { findNearestSectionBreak, getParagraphsInRanges } from '../../../commands/commands/list.command'; const useDocRanges = () => { - const textSelectionManagerService = useDependency(TextSelectionManagerService); + const docSelectionManagerService = useDependency(DocSelectionManagerService); const docParagraphSettingController = useDependency(DocParagraphSettingController); // The `getDocRanges` function internally needs to use `range.position` to obtain the offset. // However, when the form control changes and triggers the `getDocRanges` function, the `Skeleton` has already been updated. - // The information of `range.position` in the textSelectionManagerService does not match the `Skeleton`, causing errors in value retrieval. + // The information of `range.position` in the docSelectionManagerService does not match the `Skeleton`, causing errors in value retrieval. // To address this issue, adding useMemo here to only retrieve the range information for the first time to avoid mismatches between the `Skeleton` and `position`. // TODO@GGGPOUND, the business side should not be aware of the timing issue with getDocRanges. - const docRanges = useMemo(() => textSelectionManagerService.getDocRanges(), []); + const docRanges = useMemo(() => docSelectionManagerService.getDocRanges(), []); useEffect(() => { if (!docRanges.length) { diff --git a/packages/docs/src/basics/selection.ts b/packages/docs/src/basics/selection.ts index 71081f1ef49..6c6ca377f67 100644 --- a/packages/docs/src/basics/selection.ts +++ b/packages/docs/src/basics/selection.ts @@ -14,235 +14,6 @@ * limitations under the License. */ -import type { IDocumentBody, ITextRange, Nullable } from '@univerjs/core'; -import { DataStreamTreeTokenType } from '@univerjs/core'; -import { DeleteDirection } from '../types/enums/delete-direction'; -import { isCustomRangeSplitSymbol } from './custom-range'; - -export function makeSelection(startOffset: number, endOffset?: number): ITextRange { - if (typeof endOffset === 'undefined') { - return { startOffset, endOffset: startOffset, collapsed: true }; - } - - if (endOffset < startOffset) { - throw new Error(`Cannot make a doc selection when endOffset ${endOffset} is less than startOffset ${startOffset}.`); - } - - return { startOffset, endOffset, collapsed: startOffset === endOffset }; -} - -export function normalizeSelection(selection: ITextRange): ITextRange { - const { startOffset, endOffset, collapsed } = selection; - const start = Math.min(startOffset, endOffset); - const end = Math.max(startOffset, endOffset); - - return { - startOffset: start, - endOffset: end, - collapsed, - }; -} - -export function getSelectionWithSymbolMax(selection: ITextRange, body: IDocumentBody) { - let { startOffset, endOffset } = normalizeSelection(selection); - while (body.dataStream[startOffset - 1] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { - startOffset -= 1; - } - - while (body.dataStream[endOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { - endOffset += 1; - } - - return { - startOffset, - endOffset, - }; -} - -export function getSelectionWithNoSymbolSide(selection: ITextRange, body: IDocumentBody) { - let { startOffset, endOffset } = normalizeSelection(selection); - while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { - startOffset += 1; - } - - while (isCustomRangeSplitSymbol(body.dataStream[endOffset - 1])) { - endOffset -= 1; - } - - return { - startOffset, - endOffset, - }; -} - -export function getDeleteSelection(selection: T, body: IDocumentBody, direction = DeleteDirection.LEFT): T { - let { startOffset, endOffset, collapsed } = normalizeSelection(selection); - - if (collapsed) { - if (direction === DeleteDirection.LEFT) { - while (isCustomRangeSplitSymbol(body.dataStream[startOffset - 1])) { - endOffset -= 1; - startOffset -= 1; - } - } else { - while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { - endOffset += 1; - startOffset += 1; - } - } - } else { - const selectionWithSymbolMax = getSelectionWithSymbolMax(selection, body); - startOffset = selectionWithSymbolMax.startOffset; - endOffset = selectionWithSymbolMax.endOffset; - } - - collapsed = (startOffset === endOffset); - - const customRanges = body.customRanges?.filter((range) => { - if (!range.wholeEntity) { - return false; - } - if (startOffset <= range.startIndex && endOffset > range.endIndex) { - return false; - } - return isSegmentIntersects(startOffset, collapsed ? endOffset : endOffset - 1, range.startIndex, range.endIndex); - }); - - if (customRanges?.length) { - customRanges.forEach((range) => { - startOffset = Math.min(range.startIndex, startOffset); - endOffset = Math.max(range.endIndex + 1, endOffset); - }); - } - - return { - ...selection, - startOffset, - endOffset, - collapsed: startOffset === endOffset, - }; -} - -export function getInsertSelection(selection: T, body: IDocumentBody): T { - let { startOffset, endOffset, collapsed } = normalizeSelection(selection); - - if (collapsed) { - while (body.dataStream[endOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { - endOffset += 1; - startOffset += 1; - } - - while (body.dataStream[endOffset - 1] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { - endOffset -= 1; - startOffset -= 1; - } - - return { - ...selection, - startOffset, - endOffset, - collapsed, - }; - } else { - return { - ...selection, - ...getSelectionWithSymbolMax(selection, body), - collapsed: false, - }; - } -} - -/** - * Ensure custom-range has a correct order, - * when range contains range, it won't be present as intersect.
- * For Example `\s1\s2 text \s1\s2` is not allowed, expect `\s1\s2 text \s2\s1` - */ -export function getSelectionForAddCustomRange(selection: ITextRange, body: IDocumentBody): Nullable { - if (selection.startOffset === selection.endOffset) { - return null; - } - - const customRanges = body.customRanges; - if (!customRanges) { - return normalizeSelection(selection); - } - - let { startOffset, endOffset } = getSelectionWithSymbolMax(selection, body); - while (isCustomRangeSplitSymbol(body.dataStream[startOffset])) { - if (body.dataStream[startOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_START) { - const customRange = customRanges.find((range) => range.startIndex === startOffset); - if (!customRange) { - throw new Error('No custom-range matched'); - } - if (customRange.endIndex === endOffset - 1) { - return { - startOffset, - endOffset, - collapsed: false, - }; - } else if (customRange.endIndex < endOffset - 1) { - break; - } - } - - startOffset += 1; - } - - while (isCustomRangeSplitSymbol(body.dataStream[endOffset - 1])) { - if (body.dataStream[startOffset] === DataStreamTreeTokenType.CUSTOM_RANGE_END) { - const customRange = customRanges.find((range) => range.endIndex === endOffset - 1); - if (!customRange) { - throw new Error('No custom-range matched'); - } - - // but actually not possible - if (customRange.startIndex === startOffset) { - return { - startOffset, - endOffset, - collapsed: false, - }; - } else if (customRange.startIndex > startOffset) { - break; - } - } - endOffset -= 1; - } - - if (endOffset <= startOffset) { - return null; - } - - return { - startOffset, - endOffset, - collapsed: false, - }; -} -const tags = [ - DataStreamTreeTokenType.PARAGRAPH, // 段落 - DataStreamTreeTokenType.SECTION_BREAK, // 章节 - DataStreamTreeTokenType.TABLE_START, // 表格开始 - DataStreamTreeTokenType.TABLE_ROW_START, // 表格开始 - DataStreamTreeTokenType.TABLE_CELL_START, // 表格开始 - DataStreamTreeTokenType.TABLE_CELL_END, // 表格开始 - DataStreamTreeTokenType.TABLE_ROW_END, // 表格开始 - DataStreamTreeTokenType.TABLE_END, // 表格结束 - DataStreamTreeTokenType.CUSTOM_RANGE_START, // 自定义范围开始 - DataStreamTreeTokenType.CUSTOM_RANGE_END, // 自定义范围结束 - DataStreamTreeTokenType.COLUMN_BREAK, // 换列 - DataStreamTreeTokenType.PAGE_BREAK, // 换页 - DataStreamTreeTokenType.DOCS_END, // 文档结尾 - DataStreamTreeTokenType.TAB, // 制表符 - DataStreamTreeTokenType.CUSTOM_BLOCK, // 图片 mention 等不参与文档流的场景 - -]; -export function getSelectionText(dataStream: string, start: number, end: number) { - const text = dataStream.slice(start, end); - return tags.reduce((res, curr) => res.replaceAll(curr, ''), text); -} - export function isSegmentIntersects(start: number, end: number, start2: number, end2: number) { return Math.max(start, start2) <= Math.min(end, end2); } - diff --git a/packages/docs/src/commands/commands/__tests__/mock-text-selection-render-manager.ts b/packages/docs/src/commands/commands/__tests__/mock-text-selection-render-manager.ts deleted file mode 100644 index f9420a064d7..00000000000 --- a/packages/docs/src/commands/commands/__tests__/mock-text-selection-render-manager.ts +++ /dev/null @@ -1,38 +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 type { Nullable } from '@univerjs/core'; -import type { ITextSelectionInnerParam } from '@univerjs/engine-render'; -import { createIdentifier } from '@univerjs/core'; -import { BehaviorSubject } from 'rxjs'; - -export class TextSelectionRenderManager { - private readonly _textSelectionInner$ = new BehaviorSubject>(null); - - readonly textSelectionInner$ = this._textSelectionInner$.asObservable(); - - removeAllRanges() { - // empty - } - - addDocRanges() { - // empty - } -} - -export const ITextSelectionRenderManager = createIdentifier( - 'mock.univer.doc.text-selection-render-manager' -); diff --git a/packages/docs/src/commands/mutations/core-editing.mutation.ts b/packages/docs/src/commands/mutations/core-editing.mutation.ts index b73a42976a8..0073ff5271e 100644 --- a/packages/docs/src/commands/mutations/core-editing.mutation.ts +++ b/packages/docs/src/commands/mutations/core-editing.mutation.ts @@ -17,11 +17,10 @@ import { CommandType, IUniverInstanceService, JSONX } from '@univerjs/core'; import type { IMutation, IMutationCommonParams, JSONXActions, Nullable } from '@univerjs/core'; import { IRenderManagerService, type ITextRangeWithStyle } from '@univerjs/engine-render'; -import { serializeDocRange, TextSelectionManagerService } from '../../services/text-selection-manager.service'; -import type { IDocStateChangeParams } from '../../services/doc-state-change-manager.service'; -import { DocStateChangeManagerService } from '../../services/doc-state-change-manager.service'; -import { IMEInputManagerService } from '../../services/ime-input-manager.service'; +import { DocSelectionManagerService } from '../../services/doc-selection-manager.service'; import { DocSkeletonManagerService } from '../../services/doc-skeleton-manager.service'; +import type { IDocStateChangeInfo } from '../../services/doc-state-emit.service'; +import { DocStateEmitService } from '../../services/doc-state-emit.service'; export interface IRichTextEditingMutationParams extends IMutationCommonParams { unitId: string; @@ -48,7 +47,6 @@ export const RichTextEditingMutation: IMutation { const { unitId, @@ -64,6 +62,7 @@ export const RichTextEditingMutation: IMutation { - textSelectionManagerService.replaceTextRanges(textRanges, true, params.options); + docSelectionManagerService.replaceTextRanges(textRanges, true, params.options); }); } // Step 4: Emit state change event. - const changeState: IDocStateChangeParams = { + const changeState: IDocStateChangeInfo = { commandId: RichTextEditingMutationId, unitId, segmentId, @@ -120,30 +113,16 @@ export const RichTextEditingMutation: IMutation { this._injector.get(ICommandService).registerCommand(command); @@ -161,21 +73,9 @@ export class UniverDocsPlugin extends Plugin { ( [ // services - [DocStateChangeManagerService], - [IMEInputManagerService], - [ - ITextSelectionRenderManager, - { - useClass: TextSelectionRenderManager, - }, - ], - [TextSelectionManagerService], - [DocAutoFormatService], - + [DocSelectionManagerService], + [DocStateEmitService], // controllers - [NormalInputController], - [IMEInputController], - [MoveCursorController], [DocCustomRangeController], ] as Dependency[] diff --git a/packages/docs/src/index.ts b/packages/docs/src/index.ts index 6934083342a..aa8138890da 100644 --- a/packages/docs/src/index.ts +++ b/packages/docs/src/index.ts @@ -14,105 +14,23 @@ * limitations under the License. */ -export { getParagraphsInRange, getParagraphsInRanges, findNearestSectionBreak } from './commands/commands/list.command'; -export { replaceSelectionFactory } from './basics/replace'; -export { makeSelection, getSelectionText, getDeleteSelection, getInsertSelection, isSegmentIntersects } from './basics/selection'; -export { hasParagraphInTable } from './basics/paragraph'; -export type { IDocObjectParam } from './basics/component-tools'; -export { getDocObject, neoGetDocObject, getDocObjectById } from './basics/component-tools'; -export * from './basics/docs-view-key'; +export { isSegmentIntersects } from './basics/selection'; +export { type IUniverDocsConfig, UniverDocsPlugin } from './doc-plugin'; -export { UniverDocsPlugin } from './doc-plugin'; +export { DocInterceptorService } from './services/doc-interceptor/doc-interceptor.service'; +export { DOC_INTERCEPTOR_POINT } from './services/doc-interceptor/interceptor-const'; export { DocSkeletonManagerService } from './services/doc-skeleton-manager.service'; -export { TextSelectionManagerService, serializeDocRange } from './services/text-selection-manager.service'; -export { DocStateChangeManagerService, type IDocStateChangeParams } from './services/doc-state-change-manager.service'; -export { IMEInputManagerService } from './services/ime-input-manager.service'; +export { DocSelectionManagerService } from './services/doc-selection-manager.service'; +export type { IDocStateChangeParams, IDocStateChangeInfo } from './services/doc-state-emit.service'; +export { DocStateEmitService } from './services/doc-state-emit.service'; // #region - all commands - -export { BreakLineCommand } from './commands/commands/break-line.command'; -export { CutContentCommand, InnerPasteCommand } from './commands/commands/clipboard.inner.command'; -export { - InsertCommand, - DeleteCommand, - UpdateCommand, - EditorInsertTextCommandId, - type ICoverCommandParams, - type IDeleteCommandParams, - type IInsertCommandParams, - type IUpdateCommandParams, -} from './commands/commands/core-editing.command'; -export { DeleteLeftCommand, DeleteRightCommand, DeleteCustomBlockCommand, MergeTwoParagraphCommand, type IDeleteCustomBlockParams } from './commands/commands/delete.command'; -export { IMEInputCommand, type IIMEInputCommandParams } from './commands/commands/ime-input.command'; -export { - SetInlineFormatBoldCommand, - SetInlineFormatItalicCommand, - SetInlineFormatUnderlineCommand, - SetInlineFormatStrikethroughCommand, - SetInlineFormatSubscriptCommand, - SetInlineFormatSuperscriptCommand, - SetInlineFormatFontSizeCommand, - SetInlineFormatFontFamilyCommand, - SetInlineFormatTextColorCommand, - SetInlineFormatTextBackgroundColorCommand, - ResetInlineFormatTextBackgroundColorCommand, - SetInlineFormatCommand, -} from './commands/commands/inline-format.command'; -export { - ListOperationCommand, - BulletListCommand, - OrderListCommand, - ChangeListNestingLevelCommand, - ChangeListTypeCommand, - CheckListCommand, - ToggleCheckListCommand, - QuickListCommand, -} from './commands/commands/list.command'; -export { - AlignOperationCommand, - AlignLeftCommand, - AlignCenterCommand, - AlignRightCommand, - AlignJustifyCommand, -} from './commands/commands/paragraph-align.command'; -export { ReplaceContentCommand, CoverContentCommand } from './commands/commands/replace-content.command'; -export { SetDocZoomRatioCommand } from './commands/commands/set-doc-zoom-ratio.command'; -export { AfterSpaceCommand, TabCommand, EnterCommand, type ITabCommandParams } from './commands/commands/auto-format.command'; export { RichTextEditingMutation, type IRichTextEditingMutationParams, } from './commands/mutations/core-editing.mutation'; -export { MoveCursorOperation, MoveSelectionOperation } from './commands/operations/cursor.operation'; -export { SelectAllOperation } from './commands/operations/select-all.operation'; -export { SetDocZoomRatioOperation, type ISetDocZoomRatioOperationParams } from './commands/operations/set-doc-zoom-ratio.operation'; export { SetTextSelectionsOperation, type ISetTextSelectionsOperationParams, } from './commands/operations/text-selection.operation'; - // #endregion - -export { getRetainAndDeleteFromReplace } from './basics/retain-delete-params'; -export { getRichTextEditPath } from './commands/util'; -export { getPlainTextFormDocument, getPlainTextFormBody } from './basics/plain-text'; -export { addCustomRangeFactory, addCustomRangeBySelectionFactory, deleteCustomRangeFactory } from './basics/custom-range-factory'; -export { addCustomDecorationBySelectionFactory, addCustomDecorationFactory, deleteCustomDecorationFactory } from './basics/custom-decoration-factory'; -export { getCustomRangesInterestsWithRange, copyCustomRange } from './basics/custom-range'; -export { DocInterceptorService } from './services/doc-interceptor/doc-interceptor.service'; -export { DOC_INTERCEPTOR_POINT } from './services/doc-interceptor/interceptor-const'; -export { DocAutoFormatService } from './services/doc-auto-format.service'; -export { ChangeListNestingLevelType } from './commands/commands/list.command'; -export { getCommandSkeleton } from './commands/util'; -export { generateParagraphs } from './commands/commands/break-line.command'; -export type { IInnerCutCommandParams } from './commands/commands/clipboard.inner.command'; -export { getCutActionsFromDocRanges, getCustomBlockIdsInSelections } from './commands/commands/clipboard.inner.command'; -export { CreateDocTableCommand, type ICreateDocTableCommandParams } from './commands/commands/table/doc-table-create.command'; -export { DocTableDeleteRowsCommand, DocTableDeleteColumnsCommand, DocTableDeleteTableCommand } from './commands/commands/table/doc-table-delete.command'; -export type { IDocTableDeleteRowsCommandParams, IDocTableDeleteColumnsCommandParams, IDocTableDeleteTableCommandParams } from './commands/commands/table/doc-table-delete.command'; -export type { IDocTableInsertColumnCommandParams, IDocTableInsertRowCommandParams, IDocTableInsertColumnRightCommandParams, IDocTableInsertRowAboveCommandParams, IDocTableInsertRowBellowCommandParams, IDocTableInsertColumnLeftCommandParams } from './commands/commands/table/doc-table-insert.command'; -export { DocTableInsertColumnCommand, DocTableInsertRowCommand, DocTableInsertColumnRightCommand, DocTableInsertRowAboveCommand, DocTableInsertRowBellowCommand, DocTableInsertColumnLeftCommand } from './commands/commands/table/doc-table-insert.command'; -export type { IDocTableTabCommandParams } from './commands/commands/table/doc-table-tab.command'; -export { DocTableTabCommand } from './commands/commands/table/doc-table-tab.command'; - -export { genTableSource, getEmptyTableRow, getEmptyTableCell, getTableColumn } from './commands/commands/table/table'; -export { getCursorWhenDelete } from './commands/commands/delete.command'; diff --git a/packages/docs/src/services/text-selection-manager.service.ts b/packages/docs/src/services/doc-selection-manager.service.ts similarity index 62% rename from packages/docs/src/services/text-selection-manager.service.ts rename to packages/docs/src/services/doc-selection-manager.service.ts index 109517c7db7..d675909d19c 100644 --- a/packages/docs/src/services/text-selection-manager.service.ts +++ b/packages/docs/src/services/doc-selection-manager.service.ts @@ -17,19 +17,13 @@ import type { Nullable } from '@univerjs/core'; import { ICommandService, RxDisposable } from '@univerjs/core'; import type { - IDocRange, - INodePosition, + IDocSelectionInnerParam, + IRectRangeWithStyle, ISuccinctDocRangeParam, ITextRangeWithStyle, - ITextSelectionInnerParam, - ITextSelectionStyle, - RANGE_DIRECTION, - RectRange, - TextRange, } from '@univerjs/engine-render'; -import { ITextSelectionRenderManager, NORMAL_TEXT_SELECTION_PLUGIN_STYLE } from '@univerjs/engine-render'; -import { BehaviorSubject, takeUntil } from 'rxjs'; - +import { NORMAL_TEXT_SELECTION_PLUGIN_STYLE } from '@univerjs/engine-render'; +import { BehaviorSubject } from 'rxjs'; import { SetTextSelectionsOperation } from '../commands/operations/text-selection.operation'; interface IDocSelectionManagerSearchParam { @@ -37,42 +31,22 @@ interface IDocSelectionManagerSearchParam { subUnitId: string; } -export interface ITextActiveRange { - startOffset: number; - endOffset: number; - collapsed: boolean; - startNodePosition: Nullable; - endNodePosition: Nullable; - direction: RANGE_DIRECTION; - segmentId: string; - style: ITextSelectionStyle; - segmentPage: number; -} - -interface ITextSelectionManagerInsertParam extends IDocSelectionManagerSearchParam, ITextSelectionInnerParam {} - -type ITextSelectionInfo = Map>; - -export function serializeDocRange(textRange: IDocRange): ITextRangeWithStyle { - const { startOffset, endOffset, collapsed, rangeType } = textRange; - const serializedTextRange: ITextRangeWithStyle = { - startOffset: startOffset!, - endOffset: endOffset!, - collapsed, - rangeType, +export interface IRefreshSelectionParam extends IDocSelectionManagerSearchParam { + docRanges: ISuccinctDocRangeParam[]; + isEditing: boolean; + options?: { + [key: string]: boolean; }; +} - if (typeof textRange.isActive === 'function') { - serializedTextRange.isActive = textRange.isActive(); - } +interface ITextSelectionManagerInsertParam extends IDocSelectionManagerSearchParam, IDocSelectionInnerParam {} - return serializedTextRange; -} +type ITextSelectionInfo = Map>; /** * This service is for text selection. */ -export class TextSelectionManagerService extends RxDisposable { +export class DocSelectionManagerService extends RxDisposable { private _currentSelection: Nullable = null; private readonly _textSelectionInfo: ITextSelectionInfo = new Map(); @@ -80,13 +54,13 @@ export class TextSelectionManagerService extends RxDisposable { private readonly _textSelection$ = new BehaviorSubject>(null); readonly textSelection$ = this._textSelection$.asObservable(); + private readonly _refreshSelection$ = new BehaviorSubject>(null); + readonly refreshSelection$ = this._refreshSelection$.asObservable(); + constructor( - @ITextSelectionRenderManager private _textSelectionRenderManager: ITextSelectionRenderManager, @ICommandService private readonly _commandService: ICommandService ) { super(); - - this._syncSelectionFromRenderService(); } getCurrentSelection() { @@ -94,14 +68,13 @@ export class TextSelectionManagerService extends RxDisposable { } // Get textRanges, style, segmentId + /** + * @deprecated + */ getCurrentSelectionInfo() { return this._getTextRanges(this._currentSelection); } - override dispose(): void { - this._textSelection$.complete(); - } - refreshSelection() { if (this._currentSelection == null) { return; @@ -113,18 +86,33 @@ export class TextSelectionManagerService extends RxDisposable { // **Only used in test case** because this does not go through the render layer. setCurrentSelection(param: IDocSelectionManagerSearchParam) { this._currentSelection = param; + this._refresh(param); } setCurrentSelectionNotRefresh(param: IDocSelectionManagerSearchParam) { - this._currentSelection = param; + const { unitId, subUnitId } = this._currentSelection ?? {}; + const { unitId: newUnitId, subUnitId: newSubUnitId } = param; + + if (unitId !== newUnitId || subUnitId !== newSubUnitId) { + if (unitId && subUnitId) { + this._refreshSelection$.next({ + unitId, + subUnitId, + docRanges: [], + isEditing: false, + }); + } + + this._currentSelection = param; + } } - getCurrentTextRanges(): Readonly> { + getCurrentTextRanges(): Readonly> { return this._getTextRanges(this._currentSelection)?.textRanges; } - getCurrentRectRanges(): Readonly> { + getCurrentRectRanges(): Readonly> { return this._getTextRanges(this._currentSelection)?.rectRanges; } @@ -147,67 +135,40 @@ export class TextSelectionManagerService extends RxDisposable { return allRanges; } - getActiveTextRange(): Nullable { + getActiveTextRange(): Nullable { const selectionInfo = this._getTextRanges(this._currentSelection); if (selectionInfo == null) { return; } const { textRanges } = selectionInfo; - return textRanges.find((textRange) => textRange.isActive()); - } - getActiveRectRange(): Nullable { - const selectionInfo = this._getTextRanges(this._currentSelection); - if (selectionInfo == null) { - return; - } - - const { rectRanges } = selectionInfo; - return rectRanges.find((rectRange) => rectRange.isActive()); + return textRanges.find((textRange) => textRange.isActive); } - getActiveTextRangeWithStyle(): Nullable { + /** + * + * @deprecated + */ + getActiveRectRange(): Nullable { const selectionInfo = this._getTextRanges(this._currentSelection); if (selectionInfo == null) { return; } - const { textRanges, segmentId, style, segmentPage } = selectionInfo; - const activeTextRange = textRanges.find((textRange) => textRange.isActive()); - - if (activeTextRange == null) { - return null; - } - - const { startOffset, endOffset, collapsed, startNodePosition, endNodePosition, direction } = activeTextRange; - - if (startOffset == null || endOffset == null) { - return null; - } - - return { - startOffset, - endOffset, - collapsed, - startNodePosition, - endNodePosition, - direction, - segmentId, - segmentPage, - style, - }; + const { rectRanges } = selectionInfo; + return rectRanges.find((rectRange) => rectRange.isActive); } // **Only used in test case** because this does not go through the render layer. - add(textRanges: ISuccinctDocRangeParam[], isEditing = true) { + add(textRanges: ITextRangeWithStyle[], isEditing = true) { if (this._currentSelection == null) { return; } this._addByParam({ ...this._currentSelection, - textRanges: textRanges as TextRange[], + textRanges, rectRanges: [], segmentId: '', segmentPage: -1, @@ -222,25 +183,20 @@ export class TextSelectionManagerService extends RxDisposable { } // Remove all textRanges. - this._textSelectionRenderManager.removeAllRanges(); // Add new textRanges. - this._textSelectionRenderManager.addDocRanges(docRanges, isEditing, options); - } - // All textRanges should be synchronized from the render layer. - private _syncSelectionFromRenderService() { - this._textSelectionRenderManager.textSelectionInner$ - .pipe(takeUntil(this.dispose$)) - .subscribe((params) => { - if (params == null) { - return; - } + const { unitId, subUnitId } = this._currentSelection; - this._replaceTextRangesWithNoRefresh(params); - }); + this._refreshSelection$.next({ + unitId, + subUnitId, + docRanges, + isEditing, + options, + }); } - private _replaceTextRangesWithNoRefresh(textSelectionInfo: ITextSelectionInnerParam) { + replaceTextRangesWithNoRefresh(textSelectionInfo: IDocSelectionInnerParam) { if (this._currentSelection == null) { return; } @@ -268,8 +224,7 @@ export class TextSelectionManagerService extends RxDisposable { } else { return 0; } - }) - .map(serializeDocRange); + }); // For menu status. this._commandService.executeCommand(SetTextSelectionsOperation.id, { @@ -282,6 +237,10 @@ export class TextSelectionManagerService extends RxDisposable { }); } + override dispose(): void { + this._textSelection$.complete(); + } + private _getTextRanges(param: Nullable) { if (param == null) { return; @@ -295,9 +254,6 @@ export class TextSelectionManagerService extends RxDisposable { private _refresh(param: IDocSelectionManagerSearchParam): void { const allTextSelectionInfo = this._getTextRanges(param); - // Remove all textRanges. - this._textSelectionRenderManager.removeAllRanges(); - if (allTextSelectionInfo == null) { return; } @@ -306,13 +262,18 @@ export class TextSelectionManagerService extends RxDisposable { const docRanges = [...textRanges, ...rectRanges]; - if (docRanges.length > 0) { - this._textSelectionRenderManager.addDocRanges(docRanges.map(serializeDocRange), false); - } + const { unitId, subUnitId } = param; + + this._refreshSelection$.next({ + unitId, + subUnitId, + docRanges, + isEditing: false, + }); } private _replaceByParam(insertParam: ITextSelectionManagerInsertParam) { - const { unitId, subUnitId, style, segmentId, textRanges, rectRanges, isEditing, segmentPage } = insertParam; + const { unitId, subUnitId, ...selectionInsertParam } = insertParam; if (!this._textSelectionInfo.has(unitId)) { this._textSelectionInfo.set(unitId, new Map()); @@ -320,11 +281,11 @@ export class TextSelectionManagerService extends RxDisposable { const unitTextRange = this._textSelectionInfo.get(unitId)!; - unitTextRange.set(subUnitId, { textRanges, rectRanges, style, segmentId, isEditing, segmentPage }); + unitTextRange.set(subUnitId, { ...selectionInsertParam }); } private _addByParam(insertParam: ITextSelectionManagerInsertParam): void { - const { unitId, subUnitId, textRanges, rectRanges, style, segmentId, isEditing, segmentPage } = insertParam; + const { unitId, subUnitId, ...selectionInsertParam } = insertParam; if (!this._textSelectionInfo.has(unitId)) { this._textSelectionInfo.set(unitId, new Map()); @@ -333,10 +294,10 @@ export class TextSelectionManagerService extends RxDisposable { const unitTextRange = this._textSelectionInfo.get(unitId)!; if (!unitTextRange.has(subUnitId)) { - unitTextRange.set(subUnitId, { textRanges, rectRanges, style, segmentId, isEditing, segmentPage }); + unitTextRange.set(subUnitId, { ...selectionInsertParam }); } else { const OldTextRanges = unitTextRange.get(subUnitId)!; - OldTextRanges.textRanges.push(...textRanges); + OldTextRanges.textRanges.push(...insertParam.textRanges); } } } diff --git a/packages/docs/src/services/doc-state-emit.service.ts b/packages/docs/src/services/doc-state-emit.service.ts new file mode 100644 index 00000000000..307f4709c98 --- /dev/null +++ b/packages/docs/src/services/doc-state-emit.service.ts @@ -0,0 +1,59 @@ +/** + * 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 type { JSONXActions, Nullable } from '@univerjs/core'; +import { RxDisposable } from '@univerjs/core'; +import type { ITextRangeWithStyle } from '@univerjs/engine-render'; +import { BehaviorSubject } from 'rxjs'; + +interface IDocChangeState { + actions: JSONXActions; + textRanges: Nullable; +} + +export interface IDocStateChangeParams { + commandId: string; + unitId: string; + trigger: Nullable; + redoState: IDocChangeState; + undoState: IDocChangeState; + segmentId?: string; + noHistory?: boolean; + debounce?: boolean; +} + +export interface IDocStateChangeInfo extends IDocStateChangeParams { + isCompositionEnd?: boolean; +} + +export class DocStateEmitService extends RxDisposable { + private readonly _docStateChangeParams$ = new BehaviorSubject>(null); + readonly docStateChangeParams$ = this._docStateChangeParams$.asObservable(); + + constructor() { + super(); + } + + emitStateChangeInfo(params: IDocStateChangeInfo) { + this._docStateChangeParams$.next(params); + } + + override dispose(): void { + super.dispose(); + + this._docStateChangeParams$.complete(); + } +} diff --git a/packages/engine-render/src/basics/range.ts b/packages/engine-render/src/basics/range.ts index 9888cec0fe4..31adf74a332 100644 --- a/packages/engine-render/src/basics/range.ts +++ b/packages/engine-render/src/basics/range.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import type { ITextRangeParam } from '@univerjs/core'; -import type { DOC_RANGE_TYPE } from '../components/docs/text-selection/range-interface'; +import type { ITextRangeParam, Nullable } from '@univerjs/core'; +import type { INodePosition } from './interfaces'; export interface ITextSelectionStyle { strokeWidth: number; @@ -32,22 +32,31 @@ export const NORMAL_TEXT_SELECTION_PLUGIN_STYLE: ITextSelectionStyle = { }; export interface ITextRangeWithStyle extends ITextRangeParam { + startNodePosition?: Nullable; + endNodePosition?: Nullable; style?: ITextSelectionStyle; - rangeType?: DOC_RANGE_TYPE; } -// Only use in add/replaceTextRanges methods. -export interface ISuccinctDocRangeParam { - startOffset: number; - endOffset: number; - segmentId?: string; // Header of footer id. - segmentPage?: number; // Optional, because header and footer are in different pages, so need pageIndex to allocate selection in header or footer. - style?: ITextSelectionStyle; - rangeType?: DOC_RANGE_TYPE; +export interface IRectRangeWithStyle extends ITextRangeWithStyle { + startRow: number; + startColumn: number; + endRow: number; + endColumn: number; + tableId: string; + spanEntireRow: boolean; + spanEntireColumn: boolean; + spanEntireTable: boolean; } -export enum RANGE_DIRECTION { - NONE = 'none', - BACKWARD = 'backward', - FORWARD = 'forward', +// Only use in add/replaceTextRanges methods. +export type ISuccinctDocRangeParam = Pick; + +export interface IDocSelectionInnerParam { + textRanges: ITextRangeWithStyle[]; + rectRanges: IRectRangeWithStyle[]; + segmentId: string; + isEditing: boolean; + style: ITextSelectionStyle; + segmentPage: number; + options?: { [key: string]: boolean }; } diff --git a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts index e70cd329d50..8a310d12a71 100644 --- a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts +++ b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts @@ -30,9 +30,8 @@ import { Skeleton } from '../../skeleton'; import { Liquid } from '../liquid'; import type { DocumentViewModel } from '../view-model/document-view-model'; import { DocumentEditArea } from '../view-model/document-view-model'; -import { getPageFromPath } from '../text-selection/convert-text-range'; +import { getLastPage, getNullSkeleton, getPageFromPath, prepareSectionBreakConfig, resetContext, setPageParent, updateBlockIndex, updateInlineDrawingCoords } from './tools'; import type { ILayoutContext } from './tools'; -import { getLastPage, getNullSkeleton, prepareSectionBreakConfig, resetContext, setPageParent, updateBlockIndex, updateInlineDrawingCoords } from './tools'; import { createSkeletonSection } from './model/section'; import { dealWithSection } from './block/section'; import { createSkeletonPage } from './model/page'; diff --git a/packages/engine-render/src/components/docs/layout/tools.ts b/packages/engine-render/src/components/docs/layout/tools.ts index 95059c45154..25194238fb8 100644 --- a/packages/engine-render/src/components/docs/layout/tools.ts +++ b/packages/engine-render/src/components/docs/layout/tools.ts @@ -1094,3 +1094,27 @@ export function mergeByV(object: unknown, originObject: unknown, ty }; return Tools.mergeWith(object, originObject, mergeIterator) as T; } + +export function getPageFromPath(skeletonData: IDocumentSkeletonCached, path: (string | number)[]): Nullable { + const pathCopy = [...path]; + let page: Nullable = null; + + while (pathCopy.length > 0) { + const field = pathCopy.shift(); + + if (field === 'pages') { + const pageIndex = pathCopy.shift() as number; + page = skeletonData.pages[pageIndex]; + } else if (field === 'skeTables') { + const tableId = pathCopy.shift() as string; + pathCopy.shift(); // rows + const rowIndex = pathCopy.shift() as number; + pathCopy.shift(); // cells + const cellIndex = pathCopy.shift() as number; + + page = page!.skeTables?.get(tableId)?.rows[rowIndex]?.cells[cellIndex]; + } + } + + return page; +} diff --git a/packages/engine-render/src/index.ts b/packages/engine-render/src/index.ts index 9c5c8d9f4e6..65f1ad2615b 100644 --- a/packages/engine-render/src/index.ts +++ b/packages/engine-render/src/index.ts @@ -33,30 +33,20 @@ export * from './shape'; export * from './viewport'; export { DocumentViewModel } from './components/docs/view-model/document-view-model'; -export { getAnchorBounding, TEXT_RANGE_LAYER_INDEX, TextRange, getLineBounding } from './components/docs/text-selection/text-range'; -export { RectRange, convertPositionsToRectRanges } from './components/docs/text-selection/rect-range'; -export { NodePositionConvertToCursor } from './components/docs/text-selection/convert-text-range'; export { Liquid } from './components/docs/liquid'; -export { getCanvasOffsetByEngine } from './components/docs/text-selection/selection-utils'; -export { - ITextSelectionRenderManager, - TextSelectionRenderManager, -} from './components/docs/text-selection/text-selection-render-manager'; -export type { IActiveTextRange, IEditorInputConfig, ITextSelectionInnerParam } from './components/docs/text-selection/text-selection-render-manager'; export { Documents } from './components/docs/document'; export { DocBackground } from './components/docs/doc-background'; export type { IPageRenderConfig } from './components/docs/document'; export { DocumentSkeleton } from './components/docs/layout/doc-skeleton'; export { ThinEngine } from './thin-engine'; -export { getCharSpaceApply, getNumberUnitValue } from './components/docs/layout/tools'; export { type IChangeObserverConfig } from './scene.transformer'; export { DEFAULT_PADDING_DATA } from './components/sheets/sheet-skeleton'; export { DocumentEditArea } from './components/docs/view-model/document-view-model'; -export { lineIterator, glyphIterator } from './components/docs/layout/tools'; -export { getOneTextSelectionRange } from './components/docs/text-selection/convert-text-range'; -export { getLastLine } from './components/docs/layout/tools'; +export { lineIterator, glyphIterator, getPageFromPath, getLastLine, getNumberUnitValue, getCharSpaceApply } from './components/docs/layout/tools'; export { DataStreamTreeNode } from './components/docs/view-model/data-stream-tree-node'; -export type { IDocRange } from './components/docs/text-selection/range-interface'; -export { isInSameTableCell, isValidRectRange, NodePositionConvertToRectRange } from './components/docs/text-selection/convert-rect-range'; export { parseDataStreamToTree } from './components/docs/view-model/document-view-model'; -export { DOC_RANGE_TYPE } from './components/docs/text-selection/range-interface'; +export type { IDocumentOffsetConfig } from './components/docs/document'; +export { getTableIdAndSliceIndex } from './components/docs/layout/block/table'; +export { ThinScene } from './thin-scene'; +export { getOffsetRectForDom } from './basics/position'; +export type { IFindNodeRestrictions } from './components/docs/layout/doc-skeleton'; diff --git a/packages/facade/package.json b/packages/facade/package.json index 908a3a01f33..9f5ca71f672 100644 --- a/packages/facade/package.json +++ b/packages/facade/package.json @@ -62,7 +62,7 @@ "peerDependencies": { "@univerjs/core": "workspace:*", "@univerjs/data-validation": "workspace:*", - "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/network": "workspace:*", diff --git a/packages/facade/src/apis/docs/__tests__/create-test-bed.ts b/packages/facade/src/apis/docs/__tests__/create-test-bed.ts index d2a5f2da99e..7e01a9880e5 100644 --- a/packages/facade/src/apis/docs/__tests__/create-test-bed.ts +++ b/packages/facade/src/apis/docs/__tests__/create-test-bed.ts @@ -28,9 +28,9 @@ import { } from '@univerjs/core'; import enUS from '@univerjs/sheets-formula/locale/en-US'; import zhCN from '@univerjs/sheets-formula/locale/zh-CN'; -import { DocSkeletonManagerService, DocStateChangeManagerService, IMEInputManagerService, TextSelectionManagerService } from '@univerjs/docs'; -import { IRenderManagerService, ITextSelectionRenderManager, RenderManagerService, TextSelectionRenderManager } from '@univerjs/engine-render'; -import { DocsRenderService } from '@univerjs/docs-ui'; +import { DocSelectionManagerService, DocSkeletonManagerService, DocStateEmitService } from '@univerjs/docs'; +import { IRenderManagerService, RenderManagerService } from '@univerjs/engine-render'; +import { DocIMEInputManagerService, DocsRenderService, DocStateChangeManagerService } from '@univerjs/docs-ui'; import { FUniver } from '../../facade'; @@ -77,16 +77,16 @@ export function createTestBed(documentConfig?: IDocumentData, dependencies?: Dep override onStarting(): void { const injector = this._injector; injector.add([IRenderManagerService, { useClass: RenderManagerService }]); - injector.add([TextSelectionManagerService]); + injector.add([DocSelectionManagerService]); + injector.add([DocStateEmitService]); injector.add([DocStateChangeManagerService]); - injector.add([IMEInputManagerService]); injector.add([DocsRenderService]); - injector.add([ITextSelectionRenderManager, { useClass: TextSelectionRenderManager }]); dependencies?.forEach((d) => injector.add(d)); const renderManagerService = injector.get(IRenderManagerService); renderManagerService.registerRenderModule(UniverInstanceType.UNIVER_DOC, [DocSkeletonManagerService] as Dependency); + renderManagerService.registerRenderModule(UniverInstanceType.UNIVER_DOC, [DocIMEInputManagerService] as Dependency); } } diff --git a/packages/facade/src/apis/docs/__tests__/f-document.spec.ts b/packages/facade/src/apis/docs/__tests__/f-document.spec.ts index 87e34b1fffb..c864985543d 100644 --- a/packages/facade/src/apis/docs/__tests__/f-document.spec.ts +++ b/packages/facade/src/apis/docs/__tests__/f-document.spec.ts @@ -18,7 +18,8 @@ import { ICommandService } from '@univerjs/core'; import type { Injector } from '@univerjs/core'; import { beforeEach, describe, expect, it } from 'vitest'; -import { InsertCommand, RichTextEditingMutation } from '@univerjs/docs'; +import { RichTextEditingMutation } from '@univerjs/docs'; +import { InsertCommand } from '@univerjs/docs-ui'; import type { FUniver } from '../../facade'; import { createTestBed } from './create-test-bed'; diff --git a/packages/facade/src/apis/docs/f-document.ts b/packages/facade/src/apis/docs/f-document.ts index a26bcbee674..430b244346a 100644 --- a/packages/facade/src/apis/docs/f-document.ts +++ b/packages/facade/src/apis/docs/f-document.ts @@ -15,7 +15,7 @@ */ import type { DocumentDataModel, IDocumentData } from '@univerjs/core'; -import { ICommandService, +import { DOC_RANGE_TYPE, ICommandService, Inject, Injector, IResourceManagerService, @@ -24,8 +24,8 @@ import { ICommandService, UndoCommand, UniverInstanceType, } from '@univerjs/core'; -import { InsertCommand } from '@univerjs/docs'; -import { DOC_RANGE_TYPE, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { DocSelectionRenderService, InsertCommand } from '@univerjs/docs-ui'; +import { IRenderManagerService } from '@univerjs/engine-render'; export class FDocument { readonly id: string; @@ -35,7 +35,8 @@ export class FDocument { @Inject(Injector) protected readonly _injector: Injector, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @ICommandService private readonly _commandService: ICommandService, - @IResourceManagerService private readonly _resourceManagerService: IResourceManagerService + @IResourceManagerService private readonly _resourceManagerService: IResourceManagerService, + @IRenderManagerService private readonly _renderManagerService: IRenderManagerService ) { this.id = this._documentDataModel.getUnitId(); } @@ -111,9 +112,10 @@ export class FDocument { * ``` */ setSelection(startOffset: number, endOffset: number): void { - const textSelectionRenderManager = this._injector.get(ITextSelectionRenderManager); - textSelectionRenderManager.removeAllRanges(); - textSelectionRenderManager.addDocRanges( + // TODO: @jocs... + const docSelectionRenderService = this._renderManagerService.getRenderById(this.getId())?.with(DocSelectionRenderService); + docSelectionRenderService?.removeAllRanges(); + docSelectionRenderService?.addDocRanges( [ { startOffset, diff --git a/packages/facade/src/apis/sheets/f-workbook.ts b/packages/facade/src/apis/sheets/f-workbook.ts index 2d30fcb7c79..87f115d2d18 100644 --- a/packages/facade/src/apis/sheets/f-workbook.ts +++ b/packages/facade/src/apis/sheets/f-workbook.ts @@ -38,10 +38,10 @@ import type { ICanvasFloatDom } from '@univerjs/sheets-drawing-ui'; import type { IAddSheetDataValidationCommandParams, IDataValidationResCache, IRemoveSheetAllDataValidationCommandParams, IRemoveSheetDataValidationCommandParams, IUpdateSheetDataValidationOptionsCommandParams, IUpdateSheetDataValidationRangeCommandParams, IUpdateSheetDataValidationSettingCommandParams } from '@univerjs/sheets-data-validation'; import { AddSheetDataValidationCommand, DataValidationModel, RemoveSheetAllDataValidationCommand, RemoveSheetDataValidationCommand, SheetsDataValidationValidatorService, UpdateSheetDataValidationOptionsCommand, UpdateSheetDataValidationRangeCommand, UpdateSheetDataValidationSettingCommand } from '@univerjs/sheets-data-validation'; import type { IRuleChange, IValidStatusChange } from '@univerjs/data-validation'; -import type { IUpdateCommandParams } from '@univerjs/docs'; import type { CommentUpdate, IAddCommentCommandParams, IDeleteCommentCommandParams } from '@univerjs/thread-comment'; import { AddCommentCommand, DeleteCommentCommand, DeleteCommentTreeCommand, ThreadCommentModel, UpdateCommentCommand } from '@univerjs/thread-comment'; import { filter } from 'rxjs'; +import type { IUpdateCommandParams } from '@univerjs/docs-ui'; import type { IFComponentKey } from './utils'; import { FWorksheet } from './f-worksheet'; import { FRange } from './f-range'; diff --git a/packages/sheets-data-validation/package.json b/packages/sheets-data-validation/package.json index 16f997c6d7e..b312182e043 100644 --- a/packages/sheets-data-validation/package.json +++ b/packages/sheets-data-validation/package.json @@ -66,6 +66,7 @@ "@univerjs/data-validation": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/sheets": "workspace:*", @@ -82,6 +83,7 @@ "@univerjs/data-validation": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", diff --git a/packages/sheets-data-validation/src/views/list-dropdown/index.tsx b/packages/sheets-data-validation/src/views/list-dropdown/index.tsx index 9e8355e3672..998aa554693 100644 --- a/packages/sheets-data-validation/src/views/list-dropdown/index.tsx +++ b/packages/sheets-data-validation/src/views/list-dropdown/index.tsx @@ -27,7 +27,8 @@ import { RectPopup, Scrollbar } from '@univerjs/design'; import { DataValidationModel } from '@univerjs/data-validation'; import { debounceTime } from 'rxjs'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; -import { getPlainTextFormDocument, RichTextEditingMutation } from '@univerjs/docs'; +import { RichTextEditingMutation } from '@univerjs/docs'; +import { getPlainTextFormDocument } from '@univerjs/docs-ui'; import type { ListMultipleValidator } from '../../validators/list-multiple-validator'; import { deserializeListOptions, getDataValidationCellValue, serializeListOptions } from '../../validators/util'; import type { IDropdownComponentProps } from '../../services/dropdown-manager.service'; diff --git a/packages/sheets-formula/package.json b/packages/sheets-formula/package.json index f90d416895e..a43e86b42e1 100644 --- a/packages/sheets-formula/package.json +++ b/packages/sheets-formula/package.json @@ -67,6 +67,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/rpc": "workspace:*", @@ -80,6 +81,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", diff --git a/packages/sheets-formula/src/controllers/prompt.controller.ts b/packages/sheets-formula/src/controllers/prompt.controller.ts index f8948878ea3..62cad9335f5 100644 --- a/packages/sheets-formula/src/controllers/prompt.controller.ts +++ b/packages/sheets-formula/src/controllers/prompt.controller.ts @@ -16,16 +16,6 @@ // FIXME: why so many calling to close the editor here? -import type { - DocumentDataModel, - ICommandInfo, - IDisposable, - IRange, - IRangeWithCoord, - ITextRun, - Nullable, - Workbook, -} from '@univerjs/core'; import { AbsoluteRefType, Direction, @@ -50,12 +40,10 @@ import { UniverInstanceType, } from '@univerjs/core'; import { + DocSelectionManagerService, DocSkeletonManagerService, - MoveCursorOperation, - ReplaceContentCommand, - TextSelectionManagerService, } from '@univerjs/docs'; -import type { IAbsoluteRefTypeForRange, ISequenceNode } from '@univerjs/engine-formula'; +import { DocSelectionRenderService, MoveCursorOperation, ReplaceContentCommand } from '@univerjs/docs-ui'; import { compareToken, deserializeRangeWithSheet, @@ -72,11 +60,7 @@ import { import { DeviceInputEventType, IRenderManagerService, - ITextSelectionRenderManager, } from '@univerjs/engine-render'; -import type { - ISelectionWithStyle, -} from '@univerjs/sheets'; import { convertSelectionDataToRange, @@ -86,7 +70,6 @@ import { setEndForRange, SheetsSelectionsService, } from '@univerjs/sheets'; -import type { EditorBridgeService, SelectionShape } from '@univerjs/sheets-ui'; import { ExpandSelectionCommand, getEditorObject, @@ -95,20 +78,35 @@ import { MoveSelectionCommand, SheetSkeletonManagerService, } from '@univerjs/sheets-ui'; -import type { Editor } from '@univerjs/ui'; -import { IContextMenuService, IEditorService, KeyCode, MetaKeys, SetEditorResizeOperation, UNI_DISABLE_CHANGING_FOCUS_KEY } from '@univerjs/ui'; - +import { IContextMenuService, IEditorService, ILayoutService, KeyCode, MetaKeys, SetEditorResizeOperation, UNI_DISABLE_CHANGING_FOCUS_KEY } from '@univerjs/ui'; import { distinctUntilChanged, distinctUntilKeyChanged } from 'rxjs'; -import type { ISelectEditorFormulaOperationParam } from '../commands/operations/editor-formula.operation'; +import type { + DocumentDataModel, + ICommandInfo, + IDisposable, + IRange, + IRangeWithCoord, + ITextRun, + Nullable, + Workbook, +} from '@univerjs/core'; +import type { IAbsoluteRefTypeForRange, ISequenceNode } from '@univerjs/engine-formula'; +import type { + ISelectionWithStyle, +} from '@univerjs/sheets'; + +import type { EditorBridgeService, SelectionShape } from '@univerjs/sheets-ui'; +import type { Editor } from '@univerjs/ui'; import { SelectEditorFormulaOperation } from '../commands/operations/editor-formula.operation'; import { HelpFunctionOperation } from '../commands/operations/help-function.operation'; +import { ReferenceAbsoluteOperation } from '../commands/operations/reference-absolute.operation'; import { SearchFunctionOperation } from '../commands/operations/search-function.operation'; import { META_KEY_CTRL_AND_SHIFT } from '../common/prompt'; import { getFormulaRefSelectionStyle } from '../common/selection'; import { IDescriptionService } from '../services/description.service'; import { IFormulaPromptService } from '../services/prompt.service'; -import { ReferenceAbsoluteOperation } from '../commands/operations/reference-absolute.operation'; import { RefSelectionsRenderService } from '../services/render-services/ref-selections.render-service'; +import type { ISelectEditorFormulaOperationParam } from '../commands/operations/editor-formula.operation'; interface IRefSelection { refIndex: number; @@ -135,6 +133,7 @@ const sheetEditorUnitIds = [DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, DOCS_NORMAL_EDI @OnLifecycle(LifecycleStages.Steady, PromptController) export class PromptController extends Disposable { + private _listenInputCache: Set = new Set(); private _formulaRefColors: string[] = []; private _previousSequenceNodes: Nullable>; @@ -181,7 +180,6 @@ export class PromptController extends Disposable { constructor( @ICommandService private readonly _commandService: ICommandService, @IContextService private readonly _contextService: IContextService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, @Inject(IEditorBridgeService) private readonly _editorBridgeService: EditorBridgeService, @Inject(IFormulaPromptService) private readonly _formulaPromptService: IFormulaPromptService, @Inject(LexerTreeBuilder) private readonly _lexerTreeBuilder: LexerTreeBuilder, @@ -191,9 +189,10 @@ export class PromptController extends Disposable { @IRefSelectionsService private readonly _refSelectionsService: SheetsSelectionsService, @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService, @Inject(IDescriptionService) private readonly _descriptionService: IDescriptionService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _docSelectionManagerService: DocSelectionManagerService, @IContextMenuService private readonly _contextMenuService: IContextMenuService, - @IEditorService private readonly _editorService: IEditorService + @IEditorService private readonly _editorService: IEditorService, + @ILayoutService private readonly _layoutService: ILayoutService ) { super(); @@ -256,7 +255,7 @@ export class PromptController extends Disposable { private _initialCursorSync() { this.disposeWithMe( - this._textSelectionManagerService.textSelection$.subscribe((params) => { + this._docSelectionManagerService.textSelection$.subscribe((params) => { if (params?.unitId == null) { return; } @@ -299,32 +298,56 @@ export class PromptController extends Disposable { private _initialEditorInputChange() { const arrows = [KeyCode.ARROW_DOWN, KeyCode.ARROW_UP, KeyCode.ARROW_LEFT, KeyCode.ARROW_RIGHT, KeyCode.CTRL, KeyCode.SHIFT]; + // TODO: @runzhe Should there be a registration mechanism, rather than a unified process here? + this._univerInstanceService.getCurrentTypeOfUnit$(UniverInstanceType.UNIVER_DOC).subscribe((documentDataModel) => { + const unitId = documentDataModel?.getUnitId(); - this.disposeWithMe( - this._textSelectionRenderManager.onInputBefore$.subscribe((param) => { - this._previousSequenceNodes = null; - this._previousInsertRefStringIndex = null; + if (unitId == null) { + return; + } - this._selectionRenderService.setSkipLastEnabled(true); + if (this._listenInputCache.has(unitId)) { + return; + } - const event = param?.event as KeyboardEvent; - if (!event) return; + const editor = this._editorService.getEditor(unitId); - if (!arrows.includes(event.which)) { - if (this._arrowMoveActionState !== ArrowMoveAction.moveCursor) { - this._arrowMoveActionState = ArrowMoveAction.moveRefReady; - } + if (editor == null) { + return; + } - this._inputPanelState = InputPanelState.keyNormal; - } else { - this._inputPanelState = InputPanelState.keyArrow; - } + const docSelectionRenderService = this._renderManagerService.getRenderById(unitId)?.with(DocSelectionRenderService); - if (event.which !== KeyCode.F4) { - this._userCursorMove = false; - } - }) - ); + if (docSelectionRenderService) { + this.disposeWithMe( + docSelectionRenderService.onInputBefore$.subscribe((param) => { + this._previousSequenceNodes = null; + this._previousInsertRefStringIndex = null; + + this._selectionRenderService.setSkipLastEnabled(true); + + const event = param?.event as KeyboardEvent; + if (!event) return; + + if (!arrows.includes(event.which)) { + if (this._arrowMoveActionState !== ArrowMoveAction.moveCursor) { + this._arrowMoveActionState = ArrowMoveAction.moveRefReady; + } + + this._inputPanelState = InputPanelState.keyNormal; + } else { + this._inputPanelState = InputPanelState.keyArrow; + } + + if (event.which !== KeyCode.F4) { + this._userCursorMove = false; + } + }) + ); + } + + this._listenInputCache.add(unitId); + }); } private _closeRangePromptWhenEditorInvisible() { @@ -510,7 +533,7 @@ export class PromptController extends Disposable { private _initAcceptFormula() { this.disposeWithMe( this._formulaPromptService.acceptFormulaName$.subscribe((formulaString: string) => { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { this._hideFunctionPanel(); @@ -576,7 +599,7 @@ export class PromptController extends Disposable { } private _changeFunctionPanelState() { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { this._hideFunctionPanel(); @@ -675,7 +698,7 @@ export class PromptController extends Disposable { * @returns Return the character under the current cursor in the editor. */ private _getCurrentChar() { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { return; @@ -804,7 +827,7 @@ export class PromptController extends Disposable { this._formulaPromptService.setSequenceNodes(lastSequenceNodes); - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { return; @@ -1206,7 +1229,7 @@ export class PromptController extends Disposable { // Get theme color from prompt formula editor when creating a new selection. this._allSelectionRenderServices.forEach((r) => this._updateRefSelectionStyle(r, this._isSelectionMovingRefSelections)); - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { return; } @@ -1257,7 +1280,7 @@ export class PromptController extends Disposable { options: { fromSelection }, }); // The ReplaceContentCommand has canceled the selection operation, so it needs to be triggered externally once. - this._textSelectionManagerService.replaceTextRanges([ + this._docSelectionManagerService.replaceTextRanges([ { startOffset: textSelectionOffset + 1 - offset, endOffset: textSelectionOffset + 1 - offset, @@ -1266,7 +1289,7 @@ export class PromptController extends Disposable { ], true, { fromSelection }); } else { this._updateEditorModel(`${formulaString}\r\n`, textRuns); - this._textSelectionManagerService.replaceTextRanges([ + this._docSelectionManagerService.replaceTextRanges([ { startOffset: textSelectionOffset + 1 - offset, endOffset: textSelectionOffset + 1 - offset, @@ -1278,9 +1301,7 @@ export class PromptController extends Disposable { /** * After selecting the formula, allow the editor to continue entering content. */ - setTimeout(() => { - this._textSelectionRenderManager.focus(); - }, 0); + this._layoutService.focus(); } private _fitEditorSize() { @@ -1831,7 +1852,7 @@ export class PromptController extends Disposable { * Absolute range, triggered by F4 */ private _changeRefString() { - const activeRange = this._textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = this._docSelectionManagerService.getActiveTextRange(); if (activeRange == null) { return; diff --git a/packages/sheets-formula/src/views/prompt/help-function/HelpFunction.tsx b/packages/sheets-formula/src/views/prompt/help-function/HelpFunction.tsx index a0b9cf19a65..ce3ade4ea37 100644 --- a/packages/sheets-formula/src/views/prompt/help-function/HelpFunction.tsx +++ b/packages/sheets-formula/src/views/prompt/help-function/HelpFunction.tsx @@ -20,8 +20,7 @@ import type { IFunctionInfo, IFunctionParam } from '@univerjs/engine-formula'; import { CloseSingle, DetailsSingle, MoreSingle } from '@univerjs/icons'; import React, { useEffect, useState } from 'react'; -import { IEditorService, ISidebarService } from '@univerjs/ui'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IEditorService, ILayoutService, ISidebarService } from '@univerjs/ui'; import { throttleTime } from 'rxjs'; import type { IHelpFunctionOperationParams } from '../../../services/prompt.service'; import { IFormulaPromptService } from '../../../services/prompt.service'; @@ -123,8 +122,9 @@ export function HelpFunction() { setHelpVisible(!helpVisible); // focus editor - const textSelectionRenderManager = injector.get(ITextSelectionRenderManager); - textSelectionRenderManager.focus(); + // FIXME: @Jocs, still need re focus? + const layoutService = injector.get(ILayoutService); + layoutService.focus(); } return ( diff --git a/packages/sheets-formula/src/views/prompt/search-function/SearchFunction.tsx b/packages/sheets-formula/src/views/prompt/search-function/SearchFunction.tsx index 3792d1f39de..b167c05060e 100644 --- a/packages/sheets-formula/src/views/prompt/search-function/SearchFunction.tsx +++ b/packages/sheets-formula/src/views/prompt/search-function/SearchFunction.tsx @@ -16,13 +16,13 @@ import { Direction, IUniverInstanceService, useDependency } from '@univerjs/core'; import { Popup } from '@univerjs/design'; -import React, { useEffect, useRef, useState } from 'react'; - import { IEditorService } from '@univerjs/ui'; -import type { ISearchItem } from '../../../services/description.service'; -import type { INavigateParam, ISearchFunctionOperationParams } from '../../../services/prompt.service'; + +import React, { useEffect, useRef, useState } from 'react'; import { IFormulaPromptService } from '../../../services/prompt.service'; import styles from './index.module.less'; +import type { ISearchItem } from '../../../services/description.service'; +import type { INavigateParam, ISearchFunctionOperationParams } from '../../../services/prompt.service'; export function SearchFunction() { const [visible, setVisible] = useState(false); diff --git a/packages/sheets-hyper-link-ui/package.json b/packages/sheets-hyper-link-ui/package.json index 821558845ca..c140fed0872 100644 --- a/packages/sheets-hyper-link-ui/package.json +++ b/packages/sheets-hyper-link-ui/package.json @@ -68,6 +68,8 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-hyper-link": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/sheets": "workspace:*", @@ -81,6 +83,8 @@ "dependencies": { "@univerjs/core": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-hyper-link": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", diff --git a/packages/sheets-hyper-link-ui/src/controllers/set-range.controller.ts b/packages/sheets-hyper-link-ui/src/controllers/set-range.controller.ts index 2e8b982b3fd..a74c2ecdd88 100644 --- a/packages/sheets-hyper-link-ui/src/controllers/set-range.controller.ts +++ b/packages/sheets-hyper-link-ui/src/controllers/set-range.controller.ts @@ -20,7 +20,7 @@ import type { ISetRangeValuesMutationParams } from '@univerjs/sheets'; import { ClearSelectionAllCommand, ClearSelectionContentCommand, ClearSelectionFormatCommand, getSheetCommandTarget, SetRangeValuesCommand, SetRangeValuesMutation, SetRangeValuesUndoMutationFactory, SheetInterceptorService, SheetsSelectionsService } from '@univerjs/sheets'; import { AddHyperLinkMutation, HyperLinkModel, RemoveHyperLinkMutation } from '@univerjs/sheets-hyper-link'; import { IEditorBridgeService } from '@univerjs/sheets-ui'; -import { getPlainTextFormDocument } from '@univerjs/docs'; +import { getPlainTextFormDocument } from '@univerjs/docs-ui'; import { isLegalLink, serializeUrl } from '../common/util'; import type { IAddHyperLinkCommandParams } from '../commands/commands/add-hyper-link.command'; import { AddHyperLinkCommand } from '../commands/commands/add-hyper-link.command'; diff --git a/packages/sheets-numfmt/src/components/more-numfmt-type/MoreNumfmtType.tsx b/packages/sheets-numfmt/src/components/more-numfmt-type/MoreNumfmtType.tsx index 194fcffb4a2..4ebff171b64 100644 --- a/packages/sheets-numfmt/src/components/more-numfmt-type/MoreNumfmtType.tsx +++ b/packages/sheets-numfmt/src/components/more-numfmt-type/MoreNumfmtType.tsx @@ -18,11 +18,11 @@ import './index.less'; import { ICommandService, LocaleService, Range, useDependency, useInjector } from '@univerjs/core'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; import type { FormatType } from '@univerjs/sheets'; import { SheetsSelectionsService } from '@univerjs/sheets'; import React from 'react'; +import { ILayoutService } from '@univerjs/ui'; import { MENU_OPTIONS } from '../../base/const/MENU-OPTIONS'; import { SetNumfmtCommand } from '../../commands/commands/set-numfmt.command'; import { OpenNumfmtPanelOperator } from '../../commands/operations/open.numfmt.panel.operation'; @@ -40,6 +40,7 @@ export const MoreNumfmtType = (props: { value?: string }) => { export const Options = () => { const commandService = useDependency(ICommandService); const localeService = useDependency(LocaleService); + const layoutService = useDependency(ILayoutService); const injector = useInjector(); const selectionManagerService = useDependency(SheetsSelectionsService); @@ -48,7 +49,7 @@ export const Options = () => { if (!selection) { return; } - const textSelectionRenderManager = injector.get(ITextSelectionRenderManager); + const range = selection.range; const values: Array<{ row: number; col: number; pattern?: string; type?: FormatType }> = []; Range.foreach(range, (row, col) => { @@ -59,7 +60,8 @@ export const Options = () => { } }); commandService.executeCommand(SetNumfmtCommand.id, { values }); - textSelectionRenderManager.focus(); + + layoutService.focus(); }; const handleOnclick = (index: number) => { if (index === 0) { diff --git a/packages/sheets-ui/package.json b/packages/sheets-ui/package.json index 262fd83c7a8..858394d4a87 100644 --- a/packages/sheets-ui/package.json +++ b/packages/sheets-ui/package.json @@ -68,6 +68,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/sheets": "workspace:*", @@ -81,6 +82,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-formula": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", diff --git a/packages/sheets-ui/src/basics/editor/get-editor-object.ts b/packages/sheets-ui/src/basics/editor/get-editor-object.ts index ad016925d73..b4189f0a69f 100644 --- a/packages/sheets-ui/src/basics/editor/get-editor-object.ts +++ b/packages/sheets-ui/src/basics/editor/get-editor-object.ts @@ -15,7 +15,7 @@ */ import type { Nullable } from '@univerjs/core'; -import { DOCS_VIEW_KEY } from '@univerjs/docs'; +import { DOCS_VIEW_KEY } from '@univerjs/docs-ui'; import type { DocBackground, Documents, Engine, IRenderManagerService, Scene } from '@univerjs/engine-render'; export interface IDocObjectParam { diff --git a/packages/sheets-ui/src/commands/commands/inline-format.command.ts b/packages/sheets-ui/src/commands/commands/inline-format.command.ts index d31812f7fac..b0cf6f8fe0f 100644 --- a/packages/sheets-ui/src/commands/commands/inline-format.command.ts +++ b/packages/sheets-ui/src/commands/commands/inline-format.command.ts @@ -16,17 +16,7 @@ import type { ICommand } from '@univerjs/core'; import { CommandType, EDITOR_ACTIVATED, ICommandService, IContextService } from '@univerjs/core'; -import { - SetInlineFormatBoldCommand, - SetInlineFormatFontFamilyCommand, - SetInlineFormatFontSizeCommand, - SetInlineFormatItalicCommand, - SetInlineFormatStrikethroughCommand, - SetInlineFormatSubscriptCommand, - SetInlineFormatSuperscriptCommand, - SetInlineFormatTextColorCommand, - SetInlineFormatUnderlineCommand, -} from '@univerjs/docs'; +import { SetInlineFormatBoldCommand, SetInlineFormatFontFamilyCommand, SetInlineFormatFontSizeCommand, SetInlineFormatItalicCommand, SetInlineFormatStrikethroughCommand, SetInlineFormatSubscriptCommand, SetInlineFormatSuperscriptCommand, SetInlineFormatTextColorCommand, SetInlineFormatUnderlineCommand } from '@univerjs/docs-ui'; import { SetBoldCommand, SetFontFamilyCommand, diff --git a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts index a5e2dba3c4a..c748d1851f6 100644 --- a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts +++ b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts @@ -20,6 +20,7 @@ import { DEFAULT_WORKSHEET_COLUMN_WIDTH, DEFAULT_WORKSHEET_COLUMN_WIDTH_KEY, DEFAULT_WORKSHEET_ROW_HEIGHT, + DOCS_NORMAL_EDITOR_UNIT_ID_KEY, extractPureTextFromCell, handleStyleToString, ICommandService, @@ -33,10 +34,10 @@ import { LocaleService, ObjectMatrix, OnLifecycle, - Optional, RxDisposable, UniverInstanceType, + RxDisposable, UniverInstanceType, } from '@univerjs/core'; import { MessageType } from '@univerjs/design'; -import { IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; import { InsertColMutation, InsertRowMutation, @@ -49,7 +50,6 @@ import { SetWorksheetRowHeightMutation, } from '@univerjs/sheets'; import { IMessageService } from '@univerjs/ui'; -import { takeUntil } from 'rxjs'; import type { ICellData, @@ -69,6 +69,9 @@ import type { ISetWorksheetColWidthMutationParams, ISetWorksheetRowHeightMutationParams, } from '@univerjs/sheets'; + +import { takeUntil } from 'rxjs'; +import { DocSelectionRenderService } from '@univerjs/docs-ui'; import { SheetCopyCommand, SheetCutCommand, @@ -113,25 +116,28 @@ export class SheetClipboardController extends RxDisposable { @IConfigService private readonly _configService: IConfigService, @ISheetClipboardService private readonly _sheetClipboardService: ISheetClipboardService, @IMessageService private readonly _messageService: IMessageService, - @Inject(LocaleService) private readonly _localService: LocaleService, - @Optional(ITextSelectionRenderManager) private readonly _textSelectionRenderManager?: ITextSelectionRenderManager + @Inject(LocaleService) private readonly _localService: LocaleService ) { super(); this._init(); - this._textSelectionRenderManager?.onPaste$.pipe(takeUntil(this.dispose$)).subscribe((config) => { - if (!whenSheetEditorFocused(this._contextService)) { - return; - } + const docSelectionRenderService = this._renderManagerService.getRenderById(DOCS_NORMAL_EDITOR_UNIT_ID_KEY)?.with(DocSelectionRenderService); - // editor's value should not change and avoid triggering input event - config!.event.preventDefault(); + if (docSelectionRenderService) { + docSelectionRenderService.onPaste$.pipe(takeUntil(this.dispose$)).subscribe((config) => { + if (!whenSheetEditorFocused(this._contextService)) { + return; + } - const clipboardEvent = config!.event as ClipboardEvent; - const htmlContent = clipboardEvent.clipboardData?.getData('text/html'); - const textContent = clipboardEvent.clipboardData?.getData('text/plain'); - this._commandService.executeCommand(SheetPasteShortKeyCommand.id, { htmlContent, textContent }); - }); + // editor's value should not change and avoid triggering input event + config!.event.preventDefault(); + + const clipboardEvent = config!.event as ClipboardEvent; + const htmlContent = clipboardEvent.clipboardData?.getData('text/html'); + const textContent = clipboardEvent.clipboardData?.getData('text/plain'); + this._commandService.executeCommand(SheetPasteShortKeyCommand.id, { htmlContent, textContent }); + }); + } } private _init(): void { @@ -157,6 +163,7 @@ export class SheetClipboardController extends RxDisposable { this.disposeWithMe({ dispose: () => disposables.forEach((d) => d.dispose()) }); } + // eslint-disable-next-line max-lines-per-function private _initCopyingHooks(): ISheetClipboardHook { const self = this; let currentSheet: Worksheet | null = null; @@ -280,6 +287,7 @@ export class SheetClipboardController extends RxDisposable { }; } + // eslint-disable-next-line max-lines-per-function private _initPastingHook(): ISheetClipboardHook { const self = this; @@ -311,6 +319,7 @@ export class SheetClipboardController extends RxDisposable { return true; }, + // eslint-disable-next-line max-lines-per-function onPasteRows(pasteTo, rowProperties) { const { range } = pasteTo; const redoMutations: IMutationInfo[] = []; @@ -416,6 +425,7 @@ export class SheetClipboardController extends RxDisposable { }; }, + // eslint-disable-next-line max-lines-per-function onPasteColumns(pasteTo, colProperties, pasteType) { const { range } = pasteTo; const redoMutations: IMutationInfo[] = []; @@ -607,6 +617,7 @@ export class SheetClipboardController extends RxDisposable { }); } + // eslint-disable-next-line max-lines-per-function private _initSpecialPasteHooks() { const self = this; diff --git a/packages/sheets-ui/src/controllers/editor/editing.render-controller.ts b/packages/sheets-ui/src/controllers/editor/editing.render-controller.ts index fdffbc9ba0e..6fd499b0126 100644 --- a/packages/sheets-ui/src/controllers/editor/editing.render-controller.ts +++ b/packages/sheets-ui/src/controllers/editor/editing.render-controller.ts @@ -44,22 +44,17 @@ import { } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; import { - VIEWPORT_KEY as DOC_VIEWPORT_KEY, - DOCS_COMPONENT_MAIN_LAYER_INDEX, + DocSelectionManagerService, DocSkeletonManagerService, - MoveCursorOperation, - MoveSelectionOperation, RichTextEditingMutation, - TextSelectionManagerService, } from '@univerjs/docs'; -import type { DocumentSkeleton, IDocumentLayoutObject, IEditorInputConfig, IRenderContext, IRenderModule, Scene } from '@univerjs/engine-render'; +import type { DocumentSkeleton, IDocumentLayoutObject, IRenderContext, IRenderModule, Scene } from '@univerjs/engine-render'; import { convertTextRotation, DeviceInputEventType, FIX_ONE_PIXEL_BLUR_OFFSET, fixLineWidthByScale, IRenderManagerService, - ITextSelectionRenderManager, Rect, ScrollBar, } from '@univerjs/engine-render'; @@ -69,6 +64,8 @@ import { ClearSelectionFormatCommand, SetRangeValuesCommand, SetRangeValuesMutat import { distinctUntilChanged, filter } from 'rxjs'; import { IFunctionService, LexerTreeBuilder, matchToken } from '@univerjs/engine-formula'; +import type { IEditorInputConfig } from '@univerjs/docs-ui'; +import { VIEWPORT_KEY as DOC_VIEWPORT_KEY, DOCS_COMPONENT_MAIN_LAYER_INDEX, DocSelectionRenderService, MoveCursorOperation, MoveSelectionOperation } from '@univerjs/docs-ui'; import { getEditorObject } from '../../basics/editor/get-editor-object'; import { SetCellEditVisibleArrowOperation, SetCellEditVisibleOperation, SetCellEditVisibleWithF2Operation } from '../../commands/operations/cell-edit.operation'; import type { IEditorBridgeServiceVisibleParam } from '../../services/editor-bridge.service'; @@ -121,10 +118,9 @@ export class EditingRenderController extends Disposable implements IRenderModule @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, @IEditorBridgeService private readonly _editorBridgeService: IEditorBridgeService, @ICellEditorManagerService private readonly _cellEditorManagerService: ICellEditorManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, @Inject(LexerTreeBuilder) private readonly _lexerTreeBuilder: LexerTreeBuilder, @IFunctionService private readonly _functionService: IFunctionService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @ICommandService private readonly _commandService: ICommandService, @Inject(LocaleService) protected readonly _localService: LocaleService, @IEditorService private readonly _editorService: IEditorService, @@ -238,7 +234,11 @@ export class EditingRenderController extends Disposable implements IRenderModule private _initialCursorSync(d: DisposableCollection) { d.add(this._cellEditorManagerService.focus$.pipe(filter((f) => !!f)).subscribe(() => { - this._textSelectionRenderManager.sync(); + const docSelectionRenderManager = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); + + if (docSelectionRenderManager) { + docSelectionRenderManager.sync(); + } })); } @@ -278,7 +278,11 @@ export class EditingRenderController extends Disposable implements IRenderModule endOffset: 0, }]); - this._textSelectionRenderManager.activate(HIDDEN_EDITOR_POSITION, HIDDEN_EDITOR_POSITION); + const docSelectionRenderManager = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); + + if (docSelectionRenderManager) { + docSelectionRenderManager.activate(HIDDEN_EDITOR_POSITION, HIDDEN_EDITOR_POSITION); + } })); } @@ -695,19 +699,23 @@ export class EditingRenderController extends Disposable implements IRenderModule * @param d DisposableCollection */ private _initialKeyboardListener(d: DisposableCollection) { - d.add(this._textSelectionRenderManager.onInputBefore$.subscribe((config) => { - if (!this._isCurrentSheetFocused()) { - return; - } + const docSelectionRenderService = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); - const isFocusFormulaEditor = this._contextService.getContextValue(FOCUSING_FX_BAR_EDITOR); - const isFocusSheets = this._contextService.getContextValue(FOCUSING_SHEET); - // TODO@Jocs: should get editor instead of current doc - const unitId = this._instanceSrv.getCurrentUniverDocInstance()?.getUnitId(); - if (unitId && isFocusSheets && !isFocusFormulaEditor && this._editorService.isSheetEditor(unitId)) { - this._showEditorByKeyboard(config); - } - })); + if (docSelectionRenderService) { + d.add(docSelectionRenderService.onInputBefore$.subscribe((config) => { + if (!this._isCurrentSheetFocused()) { + return; + } + + const isFocusFormulaEditor = this._contextService.getContextValue(FOCUSING_FX_BAR_EDITOR); + const isFocusSheets = this._contextService.getContextValue(FOCUSING_SHEET); + // TODO@Jocs: should get editor instead of current doc + const unitId = this._instanceSrv.getCurrentUniverDocInstance()?.getUnitId(); + if (unitId && isFocusSheets && !isFocusFormulaEditor && this._editorService.isSheetEditor(unitId)) { + this._showEditorByKeyboard(config); + } + })); + } } private _showEditorByKeyboard(config: Nullable) { @@ -1028,7 +1036,7 @@ export class EditingRenderController extends Disposable implements IRenderModule } // WTF: this is should not exist at all. It is because all editor instances reuse the singleton - // "TextSelectionManagerService" and other modules. Which will be refactored soon in August, 2024. + // "DocSelectionManagerService" and other modules. Which will be refactored soon in August, 2024. private _isCurrentSheetFocused(): boolean { return this._instanceSrv.getFocusedUnit()?.getUnitId() === this._context.unitId; } diff --git a/packages/sheets-ui/src/controllers/editor/formula-editor.controller.ts b/packages/sheets-ui/src/controllers/editor/formula-editor.controller.ts index 922eb7c0213..a2c9e140124 100644 --- a/packages/sheets-ui/src/controllers/editor/formula-editor.controller.ts +++ b/packages/sheets-ui/src/controllers/editor/formula-editor.controller.ts @@ -36,11 +36,9 @@ import { } from '@univerjs/core'; import type { IRichTextEditingMutationParams } from '@univerjs/docs'; import { - CoverContentCommand, - VIEWPORT_KEY as DOC_VIEWPORT_KEY, + DocSelectionManagerService, DocSkeletonManagerService, RichTextEditingMutation, - TextSelectionManagerService, } from '@univerjs/docs'; import type { DocumentViewModel, RenderComponentType } from '@univerjs/engine-render'; import { DeviceInputEventType, IRenderManagerService, ScrollBar } from '@univerjs/engine-render'; @@ -49,6 +47,7 @@ import { MoveRangeMutation, RangeProtectionRuleModel, SetRangeValuesMutation, Wo import { takeUntil } from 'rxjs'; import { SetEditorResizeOperation } from '@univerjs/ui'; +import { CoverContentCommand, VIEWPORT_KEY as DOC_VIEWPORT_KEY } from '@univerjs/docs-ui'; import { getEditorObject } from '../../basics/editor/get-editor-object'; import type { IEditorBridgeServiceParam } from '../../services/editor-bridge.service'; import { IEditorBridgeService } from '../../services/editor-bridge.service'; @@ -66,9 +65,9 @@ export class FormulaEditorController extends RxDisposable { @IContextService private readonly _contextService: IContextService, @IFormulaEditorManagerService private readonly _formulaEditorManagerService: IFormulaEditorManagerService, @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, @Inject(RangeProtectionRuleModel) private readonly _rangeProtectionRuleModel: RangeProtectionRuleModel, - @Inject(WorksheetProtectionRuleModel) private readonly _worksheetProtectionRuleModel: WorksheetProtectionRuleModel + @Inject(WorksheetProtectionRuleModel) private readonly _worksheetProtectionRuleModel: WorksheetProtectionRuleModel, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); diff --git a/packages/sheets-ui/src/controllers/menu/menu.ts b/packages/sheets-ui/src/controllers/menu/menu.ts index f0a15f7fb5d..519d70f61f0 100644 --- a/packages/sheets-ui/src/controllers/menu/menu.ts +++ b/packages/sheets-ui/src/controllers/menu/menu.ts @@ -32,7 +32,7 @@ import { VerticalAlign, WrapStrategy, } from '@univerjs/core'; -import { SetInlineFormatCommand, SetTextSelectionsOperation, TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService, SetTextSelectionsOperation } from '@univerjs/docs'; import { RangeProtectionPermissionEditPoint, RangeProtectionPermissionViewPoint, @@ -80,6 +80,7 @@ import { import type { IAccessor } from '@univerjs/core'; import { combineLatestWith, map, Observable } from 'rxjs'; +import { SetInlineFormatCommand } from '@univerjs/docs-ui'; import { SheetCopyCommand, SheetCutCommand, @@ -1231,10 +1232,10 @@ export function SetColWidthMenuItemFactory(accessor: IAccessor): IMenuButtonItem function getFontStyleAtCursor(accessor: IAccessor) { const univerInstanceService = accessor.get(IUniverInstanceService); - const textSelectionService = accessor.get(TextSelectionManagerService); + const textSelectionService = accessor.get(DocSelectionManagerService); const editorDataModel = univerInstanceService.getUniverDocInstance(DOCS_NORMAL_EDITOR_UNIT_ID_KEY); - const activeTextRange = textSelectionService.getActiveTextRangeWithStyle(); + const activeTextRange = textSelectionService.getActiveTextRange(); if (editorDataModel == null || activeTextRange == null) return null; diff --git a/packages/sheets-ui/src/controllers/permission/sheet-permission-interceptor-base.controller.ts b/packages/sheets-ui/src/controllers/permission/sheet-permission-interceptor-base.controller.ts index 5fb4195232d..1d4298a5aa7 100644 --- a/packages/sheets-ui/src/controllers/permission/sheet-permission-interceptor-base.controller.ts +++ b/packages/sheets-ui/src/controllers/permission/sheet-permission-interceptor-base.controller.ts @@ -18,7 +18,7 @@ /* eslint-disable max-lines-per-function */ import { CustomCommandExecutionError, Disposable, DisposableCollection, FOCUSING_EDITOR_STANDALONE, ICommandService, IContextService, Inject, IPermissionService, isICellData, IUniverInstanceService, LifecycleStages, LocaleService, ObjectMatrix, OnLifecycle, Rectangle, Tools, UniverInstanceType } from '@univerjs/core'; -import { IMEInputCommand, InsertCommand } from '@univerjs/docs'; +import { IMEInputCommand, InsertCommand } from '@univerjs/docs-ui'; import { deserializeRangeWithSheet, IDefinedNamesService, LexerTreeBuilder, operatorToken, sequenceNodeType } from '@univerjs/engine-formula'; import { UnitAction } from '@univerjs/protocol'; import { ClearSelectionContentCommand, DeleteRangeMoveLeftCommand, DeleteRangeMoveUpCommand, DeltaColumnWidthCommand, DeltaRowHeightCommand, getSheetCommandTarget, InsertRangeMoveDownCommand, InsertRangeMoveRightCommand, MoveColsCommand, MoveRangeCommand, MoveRowsCommand, RangeProtectionPermissionEditPoint, RangeProtectionPermissionViewPoint, RangeProtectionRuleModel, SetBackgroundColorCommand, SetColWidthCommand, SetRangeValuesCommand, SetRowHeightCommand, SetSelectedColsVisibleCommand, SetSelectedRowsVisibleCommand, SetSpecificColsVisibleCommand, SetSpecificRowsVisibleCommand, SetWorksheetNameCommand, SetWorksheetNameMutation, SetWorksheetOrderCommand, SetWorksheetRowIsAutoHeightCommand, SetWorksheetShowCommand, SheetsSelectionsService, WorkbookCopyPermission, WorkbookEditablePermission, WorkbookHideSheetPermission, WorkbookManageCollaboratorPermission, WorkbookMoveSheetPermission, WorkbookRenameSheetPermission, WorksheetCopyPermission, WorksheetEditPermission, WorksheetProtectionRuleModel, WorksheetSetCellStylePermission, WorksheetSetCellValuePermission, WorksheetSetColumnStylePermission, WorksheetSetRowStylePermission, WorksheetViewPermission } from '@univerjs/sheets'; diff --git a/packages/sheets-ui/src/controllers/sheet-ui.controller.ts b/packages/sheets-ui/src/controllers/sheet-ui.controller.ts index 78199efc2eb..06044cefd1e 100644 --- a/packages/sheets-ui/src/controllers/sheet-ui.controller.ts +++ b/packages/sheets-ui/src/controllers/sheet-ui.controller.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { connectInjector, Disposable, ICommandService, Inject, Injector, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; - +import { connectInjector, Disposable, DOCS_NORMAL_EDITOR_UNIT_ID_KEY, ICommandService, Inject, Injector, LifecycleStages, OnLifecycle, UniverInstanceType } from '@univerjs/core'; import { SetBoldCommand, SetFontFamilyCommand, @@ -26,7 +25,8 @@ import { } from '@univerjs/sheets'; import { BuiltInUIPart, ComponentManager, ILayoutService, IMenuManagerService, IShortcutService, IUIPartsService } from '@univerjs/ui'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService } from '@univerjs/docs-ui'; import { AddWorksheetMergeAllCommand, AddWorksheetMergeCommand, @@ -351,8 +351,10 @@ export class SheetUIController extends Disposable { this.disposeWithMe( this._layoutService.registerFocusHandler(UniverInstanceType.UNIVER_SHEET, (_unitId: string) => { // DEBT: `_unitId` is not used hence we cannot support Univer mode now - const textSelectionManagerService = this._injector.get(ITextSelectionRenderManager); - textSelectionManagerService.focus(); + const renderManagerService = this._injector.get(IRenderManagerService); + const docSelectionRenderService = renderManagerService.getRenderById(DOCS_NORMAL_EDITOR_UNIT_ID_KEY)?.with(DocSelectionRenderService); + + docSelectionRenderService?.focus(); }) ); } diff --git a/packages/sheets-ui/src/controllers/shortcuts/editor.shortcut.ts b/packages/sheets-ui/src/controllers/shortcuts/editor.shortcut.ts index aea5d698c20..aca866d4b14 100644 --- a/packages/sheets-ui/src/controllers/shortcuts/editor.shortcut.ts +++ b/packages/sheets-ui/src/controllers/shortcuts/editor.shortcut.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -import { BreakLineCommand, DeleteLeftCommand } from '@univerjs/docs'; import { DeviceInputEventType } from '@univerjs/engine-render'; import type { IShortcutItem } from '@univerjs/ui'; import { KeyCode, MetaKeys } from '@univerjs/ui'; +import { BreakLineCommand, DeleteLeftCommand } from '@univerjs/docs-ui'; import { SetCellEditVisibleArrowOperation, SetCellEditVisibleOperation, diff --git a/packages/sheets-ui/src/services/editor-bridge.service.ts b/packages/sheets-ui/src/services/editor-bridge.service.ts index 73c0aa9d47d..570e2e05685 100644 --- a/packages/sheets-ui/src/services/editor-bridge.service.ts +++ b/packages/sheets-ui/src/services/editor-bridge.service.ts @@ -34,7 +34,7 @@ import { UniverInstanceType, } from '@univerjs/core'; import type { Engine, IDocumentLayoutObject, Scene } from '@univerjs/engine-render'; -import { convertTextRotation, DeviceInputEventType, getCanvasOffsetByEngine, IRenderManagerService } from '@univerjs/engine-render'; +import { convertTextRotation, DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render'; import type { ISheetLocation, SheetsSelectionsService } from '@univerjs/sheets'; import { IRefSelectionsService } from '@univerjs/sheets'; import { IEditorService } from '@univerjs/ui'; @@ -42,6 +42,7 @@ import type { KeyCode } from '@univerjs/ui'; import type { Observable } from 'rxjs'; import { BehaviorSubject } from 'rxjs'; +import { getCanvasOffsetByEngine } from '@univerjs/docs-ui'; import { SheetSkeletonManagerService } from './sheet-skeleton-manager.service'; import { ISheetSelectionRenderService } from './selection/base-selection-render.service'; import { attachPrimaryWithCoord } from './selection/util'; diff --git a/packages/sheets-ui/src/views/defined-name/DefinedName.tsx b/packages/sheets-ui/src/views/defined-name/DefinedName.tsx index 8d2d7e6380f..21872abca36 100644 --- a/packages/sheets-ui/src/views/defined-name/DefinedName.tsx +++ b/packages/sheets-ui/src/views/defined-name/DefinedName.tsx @@ -14,15 +14,15 @@ * limitations under the License. */ -import React, { useEffect } from 'react'; +import { useDependency } from '@univerjs/core'; import { Dropdown, Input } from '@univerjs/design'; -import { MoreDownSingle } from '@univerjs/icons'; -import { useDependency } from '@univerjs/core'; import { IDefinedNamesService } from '@univerjs/engine-formula'; +import { MoreDownSingle } from '@univerjs/icons'; import clsx from 'clsx'; -import styles from './index.module.less'; +import React, { useEffect } from 'react'; import { DefinedNameOverlay } from './DefinedNameOverlay'; +import styles from './index.module.less'; export function DefinedName({ disable }: { disable: boolean }) { const [rangeString, setRangeString] = React.useState(''); diff --git a/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx b/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx index 80e78daf45c..83565f9e85d 100644 --- a/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx +++ b/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx @@ -14,17 +14,17 @@ * limitations under the License. */ -import React, { useEffect, useState } from 'react'; - -import { RangeSelector, TextEditor } from '@univerjs/ui'; -import type { IUnitRange, Nullable, Workbook } from '@univerjs/core'; import { AbsoluteRefType, createInternalEditorID, IUniverInstanceService, LocaleService, Tools, UniverInstanceType, useDependency } from '@univerjs/core'; + import { Button, Input, Radio, RadioGroup, Select } from '@univerjs/design'; import { IDefinedNamesService, type IDefinedNamesServiceParam, IFunctionService, isReferenceStrings, isReferenceStringWithEffectiveColumn, LexerTreeBuilder, operatorToken, serializeRangeToRefString } from '@univerjs/engine-formula'; -import { ErrorSingle } from '@univerjs/icons'; import { hasCJKText } from '@univerjs/engine-render'; -import styles from './index.module.less'; +import { ErrorSingle } from '@univerjs/icons'; +import { RangeSelector, TextEditor } from '@univerjs/ui'; +import React, { useEffect, useState } from 'react'; +import type { IUnitRange, Nullable, Workbook } from '@univerjs/core'; import { SCOPE_WORKBOOK_VALUE } from './component-name'; +import styles from './index.module.less'; export interface IDefinedNameInputProps extends Omit { inputId: string; diff --git a/packages/sheets-zen-editor/src/controllers/zen-editor.controller.ts b/packages/sheets-zen-editor/src/controllers/zen-editor.controller.ts index 4ddc281e646..fa08c0b9172 100644 --- a/packages/sheets-zen-editor/src/controllers/zen-editor.controller.ts +++ b/packages/sheets-zen-editor/src/controllers/zen-editor.controller.ts @@ -30,13 +30,11 @@ import { RxDisposable, UniverInstanceType, } from '@univerjs/core'; -import type { IDocObjectParam, IRichTextEditingMutationParams } from '@univerjs/docs'; +import type { IRichTextEditingMutationParams } from '@univerjs/docs'; import { - VIEWPORT_KEY as DOC_VIEWPORT_KEY, + DocSelectionManagerService, DocSkeletonManagerService, - getDocObject, RichTextEditingMutation, - TextSelectionManagerService, } from '@univerjs/docs'; import type { Viewport } from '@univerjs/engine-render'; import { DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render'; @@ -45,6 +43,8 @@ import { getEditorObject, IEditorBridgeService } from '@univerjs/sheets-ui'; import { IZenZoneService } from '@univerjs/ui'; import { takeUntil } from 'rxjs'; +import type { IDocObjectParam } from '@univerjs/docs-ui'; +import { VIEWPORT_KEY as DOC_VIEWPORT_KEY, getDocObject } from '@univerjs/docs-ui'; import { OpenZenEditorOperation } from '../commands/operations/zen-editor.operation'; import { IZenEditorManagerService } from '../services/zen-editor.service'; @@ -58,7 +58,7 @@ export class ZenEditorController extends RxDisposable { @IZenZoneService private readonly _zenZoneService: IZenZoneService, @IEditorBridgeService private readonly _editorBridgeService: IEditorBridgeService, @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService ) { super(); diff --git a/packages/sheets/src/commands/commands/set-range-values.command.ts b/packages/sheets/src/commands/commands/set-range-values.command.ts index c6f72a48058..043555198c5 100644 --- a/packages/sheets/src/commands/commands/set-range-values.command.ts +++ b/packages/sheets/src/commands/commands/set-range-values.command.ts @@ -136,6 +136,7 @@ export const SetRangeValuesCommand: ICommand = { }); const result = sequenceExecute([...redos], commandService); + if (setValueMutationResult && result.result) { undoRedoService.pushUndoRedo({ unitID: unitId, diff --git a/packages/sheets/src/services/selections/selection-manager.service.ts b/packages/sheets/src/services/selections/selection-manager.service.ts index f63728699af..d7751c358ce 100644 --- a/packages/sheets/src/services/selections/selection-manager.service.ts +++ b/packages/sheets/src/services/selections/selection-manager.service.ts @@ -105,8 +105,8 @@ export class SheetsSelectionsService extends RxDisposable { setSelections(selectionDatas: ISelectionWithStyle[], type?: SelectionMoveType): void; setSelections(unitId: string, worksheetId: string, selectionDatas: ISelectionWithStyle[], type?: SelectionMoveType): void; /** - * Set seleciton data to WorkbookSelections. - * If type is not specfied, this method would clear all existing selections. + * Set selection data to WorkbookSelections. + * If type is not specified, this method would clear all existing selections. * @param unitIdOrSelections * @param worksheetIdOrType * @param selectionDatas diff --git a/packages/slides-ui/package.json b/packages/slides-ui/package.json index 7ffc7a4efdd..27c8cf273a6 100644 --- a/packages/slides-ui/package.json +++ b/packages/slides-ui/package.json @@ -68,6 +68,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/drawing": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/slides": "workspace:*", @@ -80,6 +81,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/drawing": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", diff --git a/packages/slides-ui/src/controllers/shortcuts/editor.shortcuts.ts b/packages/slides-ui/src/controllers/shortcuts/editor.shortcuts.ts index 1e3ace106cb..dd4176fe2fb 100644 --- a/packages/slides-ui/src/controllers/shortcuts/editor.shortcuts.ts +++ b/packages/slides-ui/src/controllers/shortcuts/editor.shortcuts.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { DeleteLeftCommand } from '@univerjs/docs'; import { DeviceInputEventType } from '@univerjs/engine-render'; import type { IShortcutItem } from '@univerjs/ui'; import { KeyCode, MetaKeys } from '@univerjs/ui'; +import { DeleteLeftCommand } from '@univerjs/docs-ui'; import { SetTextEditArrowOperation } from '../../commands/operations/text-edit.operation'; import { whenEditorActivated, diff --git a/packages/slides-ui/src/controllers/slide-editing.render-controller.ts b/packages/slides-ui/src/controllers/slide-editing.render-controller.ts index 20d5d642f49..ef4c729597f 100644 --- a/packages/slides-ui/src/controllers/slide-editing.render-controller.ts +++ b/packages/slides-ui/src/controllers/slide-editing.render-controller.ts @@ -43,23 +43,16 @@ import { VerticalAlign, WrapStrategy, } from '@univerjs/core'; -import type { IDocObjectParam } from '@univerjs/docs'; import { - VIEWPORT_KEY as DOC_VIEWPORT_KEY, - DOCS_COMPONENT_MAIN_LAYER_INDEX, - DOCS_VIEW_KEY, + DocSelectionManagerService, DocSkeletonManagerService, - MoveCursorOperation, - MoveSelectionOperation, RichTextEditingMutation, - TextSelectionManagerService, } from '@univerjs/docs'; import type { DocBackground, Documents, DocumentSkeleton, IDocumentLayoutObject, - IEditorInputConfig, IRenderContext, IRenderModule, Scene, @@ -70,12 +63,13 @@ import { FIX_ONE_PIXEL_BLUR_OFFSET, fixLineWidthByScale, IRenderManagerService, - ITextSelectionRenderManager, Rect, ScrollBar, } from '@univerjs/engine-render'; import { IEditorService, ILayoutService, KeyCode } from '@univerjs/ui'; import { filter } from 'rxjs'; +import type { IDocObjectParam, IEditorInputConfig } from '@univerjs/docs-ui'; +import { VIEWPORT_KEY as DOC_VIEWPORT_KEY, DOCS_COMPONENT_MAIN_LAYER_INDEX, DOCS_VIEW_KEY, DocSelectionRenderService, MoveCursorOperation, MoveSelectionOperation } from '@univerjs/docs-ui'; import type { IEditorBridgeServiceVisibleParam } from '../services/slide-editor-bridge.service'; import { ISlideEditorBridgeService } from '../services/slide-editor-bridge.service'; import { ISlideEditorManagerService } from '../services/slide-editor-manager.service'; @@ -114,10 +108,7 @@ export class SlideEditingRenderController extends Disposable implements IRenderM @IRenderManagerService private readonly _renderManagerService: IRenderManagerService, @ISlideEditorBridgeService private readonly _editorBridgeService: ISlideEditorBridgeService, @ISlideEditorManagerService private readonly _cellEditorManagerService: ISlideEditorManagerService, - @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, - // @Inject(LexerTreeBuilder) private readonly _lexerTreeBuilder: LexerTreeBuilder, - // @IFunctionService private readonly _functionService: IFunctionService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @ICommandService private readonly _commandService: ICommandService, @Inject(LocaleService) protected readonly _localService: LocaleService, @IEditorService private readonly _editorService: IEditorService @@ -208,7 +199,11 @@ export class SlideEditingRenderController extends Disposable implements IRenderM private _initialCursorSync(d: DisposableCollection) { d.add(this._cellEditorManagerService.focus$.pipe(filter((f) => !!f)).subscribe(() => { - this._textSelectionRenderManager.sync(); + const docSelectionRenderManager = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); + + if (docSelectionRenderManager) { + docSelectionRenderManager.sync(); + } })); } @@ -257,7 +252,11 @@ export class SlideEditingRenderController extends Disposable implements IRenderM // ---> _focus$.next --> editingRenderController // _textSelectionRenderManager.sync() --> _updateInputPosition --> activate(left, top) - this._textSelectionRenderManager.activate(HIDDEN_EDITOR_POSITION, HIDDEN_EDITOR_POSITION); + const docSelectionRenderManager = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_DOC)?.with(DocSelectionRenderService); + + if (docSelectionRenderManager) { + docSelectionRenderManager.activate(HIDDEN_EDITOR_POSITION, HIDDEN_EDITOR_POSITION); + } })); } @@ -663,16 +662,16 @@ export class SlideEditingRenderController extends Disposable implements IRenderM * @param d DisposableCollection */ private _initialKeyboardListener(d: DisposableCollection) { - d.add(this._textSelectionRenderManager.onInputBefore$.subscribe((config) => { - // const isFocusFormulaEditor = this._contextService.getContextValue(FORMULA_EDITOR_ACTIVATED); - // const isFocusSheets = this._contextService.getContextValue(FOCUSING_SHEET); - - // // TODO@Jocs: should get editor instead of current doc - // const unitId = this._instanceSrv.getCurrentUniverDocInstance()?.getUnitId(); - // if (unitId && isFocusSheets && !isFocusFormulaEditor && this._editorService.isSheetEditor(unitId)) { - // this._showEditorByKeyboard(config); - // } - })); + // d.add(this._textSelectionRenderManager.onInputBefore$.subscribe((config) => { + // // const isFocusFormulaEditor = this._contextService.getContextValue(FORMULA_EDITOR_ACTIVATED); + // // const isFocusSheets = this._contextService.getContextValue(FOCUSING_SHEET); + + // // // TODO@Jocs: should get editor instead of current doc + // // const unitId = this._instanceSrv.getCurrentUniverDocInstance()?.getUnitId(); + // // if (unitId && isFocusSheets && !isFocusFormulaEditor && this._editorService.isSheetEditor(unitId)) { + // // this._showEditorByKeyboard(config); + // // } + // })); } private _showEditorByKeyboard(config: Nullable) { diff --git a/packages/slides-ui/src/services/slide-popup-manager.service.ts b/packages/slides-ui/src/services/slide-popup-manager.service.ts index 370cea836d2..6f0829c6446 100644 --- a/packages/slides-ui/src/services/slide-popup-manager.service.ts +++ b/packages/slides-ui/src/services/slide-popup-manager.service.ts @@ -114,19 +114,6 @@ export class SlideCanvasPopMangerService extends Disposable { const position$ = new BehaviorSubject(position); const disposable = new DisposableCollection(); - // disposable.add(this._commandService.onCommandExecuted((commandInfo) => { - // if (commandInfo.id === SetDocZoomRatioOperation.id) { - // position$.next(calc()); - // } - // })); - - // const viewMain = currentRender.scene.getViewport(VIEWPORT_KEY.VIEW_MAIN); - // if (viewMain) { - // disposable.add(viewMain.onScrollAfter$.subscribeEvent(() => { - // position$.next(calc()); - // })); - // } - return { position, position$, diff --git a/packages/slides/src/slides-plugin.ts b/packages/slides/src/slides-plugin.ts index e07717f2584..4e6c4d2d261 100644 --- a/packages/slides/src/slides-plugin.ts +++ b/packages/slides/src/slides-plugin.ts @@ -18,8 +18,13 @@ import { IConfigService, Inject, Injector, Plugin, UniverInstanceType } from '@u import type { Engine } from '@univerjs/engine-render'; import { IRenderingEngine, IRenderManagerService } from '@univerjs/engine-render'; import type { Dependency } from '@univerjs/core'; -import type { IUniverSlidesConfig } from './controllers/config.schema'; import { defaultPluginConfig, PLUGIN_CONFIG_KEY } from './controllers/config.schema'; +// import { DocSelectionManagerService } from '@univerjs/docs'; +// import { CanvasView } from './views/render'; + +export interface IUniverSlidesConfig {} + +const DEFAULT_SLIDE_PLUGIN_DATA = {}; const PLUGIN_NAME = 'slides'; @@ -73,7 +78,7 @@ export class UniverSlidesPlugin extends Plugin { private _initializeDependencies(slideInjector: Injector) { const dependencies: Dependency[] = [ // [CanvasView], - // [TextSelectionManagerService], + // [DocSelectionManagerService], ]; dependencies.forEach((d) => { diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index e034881fa29..a1ac1614449 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -63,8 +63,14 @@ }, "devDependencies": { "@univerjs-infra/shared": "workspace:*", - "typescript": "^5.6.2", - "vite": "^5.4.3", + "@univerjs/core": "workspace:*", + "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", + "@univerjs/engine-render": "workspace:*", + "react": "18.3.1", + "rxjs": "^7.8.1", + "typescript": "^5.5.4", + "vite": "^5.4.2", "vitest": "^2.0.5" }, "univerSpace": { diff --git a/packages/thread-comment-ui/package.json b/packages/thread-comment-ui/package.json index 8f4b716be6e..0127952ea30 100644 --- a/packages/thread-comment-ui/package.json +++ b/packages/thread-comment-ui/package.json @@ -66,6 +66,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/thread-comment": "workspace:*", "@univerjs/ui": "workspace:*", @@ -78,6 +79,7 @@ "@univerjs/core": "workspace:*", "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", + "@univerjs/docs-ui": "workspace:*", "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.78", "@univerjs/protocol": "0.1.39-alpha.15", diff --git a/packages/thread-comment-ui/src/views/thread-comment-editor/index.tsx b/packages/thread-comment-ui/src/views/thread-comment-editor/index.tsx index f08747827ae..04e1bdbbd9a 100644 --- a/packages/thread-comment-ui/src/views/thread-comment-editor/index.tsx +++ b/packages/thread-comment-ui/src/views/thread-comment-editor/index.tsx @@ -18,11 +18,12 @@ import type { IThreadComment } from '@univerjs/thread-comment'; import type { MentionProps } from '@univerjs/design'; import { Button, Mention, Mentions } from '@univerjs/design'; import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'; -import { ICommandService, LocaleService, useDependency } from '@univerjs/core'; +import { ICommandService, LocaleService, UniverInstanceType, useDependency } from '@univerjs/core'; import type { IDocumentBody } from '@univerjs/core'; -import { ITextSelectionRenderManager } from '@univerjs/engine-render'; -import { TextSelectionManagerService } from '@univerjs/docs'; +import { DocSelectionManagerService } from '@univerjs/docs'; import { KeyCode } from '@univerjs/ui'; +import { IRenderManagerService } from '@univerjs/engine-render'; +import { DocSelectionRenderService } from '@univerjs/docs-ui'; import { IThreadCommentMentionDataService } from '../../services/thread-comment-mention-data.service'; import { SetActiveCommentOperation } from '../../commands/operations/comment.operations'; import styles from './index.module.less'; @@ -62,8 +63,9 @@ export const ThreadCommentEditor = forwardRef ({ reply(text) { @@ -104,11 +106,11 @@ export const ThreadCommentEditor = forwardRef { - const activeRange = textSelectionManagerService.getActiveTextRangeWithStyle(); + const activeRange = docSelectionManagerService.getActiveTextRange(); if (activeRange && activeRange.collapsed) { - textSelectionRenderManager.removeAllRanges(); + docSelectionRenderService?.removeAllRanges(); } - textSelectionRenderManager.blur(); + docSelectionRenderService?.blur(); setEditing(true); }} onKeyDown={(e) => { diff --git a/packages/ui/src/components/editor/TextEditor.tsx b/packages/ui/src/components/editor/TextEditor.tsx index 7f33aecd277..3a8c572786a 100644 --- a/packages/ui/src/components/editor/TextEditor.tsx +++ b/packages/ui/src/components/editor/TextEditor.tsx @@ -231,6 +231,12 @@ export function TextEditor(props: ITextEditorProps & Omit(null); @@ -79,9 +79,14 @@ export function DesktopContextMenu() { menuType={menuType} onOptionSelect={(params) => { const { label: id, commandId, value } = params; - commandService && commandService.executeCommand(commandId ?? id as string, { value }); - const textSelectionRenderManager = injector.get(ITextSelectionRenderManager); - textSelectionRenderManager.focus(); + + if (commandService) { + commandService.executeCommand(commandId ?? id as string, { value }); + } + + const layoutService = injector.get(ILayoutService); + layoutService.focus(); + setVisible(false); }} /> diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b8b0c9b31f9..8ca89530fe5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: 3.5.0 - version: 3.5.0(@eslint-react/eslint-plugin@1.14.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@vue/compiler-sfc@3.4.38)(eslint-plugin-format@0.1.2(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.11(eslint@9.10.0(jiti@1.21.6)))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) + version: 3.5.0(@eslint-react/eslint-plugin@1.14.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@vue/compiler-sfc@3.4.38)(eslint-plugin-format@0.1.2(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.11(eslint@9.10.0(jiti@1.21.6)))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) '@commitlint/cli': specifier: ^19.4.1 version: 19.4.1(@types/node@22.5.4)(typescript@5.6.2) @@ -31,7 +31,7 @@ importers: version: 8.0.1(release-it@17.6.0(typescript@5.6.2)) '@storybook/react': specifier: 8.2.9 - version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))(typescript@5.6.2) '@types/node': specifier: ^22.5.4 version: 22.5.4 @@ -133,7 +133,7 @@ importers: version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-interactions': specifier: 8.2.9 - version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) + version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) '@storybook/addon-links': specifier: 8.2.9 version: 8.2.9(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -151,7 +151,7 @@ importers: version: 1.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/react': specifier: 8.2.9 - version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))(typescript@5.6.2) '@storybook/react-webpack5': specifier: 8.2.9 version: 8.2.9(@swc/core@1.7.5)(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) @@ -175,7 +175,7 @@ importers: version: 12.2.0(less@4.2.0)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) storybook: specifier: 8.2.9 - version: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + version: 8.2.9(@babel/preset-env@7.25.4) storybook-addon-swc: specifier: ^1.2.0 version: 1.2.0(@swc/core@1.7.5)(terser-webpack-plugin@5.3.10(@swc/core@1.7.5)(esbuild@0.21.5)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)))(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) @@ -1902,6 +1902,9 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/engine-formula': specifier: workspace:* version: link:../engine-formula @@ -2175,6 +2178,9 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/engine-formula': specifier: workspace:* version: link:../engine-formula @@ -2273,6 +2279,12 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-hyper-link': + specifier: workspace:* + version: link:../docs-hyper-link + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/engine-formula': specifier: workspace:* version: link:../engine-formula @@ -2567,6 +2579,9 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/engine-formula': specifier: workspace:* version: link:../engine-formula @@ -2708,6 +2723,9 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/drawing': specifier: workspace:* version: link:../drawing @@ -2761,11 +2779,26 @@ importers: '@univerjs-infra/shared': specifier: workspace:* version: link:../../common/shared + '@univerjs/docs': + specifier: workspace:* + version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui + '@univerjs/engine-render': + specifier: workspace:* + version: link:../engine-render + react: + specifier: 18.3.1 + version: 18.3.1 + rxjs: + specifier: ^7.8.1 + version: 7.8.1 typescript: - specifier: ^5.6.2 + specifier: ^5.5.4 version: 5.6.2 vite: - specifier: ^5.4.3 + specifier: ^5.4.2 version: 5.4.3(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6) vitest: specifier: ^2.0.5 @@ -2807,6 +2840,9 @@ importers: '@univerjs/docs': specifier: workspace:* version: link:../docs + '@univerjs/docs-ui': + specifier: workspace:* + version: link:../docs-ui '@univerjs/engine-render': specifier: workspace:* version: link:../engine-render @@ -11211,7 +11247,7 @@ snapshots: dependencies: '@babel/runtime': 7.25.0 - '@antfu/eslint-config@3.5.0(@eslint-react/eslint-plugin@1.14.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@vue/compiler-sfc@3.4.38)(eslint-plugin-format@0.1.2(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.11(eslint@9.10.0(jiti@1.21.6)))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': + '@antfu/eslint-config@3.5.0(@eslint-react/eslint-plugin@1.14.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(@vue/compiler-sfc@3.4.38)(eslint-plugin-format@0.1.2(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.10.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.11(eslint@9.10.0(jiti@1.21.6)))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': dependencies: '@antfu/install-pkg': 0.4.1 '@clack/prompts': 0.7.0 @@ -11220,7 +11256,7 @@ snapshots: '@stylistic/eslint-plugin': 2.8.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) '@typescript-eslint/eslint-plugin': 8.5.0(@typescript-eslint/parser@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) '@typescript-eslint/parser': 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) - '@vitest/eslint-plugin': 1.1.0(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) + '@vitest/eslint-plugin': 1.1.0(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) eslint: 9.10.0(jiti@1.21.6) eslint-config-flat-gitignore: 0.3.0(eslint@9.10.0(jiti@1.21.6)) eslint-flat-config-utils: 0.4.0 @@ -12226,7 +12262,7 @@ snapshots: filesize: 10.1.4 jsonfile: 6.1.0 react-confetti: 6.1.0(react@18.3.1) - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) strip-ansi: 7.1.0 transitivePeerDependencies: - '@chromatic-com/cypress' @@ -13167,21 +13203,21 @@ snapshots: '@types/uuid': 9.0.8 dequal: 2.0.3 polished: 4.3.1 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) uuid: 9.0.1 '@storybook/addon-backgrounds@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 '@storybook/addon-controls@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: dequal: 2.0.3 lodash: 4.17.21 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 '@storybook/addon-docs@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': @@ -13191,14 +13227,14 @@ snapshots: '@storybook/blocks': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4)) '@types/react': 18.3.5 fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) rehype-external-links: 3.0.0 rehype-slug: 6.0.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color @@ -13214,7 +13250,7 @@ snapshots: '@storybook/addon-outline': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-toolbars': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-viewport': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color @@ -13222,15 +13258,15 @@ snapshots: '@storybook/addon-highlight@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) - '@storybook/addon-interactions@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': + '@storybook/addon-interactions@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': dependencies: '@storybook/global': 5.0.0 '@storybook/instrumenter': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/test': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) + '@storybook/test': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) polished: 4.3.1 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 transitivePeerDependencies: - '@jest/globals' @@ -13243,7 +13279,7 @@ snapshots: dependencies: '@storybook/csf': 0.1.11 '@storybook/global': 5.0.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 optionalDependencies: react: 18.3.1 @@ -13251,13 +13287,13 @@ snapshots: '@storybook/addon-measure@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) tiny-invariant: 1.3.3 '@storybook/addon-outline@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 '@storybook/addon-styling-webpack@1.0.0(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5))': @@ -13267,12 +13303,12 @@ snapshots: '@storybook/addon-toolbars@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/addon-viewport@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: memoizerific: 1.11.3 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/addon-webpack5-compiler-swc@1.0.5(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5))': dependencies: @@ -13295,7 +13331,7 @@ snapshots: memoizerific: 1.11.3 polished: 4.3.1 react-colorful: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) telejson: 7.2.0 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -13322,7 +13358,7 @@ snapshots: path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) terser-webpack-plugin: 5.3.10(@swc/core@1.7.5)(esbuild@0.21.5)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) ts-dedent: 2.2.0 @@ -13353,7 +13389,7 @@ snapshots: '@types/cross-spawn': 6.0.6 cross-spawn: 7.0.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + jscodeshift: 0.15.2(@babel/preset-env@7.25.4) lodash: 4.17.21 prettier: 3.3.3 recast: 0.23.9 @@ -13363,14 +13399,14 @@ snapshots: - supports-color - utf-8-validate - '@storybook/components@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/components@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/core-webpack@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@types/node': 18.19.47 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 '@storybook/core@8.2.9': @@ -13393,7 +13429,7 @@ snapshots: '@storybook/csf-plugin@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) unplugin: 1.12.2 '@storybook/csf@0.1.11': @@ -13411,19 +13447,19 @@ snapshots: dependencies: '@storybook/global': 5.0.0 '@vitest/utils': 1.6.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) util: 0.12.5 - '@storybook/manager-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/manager-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/node-logger@8.1.6': {} '@storybook/preset-react-webpack@8.2.9(@swc/core@1.7.5)(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2)': dependencies: '@storybook/core-webpack': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) + '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))(typescript@5.6.2) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) '@types/node': 18.19.47 '@types/semver': 7.5.8 @@ -13435,7 +13471,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) resolve: 1.22.8 semver: 7.6.3 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) tsconfig-paths: 4.2.0 webpack: 5.94.0(@swc/core@1.7.5)(esbuild@0.21.5) optionalDependencies: @@ -13447,9 +13483,9 @@ snapshots: - uglify-js - webpack-cli - '@storybook/preview-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/preview-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5))': dependencies: @@ -13465,21 +13501,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/react-dom-shim@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/react-dom-shim@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/react-webpack5@8.2.9(@swc/core@1.7.5)(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2)': dependencies: '@storybook/builder-webpack5': 8.2.9(@swc/core@1.7.5)(esbuild@0.21.5)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) '@storybook/preset-react-webpack': 8.2.9(@swc/core@1.7.5)(esbuild@0.21.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) - '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2) + '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))(typescript@5.6.2) '@types/node': 18.19.47 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -13490,14 +13526,14 @@ snapshots: - uglify-js - webpack-cli - '@storybook/react@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.6.2)': + '@storybook/react@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4))(typescript@5.6.2)': dependencies: - '@storybook/components': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/components': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4)) '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/preview-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/manager-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4)) + '@storybook/preview-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4)) + '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4)) + '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4)) '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 '@types/node': 18.19.47 @@ -13512,23 +13548,23 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-element-to-jsx-string: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) semver: 7.6.3 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) ts-dedent: 2.2.0 type-fest: 2.19.0 util-deprecate: 1.0.2 optionalDependencies: typescript: 5.6.2 - '@storybook/test@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': + '@storybook/test@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': dependencies: '@storybook/csf': 0.1.11 '@storybook/instrumenter': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@testing-library/dom': 10.1.0 - '@testing-library/jest-dom': 6.4.5(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) + '@testing-library/jest-dom': 6.4.5(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6)) '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) util: 0.12.5 transitivePeerDependencies: - '@jest/globals' @@ -13537,13 +13573,13 @@ snapshots: - jest - vitest - '@storybook/theming@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/theming@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@storybook/types@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + storybook: 8.2.9(@babel/preset-env@7.25.4) '@stylistic/eslint-plugin@2.8.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)': dependencies: @@ -13624,7 +13660,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.5(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': + '@testing-library/jest-dom@6.4.5(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.25.4 @@ -14032,7 +14068,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.1.0(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(happy-dom@15.0.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': + '@vitest/eslint-plugin@1.1.0(@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)(vitest@2.0.5(@types/node@22.5.4)(less@4.2.0)(sass@1.77.5)(terser@5.31.6))': dependencies: eslint: 9.10.0(jiti@1.21.6) optionalDependencies: @@ -17199,7 +17235,7 @@ snapshots: jsbn@1.1.0: {} - jscodeshift@0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)): + jscodeshift@0.15.2(@babel/preset-env@7.25.4): dependencies: '@babel/core': 7.25.2 '@babel/parser': 7.25.4 @@ -19580,7 +19616,7 @@ snapshots: terser-webpack-plugin: 5.3.10(@swc/core@1.7.5)(esbuild@0.21.5)(webpack@5.94.0(@swc/core@1.7.5)(esbuild@0.21.5)) webpack: 5.94.0(@swc/core@1.7.5)(esbuild@0.21.5) - storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)): + storybook@8.2.9(@babel/preset-env@7.25.4): dependencies: '@babel/core': 7.25.2 '@babel/types': 7.25.4 @@ -19600,7 +19636,7 @@ snapshots: fs-extra: 11.2.0 giget: 1.2.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + jscodeshift: 0.15.2(@babel/preset-env@7.25.4) leven: 3.1.0 ora: 5.4.1 prettier: 3.3.3