From 3cf7b461dca0d53f0cd71dcf305ffc1adf37ba9e Mon Sep 17 00:00:00 2001 From: Ran Luo Date: Wed, 18 Sep 2024 18:18:46 +0800 Subject: [PATCH] fix(docs): scroll to selection (#3458) --- .../controllers/doc-move-cursor.controller.ts | 24 ++++++++++ .../back-scroll.render-controller.ts | 45 ++++++++----------- .../selection/doc-selection-render.service.ts | 4 ++ .../commands/commands/zen-editor.command.ts | 2 +- 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts b/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts index d40bce0cc0..4044de3c7e 100644 --- a/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts +++ b/packages/docs-ui/src/controllers/doc-move-cursor.controller.ts @@ -44,6 +44,7 @@ import { getDocObject } from '../basics/component-tools'; import { findAboveCell, findBellowCell, findLineBeforeAndAfterTable, findTableAfterLine, findTableBeforeLine, firstLineInCell, firstLineInTable, lastLineInCell, lastLineInTable } from '../basics/table'; import { MoveCursorOperation, MoveSelectionOperation } from '../commands/operations/doc-cursor.operation'; import { NodePositionConvertToCursor } from '../services/selection/convert-text-range'; +import { DocBackScrollRenderController } from './render-controllers/back-scroll.render-controller'; import type { IMoveCursorOperationParams } from '../commands/operations/doc-cursor.operation'; @OnLifecycle(LifecycleStages.Rendered, DocMoveCursorController) @@ -167,6 +168,8 @@ export class DocMoveCursorController extends Disposable { style, }, ], false); + + this._scrollToFocusNodePosition(docDataModel.getUnitId(), focusOffset); } else { const focusGlyph = skeleton.findNodeByCharIndex(focusOffset, segmentId, segmentPage); const documentOffsetConfig = docObject.document.getOffsetConfig(); @@ -206,6 +209,8 @@ export class DocMoveCursorController extends Disposable { style, }, ], false); + + this._scrollToFocusNodePosition(docDataModel.getUnitId(), newActiveRange.endOffset); } } @@ -298,6 +303,8 @@ export class DocMoveCursorController extends Disposable { style, }, ], false); + + this._scrollToFocusNodePosition(docDataModel.getUnitId(), cursor); } else { const startNode = skeleton.findNodeByCharIndex(startOffset, segmentId, segmentPage); const endNode = skeleton.findNodeByCharIndex(endOffset, segmentId, segmentPage); @@ -331,6 +338,7 @@ export class DocMoveCursorController extends Disposable { style, }, ], false); + return; } @@ -346,6 +354,8 @@ export class DocMoveCursorController extends Disposable { style, }, ], false); + + this._scrollToFocusNodePosition(docDataModel.getUnitId(), newActiveRange.endOffset); } } @@ -552,6 +562,20 @@ export class DocMoveCursorController extends Disposable { } } + private _scrollToFocusNodePosition(unitId: string, offset: number) { + const backScrollController = this._renderManagerService.getRenderById(unitId)?.with(DocBackScrollRenderController); + if (backScrollController == null) { + return; + } + + // Scroll to the offset. + backScrollController.scrollToRange({ + startOffset: offset, + endOffset: offset, + collapsed: true, + }); + } + private _getDocObject() { return getDocObject(this._univerInstanceService, this._renderManagerService); } 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 b16c57ecf5..6f96011915 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 @@ -14,14 +14,12 @@ * limitations under the License. */ -import { Inject, IUniverInstanceService, RxDisposable } from '@univerjs/core'; +import { Inject, RxDisposable } from '@univerjs/core'; import { DocSelectionManagerService, DocSkeletonManagerService } from '@univerjs/docs'; -import { IRenderManagerService } from '@univerjs/engine-render'; import { IEditorService } from '@univerjs/ui'; import { takeUntil } from 'rxjs'; import type { DocumentDataModel, ITextRange, Nullable } from '@univerjs/core'; -import type { INodePosition, IRenderContext, IRenderModule } from '@univerjs/engine-render'; -import { getDocObject } from '../../basics/component-tools'; +import type { Documents, INodePosition, IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { VIEWPORT_KEY } from '../../basics/docs-view-key'; import { NodePositionConvertToCursor } from '../../services/selection/convert-text-range'; import { getAnchorBounding } from '../../services/selection/text-range'; @@ -33,8 +31,7 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend private readonly _context: IRenderContext, @Inject(DocSelectionManagerService) private readonly _textSelectionManagerService: DocSelectionManagerService, @IEditorService private readonly _editorService: IEditorService, - @Inject(IUniverInstanceService) private readonly _univerInstanceService: IUniverInstanceService, - @IRenderManagerService private readonly _renderManagerService: IRenderManagerService + @Inject(DocSkeletonManagerService) private readonly _docSkeletonManagerService: DocSkeletonManagerService ) { super(); @@ -49,34 +46,34 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend const { isEditing, unitId } = params; - if (isEditing) { - this._scrollToSelection(unitId); + if (unitId !== this._context.unitId || !isEditing) { + return; } + + this._scrollToSelection(); }); } - scrollToRange(unitId: string, range: ITextRange) { - const docSkeletonManagerService = this._renderManagerService.getRenderById(unitId)?.with(DocSkeletonManagerService); - const skeleton = docSkeletonManagerService?.getSkeleton(); + scrollToRange(range: ITextRange) { + const skeleton = this._docSkeletonManagerService.getSkeleton(); if (!skeleton) { return; } const { startOffset } = range; const anchorNodePosition = skeleton.findNodePositionByCharIndex(startOffset); - // const focusNodePosition = startOffset !== endOffset ? skeleton.findNodePositionByCharIndex(endOffset) : null; - this.scrollToNode(unitId, anchorNodePosition); + + this.scrollToNode(anchorNodePosition); } - scrollToNode(unitId: string, startNodePosition: Nullable) { - const docObject = this._getDocObject(); - const docSkeletonManagerService = this._renderManagerService.getRenderById(unitId)?.with(DocSkeletonManagerService); - const skeleton = docSkeletonManagerService?.getSkeleton(); + scrollToNode(startNodePosition: Nullable) { + const { unitId, scene, mainComponent } = this._context; + const skeleton = this._docSkeletonManagerService.getSkeleton(); - if (docObject == null || skeleton == null) { + if (mainComponent == null || skeleton == null) { return; } - const documentOffsetConfig = docObject.document.getOffsetConfig(); + const documentOffsetConfig = (mainComponent as Documents).getOffsetConfig(); const { docsLeft, docsTop } = documentOffsetConfig; const convertor = new NodePositionConvertToCursor(documentOffsetConfig, skeleton); @@ -89,7 +86,7 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend const top = aTop + docsTop; - const viewportMain = docObject.scene.getViewport(VIEWPORT_KEY.VIEW_MAIN); + const viewportMain = scene.getViewport(VIEWPORT_KEY.VIEW_MAIN); const isEditor = !!this._editorService.getEditor(unitId); @@ -126,7 +123,7 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend } // Let the selection show on the current screen. - private _scrollToSelection(unitId: string) { + private _scrollToSelection() { const activeTextRange = this._textSelectionManagerService.getActiveTextRange(); if (activeTextRange == null) { return; @@ -138,10 +135,6 @@ export class DocBackScrollRenderController extends RxDisposable implements IRend return; } - this.scrollToNode(unitId, startNodePosition); - } - - private _getDocObject() { - return getDocObject(this._univerInstanceService, this._renderManagerService); + this.scrollToNode(startNodePosition); } } diff --git a/packages/docs-ui/src/services/selection/doc-selection-render.service.ts b/packages/docs-ui/src/services/selection/doc-selection-render.service.ts index 4f6ef5f170..8bbff15422 100644 --- a/packages/docs-ui/src/services/selection/doc-selection-render.service.ts +++ b/packages/docs-ui/src/services/selection/doc-selection-render.service.ts @@ -448,6 +448,10 @@ export class DocSelectionRenderService extends RxDisposable implements IRenderMo this._moving(moveOffsetX, moveOffsetY); + scrollTimer.scrolling(moveOffsetX, moveOffsetY, () => { + this._moving(moveOffsetX, moveOffsetY); + }); + preMoveOffsetX = moveOffsetX; preMoveOffsetY = moveOffsetY; })); diff --git a/packages/sheets-zen-editor/src/commands/commands/zen-editor.command.ts b/packages/sheets-zen-editor/src/commands/commands/zen-editor.command.ts index 1d83b8f8f7..df5919aa6c 100644 --- a/packages/sheets-zen-editor/src/commands/commands/zen-editor.command.ts +++ b/packages/sheets-zen-editor/src/commands/commands/zen-editor.command.ts @@ -29,7 +29,7 @@ function scrollToTop(accessor: IAccessor) { endOffset: 0, }; if (backScrollController) { - backScrollController.scrollToRange(DOCS_ZEN_EDITOR_UNIT_ID_KEY, textRange as ITextRange); + backScrollController.scrollToRange(textRange as ITextRange); } }