wordinweb 0.2.3 → 0.2.4

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/dist/collab.d.ts CHANGED
@@ -844,6 +844,9 @@ interface UseCollabOptions {
844
844
  * (join cold, keep nothing).
845
845
  */
846
846
  store?: BundleStore;
847
+ /** Open the stored browser copy without creating a socket. Reconnect uses
848
+ * the normal resume path and reconciles the captured offline tail. */
849
+ startOffline?: boolean;
847
850
  /** Claim the identity from an existing live connection (doc 12 §7 "use
848
851
  * here instead"): set after an `already-open` refusal and remount. */
849
852
  takeover?: boolean;
package/dist/collab.js CHANGED
@@ -79,7 +79,7 @@ import {
79
79
  setSmartArtTextFormat,
80
80
  toggleCheckbox,
81
81
  validatePastedOoxml
82
- } from "./chunk-OIN65MGS.js";
82
+ } from "./chunk-QH2L3NPL.js";
83
83
  import "./chunk-7D4SUZUM.js";
84
84
 
85
85
  // src/collab.tsx
@@ -1087,7 +1087,7 @@ function tableOfParagraph(doc, ids, cellParagraphId) {
1087
1087
  return null;
1088
1088
  }
1089
1089
  function firstDrawingIn(el) {
1090
- if (localName(el.name) === "drawing") return el;
1090
+ if (["drawing", "shape", "rect"].includes(localName(el.name))) return el;
1091
1091
  for (const c of el.children) {
1092
1092
  const found = firstDrawingIn(c);
1093
1093
  if (found) return found;
@@ -1656,7 +1656,7 @@ function arrivalMode(tailLength, diverged, opts = {}) {
1656
1656
  }
1657
1657
 
1658
1658
  // ../collab/src/protocol.ts
1659
- var ENGINE_VERSION = "e9";
1659
+ var ENGINE_VERSION = "e10";
1660
1660
  var PRESENCE_MAX_RANGES = 64;
1661
1661
  function sanitizePresencePosition(pos) {
1662
1662
  if (!pos || !pos.ranges) return pos;
@@ -4274,6 +4274,7 @@ function withDeadline(p, ms, fallback) {
4274
4274
  }
4275
4275
  function useCollab(opts) {
4276
4276
  const { url, docId, clientId, token, createSocket, store, profile, takeover, docKey, shareCode, ownerToken, httpBase } = opts;
4277
+ const startOffline = Boolean(opts.startOffline);
4277
4278
  const connRef = useRef(null);
4278
4279
  const carriedIdAllocator = useMemo(() => new CarriedIdAllocator(clientId), [clientId]);
4279
4280
  const [doc, setDoc] = useState(null);
@@ -4317,17 +4318,18 @@ function useCollab(opts) {
4317
4318
  const persisterRef = useRef(null);
4318
4319
  const tailConnRef = useRef(null);
4319
4320
  const offlinePersistTimerRef = useRef(null);
4320
- const [connection, setConnection] = useState("live");
4321
- const connectionRef = useRef("live");
4321
+ const [connection, setConnection] = useState(startOffline ? "lost" : "live");
4322
+ const connectionRef = useRef(startOffline ? "lost" : "live");
4322
4323
  const [reconnectNonce, setReconnectNonce] = useState(0);
4323
4324
  const backoffRef = useRef(0);
4324
4325
  const attemptRef = useRef(0);
4325
4326
  const retryTimerRef = useRef(null);
4326
4327
  const activeSocketRef = useRef(null);
4327
- const manuallyOfflineRef = useRef(false);
4328
+ const manuallyOfflineRef = useRef(startOffline);
4328
4329
  const disconnectSeqRef = useRef(null);
4329
4330
  const manualDraftBankedRef = useRef(false);
4330
4331
  const manualDraftSnapshotRef = useRef(null);
4332
+ const offlineBaseBundleRef = useRef(null);
4331
4333
  const flushDoneRef = useRef(Promise.resolve());
4332
4334
  const maxRetries = opts.liveness?.maxRetries ?? 6;
4333
4335
  const livenessRef = useRef(opts.liveness);
@@ -4339,7 +4341,7 @@ function useCollab(opts) {
4339
4341
  attemptRef.current = 0;
4340
4342
  if (manuallyOfflineRef.current) {
4341
4343
  const currentDoc = docRef.current;
4342
- const currentBundle = connRef.current?.exportBundle(docId);
4344
+ const currentBundle = connRef.current?.exportBundle(docId) ?? offlineBaseBundleRef.current;
4343
4345
  const ids = currentDoc?.stableIds;
4344
4346
  manualDraftSnapshotRef.current = currentDoc && currentBundle && ids ? {
4345
4347
  ...currentBundle,
@@ -4469,6 +4471,51 @@ function useCollab(opts) {
4469
4471
  };
4470
4472
  useEffect(() => {
4471
4473
  clearDeadlines();
4474
+ if (startOffline && reconnectNonce === 0) {
4475
+ let disposed2 = false;
4476
+ if (!store) {
4477
+ setRefused("no-session");
4478
+ return;
4479
+ }
4480
+ void store.get(docId).then((bundle) => {
4481
+ if (disposed2) return;
4482
+ if (!bundle) {
4483
+ setRefused("no-session");
4484
+ return;
4485
+ }
4486
+ const replica = new ClientReplica(bundle.confirmedBytes, bundle.confirmedSidecar);
4487
+ for (const intent of bundle.pending) replica.submitLocal(intent);
4488
+ const offlineTail = bundle.offlineTail ?? [];
4489
+ let scope = null;
4490
+ for (const intent of offlineTail) {
4491
+ const result = applyIntentScoped(replica.doc, replica.ids, intent);
4492
+ if (!result.applied) continue;
4493
+ resyncScope(replica.doc, replica.ids, result);
4494
+ scope = scope ? unionScopes(scope, result) : result;
4495
+ }
4496
+ offlineBaseBundleRef.current = bundle;
4497
+ offlineTailRef.current = offlineTail.length ? [...offlineTail] : void 0;
4498
+ offlineEpochRef.current = bundle.offlineTailEpoch ?? bundle.genesisId;
4499
+ disconnectSeqRef.current = bundle.offlineBaseSeq ?? bundle.confirmedSeq;
4500
+ lastGenesisRef.current = bundle.genesisId;
4501
+ docRef.current = replica.doc;
4502
+ publishedDocRef.current = replica.doc;
4503
+ renderScopeRef.current = scope ?? { kind: "doc" };
4504
+ setDoc(replica.doc);
4505
+ setOfflineHeld(offlineTail.length);
4506
+ setReady(true);
4507
+ setVersion((value) => value + 1);
4508
+ setRenderVersion((value) => value + 1);
4509
+ connectionRef.current = "lost";
4510
+ setConnection("lost");
4511
+ }).catch(() => {
4512
+ if (!disposed2) setPersistErrors((count) => count + 1);
4513
+ });
4514
+ return () => {
4515
+ disposed2 = true;
4516
+ flushOfflinePersist();
4517
+ };
4518
+ }
4472
4519
  const socket = (createSocket ?? ((u) => new WebSocket(u)))(url);
4473
4520
  activeSocketRef.current = socket;
4474
4521
  let disposed = false;
@@ -4697,7 +4744,7 @@ function useCollab(opts) {
4697
4744
  connRef.current = null;
4698
4745
  if (activeSocketRef.current === socket) activeSocketRef.current = null;
4699
4746
  };
4700
- }, [url, docId, clientId, token, createSocket, store, takeover, docKey, shareCode, ownerToken, httpBase, reconnectNonce]);
4747
+ }, [url, docId, clientId, token, createSocket, store, takeover, docKey, shareCode, ownerToken, httpBase, reconnectNonce, startOffline]);
4701
4748
  useEffect(() => () => {
4702
4749
  if (retryTimerRef.current !== null) clearTimeout(retryTimerRef.current);
4703
4750
  retryTimerRef.current = null;