@ai-matrx/office 0.8.44 → 0.8.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -2
- package/dist/collab-sheets-transform.cjs +12 -0
- package/dist/collab-sheets-transform.cjs.map +1 -1
- package/dist/collab-sheets-transform.js +12 -0
- package/dist/collab-sheets-transform.js.map +1 -1
- package/dist/docs.cjs +85 -24
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.d.cts +15 -1
- package/dist/docs.d.ts +15 -1
- package/dist/docs.js +65 -4
- package/dist/docs.js.map +1 -1
- package/dist/univer-collab.cjs +196 -15
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +68 -7
- package/dist/univer-collab.d.ts +68 -7
- package/dist/univer-collab.js +196 -15
- package/dist/univer-collab.js.map +1 -1
- package/package.json +6 -5
package/dist/univer-collab.d.cts
CHANGED
|
@@ -411,14 +411,18 @@ declare function undoStacksOf(service: unknown): {
|
|
|
411
411
|
/**
|
|
412
412
|
* §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped.
|
|
413
413
|
*
|
|
414
|
-
* `stack` says which side of each item applies
|
|
415
|
-
* `
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
414
|
+
* `stack` says which side of each item applies next: an undo-stack item's `undoMutations`, a redo-stack item's
|
|
415
|
+
* `redoMutations`. A stack applies top first, so each item's active side applies to the document as the items
|
|
416
|
+
* above it leave it: the top item meets the remote op as it is, and every item below meets it carried past the
|
|
417
|
+
* active sides of the items above (rebasing each item against the same op put a deeper item at offsets the items
|
|
418
|
+
* above had moved). The inactive side meets the op carried past its own active side; it is a fallback only: the
|
|
419
|
+
* room rewrites it from the real document whenever the item runs (`openDocsOtRoom`, walk 2 F1), because a tie at
|
|
420
|
+
* the edge of what the active side removes cannot say on which side of a collaborator's letters it belongs.
|
|
420
421
|
*/
|
|
421
422
|
declare function rebaseUndoStack(items: UndoItem$1[], remote: DocsOp, stack: "undo" | "redo"): number;
|
|
423
|
+
/** Univer 1.0.4's undo and redo command ids (the outermost command of every mutation a history step runs). */
|
|
424
|
+
declare const UNDO_COMMAND = "univer.command.undo";
|
|
425
|
+
declare const REDO_COMMAND = "univer.command.redo";
|
|
422
426
|
declare function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom;
|
|
423
427
|
|
|
424
428
|
interface CaretRange {
|
|
@@ -617,6 +621,11 @@ interface SheetsOtPort {
|
|
|
617
621
|
busy(): boolean;
|
|
618
622
|
/** Run `fn` once no local command is running (immediately when none is). */
|
|
619
623
|
whenIdle(fn: () => void): void;
|
|
624
|
+
/**
|
|
625
|
+
* True when this remote op must wait (and so must every op after it) until `whenIdle`: the port's cell editor is
|
|
626
|
+
* open on a cell the op touches. The held ops apply when it closes, and the person's commit is rebased over them.
|
|
627
|
+
*/
|
|
628
|
+
defers?(op: SheetMutation[]): boolean;
|
|
620
629
|
/** Apply one committed mutation to this seat's workbook; throws when the editor refused it. */
|
|
621
630
|
applyRemote(m: SheetMutation): void;
|
|
622
631
|
/** The workbook as the editor holds it now (with resources), or null when none is mounted. */
|
|
@@ -637,11 +646,18 @@ interface SheetsOtPort {
|
|
|
637
646
|
/** Ask for a save (the record's one coalesced save). */
|
|
638
647
|
markDirty(): void;
|
|
639
648
|
}
|
|
649
|
+
/**
|
|
650
|
+
* `resynced`: this seat's workbook disagreed with the room's (a peer's quiet hash, a save's hash or an ack) and the
|
|
651
|
+
* reload that healed it changed what the person sees. One notice per heal; a heal that changed nothing says nothing.
|
|
652
|
+
*/
|
|
640
653
|
type SheetsOtNotice = OpSessionNotice<SheetOp> | {
|
|
641
654
|
kind: "not_shared";
|
|
642
655
|
mutationId: string;
|
|
643
656
|
} | {
|
|
644
657
|
kind: "not_live";
|
|
658
|
+
} | {
|
|
659
|
+
kind: "resynced";
|
|
660
|
+
reason: string;
|
|
645
661
|
};
|
|
646
662
|
/**
|
|
647
663
|
* The adapter's transform: the C5a/C5b group transform, with `lost` widened by what y can no longer apply
|
|
@@ -782,6 +798,10 @@ interface SheetsWorksheetLike {
|
|
|
782
798
|
getMaxColumns?(): number;
|
|
783
799
|
getCellRaw(row: number, col: number): Obj | null | undefined;
|
|
784
800
|
getMergeData(): SheetRange[];
|
|
801
|
+
/** Univer's `Worksheet.getCellMatrix()` (every stored cell). */
|
|
802
|
+
getCellMatrix?(): {
|
|
803
|
+
forValue(fn: (row: number, col: number, cell: Obj | null | undefined) => unknown): void;
|
|
804
|
+
};
|
|
785
805
|
}
|
|
786
806
|
interface SheetsWorkbookLike {
|
|
787
807
|
getUnitId(): string;
|
|
@@ -821,10 +841,51 @@ interface UniverSheetsOtPortOptions {
|
|
|
821
841
|
* time on this seat. Without it a seat with a filter diverges from its peers on that write.
|
|
822
842
|
*/
|
|
823
843
|
filterRange?(unitId: string, subUnitId: string): SheetRange | null | undefined;
|
|
844
|
+
/**
|
|
845
|
+
* The cell this seat's cell editor is open on, or null when it is closed (`IEditorBridgeService`:
|
|
846
|
+
* `isVisible().visible` and `getEditLocation()`). Univer rewrites an open editor's text whenever any write lands on
|
|
847
|
+
* its cell (`EditorDataSyncController` → `refreshEditCellState` → the editor's `ReplaceSnapshotCommand`, caret back
|
|
848
|
+
* to 0), so a peer's value landing mid-typing spliced into the draft and Enter committed the mix (the attack's
|
|
849
|
+
* "$1,234.50" vs "$7" → 507). While the editor is open, a remote op that touches its cell or its sheet is held,
|
|
850
|
+
* and so is everything after it: the person's draft and the cell it is committed against stay as they saw them,
|
|
851
|
+
* and their commit is rebased over the held ops when the editor closes (the later commit wins whole).
|
|
852
|
+
*/
|
|
853
|
+
cellEditor?(): EditedCell | null;
|
|
824
854
|
/** Replace the workbook's whole content, keeping its unit id. */
|
|
825
855
|
load(snapshot: unknown): void;
|
|
826
856
|
markDirty(): void;
|
|
827
857
|
}
|
|
858
|
+
/** The cell an open cell editor is on. */
|
|
859
|
+
interface EditedCell {
|
|
860
|
+
sheetId: string;
|
|
861
|
+
row: number;
|
|
862
|
+
col: number;
|
|
863
|
+
}
|
|
864
|
+
/** What the port reads of Univer's `SheetsFilterService` (sheets-filter). */
|
|
865
|
+
interface FilterServiceLike {
|
|
866
|
+
getFilterModel(unitId: string, subUnitId: string): {
|
|
867
|
+
getRange(): SheetRange | null | undefined;
|
|
868
|
+
} | null | undefined;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* The port's `filterRange` over Univer's filter service: the range as the filter stores it, `rangeType` included.
|
|
872
|
+
* Every host lends this one (the editor, the fold, the fuzz seats): a host that dropped `rangeType` restored a peer's
|
|
873
|
+
* growth without it, and that seat's filter saved differently from the others (hash_mismatch, live attack rev 90).
|
|
874
|
+
*/
|
|
875
|
+
declare function filterServiceRange(service: () => FilterServiceLike | null | undefined): (unitId: string, subUnitId: string) => SheetRange | null;
|
|
876
|
+
/** What the port reads of Univer's `IEditorBridgeService` (sheets-ui). */
|
|
877
|
+
interface EditorBridgeLike {
|
|
878
|
+
isVisible(): {
|
|
879
|
+
visible: boolean;
|
|
880
|
+
};
|
|
881
|
+
getEditLocation(): {
|
|
882
|
+
sheetId: string;
|
|
883
|
+
row: number;
|
|
884
|
+
column: number;
|
|
885
|
+
} | null | undefined;
|
|
886
|
+
}
|
|
887
|
+
/** The port's `cellEditor` over Univer's editor bridge: the cell the cell editor is open on, or null. */
|
|
888
|
+
declare function editorBridgeCell(bridge: EditorBridgeLike): () => EditedCell | null;
|
|
828
889
|
/** One selection as `SheetsSelectionsService` holds it (range, primary cell, style). */
|
|
829
890
|
interface SheetSelection {
|
|
830
891
|
range: SheetRange & {
|
|
@@ -933,4 +994,4 @@ declare function startWorkbookOtRoom(port: SheetsOtPort & {
|
|
|
933
994
|
dispose?: () => void;
|
|
934
995
|
}, o: WorkbookOtRoomOptions): Promise<WorkbookOtRoomHandle>;
|
|
935
996
|
|
|
936
|
-
export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, encodeSheetOp, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
|
|
997
|
+
export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
|
package/dist/univer-collab.d.ts
CHANGED
|
@@ -411,14 +411,18 @@ declare function undoStacksOf(service: unknown): {
|
|
|
411
411
|
/**
|
|
412
412
|
* §6.9: rebase one stack over a remote op; items that cannot follow are dropped. Returns how many were dropped.
|
|
413
413
|
*
|
|
414
|
-
* `stack` says which side of each item applies
|
|
415
|
-
* `
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
414
|
+
* `stack` says which side of each item applies next: an undo-stack item's `undoMutations`, a redo-stack item's
|
|
415
|
+
* `redoMutations`. A stack applies top first, so each item's active side applies to the document as the items
|
|
416
|
+
* above it leave it: the top item meets the remote op as it is, and every item below meets it carried past the
|
|
417
|
+
* active sides of the items above (rebasing each item against the same op put a deeper item at offsets the items
|
|
418
|
+
* above had moved). The inactive side meets the op carried past its own active side; it is a fallback only: the
|
|
419
|
+
* room rewrites it from the real document whenever the item runs (`openDocsOtRoom`, walk 2 F1), because a tie at
|
|
420
|
+
* the edge of what the active side removes cannot say on which side of a collaborator's letters it belongs.
|
|
420
421
|
*/
|
|
421
422
|
declare function rebaseUndoStack(items: UndoItem$1[], remote: DocsOp, stack: "undo" | "redo"): number;
|
|
423
|
+
/** Univer 1.0.4's undo and redo command ids (the outermost command of every mutation a history step runs). */
|
|
424
|
+
declare const UNDO_COMMAND = "univer.command.undo";
|
|
425
|
+
declare const REDO_COMMAND = "univer.command.redo";
|
|
422
426
|
declare function openDocsOtRoom(o: OpenDocsOtRoomOptions): DocsOtRoom;
|
|
423
427
|
|
|
424
428
|
interface CaretRange {
|
|
@@ -617,6 +621,11 @@ interface SheetsOtPort {
|
|
|
617
621
|
busy(): boolean;
|
|
618
622
|
/** Run `fn` once no local command is running (immediately when none is). */
|
|
619
623
|
whenIdle(fn: () => void): void;
|
|
624
|
+
/**
|
|
625
|
+
* True when this remote op must wait (and so must every op after it) until `whenIdle`: the port's cell editor is
|
|
626
|
+
* open on a cell the op touches. The held ops apply when it closes, and the person's commit is rebased over them.
|
|
627
|
+
*/
|
|
628
|
+
defers?(op: SheetMutation[]): boolean;
|
|
620
629
|
/** Apply one committed mutation to this seat's workbook; throws when the editor refused it. */
|
|
621
630
|
applyRemote(m: SheetMutation): void;
|
|
622
631
|
/** The workbook as the editor holds it now (with resources), or null when none is mounted. */
|
|
@@ -637,11 +646,18 @@ interface SheetsOtPort {
|
|
|
637
646
|
/** Ask for a save (the record's one coalesced save). */
|
|
638
647
|
markDirty(): void;
|
|
639
648
|
}
|
|
649
|
+
/**
|
|
650
|
+
* `resynced`: this seat's workbook disagreed with the room's (a peer's quiet hash, a save's hash or an ack) and the
|
|
651
|
+
* reload that healed it changed what the person sees. One notice per heal; a heal that changed nothing says nothing.
|
|
652
|
+
*/
|
|
640
653
|
type SheetsOtNotice = OpSessionNotice<SheetOp> | {
|
|
641
654
|
kind: "not_shared";
|
|
642
655
|
mutationId: string;
|
|
643
656
|
} | {
|
|
644
657
|
kind: "not_live";
|
|
658
|
+
} | {
|
|
659
|
+
kind: "resynced";
|
|
660
|
+
reason: string;
|
|
645
661
|
};
|
|
646
662
|
/**
|
|
647
663
|
* The adapter's transform: the C5a/C5b group transform, with `lost` widened by what y can no longer apply
|
|
@@ -782,6 +798,10 @@ interface SheetsWorksheetLike {
|
|
|
782
798
|
getMaxColumns?(): number;
|
|
783
799
|
getCellRaw(row: number, col: number): Obj | null | undefined;
|
|
784
800
|
getMergeData(): SheetRange[];
|
|
801
|
+
/** Univer's `Worksheet.getCellMatrix()` (every stored cell). */
|
|
802
|
+
getCellMatrix?(): {
|
|
803
|
+
forValue(fn: (row: number, col: number, cell: Obj | null | undefined) => unknown): void;
|
|
804
|
+
};
|
|
785
805
|
}
|
|
786
806
|
interface SheetsWorkbookLike {
|
|
787
807
|
getUnitId(): string;
|
|
@@ -821,10 +841,51 @@ interface UniverSheetsOtPortOptions {
|
|
|
821
841
|
* time on this seat. Without it a seat with a filter diverges from its peers on that write.
|
|
822
842
|
*/
|
|
823
843
|
filterRange?(unitId: string, subUnitId: string): SheetRange | null | undefined;
|
|
844
|
+
/**
|
|
845
|
+
* The cell this seat's cell editor is open on, or null when it is closed (`IEditorBridgeService`:
|
|
846
|
+
* `isVisible().visible` and `getEditLocation()`). Univer rewrites an open editor's text whenever any write lands on
|
|
847
|
+
* its cell (`EditorDataSyncController` → `refreshEditCellState` → the editor's `ReplaceSnapshotCommand`, caret back
|
|
848
|
+
* to 0), so a peer's value landing mid-typing spliced into the draft and Enter committed the mix (the attack's
|
|
849
|
+
* "$1,234.50" vs "$7" → 507). While the editor is open, a remote op that touches its cell or its sheet is held,
|
|
850
|
+
* and so is everything after it: the person's draft and the cell it is committed against stay as they saw them,
|
|
851
|
+
* and their commit is rebased over the held ops when the editor closes (the later commit wins whole).
|
|
852
|
+
*/
|
|
853
|
+
cellEditor?(): EditedCell | null;
|
|
824
854
|
/** Replace the workbook's whole content, keeping its unit id. */
|
|
825
855
|
load(snapshot: unknown): void;
|
|
826
856
|
markDirty(): void;
|
|
827
857
|
}
|
|
858
|
+
/** The cell an open cell editor is on. */
|
|
859
|
+
interface EditedCell {
|
|
860
|
+
sheetId: string;
|
|
861
|
+
row: number;
|
|
862
|
+
col: number;
|
|
863
|
+
}
|
|
864
|
+
/** What the port reads of Univer's `SheetsFilterService` (sheets-filter). */
|
|
865
|
+
interface FilterServiceLike {
|
|
866
|
+
getFilterModel(unitId: string, subUnitId: string): {
|
|
867
|
+
getRange(): SheetRange | null | undefined;
|
|
868
|
+
} | null | undefined;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* The port's `filterRange` over Univer's filter service: the range as the filter stores it, `rangeType` included.
|
|
872
|
+
* Every host lends this one (the editor, the fold, the fuzz seats): a host that dropped `rangeType` restored a peer's
|
|
873
|
+
* growth without it, and that seat's filter saved differently from the others (hash_mismatch, live attack rev 90).
|
|
874
|
+
*/
|
|
875
|
+
declare function filterServiceRange(service: () => FilterServiceLike | null | undefined): (unitId: string, subUnitId: string) => SheetRange | null;
|
|
876
|
+
/** What the port reads of Univer's `IEditorBridgeService` (sheets-ui). */
|
|
877
|
+
interface EditorBridgeLike {
|
|
878
|
+
isVisible(): {
|
|
879
|
+
visible: boolean;
|
|
880
|
+
};
|
|
881
|
+
getEditLocation(): {
|
|
882
|
+
sheetId: string;
|
|
883
|
+
row: number;
|
|
884
|
+
column: number;
|
|
885
|
+
} | null | undefined;
|
|
886
|
+
}
|
|
887
|
+
/** The port's `cellEditor` over Univer's editor bridge: the cell the cell editor is open on, or null. */
|
|
888
|
+
declare function editorBridgeCell(bridge: EditorBridgeLike): () => EditedCell | null;
|
|
828
889
|
/** One selection as `SheetsSelectionsService` holds it (range, primary cell, style). */
|
|
829
890
|
interface SheetSelection {
|
|
830
891
|
range: SheetRange & {
|
|
@@ -933,4 +994,4 @@ declare function startWorkbookOtRoom(port: SheetsOtPort & {
|
|
|
933
994
|
dispose?: () => void;
|
|
934
995
|
}, o: WorkbookOtRoomOptions): Promise<WorkbookOtRoomHandle>;
|
|
935
996
|
|
|
936
|
-
export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, encodeSheetOp, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
|
|
997
|
+
export { COLLAB_COVERED_KEY, type CollabBase, type CollabMutationInfo, type CollabProviderLike, type CommandServiceLike, DOCS_COLLAB_PROTO, DOCS_TRANSFORM_VERSION, DOC_LOCAL_KEYS, type DocsLocalMutation, type DocsLost, type DocsOp, type DocsOtNotice, type DocsOtPort, type DocsOtRoom, type DocsTransformResult, type DocumentOtFactoryOptions, type DocumentRestoreDeps, type DocumentRestoreResult, type EditedCell, type EditorBridgeLike, type FilterServiceLike, type OpenDocsOtRoomOptions, type OpenSheetsOtRoomOptions, type OtRoomsKnob, REDO_COMMAND, RICH_TEXT_EDITING, SENDER_VIEW_PARAMS, SHEETS_COLLAB_PROTO, SHEETS_EDIT_GROUP, SHEETS_READABLE_PROTOS, SHEET_ROOM_EDITOR_PRESETS, SHEET_ROOM_PLUGIN_PACKAGES, type SheetOp, type SheetSelection, type SheetsCommandService, type SheetsLocalEvent, type SheetsLocalGroup, type SheetsNotShared, type SheetsOtAdapter, type SheetsOtAdapterHooks, type SheetsOtNotice, type SheetsOtPort, type SheetsOtRoom, type SheetsWorkbookLike, type SheetsWorksheetLike, UNDO_COMMAND, type UniverSheetsOtPortOptions, WorkbookCollabSession, type WorkbookCollabSessionOptions, type WorkbookOtRoomHandle, type WorkbookOtRoomOptions, type WorkbookOtRoomsKnob, applyDocsOp, asLoadedDocsSnapshot, canonicalDocsSnapshot, canonicalDocsString, canonicalKeys, canonicalSheet, canonicalSheetString, composeDocsOps, createSheetsOtAdapter, decodeSheetOp, docsStateHash, documentOtFactory, documentUsesOrderedRoom, dropEmptyStyleRetains, editorBridgeCell, encodeSheetOp, filterServiceRange, invertDocsOp, isCellEditorScratch, isNoopDocsOp, moveSelectionsThrough, normalizeDocsOp, offlineTextOfGroups, openDocsOtRoom, openSheetsOtRoom, rebaseSheetUndoStack, rebaseUndoStack, restoreDocumentSnapshot, sheetsStateHash, stampCovered, stampDeterministicIds, startWorkbookOtRoom, stripSenderView, takeCovered, transformDocsOp, transformSheetOp, transformTextX, undoStacksOf, univerSheetsOtPort, workbookUsesOrderedRoom };
|
package/dist/univer-collab.js
CHANGED
|
@@ -1165,26 +1165,77 @@ function rebaseUndoStack(items, remote, stack) {
|
|
|
1165
1165
|
const first = stack === "undo" ? "undoMutations" : "redoMutations";
|
|
1166
1166
|
const second = stack === "undo" ? "redoMutations" : "undoMutations";
|
|
1167
1167
|
let dropped = 0;
|
|
1168
|
-
|
|
1168
|
+
let R = remote;
|
|
1169
|
+
for (let i = items.length - 1; i >= 0 && !isNoopDocsOp(R); i--) {
|
|
1169
1170
|
const item = items[i];
|
|
1170
1171
|
try {
|
|
1171
|
-
const a = threadThrough(item[first],
|
|
1172
|
+
const a = threadThrough(item[first], R);
|
|
1172
1173
|
const b = threadThrough(item[second], a.after);
|
|
1173
1174
|
if (a.next) item[first] = a.next;
|
|
1174
1175
|
if (b.next) item[second] = b.next;
|
|
1176
|
+
R = a.after;
|
|
1175
1177
|
} catch {
|
|
1176
1178
|
items.splice(i, 1);
|
|
1177
1179
|
dropped++;
|
|
1180
|
+
R = carryPast(item[first], R);
|
|
1178
1181
|
}
|
|
1179
1182
|
}
|
|
1180
1183
|
return dropped;
|
|
1181
1184
|
}
|
|
1185
|
+
function carryPast(list, remote) {
|
|
1186
|
+
let R = remote;
|
|
1187
|
+
for (const m of list ?? []) {
|
|
1188
|
+
if (m.id !== RICH_TEXT_EDITING || isNoopDocsOp(R)) continue;
|
|
1189
|
+
const own = m.params.actions;
|
|
1190
|
+
if (touchesPageSetup(own) && touchesPageSetup(R)) continue;
|
|
1191
|
+
R = transformDocsOp(R, own, "right").op;
|
|
1192
|
+
}
|
|
1193
|
+
return R;
|
|
1194
|
+
}
|
|
1195
|
+
var UNDO_COMMAND = "univer.command.undo";
|
|
1196
|
+
var REDO_COMMAND = "univer.command.redo";
|
|
1182
1197
|
function openDocsOtRoom(o) {
|
|
1183
1198
|
const { port } = o;
|
|
1184
1199
|
let session = null;
|
|
1185
1200
|
let composing = false;
|
|
1186
1201
|
let queue = [];
|
|
1187
1202
|
const drainWaiters = [];
|
|
1203
|
+
let replay = null;
|
|
1204
|
+
const noteHistoryStep = (m, inverse) => {
|
|
1205
|
+
const side = m.cmd === UNDO_COMMAND ? "undo" : m.cmd === REDO_COMMAND ? "redo" : null;
|
|
1206
|
+
if (!side) {
|
|
1207
|
+
replay = null;
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
for (const t of port.undoTargets()) {
|
|
1211
|
+
const stacks = undoStacksOf(t.service);
|
|
1212
|
+
const stack = stacks ? (side === "undo" ? stacks.undo : stacks.redo).get(t.unitId) : void 0;
|
|
1213
|
+
const item = stack?.[stack.length - 1];
|
|
1214
|
+
const list = item ? side === "undo" ? item.undoMutations : item.redoMutations : void 0;
|
|
1215
|
+
const k = list ? list.findIndex((x) => x.params === m.params) : -1;
|
|
1216
|
+
if (!item || !list || k < 0) continue;
|
|
1217
|
+
if (k === 0 || !replay || replay.item !== item || replay.side !== side) {
|
|
1218
|
+
const other = (side === "undo" ? item.redoMutations : item.undoMutations)?.[0]?.params ?? {};
|
|
1219
|
+
const { textRanges: _t, layoutState: _l, actions: _a, ...template } = other;
|
|
1220
|
+
replay = { item, side, inverses: [], template };
|
|
1221
|
+
}
|
|
1222
|
+
if (inverse === void 0 || list.some((x) => x.id !== RICH_TEXT_EDITING)) {
|
|
1223
|
+
replay = null;
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
replay.inverses.unshift(inverse);
|
|
1227
|
+
if (k === list.length - 1) {
|
|
1228
|
+
const rewritten = replay.inverses.filter((op) => !isNoopDocsOp(op)).map((op) => ({ id: RICH_TEXT_EDITING, params: { ...replay.template, segmentId: m.params?.segmentId ?? "", actions: op } }));
|
|
1229
|
+
if (rewritten.length) {
|
|
1230
|
+
if (side === "undo") item.redoMutations = rewritten;
|
|
1231
|
+
else item.undoMutations = rewritten;
|
|
1232
|
+
}
|
|
1233
|
+
replay = null;
|
|
1234
|
+
}
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
replay = null;
|
|
1238
|
+
};
|
|
1188
1239
|
const notice = (n) => {
|
|
1189
1240
|
try {
|
|
1190
1241
|
o.onNotice?.(n);
|
|
@@ -1282,7 +1333,10 @@ function openDocsOtRoom(o) {
|
|
|
1282
1333
|
}
|
|
1283
1334
|
const p = m.params ?? {};
|
|
1284
1335
|
const applied = p.actions ?? null;
|
|
1285
|
-
if (isNoopDocsOp(applied))
|
|
1336
|
+
if (isNoopDocsOp(applied)) {
|
|
1337
|
+
noteHistoryStep(m, null);
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1286
1340
|
let op = normalizeDocsOp(structuredClone(applied));
|
|
1287
1341
|
let inverse;
|
|
1288
1342
|
try {
|
|
@@ -1290,6 +1344,7 @@ function openDocsOtRoom(o) {
|
|
|
1290
1344
|
} catch {
|
|
1291
1345
|
inverse = void 0;
|
|
1292
1346
|
}
|
|
1347
|
+
noteHistoryStep(m, inverse === void 0 ? void 0 : normalizeDocsOp(inverse));
|
|
1293
1348
|
if (queue.length) {
|
|
1294
1349
|
inverse = void 0;
|
|
1295
1350
|
const next = [];
|
|
@@ -2781,6 +2836,18 @@ function transformCell(X, Y4, side) {
|
|
|
2781
2836
|
if (styleKeys(xs).length !== styleKeys(kept ?? {}).length) xLost = true;
|
|
2782
2837
|
}
|
|
2783
2838
|
}
|
|
2839
|
+
if (hasContent(X) && hasContent(Y4)) {
|
|
2840
|
+
const has = (s) => !!s && typeof s === "object" && "n" in s;
|
|
2841
|
+
const outS = out.s;
|
|
2842
|
+
if (side === "left" && !has(X.s) && has(Y4.s) && X.s !== null) {
|
|
2843
|
+
out.s = { ...outS && typeof outS === "object" ? outS : {}, n: null };
|
|
2844
|
+
} else if (side === "right" && outS && typeof outS === "object" && "n" in outS) {
|
|
2845
|
+
const rest = withoutStyleKeys(outS, /* @__PURE__ */ new Set(["n"]));
|
|
2846
|
+
if (rest) out.s = rest;
|
|
2847
|
+
else delete out.s;
|
|
2848
|
+
xLost = true;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2784
2851
|
return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };
|
|
2785
2852
|
}
|
|
2786
2853
|
function transformCellsOverCells(x, y, side) {
|
|
@@ -3941,7 +4008,7 @@ function createSheetsOtAdapter(port, hooks = {}) {
|
|
|
3941
4008
|
decode: decodeSheetOp,
|
|
3942
4009
|
apply(op) {
|
|
3943
4010
|
if (isNoopSheetOp(op)) return true;
|
|
3944
|
-
if (port.busy() || queue.length) {
|
|
4011
|
+
if (port.busy() || queue.length || port.defers?.(op)) {
|
|
3945
4012
|
queue.push(op);
|
|
3946
4013
|
if (!draining) {
|
|
3947
4014
|
draining = true;
|
|
@@ -3974,9 +4041,9 @@ function createSheetsOtAdapter(port, hooks = {}) {
|
|
|
3974
4041
|
async hash() {
|
|
3975
4042
|
if (port.busy() || queue.length) {
|
|
3976
4043
|
await new Promise((resolve) => {
|
|
3977
|
-
const done = setTimeout(resolve, 5e3);
|
|
4044
|
+
const done = queue.length ? null : setTimeout(resolve, 5e3);
|
|
3978
4045
|
port.whenIdle(() => {
|
|
3979
|
-
clearTimeout(done);
|
|
4046
|
+
if (done) clearTimeout(done);
|
|
3980
4047
|
setTimeout(resolve, 0);
|
|
3981
4048
|
});
|
|
3982
4049
|
});
|
|
@@ -4006,7 +4073,6 @@ function createSheetsOtAdapter(port, hooks = {}) {
|
|
|
4006
4073
|
function openSheetsOtRoom(o) {
|
|
4007
4074
|
const { port } = o;
|
|
4008
4075
|
let session = null;
|
|
4009
|
-
const adapter = createSheetsOtAdapter(port);
|
|
4010
4076
|
const notice = (n) => {
|
|
4011
4077
|
try {
|
|
4012
4078
|
o.onNotice?.(n);
|
|
@@ -4014,6 +4080,29 @@ function openSheetsOtRoom(o) {
|
|
|
4014
4080
|
console.warn("[sheets-ot] notice handler failed", err);
|
|
4015
4081
|
}
|
|
4016
4082
|
};
|
|
4083
|
+
const adapter = createSheetsOtAdapter(port);
|
|
4084
|
+
let healing = null;
|
|
4085
|
+
const HEALS = /* @__PURE__ */ new Set(["hash_mismatch", "save_hash_mismatch", "ack_mismatch"]);
|
|
4086
|
+
const screen = () => {
|
|
4087
|
+
try {
|
|
4088
|
+
const s = port.snapshot();
|
|
4089
|
+
return s ? canonicalSheetString(s) : null;
|
|
4090
|
+
} catch {
|
|
4091
|
+
return null;
|
|
4092
|
+
}
|
|
4093
|
+
};
|
|
4094
|
+
const onIncident = (i) => {
|
|
4095
|
+
if (HEALS.has(i.kind) && !healing) healing = { reason: i.kind, before: screen() };
|
|
4096
|
+
o.onIncident?.(i);
|
|
4097
|
+
};
|
|
4098
|
+
const onStatus = (st) => {
|
|
4099
|
+
if (st === "live" && healing) {
|
|
4100
|
+
const h = healing;
|
|
4101
|
+
healing = null;
|
|
4102
|
+
if (h.before !== null && screen() !== h.before) notice({ kind: "resynced", reason: h.reason });
|
|
4103
|
+
} else if (st === "read_only" || st === "closed") healing = null;
|
|
4104
|
+
o.onStatus?.(st);
|
|
4105
|
+
};
|
|
4017
4106
|
const onLocal = (e) => {
|
|
4018
4107
|
if (!session) return;
|
|
4019
4108
|
if (e.kind === "not_shared") {
|
|
@@ -4054,8 +4143,8 @@ function openSheetsOtRoom(o) {
|
|
|
4054
4143
|
clientId: o.clientId,
|
|
4055
4144
|
...o.presence ? { presence: o.presence } : {},
|
|
4056
4145
|
onNotice: (n) => notice(n),
|
|
4057
|
-
|
|
4058
|
-
|
|
4146
|
+
onIncident,
|
|
4147
|
+
onStatus,
|
|
4059
4148
|
...o.offline ? { offline: o.offline } : {},
|
|
4060
4149
|
...o.onOffline ? { onOffline: o.onOffline } : {}
|
|
4061
4150
|
});
|
|
@@ -4148,6 +4237,23 @@ function releaseUnitPluginState(cs, unitId, saved) {
|
|
|
4148
4237
|
}
|
|
4149
4238
|
|
|
4150
4239
|
// src/univer/collab/sheets-ot/univer-port.ts
|
|
4240
|
+
function filterServiceRange(service) {
|
|
4241
|
+
return (unitId, subUnitId) => {
|
|
4242
|
+
try {
|
|
4243
|
+
const r = service()?.getFilterModel(unitId, subUnitId)?.getRange();
|
|
4244
|
+
return r ? { startRow: r.startRow, endRow: r.endRow, startColumn: r.startColumn, endColumn: r.endColumn, ...r.rangeType !== void 0 ? { rangeType: r.rangeType } : {} } : null;
|
|
4245
|
+
} catch {
|
|
4246
|
+
return null;
|
|
4247
|
+
}
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
function editorBridgeCell(bridge) {
|
|
4251
|
+
return () => {
|
|
4252
|
+
if (!bridge.isVisible()?.visible) return null;
|
|
4253
|
+
const at = bridge.getEditLocation();
|
|
4254
|
+
return at ? { sheetId: at.sheetId, row: at.row, col: at.column } : null;
|
|
4255
|
+
};
|
|
4256
|
+
}
|
|
4151
4257
|
var COMMAND = 0;
|
|
4152
4258
|
var MUTATION = 2;
|
|
4153
4259
|
var VALUES = "sheet.mutation.set-range-values";
|
|
@@ -4155,6 +4261,7 @@ var ADD_MERGE = "sheet.mutation.add-worksheet-merge";
|
|
|
4155
4261
|
var REMOVE_MERGE = "sheet.mutation.remove-worksheet-merge";
|
|
4156
4262
|
var SHEET_NAME = "sheet.mutation.set-worksheet-name";
|
|
4157
4263
|
var INSERT_SHEET = "sheet.mutation.insert-sheet";
|
|
4264
|
+
var REMOVE_SHEET2 = "sheet.mutation.remove-sheet";
|
|
4158
4265
|
var FILTER_RANGE = "sheet.mutation.set-filter-range";
|
|
4159
4266
|
var RESHAPE = /* @__PURE__ */ new Set(["sheet.mutation.set-worksheet-row-count", "sheet.mutation.set-worksheet-column-count", "sheet.mutation.remove-sheet", INSERT_SHEET]);
|
|
4160
4267
|
var UNDO = "univer.command.undo";
|
|
@@ -4174,6 +4281,18 @@ function univerSheetsOtPort(o) {
|
|
|
4174
4281
|
const tracker = { stack: [], settle: () => settle() };
|
|
4175
4282
|
let group = null;
|
|
4176
4283
|
let applying = false;
|
|
4284
|
+
let editorHold = false;
|
|
4285
|
+
const edited = () => {
|
|
4286
|
+
try {
|
|
4287
|
+
return o.cellEditor?.() ?? null;
|
|
4288
|
+
} catch {
|
|
4289
|
+
return null;
|
|
4290
|
+
}
|
|
4291
|
+
};
|
|
4292
|
+
const holding = () => {
|
|
4293
|
+
if (editorHold && !edited()) editorHold = false;
|
|
4294
|
+
return editorHold;
|
|
4295
|
+
};
|
|
4177
4296
|
const unitId = () => o.workbook()?.getUnitId() ?? null;
|
|
4178
4297
|
const mine = (params) => {
|
|
4179
4298
|
const u = unitId();
|
|
@@ -4202,7 +4321,7 @@ function univerSheetsOtPort(o) {
|
|
|
4202
4321
|
if (!u || !o.filterRange) return null;
|
|
4203
4322
|
try {
|
|
4204
4323
|
const r = o.filterRange(u, sheet);
|
|
4205
|
-
return r ? { startRow: r.startRow, endRow: r.endRow, startColumn: r.startColumn, endColumn: r.endColumn } : null;
|
|
4324
|
+
return r ? { startRow: r.startRow, endRow: r.endRow, startColumn: r.startColumn, endColumn: r.endColumn, ...r.rangeType !== void 0 ? { rangeType: r.rangeType } : {} } : null;
|
|
4206
4325
|
} catch {
|
|
4207
4326
|
return null;
|
|
4208
4327
|
}
|
|
@@ -4218,10 +4337,45 @@ function univerSheetsOtPort(o) {
|
|
|
4218
4337
|
}
|
|
4219
4338
|
}
|
|
4220
4339
|
};
|
|
4340
|
+
const sweepRemovedSheetRefs = (g) => {
|
|
4341
|
+
const removed = g.mutations.filter((m) => m.id === REMOVE_SHEET2).map((m) => String(m.params.subUnitId ?? ""));
|
|
4342
|
+
const wb = o.workbook();
|
|
4343
|
+
const u = unitId();
|
|
4344
|
+
if (!removed.length || !wb || !u) return;
|
|
4345
|
+
const refSheets = {};
|
|
4346
|
+
for (const [id, name] of Object.entries(g.sheets)) refSheets[name] = id;
|
|
4347
|
+
for (const gone of removed) {
|
|
4348
|
+
const name = g.sheets[gone];
|
|
4349
|
+
if (!name) continue;
|
|
4350
|
+
for (const ws of wb.getSheets()) {
|
|
4351
|
+
const sheet = ws.getSheetId();
|
|
4352
|
+
const cells = {};
|
|
4353
|
+
ws.getCellMatrix?.().forValue((r, c, cell) => {
|
|
4354
|
+
const f = cell?.f;
|
|
4355
|
+
if (typeof f !== "string" || !f.includes(name)) return;
|
|
4356
|
+
const out = rewriteFormula(f, { ownSheet: sheet, refSheets }, { kind: "remove-sheet", sheet: gone });
|
|
4357
|
+
if (typeof out !== "string" && out.changed) (cells[r] ??= {})[c] = { f: out.text, si: null };
|
|
4358
|
+
});
|
|
4359
|
+
if (!Object.keys(cells).length) continue;
|
|
4360
|
+
applying = true;
|
|
4361
|
+
try {
|
|
4362
|
+
cs.syncExecuteCommand(VALUES, { unitId: u, subUnitId: sheet, cellValue: json(cells) });
|
|
4363
|
+
} finally {
|
|
4364
|
+
applying = false;
|
|
4365
|
+
}
|
|
4366
|
+
const done = {};
|
|
4367
|
+
for (const r of Object.keys(cells))
|
|
4368
|
+
for (const c of Object.keys(cells[r])) (done[r] ??= {})[c] = completeCellContent(cells[r][c], json(ws.getCellRaw(Number(r), Number(c)) ?? null));
|
|
4369
|
+
g.mutations.push({ id: VALUES, params: { subUnitId: sheet, cellValue: done } });
|
|
4370
|
+
g.inverses.push(void 0);
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
};
|
|
4221
4374
|
const flush = () => {
|
|
4222
4375
|
const g = group;
|
|
4223
4376
|
group = null;
|
|
4224
4377
|
if (!g) return;
|
|
4378
|
+
if (!g.notShared) sweepRemovedSheetRefs(g);
|
|
4225
4379
|
if (g.notShared) emit({ kind: "not_shared", mutationId: g.notShared, label: g.label });
|
|
4226
4380
|
else if (g.mutations.length) {
|
|
4227
4381
|
const mutations = annotateSheetOps(annotateFormulas(g.mutations, g.sheets, g.names), g.order);
|
|
@@ -4233,7 +4387,7 @@ function univerSheetsOtPort(o) {
|
|
|
4233
4387
|
};
|
|
4234
4388
|
function settle() {
|
|
4235
4389
|
if (tracker.stack.length === 0) flush();
|
|
4236
|
-
if (tracker.stack.length === 0 && !group) for (const fn of idle.splice(0)) fn();
|
|
4390
|
+
if (tracker.stack.length === 0 && !group && !holding()) for (const fn of idle.splice(0)) fn();
|
|
4237
4391
|
}
|
|
4238
4392
|
const before = cs.beforeCommandExecuted((info, options) => {
|
|
4239
4393
|
if (info.id === UNDO || info.id === REDO) for (const fn of [...undoWatchers]) fn();
|
|
@@ -4247,6 +4401,7 @@ function univerSheetsOtPort(o) {
|
|
|
4247
4401
|
const ws = o.workbook()?.getSheetBySheetId(String(p.subUnitId ?? ""));
|
|
4248
4402
|
if (!ws) return;
|
|
4249
4403
|
const record = { merges: json(ws.getMergeData() ?? []) };
|
|
4404
|
+
if (!group) record.lone = openGroup(null);
|
|
4250
4405
|
if (info.id === VALUES) {
|
|
4251
4406
|
record.cells = /* @__PURE__ */ new Map();
|
|
4252
4407
|
const cells = p.cellValue ?? {};
|
|
@@ -4283,6 +4438,7 @@ function univerSheetsOtPort(o) {
|
|
|
4283
4438
|
}
|
|
4284
4439
|
};
|
|
4285
4440
|
const after = cs.onCommandExecuted((info) => {
|
|
4441
|
+
if (editorHold && tracker.stack.length === 0 && !group && !edited()) settle();
|
|
4286
4442
|
if (info.type !== COMMAND) return;
|
|
4287
4443
|
const at = tracker.stack.lastIndexOf(info.id);
|
|
4288
4444
|
if (at >= 0) tracker.stack.splice(at, 1);
|
|
@@ -4364,7 +4520,7 @@ function univerSheetsOtPort(o) {
|
|
|
4364
4520
|
else {
|
|
4365
4521
|
inv = {};
|
|
4366
4522
|
if (CONTENT_KEYS.some((k) => k !== "t" && k in done)) Object.assign(inv, fullContent(p));
|
|
4367
|
-
if ("s" in done) inv.s = p?.s
|
|
4523
|
+
if ("s" in done) inv.s = inverseStyle(p?.s, done.s);
|
|
4368
4524
|
}
|
|
4369
4525
|
(invCells[r] ??= {})[c] = inv;
|
|
4370
4526
|
}
|
|
@@ -4402,7 +4558,7 @@ function univerSheetsOtPort(o) {
|
|
|
4402
4558
|
};
|
|
4403
4559
|
const collab = cs.onMutationExecutedForCollab((info, options) => {
|
|
4404
4560
|
if (applying || flagged(options) || !mine(info.params)) return;
|
|
4405
|
-
if (!group) group = openGroup(null);
|
|
4561
|
+
if (!group) group = pre.get(info.params)?.lone ?? openGroup(null);
|
|
4406
4562
|
const g = group;
|
|
4407
4563
|
if (!g.notShared) {
|
|
4408
4564
|
const r = capture(info);
|
|
@@ -4483,11 +4639,18 @@ function univerSheetsOtPort(o) {
|
|
|
4483
4639
|
listeners.add(listener);
|
|
4484
4640
|
return () => void listeners.delete(listener);
|
|
4485
4641
|
},
|
|
4486
|
-
busy: () => tracker.stack.length > 0 || group !== null,
|
|
4642
|
+
busy: () => tracker.stack.length > 0 || group !== null || holding(),
|
|
4643
|
+
defers(op) {
|
|
4644
|
+
if (holding()) return true;
|
|
4645
|
+
const at = edited();
|
|
4646
|
+
if (!at || !op.some((m) => touchesEditedCell(m, at))) return false;
|
|
4647
|
+
editorHold = true;
|
|
4648
|
+
return true;
|
|
4649
|
+
},
|
|
4487
4650
|
/** The outermost commands still running here (why the port is busy), for logs. */
|
|
4488
4651
|
running: () => [...tracker.stack, ...group && tracker.stack.length === 0 ? ["(group)"] : []],
|
|
4489
4652
|
whenIdle(fn) {
|
|
4490
|
-
if (tracker.stack.length === 0 && !group) fn();
|
|
4653
|
+
if (tracker.stack.length === 0 && !group && !holding()) fn();
|
|
4491
4654
|
else idle.push(fn);
|
|
4492
4655
|
},
|
|
4493
4656
|
applyRemote(m) {
|
|
@@ -4547,6 +4710,20 @@ function univerSheetsOtPort(o) {
|
|
|
4547
4710
|
}
|
|
4548
4711
|
};
|
|
4549
4712
|
}
|
|
4713
|
+
function inverseStyle(prev, wrote) {
|
|
4714
|
+
if (!prev || typeof prev !== "object") return null;
|
|
4715
|
+
if (!wrote || typeof wrote !== "object") return prev;
|
|
4716
|
+
const out = { ...prev };
|
|
4717
|
+
for (const k of Object.keys(wrote)) if (!(k in out)) out[k] = null;
|
|
4718
|
+
return out;
|
|
4719
|
+
}
|
|
4720
|
+
function touchesEditedCell(m, at) {
|
|
4721
|
+
const sheet = String(m.params.subUnitId ?? "");
|
|
4722
|
+
if (sheet !== at.sheetId) return false;
|
|
4723
|
+
if (m.id !== VALUES) return true;
|
|
4724
|
+
const row = m.params.cellValue?.[at.row];
|
|
4725
|
+
return !!row && Object.prototype.hasOwnProperty.call(row, at.col);
|
|
4726
|
+
}
|
|
4550
4727
|
function fullContent(cell) {
|
|
4551
4728
|
const out = {};
|
|
4552
4729
|
for (const k of CONTENT_KEYS) out[k] = cell && cell[k] !== void 0 ? cell[k] : null;
|
|
@@ -4857,6 +5034,7 @@ export {
|
|
|
4857
5034
|
DOCS_COLLAB_PROTO,
|
|
4858
5035
|
DOCS_TRANSFORM_VERSION,
|
|
4859
5036
|
DOC_LOCAL_KEYS,
|
|
5037
|
+
REDO_COMMAND,
|
|
4860
5038
|
RICH_TEXT_EDITING,
|
|
4861
5039
|
SENDER_VIEW_PARAMS,
|
|
4862
5040
|
SHEETS_COLLAB_PROTO,
|
|
@@ -4864,6 +5042,7 @@ export {
|
|
|
4864
5042
|
SHEETS_READABLE_PROTOS,
|
|
4865
5043
|
SHEET_ROOM_EDITOR_PRESETS,
|
|
4866
5044
|
SHEET_ROOM_PLUGIN_PACKAGES,
|
|
5045
|
+
UNDO_COMMAND,
|
|
4867
5046
|
WorkbookCollabSession,
|
|
4868
5047
|
applyDocsOp,
|
|
4869
5048
|
asLoadedDocsSnapshot,
|
|
@@ -4879,7 +5058,9 @@ export {
|
|
|
4879
5058
|
documentOtFactory,
|
|
4880
5059
|
documentUsesOrderedRoom,
|
|
4881
5060
|
dropEmptyStyleRetains,
|
|
5061
|
+
editorBridgeCell,
|
|
4882
5062
|
encodeSheetOp,
|
|
5063
|
+
filterServiceRange,
|
|
4883
5064
|
invertDocsOp,
|
|
4884
5065
|
isCellEditorScratch,
|
|
4885
5066
|
isNoopDocsOp,
|