From 8d46a657e4e3478c8ec817a1d62dd29f46387e11 Mon Sep 17 00:00:00 2001 From: Wenzhao Hu <12122021+wzhudev@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:00:36 +0800 Subject: [PATCH 1/5] feat(uni-formula): support slide --- .../uni-formula-ui/package.json | 2 + .../{command.ts => commands/doc.command.ts} | 3 +- .../src/commands/commands/slide.command.ts | 74 +++++++++++ .../uni-formula-ui/src/commands/operation.ts | 60 --------- .../src/commands/operations/doc.operation.ts | 78 ++++++++++++ ...ler.ts => doc-formula-input.controller.ts} | 46 +++---- .../slide-formula-input.controller.ts | 108 ++++++++++++++++ .../controllers/uni-formula-ui.controller.ts | 38 ++++++ .../src/services/formula-popup.service.ts | 52 +++++--- .../slide-ui-formula-cache.service.ts | 46 +++++++ .../src/services/uni-formula.service.ts | 115 +++++++++++++---- .../src/uni-formula-ui.plugin.ts | 12 +- .../src/views/components/DocFormulaPopup.tsx | 23 ++-- packages-experimental/uni-formula/README.md | 2 +- .../doc-formula.mutation.ts} | 13 +- .../mutations/slide-formua.mutation.ts | 58 +++++++++ .../uni-formula/src/const.ts | 4 +- .../src/controller/uni-formula.controller.ts | 2 +- .../uni-formula/src/index.ts | 7 +- .../uni-formula/src/models/slide-formula.ts | 50 ++++++++ .../src/services/uni-formula.service.ts | 116 ++++++++++++------ .../uni-formula/src/uni-formula.plugin.ts | 4 +- .../slide-editing.render-controller.ts | 15 +-- packages/slides-ui/src/index.ts | 1 + pnpm-lock.yaml | 3 + 25 files changed, 730 insertions(+), 202 deletions(-) rename packages-experimental/uni-formula-ui/src/commands/{command.ts => commands/doc.command.ts} (99%) create mode 100644 packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts delete mode 100644 packages-experimental/uni-formula-ui/src/commands/operation.ts create mode 100644 packages-experimental/uni-formula-ui/src/commands/operations/doc.operation.ts rename packages-experimental/uni-formula-ui/src/controllers/{formula-input.controller.ts => doc-formula-input.controller.ts} (75%) create mode 100644 packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts create mode 100644 packages-experimental/uni-formula-ui/src/controllers/uni-formula-ui.controller.ts create mode 100644 packages-experimental/uni-formula-ui/src/services/slide-ui-formula-cache.service.ts rename packages-experimental/uni-formula/src/commands/{mutation.ts => mutations/doc-formula.mutation.ts} (89%) create mode 100644 packages-experimental/uni-formula/src/commands/mutations/slide-formua.mutation.ts create mode 100644 packages-experimental/uni-formula/src/models/slide-formula.ts diff --git a/packages-experimental/uni-formula-ui/package.json b/packages-experimental/uni-formula-ui/package.json index 3bda4dd0ccc..5a0f86b8bd8 100644 --- a/packages-experimental/uni-formula-ui/package.json +++ b/packages-experimental/uni-formula-ui/package.json @@ -64,6 +64,7 @@ "@univerjs/docs-ui": "workspace:*", "@univerjs/rpc": "workspace:*", "@univerjs/sheets-formula": "workspace:*", + "@univerjs/slides-ui": "workspace:*", "@univerjs/ui": "workspace:*", "@univerjs/uni-formula": "workspace:*", "clsx": ">=2.0.0", @@ -79,6 +80,7 @@ "@univerjs/rpc": "workspace:*", "@univerjs/shared": "workspace:*", "@univerjs/sheets-formula": "workspace:*", + "@univerjs/slides-ui": "workspace:*", "@univerjs/ui": "workspace:*", "@univerjs/uni-formula": "workspace:*", "clsx": "^2.1.1", diff --git a/packages-experimental/uni-formula-ui/src/commands/command.ts b/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts similarity index 99% rename from packages-experimental/uni-formula-ui/src/commands/command.ts rename to packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts index 4f9746e6e19..b9614323142 100644 --- a/packages-experimental/uni-formula-ui/src/commands/command.ts +++ b/packages-experimental/uni-formula-ui/src/commands/commands/doc.command.ts @@ -22,8 +22,9 @@ import { AddDocUniFormulaMutation, RemoveDocUniFormulaMutation, UpdateDocUniForm export interface IAddDocUniFormulaCommandParams { unitId: string; - f: string; startIndex: number; + + f: string; } export const AddDocUniFormulaCommand: ICommand = { 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 new file mode 100644 index 00000000000..aac0d680110 --- /dev/null +++ b/packages-experimental/uni-formula-ui/src/commands/commands/slide.command.ts @@ -0,0 +1,74 @@ +/** + * 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 { 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 { SlideUIFormulaCacheService } from '../../services/slide-ui-formula-cache.service'; + +export interface IAddSlideUniFormulaCommandParams { + unitId: string; + pageId: string; + elementId: string; + startIndex: number; + + f: string; +} + +export const AddSlideUniFormulaCommand: ICommand = { + type: CommandType.COMMAND, + id: 'slide.command.add-slide-uni-formula', + async handler(accessor, params: IAddSlideUniFormulaCommandParams) { + const { f, startIndex } = params; + + const commandService = accessor.get(ICommandService); + const slideUiFormulaCacheService = accessor.get(SlideUIFormulaCacheService); + const localeService = accessor.get(LocaleService); + + // TODO: use placeholder here? + const rangeId = generateRandomId(); + const dataStream = makeCustomRangeStream(f); + const body: IDocumentBody = { + dataStream, + customRanges: [{ + startIndex: 0, + endIndex: dataStream.length - 1, + rangeId, + rangeType: CustomRangeType.UNI_FORMULA, + wholeEntity: true, + }], + }; + + const insertCustomRangeMutation = replaceSelectionFactory(accessor, { + unitId: SLIDE_EDITOR_ID, + body, + selection: makeSelection(startIndex, startIndex + 1), + }); + + // NOTE: For slides, the process to update a element's content is pretty different from docs. + // Since the text editor in slides is temporary, we don't need to update the content of the element when user + // has not confirmed the change. So we don't need to add a mutation to update resources here. + // We will do that when user confirms the change. + + if (insertCustomRangeMutation) { + slideUiFormulaCacheService.writeCache(params); + return commandService.executeCommand(insertCustomRangeMutation.id, insertCustomRangeMutation.params, { onlyLocal: true }); + } + + return false; + }, +}; diff --git a/packages-experimental/uni-formula-ui/src/commands/operation.ts b/packages-experimental/uni-formula-ui/src/commands/operation.ts deleted file mode 100644 index aa91b6c4f72..00000000000 --- a/packages-experimental/uni-formula-ui/src/commands/operation.ts +++ /dev/null @@ -1,60 +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 { ICommand, IOperation } from '@univerjs/core'; -import { CommandType } from '@univerjs/core'; -import { DocFormulaPopupService } from '../services/formula-popup.service'; - -export interface IShowFormulaPopupOperationParams { - unitId: string; - startIndex: number; - - type?: 'new' | 'existing'; - rangeId?: string; -} - -export const ShowFormulaPopupOperation: IOperation = { - id: 'doc.operation.show-formula-popup', - type: CommandType.OPERATION, - handler(accessor, params: IShowFormulaPopupOperationParams) { - const { type = 'new', startIndex, unitId, rangeId } = params; - const docFormulaPopupService = accessor.get(DocFormulaPopupService); - - if (type === 'existing' && !rangeId) { - return false; - } - - return docFormulaPopupService.showPopup(unitId, startIndex, type, rangeId); - }, -}; - -export const CloseFormulaPopupOperation: IOperation = { - id: 'doc.operation.close-formula-popup', - type: CommandType.OPERATION, - handler(accessor) { - const docFormulaPopupService = accessor.get(DocFormulaPopupService); - return docFormulaPopupService.closePopup(true); - }, -}; - -export const ConfirmFormulaPopupCommand: ICommand = { - id: 'doc.operation.confirm-formula-popup', - type: CommandType.COMMAND, - handler(accessor) { - const docFormulaPopupService = accessor.get(DocFormulaPopupService); - return docFormulaPopupService.confirmPopup(); - }, -}; diff --git a/packages-experimental/uni-formula-ui/src/commands/operations/doc.operation.ts b/packages-experimental/uni-formula-ui/src/commands/operations/doc.operation.ts new file mode 100644 index 00000000000..836e3ffc1bf --- /dev/null +++ b/packages-experimental/uni-formula-ui/src/commands/operations/doc.operation.ts @@ -0,0 +1,78 @@ +/** + * 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 { ICommand, IOperation } from '@univerjs/core'; +import { CommandType } from '@univerjs/core'; +import { UniFormulaPopupService } from '../../services/formula-popup.service'; + +export interface IDocPopupPosition { + rangeId?: string; +} + +export interface ISlidePopupPosition extends IDocPopupPosition { + pageId: string; + elementId: string; +} + +export type IPopupPosition = IDocPopupPosition | ISlidePopupPosition; + +export function isSlidePosition(position?: IPopupPosition): position is ISlidePopupPosition { + return !!position && 'pageId' in position; +} + +export interface IShowDocFormulaPopupOperationParams { + unitId: string; + startIndex: number; + type?: 'new' | 'existing'; + position: IDocPopupPosition; +} + +export interface IShowSlideFormulaPopupOPerationParams extends IShowDocFormulaPopupOperationParams { + position: ISlidePopupPosition; +} + +export type IShowFormulaPopupOperationParams = IShowDocFormulaPopupOperationParams | IShowSlideFormulaPopupOPerationParams; + +export const ShowFormulaPopupOperation: IOperation = { + id: 'uni-formula.operation.show-formula-popup', + type: CommandType.OPERATION, + handler(accessor, params: IShowFormulaPopupOperationParams) { + const { type = 'new', startIndex, unitId, position } = params; + const { rangeId } = position; + const formulaPopupService = accessor.get(UniFormulaPopupService); + + if (type === 'existing' && !rangeId) return false; + return formulaPopupService.showDocPopup(unitId, startIndex, type, position); + }, +}; + +export const CloseFormulaPopupOperation: IOperation = { + id: 'uni-formula.operation.close-formula-popup', + type: CommandType.OPERATION, + handler(accessor) { + const docFormulaPopupService = accessor.get(UniFormulaPopupService); + return docFormulaPopupService.closePopup(true); + }, +}; + +export const ConfirmFormulaPopupCommand: ICommand = { + id: 'uni-formula.operation.confirm-formula-popup', + type: CommandType.COMMAND, + handler(accessor) { + const docFormulaPopupService = accessor.get(UniFormulaPopupService); + return docFormulaPopupService.confirmPopup(); + }, +}; diff --git a/packages-experimental/uni-formula-ui/src/controllers/formula-input.controller.ts b/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts similarity index 75% rename from packages-experimental/uni-formula-ui/src/controllers/formula-input.controller.ts rename to packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts index 0244f5fb01a..12ab9f662e4 100644 --- a/packages-experimental/uni-formula-ui/src/controllers/formula-input.controller.ts +++ b/packages-experimental/uni-formula-ui/src/controllers/doc-formula-input.controller.ts @@ -17,53 +17,45 @@ 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 { ComponentManager, IEditorService } from '@univerjs/ui'; +import { IEditorService } from '@univerjs/ui'; import { DocHoverManagerService } from '@univerjs/docs-ui'; -import { AddDocUniFormulaCommand, RemoveDocUniFormulaCommand, UpdateDocUniFormulaCommand } from '../commands/command'; -import type { IShowFormulaPopupOperationParams } from '../commands/operation'; -import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand, ShowFormulaPopupOperation } from '../commands/operation'; -import { DocFormulaPopup, DOCS_UNI_FORMULA_EDITOR_UNIT_ID_KEY } from '../views/components/DocFormulaPopup'; -import { DocFormulaPopupService } from '../services/formula-popup.service'; +import { AddDocUniFormulaCommand, RemoveDocUniFormulaCommand, UpdateDocUniFormulaCommand } from '../commands/commands/doc.command'; +import type { IShowFormulaPopupOperationParams } from '../commands/operations/doc.operation'; +import { CloseFormulaPopupOperation, ShowFormulaPopupOperation } from '../commands/operations/doc.operation'; +import { UNI_FORMULA_EDITOR_ID } from '../views/components/DocFormulaPopup'; +import { UniFormulaPopupService } from '../services/formula-popup.service'; const FORMULA_INPUT_TRIGGER_CHAR = '='; -@OnLifecycle(LifecycleStages.Steady, DocUniFormulaController) -export class DocUniFormulaController extends Disposable { +@OnLifecycle(LifecycleStages.Steady, DocUniFormulaInputController) +export class DocUniFormulaInputController extends Disposable { constructor( @ICommandService private readonly _commandService: ICommandService, @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, @IEditorService private readonly _editorService: IEditorService, @ILogService private readonly _logService: ILogService, - @Inject(DocHoverManagerService) private readonly _docHoverManagerService: DocHoverManagerService, - @Inject(DocFormulaPopupService) private readonly _docFormulaPopupService: DocFormulaPopupService, - @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, - @Inject(ComponentManager) private readonly _componentManager: ComponentManager + @Inject(DocHoverManagerService) private readonly _docHoverManagerSrv: DocHoverManagerService, + @Inject(UniFormulaPopupService) private readonly _formulaPopupSrv: UniFormulaPopupService, + @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService ) { super(); this._initKeyboardListeners(); - this._initComponents(); this._initCommands(); this._initHoverListener(); } private _initCommands(): void { [ - ShowFormulaPopupOperation, - CloseFormulaPopupOperation, - ConfirmFormulaPopupCommand, AddDocUniFormulaCommand, RemoveDocUniFormulaCommand, UpdateDocUniFormulaCommand, ].forEach((command) => this._commandService.registerCommand(command)); } - private _initComponents(): void { - this.disposeWithMe(this._componentManager.register(DocFormulaPopup.componentKey, DocFormulaPopup)); - } - private _initKeyboardListeners(): void { + // TODO@wzhudev: only need to listen when a doc unit is focused. // The formula input trigger works not exactly the same as Mention. this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => { const currentEditor = this._editorService.getFocusEditor(); @@ -72,7 +64,7 @@ export class DocUniFormulaController extends Disposable { const { id } = commandInfo; if ( - currentEditor?.editorUnitId === DOCS_UNI_FORMULA_EDITOR_UNIT_ID_KEY || + currentEditor?.editorUnitId === UNI_FORMULA_EDITOR_ID || focusedUnit?.type !== UniverInstanceType.UNIVER_DOC ) { return; @@ -86,7 +78,7 @@ export class DocUniFormulaController extends Disposable { startIndex: activeRange.startOffset! - 1, unitId: focusedUnit.getUnitId(), }); - } else if (this._docFormulaPopupService.popupInfo) { + } else if (this._formulaPopupSrv.popupInfo) { this._closePopup(); } } @@ -98,13 +90,13 @@ export class DocUniFormulaController extends Disposable { } private _initHoverListener(): void { - this.disposeWithMe(this._docHoverManagerService.activeCustomRanges$.subscribe((customRanges) => { + this.disposeWithMe(this._docHoverManagerSrv.activeCustomRanges$.subscribe((customRanges) => { const focusedUnit = this._instanceSrv.getFocusedUnit(); if ( !focusedUnit || - this._docFormulaPopupService.popupInfo?.type === 'new' || - this._docFormulaPopupService.popupLocked + this._formulaPopupSrv.popupInfo?.type === 'new' || + this._formulaPopupSrv.popupLocked ) { return; } @@ -126,7 +118,7 @@ export class DocUniFormulaController extends Disposable { } })); - this.disposeWithMe(this._docFormulaPopupService.popupHovered$.subscribe((hovered) => { + this.disposeWithMe(this._formulaPopupSrv.popupHovered$.subscribe((hovered) => { if (hovered) { this._removeTimer(); } @@ -151,7 +143,7 @@ export class DocUniFormulaController extends Disposable { private _closePopupTimer: number | null = null; private _closePopup(timeout: number = 0): void { - if (!this._docFormulaPopupService.popupInfo) { + if (!this._formulaPopupSrv.popupInfo) { return; } 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 new file mode 100644 index 00000000000..83a44551c34 --- /dev/null +++ b/packages-experimental/uni-formula-ui/src/controllers/slide-formula-input.controller.ts @@ -0,0 +1,108 @@ +/** + * 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 { Disposable, ICommandService, Inject, 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 { AddSlideUniFormulaCommand } from '../commands/commands/slide.command'; +import { UNI_FORMULA_EDITOR_ID } from '../views/components/DocFormulaPopup'; +import { UniFormulaPopupService } from '../services/formula-popup.service'; +import type { IShowFormulaPopupOperationParams, ISlidePopupPosition } from '../commands/operations/doc.operation'; +import { CloseFormulaPopupOperation, ShowFormulaPopupOperation } from '../commands/operations/doc.operation'; + +const FORMULA_INPUT_TRIGGER_CHAR = '='; + +@OnLifecycle(LifecycleStages.Steady, SlideUniFormulaInputController) +export class SlideUniFormulaInputController extends Disposable { + constructor( + @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, + @ICommandService private readonly _commandSrv: ICommandService, + @IEditorService private readonly _editorSrv: IEditorService, + @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, + @Inject(UniFormulaPopupService) private readonly _formulaPopupSrv: UniFormulaPopupService + ) { + super(); + + this._initCommands(); + this._initKeyboardListeners(); + } + + private _initCommands() { + [ + AddSlideUniFormulaCommand, + ].forEach((cmd) => this._commandSrv.registerCommand(cmd)); + } + + private _initKeyboardListeners(): void { + this.disposeWithMe(this._commandSrv.onCommandExecuted((commandInfo) => { + const currentEditor = this._editorSrv.getFocusEditor(); + const focusedUnit = this._instanceSrv.getFocusedUnit(); + + const { id } = commandInfo; + + if ( + currentEditor?.editorUnitId === UNI_FORMULA_EDITOR_ID || + focusedUnit?.type !== UniverInstanceType.UNIVER_SLIDE + ) { + return; + } + + if (id === InsertCommand.id) { + const params = commandInfo.params as IInsertCommandParams; + const activeRange = this._textSelectionManagerService.getActiveTextRange(); + if (params.body.dataStream === FORMULA_INPUT_TRIGGER_CHAR && activeRange) { + this._showPopup({ + startIndex: activeRange.startOffset! - 1, + unitId: focusedUnit.getUnitId(), + position: { + // TODO@wzhudev: we should know what page and element it is + pageId: 'page123', + elementId: 'element123', + } as ISlidePopupPosition, + }); + } else if (this._formulaPopupSrv.popupInfo) { + this._closePopup(); + } + } + })); + } + + private _removeTimer(): void { + if (this._closePopupTimer !== null) { + window.clearTimeout(this._closePopupTimer); + this._closePopupTimer = null; + } + } + + private _showPopup(params: IShowFormulaPopupOperationParams): void { + this._removeTimer(); + this._commandSrv.executeCommand(ShowFormulaPopupOperation.id, params); + } + + private _closePopupTimer: number | null = null; + private _closePopup(timeout: number = 0): void { + if (!this._formulaPopupSrv.popupInfo) { + return; + } + + if (timeout === 0) { + this._commandSrv.executeCommand(CloseFormulaPopupOperation.id); + } else { + this._closePopupTimer = window.setTimeout(() => this._closePopup(0), timeout); + } + } +} diff --git a/packages-experimental/uni-formula-ui/src/controllers/uni-formula-ui.controller.ts b/packages-experimental/uni-formula-ui/src/controllers/uni-formula-ui.controller.ts new file mode 100644 index 00000000000..adbd5a60fa9 --- /dev/null +++ b/packages-experimental/uni-formula-ui/src/controllers/uni-formula-ui.controller.ts @@ -0,0 +1,38 @@ +/** + * 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 { Disposable, ICommandService, Inject, LifecycleStages, OnLifecycle } from '@univerjs/core'; +import { ComponentManager } from '@univerjs/ui'; +import { UniFormulaPopup } from '../views/components/DocFormulaPopup'; +import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand, ShowFormulaPopupOperation } from '../commands/operations/doc.operation'; + +@OnLifecycle(LifecycleStages.Steady, UniFormulaUniController) +export class UniFormulaUniController extends Disposable { + constructor( + @ICommandService private readonly _commandSrv: ICommandService, + @Inject(ComponentManager) private readonly _componentManager: ComponentManager + ) { + super(); + + [ + ShowFormulaPopupOperation, + CloseFormulaPopupOperation, + ConfirmFormulaPopupCommand, + ].forEach((command) => this._commandSrv.registerCommand(command)); + + this.disposeWithMe(this._componentManager.register(UniFormulaPopup.componentKey, UniFormulaPopup)); + } +} 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 2bf76393291..f3f294123e4 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 @@ -23,29 +23,28 @@ import type { IShortcutItem } from '@univerjs/ui'; import { IShortcutService, KeyCode } from '@univerjs/ui'; import { FORMULA_PROMPT_ACTIVATED } from '@univerjs/sheets-formula'; import { IUniFormulaService } from '@univerjs/uni-formula'; -import type { IAddDocUniFormulaCommandParams } from '../commands/command'; -import { AddDocUniFormulaCommand } from '../commands/command'; -import { ConfirmFormulaPopupCommand } from '../commands/operation'; +import type { IAddDocUniFormulaCommandParams } from '../commands/commands/doc.command'; +import { AddDocUniFormulaCommand } from '../commands/commands/doc.command'; +import type { IPopupPosition } from '../commands/operations/doc.operation'; +import { ConfirmFormulaPopupCommand, isSlidePosition } from '../commands/operations/doc.operation'; +import type { IAddSlideUniFormulaCommandParams } from '../commands/commands/slide.command'; +import { AddSlideUniFormulaCommand } from '../commands/commands/slide.command'; export const DOC_FORMULA_POPUP_KEY = 'DOC_FORMULA_POPUP' as const; -export interface IDocFormulaPopupInfo { +export interface IUniFormulaPopupInfo { unitId: string; - - /** If the popup is for inserting a formula or inspecting an existing formula. */ type: 'new' | 'existing'; - f: Nullable; - disposable: IDisposable; - startIndex: number; + position?: IPopupPosition; } -export class DocFormulaPopupService extends Disposable { - private readonly _popupInfo$ = new BehaviorSubject>(null); +export class UniFormulaPopupService extends Disposable { + private readonly _popupInfo$ = new BehaviorSubject>(null); readonly popupInfo$ = this._popupInfo$.asObservable(); - get popupInfo(): Nullable { return this._popupInfo$.getValue(); } + get popupInfo(): Nullable { return this._popupInfo$.getValue(); } private _popupLocked = false; get popupLocked(): boolean { return this._popupLocked; } @@ -94,22 +93,24 @@ export class DocFormulaPopupService extends Disposable { this._popupHovered$.next(hovered); } - showPopup(unitId: string, startIndex: number, type: 'new'): boolean; - showPopup(unitId: string, startIndex: number, type: 'existing', rangeId: string): boolean; - showPopup(unitId: string, startIndex: number, type: 'new' | 'existing', rangeId?: string): boolean; - showPopup(unitId: string, startIndex: number, type: 'new' | 'existing', rangeId?: string): boolean { + showDocPopup(unitId: string, startIndex: number, type: 'new'): boolean; + showDocPopup(unitId: string, startIndex: number, type: 'existing', position: IPopupPosition): boolean; + showDocPopup(unitId: string, startIndex: number, type: 'new' | 'existing', position?: IPopupPosition): boolean; + showDocPopup(unitId: string, startIndex: number, type: 'new' | 'existing', position?: IPopupPosition): boolean { this.closePopup(); - const f = (rangeId && type === 'existing') - ? this._uniFormulaService.getFormulaWithRangeId(unitId, rangeId)?.f ?? '=' + // Open existing doc formula. + const f = (position && position.rangeId && type === 'existing') + ? this._uniFormulaService.getDocFormula(unitId, position.rangeId)?.f ?? '=' : '='; + const disposable = this._docCanvasPopupManagerService.attachPopupToRange(makeSelection(startIndex), { componentKey: DOC_FORMULA_POPUP_KEY, onClickOutside: () => this.closePopup(), // user may update ref range selections direction: 'top', }); - this._popupInfo$.next({ unitId, disposable, type, f, startIndex }); + this._popupInfo$.next({ unitId, disposable, type, f, startIndex, position }); return true; } @@ -135,7 +136,18 @@ export class DocFormulaPopupService extends Disposable { this.unlockPopup(); this.closePopup(); - // write this formula string to doc + // Write to slide. + if (isSlidePosition(info.position)) { + return this._commandService.executeCommand(AddSlideUniFormulaCommand.id, { + unitId: info.unitId, + f, + startIndex: info.startIndex, + pageId: info.position.pageId, + elementId: info.position.elementId, + }); + } + + // Write to doc. return this._commandService.executeCommand(AddDocUniFormulaCommand.id, { unitId: info.unitId, f, diff --git a/packages-experimental/uni-formula-ui/src/services/slide-ui-formula-cache.service.ts b/packages-experimental/uni-formula-ui/src/services/slide-ui-formula-cache.service.ts new file mode 100644 index 00000000000..638ab51b38a --- /dev/null +++ b/packages-experimental/uni-formula-ui/src/services/slide-ui-formula-cache.service.ts @@ -0,0 +1,46 @@ +/** + * 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 { Disposable } from '@univerjs/core'; +import { IUniFormulaService } from '@univerjs/uni-formula'; +import type { IAddSlideUniFormulaCommandParams } from '../commands/commands/slide.command'; +import type { UniFormulaService } from './uni-formula.service'; + +export class SlideUIFormulaCacheService extends Disposable { + private readonly _caches: IAddSlideUniFormulaCommandParams[] = []; + + constructor( + @IUniFormulaService private readonly _uniFormulaService: UniFormulaService + ) { + super(); + } + + writeCache(params: IAddSlideUniFormulaCommandParams) { + if (this._caches.length && this._caches[this._caches.length - 1].elementId === params.elementId) { + this._caches.length = 0; + } + + this._caches.push(params); + } + + applyCache() { + + } + + abortCache() { + this._caches.length = 0; + } +} 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 6c118314b7d..51921135ff7 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 @@ -21,7 +21,8 @@ import type { IDisposable, IDocumentBody, Nullable, -} from '@univerjs/core'; + + SlideDataModel } from '@univerjs/core'; import { CommandType, CustomRangeType, @@ -39,14 +40,19 @@ import { import { makeSelection, replaceSelectionFactory } from '@univerjs/docs'; import { DataSyncPrimaryController } from '@univerjs/rpc'; import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; -import type { IDocFormulaCache } from '@univerjs/uni-formula'; +import type { IDocFormulaCache, ISlideFormulaCache } from '@univerjs/uni-formula'; import { DumbUniFormulaService, IUniFormulaService } from '@univerjs/uni-formula'; import { take } from 'rxjs'; +import type { ISlidePopupPosition } from '../commands/operations/doc.operation'; + +const PSEUDO_SUBUNIT = 'PSEUDO_SUBUNIT'; + +export interface IUpdateSlideUniFormulaCacheCommandParams { + unitId: string; + positions: ISlidePopupPosition[]; + cache: ISlideFormulaCache[]; +} -const DOC_PSEUDO_SUBUNIT = 'DOC_PSEUDO_SUBUNIT'; -/** - * Update calculating result in a batch. - */ export interface IUpdateDocUniFormulaCacheCommandParams { /** The doc in which formula results changed. */ unitId: string; @@ -56,6 +62,26 @@ export interface IUpdateDocUniFormulaCacheCommandParams { cache: IDocFormulaCache[]; } +export const UpdateSlideUniFormulaCacheCommand: ICommand = { + type: CommandType.COMMAND, + id: 'uni-formula.mutation.update-slide-uni-formula-cache', + handler(accessor, params: IUpdateSlideUniFormulaCacheCommandParams) { + const { unitId, positions, cache } = params; + + const uniFormulaService = accessor.get(IUniFormulaService); + const instanceService = accessor.get(IUniverInstanceService); + const commandService = accessor.get(ICommandService); + + const slide = instanceService.getUnit(unitId, UniverInstanceType.UNIVER_SLIDE); + if (!slide) return true; + + return positions.every((position, index) => { + // TODO@wzhudev: how to directly change the content of a slide element? + return true; + }); + }, +}; + /** * This command is internal. It should not be exposed to third-party developers. * @@ -63,7 +89,7 @@ export interface IUpdateDocUniFormulaCacheCommandParams { */ export const UpdateDocUniFormulaCacheCommand: ICommand = { type: CommandType.COMMAND, - id: 'doc.mutation.update-doc-uni-formula-cache', + id: 'uni-formula.mutation.update-doc-uni-formula-cache', handler(accessor, params: IUpdateDocUniFormulaCacheCommandParams) { const { unitId, ids, cache } = params; @@ -71,11 +97,11 @@ export const UpdateDocUniFormulaCacheCommand: ICommand(unitId, UniverInstanceType.UNIVER_DOC); + const doc = instanceService.getUnit(unitId, UniverInstanceType.UNIVER_DOC); + // The document may have not loaded on this client. We are safe to ignore cache updating. + if (!doc) return true; - /** The document may have not loaded on this client. We are safe to ignore cache updating. */ - if (!data) return true; - const body = data.getBody(); + const body = doc.getBody(); function getRange(rangeId: string) { return body?.customRanges?.find((r) => r.rangeId === rangeId); @@ -164,7 +190,7 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm const pseudoId = getPseudoUnitKey(unitId); this._checkSyncingUnit(pseudoId); - const id = this._registerOtherFormulaSrv.registerFormula(pseudoId, DOC_PSEUDO_SUBUNIT, f); + const id = this._registerOtherFormulaSrv.registerFormula(pseudoId, PSEUDO_SUBUNIT, f); this._docFormulas.set(key, { unitId, rangeId, f, formulaId: id, v, t }); this._formulaIdToKey.set(id, key); @@ -176,6 +202,36 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm return toDisposable(() => this.unregisterDocFormula(unitId, rangeId)); } + override registerSlideFormula( + unitId: string, + pageId: string, + elementId: string, + rangeId: string, + f: string, + v: ICellData['v'], + t: ICellData['t'] + ): IDisposable { + const key = getSlideFormulaKey(unitId, pageId, elementId, rangeId); + if (this._slideFormulas.has(key)) { + throw new Error(`[UniFormulaService]: cannot register formula ${key} when it is already registered!`); + } + + if (this._canPerformFormulaCalculation) { + const pseudoId = getPseudoUnitKey(unitId); + this._checkSyncingUnit(pseudoId); + + const id = this._registerOtherFormulaSrv.registerFormula(pseudoId, PSEUDO_SUBUNIT, f); + this._slideFormulas.set(key, { unitId, pageId, elementId, rangeId, f, formulaId: id, v, t }); + this._formulaIdToKey.set(id, key); + + this._checkResultSubscription(); + } else { + this._slideFormulas.set(key, { unitId, pageId, elementId, rangeId, f, formulaId: '', v, t }); + } + + return toDisposable(() => this.unregisterSlideFormula(unitId, pageId, elementId, rangeId)); + } + override unregisterDocFormula(unitId: string, rangeId: string): void { const key = getDocFormulaKey(unitId, rangeId); const item = this._docFormulas.get(key); @@ -186,13 +242,30 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm this._dataSyncDisposables.get(pseudoId)?.dec(); if (this._canPerformFormulaCalculation) { - this._registerOtherFormulaSrv.deleteFormula(pseudoId, DOC_PSEUDO_SUBUNIT, [item.formulaId]); + this._registerOtherFormulaSrv.deleteFormula(pseudoId, PSEUDO_SUBUNIT, [item.formulaId]); this._formulaIdToKey.delete(item.formulaId); } this._docFormulas.delete(key); } + override unregisterSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): void { + const key = getSlideFormulaKey(unitId, pageId, elementId, formulaId); + const item = this._slideFormulas.get(key); + if (!item) return; + + const pseudoId = getPseudoUnitKey(unitId); + this._checkDisposingResultSubscription(); + this._dataSyncDisposables.get(pseudoId)?.dec(); + + if (this._canPerformFormulaCalculation) { + this._registerOtherFormulaSrv.deleteFormula(pseudoId, PSEUDO_SUBUNIT, [item.formulaId]); + this._formulaIdToKey.delete(item.formulaId); + } + + this._slideFormulas.delete(key); + } + private _initFormulaRegistration(): void { // When the doc bootstraps, there could be no sheets modules loaded. So we need to check if there // are registered formulas but not added to the formula system. @@ -202,7 +275,7 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm const pseudoId = getPseudoUnitKey(unitId); this._checkSyncingUnit(pseudoId); - const id = this._registerOtherFormulaSrv.registerFormula(pseudoId, DOC_PSEUDO_SUBUNIT, f); + const id = this._registerOtherFormulaSrv.registerFormula(pseudoId, PSEUDO_SUBUNIT, f); value.formulaId = id; this._formulaIdToKey.set(id, key); } @@ -227,7 +300,7 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm this._resultSubscription = toDisposable(this._registerOtherFormulaSrv.formulaResult$.subscribe((resultMap) => { for (const resultOfUnit in resultMap) { - const results = resultMap[resultOfUnit][DOC_PSEUDO_SUBUNIT]; + const results = resultMap[resultOfUnit][PSEUDO_SUBUNIT]; if (results) { const mutationParam = results.map((result) => { const formulaId = result.formulaId; @@ -258,6 +331,8 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm if (mutationParam.ids.length === 0) return; this._commandSrv.executeCommand(UpdateDocUniFormulaCacheCommand.id, mutationParam as IUpdateDocUniFormulaCacheCommandParams); + + // TODO@wzhudev: handle slide formula cache updating. } } })); @@ -273,12 +348,6 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm this._resultSubscription = null; } } - - private _checkFormulaUsable(): void { - if (!this._canPerformFormulaCalculation && this._instanceSrv.getAllUnitsForType(UniverInstanceType.UNIVER_SHEET).length) { - this._canPerformFormulaCalculation = true; - } - } } function getPseudoUnitKey(unitId: string): string { @@ -288,3 +357,7 @@ function getPseudoUnitKey(unitId: string): string { function getDocFormulaKey(unitId: string, formulaId: string): string { return `pseudo-${unitId}-${formulaId}`; } + +function getSlideFormulaKey(unitId: string, pageId: string, elementId: string, rangeId: string): string { + return `pseudo-${unitId}-${pageId}-${elementId}-${rangeId}`; +} diff --git a/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts b/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts index 9ed4172d839..f919a12678d 100644 --- a/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts +++ b/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts @@ -19,9 +19,11 @@ import { DependentOn, Inject, Injector, Plugin, UniverInstanceType } from '@univ import { IUniFormulaService, UniverDocUniFormulaPlugin } from '@univerjs/uni-formula'; import { DOC_FORMULA_UI_PLUGIN_NAME } from './const'; -import { DocFormulaPopupService } from './services/formula-popup.service'; -import { DocUniFormulaController } from './controllers/formula-input.controller'; +import { UniFormulaPopupService } from './services/formula-popup.service'; +import { DocUniFormulaInputController } from './controllers/doc-formula-input.controller'; import { UniFormulaService } from './services/uni-formula.service'; +import { UniFormulaUniController } from './controllers/uni-formula-ui.controller'; +import { SlideUniFormulaInputController } from './controllers/slide-formula-input.controller'; @DependentOn(UniverDocUniFormulaPlugin) export class UniverDocUniFormulaUIPlugin extends Plugin { @@ -37,8 +39,10 @@ export class UniverDocUniFormulaUIPlugin extends Plugin { override onStarting(injector: Injector): void { ([ - [DocUniFormulaController], - [DocFormulaPopupService], + [UniFormulaUniController], + [DocUniFormulaInputController], + [SlideUniFormulaInputController], + [UniFormulaPopupService], [IUniFormulaService, { useClass: UniFormulaService }], ] as Dependency[]).forEach((d) => injector.add(d)); } diff --git a/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx b/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx index 89ade0d894c..b42f0c3b9ec 100644 --- a/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx +++ b/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx @@ -20,16 +20,17 @@ import { TextEditor, useObservable } from '@univerjs/ui'; import type { IDocumentData, Nullable } from '@univerjs/core'; import { BooleanNumber, createInternalEditorID, DEFAULT_EMPTY_DOCUMENT_VALUE, DocumentFlavor, HorizontalAlign, ICommandService, LocaleService, useDependency, VerticalAlign, WrapStrategy } from '@univerjs/core'; import { CheckMarkSingle, CloseSingle } from '@univerjs/icons'; -import type { IDocFormulaPopupInfo } from '../../services/formula-popup.service'; -import { DOC_FORMULA_POPUP_KEY, DocFormulaPopupService } from '../../services/formula-popup.service'; +import type { IUniFormulaPopupInfo } from '../../services/formula-popup.service'; +import { DOC_FORMULA_POPUP_KEY, UniFormulaPopupService } from '../../services/formula-popup.service'; -import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand } from '../../commands/operation'; +import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand } from '../../commands/operations/doc.operation'; import styles from './index.module.less'; -export const DOCS_UNI_FORMULA_EDITOR_UNIT_ID_KEY = createInternalEditorID('UNI_FORMULA'); +export const UNI_FORMULA_EDITOR_ID = createInternalEditorID('UNI_FORMULA'); + function makeSnapshot(f: string): IDocumentData { return { - id: DOCS_UNI_FORMULA_EDITOR_UNIT_ID_KEY, + id: UNI_FORMULA_EDITOR_ID, body: { dataStream: `${f}${DEFAULT_EMPTY_DOCUMENT_VALUE}`, textRuns: [], @@ -62,8 +63,8 @@ function makeSnapshot(f: string): IDocumentData { }; } -export function DocFormulaPopup() { - const docFormulaPopupService = useDependency(DocFormulaPopupService); +export function UniFormulaPopup() { + const docFormulaPopupService = useDependency(UniFormulaPopupService); const popupInfo = useObservable(docFormulaPopupService.popupInfo$); if (!popupInfo) { @@ -73,14 +74,14 @@ export function DocFormulaPopup() { return ; } -DocFormulaPopup.componentKey = DOC_FORMULA_POPUP_KEY; +UniFormulaPopup.componentKey = DOC_FORMULA_POPUP_KEY; -function DocFormula(props: { popupInfo: IDocFormulaPopupInfo }) { +function DocFormula(props: { popupInfo: IUniFormulaPopupInfo }) { const { popupInfo } = props; const { f } = popupInfo; const localeService = useDependency(LocaleService); - const formulaPopupService = useDependency(DocFormulaPopupService); + const formulaPopupService = useDependency(UniFormulaPopupService); const commandService = useDependency(ICommandService); const [formulaString, setFormulaString] = useState>(f); @@ -122,7 +123,7 @@ function DocFormula(props: { popupInfo: IDocFormulaPopupInfo }) { return (
onHovered(true)} onMouseLeave={() => onHovered(false)}> = { @@ -41,8 +39,7 @@ export const AddDocUniFormulaMutation: IMutation = { type: CommandType.MUTATION, @@ -51,7 +48,7 @@ export const UpdateDocUniFormulaMutation: IMutation = { + type: CommandType.MUTATION, + id: 'slide.mutation.add-slide-uni-formula', + handler(accessor, params: IAddSlideUniFormulaMutationParams) { + const { unitId, pageId, elementId, f, rangeId: id } = params; + const uniFormulaService = accessor.get(IUniFormulaService); + + uniFormulaService.registerSlideFormula(unitId, pageId, elementId, id, f); + + return true; + }, +}; + +export interface IUpdateSlideUniFormulaMutationParams extends IAddSlideUniFormulaMutationParams {} + +export const UpdateSlideUniFormulaMutation: IMutation = { + type: CommandType.MUTATION, + id: 'slide.mutation.update-slide-uni-formula', + handler(accessor, params: IUpdateSlideUniFormulaMutationParams) { + const { unitId, pageId, elementId, f, rangeId: id } = params; + const uniFormulaService = accessor.get(IUniFormulaService); + + if (!uniFormulaService.hasSlideFormula(unitId, pageId, elementId, id)) return false; + + uniFormulaService.unregisterSlideFormula(unitId, pageId, elementId, id); + uniFormulaService.registerSlideFormula(unitId, pageId, elementId, id, f); + return true; + }, +}; diff --git a/packages-experimental/uni-formula/src/const.ts b/packages-experimental/uni-formula/src/const.ts index f64cf70de99..656c6db4c57 100644 --- a/packages-experimental/uni-formula/src/const.ts +++ b/packages-experimental/uni-formula/src/const.ts @@ -14,4 +14,6 @@ * limitations under the License. */ -export const DOC_FORMULA_PLUGIN_NAME = 'DOC_FORMULA_PLUGIN'; +export const UNI_FORMULA_PLUGIN_NAME = 'UI_FORMULA_PLUGIN'; + +export const DOC_UNI_FORMULA_RESOURCE_NAME = 'DOC_FORMULA_PLUGIN'; diff --git a/packages-experimental/uni-formula/src/controller/uni-formula.controller.ts b/packages-experimental/uni-formula/src/controller/uni-formula.controller.ts index bf8d85bb137..73a07df2556 100644 --- a/packages-experimental/uni-formula/src/controller/uni-formula.controller.ts +++ b/packages-experimental/uni-formula/src/controller/uni-formula.controller.ts @@ -15,7 +15,7 @@ */ import { ICommandService } from '@univerjs/core'; -import { AddDocUniFormulaMutation, RemoveDocUniFormulaMutation, UpdateDocUniFormulaMutation } from '../commands/mutation'; +import { AddDocUniFormulaMutation, RemoveDocUniFormulaMutation, UpdateDocUniFormulaMutation } from '../commands/mutations/doc-formula.mutation'; export class UniFormulaController { constructor( diff --git a/packages-experimental/uni-formula/src/index.ts b/packages-experimental/uni-formula/src/index.ts index 544e9043e36..d121af161f5 100644 --- a/packages-experimental/uni-formula/src/index.ts +++ b/packages-experimental/uni-formula/src/index.ts @@ -16,8 +16,9 @@ export { UniverDocUniFormulaPlugin } from './uni-formula.plugin'; export { IUniFormulaService, DumbUniFormulaService } from './services/uni-formula.service'; -export { DOC_FORMULA_PLUGIN_NAME } from './const'; -export { type IDocFormulaCache, type IDocFormulaData, type IDocFormulaReference } from './models/doc-formula'; +export { UNI_FORMULA_PLUGIN_NAME as DOC_FORMULA_PLUGIN_NAME } from './const'; +export type { IDocFormulaCache, IDocFormulaData, IDocFormulaReference } from './models/doc-formula'; +export type { ISlideFormulaCache, ISlideFormulaData, ISlideFormulaReference } from './models/slide-formula'; // #region - all commands @@ -28,6 +29,6 @@ export { AddDocUniFormulaMutation, RemoveDocUniFormulaMutation, UpdateDocUniFormulaMutation, -} from './commands/mutation'; +} from './commands/mutations/doc-formula.mutation'; // #endregion diff --git a/packages-experimental/uni-formula/src/models/slide-formula.ts b/packages-experimental/uni-formula/src/models/slide-formula.ts new file mode 100644 index 00000000000..e3d9d9050b5 --- /dev/null +++ b/packages-experimental/uni-formula/src/models/slide-formula.ts @@ -0,0 +1,50 @@ +/** + * 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 { ICellData } from '@univerjs/core'; + +export interface ISlideFormulaData { + rangeId: string; + + f: string; + + v?: ICellData['v']; + + t?: ICellData['t']; +} + +export interface ISlideFormulaReference extends ISlideFormulaData { + unitId: string; + + pageId: string; + + elementId: string; + + formulaId: string; +} + +export interface ISlideFormulaCache extends Pick { } + +export function slideToJson(formulas: ISlideFormulaReference[]): string { + return JSON.stringify(formulas.map((f) => ({ + rangeId: f.rangeId, + pageId: f.pageId, + elementId: f.elementId, + f: f.f, + v: f.v, + t: f.t, + }))); +} diff --git a/packages-experimental/uni-formula/src/services/uni-formula.service.ts b/packages-experimental/uni-formula/src/services/uni-formula.service.ts index 2b4cd88f500..25fc0762aec 100644 --- a/packages-experimental/uni-formula/src/services/uni-formula.service.ts +++ b/packages-experimental/uni-formula/src/services/uni-formula.service.ts @@ -26,68 +26,63 @@ import { } from '@univerjs/core'; import { type IDocFormulaCache, type IDocFormulaData, type IDocFormulaReference, toJson } from '../models/doc-formula'; -import { DOC_FORMULA_PLUGIN_NAME } from '../const'; +import { DOC_UNI_FORMULA_RESOURCE_NAME } from '../const'; +import type { ISlideFormulaReference } from '../models/slide-formula'; export interface IUniFormulaService { - getFormulaWithRangeId(unitId: string, rangeId: string): Nullable; - registerDocFormula(unitId: string, rangeId: string, f: string, v: ICellData['v'], t: ICellData['t']): IDisposable; + updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean; + + // #region doc + hasDocFormula(unitId: string, formulaId: string): boolean; + getDocFormula(unitId: string, rangeId: string): Nullable; + registerDocFormula(unitId: string, rangeId: string, f: string, v: ICellData['v'], t: ICellData['t']): IDisposable; unregisterDocFormula(unitId: string, rangeId: string): void; - hasFocFormula(unitId: string, formulaId: string): boolean; - updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean; + + // #endregion + + // #region slide + + hasSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): boolean; + getSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): Nullable; + registerSlideFormula(unitId: string, pageId: string, elementId: string, f: string, v: ICellData['v'], t: ICellData['t']): IDisposable; + unregisterSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): void; + + // #endregion } export const IUniFormulaService = createIdentifier('uni-formula.uni-formula.service'); +// NOTE@wzhudev: we implement formula for doc and slide here for convenience, but we should separate them in the future. + export class DumbUniFormulaService extends Disposable implements IUniFormulaService { - /** This data maps doc formula key to the formula id in the formula system. */ protected readonly _docFormulas = new Map(); + protected readonly _slideFormulas = new Map(); constructor( - @IResourceManagerService resourceManagerService: IResourceManagerService, + @IResourceManagerService resourceManagerSrv: IResourceManagerService, @ICommandService protected readonly _commandSrv: ICommandService, @IUniverInstanceService protected readonly _instanceSrv: IUniverInstanceService ) { super(); - this._initDocFormulaResources(resourceManagerService); + this._initDocFormulaResources(resourceManagerSrv); this._instanceSrv.getTypeOfUnitDisposed$(UniverInstanceType.UNIVER_DOC).subscribe((doc) => { this._unregisterDoc(doc.getUnitId()); }); } - hasFocFormula(unitId: string, formulaId: string): boolean { + // #region docs + + hasDocFormula(unitId: string, formulaId: string): boolean { return this._docFormulas.has(getDocFormulaKey(unitId, formulaId)); } - getFormulaWithRangeId(unitId: string, rangeId: string): Nullable { + getDocFormula(unitId: string, rangeId: string): Nullable { return this._docFormulas.get(getDocFormulaKey(unitId, rangeId)) ?? null; } - updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean { - formulaIds.forEach((id, index) => { - const formulaData = this._docFormulas.get(getDocFormulaKey(unitId, id)); - if (!formulaData) return true; - - formulaData.v = v[index].v; - formulaData.t = v[index].t; - return true; - }); - - return true; - } - - /** - * Remove all formulas under a doc. - */ - private _unregisterDoc(unitId: string): void { - const existingFormulas = Array.from(this._docFormulas.entries()); - existingFormulas.forEach(([_, value]) => { - if (value.unitId === unitId) this.unregisterDocFormula(unitId, value.rangeId); - }); - } - /** * Register a doc formula into the formula system. */ @@ -112,7 +107,7 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ private _initDocFormulaResources(resourceManagerService: IResourceManagerService): void { resourceManagerService.registerPluginResource({ - pluginName: DOC_FORMULA_PLUGIN_NAME, + pluginName: DOC_UNI_FORMULA_RESOURCE_NAME, businesses: [UniverInstanceType.UNIVER_DOC], toJson: (unitId: string) => { const formulas = this._getAllFormulasOfUnit(unitId); @@ -131,13 +126,64 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ }); } + /** + * Remove all formulas under a doc. + */ + private _unregisterDoc(unitId: string): void { + const existingFormulas = Array.from(this._docFormulas.entries()); + existingFormulas.forEach(([_, value]) => { + if (value.unitId === unitId) this.unregisterDocFormula(unitId, value.rangeId); + }); + } + + // #endregion + + updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean { + formulaIds.forEach((id, index) => { + const formulaData = this._docFormulas.get(getDocFormulaKey(unitId, id)); + if (!formulaData) return true; + + formulaData.v = v[index].v; + formulaData.t = v[index].t; + return true; + }); + + return true; + } + + // #region slides + + registerSlideFormula( + unitId: string, + pageId: string, + elementId: string, + f: string, + v: ICellData['v'], t: ICellData['t'] + ): IDisposable { + + } + + hasSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): boolean { + throw new Error('Method not implemented.'); + } + + getSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): Nullable { + throw new Error('Method not implemented.'); + } + + unregisterSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): void { + throw new Error('Method not implemented.'); + } + + // #endregion + private _getAllFormulasOfUnit(unitId: string) { const formulas = Array.from(this._docFormulas.entries()).filter((v) => v[1].unitId === unitId); return formulas; } } -export function getPseudoUnitKey(unitId: string): string { +export function getPseudoDocUnitKey(unitId: string): string { return `pseudo-${unitId}`; } diff --git a/packages-experimental/uni-formula/src/uni-formula.plugin.ts b/packages-experimental/uni-formula/src/uni-formula.plugin.ts index f14cff93174..8e1e338f0ad 100644 --- a/packages-experimental/uni-formula/src/uni-formula.plugin.ts +++ b/packages-experimental/uni-formula/src/uni-formula.plugin.ts @@ -17,11 +17,11 @@ import type { Dependency } from '@univerjs/core'; import { Inject, Injector, Plugin, UniverInstanceType } from '@univerjs/core'; import { DumbUniFormulaService, IUniFormulaService } from './services/uni-formula.service'; -import { DOC_FORMULA_PLUGIN_NAME } from './const'; +import { UNI_FORMULA_PLUGIN_NAME } from './const'; import { UniFormulaController } from './controller/uni-formula.controller'; export class UniverDocUniFormulaPlugin extends Plugin { - static override pluginName: string = DOC_FORMULA_PLUGIN_NAME; + static override pluginName: string = UNI_FORMULA_PLUGIN_NAME; // This plugin should load only when sheet related modules are loaded. static override type: UniverInstanceType = UniverInstanceType.UNIVER_UNKNOWN; 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 f5029dddf9b..ac8b4106ad9 100644 --- a/packages/slides-ui/src/controllers/slide-editing.render-controller.ts +++ b/packages/slides-ui/src/controllers/slide-editing.render-controller.ts @@ -27,13 +27,10 @@ import { Direction, Disposable, DisposableCollection, - DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY, EDITOR_ACTIVATED, FOCUSING_EDITOR_BUT_HIDDEN, - FOCUSING_EDITOR_INPUT_FORMULA, FOCUSING_EDITOR_STANDALONE, FOCUSING_UNIVER_EDITOR_STANDALONE_SINGLE_MODE, - FORMULA_EDITOR_ACTIVATED, HorizontalAlign, ICommandService, IContextService, @@ -719,9 +716,17 @@ export class SlideEditingRenderController extends Disposable implements IRenderM const editedMutations = [RichTextEditingMutation.id]; d.add(this._commandService.onCommandExecuted((command: ICommandInfo) => { + // Only should do something when it is the current editor. + // FIXME: listen to command execution is pretty expensive. We should + // have multi editor instances and only handle event from a single editor. + if (this._editorService.getFocusId() !== this._renderContext.unitId) { + return; + } + if (moveCursorOP.includes(command.id)) { this._moveCursorCmdHandler(command); } + if (editedMutations.includes(command.id)) { if (this._editorBridgeService.isVisible()) { this._editingChangedHandler(); @@ -806,10 +811,7 @@ export class SlideEditingRenderController extends Disposable implements IRenderM } private _exitInput(param: IEditorBridgeServiceVisibleParam) { - this._contextService.setContextValue(FOCUSING_EDITOR_INPUT_FORMULA, false); this._contextService.setContextValue(EDITOR_ACTIVATED, false); - this._contextService.setContextValue(FOCUSING_EDITOR_BUT_HIDDEN, false); - this._contextService.setContextValue(FORMULA_EDITOR_ACTIVATED, false); this._cellEditorManagerService.setState({ show: param.visible, @@ -819,7 +821,6 @@ export class SlideEditingRenderController extends Disposable implements IRenderM return; } this._undoRedoService.clearUndoRedo(editorUnitId); - this._undoRedoService.clearUndoRedo(DOCS_FORMULA_BAR_EDITOR_UNIT_ID_KEY); } private _moveCursor(keycode?: KeyCode) { diff --git a/packages/slides-ui/src/index.ts b/packages/slides-ui/src/index.ts index bdd0a3331f7..46e2b3a7ed3 100644 --- a/packages/slides-ui/src/index.ts +++ b/packages/slides-ui/src/index.ts @@ -34,3 +34,4 @@ export { SlideAddTextOperation } from './commands/operations/insert-text.operati // #endregion export { SlideEditorContainer } from './views/editor-container/EditorContainer'; +export { SLIDE_EDITOR_ID } from './const'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 902449d87e2..fe5024a657d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -511,6 +511,9 @@ importers: '@univerjs/sheets-formula': specifier: workspace:* version: link:../../packages/sheets-formula + '@univerjs/slides-ui': + specifier: workspace:* + version: link:../../packages/slides-ui '@univerjs/ui': specifier: workspace:* version: link:../../packages/ui From 35eb49d5c8ef6fa7649c39988b14a1fd63d961ed Mon Sep 17 00:00:00 2001 From: Wenzhao Hu <12122021+wzhudev@users.noreply.github.com> Date: Sun, 11 Aug 2024 06:42:53 +0800 Subject: [PATCH 2/5] feat: hook on slide formula --- .../uni-formula-ui/package.json | 2 + .../src/commands/commands/slide.command.ts | 7 +-- .../{doc.operation.ts => operation.ts} | 0 .../doc-formula-input.controller.ts | 4 +- .../slide-formula-input.controller.ts | 19 +++++--- .../controllers/uni-formula-ui.controller.ts | 2 +- .../src/services/formula-popup.service.ts | 4 +- .../slide-ui-formula-cache.service.ts | 48 +++++++++++++++---- .../src/services/uni-formula.service.ts | 2 +- .../src/uni-formula-ui.plugin.ts | 2 + .../src/views/components/DocFormulaPopup.tsx | 2 +- .../slide-editor-bridge.render-controller.ts | 5 +- packages/slides-ui/src/index.ts | 1 + .../services/slide-editor-bridge.service.ts | 13 ++++- .../services/slide-editor-manager.service.ts | 2 - pnpm-lock.yaml | 3 ++ 16 files changed, 87 insertions(+), 29 deletions(-) rename packages-experimental/uni-formula-ui/src/commands/operations/{doc.operation.ts => operation.ts} (100%) diff --git a/packages-experimental/uni-formula-ui/package.json b/packages-experimental/uni-formula-ui/package.json index 5a0f86b8bd8..613c8942b97 100644 --- a/packages-experimental/uni-formula-ui/package.json +++ b/packages-experimental/uni-formula-ui/package.json @@ -62,6 +62,7 @@ "@univerjs/core": "workspace:*", "@univerjs/docs": "workspace:*", "@univerjs/docs-ui": "workspace:*", + "@univerjs/engine-render": "workspace:*", "@univerjs/rpc": "workspace:*", "@univerjs/sheets-formula": "workspace:*", "@univerjs/slides-ui": "workspace:*", @@ -76,6 +77,7 @@ "@univerjs/design": "workspace:*", "@univerjs/docs": "workspace:*", "@univerjs/docs-ui": "workspace:*", + "@univerjs/engine-render": "workspace:*", "@univerjs/icons": "^0.1.72", "@univerjs/rpc": "workspace:*", "@univerjs/shared": "workspace:*", 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 aac0d680110..d8ebb2cb161 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 @@ -33,15 +33,16 @@ export const AddSlideUniFormulaCommand: ICommand = new Map(); constructor( + @ISlideEditorBridgeService private readonly _editorBridgeService: ISlideEditorBridgeService, @IUniFormulaService private readonly _uniFormulaService: UniFormulaService ) { super(); + + this._editorBridgeService.endEditing$.subscribe((richText) => this._checkApplyCache(richText)); } - writeCache(params: IAddSlideUniFormulaCommandParams) { - if (this._caches.length && this._caches[this._caches.length - 1].elementId === params.elementId) { - this._caches.length = 0; + writeCache(rangeId: string, params: IAddSlideUniFormulaCommandParams) { + if (this._caches.size && this._caches.values().next().value.unitId !== params.unitId) { + this.clearCache(); } - this._caches.push(params); + this._caches.set(rangeId, params); } - applyCache() { + private _checkApplyCache(richText: RichText) { + const document = richText.documentData; + const customRanges = document.body?.customRanges; + if (!customRanges || customRanges.length === 0) { + this.clearCache(); + return; + }; + + // Check if there are custom ranges in the rich text. If there are, we would write apply the cache + // to the uni formula service + customRanges.forEach((range) => { + if (range.rangeType === CustomRangeType.UNI_FORMULA) { + const cache = this._caches.get(range.rangeId); + if (cache) { + this._applyCache(range.rangeId, cache); + } else { + throw new Error('[SlideUIFormulaCacheService]: cache not found!'); + } + } + }); + + this.clearCache(); + } + private _applyCache(rangeId: string, cache: IAddSlideUniFormulaCommandParams) { + const { unitId, pageId, elementId, f } = cache; + this._uniFormulaService.registerSlideFormula(unitId, pageId, elementId, rangeId, f); } - abortCache() { - this._caches.length = 0; + clearCache() { + this._caches.clear(); } } 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 51921135ff7..83db6034428 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 @@ -43,7 +43,7 @@ import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; import type { IDocFormulaCache, ISlideFormulaCache } from '@univerjs/uni-formula'; import { DumbUniFormulaService, IUniFormulaService } from '@univerjs/uni-formula'; import { take } from 'rxjs'; -import type { ISlidePopupPosition } from '../commands/operations/doc.operation'; +import type { ISlidePopupPosition } from '../commands/operations/operation'; const PSEUDO_SUBUNIT = 'PSEUDO_SUBUNIT'; diff --git a/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts b/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts index f919a12678d..882fbc2a66e 100644 --- a/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts +++ b/packages-experimental/uni-formula-ui/src/uni-formula-ui.plugin.ts @@ -24,6 +24,7 @@ import { DocUniFormulaInputController } from './controllers/doc-formula-input.co import { UniFormulaService } from './services/uni-formula.service'; import { UniFormulaUniController } from './controllers/uni-formula-ui.controller'; import { SlideUniFormulaInputController } from './controllers/slide-formula-input.controller'; +import { SlideUIFormulaCacheService } from './services/slide-ui-formula-cache.service'; @DependentOn(UniverDocUniFormulaPlugin) export class UniverDocUniFormulaUIPlugin extends Plugin { @@ -42,6 +43,7 @@ export class UniverDocUniFormulaUIPlugin extends Plugin { [UniFormulaUniController], [DocUniFormulaInputController], [SlideUniFormulaInputController], + [SlideUIFormulaCacheService], [UniFormulaPopupService], [IUniFormulaService, { useClass: UniFormulaService }], ] as Dependency[]).forEach((d) => injector.add(d)); diff --git a/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx b/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx index b42f0c3b9ec..b8047f0c1fa 100644 --- a/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx +++ b/packages-experimental/uni-formula-ui/src/views/components/DocFormulaPopup.tsx @@ -23,7 +23,7 @@ import { CheckMarkSingle, CloseSingle } from '@univerjs/icons'; import type { IUniFormulaPopupInfo } from '../../services/formula-popup.service'; import { DOC_FORMULA_POPUP_KEY, UniFormulaPopupService } from '../../services/formula-popup.service'; -import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand } from '../../commands/operations/doc.operation'; +import { CloseFormulaPopupOperation, ConfirmFormulaPopupCommand } from '../../commands/operations/operation'; import styles from './index.module.less'; export const UNI_FORMULA_EDITOR_ID = createInternalEditorID('UNI_FORMULA'); diff --git a/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts b/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts index f3a3f10f4e1..e0db2b998f1 100644 --- a/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts +++ b/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts @@ -55,7 +55,7 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I @IContextService private readonly _contextService: IContextService, @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, @ICommandService private readonly _commandService: ICommandService, - @Inject(ISlideEditorBridgeService) private readonly _editorBridgeService: ISlideEditorBridgeService, + @ISlideEditorBridgeService private readonly _editorBridgeService: ISlideEditorBridgeService, @Inject(TextSelectionManagerService) private readonly _textSelectionManagerService: TextSelectionManagerService, @ITextSelectionRenderManager private readonly _textSelectionRenderManager: ITextSelectionRenderManager, @Inject(CanvasView) private readonly _canvasView: CanvasView @@ -161,6 +161,9 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I if (!slideData) return false; curRichText.refreshDocumentByDocData(); curRichText.resizeToContentSize(); + + this._editorBridgeService.endEditing$.next(curRichText); + this._curRichText = null; } diff --git a/packages/slides-ui/src/index.ts b/packages/slides-ui/src/index.ts index 46e2b3a7ed3..154980ad128 100644 --- a/packages/slides-ui/src/index.ts +++ b/packages/slides-ui/src/index.ts @@ -18,6 +18,7 @@ export { UniverSlidesUIPlugin } from './slides-ui-plugin'; export { SlidesUIController } from './controllers/slide-ui.controller'; export { SlideSideBar } from './components/slide-bar/SlideBar'; +export { ISlideEditorBridgeService } from './services/slide-editor-bridge.service'; export { SlideCanvasPopMangerService } from './services/slide-popup-manager.service'; export type { IUniverSlidesDrawingConfig } from './controllers/slide-ui.controller'; diff --git a/packages/slides-ui/src/services/slide-editor-bridge.service.ts b/packages/slides-ui/src/services/slide-editor-bridge.service.ts index aadfe657d3e..66e96c1ec2d 100644 --- a/packages/slides-ui/src/services/slide-editor-bridge.service.ts +++ b/packages/slides-ui/src/services/slide-editor-bridge.service.ts @@ -32,7 +32,7 @@ import { SLIDE_KEY } from '@univerjs/slides'; import type { KeyCode } from '@univerjs/ui'; import { IEditorService } from '@univerjs/ui'; import type { Observable } from 'rxjs'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, Subject } from 'rxjs'; import { SLIDE_EDITOR_ID } from '../const'; // TODO same as @univerjs/slides/views/render/adaptors/index.js @@ -77,6 +77,13 @@ export interface ISetEditorInfo { export interface ISlideEditorBridgeService { currentEditRectState$: Observable>; visible$: Observable; + + /** + * @deprecated This is a temp solution only for demo purposes. We should have mutations to directly write + * content to slides. + */ + endEditing$: Subject; + // interceptor: InterceptorManager<{ // BEFORE_CELL_EDIT: typeof BEFORE_CELL_EDIT; // AFTER_CELL_EDIT: typeof AFTER_CELL_EDIT; @@ -119,8 +126,12 @@ export class SlideEditorBridgeService extends Disposable implements ISlideEditor private readonly _visible$ = new BehaviorSubject(this._visibleParam); readonly visible$ = this._visible$.asObservable(); + private readonly _afterVisible$ = new BehaviorSubject(this._visibleParam); readonly afterVisible$ = this._afterVisible$.asObservable(); + + readonly endEditing$ = new Subject(); + private _currentEditRectInfo: ISetEditorInfo; constructor( diff --git a/packages/slides-ui/src/services/slide-editor-manager.service.ts b/packages/slides-ui/src/services/slide-editor-manager.service.ts index 23709327e32..c804dbbae3d 100644 --- a/packages/slides-ui/src/services/slide-editor-manager.service.ts +++ b/packages/slides-ui/src/services/slide-editor-manager.service.ts @@ -48,11 +48,9 @@ export class SlideEditorManagerService implements ISlideEditorManagerService, ID private _rect: Nullable = null; private readonly _state$ = new BehaviorSubject>(null); - readonly state$ = this._state$.asObservable(); private readonly _rect$ = new BehaviorSubject>(null); - readonly rect$ = this._rect$.asObservable(); private _focus: boolean = false; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe5024a657d..3fca1a9d8f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -499,6 +499,9 @@ importers: '@univerjs/docs-ui': specifier: workspace:* version: link:../../packages/docs-ui + '@univerjs/engine-render': + specifier: workspace:* + version: link:../../packages/engine-render '@univerjs/icons': specifier: ^0.1.72 version: 0.1.72(react-dom@18.3.1(react@18.3.1))(react@18.3.1) From 674e3b4e26c4eb475cd0ae7c5e2143ca50104ce0 Mon Sep 17 00:00:00 2001 From: Wenzhao Hu <12122021+wzhudev@users.noreply.github.com> Date: Sun, 11 Aug 2024 15:58:47 +0800 Subject: [PATCH 3/5] feat: write back calc value --- examples/src/main.tsx | 2 +- .../uni-formula-ui/package.json | 2 + .../doc-formula-input.controller.ts | 3 +- .../slide-formula-input.controller.ts | 4 +- .../src/services/uni-formula.service.ts | 108 ++++++++++++++---- .../src/services/uni-formula.service.ts | 64 ++++++++--- packages/docs/src/basics/replace.ts | 21 +++- packages/engine-render/src/shape/rich-text.ts | 6 +- .../slide-editor-bridge.render-controller.ts | 10 +- pnpm-lock.yaml | 23 ++-- 10 files changed, 176 insertions(+), 67 deletions(-) diff --git a/examples/src/main.tsx b/examples/src/main.tsx index 198bf5d14a4..04cbe1c8b7d 100644 --- a/examples/src/main.tsx +++ b/examples/src/main.tsx @@ -53,7 +53,7 @@ function Examples() { title: '📚 Docs Uniscript', href: './docs-uniscript/', }, { - title: '🌌 Universe', + title: '🌌 Uni Mode', href: './uni/', }, { title: '📱 Mobile', diff --git a/packages-experimental/uni-formula-ui/package.json b/packages-experimental/uni-formula-ui/package.json index 613c8942b97..57bd3c9d642 100644 --- a/packages-experimental/uni-formula-ui/package.json +++ b/packages-experimental/uni-formula-ui/package.json @@ -65,6 +65,7 @@ "@univerjs/engine-render": "workspace:*", "@univerjs/rpc": "workspace:*", "@univerjs/sheets-formula": "workspace:*", + "@univerjs/slides": "workspace:*", "@univerjs/slides-ui": "workspace:*", "@univerjs/ui": "workspace:*", "@univerjs/uni-formula": "workspace:*", @@ -82,6 +83,7 @@ "@univerjs/rpc": "workspace:*", "@univerjs/shared": "workspace:*", "@univerjs/sheets-formula": "workspace:*", + "@univerjs/slides": "workspace:*", "@univerjs/slides-ui": "workspace:*", "@univerjs/ui": "workspace:*", "@univerjs/uni-formula": "workspace:*", 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 4b5ea18f001..f7872b182b4 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 @@ -77,6 +77,7 @@ export class DocUniFormulaInputController extends Disposable { this._showPopup({ startIndex: activeRange.startOffset! - 1, unitId: focusedUnit.getUnitId(), + position: {}, }); } else if (this._formulaPopupSrv.popupInfo) { this._closePopup(); @@ -108,7 +109,7 @@ export class DocUniFormulaInputController extends Disposable { this._showPopup({ startIndex, unitId: focusedUnit.getUnitId(), - rangeId, + position: { rangeId }, type: 'existing', }); } else { 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 64d9df28d7f..53c98560791 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 @@ -70,8 +70,8 @@ export class SlideUniFormulaInputController extends Disposable { // NOTE: we can avoid manually get the SlideEditorBridgeService when we split // slide formula editor plugin into a separate package. const editorBridgeService = this._injector.get(ISlideEditorBridgeService); - const editorReact = editorBridgeService.getEditorRect(); - const { pageId, richTextObj } = editorReact; + const editorRect = editorBridgeService.getEditorRect(); + const { pageId, richTextObj } = editorRect; const { oKey } = richTextObj; this._showPopup({ startIndex: activeRange.startOffset! - 1, 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 83db6034428..5df42c451db 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 @@ -21,7 +21,6 @@ import type { IDisposable, IDocumentBody, Nullable, - SlideDataModel } from '@univerjs/core'; import { CommandType, @@ -40,10 +39,12 @@ import { import { makeSelection, replaceSelectionFactory } from '@univerjs/docs'; import { DataSyncPrimaryController } from '@univerjs/rpc'; import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; +import { CanvasView } from '@univerjs/slides'; import type { IDocFormulaCache, ISlideFormulaCache } from '@univerjs/uni-formula'; import { DumbUniFormulaService, IUniFormulaService } from '@univerjs/uni-formula'; import { take } from 'rxjs'; -import type { ISlidePopupPosition } from '../commands/operations/operation'; +import { RichText } from '@univerjs/engine-render'; +import { type IDocPopupPosition, type ISlidePopupPosition, isSlidePosition } from '../commands/operations/operation'; const PSEUDO_SUBUNIT = 'PSEUDO_SUBUNIT'; @@ -56,8 +57,7 @@ export interface IUpdateSlideUniFormulaCacheCommandParams { export interface IUpdateDocUniFormulaCacheCommandParams { /** The doc in which formula results changed. */ unitId: string; - /** Range ids. */ - ids: string[]; + positions: ISlidePopupPosition[] | IDocPopupPosition[]; /** Calculation results. */ cache: IDocFormulaCache[]; } @@ -70,13 +70,53 @@ export const UpdateSlideUniFormulaCacheCommand: ICommand(unitId, UniverInstanceType.UNIVER_SLIDE); if (!slide) return true; return positions.every((position, index) => { - // TODO@wzhudev: how to directly change the content of a slide element? + // TODO@wzhudev: we should get the slide's rendering modules to update the formula results. + // Note that this is very hacky because Univer Slide hasn't provide any mutations to + // modify its content. This is just for POC of uni formula. + const scene = slideCanvasView.getRenderUnitByPageId(position.pageId).scene; + if (!scene) return false; + + const element = scene.getObject(position.elementId); + if (!element || !(element instanceof RichText)) return false; + + const documentModel = element.documentModel; + const originBody = documentModel.getBody()!; + const range = originBody.customRanges?.find((r) => r.rangeId === position.rangeId); + if (!range) return false; + + const dataStream = makeCustomRangeStream(`${cache[index].v ?? ''}`); + const body: IDocumentBody = { + dataStream, + customRanges: [{ + startIndex: 0, + endIndex: dataStream.length - 1, + rangeId: position.rangeId!, + rangeType: CustomRangeType.UNI_FORMULA, + wholeEntity: true, + }], + }; + + const redoMutation = replaceSelectionFactory(accessor, { + unitId, + originBody, + body, + selection: makeSelection(range.startIndex, range.endIndex), + }); + + if (!redoMutation) return false; + + // This is pretty annoying... + element.documentModel.apply(redoMutation.params.actions); + element.refreshDocumentByDocData(); // trigger re-render + + uniFormulaService.updateSlideFormulaResults(unitId, position.pageId, position.elementId, position.rangeId!, cache[index]); + return true; }); }, @@ -91,7 +131,7 @@ export const UpdateDocUniFormulaCacheCommand: ICommand r.rangeId === rangeId); } - const saveCacheResult = uniFormulaService.updateFormulaResults(unitId, ids, cache); + const ids = positions.map((position) => position.rangeId!); + const saveCacheResult = uniFormulaService.updateDocFormulaResults(unitId, ids, cache); if (!saveCacheResult) return false; return ids.every((id, index) => { @@ -162,7 +203,10 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm ) { super(resourceManagerService, commandSrv, instanceSrv); - commandSrv.registerCommand(UpdateDocUniFormulaCacheCommand); + [ + UpdateSlideUniFormulaCacheCommand, + UpdateDocUniFormulaCacheCommand, + ].forEach((command) => commandSrv.registerCommand(command)); // Only able to perform formula calculation after a sheet is loaded. // FIXME: the formula engine is not unit-agnostic. @@ -307,32 +351,52 @@ export class UniFormulaService extends DumbUniFormulaService implements IUniForm const key = this._formulaIdToKey.get(formulaId); if (!key) return null; - const item = this._docFormulas.get(key); - if (!item) return null; - - const r = result.result?.[0][0]; - if (item.v === r?.v && item.t === r?.t) return null; - - return { id: item.rangeId, unitId: item.unitId, cache: r }; + const docItem = this._docFormulas.get(key); + if (docItem) { + const r = result.result?.[0][0]; + if (docItem.v === r?.v && docItem.t === r?.t) return null; + + return { position: { rangeId: docItem.rangeId }, unitId: docItem.unitId, cache: r }; + }; + + const slideItem = this._slideFormulas.get(key); + if (slideItem) { + const r = result.result?.[0][0]; + if (slideItem.v === r?.v && slideItem.t === r?.t) return null; + + return { + unitId: slideItem.unitId, + position: { + elementId: slideItem.elementId, + rangeId: slideItem.rangeId, + pageId: slideItem.pageId, + }, + cache: r, + }; + } + + return null; }).reduce((previous, curr) => { if (!curr || !curr.cache) return previous; if (!previous.unitId) previous.unitId = curr.unitId; - previous.ids.push(curr.id); + previous.positions.push(curr.position); previous.cache.push(curr.cache); return previous; }, { unitId: '', - ids: [] as string[], + positions: [] as (ISlidePopupPosition | IDocPopupPosition)[], cache: [] as Pick[], }); - if (mutationParam.ids.length === 0) return; - - this._commandSrv.executeCommand(UpdateDocUniFormulaCacheCommand.id, mutationParam as IUpdateDocUniFormulaCacheCommandParams); + if (mutationParam.positions.length === 0) return; - // TODO@wzhudev: handle slide formula cache updating. + if (isSlidePosition(mutationParam.positions[0])) { + this._commandSrv.executeCommand(UpdateSlideUniFormulaCacheCommand.id, mutationParam as IUpdateSlideUniFormulaCacheCommandParams); + } else { + this._commandSrv.executeCommand(UpdateDocUniFormulaCacheCommand.id, mutationParam as IUpdateDocUniFormulaCacheCommandParams); + } } } })); diff --git a/packages-experimental/uni-formula/src/services/uni-formula.service.ts b/packages-experimental/uni-formula/src/services/uni-formula.service.ts index 25fc0762aec..c07183a352e 100644 --- a/packages-experimental/uni-formula/src/services/uni-formula.service.ts +++ b/packages-experimental/uni-formula/src/services/uni-formula.service.ts @@ -30,7 +30,8 @@ import { DOC_UNI_FORMULA_RESOURCE_NAME } from '../const'; import type { ISlideFormulaReference } from '../models/slide-formula'; export interface IUniFormulaService { - updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean; + updateDocFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean; + updateSlideFormulaResults(unitId: string, pageId: string, elementId: string, formulaId: string, v: IDocFormulaCache): boolean; // #region doc @@ -83,6 +84,19 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ return this._docFormulas.get(getDocFormulaKey(unitId, rangeId)) ?? null; } + updateDocFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean { + formulaIds.forEach((id, index) => { + const formulaData = this._docFormulas.get(getDocFormulaKey(unitId, id)); + if (!formulaData) return true; + + formulaData.v = v[index].v; + formulaData.t = v[index].t; + return true; + }); + + return true; + } + /** * Register a doc formula into the formula system. */ @@ -105,6 +119,15 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ } } + updateSlideFormulaResults(unitId: string, pageId: string, elementId: string, formulaId: string, v: IDocFormulaCache): boolean { + const formulaData = this._slideFormulas.get(getSlideFormulaKey(unitId, pageId, elementId, formulaId)); + if (!formulaData) return true; + + formulaData.v = v.v; + formulaData.t = v.t; + return true; + } + private _initDocFormulaResources(resourceManagerService: IResourceManagerService): void { resourceManagerService.registerPluginResource({ pluginName: DOC_UNI_FORMULA_RESOURCE_NAME, @@ -138,41 +161,41 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ // #endregion - updateFormulaResults(unitId: string, formulaIds: string[], v: IDocFormulaCache[]): boolean { - formulaIds.forEach((id, index) => { - const formulaData = this._docFormulas.get(getDocFormulaKey(unitId, id)); - if (!formulaData) return true; - - formulaData.v = v[index].v; - formulaData.t = v[index].t; - return true; - }); - - return true; - } - // #region slides registerSlideFormula( unitId: string, pageId: string, elementId: string, + rangeId: string, f: string, - v: ICellData['v'], t: ICellData['t'] + v: ICellData['v'], + t: ICellData['t'] ): IDisposable { + const key = getSlideFormulaKey(unitId, pageId, elementId, f); + if (this._slideFormulas.has(key)) { + throw new Error(`[UniFormulaService]: cannot register formula ${key} when it is already registered!`); + } + + this._slideFormulas.set(key, { unitId, pageId, elementId, rangeId, formulaId: '', f, v, t }); + return toDisposable(() => this.unregisterDocFormula(unitId, rangeId)); } hasSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): boolean { - throw new Error('Method not implemented.'); + return this._slideFormulas.has(getSlideFormulaKey(unitId, pageId, elementId, formulaId)); } getSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): Nullable { - throw new Error('Method not implemented.'); + return this._slideFormulas.get(getSlideFormulaKey(unitId, pageId, elementId, formulaId)) ?? null; } unregisterSlideFormula(unitId: string, pageId: string, elementId: string, formulaId: string): void { - throw new Error('Method not implemented.'); + const key = getSlideFormulaKey(unitId, pageId, elementId, formulaId); + const item = this._slideFormulas.get(key); + if (item) { + this._slideFormulas.delete(key); + } } // #endregion @@ -190,3 +213,8 @@ export function getPseudoDocUnitKey(unitId: string): string { export function getDocFormulaKey(unitId: string, formulaId: string): string { return `pseudo-${unitId}-${formulaId}`; } + +function getSlideFormulaKey(unitId: string, pageId: string, elementId: string, formulaId: string): string { + return `pseudo-${unitId}-${pageId}-${elementId}-${formulaId}`; +} + diff --git a/packages/docs/src/basics/replace.ts b/packages/docs/src/basics/replace.ts index 154b67ef431..d7bc2274e71 100644 --- a/packages/docs/src/basics/replace.ts +++ b/packages/docs/src/basics/replace.ts @@ -113,20 +113,29 @@ export function getRetainAndDeleteAndExcludeLineBreak( export interface IReplaceSelectionFactoryParams { unitId: string; selection?: ITextRange; + + originBody?: IDocumentBody; + + /** Body to be inserted at the given position. */ body: IDocumentBody; // Do not contain `\r\n` at the end. + textRanges?: ITextRangeWithStyle[]; } export function replaceSelectionFactory(accessor: IAccessor, params: IReplaceSelectionFactoryParams) { - const { unitId, body: insertBody } = params; + const { unitId, originBody, body: insertBody } = params; const univerInstanceService = accessor.get(IUniverInstanceService); - const docDataModel = univerInstanceService.getUnit(unitId); - const textSelectionManagerService = accessor.get(TextSelectionManagerService); - if (!docDataModel) { - return false; + + let body: IDocumentBody | undefined; + if (!params.originBody) { + const docDataModel = univerInstanceService.getUnit(unitId); + body = docDataModel?.getBody(); + } else { + body = originBody; } + if (!body) return false; - const body = docDataModel.getBody(); + const textSelectionManagerService = accessor.get(TextSelectionManagerService); const selection = params.selection ?? textSelectionManagerService.getActiveTextRangeWithStyle(); if (!selection || !body) { return false; diff --git a/packages/engine-render/src/shape/rich-text.ts b/packages/engine-render/src/shape/rich-text.ts index 0d99bd67e5e..7ae1b6cf743 100644 --- a/packages/engine-render/src/shape/rich-text.ts +++ b/packages/engine-render/src/shape/rich-text.ts @@ -59,6 +59,8 @@ export class RichText extends BaseObject { private _documents!: Documents; + documentModel!: DocumentDataModel; + /** * fontFamily */ @@ -145,7 +147,7 @@ export class RichText extends BaseObject { this._documentData = this._convertToDocumentData(props.text || ''); } - const docModel = new DocumentDataModel(this._documentData); + const docModel = this.documentModel = new DocumentDataModel(this._documentData); const docViewModel = new DocumentViewModel(docModel); this._documentSkeleton = DocumentSkeleton.create(docViewModel, this._localeService); @@ -356,7 +358,7 @@ export class RichText extends BaseObject { * now it is invoked when transformByState(change editor size) & end of editing */ refreshDocumentByDocData() { - const docModel = new DocumentDataModel(this._documentData); + const docModel = this.documentModel = new DocumentDataModel(this._documentData); const docViewModel = new DocumentViewModel(docModel); this._documentSkeleton = DocumentSkeleton.create(docViewModel, this._localeService); diff --git a/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts b/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts index e0db2b998f1..e28f3c69eee 100644 --- a/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts +++ b/packages/slides-ui/src/controllers/slide-editor-bridge.render-controller.ts @@ -78,7 +78,7 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I // })); } - private _setEditorRect(targetObject: RichText) { + private _setEditorRect(pageId: string, targetObject: RichText) { this._curRichText = targetObject as RichText; const { scene, engine } = this._renderContext; const unitId = this._renderContext.unitId; @@ -87,7 +87,7 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I scene, engine, unitId, - pageId: '', + pageId, // FIXME: wtf this is an empty string? richTextObj: targetObject, }; @@ -133,7 +133,7 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I if (object.objectType !== ObjectType.RICH_TEXT) { this.pickOtherObjects(); } else { - this.startEditing(object as RichText); + this.startEditing(page.id, object as RichText); } })); @@ -174,10 +174,10 @@ export class SlideEditorBridgeRenderController extends RxDisposable implements I * TODO @lumixraku need scale param * @param target */ - startEditing(target: RichText) { + startEditing(pageId: string, target: RichText) { // this.setSlideTextEditor$.next({ content, rect }); - this._setEditorRect(target); + this._setEditorRect(pageId, target); this.setEditorVisible(true); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fca1a9d8f6..f8ac8578eac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: 2.24.1 - version: 2.24.1(@eslint-react/eslint-plugin@1.9.0(eslint@9.8.0)(typescript@5.5.4))(@vue/compiler-sfc@3.4.35)(eslint-plugin-format@0.1.2(eslint@9.8.0))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.8.0))(eslint-plugin-react-refresh@0.4.9(eslint@9.8.0))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) + version: 2.24.1(@eslint-react/eslint-plugin@1.9.0(eslint@9.8.0)(typescript@5.5.4))(@vue/compiler-sfc@3.4.35)(eslint-plugin-format@0.1.2(eslint@9.8.0))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.8.0))(eslint-plugin-react-refresh@0.4.9(eslint@9.8.0))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) '@commitlint/cli': specifier: ^19.3.0 version: 19.3.0(@types/node@22.1.0)(typescript@5.5.4) @@ -133,7 +133,7 @@ importers: version: 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7))) '@storybook/addon-interactions': specifier: 8.2.7 - version: 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) + version: 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) '@storybook/addon-links': specifier: 8.2.7 version: 8.2.7(react@18.3.1)(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7))) @@ -514,6 +514,9 @@ importers: '@univerjs/sheets-formula': specifier: workspace:* version: link:../../packages/sheets-formula + '@univerjs/slides': + specifier: workspace:* + version: link:../../packages/slides '@univerjs/slides-ui': specifier: workspace:* version: link:../../packages/slides-ui @@ -10915,7 +10918,7 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 - '@antfu/eslint-config@2.24.1(@eslint-react/eslint-plugin@1.9.0(eslint@9.8.0)(typescript@5.5.4))(@vue/compiler-sfc@3.4.35)(eslint-plugin-format@0.1.2(eslint@9.8.0))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.8.0))(eslint-plugin-react-refresh@0.4.9(eslint@9.8.0))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': + '@antfu/eslint-config@2.24.1(@eslint-react/eslint-plugin@1.9.0(eslint@9.8.0)(typescript@5.5.4))(@vue/compiler-sfc@3.4.35)(eslint-plugin-format@0.1.2(eslint@9.8.0))(eslint-plugin-react-hooks@5.1.0-rc-107a2f8c3e-20240617(eslint@9.8.0))(eslint-plugin-react-refresh@0.4.9(eslint@9.8.0))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': dependencies: '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 @@ -10940,7 +10943,7 @@ snapshots: eslint-plugin-toml: 0.11.1(eslint@9.8.0) eslint-plugin-unicorn: 55.0.0(eslint@9.8.0) eslint-plugin-unused-imports: 4.0.1(@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0) - eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) + eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) eslint-plugin-vue: 9.27.0(eslint@9.8.0) eslint-plugin-yml: 1.14.0(eslint@9.8.0) eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.4.35)(eslint@9.8.0) @@ -12808,11 +12811,11 @@ snapshots: '@storybook/global': 5.0.0 storybook: 8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)) - '@storybook/addon-interactions@8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': + '@storybook/addon-interactions@8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': dependencies: '@storybook/global': 5.0.0 '@storybook/instrumenter': 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7))) - '@storybook/test': 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) + '@storybook/test': 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) polished: 4.3.1 storybook: 8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)) ts-dedent: 2.2.0 @@ -13103,12 +13106,12 @@ snapshots: optionalDependencies: typescript: 5.5.4 - '@storybook/test@8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': + '@storybook/test@8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7)))(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': dependencies: '@storybook/csf': 0.1.11 '@storybook/instrumenter': 8.2.7(storybook@8.2.7(@babel/preset-env@7.24.7(@babel/core@7.24.7))) '@testing-library/dom': 10.1.0 - '@testing-library/jest-dom': 6.4.5(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) + '@testing-library/jest-dom': 6.4.5(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)) '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 @@ -13243,7 +13246,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.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': + '@testing-library/jest-dom@6.4.5(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.7 @@ -15698,7 +15701,7 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4) - eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)): + eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)(vitest@2.0.5(@types/node@22.1.0)(happy-dom@14.12.3)(jsdom@24.1.0)(less@4.2.0)(sass@1.77.5)(terser@5.31.1)): dependencies: '@typescript-eslint/utils': 7.18.0(eslint@9.8.0)(typescript@5.5.4) eslint: 9.8.0 From 4fb992fdcf8e38190fb8176b6b487d3bcd2a5b5e Mon Sep 17 00:00:00 2001 From: Wenzhao Hu <12122021+wzhudev@users.noreply.github.com> Date: Sun, 11 Aug 2024 16:04:56 +0800 Subject: [PATCH 4/5] fix: fix lint --- .../uni-formula/src/services/uni-formula.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages-experimental/uni-formula/src/services/uni-formula.service.ts b/packages-experimental/uni-formula/src/services/uni-formula.service.ts index c07183a352e..71b5fcb3e79 100644 --- a/packages-experimental/uni-formula/src/services/uni-formula.service.ts +++ b/packages-experimental/uni-formula/src/services/uni-formula.service.ts @@ -61,7 +61,7 @@ export class DumbUniFormulaService extends Disposable implements IUniFormulaServ protected readonly _slideFormulas = new Map(); constructor( - @IResourceManagerService resourceManagerSrv: IResourceManagerService, + @IResourceManagerService resourceManagerSrv: IResourceManagerService, @ICommandService protected readonly _commandSrv: ICommandService, @IUniverInstanceService protected readonly _instanceSrv: IUniverInstanceService ) { From f5d902c389efc994f9e6768ba5cf90aa530eb63d Mon Sep 17 00:00:00 2001 From: Wenzhao Hu <12122021+wzhudev@users.noreply.github.com> Date: Sun, 11 Aug 2024 16:07:06 +0800 Subject: [PATCH 5/5] feat: change i18n --- packages-experimental/uni-formula-ui/src/locale/en-US.ts | 2 +- packages-experimental/uni-formula-ui/src/locale/ru-RU.ts | 2 +- packages-experimental/uni-formula-ui/src/locale/vi-VN.ts | 2 +- packages-experimental/uni-formula-ui/src/locale/zh-CN.ts | 2 +- packages-experimental/uni-formula-ui/src/locale/zh-TW.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages-experimental/uni-formula-ui/src/locale/en-US.ts b/packages-experimental/uni-formula-ui/src/locale/en-US.ts index 3f0e266a592..ef449432bec 100644 --- a/packages-experimental/uni-formula-ui/src/locale/en-US.ts +++ b/packages-experimental/uni-formula-ui/src/locale/en-US.ts @@ -30,7 +30,7 @@ const locale: typeof zhCN = { }, }, command: { - 'stream-placeholder': 'Doc Formula', + 'stream-placeholder': 'Uni Formula', }, }, }; diff --git a/packages-experimental/uni-formula-ui/src/locale/ru-RU.ts b/packages-experimental/uni-formula-ui/src/locale/ru-RU.ts index 6856c0ffe1b..aa610228dda 100644 --- a/packages-experimental/uni-formula-ui/src/locale/ru-RU.ts +++ b/packages-experimental/uni-formula-ui/src/locale/ru-RU.ts @@ -30,7 +30,7 @@ const locale: typeof zhCN = { }, }, command: { - 'stream-placeholder': 'Doc Formula', + 'stream-placeholder': 'Uni Formula', }, }, }; diff --git a/packages-experimental/uni-formula-ui/src/locale/vi-VN.ts b/packages-experimental/uni-formula-ui/src/locale/vi-VN.ts index 6856c0ffe1b..aa610228dda 100644 --- a/packages-experimental/uni-formula-ui/src/locale/vi-VN.ts +++ b/packages-experimental/uni-formula-ui/src/locale/vi-VN.ts @@ -30,7 +30,7 @@ const locale: typeof zhCN = { }, }, command: { - 'stream-placeholder': 'Doc Formula', + 'stream-placeholder': 'Uni Formula', }, }, }; diff --git a/packages-experimental/uni-formula-ui/src/locale/zh-CN.ts b/packages-experimental/uni-formula-ui/src/locale/zh-CN.ts index 20e223fab76..994267d8190 100644 --- a/packages-experimental/uni-formula-ui/src/locale/zh-CN.ts +++ b/packages-experimental/uni-formula-ui/src/locale/zh-CN.ts @@ -28,7 +28,7 @@ const locale = { }, }, command: { - 'stream-placeholder': '文档公式', + 'stream-placeholder': '无界公式', }, }, }; diff --git a/packages-experimental/uni-formula-ui/src/locale/zh-TW.ts b/packages-experimental/uni-formula-ui/src/locale/zh-TW.ts index 6856c0ffe1b..aa610228dda 100644 --- a/packages-experimental/uni-formula-ui/src/locale/zh-TW.ts +++ b/packages-experimental/uni-formula-ui/src/locale/zh-TW.ts @@ -30,7 +30,7 @@ const locale: typeof zhCN = { }, }, command: { - 'stream-placeholder': 'Doc Formula', + 'stream-placeholder': 'Uni Formula', }, }, };