diff --git a/packages/core/src/services/command/command.service.ts b/packages/core/src/services/command/command.service.ts index 787314a9ce..022ef9d0fc 100644 --- a/packages/core/src/services/command/command.service.ts +++ b/packages/core/src/services/command/command.service.ts @@ -276,27 +276,31 @@ export class CommandService implements ICommandService { params?: P, options?: IExecutionOptions ): Promise { - const item = this._commandRegistry.getCommand(id); - if (item) { - const [command] = item; - const commandInfo: ICommandInfo = { - id: command.id, - type: command.type, - params, - }; + try { + const item = this._commandRegistry.getCommand(id); + if (item) { + const [command] = item; + const commandInfo: ICommandInfo = { + id: command.id, + type: command.type, + params, + }; - const stackItemDisposable = this._pushCommandExecutionStack(commandInfo); + const stackItemDisposable = this._pushCommandExecutionStack(commandInfo); - this._beforeCommandExecutionListeners.forEach((listener) => listener(commandInfo, options)); - const result = await this._execute(command as ICommand, params, options); - this._commandExecutedListeners.forEach((listener) => listener(commandInfo, options)); + this._beforeCommandExecutionListeners.forEach((listener) => listener(commandInfo, options)); + const result = await this._execute(command as ICommand, params, options); + this._commandExecutedListeners.forEach((listener) => listener(commandInfo, options)); - stackItemDisposable.dispose(); + stackItemDisposable.dispose(); - return result; + return result; + } + throw new Error(`[CommandService]: command "${id}" is not registered.`); + } catch (error) { + this._logService.error(error); + throw error; } - - throw new Error(`[CommandService]: command "${id}" is not registered.`); } syncExecuteCommand

( diff --git a/packages/core/src/shared/object-matrix.ts b/packages/core/src/shared/object-matrix.ts index b42ad0ff74..f509945a8f 100644 --- a/packages/core/src/shared/object-matrix.ts +++ b/packages/core/src/shared/object-matrix.ts @@ -400,7 +400,9 @@ export class ObjectMatrix { insertColumns(start: number, count: number): void { for (let c = start; c < start + count; c++) { this.forEach((row, data) => { - insertMatrixArray(c, undefined, data); + if (data) { + insertMatrixArray(c, undefined, data); + } }); } } @@ -411,7 +413,9 @@ export class ObjectMatrix { removeColumns(start: number, count: number): void { this.forEach((row, value) => { - spliceArray(start, count, value); + if (value) { + spliceArray(start, count, value); + } }); } diff --git a/packages/core/src/types/interfaces/i-cell-custom-render.ts b/packages/core/src/types/interfaces/i-cell-custom-render.ts index 62f0a9830e..7d9c4044fc 100644 --- a/packages/core/src/types/interfaces/i-cell-custom-render.ts +++ b/packages/core/src/types/interfaces/i-cell-custom-render.ts @@ -27,7 +27,7 @@ export interface ICellRenderContext { data: ICellDataForSheetInterceptor; style: Nullable; primaryWithCoord: ISelectionCellWithCoord; - unitId?: string; + unitId: string; subUnitId: string; row: number; col: number; diff --git a/packages/data-validation/src/commands/commands/data-validation.command.ts b/packages/data-validation/src/commands/commands/data-validation.command.ts index b4747d5ac4..ac477593a9 100644 --- a/packages/data-validation/src/commands/commands/data-validation.command.ts +++ b/packages/data-validation/src/commands/commands/data-validation.command.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CommandType, ICommandService, IUndoRedoService } from '@univerjs/core'; +import { CommandType, ICommandService, ILogService, IUndoRedoService } from '@univerjs/core'; import type { ICommand, IDataValidationRule, IDataValidationRuleBase, IDataValidationRuleOptions, IMutationInfo, IRange, ISheetDataValidationRule } from '@univerjs/core'; import type { Injector } from '@wendellhu/redi'; import type { ISheetCommandSharedParams } from '@univerjs/sheets'; @@ -32,10 +32,15 @@ export interface IAddDataValidationCommandParams extends ISheetCommandSharedPara index?: number; } +/** + * @deprecated + */ export const AddDataValidationCommand: ICommand = { type: CommandType.COMMAND, id: 'data-validation.command.addRule', async handler(accessor, params) { + const logService = accessor.get(ILogService); + logService.warn('[Deprecated] AddDataValidationCommand is deprecated, please use AddSheetDataValidationCommand in @univerjs/sheets-data-validation instead!'); if (!params) { return false; } @@ -151,10 +156,15 @@ export interface IUpdateDataValidationOptionsCommandParams extends ISheetCommand options: IDataValidationRuleOptions; } +/** + * @deprecated + */ export const UpdateDataValidationOptionsCommand: ICommand = { type: CommandType.COMMAND, id: 'data-validation.command.updateDataValidationSetting', handler(accessor, params) { + const logService = accessor.get(ILogService); + logService.warn('[Deprecated] UpdateDataValidationOptionsCommand is deprecated, please use UpdateSheetDataValidationOptionsCommand in @univerjs/sheets-data-validation instead!'); if (!params) { return false; } @@ -213,10 +223,15 @@ export interface IUpdateDataValidationSettingCommandParams extends ISheetCommand setting: IDataValidationRuleBase; } +/** + * @deprecated + */ export const UpdateDataValidationSettingCommand: ICommand = { type: CommandType.COMMAND, id: 'data-validation.command.updateDataValidationOptions', handler(accessor, params) { + const logService = accessor.get(ILogService); + logService.warn('[Deprecated] UpdateDataValidationSettingCommand is deprecated, please use UpdateSheetDataValidationSettingCommand in @univerjs/sheets-data-validation instead!'); if (!params) { return false; } diff --git a/packages/data-validation/src/index.ts b/packages/data-validation/src/index.ts index fc7674421d..f754fb88ee 100644 --- a/packages/data-validation/src/index.ts +++ b/packages/data-validation/src/index.ts @@ -21,8 +21,6 @@ export { DataValidationModel } from './models/data-validation-model'; export type { IRemoveDataValidationCommandParams, IAddDataValidationCommandParams, - IUpdateDataValidationOptionsCommandParams, - IUpdateDataValidationSettingCommandParams, IRemoveAllDataValidationCommandParams, } from './commands/commands/data-validation.command'; @@ -30,7 +28,6 @@ export { AddDataValidationMutation, RemoveDataValidationMutation, UpdateDataValidationMutation, - } from './commands/mutations/data-validation.mutation'; export type { diff --git a/packages/engine-render/src/components/sheets/extensions/custom.ts b/packages/engine-render/src/components/sheets/extensions/custom.ts index 5c8a29d6a4..016c30ec1c 100644 --- a/packages/engine-render/src/components/sheets/extensions/custom.ts +++ b/packages/engine-render/src/components/sheets/extensions/custom.ts @@ -86,6 +86,7 @@ export class Custom extends SheetExtension { row, col, worksheet, + unitId: worksheet.unitId, }; // current cell is hidden diff --git a/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts b/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts index a6fb377a45..1769ed7edf 100644 --- a/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts +++ b/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts @@ -14,14 +14,18 @@ * limitations under the License. */ -import { CommandType, ICommandService, IUndoRedoService, IUniverInstanceService, sequenceExecuteAsync } from '@univerjs/core'; -import type { ICommand, IMutationInfo, IRange, ISheetDataValidationRule } from '@univerjs/core'; +import { CommandType, DataValidationType, ICommandService, IUndoRedoService, IUniverInstanceService, ObjectMatrix, Range, sequenceExecute, sequenceExecuteAsync, Tools } from '@univerjs/core'; +import type { CellValue, ICellData, ICommand, IDataValidationRuleBase, IDataValidationRuleOptions, IMutationInfo, IRange, ISheetDataValidationRule, Nullable } from '@univerjs/core'; import type { IAddDataValidationMutationParams, IUpdateDataValidationMutationParams } from '@univerjs/data-validation'; -import { AddDataValidationMutation, createDefaultNewRule, DataValidationModel, RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; -import { getSheetCommandTarget } from '@univerjs/sheets'; +import { AddDataValidationMutation, createDefaultNewRule, DataValidationModel, DataValidatorRegistryService, getRuleOptions, getRuleSetting, RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; +import type { ISetRangeValuesMutationParams, ISheetCommandSharedParams } from '@univerjs/sheets'; +import { getSheetCommandTarget, SetRangeValuesMutation, SetRangeValuesUndoMutationFactory } from '@univerjs/sheets'; +import type { IAccessor } from '@wendellhu/redi'; import type { SheetDataValidationManager } from '../../models/sheet-data-validation-manager'; import { OpenValidationPanelOperation } from '../operations/data-validation.operation'; import type { RangeMutation } from '../../models/rule-matrix'; +import { CHECKBOX_FORMULA_1, CHECKBOX_FORMULA_2, type CheckboxValidator } from '../../validators'; +import { getStringCellValue } from '../../utils/get-cell-data-origin'; export interface IUpdateSheetDataValidationRangeCommandParams { unitId: string; @@ -30,12 +34,57 @@ export interface IUpdateSheetDataValidationRangeCommandParams { ranges: IRange[]; } +function isBlankCell(cellData: Nullable) { + if (!cellData) { + return true; + } + + if (!cellData.p) { + return Tools.isBlank(cellData.v); + } + + const dataStream = (cellData.p.body?.dataStream ?? '').slice(0, -2).trim(); + return !dataStream; +} + // eslint-disable-next-line max-lines-per-function -export function getDataValidationDiffMutations(unitId: string, subUnitId: string, diffs: RangeMutation[]) { +export function getDataValidationDiffMutations( + unitId: string, + subUnitId: string, + diffs: RangeMutation[], + accessor: IAccessor +) { const redoMutations: IMutationInfo[] = []; - const undoMutations: IMutationInfo[] = []; + const model = accessor.get(DataValidationModel); + const manager = model.ensureManager(unitId, subUnitId) as SheetDataValidationManager; + const univerInstanceService = accessor.get(IUniverInstanceService); + const target = getSheetCommandTarget(univerInstanceService, { unitId, subUnitId }); + if (!target) { + return { + redoMutations, + undoMutations, + }; + } + const { worksheet } = target; + const redoMatrix = new ObjectMatrix(); + function setRangesDefaultValue(ranges: IRange[], defaultValue: CellValue) { + ranges.forEach((range) => { + Range.foreach(range, (row, column) => { + const cellData = worksheet.getCellRaw(row, column); + const value = getStringCellValue(cellData); + if (isBlankCell(cellData) || value === defaultValue) { + redoMatrix.setValue(row, column, { + v: defaultValue, + p: null, + }); + } + }); + }); + } + + // eslint-disable-next-line max-lines-per-function diffs.forEach((diff) => { switch (diff.type) { case 'delete': @@ -82,6 +131,12 @@ export function getDataValidationDiffMutations(unitId: string, subUnitId: string }, } as IUpdateDataValidationMutationParams, }); + const rule = manager.getRuleById(diff.ruleId); + if (rule && rule.type === DataValidationType.CHECKBOX) { + const validator = manager.getValidator(DataValidationType.CHECKBOX) as CheckboxValidator; + const formula = validator.parseFormulaSync(rule, unitId, subUnitId); + setRangesDefaultValue(diff.newRanges, formula.formula2!); + } break; } case 'add': { @@ -101,6 +156,11 @@ export function getDataValidationDiffMutations(unitId: string, subUnitId: string ruleId: diff.rule.uid, }, }); + if (diff.rule.type === DataValidationType.CHECKBOX) { + const validator = manager.getValidator(DataValidationType.CHECKBOX) as CheckboxValidator; + const formula = validator.parseFormulaSync(diff.rule, unitId, subUnitId); + setRangesDefaultValue(diff.rule.ranges, formula.formula2!); + } break; } default: @@ -108,6 +168,23 @@ export function getDataValidationDiffMutations(unitId: string, subUnitId: string } }); + const redoSetRangeValues = { + id: SetRangeValuesMutation.id, + params: { + unitId, + subUnitId, + cellValue: redoMatrix.getData(), + } as ISetRangeValuesMutationParams, + }; + + const undoSetRangeValues = { + id: SetRangeValuesMutation.id, + params: SetRangeValuesUndoMutationFactory(accessor, redoSetRangeValues.params), + }; + + redoMutations.push(redoSetRangeValues); + undoMutations.push(undoSetRangeValues); + return { redoMutations, undoMutations, @@ -117,7 +194,7 @@ export function getDataValidationDiffMutations(unitId: string, subUnitId: string export const UpdateSheetDataValidationRangeCommand: ICommand = { type: CommandType.COMMAND, id: 'sheet.command.updateDataValidationRuleRange', - async handler(accessor, params) { + async handler(accessor, params) { if (!params) { return false; } @@ -135,7 +212,7 @@ export const UpdateSheetDataValidationRangeCommand: ICommand = { + type: CommandType.COMMAND, + id: 'sheets.command.update-data-validation-setting', + // eslint-disable-next-line max-lines-per-function + handler(accessor, params) { + if (!params) { + return false; + } + const commandService = accessor.get(ICommandService); + const redoUndoService = accessor.get(IUndoRedoService); + const dataValidationModel = accessor.get(DataValidationModel); + const dataValidatorRegistryService = accessor.get(DataValidatorRegistryService); + + const { unitId, subUnitId, ruleId, setting } = params; + const validator = dataValidatorRegistryService.getValidatorItem(setting.type); + + if (!validator) { + return false; + } + const rule = dataValidationModel.getRuleById(unitId, subUnitId, ruleId); + if (!rule) { + return false; + } + + if (!validator.validatorFormula({ ...rule, ...setting }, unitId, subUnitId).success) { + return false; + } + + const mutationParams: IUpdateDataValidationMutationParams = { + unitId, + subUnitId, + ruleId, + payload: { + type: UpdateRuleType.SETTING, + payload: setting, + }, + }; + + const redoMutations: IMutationInfo[] = [{ + id: UpdateDataValidationMutation.id, + params: mutationParams, + }]; + const undoMutationParams: IUpdateDataValidationMutationParams = { + unitId, + subUnitId, + ruleId, + payload: { + type: UpdateRuleType.SETTING, + payload: getRuleSetting(rule), + }, + }; + const undoMutations: IMutationInfo[] = [{ + id: UpdateDataValidationMutation.id, + params: undoMutationParams, + }]; + + if (setting.type === DataValidationType.CHECKBOX) { + const ranges = rule.ranges as IRange[]; + const univerInstanceService = accessor.get(IUniverInstanceService); + const target = getSheetCommandTarget(univerInstanceService, { unitId, subUnitId }); + if (target) { + const redoMatrix = new ObjectMatrix(); + const { worksheet } = target; + const { formula2: oldFormula2 = CHECKBOX_FORMULA_2, formula1: oldFormula1 = CHECKBOX_FORMULA_1 } = rule; + const { formula2 = CHECKBOX_FORMULA_2, formula1 = CHECKBOX_FORMULA_1 } = setting; + ranges.forEach((range) => { + Range.foreach(range, (row, column) => { + const cellData = worksheet.getCellRaw(row, column); + const value = getStringCellValue(cellData); + if (isBlankCell(cellData) || value === String(oldFormula2)) { + redoMatrix.setValue(row, column, { + v: formula2, + p: null, + }); + } else if (value === String(oldFormula1)) { + redoMatrix.setValue(row, column, { + v: formula1, + p: null, + }); + } + }); + }); + + const redoSetRangeValues = { + id: SetRangeValuesMutation.id, + params: { + unitId, + subUnitId, + cellValue: redoMatrix.getData(), + } as ISetRangeValuesMutationParams, + }; + + const undoSetRangeValues = { + id: SetRangeValuesMutation.id, + params: SetRangeValuesUndoMutationFactory(accessor, redoSetRangeValues.params), + }; + redoMutations.push(redoSetRangeValues); + undoMutations.push(undoSetRangeValues); + } + } + const res = sequenceExecute(redoMutations, commandService); + if (res.result) { + redoUndoService.pushUndoRedo({ + unitID: unitId, + redoMutations, + undoMutations, + }); + return true; + } + + return false; + }, +}; + +export interface IUpdateSheetDataValidationOptionsCommandParams extends ISheetCommandSharedParams { + ruleId: string; + options: IDataValidationRuleOptions; +} + +export const UpdateSheetDataValidationOptionsCommand: ICommand = { + type: CommandType.COMMAND, + id: 'sheets.command.update-data-validation-options', + handler(accessor, params) { + if (!params) { + return false; + } + const commandService = accessor.get(ICommandService); + const redoUndoService = accessor.get(IUndoRedoService); + const dataValidationModel = accessor.get(DataValidationModel); + + const { unitId, subUnitId, ruleId, options } = params; + + const rule = dataValidationModel.getRuleById(unitId, subUnitId, ruleId); + if (!rule) { + return false; + } + + const mutationParams: IUpdateDataValidationMutationParams = { + unitId, + subUnitId, + ruleId, + payload: { + type: UpdateRuleType.OPTIONS, + payload: options, + }, + }; + + const redoMutations: IMutationInfo[] = [{ + id: UpdateDataValidationMutation.id, + params: mutationParams, + }]; + const undoMutationParams: IUpdateDataValidationMutationParams = { + unitId, + subUnitId, + ruleId, + payload: { + type: UpdateRuleType.OPTIONS, + payload: getRuleOptions(rule), + }, + }; + const undoMutations: IMutationInfo[] = [{ + id: UpdateDataValidationMutation.id, + params: undoMutationParams, + }]; + + redoUndoService.pushUndoRedo({ + unitID: unitId, + redoMutations, + undoMutations, + }); + + commandService.executeCommand(UpdateDataValidationMutation.id, mutationParams); + return true; + }, +}; + diff --git a/packages/sheets-data-validation/src/controllers/dv-auto-fill.controller.ts b/packages/sheets-data-validation/src/controllers/dv-auto-fill.controller.ts index af7ea0eb7c..c62505ae0d 100644 --- a/packages/sheets-data-validation/src/controllers/dv-auto-fill.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv-auto-fill.controller.ts @@ -17,7 +17,7 @@ import { DataValidationType, Disposable, LifecycleStages, OnLifecycle, Range, Rectangle } from '@univerjs/core'; import type { IAutoFillLocation, ISheetAutoFillHook } from '@univerjs/sheets-ui'; import { APPLY_TYPE, getAutoFillRepeatRange, IAutoFillService, virtualizeDiscreteRanges } from '@univerjs/sheets-ui'; -import { Inject } from '@wendellhu/redi'; +import { Inject, Injector } from '@wendellhu/redi'; import { DataValidationModel } from '@univerjs/data-validation'; import { DATA_VALIDATION_PLUGIN_NAME } from '../common/const'; import type { SheetDataValidationManager } from '../models/sheet-data-validation-manager'; @@ -27,7 +27,8 @@ import { getDataValidationDiffMutations } from '../commands/commands/data-valida export class DataValidationAutoFillController extends Disposable { constructor( @IAutoFillService private readonly _autoFillService: IAutoFillService, - @Inject(DataValidationModel) private readonly _dataValidationModel: DataValidationModel + @Inject(DataValidationModel) private readonly _dataValidationModel: DataValidationModel, + @Inject(Injector) private readonly _injector: Injector ) { super(); this._initAutoFill(); @@ -95,7 +96,7 @@ export class DataValidationAutoFillController extends Disposable { }); const diffs = ruleMatrixCopy.diff(manager.getDataValidations()); - const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs); + const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs, this._injector); return { undos: undoMutations, redos: redoMutations, diff --git a/packages/sheets-data-validation/src/controllers/dv-copy-paste.controller.ts b/packages/sheets-data-validation/src/controllers/dv-copy-paste.controller.ts index f26c7e26a1..3c55e987ed 100644 --- a/packages/sheets-data-validation/src/controllers/dv-copy-paste.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv-copy-paste.controller.ts @@ -153,7 +153,8 @@ export class DataValidationCopyPasteController extends Disposable { const { redoMutations, undoMutations } = getDataValidationDiffMutations( copyInfo.unitId, copyInfo.subUnitId, - ruleMatrix.diffWithAddition(manager.getDataValidations(), additionRules.values()) + ruleMatrix.diffWithAddition(manager.getDataValidations(), additionRules.values()), + this._injector ); return { @@ -187,7 +188,8 @@ export class DataValidationCopyPasteController extends Disposable { const { redoMutations, undoMutations } = getDataValidationDiffMutations( unitId, subUnitId, - ruleMatrix.diff(manager.getDataValidations()) + ruleMatrix.diff(manager.getDataValidations()), + this._injector ); return { diff --git a/packages/sheets-data-validation/src/controllers/dv-render.controller.ts b/packages/sheets-data-validation/src/controllers/dv-render.controller.ts index fb26c72f53..ea03c0fbad 100644 --- a/packages/sheets-data-validation/src/controllers/dv-render.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv-render.controller.ts @@ -27,7 +27,7 @@ import { INTERCEPTOR_POINT, SheetInterceptorService } from '@univerjs/sheets'; import { DataValidationPanel, DATE_DROPDOWN_KEY, DateDropdown, LIST_DROPDOWN_KEY, ListDropDown } from '../views'; import { FORMULA_INPUTS } from '../views/formula-input'; import { getCellValueOrigin } from '../utils/get-cell-data-origin'; -import type { CheckboxValidator, ListValidator } from '../validators'; +import type { ListValidator } from '../validators'; import type { SheetDataValidationManager } from '../models/sheet-data-validation-manager'; import { CellDropdown, DROP_DOWN_KEY } from '../views/drop-down'; import { DataValidationDropdownManagerService } from '../services/dropdown-manager.service'; @@ -256,18 +256,12 @@ export class SheetsDataValidationRenderController extends RxDisposable { } if (rule.type === DataValidationType.CHECKBOX) { - const { formula2 } = (validator as CheckboxValidator).parseFormulaSync(rule, pos.unitId, pos.subUnitId); - if (!cellValue) { - extra = { - v: formula2, - t: 1, - p: null, - interceptorStyle: { - ...cell?.interceptorStyle, - tb: WrapStrategy.CLIP, - }, - }; - } + extra = { + interceptorStyle: { + ...cell?.interceptorStyle, + tb: WrapStrategy.CLIP, + }, + }; } if (rule.type === DataValidationType.LIST && (rule.renderMode === DataValidationRenderMode.ARROW || rule.renderMode === DataValidationRenderMode.TEXT)) { @@ -454,18 +448,13 @@ export class SheetsDataValidationMobileRenderController extends RxDisposable { } if (rule.type === DataValidationType.CHECKBOX) { - const { formula2 } = (validator as CheckboxValidator).parseFormulaSync(rule, pos.unitId, pos.subUnitId); - if (!cellValue) { - extra = { - v: formula2, - t: 1, - p: null, - interceptorStyle: { - ...cell?.interceptorStyle, - tb: WrapStrategy.CLIP, - }, - }; - } + extra = { + + interceptorStyle: { + ...cell?.interceptorStyle, + tb: WrapStrategy.CLIP, + }, + }; } if (rule.type === DataValidationType.LIST && (rule.renderMode === DataValidationRenderMode.ARROW || rule.renderMode === DataValidationRenderMode.TEXT)) { diff --git a/packages/sheets-data-validation/src/controllers/dv.controller.ts b/packages/sheets-data-validation/src/controllers/dv.controller.ts index c0165c4a86..19b739c51b 100644 --- a/packages/sheets-data-validation/src/controllers/dv.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv.controller.ts @@ -123,7 +123,7 @@ export class DataValidationController extends RxDisposable { selections && ruleMatrix.removeRange(selections); const diffs = ruleMatrix.diff(manager.getDataValidations()); - const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs); + const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs, this._injector); return { undos: undoMutations, diff --git a/packages/sheets-data-validation/src/locale/en-US.ts b/packages/sheets-data-validation/src/locale/en-US.ts index 62e2bcc036..b0f579f9aa 100644 --- a/packages/sheets-data-validation/src/locale/en-US.ts +++ b/packages/sheets-data-validation/src/locale/en-US.ts @@ -20,6 +20,7 @@ const locale: typeof zhCN = { dataValidation: { title: 'Data validation', validFail: { + value: 'Please input a value', common: 'Please input value or formula', number: 'Please input number or formula', formula: 'Please input formula', @@ -30,6 +31,7 @@ const locale: typeof zhCN = { checkboxEqual: 'Enter different values for ticked and unticked cell contents.', formulaError: 'The reference range contains invisible data, please readjust the range', listIntersects: 'The selected range cannot intersect with the scope of the rules', + primitive: 'Formulas are not permitted for custom ticked and unticked values.', }, panel: { title: 'Data validation management', @@ -43,6 +45,7 @@ const locale: typeof zhCN = { removeRule: 'Remove', done: 'Done', formulaPlaceholder: 'Please input value or formula', + valuePlaceholder: 'Please input value', formulaAnd: 'and', invalid: 'Invalid', showWarning: 'Show warning', diff --git a/packages/sheets-data-validation/src/locale/ru-RU.ts b/packages/sheets-data-validation/src/locale/ru-RU.ts index d6c9645353..438816974b 100644 --- a/packages/sheets-data-validation/src/locale/ru-RU.ts +++ b/packages/sheets-data-validation/src/locale/ru-RU.ts @@ -20,6 +20,7 @@ const locale: typeof zhCN = { dataValidation: { title: 'Проверка данных', validFail: { + value: 'Пожалуйста, введите значение', common: 'Пожалуйста, введите значение или формулу', number: 'Пожалуйста, введите число или формулу', formula: 'Пожалуйста, введите формулу', @@ -30,6 +31,7 @@ const locale: typeof zhCN = { checkboxEqual: 'Для выбранных и не выбранных ячеек введите разные значения', formulaError: 'Диапазон ссылок содержит невидимые данные, пожалуйста, пересмотрите диапазон', listIntersects: 'Выбранный диапазон не может пересекаться с диапазоном правила.', + primitive: 'Formulas are not permitted for custom ticked and unticked values.', }, panel: { title: 'Управление проверкой данных', @@ -43,6 +45,7 @@ const locale: typeof zhCN = { removeRule: 'Удалить', done: 'Готово', formulaPlaceholder: 'Пожалуйста, введите значение или формулу', + valuePlaceholder: 'Пожалуйста, введите значение', formulaAnd: 'и', invalid: 'Недопустимо', showWarning: 'Показать предупреждение', diff --git a/packages/sheets-data-validation/src/locale/zh-CN.ts b/packages/sheets-data-validation/src/locale/zh-CN.ts index 9fab9fee0a..6c15c6a055 100644 --- a/packages/sheets-data-validation/src/locale/zh-CN.ts +++ b/packages/sheets-data-validation/src/locale/zh-CN.ts @@ -18,9 +18,10 @@ const locale = { dataValidation: { title: '数据验证', validFail: { + value: '请输入一个合法值', common: '请输入值或公式', number: '请输入合法的数字或公式', - formula: '请输入合法的公式或公式', + formula: '请输入合法的公式', integer: '请输入合法的整数或公式', date: '请输入合法的日期或公式', list: '请输入至少一个合法选项', @@ -28,6 +29,7 @@ const locale = { checkboxEqual: '为勾选和未勾选的单元格内容输入不同的值。', formulaError: '引用范围内包含不可见的数据,请重新调整范围', listIntersects: '所选范围不能和规则范围相交', + primitive: '自定义勾选和未勾选值不允许使用公式。', }, panel: { title: '管理数据验证', @@ -41,6 +43,7 @@ const locale = { removeRule: '删除规则', done: '确认', formulaPlaceholder: '请输入值或公式', + valuePlaceholder: '请输入值', formulaAnd: '与', invalid: '数据无效时', showWarning: '显示警告', diff --git a/packages/sheets-data-validation/src/models/sheet-data-validation-manager.ts b/packages/sheets-data-validation/src/models/sheet-data-validation-manager.ts index d50e24bd9b..405faec747 100644 --- a/packages/sheets-data-validation/src/models/sheet-data-validation-manager.ts +++ b/packages/sheets-data-validation/src/models/sheet-data-validation-manager.ts @@ -126,6 +126,10 @@ export class SheetDataValidationManager extends DataValidationManager, rule: ISheetDataValidationRule, pos: ISheetLocationBase, onCompete: (status: DataValidationStatus, changed: boolean) => void): DataValidationStatus { const { col, row, unitId, subUnitId } = pos; const ruleId = rule.uid; - const validator = this._dataValidatorRegistryService.getValidatorItem(rule.type); + const validator = this.getValidator(rule.type); if (validator) { const current = this._cache.getValue(row, col); if (!current || current.value !== cellValue) { diff --git a/packages/sheets-data-validation/src/plugin.ts b/packages/sheets-data-validation/src/plugin.ts index 3e08329e62..195bb2ac09 100644 --- a/packages/sheets-data-validation/src/plugin.ts +++ b/packages/sheets-data-validation/src/plugin.ts @@ -24,7 +24,7 @@ import { DefaultSheetsDataValidation, SheetsDataValidationRenderController } fro import { DataValidationController } from './controllers/dv.controller'; import { SheetDataValidationService } from './services/dv.service'; import { DataValidationAlertController } from './controllers/dv-alert.controller'; -import { AddSheetDataValidationAndOpenCommand, AddSheetDataValidationCommand, UpdateSheetDataValidationRangeCommand } from './commands/commands/data-validation.command'; +import { AddSheetDataValidationAndOpenCommand, AddSheetDataValidationCommand, UpdateSheetDataValidationOptionsCommand, UpdateSheetDataValidationRangeCommand, UpdateSheetDataValidationSettingCommand } from './commands/commands/data-validation.command'; import { DataValidationCacheService } from './services/dv-cache.service'; import { DataValidationFormulaService } from './services/dv-formula.service'; import { DataValidationCustomFormulaService } from './services/dv-custom-formula.service'; @@ -91,6 +91,8 @@ export class UniverSheetsDataValidationPlugin extends Plugin { AddSheetDataValidationCommand, AddSheetDataValidationAndOpenCommand, UpdateSheetDataValidationRangeCommand, + UpdateSheetDataValidationSettingCommand, + UpdateSheetDataValidationOptionsCommand, // operation ShowDataValidationDropdown, diff --git a/packages/sheets-data-validation/src/utils/get-cell-data-origin.ts b/packages/sheets-data-validation/src/utils/get-cell-data-origin.ts index 66b61bd76a..03e95b7e75 100644 --- a/packages/sheets-data-validation/src/utils/get-cell-data-origin.ts +++ b/packages/sheets-data-validation/src/utils/get-cell-data-origin.ts @@ -37,3 +37,7 @@ export function getCellValueOrigin(cell: Nullable) { return cell?.v; } + +export function getStringCellValue(cell: Nullable) { + return String(getCellValueOrigin(cell) ?? ''); +} diff --git a/packages/sheets-data-validation/src/validators/checkbox-validator.ts b/packages/sheets-data-validation/src/validators/checkbox-validator.ts index f05adc825f..7a7977ec21 100644 --- a/packages/sheets-data-validation/src/validators/checkbox-validator.ts +++ b/packages/sheets-data-validation/src/validators/checkbox-validator.ts @@ -15,10 +15,9 @@ */ import { DataValidationType, isFormulaString, Tools } from '@univerjs/core'; -import type { CellValue, DataValidationOperator, IDataValidationRule, IDataValidationRuleBase, ISheetDataValidationRule, Nullable } from '@univerjs/core'; +import type { CellValue, DataValidationOperator, IDataValidationRule, IDataValidationRuleBase, ISheetDataValidationRule, LocaleService, Nullable } from '@univerjs/core'; import { BaseDataValidator } from '@univerjs/data-validation'; import type { IFormulaResult, IFormulaValidResult, IValidatorCellInfo } from '@univerjs/data-validation'; -import type { ISheetLocation } from '@univerjs/sheets'; import { CheckboxRender } from '../widgets/checkbox-widget'; import { DataValidationFormulaService } from '../services/dv-formula.service'; import { getFormulaResult } from '../utils/formula'; @@ -27,6 +26,18 @@ import { CHECKBOX_FORMULA_INPUT_NAME } from '../views/formula-input'; export const CHECKBOX_FORMULA_1 = 1; export const CHECKBOX_FORMULA_2 = 0; +function getFailMessage(formula: string | undefined, localeService: LocaleService) { + if (Tools.isBlank(formula)) { + return localeService.t('dataValidation.validFail.value'); + } + + if (isFormulaString(formula)) { + return localeService.t('dataValidation.validFail.primitive'); + } + + return ''; +} + export class CheckboxValidator extends BaseDataValidator { override id: string = DataValidationType.CHECKBOX; override title: string = 'dataValidation.checkbox.title'; @@ -38,31 +49,40 @@ export class CheckboxValidator extends BaseDataValidator { private _formulaService = this.injector.get(DataValidationFormulaService); - override skipDefaultFontRender(rule: ISheetDataValidationRule, cellValue: Nullable, pos: ISheetLocation) { + override skipDefaultFontRender(rule: ISheetDataValidationRule, cellValue: Nullable, pos: { unitId: string; subUnitId: string }) { const { formula1, formula2 } = this.parseFormulaSync(rule, pos.unitId, pos.subUnitId); const valueStr = `${cellValue ?? ''}`; - return !valueStr || (valueStr === (`${formula1}`) || valueStr === `${formula2}`); + + const res = !valueStr || (valueStr === (`${formula1}`) || valueStr === `${formula2}`); + return res; } override validatorFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): IFormulaValidResult { const { formula1, formula2 } = rule; - const formula1Success = !Tools.isBlank(formula1); - const formula2Success = !Tools.isBlank(formula2); const isEqual = formula1 === formula2; + if (Tools.isBlank(formula1) && Tools.isBlank(formula2)) { + return { + success: true, + }; + } + + if (isEqual) { + return { + success: false, + formula1: this.localeService.t('dataValidation.validFail.checkboxEqual'), + formula2: this.localeService.t('dataValidation.validFail.checkboxEqual'), + }; + } + + const error1 = getFailMessage(formula1, this.localeService); + const error2 = getFailMessage(formula2, this.localeService); + return { - success: (formula1Success && formula2Success && !isEqual) || (!formula1Success && !formula2Success), - formula1: !formula1Success ? - this.localeService.t('dataValidation.validFail.common') - : isEqual ? - this.localeService.t('dataValidation.validFail.checkboxEqual') - : '', - formula2: !formula2Success ? - this.localeService.t('dataValidation.validFail.common') - : isEqual ? - this.localeService.t('dataValidation.validFail.checkboxEqual') - : '', + success: (!error1 && !error2), + formula1: error1, + formula2: error2, }; } diff --git a/packages/sheets-data-validation/src/views/detail/index.tsx b/packages/sheets-data-validation/src/views/detail/index.tsx index 188e3a40ac..0b03273062 100644 --- a/packages/sheets-data-validation/src/views/detail/index.tsx +++ b/packages/sheets-data-validation/src/views/detail/index.tsx @@ -16,15 +16,14 @@ import type { DataValidationOperator, DataValidationType, IDataValidationRuleBase, IDataValidationRuleOptions, IExecutionOptions, ISheetDataValidationRule, IUnitRange } from '@univerjs/core'; import { createInternalEditorID, debounce, ICommandService, isUnitRangesEqual, isValidRange, LocaleService, RedoCommand, shallowEqual, UndoCommand } from '@univerjs/core'; -import type { IUpdateDataValidationSettingCommandParams } from '@univerjs/data-validation'; -import { DataValidationModel, DataValidatorRegistryScope, DataValidatorRegistryService, getRuleOptions, getRuleSetting, RemoveDataValidationCommand, TWO_FORMULA_OPERATOR_COUNT, UpdateDataValidationOptionsCommand, UpdateDataValidationSettingCommand } from '@univerjs/data-validation'; +import { DataValidationModel, DataValidatorRegistryScope, DataValidatorRegistryService, getRuleOptions, getRuleSetting, RemoveDataValidationCommand, TWO_FORMULA_OPERATOR_COUNT } from '@univerjs/data-validation'; import { Button, FormLayout, Select } from '@univerjs/design'; import { ComponentManager, RangeSelector, useEvent, useObservable } from '@univerjs/ui'; import { useDependency } from '@wendellhu/redi/react-bindings'; import React, { useEffect, useMemo, useState } from 'react'; import { serializeRange } from '@univerjs/engine-formula'; import type { IUpdateSheetDataValidationRangeCommandParams } from '../../commands/commands/data-validation.command'; -import { UpdateSheetDataValidationRangeCommand } from '../../commands/commands/data-validation.command'; +import { UpdateSheetDataValidationOptionsCommand, UpdateSheetDataValidationRangeCommand, UpdateSheetDataValidationSettingCommand } from '../../commands/commands/data-validation.command'; import { DataValidationOptions } from '../options'; import { DataValidationPanelService } from '../../services/data-validation-panel.service'; import styles from './index.module.less'; @@ -124,7 +123,7 @@ export function DataValidationDetail() { ...localRule, ...setting, }); - const params: IUpdateDataValidationSettingCommandParams = { + const params = { unitId, subUnitId, ruleId, @@ -132,7 +131,7 @@ export function DataValidationDetail() { }; debounceExecute( - UpdateDataValidationSettingCommand.id, + UpdateSheetDataValidationSettingCommand.id, params, undefined ); @@ -176,7 +175,7 @@ export function DataValidationDetail() { }; setLocalRule(newRule); - commandService.executeCommand(UpdateDataValidationSettingCommand.id, { + commandService.executeCommand(UpdateSheetDataValidationSettingCommand.id, { unitId, subUnitId, ruleId: localRule.uid, @@ -199,7 +198,7 @@ export function DataValidationDetail() { }); debounceExecute( - UpdateDataValidationOptionsCommand.id, + UpdateSheetDataValidationOptionsCommand.id, { unitId, subUnitId, diff --git a/packages/sheets-data-validation/src/views/formula-input/checkbox-formula-input.tsx b/packages/sheets-data-validation/src/views/formula-input/checkbox-formula-input.tsx index 69ddaf4edc..9769c1cb60 100644 --- a/packages/sheets-data-validation/src/views/formula-input/checkbox-formula-input.tsx +++ b/packages/sheets-data-validation/src/views/formula-input/checkbox-formula-input.tsx @@ -55,7 +55,7 @@ export function CheckboxFormulaInput(props: IFormulaInputProps) { { onChange?.({ @@ -72,7 +72,7 @@ export function CheckboxFormulaInput(props: IFormulaInputProps) { { onChange?.({ diff --git a/packages/sheets-data-validation/src/views/list/index.tsx b/packages/sheets-data-validation/src/views/list/index.tsx index 1ef5bfaf06..a855243f02 100644 --- a/packages/sheets-data-validation/src/views/list/index.tsx +++ b/packages/sheets-data-validation/src/views/list/index.tsx @@ -28,7 +28,6 @@ import { DataValidationItem } from '../item'; import type { IAddSheetDataValidationCommandParams } from '../../commands/commands/data-validation.command'; import { AddSheetDataValidationCommand } from '../../commands/commands/data-validation.command'; import { DataValidationPanelService } from '../../services/data-validation-panel.service'; -import { DataValidationController } from '../../controllers/dv.controller'; import styles from './index.module.less'; export function DataValidationList() { @@ -50,8 +49,6 @@ function DataValidationListWithWorkbook(props: { workbook: Workbook }) { const commandService = useDependency(ICommandService); const injector = useDependency(Injector); const dataValidationPanelService = useDependency(DataValidationPanelService); - const dataValidationController = useDependency(DataValidationController); - const localeService = useDependency(LocaleService); const [rules, setRules] = useState([]); diff --git a/packages/sheets-data-validation/src/widgets/checkbox-widget.ts b/packages/sheets-data-validation/src/widgets/checkbox-widget.ts index 9d33608a42..8727b9e22d 100644 --- a/packages/sheets-data-validation/src/widgets/checkbox-widget.ts +++ b/packages/sheets-data-validation/src/widgets/checkbox-widget.ts @@ -22,6 +22,7 @@ import type { ISetRangeValuesCommandParams } from '@univerjs/sheets'; import { SetRangeValuesCommand } from '@univerjs/sheets'; import type { BaseDataValidator, IBaseDataValidationWidget, IFormulaResult } from '@univerjs/data-validation'; import { Inject } from '@wendellhu/redi'; +import type { CheckboxValidator } from '../validators/checkbox-validator'; import { CHECKBOX_FORMULA_1, CHECKBOX_FORMULA_2 } from '../validators/checkbox-validator'; import { DataValidationFormulaService } from '../services/dv-formula.service'; import { getFormulaResult } from '../utils/formula'; @@ -97,18 +98,18 @@ export class CheckboxRender implements IBaseDataValidationWidget { const cellBounding = primaryWithCoord.isMergedMainCell ? primaryWithCoord.mergeInfo : primaryWithCoord; const value = getCellValueOrigin(data); const rule = data.dataValidation?.rule; - const validator = data.dataValidation?.validator as BaseDataValidator; + const validator = data.dataValidation?.validator as CheckboxValidator; if (!rule || !validator) { return; } const colors = this._themeService.getCurrentTheme(); - if (!validator.skipDefaultFontRender(rule, value, { unitId, subUnitId })) { + if (!validator.skipDefaultFontRender(rule, value, { unitId: unitId!, subUnitId })) { return; } - const { formula1 = CHECKBOX_FORMULA_1 } = rule; - + const result = validator.parseFormulaSync(rule, unitId, subUnitId); + const { formula1 } = result; const layout = this._calc(cellBounding, style); const { a: scaleX, d: scaleY } = ctx.getTransform(); const left = fixLineWidthByScale(layout.left, scaleX); diff --git a/packages/sheets-ui/src/common/utils.ts b/packages/sheets-ui/src/common/utils.ts index b209ab1aca..28a2fa9535 100644 --- a/packages/sheets-ui/src/common/utils.ts +++ b/packages/sheets-ui/src/common/utils.ts @@ -91,7 +91,7 @@ export function getClearContentMutationParamsForRanges( function getClearContentMutationParamForRange(worksheet: Worksheet, range: IRange): ObjectMatrix> { const { startRow, startColumn, endColumn, endRow } = range; - const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn); + const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn, true); const redoMatrix = new ObjectMatrix>(); let leftTopCellValue: Nullable = null; cellMatrix.forValue((row, col, cellData) => { diff --git a/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts b/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts index cd18608e68..61e17ecac9 100644 --- a/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts +++ b/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts @@ -56,6 +56,7 @@ export class CellCustomRenderController extends Disposable implements IRenderMod const currentRender = this._renderManagerService.getRenderById(unitId); if (currentRender && currentRender.mainComponent) { const spreadsheet = currentRender.mainComponent as Spreadsheet; + // eslint-disable-next-line max-lines-per-function const getActiveRender = (evt: IPointerEvent | IMouseEvent) => { const { offsetX, offsetY } = evt; const scene = currentRender.scene; diff --git a/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts b/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts index 7ecb89e979..b680bcb3a1 100644 --- a/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts +++ b/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -import type { Nullable, Workbook, Worksheet } from '@univerjs/core'; +import { Disposable, type Nullable, type Workbook, type Worksheet } from '@univerjs/core'; import type { IRenderContext, IRenderModule } from '@univerjs/engine-render'; import { SpreadsheetSkeleton } from '@univerjs/engine-render'; -import type { IDisposable } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; import { BehaviorSubject } from 'rxjs'; @@ -43,7 +42,7 @@ export interface ISheetSkeletonManagerSearch { * The viewModel is also a temporary storage variable, which does not need to be persisted, * so it is managed uniformly through the service. */ -export class SheetSkeletonManagerService implements IDisposable, IRenderModule { +export class SheetSkeletonManagerService extends Disposable implements IRenderModule { private _currentSkeletonSearchParam: ISheetSkeletonManagerSearch = { sheetId: '', }; @@ -64,12 +63,23 @@ export class SheetSkeletonManagerService implements IDisposable, IRenderModule { @Inject(Injector) private readonly _injector: Injector ) { // empty + super(); + + this.disposeWithMe(() => { + this._currentSkeletonBefore$.complete(); + this._currentSkeleton$.complete(); + this._sheetSkeletonParam = []; + }); + + this._initRemoveSheet(); } - dispose(): void { - this._currentSkeletonBefore$.complete(); - this._currentSkeleton$.complete(); - this._sheetSkeletonParam = []; + private _initRemoveSheet() { + this.disposeWithMe(this._context.unit.sheetDisposed$.subscribe((sheet) => { + this.disposeSkeleton({ + sheetId: sheet.getSheetId(), + }); + })); } getCurrentSkeleton(): SpreadsheetSkeleton { @@ -162,6 +172,15 @@ export class SheetSkeletonManagerService implements IDisposable, IRenderModule { return newSkeleton; } + disposeSkeleton(searchParm: ISheetSkeletonManagerSearch) { + const index = this._sheetSkeletonParam.findIndex((param) => param.sheetId === searchParm.sheetId); + if (index > -1) { + const skeleton = this._sheetSkeletonParam[index]; + skeleton.skeleton.dispose(); + this._sheetSkeletonParam.splice(index, 1); + } + } + private _getSkeleton(searchParm: ISheetSkeletonManagerSearch): Nullable { const item = this._sheetSkeletonParam.find((param) => param.sheetId === searchParm.sheetId); if (item != null) { diff --git a/packages/sheets-ui/src/sheets-ui-plugin.ts b/packages/sheets-ui/src/sheets-ui-plugin.ts index 1907c832b4..3a83818a07 100644 --- a/packages/sheets-ui/src/sheets-ui-plugin.ts +++ b/packages/sheets-ui/src/sheets-ui-plugin.ts @@ -150,6 +150,7 @@ export class UniverSheetsUIPlugin extends Plugin { [SheetPermissionInterceptorBaseController], [SheetPermissionInitController], [MoveRangeController], + ] as Dependency[] ).forEach((d) => injector.add(d)); @@ -218,6 +219,7 @@ export class UniverSheetsUIPlugin extends Plugin { SheetPermissionInterceptorCanvasRenderController, SheetPermissionInterceptorFormulaRenderController, SheetPermissionRenderController, + ]).forEach((m) => { this.disposeWithMe(this._renderManagerService.registerRenderModule(UniverInstanceType.UNIVER_SHEET, m)); }); diff --git a/packages/sheets/src/commands/commands/add-worksheet-merge.command.ts b/packages/sheets/src/commands/commands/add-worksheet-merge.command.ts index 074678ebaf..984f46dc94 100644 --- a/packages/sheets/src/commands/commands/add-worksheet-merge.command.ts +++ b/packages/sheets/src/commands/commands/add-worksheet-merge.command.ts @@ -104,7 +104,7 @@ function getClearContentMutationParamsForRanges( function getClearContentMutationParamForRange(worksheet: Worksheet, range: IRange): ObjectMatrix> { const { startRow, startColumn, endColumn, endRow } = range; - const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn); + const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn, true); const redoMatrix = new ObjectMatrix>(); cellMatrix.forValue((row, col, cellData) => { if (cellData && (row !== startRow || col !== startColumn)) { diff --git a/packages/sheets/src/services/ref-range/ref-range.service.ts b/packages/sheets/src/services/ref-range/ref-range.service.ts index 2989c9ec1d..5fa6cb8175 100644 --- a/packages/sheets/src/services/ref-range/ref-range.service.ts +++ b/packages/sheets/src/services/ref-range/ref-range.service.ts @@ -68,7 +68,6 @@ class WatchRange extends Disposable { if (mutation.params.unitId !== this._unitId || mutation.params.subUnitId !== this._subUnitId) { return; } - if (!this._range) { return; } @@ -122,7 +121,6 @@ export class RefRangeService extends Disposable { if (this._watchRanges.size === 0) { watchRangesListener = this._commandService.onCommandExecuted((command) => { if (command.type !== CommandType.MUTATION) return false; - for (const watchRange of this._watchRanges) { watchRange.onMutation(command as IMutationInfo); } diff --git a/packages/ui/src/views/components/sidebar/Sidebar.tsx b/packages/ui/src/views/components/sidebar/Sidebar.tsx index 50d61e901e..9784a77f41 100644 --- a/packages/ui/src/views/components/sidebar/Sidebar.tsx +++ b/packages/ui/src/views/components/sidebar/Sidebar.tsx @@ -17,51 +17,49 @@ import { CloseSingle } from '@univerjs/icons'; import { useDependency } from '@wendellhu/redi/react-bindings'; import clsx from 'clsx'; -import React, { useEffect, useMemo, useState } from 'react'; - +import React, { useMemo } from 'react'; import { CustomLabel } from '../../../components/custom-label/CustomLabel'; import { ISidebarService } from '../../../services/sidebar/sidebar.service'; +import { useObservable } from '../../../components/hooks/observable'; import styles from './index.module.less'; import type { ISidebarMethodOptions } from './interface'; export function Sidebar() { const sidebarService = useDependency(ISidebarService); + const sidebarOptions = useObservable(sidebarService.sidebarOptions$); - const [sidebarOptions, setSidebarOptions] = useState({}); + const options = useMemo(() => { + if (!sidebarOptions) { + return null; + } - useEffect(() => { - const subscribtion = sidebarService.sidebarOptions$.subscribe((options: ISidebarMethodOptions) => { - setSidebarOptions(options); - }); - - return () => { - subscribtion.unsubscribe(); + const copy = { ...sidebarOptions } as Omit & { + children?: React.ReactNode; + header?: React.ReactNode; + footer?: React.ReactNode; }; - }, []); - const options = sidebarOptions as Omit & { - children?: React.ReactNode; - header?: React.ReactNode; - footer?: React.ReactNode; - }; - for (const key of ['children', 'header', 'footer']) { - const k = key as keyof ISidebarMethodOptions; + for (const key of ['children', 'header', 'footer']) { + const k = key as keyof ISidebarMethodOptions; - if (sidebarOptions[k]) { - const props = sidebarOptions[k] as any; + if (sidebarOptions[k]) { + const props = sidebarOptions[k] as any; - if (props) { - (options as any)[k] = ; + if (props) { + (copy as any)[k] = ; + } } } - } + + return copy; + }, [sidebarOptions]); const _className = clsx(styles.sidebar, { - [styles.sidebarOpen]: options.visible, + [styles.sidebarOpen]: options?.visible, }); const width = useMemo(() => { - if (!options.visible) return 0; + if (!options?.visible) return 0; if (typeof options.width === 'number') { return `${options.width}px`; @@ -76,7 +74,6 @@ export function Sidebar() { visible: false, }; - setSidebarOptions(options); sidebarService.sidebarOptions$.next(options); options?.onClose?.(); }