rita-workspace 0.5.45 → 0.5.47

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/index.d.mts CHANGED
@@ -160,7 +160,7 @@ interface WorkspaceContextValue {
160
160
  /** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
161
161
  * the user reordered (e.g. all root drawings, or all drawings in a folder). */
162
162
  reorderDrawings: (orderedIds: string[]) => Promise<void>;
163
- saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
163
+ saveCurrentDrawing: (expectedDrawingId: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
164
164
  saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
165
165
  refreshDrawings: () => Promise<void>;
166
166
  exportWorkspace: () => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -160,7 +160,7 @@ interface WorkspaceContextValue {
160
160
  /** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
161
161
  * the user reordered (e.g. all root drawings, or all drawings in a folder). */
162
162
  reorderDrawings: (orderedIds: string[]) => Promise<void>;
163
- saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
163
+ saveCurrentDrawing: (expectedDrawingId: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
164
164
  saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
165
165
  refreshDrawings: () => Promise<void>;
166
166
  exportWorkspace: () => Promise<void>;
package/dist/index.js CHANGED
@@ -431,6 +431,13 @@ function isLanguageSupported(langCode) {
431
431
  return lang in translations;
432
432
  }
433
433
 
434
+ // src/state/saveGuard.ts
435
+ function shouldAbortSaveDueToIdMismatch(expectedDrawingId, currentActiveDrawingId) {
436
+ if (!expectedDrawingId) return true;
437
+ if (!currentActiveDrawingId) return true;
438
+ return expectedDrawingId !== currentActiveDrawingId;
439
+ }
440
+
434
441
  // src/state/WorkspaceContext.tsx
435
442
  var import_jsx_runtime = require("react/jsx-runtime");
436
443
  warmDB();
@@ -991,12 +998,16 @@ function WorkspaceProvider({ children, lang = "en" }) {
991
998
  return null;
992
999
  }
993
1000
  }, [workspace]);
994
- const saveCurrentDrawing = (0, import_react.useCallback)(async (elements, appState, files) => {
995
- if (!activeDrawing) return;
996
- if (isDrawingOpenedEarlierInOtherTab(activeDrawing.id)) return;
1001
+ const saveCurrentDrawing = (0, import_react.useCallback)(async (expectedDrawingId, elements, appState, files) => {
1002
+ if (shouldAbortSaveDueToIdMismatch(expectedDrawingId, activeDrawingIdRef.current)) {
1003
+ return;
1004
+ }
1005
+ if (!activeDrawing || activeDrawing.id !== expectedDrawingId) return;
1006
+ if (isDrawingOpenedEarlierInOtherTab(expectedDrawingId)) return;
997
1007
  try {
998
- const fresh = await getDrawing(activeDrawing.id);
1008
+ const fresh = await getDrawing(expectedDrawingId);
999
1009
  if (fresh && fresh.updatedAt > (activeDrawing.updatedAt ?? 0)) return;
1010
+ if (shouldAbortSaveDueToIdMismatch(expectedDrawingId, activeDrawingIdRef.current)) return;
1000
1011
  if (Array.isArray(elements) && elements.length === 0 && fresh && Array.isArray(fresh.elements) && fresh.elements.length > 0) {
1001
1012
  return;
1002
1013
  }
@@ -1007,7 +1018,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
1007
1018
  if (files) {
1008
1019
  updateData.files = files;
1009
1020
  }
1010
- await updateDrawing(activeDrawing.id, updateData);
1021
+ await updateDrawing(expectedDrawingId, updateData);
1011
1022
  const now = Date.now();
1012
1023
  const patch = {
1013
1024
  elements,
@@ -1015,8 +1026,8 @@ function WorkspaceProvider({ children, lang = "en" }) {
1015
1026
  ...files ? { files } : {},
1016
1027
  updatedAt: now
1017
1028
  };
1018
- setDrawings((prev) => prev.map((d) => d.id === activeDrawing.id ? { ...d, ...patch } : d));
1019
- setActiveDrawing2((prev) => prev && prev.id === activeDrawing.id ? { ...prev, ...patch } : prev);
1029
+ setDrawings((prev) => prev.map((d) => d.id === expectedDrawingId ? { ...d, ...patch } : d));
1030
+ setActiveDrawing2((prev) => prev && prev.id === expectedDrawingId ? { ...prev, ...patch } : prev);
1020
1031
  } catch (err) {
1021
1032
  setError(err instanceof Error ? err.message : "Failed to save drawing");
1022
1033
  }
@@ -1754,11 +1765,7 @@ var DrawingsDialog = ({
1754
1765
  setSelectedId(null);
1755
1766
  }
1756
1767
  setIsRefreshing(true);
1757
- refreshDrawings().then(() => {
1758
- if (isFirstOpen) {
1759
- setExpandedFolders(new Set(foldersRef.current.map((f) => f.id)));
1760
- }
1761
- }).finally(() => setIsRefreshing(false));
1768
+ refreshDrawings().finally(() => setIsRefreshing(false));
1762
1769
  }
1763
1770
  prevOpenRef.current = open;
1764
1771
  }, [open, refreshDrawings]);
@@ -2839,12 +2846,14 @@ function useExcalidrawBridge({
2839
2846
  if (saveTimeoutRef.current) {
2840
2847
  clearTimeout(saveTimeoutRef.current);
2841
2848
  }
2849
+ const expectedId = activeDrawing?.id;
2850
+ if (!expectedId) return;
2842
2851
  saveTimeoutRef.current = setTimeout(async () => {
2843
2852
  const elements = excalidrawAPI.getSceneElements();
2844
2853
  const appState = excalidrawAPI.getAppState();
2845
- await saveCurrentDrawing(elements, appState);
2854
+ await saveCurrentDrawing(expectedId, elements, appState);
2846
2855
  }, autoSaveInterval);
2847
- }, [excalidrawAPI, saveCurrentDrawing, autoSaveInterval]);
2856
+ }, [excalidrawAPI, saveCurrentDrawing, autoSaveInterval, activeDrawing]);
2848
2857
  (0, import_react6.useEffect)(() => {
2849
2858
  return () => {
2850
2859
  if (saveTimeoutRef.current) {
@@ -2882,7 +2891,7 @@ function WorkspaceBridge({
2882
2891
  scrollY: appState.scrollY
2883
2892
  // Add other persistent properties as needed
2884
2893
  };
2885
- await saveCurrentDrawing(elements, persistentAppState, files);
2894
+ await saveCurrentDrawing(activeDrawing.id, elements, persistentAppState, files);
2886
2895
  onDrawingSave?.(activeDrawing.id);
2887
2896
  } catch (error) {
2888
2897
  console.error("[WorkspaceBridge] Failed to save drawing:", error);
package/dist/index.mjs CHANGED
@@ -359,6 +359,13 @@ function isLanguageSupported(langCode) {
359
359
  return lang in translations;
360
360
  }
361
361
 
362
+ // src/state/saveGuard.ts
363
+ function shouldAbortSaveDueToIdMismatch(expectedDrawingId, currentActiveDrawingId) {
364
+ if (!expectedDrawingId) return true;
365
+ if (!currentActiveDrawingId) return true;
366
+ return expectedDrawingId !== currentActiveDrawingId;
367
+ }
368
+
362
369
  // src/state/WorkspaceContext.tsx
363
370
  import { jsx } from "react/jsx-runtime";
364
371
  warmDB();
@@ -919,12 +926,16 @@ function WorkspaceProvider({ children, lang = "en" }) {
919
926
  return null;
920
927
  }
921
928
  }, [workspace]);
922
- const saveCurrentDrawing = useCallback(async (elements, appState, files) => {
923
- if (!activeDrawing) return;
924
- if (isDrawingOpenedEarlierInOtherTab(activeDrawing.id)) return;
929
+ const saveCurrentDrawing = useCallback(async (expectedDrawingId, elements, appState, files) => {
930
+ if (shouldAbortSaveDueToIdMismatch(expectedDrawingId, activeDrawingIdRef.current)) {
931
+ return;
932
+ }
933
+ if (!activeDrawing || activeDrawing.id !== expectedDrawingId) return;
934
+ if (isDrawingOpenedEarlierInOtherTab(expectedDrawingId)) return;
925
935
  try {
926
- const fresh = await getDrawing(activeDrawing.id);
936
+ const fresh = await getDrawing(expectedDrawingId);
927
937
  if (fresh && fresh.updatedAt > (activeDrawing.updatedAt ?? 0)) return;
938
+ if (shouldAbortSaveDueToIdMismatch(expectedDrawingId, activeDrawingIdRef.current)) return;
928
939
  if (Array.isArray(elements) && elements.length === 0 && fresh && Array.isArray(fresh.elements) && fresh.elements.length > 0) {
929
940
  return;
930
941
  }
@@ -935,7 +946,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
935
946
  if (files) {
936
947
  updateData.files = files;
937
948
  }
938
- await updateDrawing(activeDrawing.id, updateData);
949
+ await updateDrawing(expectedDrawingId, updateData);
939
950
  const now = Date.now();
940
951
  const patch = {
941
952
  elements,
@@ -943,8 +954,8 @@ function WorkspaceProvider({ children, lang = "en" }) {
943
954
  ...files ? { files } : {},
944
955
  updatedAt: now
945
956
  };
946
- setDrawings((prev) => prev.map((d) => d.id === activeDrawing.id ? { ...d, ...patch } : d));
947
- setActiveDrawing2((prev) => prev && prev.id === activeDrawing.id ? { ...prev, ...patch } : prev);
957
+ setDrawings((prev) => prev.map((d) => d.id === expectedDrawingId ? { ...d, ...patch } : d));
958
+ setActiveDrawing2((prev) => prev && prev.id === expectedDrawingId ? { ...prev, ...patch } : prev);
948
959
  } catch (err) {
949
960
  setError(err instanceof Error ? err.message : "Failed to save drawing");
950
961
  }
@@ -1682,11 +1693,7 @@ var DrawingsDialog = ({
1682
1693
  setSelectedId(null);
1683
1694
  }
1684
1695
  setIsRefreshing(true);
1685
- refreshDrawings().then(() => {
1686
- if (isFirstOpen) {
1687
- setExpandedFolders(new Set(foldersRef.current.map((f) => f.id)));
1688
- }
1689
- }).finally(() => setIsRefreshing(false));
1696
+ refreshDrawings().finally(() => setIsRefreshing(false));
1690
1697
  }
1691
1698
  prevOpenRef.current = open;
1692
1699
  }, [open, refreshDrawings]);
@@ -2767,12 +2774,14 @@ function useExcalidrawBridge({
2767
2774
  if (saveTimeoutRef.current) {
2768
2775
  clearTimeout(saveTimeoutRef.current);
2769
2776
  }
2777
+ const expectedId = activeDrawing?.id;
2778
+ if (!expectedId) return;
2770
2779
  saveTimeoutRef.current = setTimeout(async () => {
2771
2780
  const elements = excalidrawAPI.getSceneElements();
2772
2781
  const appState = excalidrawAPI.getAppState();
2773
- await saveCurrentDrawing(elements, appState);
2782
+ await saveCurrentDrawing(expectedId, elements, appState);
2774
2783
  }, autoSaveInterval);
2775
- }, [excalidrawAPI, saveCurrentDrawing, autoSaveInterval]);
2784
+ }, [excalidrawAPI, saveCurrentDrawing, autoSaveInterval, activeDrawing]);
2776
2785
  useEffect4(() => {
2777
2786
  return () => {
2778
2787
  if (saveTimeoutRef.current) {
@@ -2810,7 +2819,7 @@ function WorkspaceBridge({
2810
2819
  scrollY: appState.scrollY
2811
2820
  // Add other persistent properties as needed
2812
2821
  };
2813
- await saveCurrentDrawing(elements, persistentAppState, files);
2822
+ await saveCurrentDrawing(activeDrawing.id, elements, persistentAppState, files);
2814
2823
  onDrawingSave?.(activeDrawing.id);
2815
2824
  } catch (error) {
2816
2825
  console.error("[WorkspaceBridge] Failed to save drawing:", error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rita-workspace",
3
- "version": "0.5.45",
3
+ "version": "0.5.47",
4
4
  "description": "Multi-drawing workspace feature for Rita (Excalidraw fork)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",