From ab242a32a1efabe15b6024c2fd45f11166a639a4 Mon Sep 17 00:00:00 2001 From: zhangw Date: Sat, 20 Jul 2024 13:41:50 +0800 Subject: [PATCH] feat(data-validation): code optimize for data-validation (#2815) --- .../commands/data-validation.command.ts | 5 +- .../mutations/data-validation.mutation.ts | 18 +++--- .../src/controllers/dv-resource.controller.ts | 2 +- .../src/controllers/dv-sheet.controller.ts | 2 + packages/data-validation/src/index.ts | 2 +- .../src/models/data-validation-manager.ts | 20 ++----- .../src/models/data-validation-model.ts | 22 ++++--- .../commands/data-validation.command.ts | 11 +++- .../controllers/dv-auto-fill.controller.ts | 2 +- .../controllers/dv-copy-paste.controller.ts | 6 +- .../src/controllers/dv-model.controller.ts | 1 - .../controllers/dv-ref-range.controller.ts | 2 + .../src/controllers/dv-render.controller.ts | 57 +++++++++++-------- .../src/controllers/dv.controller.ts | 2 +- .../models/sheet-data-validation-manager.ts | 20 +------ 15 files changed, 89 insertions(+), 83 deletions(-) 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 8dcf8644948..98cf0f4d47b 100644 --- a/packages/data-validation/src/commands/commands/data-validation.command.ts +++ b/packages/data-validation/src/commands/commands/data-validation.command.ts @@ -37,7 +37,7 @@ export interface IAddDataValidationCommandParams extends ISheetCommandSharedPara export const AddDataValidationCommand: ICommand = { type: CommandType.COMMAND, id: 'data-validation.command.addRule', - async handler(accessor, params) { + 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) { @@ -83,7 +83,7 @@ export interface IRemoveDataValidationCommandParams extends ISheetCommandSharedP export const removeDataValidationUndoFactory = (accessor: Injector, redoParams: IRemoveDataValidationMutationParams) => { const dataValidationModel = accessor.get(DataValidationModel); - const { unitId, subUnitId, ruleId } = redoParams; + const { unitId, subUnitId, ruleId, source } = redoParams; if (Array.isArray(ruleId)) { const rules = ruleId.map((id) => dataValidationModel.getRuleById(unitId, subUnitId, id)).filter(Boolean) as ISheetDataValidationRule[]; return [{ @@ -92,6 +92,7 @@ export const removeDataValidationUndoFactory = (accessor: Injector, redoParams: unitId, subUnitId, rule: rules, + source, } as IAddDataValidationMutationParams, }]; } diff --git a/packages/data-validation/src/commands/mutations/data-validation.mutation.ts b/packages/data-validation/src/commands/mutations/data-validation.mutation.ts index 5e75267b748..5e96d22e458 100644 --- a/packages/data-validation/src/commands/mutations/data-validation.mutation.ts +++ b/packages/data-validation/src/commands/mutations/data-validation.mutation.ts @@ -18,11 +18,13 @@ import { CommandType } from '@univerjs/core'; import type { ICommand, IDataValidationRule } from '@univerjs/core'; import type { ISheetCommandSharedParams } from '@univerjs/sheets'; import type { IUpdateRulePayload } from '../../types/interfaces/i-update-rule-payload'; +import type { DataValidationChangeSource } from '../../models/data-validation-model'; import { DataValidationModel } from '../../models/data-validation-model'; export interface IAddDataValidationMutationParams extends ISheetCommandSharedParams { rule: IDataValidationRule | IDataValidationRule[]; index?: number; + source?: DataValidationChangeSource; } export const AddDataValidationMutation: ICommand = { @@ -32,9 +34,9 @@ export const AddDataValidationMutation: ICommand = { @@ -52,14 +55,14 @@ export const RemoveDataValidationMutation: ICommand { - dataValidationModel.removeRule(unitId, subUnitId, item); + dataValidationModel.removeRule(unitId, subUnitId, item, source); }); } else { - dataValidationModel.removeRule(unitId, subUnitId, ruleId); + dataValidationModel.removeRule(unitId, subUnitId, ruleId, source); } return true; @@ -69,6 +72,7 @@ export const RemoveDataValidationMutation: ICommand = { @@ -79,9 +83,9 @@ export const UpdateDataValidationMutation: ICommand { const ruleList = value[subunitId]; ruleList.forEach((rule) => { - this._dataValidationModel.addRule(unitID, subunitId, rule); + this._dataValidationModel.addRule(unitID, subunitId, rule, 'patched'); }); }); }, diff --git a/packages/data-validation/src/controllers/dv-sheet.controller.ts b/packages/data-validation/src/controllers/dv-sheet.controller.ts index 0e0bc22ee48..1f51db602d4 100644 --- a/packages/data-validation/src/controllers/dv-sheet.controller.ts +++ b/packages/data-validation/src/controllers/dv-sheet.controller.ts @@ -61,11 +61,13 @@ export class DataValidationSheetController extends Disposable { unitId, subUnitId, ruleId: ids, + source: 'patched', }; const undoParams: IAddDataValidationMutationParams = { unitId, subUnitId, rule: rules, + source: 'patched', }; return { diff --git a/packages/data-validation/src/index.ts b/packages/data-validation/src/index.ts index 992ea35905a..93889158e33 100644 --- a/packages/data-validation/src/index.ts +++ b/packages/data-validation/src/index.ts @@ -16,7 +16,7 @@ export { UniverDataValidationPlugin } from './plugin'; export { DataValidatorRegistryService, DataValidatorRegistryScope } from './services/data-validator-registry.service'; -export { DataValidationModel } from './models/data-validation-model'; +export { DataValidationModel, type DataValidationChangeSource } from './models/data-validation-model'; export { createDefaultNewRule, diff --git a/packages/data-validation/src/models/data-validation-manager.ts b/packages/data-validation/src/models/data-validation-manager.ts index aab752e39a5..ac8e9236acb 100644 --- a/packages/data-validation/src/models/data-validation-manager.ts +++ b/packages/data-validation/src/models/data-validation-manager.ts @@ -16,29 +16,24 @@ import type { CellValue, IDataValidationRule, Nullable } from '@univerjs/core'; import { DataValidationStatus, Disposable } from '@univerjs/core'; -import { Subject } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import type { IUpdateRulePayload } from '../types/interfaces/i-update-rule-payload'; import { UpdateRuleType } from '../types/enum/update-rule-type'; import { getRuleOptions, getRuleSetting } from '../common/util'; export class DataValidationManager extends Disposable { - private _dataValidations: T[]; + private _dataValidations: T[] = []; private _dataValidationMap = new Map(); - private _dataValidations$ = new Subject(); + private _dataValidations$ = new BehaviorSubject(this._dataValidations); readonly unitId: string; readonly subUnitId: string; readonly dataValidations$ = this._dataValidations$.asObservable(); - constructor(unitId: string, subUnitId: string, dataValidations: T[] | undefined) { + constructor(unitId: string, subUnitId: string) { super(); this.unitId = unitId; this.subUnitId = subUnitId; - if (!dataValidations) { - return; - } - - this._insertRules(dataValidations); this._notice(); this.disposeWithMe({ @@ -52,13 +47,6 @@ export class DataValidationManager extends Dispos this._dataValidations$.next(this._dataValidations); } - private _insertRules(dataValidations: T[]) { - this._dataValidations = dataValidations; - dataValidations.forEach((validation) => { - this._dataValidationMap.set(validation.uid, validation); - }); - } - getRuleById(id: string) { return this._dataValidationMap.get(id); } diff --git a/packages/data-validation/src/models/data-validation-model.ts b/packages/data-validation/src/models/data-validation-model.ts index 71cbde9a496..90b26910f97 100644 --- a/packages/data-validation/src/models/data-validation-model.ts +++ b/packages/data-validation/src/models/data-validation-model.ts @@ -20,13 +20,15 @@ import type { IUpdateRulePayload } from '../types/interfaces/i-update-rule-paylo import { DataValidationManager } from './data-validation-manager'; type ManagerCreator = (unitId: string, subUnitId: string) => DataValidationManager; -type RuleChangeType = 'update' | 'add' | 'remove'; +type DataValidationChangeType = 'update' | 'add' | 'remove'; +export type DataValidationChangeSource = 'command' | 'patched'; export interface IRuleChange { rule?: T; - type: RuleChangeType; + type: DataValidationChangeType; unitId: string; subUnitId: string; + source: DataValidationChangeSource; } export interface IValidStatusChange { @@ -38,7 +40,7 @@ export interface IValidStatusChange { export class DataValidationModel extends Disposable { private readonly _model = new Map>>(); - private _managerCreator: ManagerCreator = (unitId: string, subUnitId: string) => new DataValidationManager(unitId, subUnitId, []); + private _managerCreator: ManagerCreator = (unitId: string, subUnitId: string) => new DataValidationManager(unitId, subUnitId); private readonly _ruleChange$ = new Subject>(); private readonly _validStatusChange$ = new Subject(); @@ -75,10 +77,11 @@ export class DataValidationModel { - this._addRuleSideEffect(unitId, subUnitId, item); + this._addRuleSideEffect(unitId, subUnitId, item, source); }); manager.addRule(rule, index); @@ -106,7 +110,7 @@ export class DataValidationModel { - const ranges: IRange[] = []; - infos.forEach((info) => { - if (info.rule?.ranges) { - ranges.push(...info.rule.ranges); + this._dataValidationModel.ruleChange$ + .pipe( + // patched data-validation change don't need to re-calc row height + // re-calc of row height will be triggered precisely by the origin command + filter((change) => change.source === 'command'), + bufferTime(16) + ) + .subscribe((infos) => { + const ranges: IRange[] = []; + infos.forEach((info) => { + if (info.rule?.ranges) { + ranges.push(...info.rule.ranges); + } + }); + + if (ranges.length) { + const mutations = this._autoHeightController.getUndoRedoParamsOfAutoHeight(ranges); + sequenceExecute(mutations.redos, this._commandService); } }); - - if (ranges.length) { - const mutations = this._autoHeightController.getUndoRedoParamsOfAutoHeight(ranges); - sequenceExecute(mutations.redos, this._commandService); - } - }); } } @@ -510,19 +517,23 @@ export class SheetsDataValidationMobileRenderController extends RxDisposable { } private _initAutoHeight() { - this._dataValidationModel.ruleChange$.pipe(bufferTime(16)).subscribe((infos) => { - const ranges: IRange[] = []; - infos.forEach((info) => { - if (info.rule?.ranges) { - ranges.push(...info.rule.ranges); + this._dataValidationModel.ruleChange$ + .pipe( + filter((change) => change.source === 'command'), + bufferTime(16) + ).subscribe((infos) => { + const ranges: IRange[] = []; + infos.forEach((info) => { + if (info.rule?.ranges) { + ranges.push(...info.rule.ranges); + } + }); + + if (ranges.length) { + const mutations = this._autoHeightController.getUndoRedoParamsOfAutoHeight(ranges); + sequenceExecute(mutations.redos, this._commandService); } }); - - if (ranges.length) { - const mutations = this._autoHeightController.getUndoRedoParamsOfAutoHeight(ranges); - sequenceExecute(mutations.redos, this._commandService); - } - }); } } diff --git a/packages/sheets-data-validation/src/controllers/dv.controller.ts b/packages/sheets-data-validation/src/controllers/dv.controller.ts index 834be298b85..4e4ca72c7e4 100644 --- a/packages/sheets-data-validation/src/controllers/dv.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv.controller.ts @@ -128,7 +128,7 @@ export class DataValidationController extends RxDisposable { selections && ruleMatrix.removeRange(selections); const diffs = ruleMatrix.diff(manager.getDataValidations()); - const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs, this._injector); + const { redoMutations, undoMutations } = getDataValidationDiffMutations(unitId, subUnitId, diffs, this._injector, 'patched'); return { undos: undoMutations, 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 3c88d346268..a47fee006ae 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 @@ -16,7 +16,7 @@ import type { CellValue, Injector, ISheetDataValidationRule, Nullable, Workbook } from '@univerjs/core'; import { DataValidationManager, DataValidatorRegistryService, UpdateRuleType } from '@univerjs/data-validation'; -import { DataValidationStatus, DataValidationType, IUniverInstanceService, ObjectMatrix, Range, UniverInstanceType } from '@univerjs/core'; +import { DataValidationStatus, DataValidationType, IUniverInstanceService, ObjectMatrix, UniverInstanceType } from '@univerjs/core'; import type { IUpdateRulePayload } from '@univerjs/data-validation'; import type { ISheetLocationBase } from '@univerjs/sheets'; import { isReferenceString } from '@univerjs/engine-formula'; @@ -24,7 +24,6 @@ import type { IDataValidationResCache } from '../services/dv-cache.service'; import { DataValidationCacheService } from '../services/dv-cache.service'; import { DataValidationFormulaService } from '../services/dv-formula.service'; import { DataValidationCustomFormulaService } from '../services/dv-custom-formula.service'; -import { DataValidationRefRangeController } from '../controllers/dv-ref-range.controller'; import { RuleMatrix } from './rule-matrix'; export class SheetDataValidationManager extends DataValidationManager { @@ -37,36 +36,21 @@ export class SheetDataValidationManager extends DataValidationManager>; - private _dataValidationRefRangeController: DataValidationRefRangeController; constructor( unitId: string, subUnitId: string, - rules: ISheetDataValidationRule[] | undefined, private readonly _injector: Injector ) { - super(unitId, subUnitId, rules); + super(unitId, subUnitId); this._dataValidatorRegistryService = this._injector.get(DataValidatorRegistryService); this._dataValidationCacheService = this._injector.get(DataValidationCacheService); this._dataValidationFormulaService = this._injector.get(DataValidationFormulaService); this._dataValidationCustomFormulaService = this._injector.get(DataValidationCustomFormulaService); - this._dataValidationRefRangeController = this._injector.get(DataValidationRefRangeController); this._cache = this._dataValidationCacheService.ensureCache(unitId, subUnitId); const univerInstanceService = this._injector.get(IUniverInstanceService); const worksheet = univerInstanceService.getUnit(unitId, UniverInstanceType.UNIVER_SHEET)!.getSheetBySheetId(subUnitId)!; const matrix = new ObjectMatrix(); - rules?.forEach((rule) => { - const ruleId = rule.uid; - rule.ranges.forEach((range) => { - Range.foreach(range, (row, col) => { - matrix.setValue(row, col, ruleId); - }); - }); - }); - - rules?.forEach((rule) => { - this._dataValidationRefRangeController.register(unitId, subUnitId, rule); - }); this._ruleMatrix = new RuleMatrix(matrix, worksheet); }