@ai-matrx/office 0.8.19 → 0.8.21
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 +23 -0
- package/dist/collab-sheets-transform.cjs +354 -16
- package/dist/collab-sheets-transform.cjs.map +1 -1
- package/dist/collab-sheets-transform.d.cts +32 -4
- package/dist/collab-sheets-transform.d.ts +32 -4
- package/dist/collab-sheets-transform.js +354 -16
- package/dist/collab-sheets-transform.js.map +1 -1
- package/dist/univer-collab.cjs +420 -64
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +7 -1
- package/dist/univer-collab.d.ts +7 -1
- package/dist/univer-collab.js +424 -67
- package/dist/univer-collab.js.map +1 -1
- package/package.json +4 -4
package/dist/univer-collab.cjs
CHANGED
|
@@ -119,6 +119,7 @@ var WorkbookCollabSession = class {
|
|
|
119
119
|
muted = 0;
|
|
120
120
|
started = false;
|
|
121
121
|
disposed = false;
|
|
122
|
+
stopColor = null;
|
|
122
123
|
/** Room entries this seat holds in its content: applied from a peer, or made here. */
|
|
123
124
|
applied = /* @__PURE__ */ new Set();
|
|
124
125
|
/** Entries without an id (a peer on an older build) are applied once, by identity. */
|
|
@@ -140,12 +141,12 @@ var WorkbookCollabSession = class {
|
|
|
140
141
|
uid: this.options.uid,
|
|
141
142
|
clientId: this.options.clientId,
|
|
142
143
|
name: this.options.uid.slice(0, 8),
|
|
143
|
-
color: pickColor(this.options.uid),
|
|
144
144
|
sheetId: null,
|
|
145
145
|
row: null,
|
|
146
146
|
col: null,
|
|
147
147
|
ts: Date.now()
|
|
148
148
|
});
|
|
149
|
+
this.stopColor = (0, import_collab.claimCollaboratorColor)(this.awareness, { uid: this.options.uid, clientId: this.options.clientId });
|
|
149
150
|
this.provider = this.options.makeProvider({
|
|
150
151
|
workbookId: this.options.workbookId,
|
|
151
152
|
clientId: this.options.clientId,
|
|
@@ -206,6 +207,8 @@ var WorkbookCollabSession = class {
|
|
|
206
207
|
this.awareness.off("change", this.awarenessObserver);
|
|
207
208
|
this.awarenessObserver = null;
|
|
208
209
|
}
|
|
210
|
+
this.stopColor?.();
|
|
211
|
+
this.stopColor = null;
|
|
209
212
|
this.provider?.disconnect();
|
|
210
213
|
this.provider = null;
|
|
211
214
|
if (this.awareness) {
|
|
@@ -412,32 +415,6 @@ function stripSenderView(params) {
|
|
|
412
415
|
function isCellEditorScratch(info) {
|
|
413
416
|
return typeof info.id === "string" && info.id.startsWith("doc.mutation.");
|
|
414
417
|
}
|
|
415
|
-
var CURSOR_PALETTE = [
|
|
416
|
-
"#3b82f6",
|
|
417
|
-
// blue
|
|
418
|
-
"#10b981",
|
|
419
|
-
// emerald
|
|
420
|
-
"#f59e0b",
|
|
421
|
-
// amber
|
|
422
|
-
"#ef4444",
|
|
423
|
-
// red
|
|
424
|
-
"#8b5cf6",
|
|
425
|
-
// violet
|
|
426
|
-
"#06b6d4",
|
|
427
|
-
// cyan
|
|
428
|
-
"#ec4899",
|
|
429
|
-
// pink
|
|
430
|
-
"#84cc16"
|
|
431
|
-
// lime
|
|
432
|
-
];
|
|
433
|
-
function pickColor(uid) {
|
|
434
|
-
let h = 2166136261;
|
|
435
|
-
for (let i = 0; i < uid.length; i++) {
|
|
436
|
-
h ^= uid.charCodeAt(i);
|
|
437
|
-
h = Math.imul(h, 16777619);
|
|
438
|
-
}
|
|
439
|
-
return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? "#ec4899";
|
|
440
|
-
}
|
|
441
418
|
|
|
442
419
|
// src/univer/collab/docs-ot/transform.ts
|
|
443
420
|
var import_core = require("@univerjs/core");
|
|
@@ -1781,6 +1758,14 @@ var SHEET_MUTATIONS = {
|
|
|
1781
1758
|
"sheet.mutation.set-worksheet-row-auto-height": covered("size", "rowsAutoHeightInfo"),
|
|
1782
1759
|
"sheet.mutation.set-worksheet-col-width": covered("size", "ranges", "colWidth"),
|
|
1783
1760
|
"sheet.mutation.set-worksheet-name": covered("name", "name"),
|
|
1761
|
+
// ── covered (C5c) ────────────────────────────────────────────────────────────────────────────────
|
|
1762
|
+
"sheet.mutation.set.numfmt": covered("numfmt", "values", "refMap"),
|
|
1763
|
+
"sheet.mutation.remove.numfmt": covered("numfmt", "ranges"),
|
|
1764
|
+
"sheet.mutation.set-worksheet-row-count": covered("count", "rowCount"),
|
|
1765
|
+
"sheet.mutation.set-worksheet-column-count": covered("count", "columnCount"),
|
|
1766
|
+
"sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
|
|
1767
|
+
"sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
|
|
1768
|
+
"sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
|
|
1784
1769
|
// ── never travels ────────────────────────────────────────────────────────────────────────────────
|
|
1785
1770
|
"formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
|
|
1786
1771
|
"formula.mutation.set-trigger-formula-calculation-start": never(FORMULA_RESULT),
|
|
@@ -1815,12 +1800,7 @@ var SHEET_MUTATIONS = {
|
|
|
1815
1800
|
"thread-comment.mutation.delete-comment": never(UNIVER_COMMENTS),
|
|
1816
1801
|
// ── barriers: X (no transform yet, design §10) ───────────────────────────────────────────────────
|
|
1817
1802
|
"sheet.mutation.reorder-range": barrier("X", "sort: a permutation, not transformed yet"),
|
|
1818
|
-
"sheet.mutation.set-worksheet-row-count": barrier("X", "absolute row count; needs delta semantics"),
|
|
1819
|
-
"sheet.mutation.set-worksheet-column-count": barrier("X", "absolute column count; needs delta semantics"),
|
|
1820
|
-
"sheet.mutation.set-worksheet-order": barrier("X", "absolute sheet order; needs move semantics"),
|
|
1821
1803
|
"sheet.mutation.move-range": barrier("X", "cut-paste carries the sender's cell matrices"),
|
|
1822
|
-
"sheet.mutation.insert-sheet": barrier("X", "sheet add: not in C5a"),
|
|
1823
|
-
"sheet.mutation.remove-sheet": barrier("X", "sheet remove: not in C5a"),
|
|
1824
1804
|
"sheet.mutation.set-worksheet-hidden": barrier("X", "sheet-level setting: not in C5a"),
|
|
1825
1805
|
"sheet.mutation.set-tab-color": barrier("X", "sheet-level setting: not in C5a"),
|
|
1826
1806
|
"sheet.mutation.set-workbook-name": barrier("X", "workbook-level setting: not in C5a"),
|
|
@@ -1835,8 +1815,6 @@ var SHEET_MUTATIONS = {
|
|
|
1835
1815
|
"sheet.mutation.set-row-visible": barrier("X", "row visibility: not in C5a"),
|
|
1836
1816
|
"sheet.mutation.set-col-hidden": barrier("X", "column visibility: not in C5a"),
|
|
1837
1817
|
"sheet.mutation.set-col-visible": barrier("X", "column visibility: not in C5a"),
|
|
1838
|
-
"sheet.mutation.set.numfmt": barrier("X", "number formats by range: not in C5a"),
|
|
1839
|
-
"sheet.mutation.remove.numfmt": barrier("X", "number formats by range: not in C5a"),
|
|
1840
1818
|
"sheet.mutation.add-range-protection": barrier("X", "permissions: not in C5a"),
|
|
1841
1819
|
"sheet.mutation.set-range-protection": barrier("X", "permissions: not in C5a"),
|
|
1842
1820
|
"sheet.mutation.delete-range-protection": barrier("X", "permissions: not in C5a"),
|
|
@@ -2231,7 +2209,7 @@ function refSheetsFor(texts, sheets) {
|
|
|
2231
2209
|
}
|
|
2232
2210
|
|
|
2233
2211
|
// src/collab/sheets/transform/transform.ts
|
|
2234
|
-
var SHEET_TRANSFORMER_VERSION = "
|
|
2212
|
+
var SHEET_TRANSFORMER_VERSION = "c5c-1";
|
|
2235
2213
|
var ID = {
|
|
2236
2214
|
values: "sheet.mutation.set-range-values",
|
|
2237
2215
|
insertRow: "sheet.mutation.insert-row",
|
|
@@ -2248,7 +2226,14 @@ var ID = {
|
|
|
2248
2226
|
colWidth: "sheet.mutation.set-worksheet-col-width",
|
|
2249
2227
|
name: "sheet.mutation.set-worksheet-name",
|
|
2250
2228
|
setName: "formula.mutation.set-defined-name",
|
|
2251
|
-
removeName: "formula.mutation.remove-defined-name"
|
|
2229
|
+
removeName: "formula.mutation.remove-defined-name",
|
|
2230
|
+
setNumfmt: "sheet.mutation.set.numfmt",
|
|
2231
|
+
removeNumfmt: "sheet.mutation.remove.numfmt",
|
|
2232
|
+
rowCount: "sheet.mutation.set-worksheet-row-count",
|
|
2233
|
+
colCount: "sheet.mutation.set-worksheet-column-count",
|
|
2234
|
+
insertSheet: "sheet.mutation.insert-sheet",
|
|
2235
|
+
removeSheet: "sheet.mutation.remove-sheet",
|
|
2236
|
+
sheetOrder: "sheet.mutation.set-worksheet-order"
|
|
2252
2237
|
};
|
|
2253
2238
|
var PAIR_BARRIERS = {};
|
|
2254
2239
|
var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
|
|
@@ -2360,6 +2345,20 @@ function mergeThrough(s, m) {
|
|
|
2360
2345
|
}
|
|
2361
2346
|
return { range: m, fixup: false };
|
|
2362
2347
|
}
|
|
2348
|
+
function mergeFixupsOwed(m, mergesBefore) {
|
|
2349
|
+
const st = structuralOf(m);
|
|
2350
|
+
if (!st) return null;
|
|
2351
|
+
const remove = [];
|
|
2352
|
+
const add = [];
|
|
2353
|
+
for (const q of mergesBefore) {
|
|
2354
|
+
const t = mergeThrough(st, q);
|
|
2355
|
+
if (!t.fixup) continue;
|
|
2356
|
+
remove.push({ startRow: q.startRow, endRow: q.endRow, startColumn: q.startColumn, endColumn: q.endColumn, ...q.rangeType !== void 0 ? { rangeType: q.rangeType } : {} });
|
|
2357
|
+
if (t.range) add.push({ ...t.range });
|
|
2358
|
+
}
|
|
2359
|
+
return remove.length ? { remove, add } : null;
|
|
2360
|
+
}
|
|
2361
|
+
var isStructuralMutation = (m) => structuralOf(m) !== null;
|
|
2363
2362
|
function exactMergeRemovals(group, merges) {
|
|
2364
2363
|
const sim = new Map(Object.entries(merges).map(([k, v]) => [k, v.map((r) => ({ ...r }))]));
|
|
2365
2364
|
const out = [];
|
|
@@ -2406,8 +2405,24 @@ function cellsMutation(template, cells) {
|
|
|
2406
2405
|
function putCell(cells, r, c, v) {
|
|
2407
2406
|
(cells[r] ??= {})[c] = v;
|
|
2408
2407
|
}
|
|
2408
|
+
function cellsOverlap(a, b) {
|
|
2409
|
+
for (const r of Object.keys(a)) {
|
|
2410
|
+
const br = b[r];
|
|
2411
|
+
if (!br) continue;
|
|
2412
|
+
for (const c of Object.keys(a[r] ?? {})) if (c in br) return true;
|
|
2413
|
+
}
|
|
2414
|
+
return false;
|
|
2415
|
+
}
|
|
2409
2416
|
var isEmptyMatrix = (cells) => Object.values(cells).every((row) => Object.keys(row).length === 0);
|
|
2417
|
+
var cellBarrierCache = /* @__PURE__ */ new WeakMap();
|
|
2410
2418
|
function cellBarrier(m) {
|
|
2419
|
+
const hit = cellBarrierCache.get(m);
|
|
2420
|
+
if (hit !== void 0) return hit;
|
|
2421
|
+
const why = cellBarrierOf(m);
|
|
2422
|
+
cellBarrierCache.set(m, why);
|
|
2423
|
+
return why;
|
|
2424
|
+
}
|
|
2425
|
+
function cellBarrierOf(m) {
|
|
2411
2426
|
if (m.params.isOverrideStyle) return "set-range-values with isOverrideStyle (whole-style replace) is not covered";
|
|
2412
2427
|
let why = null;
|
|
2413
2428
|
forEachCell(cellsOf(m), (_r, _c, v) => {
|
|
@@ -2489,6 +2504,7 @@ function transformCell(X, Y4, side) {
|
|
|
2489
2504
|
function transformCellsOverCells(x, y, side) {
|
|
2490
2505
|
if (sheetOf(x) !== sheetOf(y)) return ok([x]);
|
|
2491
2506
|
const ycells = cellsOf(y);
|
|
2507
|
+
if (!cellsOverlap(cellsOf(x), ycells)) return ok([x]);
|
|
2492
2508
|
const xd = isDerived(x);
|
|
2493
2509
|
const yd = isDerived(y);
|
|
2494
2510
|
const eff = derivedSide(x, y, side);
|
|
@@ -2516,7 +2532,7 @@ function transformCellsOverCells(x, y, side) {
|
|
|
2516
2532
|
const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
|
|
2517
2533
|
return ok(op, lost, dropped);
|
|
2518
2534
|
}
|
|
2519
|
-
var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived"];
|
|
2535
|
+
var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived", "sheetIndex", "sheetsLeft"];
|
|
2520
2536
|
var isDerived = (m) => m.params.derived === true;
|
|
2521
2537
|
function derivedSide(x, y, side) {
|
|
2522
2538
|
const xd = isDerived(x);
|
|
@@ -2538,7 +2554,15 @@ function withRefSheets(params, rs) {
|
|
|
2538
2554
|
return out;
|
|
2539
2555
|
}
|
|
2540
2556
|
var hasFormulaText = (v) => !!v && (isFormulaText(v.f) || typeof v.ref === "string");
|
|
2557
|
+
var hasFormulaCache = /* @__PURE__ */ new WeakMap();
|
|
2541
2558
|
function hasFormula(m) {
|
|
2559
|
+
const hit = hasFormulaCache.get(m);
|
|
2560
|
+
if (hit !== void 0) return hit;
|
|
2561
|
+
const any = hasFormulaOf(m);
|
|
2562
|
+
hasFormulaCache.set(m, any);
|
|
2563
|
+
return any;
|
|
2564
|
+
}
|
|
2565
|
+
function hasFormulaOf(m) {
|
|
2542
2566
|
let any = false;
|
|
2543
2567
|
forEachCell(cellsOf(m), (_r, _c, v) => {
|
|
2544
2568
|
any ||= hasFormulaText(v);
|
|
@@ -2577,15 +2601,18 @@ function cellThrough(sheet, change, r, c) {
|
|
|
2577
2601
|
return nr === null || nc === null ? null : [nr, nc];
|
|
2578
2602
|
}
|
|
2579
2603
|
function cellsOverChange(x, change) {
|
|
2604
|
+
if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok([x]);
|
|
2580
2605
|
const ctx = formulaCtx(x);
|
|
2581
2606
|
const out = {};
|
|
2582
2607
|
const dropped = [];
|
|
2583
2608
|
let why = null;
|
|
2609
|
+
let changed = false;
|
|
2584
2610
|
forEachCell(cellsOf(x), (r, c, v) => {
|
|
2585
2611
|
if (why) return;
|
|
2586
2612
|
const at = cellThrough(sheetOf(x), change, r, c);
|
|
2587
2613
|
if (!at) {
|
|
2588
2614
|
dropped.push(cellRef(sheetOf(x), r, c));
|
|
2615
|
+
changed = true;
|
|
2589
2616
|
return;
|
|
2590
2617
|
}
|
|
2591
2618
|
let e = v;
|
|
@@ -2596,14 +2623,19 @@ function cellsOverChange(x, change) {
|
|
|
2596
2623
|
return;
|
|
2597
2624
|
}
|
|
2598
2625
|
e = res.entry;
|
|
2626
|
+
if (res.changed) changed = true;
|
|
2599
2627
|
}
|
|
2628
|
+
if (at[0] !== r || at[1] !== c) changed = true;
|
|
2600
2629
|
putCell(out, at[0], at[1], e);
|
|
2601
2630
|
});
|
|
2602
2631
|
if (why) return barrier2(why);
|
|
2603
|
-
const
|
|
2632
|
+
const rsAfter = refSheetsAfter(ctx.refSheets, change);
|
|
2633
|
+
if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok([x]);
|
|
2634
|
+
const params = { ...withRefSheets(x.params, rsAfter), cellValue: out };
|
|
2604
2635
|
return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
|
|
2605
2636
|
}
|
|
2606
2637
|
function rewritesOf(y, change) {
|
|
2638
|
+
if (!hasFormula(y)) return null;
|
|
2607
2639
|
const ctx = formulaCtx(y);
|
|
2608
2640
|
const out = {};
|
|
2609
2641
|
let why = null;
|
|
@@ -2749,6 +2781,255 @@ function buildSize(template, values) {
|
|
|
2749
2781
|
const value = uniform !== void 0 && [...values.values()].every((v) => v === uniform) ? uniform : Object.fromEntries(values);
|
|
2750
2782
|
return { id: template.id, params: { ...p, ranges, [field]: value } };
|
|
2751
2783
|
}
|
|
2784
|
+
var isNumfmt = (m) => m.id === ID.setNumfmt || m.id === ID.removeNumfmt;
|
|
2785
|
+
function nfParts(m) {
|
|
2786
|
+
if (m.id === ID.removeNumfmt) return [{ key: null, ranges: (m.params.ranges ?? []).map((r) => ({ ...r })) }];
|
|
2787
|
+
const values = m.params.values ?? {};
|
|
2788
|
+
return Object.keys(values).map((k) => ({ key: k, ranges: (values[k]?.ranges ?? []).map((r) => ({ ...r })) }));
|
|
2789
|
+
}
|
|
2790
|
+
function nfBuild(m, parts) {
|
|
2791
|
+
const keep = parts.filter((p) => p.ranges.length);
|
|
2792
|
+
if (!keep.length) return [];
|
|
2793
|
+
if (m.id === ID.removeNumfmt) return [{ id: m.id, params: { ...m.params, ranges: keep[0].ranges } }];
|
|
2794
|
+
const values = {};
|
|
2795
|
+
const refMap = {};
|
|
2796
|
+
const srcValues = m.params.values ?? {};
|
|
2797
|
+
const srcRef = m.params.refMap ?? {};
|
|
2798
|
+
for (const p of keep) {
|
|
2799
|
+
values[p.key] = { ...srcValues[p.key], ranges: p.ranges };
|
|
2800
|
+
refMap[p.key] = srcRef[p.key];
|
|
2801
|
+
}
|
|
2802
|
+
return [{ id: m.id, params: { ...m.params, values, refMap } }];
|
|
2803
|
+
}
|
|
2804
|
+
function nfValueAt(m, row, col) {
|
|
2805
|
+
for (const p of nfParts(m))
|
|
2806
|
+
if (p.ranges.some((r) => r.startRow <= row && row <= r.endRow && r.startColumn <= col && col <= r.endColumn)) {
|
|
2807
|
+
if (p.key === null) return null;
|
|
2808
|
+
const ref = (m.params.refMap ?? {})[p.key];
|
|
2809
|
+
return { pattern: ref?.pattern };
|
|
2810
|
+
}
|
|
2811
|
+
return void 0;
|
|
2812
|
+
}
|
|
2813
|
+
function spanThrough(op, lo, hi) {
|
|
2814
|
+
const pieces = [];
|
|
2815
|
+
if (op.kind === "insert") pieces.push([0, op.at - 1, 0], [op.at, Infinity, op.count]);
|
|
2816
|
+
else if (op.kind === "remove") pieces.push([0, op.start - 1, 0], [op.start + op.count, Infinity, -op.count]);
|
|
2817
|
+
else if (op.count <= 0 || op.to >= op.from && op.to <= op.from + op.count) pieces.push([0, Infinity, 0]);
|
|
2818
|
+
else if (op.to > op.from) {
|
|
2819
|
+
const n = op.count;
|
|
2820
|
+
pieces.push([0, op.from - 1, 0], [op.from, op.from + n - 1, op.to - n - op.from], [op.from + n, op.to - 1, -n], [op.to, Infinity, 0]);
|
|
2821
|
+
} else {
|
|
2822
|
+
const n = op.count;
|
|
2823
|
+
pieces.push([0, op.to - 1, 0], [op.to, op.from - 1, n], [op.from, op.from + n - 1, op.to - op.from], [op.from + n, Infinity, 0]);
|
|
2824
|
+
}
|
|
2825
|
+
const out = [];
|
|
2826
|
+
for (const [a, b, d] of pieces) {
|
|
2827
|
+
const x0 = Math.max(a, lo);
|
|
2828
|
+
const x1 = Math.min(b, hi);
|
|
2829
|
+
if (x0 <= x1) out.push([x0 + d, x1 + d]);
|
|
2830
|
+
}
|
|
2831
|
+
out.sort((p, q) => p[0] - q[0]);
|
|
2832
|
+
const merged = [];
|
|
2833
|
+
for (const p of out) {
|
|
2834
|
+
const last = merged[merged.length - 1];
|
|
2835
|
+
if (last && last[1] + 1 >= p[0]) last[1] = Math.max(last[1], p[1]);
|
|
2836
|
+
else merged.push([p[0], p[1]]);
|
|
2837
|
+
}
|
|
2838
|
+
return merged;
|
|
2839
|
+
}
|
|
2840
|
+
function rectsThrough(st, rects) {
|
|
2841
|
+
const [a0, a1] = S(st.axis);
|
|
2842
|
+
const out = [];
|
|
2843
|
+
for (const r of rects) for (const [lo, hi] of spanThrough(st.op, r[a0], r[a1])) out.push({ ...r, [a0]: lo, [a1]: hi });
|
|
2844
|
+
return out;
|
|
2845
|
+
}
|
|
2846
|
+
function rectMinus(a, b) {
|
|
2847
|
+
if (a.startRow > b.endRow || b.startRow > a.endRow || a.startColumn > b.endColumn || b.startColumn > a.endColumn) return [a];
|
|
2848
|
+
const out = [];
|
|
2849
|
+
if (a.startRow < b.startRow) out.push({ ...a, endRow: b.startRow - 1 });
|
|
2850
|
+
if (a.endRow > b.endRow) out.push({ ...a, startRow: b.endRow + 1 });
|
|
2851
|
+
const r0 = Math.max(a.startRow, b.startRow);
|
|
2852
|
+
const r1 = Math.min(a.endRow, b.endRow);
|
|
2853
|
+
if (a.startColumn < b.startColumn) out.push({ ...a, startRow: r0, endRow: r1, endColumn: b.startColumn - 1 });
|
|
2854
|
+
if (a.endColumn > b.endColumn) out.push({ ...a, startRow: r0, endRow: r1, startColumn: b.endColumn + 1 });
|
|
2855
|
+
return out;
|
|
2856
|
+
}
|
|
2857
|
+
function rectsMinus(as, bs) {
|
|
2858
|
+
let cur = as;
|
|
2859
|
+
for (const b of bs) cur = cur.flatMap((a) => rectMinus(a, b));
|
|
2860
|
+
return cur;
|
|
2861
|
+
}
|
|
2862
|
+
function nWrites(m) {
|
|
2863
|
+
const out = [];
|
|
2864
|
+
forEachCell(cellsOf(m), (r, c, v) => {
|
|
2865
|
+
if (v === null || v.s === null || v.s && typeof v.s === "object" && "n" in v.s)
|
|
2866
|
+
out.push({ startRow: r, endRow: r, startColumn: c, endColumn: c });
|
|
2867
|
+
});
|
|
2868
|
+
return out;
|
|
2869
|
+
}
|
|
2870
|
+
function numfmtPair(x, y, side, sx, sy) {
|
|
2871
|
+
const nx = isNumfmt(x);
|
|
2872
|
+
const ny = isNumfmt(y);
|
|
2873
|
+
if (!nx && !ny) return null;
|
|
2874
|
+
if (nx && sy) return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
|
|
2875
|
+
if (ny && sx) return ok([x]);
|
|
2876
|
+
if (nx && ny) {
|
|
2877
|
+
if (side === "left") return ok([x]);
|
|
2878
|
+
const ys = nfParts(y).flatMap((p) => p.ranges);
|
|
2879
|
+
return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
|
|
2880
|
+
}
|
|
2881
|
+
if (nx && y.id === ID.values) {
|
|
2882
|
+
if (side === "left") return ok([x]);
|
|
2883
|
+
const ys = nWrites(y);
|
|
2884
|
+
return ys.length ? ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok([x]);
|
|
2885
|
+
}
|
|
2886
|
+
if (ny && x.id === ID.values) {
|
|
2887
|
+
if (side === "left") return ok([x]);
|
|
2888
|
+
const out = {};
|
|
2889
|
+
const tail = {};
|
|
2890
|
+
let touched = false;
|
|
2891
|
+
forEachCell(cellsOf(x), (r, c, v) => {
|
|
2892
|
+
const n = nfValueAt(y, r, c);
|
|
2893
|
+
if (n === void 0) return putCell(out, r, c, v);
|
|
2894
|
+
if (v === null || v.s === null) {
|
|
2895
|
+
putCell(out, r, c, v);
|
|
2896
|
+
if (n) {
|
|
2897
|
+
putCell(tail, r, c, { s: { n } });
|
|
2898
|
+
touched = true;
|
|
2899
|
+
}
|
|
2900
|
+
return;
|
|
2901
|
+
}
|
|
2902
|
+
if (v.s && typeof v.s === "object" && "n" in v.s) {
|
|
2903
|
+
const { n: _drop, ...rest } = v.s;
|
|
2904
|
+
const e = { ...v };
|
|
2905
|
+
if (Object.keys(rest).length) e.s = rest;
|
|
2906
|
+
else delete e.s;
|
|
2907
|
+
touched = true;
|
|
2908
|
+
if (Object.keys(e).length) putCell(out, r, c, e);
|
|
2909
|
+
return;
|
|
2910
|
+
}
|
|
2911
|
+
putCell(out, r, c, v);
|
|
2912
|
+
});
|
|
2913
|
+
if (!touched) return ok([x]);
|
|
2914
|
+
const ops = [];
|
|
2915
|
+
if (!isEmptyMatrix(out)) ops.push(cellsMutation(x, out));
|
|
2916
|
+
if (!isEmptyMatrix(tail)) ops.push({ id: ID.values, params: { subUnitId: sheetOf(x), cellValue: tail } });
|
|
2917
|
+
return ok(ops);
|
|
2918
|
+
}
|
|
2919
|
+
return ok([x]);
|
|
2920
|
+
}
|
|
2921
|
+
var isCount = (m) => m.id === ID.rowCount || m.id === ID.colCount;
|
|
2922
|
+
var countAxis = (m) => m.id === ID.rowCount ? "row" : "col";
|
|
2923
|
+
var countKey = (m) => m.id === ID.rowCount ? "rowCount" : "columnCount";
|
|
2924
|
+
function countPair(x, y, sy) {
|
|
2925
|
+
if (!isCount(x)) return isCount(y) ? ok([x]) : null;
|
|
2926
|
+
const k = countKey(x);
|
|
2927
|
+
const v = Number(x.params[k]);
|
|
2928
|
+
if (sy) {
|
|
2929
|
+
if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok([x]);
|
|
2930
|
+
const d = sy.op.kind === "insert" ? sy.op.count : -sy.op.count;
|
|
2931
|
+
return ok([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
|
|
2932
|
+
}
|
|
2933
|
+
if (isCount(y) && y.id === x.id) {
|
|
2934
|
+
const w = Number(y.params[k]);
|
|
2935
|
+
return ok([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
|
|
2936
|
+
}
|
|
2937
|
+
return ok([x]);
|
|
2938
|
+
}
|
|
2939
|
+
var isSheetOp = (m) => m.id === ID.insertSheet || m.id === ID.removeSheet || m.id === ID.sheetOrder;
|
|
2940
|
+
var sheetIdOf = (m) => m.id === ID.insertSheet ? String(m.params.sheet?.id ?? "") : sheetOf(m);
|
|
2941
|
+
function sheetAxisOf(m) {
|
|
2942
|
+
const p = m.params;
|
|
2943
|
+
if (m.id === ID.insertSheet) return typeof p.index === "number" ? { kind: "insert", at: p.index, count: 1 } : null;
|
|
2944
|
+
if (m.id === ID.removeSheet) return typeof p.sheetIndex === "number" ? { kind: "remove", start: p.sheetIndex, count: 1 } : null;
|
|
2945
|
+
if (m.id === ID.sheetOrder) {
|
|
2946
|
+
const f = Number(p.fromOrder);
|
|
2947
|
+
const t = Number(p.toOrder);
|
|
2948
|
+
return { kind: "move", from: f, count: 1, to: t > f ? t + 1 : t };
|
|
2949
|
+
}
|
|
2950
|
+
return null;
|
|
2951
|
+
}
|
|
2952
|
+
function buildSheetOp(template, op) {
|
|
2953
|
+
if (op.kind === "insert") return { id: template.id, params: { ...template.params, index: op.at } };
|
|
2954
|
+
if (op.kind === "remove") return { id: template.id, params: { ...template.params, sheetIndex: op.start } };
|
|
2955
|
+
return { id: template.id, params: { ...template.params, fromOrder: op.from, toOrder: op.to > op.from ? op.to - 1 : op.to } };
|
|
2956
|
+
}
|
|
2957
|
+
function namesSheet(m, id) {
|
|
2958
|
+
const rs = refSheetsOf(m);
|
|
2959
|
+
return !!rs && Object.values(rs).includes(id) && (m.id === ID.setName || hasFormula(m));
|
|
2960
|
+
}
|
|
2961
|
+
function sheetPair(x, y, side) {
|
|
2962
|
+
const xs = isSheetOp(x);
|
|
2963
|
+
const ys = isSheetOp(y);
|
|
2964
|
+
if (!xs && !ys) return null;
|
|
2965
|
+
if (xs && ys) {
|
|
2966
|
+
const a = sheetAxisOf(x);
|
|
2967
|
+
const b = sheetAxisOf(y);
|
|
2968
|
+
if (!a || !b) return barrier2("a sheet add or remove without its index (capture must call annotateSheetOps)");
|
|
2969
|
+
if (x.id === ID.insertSheet && y.id === ID.insertSheet && sheetIdOf(x) === sheetIdOf(y)) {
|
|
2970
|
+
return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok([]) : barrier2("the same sheet id added twice with different content");
|
|
2971
|
+
}
|
|
2972
|
+
if (x.id === ID.removeSheet && typeof x.params.sheetsLeft === "number" && sheetIdOf(x) !== sheetIdOf(y) && (y.id === ID.removeSheet || y.id === ID.insertSheet)) {
|
|
2973
|
+
const left = x.params.sheetsLeft + (y.id === ID.insertSheet ? 1 : -1);
|
|
2974
|
+
if (left < 1) return barrier2("concurrent sheet removes would leave the workbook without a sheet");
|
|
2975
|
+
const out2 = transformAxis(a, b, side);
|
|
2976
|
+
if (!out2) return barrier2("sheet order: no transform");
|
|
2977
|
+
return ok(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
|
|
2978
|
+
}
|
|
2979
|
+
const out = transformAxis(a, b, side);
|
|
2980
|
+
if (!out) return barrier2("sheet order: no transform");
|
|
2981
|
+
return ok(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
|
|
2982
|
+
}
|
|
2983
|
+
if (ys) {
|
|
2984
|
+
if (y.id !== ID.removeSheet) return ok([x]);
|
|
2985
|
+
const gone2 = sheetOf(y);
|
|
2986
|
+
if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
|
|
2987
|
+
if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
|
|
2988
|
+
return ok([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
|
|
2989
|
+
return ok([x]);
|
|
2990
|
+
}
|
|
2991
|
+
if (x.id !== ID.removeSheet) return ok([x]);
|
|
2992
|
+
const gone = sheetOf(x);
|
|
2993
|
+
if (namesSheet(y, gone)) return barrier2("a formula names a sheet removed at the same time");
|
|
2994
|
+
return ok([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
|
|
2995
|
+
}
|
|
2996
|
+
function annotateSheetOps(group, sheetOrder) {
|
|
2997
|
+
const order = [...sheetOrder];
|
|
2998
|
+
return group.map((m) => {
|
|
2999
|
+
if (m.id === ID.insertSheet) {
|
|
3000
|
+
const index = typeof m.params.index === "number" ? Math.min(m.params.index, order.length) : order.length;
|
|
3001
|
+
order.splice(index, 0, sheetIdOf(m));
|
|
3002
|
+
return index === m.params.index ? m : { id: m.id, params: { ...m.params, index } };
|
|
3003
|
+
}
|
|
3004
|
+
if (m.id === ID.removeSheet) {
|
|
3005
|
+
const i = order.indexOf(sheetOf(m));
|
|
3006
|
+
if (i >= 0) order.splice(i, 1);
|
|
3007
|
+
return i >= 0 ? { id: m.id, params: { ...m.params, sheetIndex: i, sheetsLeft: order.length } } : m;
|
|
3008
|
+
}
|
|
3009
|
+
if (m.id === ID.sheetOrder) {
|
|
3010
|
+
const f = Number(m.params.fromOrder);
|
|
3011
|
+
const [id] = order.splice(f, 1);
|
|
3012
|
+
order.splice(Number(m.params.toOrder), 0, id ?? sheetOf(m));
|
|
3013
|
+
}
|
|
3014
|
+
return m;
|
|
3015
|
+
});
|
|
3016
|
+
}
|
|
3017
|
+
function inlineSheetStyles(sheet, styleOf) {
|
|
3018
|
+
const out = JSON.parse(JSON.stringify(sheet));
|
|
3019
|
+
const fix = (o) => {
|
|
3020
|
+
if (o && typeof o.s === "string") {
|
|
3021
|
+
const st = styleOf(o.s);
|
|
3022
|
+
if (st) o.s = JSON.parse(JSON.stringify(st));
|
|
3023
|
+
}
|
|
3024
|
+
};
|
|
3025
|
+
for (const row of Object.values(out.cellData ?? {})) for (const cell of Object.values(row ?? {})) fix(cell);
|
|
3026
|
+
for (const key of ["rowData", "columnData"]) for (const v of Object.values(out[key] ?? {})) fix(v);
|
|
3027
|
+
if (typeof out.defaultStyle === "string") {
|
|
3028
|
+
const st = styleOf(out.defaultStyle);
|
|
3029
|
+
if (st) out.defaultStyle = JSON.parse(JSON.stringify(st));
|
|
3030
|
+
}
|
|
3031
|
+
return out;
|
|
3032
|
+
}
|
|
2752
3033
|
function familyOf(id) {
|
|
2753
3034
|
const e = SHEET_MUTATIONS[id];
|
|
2754
3035
|
return e && e.kind === "covered" ? e.family : "";
|
|
@@ -2765,6 +3046,8 @@ function transformMutation(x, y, side) {
|
|
|
2765
3046
|
}
|
|
2766
3047
|
const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
|
|
2767
3048
|
if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
|
|
3049
|
+
const sp = sheetPair(x, y, side);
|
|
3050
|
+
if (sp) return sp;
|
|
2768
3051
|
const fp = formulaPair(x, y, side);
|
|
2769
3052
|
if (fp) return fp;
|
|
2770
3053
|
if (sheetOf(x) !== sheetOf(y)) return ok([x]);
|
|
@@ -2772,6 +3055,10 @@ function transformMutation(x, y, side) {
|
|
|
2772
3055
|
const fy = familyOf(y.id);
|
|
2773
3056
|
const sy = structuralOf(y);
|
|
2774
3057
|
const sx = structuralOf(x);
|
|
3058
|
+
const cp = countPair(x, y, sy);
|
|
3059
|
+
if (cp) return cp;
|
|
3060
|
+
const np = numfmtPair(x, y, side, sx, sy);
|
|
3061
|
+
if (np) return np;
|
|
2775
3062
|
if (sx && sy) {
|
|
2776
3063
|
if (sx.axis !== sy.axis) return ok([x]);
|
|
2777
3064
|
const out = transformAxis(sx.op, sy.op, side);
|
|
@@ -2879,22 +3166,45 @@ function tSeq(xs, ys, side, acc) {
|
|
|
2879
3166
|
acc.dropped.push(...a.dropped);
|
|
2880
3167
|
return [a.op, b.op];
|
|
2881
3168
|
}
|
|
3169
|
+
const outX = [];
|
|
3170
|
+
let curY = ys;
|
|
3171
|
+
for (const x of xs) {
|
|
3172
|
+
let curX = [x];
|
|
3173
|
+
const nextY = [];
|
|
3174
|
+
for (const y of curY) {
|
|
3175
|
+
if (curX.length === 0) {
|
|
3176
|
+
nextY.push(y);
|
|
3177
|
+
continue;
|
|
3178
|
+
}
|
|
3179
|
+
const r = tSeq(curX, [y], side, acc);
|
|
3180
|
+
if (blocked(r)) return r;
|
|
3181
|
+
curX = r[0];
|
|
3182
|
+
for (const m of r[1]) nextY.push(m);
|
|
3183
|
+
}
|
|
3184
|
+
for (const m of curX) outX.push(m);
|
|
3185
|
+
curY = nextY;
|
|
3186
|
+
}
|
|
3187
|
+
return [outX, curY];
|
|
3188
|
+
}
|
|
3189
|
+
function tSeqOld(xs, ys, side, acc) {
|
|
3190
|
+
if (xs.length === 0 || ys.length === 0) return [xs, ys];
|
|
3191
|
+
if (xs.length === 1 && ys.length === 1) return tSeq(xs, ys, side, acc);
|
|
2882
3192
|
if (xs.length > 1) {
|
|
2883
|
-
const first2 =
|
|
3193
|
+
const first2 = tSeqOld([xs[0]], ys, side, acc);
|
|
2884
3194
|
if (blocked(first2)) return first2;
|
|
2885
|
-
const rest2 =
|
|
3195
|
+
const rest2 = tSeqOld(xs.slice(1), first2[1], side, acc);
|
|
2886
3196
|
if (blocked(rest2)) return rest2;
|
|
2887
3197
|
return [[...first2[0], ...rest2[0]], rest2[1]];
|
|
2888
3198
|
}
|
|
2889
|
-
const first =
|
|
3199
|
+
const first = tSeqOld(xs, [ys[0]], side, acc);
|
|
2890
3200
|
if (blocked(first)) return first;
|
|
2891
|
-
const rest =
|
|
3201
|
+
const rest = tSeqOld(first[0], ys.slice(1), side, acc);
|
|
2892
3202
|
if (blocked(rest)) return rest;
|
|
2893
3203
|
return [rest[0], [...first[1], ...rest[1]]];
|
|
2894
3204
|
}
|
|
2895
3205
|
function transformGroup(x, y, side) {
|
|
2896
3206
|
const acc = { lost: [], dropped: [] };
|
|
2897
|
-
const r = tSeq([...x], [...y], side, acc);
|
|
3207
|
+
const r = (process.env.OLD_TSEQ ? tSeqOld : tSeq)([...x], [...y], side, acc);
|
|
2898
3208
|
if (blocked(r)) return r;
|
|
2899
3209
|
return { op: r[0], lost: [...new Set(acc.lost)], dropped: [...new Set(acc.dropped)] };
|
|
2900
3210
|
}
|
|
@@ -2964,7 +3274,7 @@ async function sheetsStateHash(snapshot) {
|
|
|
2964
3274
|
}
|
|
2965
3275
|
|
|
2966
3276
|
// src/univer/collab/sheets-ot/room.ts
|
|
2967
|
-
var SHEETS_COLLAB_PROTO =
|
|
3277
|
+
var SHEETS_COLLAB_PROTO = 2;
|
|
2968
3278
|
var SHEETS_EDIT_GROUP = "sheets.edit";
|
|
2969
3279
|
var flip2 = (side) => side === "left" ? "right" : "left";
|
|
2970
3280
|
var isNoopSheetOp = (op) => op == null || op.length === 0;
|
|
@@ -3011,6 +3321,11 @@ function travelingShape(m) {
|
|
|
3011
3321
|
}
|
|
3012
3322
|
return { id: m.id, params };
|
|
3013
3323
|
}
|
|
3324
|
+
var shapedLists = /* @__PURE__ */ new WeakMap();
|
|
3325
|
+
function cachedShape(list) {
|
|
3326
|
+
const hit = shapedLists.get(list);
|
|
3327
|
+
return hit && hit.src.length === list.length && hit.src.every((m, i) => m === list[i]) ? hit.shaped : null;
|
|
3328
|
+
}
|
|
3014
3329
|
function rebaseSheetUndoStack(items, remote, unitId) {
|
|
3015
3330
|
if (isNoopSheetOp(remote)) return 0;
|
|
3016
3331
|
let dropped = 0;
|
|
@@ -3022,7 +3337,11 @@ function rebaseSheetUndoStack(items, remote, unitId) {
|
|
|
3022
3337
|
if (!ok2 || !list?.length) continue;
|
|
3023
3338
|
const isOperation = (id) => !SHEET_MUTATIONS[id] && id.includes(".operation.");
|
|
3024
3339
|
const operations = list.filter((m) => isOperation(m.id));
|
|
3025
|
-
|
|
3340
|
+
let shaped = cachedShape(list);
|
|
3341
|
+
if (!shaped) {
|
|
3342
|
+
shaped = list.filter((m) => !isOperation(m.id)).map(travelingShape);
|
|
3343
|
+
shapedLists.set(list, { src: list.slice(), shaped });
|
|
3344
|
+
}
|
|
3026
3345
|
if (shaped.some((m) => m === null)) {
|
|
3027
3346
|
ok2 = false;
|
|
3028
3347
|
continue;
|
|
@@ -3034,8 +3353,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
|
|
|
3034
3353
|
ok2 = false;
|
|
3035
3354
|
continue;
|
|
3036
3355
|
}
|
|
3037
|
-
if (
|
|
3038
|
-
|
|
3356
|
+
if (r.op.length === shaped.length && r.op.every((m, i2) => m === shaped[i2])) continue;
|
|
3357
|
+
const next = [...r.op.map((m) => ({ id: m.id, params: { ...forApply(m).params, unitId } })), ...operations];
|
|
3358
|
+
shapedLists.set(next, { src: next.slice(), shaped: r.op });
|
|
3359
|
+
item[key] = next;
|
|
3039
3360
|
} catch {
|
|
3040
3361
|
ok2 = false;
|
|
3041
3362
|
}
|
|
@@ -3110,7 +3431,7 @@ function createSheetsOtAdapter(port, hooks = {}) {
|
|
|
3110
3431
|
});
|
|
3111
3432
|
});
|
|
3112
3433
|
}
|
|
3113
|
-
return sheetsStateHash(port.snapshot());
|
|
3434
|
+
return (hooks.stateHash ?? sheetsStateHash)(port.snapshot());
|
|
3114
3435
|
},
|
|
3115
3436
|
held: () => queue.length,
|
|
3116
3437
|
rebaseLocalOverHeld(local) {
|
|
@@ -3222,6 +3543,8 @@ var VALUES = "sheet.mutation.set-range-values";
|
|
|
3222
3543
|
var ADD_MERGE = "sheet.mutation.add-worksheet-merge";
|
|
3223
3544
|
var REMOVE_MERGE = "sheet.mutation.remove-worksheet-merge";
|
|
3224
3545
|
var SHEET_NAME = "sheet.mutation.set-worksheet-name";
|
|
3546
|
+
var INSERT_SHEET = "sheet.mutation.insert-sheet";
|
|
3547
|
+
var RESHAPE = /* @__PURE__ */ new Set(["sheet.mutation.set-worksheet-row-count", "sheet.mutation.set-worksheet-column-count", "sheet.mutation.remove-sheet", INSERT_SHEET]);
|
|
3225
3548
|
var DEPTH_GUARD = /* @__PURE__ */ Symbol.for("ai-matrx.office.sheets.command-depth-guard");
|
|
3226
3549
|
var json = (v) => v === void 0 ? v : JSON.parse(JSON.stringify(v));
|
|
3227
3550
|
var flagged = (options) => {
|
|
@@ -3258,7 +3581,8 @@ function univerSheetsOtPort(o) {
|
|
|
3258
3581
|
for (const [id, d] of Object.entries(map)) out[id] = String(d?.name ?? "");
|
|
3259
3582
|
return out;
|
|
3260
3583
|
};
|
|
3261
|
-
const
|
|
3584
|
+
const sheetOrder = () => (o.workbook()?.getSheets() ?? []).map((ws) => ws.getSheetId());
|
|
3585
|
+
const openGroup = (label) => ({ label, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
|
|
3262
3586
|
const emit = (e) => {
|
|
3263
3587
|
for (const l of [...listeners]) {
|
|
3264
3588
|
try {
|
|
@@ -3274,7 +3598,8 @@ function univerSheetsOtPort(o) {
|
|
|
3274
3598
|
if (!g) return;
|
|
3275
3599
|
if (g.notShared) emit({ kind: "not_shared", mutationId: g.notShared, label: g.label });
|
|
3276
3600
|
else if (g.mutations.length) {
|
|
3277
|
-
const mutations = annotateFormulas(g.mutations, g.sheets, g.names);
|
|
3601
|
+
const mutations = annotateSheetOps(annotateFormulas(g.mutations, g.sheets, g.names), g.order);
|
|
3602
|
+
if (mutations.some((m) => isStructuralMutation(m) || RESHAPE.has(m.id))) clampSelection();
|
|
3278
3603
|
const known = g.inverses.every((i) => i !== void 0);
|
|
3279
3604
|
const inverse = known ? annotateFormulas(g.inverses.slice().reverse().flat(), g.sheets, g.names) : void 0;
|
|
3280
3605
|
emit({ kind: "group", mutations, ...inverse !== void 0 ? { inverse } : {}, label: g.label });
|
|
@@ -3308,7 +3633,27 @@ function univerSheetsOtPort(o) {
|
|
|
3308
3633
|
}
|
|
3309
3634
|
if (info.id === SHEET_NAME) record.name = ws.getName();
|
|
3310
3635
|
pre.set(p, record);
|
|
3636
|
+
const owed = isStructuralMutation({ id: info.id, params: p }) ? mergeFixupsOwed({ id: info.id, params: p }, record.merges ?? []) : null;
|
|
3637
|
+
if (owed) {
|
|
3638
|
+
runOwn(REMOVE_MERGE, String(p.subUnitId), owed.remove, ADD_MERGE);
|
|
3639
|
+
if (owed.add.length) record.addAfter = owed.add;
|
|
3640
|
+
}
|
|
3311
3641
|
});
|
|
3642
|
+
const runOwn = (id, sheet, ranges, inverseId) => {
|
|
3643
|
+
const u = unitId();
|
|
3644
|
+
if (!u) return;
|
|
3645
|
+
applying = true;
|
|
3646
|
+
try {
|
|
3647
|
+
cs.syncExecuteCommand(id, { unitId: u, subUnitId: sheet, ranges: json(ranges) }, { onlyLocal: true });
|
|
3648
|
+
} finally {
|
|
3649
|
+
applying = false;
|
|
3650
|
+
}
|
|
3651
|
+
if (!group) group = openGroup(null);
|
|
3652
|
+
if (!group.notShared) {
|
|
3653
|
+
group.mutations.push({ id, params: { subUnitId: sheet, ranges: json(ranges) } });
|
|
3654
|
+
group.inverses.push([{ id: inverseId, params: { subUnitId: sheet, ranges: json(ranges) } }]);
|
|
3655
|
+
}
|
|
3656
|
+
};
|
|
3312
3657
|
const after = cs.onCommandExecuted((info) => {
|
|
3313
3658
|
if (info.type !== COMMAND) return;
|
|
3314
3659
|
const at = tracker.stack.lastIndexOf(info.id);
|
|
@@ -3406,6 +3751,8 @@ function univerSheetsOtPort(o) {
|
|
|
3406
3751
|
if (!m2) return { m: null, inverse: void 0 };
|
|
3407
3752
|
return { m: m2, inverse: [{ id: ADD_MERGE, params: { subUnitId: sheet, ranges: json(m2.params.ranges) } }] };
|
|
3408
3753
|
}
|
|
3754
|
+
if (info.id === INSERT_SHEET && params.sheet && typeof params.sheet === "object")
|
|
3755
|
+
params.sheet = inlineSheetStyles(params.sheet, (id) => o.workbook()?.getStyles().get(id));
|
|
3409
3756
|
const m = { id: info.id, params };
|
|
3410
3757
|
switch (info.id) {
|
|
3411
3758
|
case "sheet.mutation.insert-row":
|
|
@@ -3422,8 +3769,7 @@ function univerSheetsOtPort(o) {
|
|
|
3422
3769
|
};
|
|
3423
3770
|
const collab = cs.onMutationExecutedForCollab((info, options) => {
|
|
3424
3771
|
if (applying || flagged(options) || !mine(info.params)) return;
|
|
3425
|
-
|
|
3426
|
-
if (lone) group = openGroup(null);
|
|
3772
|
+
if (!group) group = openGroup(null);
|
|
3427
3773
|
const g = group;
|
|
3428
3774
|
if (!g.notShared) {
|
|
3429
3775
|
const r = capture(info);
|
|
@@ -3433,11 +3779,29 @@ function univerSheetsOtPort(o) {
|
|
|
3433
3779
|
g.inverses.push(r.inverse);
|
|
3434
3780
|
}
|
|
3435
3781
|
}
|
|
3436
|
-
|
|
3782
|
+
const owedAdd = pre.get(info.params)?.addAfter;
|
|
3783
|
+
if (owedAdd?.length) runOwn(ADD_MERGE, String(info.params.subUnitId ?? ""), owedAdd, REMOVE_MERGE);
|
|
3784
|
+
if (tracker.stack.length === 0) settle();
|
|
3437
3785
|
});
|
|
3786
|
+
const clampSelection = () => {
|
|
3787
|
+
const sel = o.selections;
|
|
3788
|
+
if (!sel) return;
|
|
3789
|
+
try {
|
|
3790
|
+
const sheet = sel.sheetId();
|
|
3791
|
+
const ws = sheet ? o.workbook()?.getSheetBySheetId(sheet) : null;
|
|
3792
|
+
const current = sel.get();
|
|
3793
|
+
if (!ws || !current?.length) return;
|
|
3794
|
+
const rows = ws.getMaxRows?.() ?? Number.MAX_SAFE_INTEGER;
|
|
3795
|
+
const cols = ws.getMaxColumns?.() ?? Number.MAX_SAFE_INTEGER;
|
|
3796
|
+
const next = moveSelectionsThrough(json(current), { id: "", params: {} }, rows, cols);
|
|
3797
|
+
if (JSON.stringify(next) !== JSON.stringify(current)) sel.set(next);
|
|
3798
|
+
} catch (err) {
|
|
3799
|
+
console.warn("[sheets-ot] could not keep this seat's selection inside the sheet after its own row or column change", err);
|
|
3800
|
+
}
|
|
3801
|
+
};
|
|
3438
3802
|
const followSelection = (m) => {
|
|
3439
3803
|
const sel = o.selections;
|
|
3440
|
-
if (!sel || !axisOpOf(m)) return;
|
|
3804
|
+
if (!sel || !axisOpOf(m) && !RESHAPE.has(m.id)) return;
|
|
3441
3805
|
try {
|
|
3442
3806
|
const sheet = String(m.params.subUnitId ?? "");
|
|
3443
3807
|
if (sel.sheetId() !== sheet) return;
|
|
@@ -3643,15 +4007,6 @@ async function workbookUsesOrderedRoom(workbookId, knob, isNewWorkbook) {
|
|
|
3643
4007
|
if (knob === "new") return isNewWorkbook();
|
|
3644
4008
|
return false;
|
|
3645
4009
|
}
|
|
3646
|
-
function pickColor2(uid) {
|
|
3647
|
-
const palette = ["#ef4444", "#f59e0b", "#10b981", "#3b82f6", "#8b5cf6", "#ec4899", "#14b8a6", "#f97316"];
|
|
3648
|
-
let h = 2166136261;
|
|
3649
|
-
for (let i = 0; i < uid.length; i++) {
|
|
3650
|
-
h ^= uid.charCodeAt(i);
|
|
3651
|
-
h = Math.imul(h, 16777619);
|
|
3652
|
-
}
|
|
3653
|
-
return palette[Math.abs(h) % palette.length] ?? "#ec4899";
|
|
3654
|
-
}
|
|
3655
4010
|
async function startWorkbookOtRoom(port, o) {
|
|
3656
4011
|
const latest = await getLatestSnapshot(o.workbookId);
|
|
3657
4012
|
if (!latest.success) throw new Error(latest.error);
|
|
@@ -3668,12 +4023,12 @@ async function startWorkbookOtRoom(port, o) {
|
|
|
3668
4023
|
uid: o.uid,
|
|
3669
4024
|
clientId: o.clientId,
|
|
3670
4025
|
name: o.displayName ?? o.uid.slice(0, 8),
|
|
3671
|
-
color: pickColor2(o.uid),
|
|
3672
4026
|
sheetId: null,
|
|
3673
4027
|
row: null,
|
|
3674
4028
|
col: null,
|
|
3675
4029
|
ts: Date.now()
|
|
3676
4030
|
});
|
|
4031
|
+
const stopColor = (0, import_collab6.claimCollaboratorColor)(awareness, { uid: o.uid, clientId: o.clientId });
|
|
3677
4032
|
const publishAwareness = () => o.onAwareness?.(new Map(awareness.getStates()));
|
|
3678
4033
|
awareness.on("change", publishAwareness);
|
|
3679
4034
|
const provider = new import_collab6.SupabaseYjsProvider({
|
|
@@ -3719,6 +4074,7 @@ async function startWorkbookOtRoom(port, o) {
|
|
|
3719
4074
|
awareness.setLocalState({ ...current, sheetId: c.sheetId, row: c.row, col: c.col, ts: Date.now() });
|
|
3720
4075
|
},
|
|
3721
4076
|
stop() {
|
|
4077
|
+
stopColor();
|
|
3722
4078
|
room.stop();
|
|
3723
4079
|
port.dispose?.();
|
|
3724
4080
|
awareness.off("change", publishAwareness);
|