mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
feat: add freezeSync config and api to controll whether synchronize the frozen state to other users in real-time collaboration (#5960)
This commit is contained in:
@@ -1261,7 +1261,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
|
||||
const params = command.params as IInsertRowCommandParams;
|
||||
const { range, direction } = params;
|
||||
const insertCount = range.endRow - range.startRow + 1;
|
||||
if (range.startRow + 1 < freeze.startRow || (range.startRow + 1 === freeze.startRow && direction === Direction.UP)) {
|
||||
if (range.startRow < freeze.startRow || (range.startRow + 1 === freeze.startRow && direction === Direction.UP)) {
|
||||
const newFreeze: IFreeze = {
|
||||
...freeze,
|
||||
startRow: Math.max(1, freeze.startRow + insertCount),
|
||||
@@ -1276,7 +1276,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
|
||||
const params = command.params as IInsertColCommandParams;
|
||||
const { range, direction } = params;
|
||||
const insertCount = range.endColumn - range.startColumn + 1;
|
||||
if (range.startColumn + 1 < freeze.startColumn || (range.startColumn + 1 === freeze.startColumn && direction === Direction.LEFT)) {
|
||||
if (range.startColumn < freeze.startColumn || (range.startColumn + 1 === freeze.startColumn && direction === Direction.LEFT)) {
|
||||
const newFreeze: IFreeze = {
|
||||
...freeze,
|
||||
startColumn: Math.max(1, freeze.startColumn + insertCount),
|
||||
|
||||
@@ -37,6 +37,12 @@ export interface IUniverSheetsConfig {
|
||||
* default false, auto height works for merged cells
|
||||
*/
|
||||
autoHeightForMergedCells?: boolean;
|
||||
|
||||
/**
|
||||
* Whether synchronize the frozen state to other users in real-time collaboration.
|
||||
* @default true
|
||||
*/
|
||||
freezeSync?: boolean;
|
||||
}
|
||||
|
||||
export const defaultPluginConfig: IUniverSheetsConfig = {};
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* 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 { IExecutionOptions, IFreeze, Workbook } from '@univerjs/core';
|
||||
import type { IInsertColMutationParams, IInsertRowMutationParams, IRemoveColMutationParams, IRemoveRowsMutationParams } from '../basics';
|
||||
import type { IMoveColumnsMutationParams, IMoveRowsMutationParams } from '../commands/mutations/move-rows-cols.mutation';
|
||||
import type { IUniverSheetsConfig } from './config.schema';
|
||||
import { Disposable, DisposableCollection, ICommandService, IConfigService, Inject, IUniverInstanceService, sequenceExecute, UniverInstanceType } from '@univerjs/core';
|
||||
import { InsertColMutation, InsertRowMutation } from '../commands/mutations/insert-row-col.mutation';
|
||||
import { MoveColsMutation, MoveRowsMutation } from '../commands/mutations/move-rows-cols.mutation';
|
||||
import { RemoveColMutation, RemoveRowMutation } from '../commands/mutations/remove-row-col.mutation';
|
||||
import { SetFrozenMutation } from '../commands/mutations/set-frozen.mutation';
|
||||
import { SHEETS_PLUGIN_CONFIG_KEY } from './config.schema';
|
||||
|
||||
const sheetsFreezeOnlyLocalMutationIds = [
|
||||
SetFrozenMutation.id,
|
||||
];
|
||||
|
||||
const effectedByOnlyLocalMutationIds = [
|
||||
InsertRowMutation.id,
|
||||
InsertColMutation.id,
|
||||
RemoveRowMutation.id,
|
||||
RemoveColMutation.id,
|
||||
MoveRowsMutation.id,
|
||||
MoveColsMutation.id,
|
||||
];
|
||||
|
||||
export class SheetsFreezeSyncController extends Disposable {
|
||||
private _d: DisposableCollection = new DisposableCollection();
|
||||
private _enabled: boolean = true;
|
||||
|
||||
constructor(
|
||||
@Inject(IUniverInstanceService) private readonly _univerInstanceService: IUniverInstanceService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IConfigService private readonly _configService: IConfigService
|
||||
) {
|
||||
super();
|
||||
|
||||
const freezeSync = this._configService.getConfig<IUniverSheetsConfig>(SHEETS_PLUGIN_CONFIG_KEY)?.freezeSync ?? true;
|
||||
this.setEnabled(freezeSync);
|
||||
}
|
||||
|
||||
getEnabled() {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
setEnabled(enabled: boolean) {
|
||||
if (enabled) {
|
||||
this._d.dispose();
|
||||
} else {
|
||||
this._initOnlyLocalListener();
|
||||
}
|
||||
this._enabled = enabled;
|
||||
}
|
||||
|
||||
private _initOnlyLocalListener() {
|
||||
this._d.add(
|
||||
this._commandService.beforeCommandExecuted((commandInfo, options) => {
|
||||
if (sheetsFreezeOnlyLocalMutationIds.includes(commandInfo.id)) {
|
||||
if (!options) options = {};
|
||||
options.onlyLocal = true;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this._d.add(
|
||||
this._commandService.onCommandExecuted((commandInfo, options) => {
|
||||
if (effectedByOnlyLocalMutationIds.includes(commandInfo.id) && options?.fromCollab) {
|
||||
const { id, params } = commandInfo;
|
||||
|
||||
if (id === InsertRowMutation.id) {
|
||||
this._handleInsertRowMutation(params as IInsertRowMutationParams, options);
|
||||
} else if (id === InsertColMutation.id) {
|
||||
this._handleInsertColMutation(params as IInsertColMutationParams, options);
|
||||
} else if (id === RemoveRowMutation.id) {
|
||||
this._handleRemoveRowMutation(params as IRemoveRowsMutationParams, options);
|
||||
} else if (id === RemoveColMutation.id) {
|
||||
this._handleRemoveColMutation(params as IRemoveColMutationParams, options);
|
||||
} else if (id === MoveRowsMutation.id) {
|
||||
this._handleMoveRowsMutation(params as IMoveRowsMutationParams, options);
|
||||
} else if (id === MoveColsMutation.id) {
|
||||
this._handleMoveColsMutation(params as IMoveColumnsMutationParams, options);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private _handleInsertRowMutation(params: IInsertRowMutationParams, options?: IExecutionOptions) {
|
||||
const { range, unitId, subUnitId } = params;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
if (!freeze) return;
|
||||
|
||||
if (range.startRow < freeze.startRow) {
|
||||
const insertCount = range.endRow - range.startRow + 1;
|
||||
const newFreeze = {
|
||||
...freeze,
|
||||
startRow: Math.max(1, freeze.startRow + insertCount),
|
||||
ySplit: Math.max(1, freeze.ySplit + insertCount),
|
||||
};
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleInsertColMutation(params: IInsertColMutationParams, options?: IExecutionOptions) {
|
||||
const { range, unitId, subUnitId } = params as IInsertColMutationParams;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
if (!freeze) return;
|
||||
|
||||
if (range.startColumn < freeze.startColumn) {
|
||||
const insertCount = range.endColumn - range.startColumn + 1;
|
||||
const newFreeze = {
|
||||
...freeze,
|
||||
startColumn: Math.max(1, freeze.startColumn + insertCount),
|
||||
xSplit: Math.max(1, freeze.xSplit + insertCount),
|
||||
};
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleRemoveRowMutation(params: IRemoveRowsMutationParams, options?: IExecutionOptions) {
|
||||
const { range, unitId, subUnitId } = params as IRemoveRowsMutationParams;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
if (!freeze) return;
|
||||
|
||||
if (range.startRow < freeze.startRow) {
|
||||
const removeCount = Math.min(freeze.startRow, range.endRow + 1) - range.startRow;
|
||||
const newFreeze = {
|
||||
...freeze,
|
||||
startRow: Math.max(1, freeze.startRow - removeCount),
|
||||
ySplit: Math.max(1, freeze.ySplit - removeCount),
|
||||
};
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleRemoveColMutation(params: IRemoveColMutationParams, options?: IExecutionOptions) {
|
||||
const { range, unitId, subUnitId } = params as IRemoveColMutationParams;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
if (!freeze) return;
|
||||
|
||||
if (range.startColumn < freeze.startColumn) {
|
||||
const removeCount = Math.min(freeze.startColumn, range.endColumn + 1) - range.startColumn;
|
||||
const newFreeze = {
|
||||
...freeze,
|
||||
startColumn: Math.max(1, freeze.startColumn - removeCount),
|
||||
xSplit: Math.max(1, freeze.xSplit - removeCount),
|
||||
};
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleMoveRowsMutation(params: IMoveRowsMutationParams, options?: IExecutionOptions) {
|
||||
const { sourceRange, targetRange, unitId, subUnitId } = params as IMoveRowsMutationParams;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
|
||||
if (
|
||||
!freeze ||
|
||||
freeze.startRow <= 0 ||
|
||||
(sourceRange.startRow >= freeze.startRow && targetRange.startRow >= freeze.startRow) ||
|
||||
(sourceRange.endRow < freeze.startRow && targetRange.endRow < freeze.startRow)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const moveCount = sourceRange.endRow - sourceRange.startRow + 1;
|
||||
const moveFreezeCount = Math.max(
|
||||
Math.min(freeze.startRow, sourceRange.endRow + 1) - sourceRange.startRow,
|
||||
0
|
||||
);
|
||||
const newFreeze: IFreeze = { ...freeze };
|
||||
|
||||
if (targetRange.startRow >= freeze.startRow) {
|
||||
// Move down
|
||||
newFreeze.startRow = Math.max(1, freeze.startRow - moveFreezeCount);
|
||||
newFreeze.ySplit = Math.max(1, freeze.ySplit - moveFreezeCount);
|
||||
} else {
|
||||
// Move up
|
||||
newFreeze.startRow = freeze.startRow + moveCount - moveFreezeCount;
|
||||
newFreeze.ySplit = freeze.ySplit + moveCount - moveFreezeCount;
|
||||
}
|
||||
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
|
||||
private _handleMoveColsMutation(params: IMoveColumnsMutationParams, options?: IExecutionOptions) {
|
||||
const { sourceRange, targetRange, unitId, subUnitId } = params as IMoveColumnsMutationParams;
|
||||
const freeze = this._getFreeze(unitId, subUnitId);
|
||||
|
||||
if (
|
||||
!freeze ||
|
||||
freeze.startColumn <= 0 ||
|
||||
(sourceRange.startColumn >= freeze.startColumn && targetRange.startColumn >= freeze.startColumn) ||
|
||||
(sourceRange.endColumn < freeze.startColumn && targetRange.endColumn < freeze.startColumn)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const moveCount = sourceRange.endColumn - sourceRange.startColumn + 1;
|
||||
const moveFreezeCount = Math.max(
|
||||
Math.min(freeze.startColumn, sourceRange.endColumn + 1) - sourceRange.startColumn,
|
||||
0
|
||||
);
|
||||
const newFreeze: IFreeze = { ...freeze };
|
||||
|
||||
if (targetRange.startColumn >= freeze.startColumn) {
|
||||
// Move right
|
||||
newFreeze.startColumn = Math.max(1, freeze.startColumn - moveFreezeCount);
|
||||
newFreeze.xSplit = Math.max(1, freeze.xSplit - moveFreezeCount);
|
||||
} else {
|
||||
// Move left
|
||||
newFreeze.startColumn = freeze.startColumn + moveCount - moveFreezeCount;
|
||||
newFreeze.xSplit = freeze.xSplit + moveCount - moveFreezeCount;
|
||||
}
|
||||
|
||||
this._sequenceExecute(unitId, subUnitId, newFreeze, options);
|
||||
}
|
||||
|
||||
private _getFreeze(unitId: string, subUnitId: string) {
|
||||
const workbook = this._univerInstanceService.getUnit<Workbook>(unitId, UniverInstanceType.UNIVER_SHEET);
|
||||
if (!workbook) return null;
|
||||
const worksheet = workbook.getSheetBySheetId(subUnitId);
|
||||
if (!worksheet) return null;
|
||||
return worksheet.getFreeze();
|
||||
}
|
||||
|
||||
private _sequenceExecute(unitId: string, subUnitId: string, newFreeze: IFreeze, options?: IExecutionOptions) {
|
||||
sequenceExecute([
|
||||
{
|
||||
id: SetFrozenMutation.id,
|
||||
params: {
|
||||
...newFreeze,
|
||||
unitId,
|
||||
subUnitId,
|
||||
resetScroll: false,
|
||||
},
|
||||
},
|
||||
], this._commandService, options);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import type { FRange } from './f-range';
|
||||
import type { FWorksheet } from './f-worksheet';
|
||||
import { CanceledError, ICommandService, IUniverInstanceService, toDisposable, UniverInstanceType } from '@univerjs/core';
|
||||
import { FUniver } from '@univerjs/core/facade';
|
||||
import { COMMAND_LISTENER_VALUE_CHANGE, getValueChangedEffectedRange, InsertSheetCommand, RemoveSheetCommand, SetGridlinesColorCommand, SetTabColorMutation, SetWorksheetActiveOperation, SetWorksheetHideMutation, SetWorksheetNameCommand, SetWorksheetOrderMutation, ToggleGridlinesCommand } from '@univerjs/sheets';
|
||||
import { COMMAND_LISTENER_VALUE_CHANGE, getValueChangedEffectedRange, InsertSheetCommand, RemoveSheetCommand, SetGridlinesColorCommand, SetTabColorMutation, SetWorksheetActiveOperation, SetWorksheetHideMutation, SetWorksheetNameCommand, SetWorksheetOrderMutation, SheetsFreezeSyncController, ToggleGridlinesCommand } from '@univerjs/sheets';
|
||||
import { FDefinedNameBuilder } from './f-defined-name';
|
||||
import { FPermission } from './f-permission';
|
||||
import { FWorkbook } from './f-workbook';
|
||||
@@ -161,6 +161,17 @@ export interface IFUniverSheetsMixin {
|
||||
* ```
|
||||
*/
|
||||
getActiveSheet(): Nullable<{ workbook: FWorkbook; worksheet: FWorksheet }>;
|
||||
|
||||
/**
|
||||
* Set whether to enable synchronize the frozen state to other users in real-time collaboration.
|
||||
* @param {boolean} enabled - Whether to enable freeze sync. Default is true.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Disable freeze sync
|
||||
* univerAPI.setFreezeSync(false);
|
||||
* ```
|
||||
*/
|
||||
setFreezeSync(enabled: boolean): void;
|
||||
}
|
||||
|
||||
export class FUniverSheetsMixin extends FUniver implements IFUniverSheetsMixin {
|
||||
@@ -632,6 +643,11 @@ export class FUniverSheetsMixin extends FUniver implements IFUniverSheetsMixin {
|
||||
return { workbook, worksheet };
|
||||
}
|
||||
|
||||
override setFreezeSync(enabled: boolean): void {
|
||||
const controller = this._injector.get(SheetsFreezeSyncController);
|
||||
controller.setEnabled(enabled);
|
||||
}
|
||||
|
||||
private _fireActiveSheetChanged(workbook: FWorkbook, newActiveSheet: FWorksheet): void {
|
||||
this.fireEvent(this.Event.ActiveSheetChanged, {
|
||||
workbook,
|
||||
|
||||
@@ -322,6 +322,7 @@ export { type IUniverSheetsConfig } from './controllers/config.schema';
|
||||
export { MAX_CELL_PER_SHEET_KEY } from './controllers/config/config';
|
||||
export { DefinedNameDataController } from './controllers/defined-name-data.controller';
|
||||
export { SCOPE_WORKBOOK_VALUE_DEFINED_NAME } from './controllers/defined-name-data.controller';
|
||||
export { SheetsFreezeSyncController } from './controllers/freeze-sync.controller';
|
||||
export { getAddMergeMutationRangeByType } from './controllers/merge-cell.controller';
|
||||
export { MERGE_CELL_INTERCEPTOR_CHECK, MergeCellController } from './controllers/merge-cell.controller';
|
||||
export { SheetPermissionCheckController } from './controllers/permission/sheet-permission-check.controller';
|
||||
|
||||
@@ -23,16 +23,15 @@ import { CalculateResultApplyController } from './controllers/calculate-result-a
|
||||
import { ONLY_REGISTER_FORMULA_RELATED_MUTATIONS_KEY } from './controllers/config';
|
||||
import { defaultPluginConfig, SHEETS_PLUGIN_CONFIG_KEY } from './controllers/config.schema';
|
||||
import { DefinedNameDataController } from './controllers/defined-name-data.controller';
|
||||
import { SheetsFreezeSyncController } from './controllers/freeze-sync.controller';
|
||||
import { MergeCellController } from './controllers/merge-cell.controller';
|
||||
import { NumberCellDisplayController } from './controllers/number-cell.controller';
|
||||
import { SheetPermissionCheckController } from './controllers/permission/sheet-permission-check.controller';
|
||||
import { SheetPermissionInitController } from './controllers/permission/sheet-permission-init.controller';
|
||||
import { SheetPermissionViewModelController } from './controllers/permission/sheet-permission-view-model.controller';
|
||||
|
||||
import { ZebraCrossingCacheController } from './controllers/zebar-crossing.controller';
|
||||
import { RangeProtectionRenderModel } from './model/range-protection-render.model';
|
||||
import { RangeProtectionRuleModel } from './model/range-protection-rule.model';
|
||||
|
||||
import { RangeProtectionCache } from './model/range-protection.cache';
|
||||
import { SheetRangeThemeModel } from './model/range-theme-model';
|
||||
import { BorderStyleManagerService } from './services/border-style-manager.service';
|
||||
@@ -105,6 +104,7 @@ export class UniverSheetsPlugin extends Plugin {
|
||||
[NumberCellDisplayController],
|
||||
[DefinedNameDataController],
|
||||
[ZebraCrossingCacheController],
|
||||
[SheetsFreezeSyncController],
|
||||
|
||||
// permission
|
||||
[WorksheetPermissionService],
|
||||
@@ -140,6 +140,7 @@ export class UniverSheetsPlugin extends Plugin {
|
||||
[RangeProtectionService],
|
||||
[IExclusiveRangeService],
|
||||
[SheetPermissionInitController],
|
||||
[SheetsFreezeSyncController],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user