rita-workspace 0.4.7 → 0.5.0
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 +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +132 -15
- package/dist/index.mjs +145 -28
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -323,12 +323,115 @@ function useWorkspaceLang() {
|
|
|
323
323
|
}
|
|
324
324
|
return { lang: context.lang, t: context.t };
|
|
325
325
|
}
|
|
326
|
+
var TAB_ID = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
327
|
+
var TABS_KEY = "rita-workspace-tabs";
|
|
328
|
+
var TAB_CHANNEL = "rita-workspace-tabs";
|
|
329
|
+
function getTabsMap() {
|
|
330
|
+
try {
|
|
331
|
+
const raw = JSON.parse(localStorage.getItem(TABS_KEY) || "{}");
|
|
332
|
+
const result = {};
|
|
333
|
+
for (const [tabId, value] of Object.entries(raw)) {
|
|
334
|
+
if (typeof value === "string") {
|
|
335
|
+
result[tabId] = { drawingId: value, openedAt: 0 };
|
|
336
|
+
} else if (value && typeof value === "object" && "drawingId" in value) {
|
|
337
|
+
result[tabId] = value;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return result;
|
|
341
|
+
} catch {
|
|
342
|
+
return {};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function setTabDrawing(drawingId) {
|
|
346
|
+
const tabs = getTabsMap();
|
|
347
|
+
if (drawingId) {
|
|
348
|
+
const existing = tabs[TAB_ID];
|
|
349
|
+
if (existing && existing.drawingId === drawingId) {
|
|
350
|
+
} else {
|
|
351
|
+
tabs[TAB_ID] = { drawingId, openedAt: Date.now() };
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
delete tabs[TAB_ID];
|
|
355
|
+
}
|
|
356
|
+
localStorage.setItem(TABS_KEY, JSON.stringify(tabs));
|
|
357
|
+
}
|
|
358
|
+
function isDrawingOpenedEarlierInOtherTab(drawingId) {
|
|
359
|
+
const tabs = getTabsMap();
|
|
360
|
+
const myEntry = tabs[TAB_ID];
|
|
361
|
+
if (!myEntry) return false;
|
|
362
|
+
const myOpenedAt = myEntry.openedAt;
|
|
363
|
+
return Object.entries(tabs).some(
|
|
364
|
+
([tabId, entry]) => tabId !== TAB_ID && entry.drawingId === drawingId && entry.openedAt <= myOpenedAt
|
|
365
|
+
);
|
|
366
|
+
}
|
|
326
367
|
function WorkspaceProvider({ children, lang = "en" }) {
|
|
327
368
|
const [workspace, setWorkspace] = (0, import_react.useState)(null);
|
|
328
369
|
const [drawings, setDrawings] = (0, import_react.useState)([]);
|
|
329
370
|
const [activeDrawing, setActiveDrawing2] = (0, import_react.useState)(null);
|
|
330
371
|
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
331
372
|
const [error, setError] = (0, import_react.useState)(null);
|
|
373
|
+
const [isDrawingConflict, setIsDrawingConflict] = (0, import_react.useState)(false);
|
|
374
|
+
const prevConflictRef = (0, import_react.useRef)(false);
|
|
375
|
+
(0, import_react.useEffect)(() => {
|
|
376
|
+
if (prevConflictRef.current && !isDrawingConflict && activeDrawing?.id) {
|
|
377
|
+
getDrawing(activeDrawing.id).then((fresh) => {
|
|
378
|
+
if (fresh) {
|
|
379
|
+
setActiveDrawing2(fresh);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
prevConflictRef.current = isDrawingConflict;
|
|
384
|
+
}, [isDrawingConflict, activeDrawing?.id]);
|
|
385
|
+
(0, import_react.useEffect)(() => {
|
|
386
|
+
const drawingId = activeDrawing?.id || null;
|
|
387
|
+
setTabDrawing(drawingId);
|
|
388
|
+
if (drawingId) {
|
|
389
|
+
setIsDrawingConflict(isDrawingOpenedEarlierInOtherTab(drawingId));
|
|
390
|
+
} else {
|
|
391
|
+
setIsDrawingConflict(false);
|
|
392
|
+
}
|
|
393
|
+
const recheckConflict = () => {
|
|
394
|
+
if (drawingId) {
|
|
395
|
+
setIsDrawingConflict(isDrawingOpenedEarlierInOtherTab(drawingId));
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
let channel = null;
|
|
399
|
+
try {
|
|
400
|
+
channel = new BroadcastChannel(TAB_CHANNEL);
|
|
401
|
+
channel.postMessage({ type: "drawing-changed", tabId: TAB_ID, drawingId });
|
|
402
|
+
channel.onmessage = (event) => {
|
|
403
|
+
if (event.data?.tabId !== TAB_ID) {
|
|
404
|
+
recheckConflict();
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
} catch {
|
|
408
|
+
}
|
|
409
|
+
const onStorage = (e) => {
|
|
410
|
+
if (e.key === TABS_KEY) {
|
|
411
|
+
recheckConflict();
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
window.addEventListener("storage", onStorage);
|
|
415
|
+
return () => {
|
|
416
|
+
channel?.close();
|
|
417
|
+
window.removeEventListener("storage", onStorage);
|
|
418
|
+
};
|
|
419
|
+
}, [activeDrawing?.id]);
|
|
420
|
+
(0, import_react.useEffect)(() => {
|
|
421
|
+
const onUnload = () => {
|
|
422
|
+
const tabs = getTabsMap();
|
|
423
|
+
delete tabs[TAB_ID];
|
|
424
|
+
localStorage.setItem(TABS_KEY, JSON.stringify(tabs));
|
|
425
|
+
try {
|
|
426
|
+
const channel = new BroadcastChannel(TAB_CHANNEL);
|
|
427
|
+
channel.postMessage({ type: "tab-closed", tabId: TAB_ID });
|
|
428
|
+
channel.close();
|
|
429
|
+
} catch {
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
window.addEventListener("beforeunload", onUnload);
|
|
433
|
+
return () => window.removeEventListener("beforeunload", onUnload);
|
|
434
|
+
}, []);
|
|
332
435
|
const t = getTranslations(lang);
|
|
333
436
|
(0, import_react.useEffect)(() => {
|
|
334
437
|
async function init() {
|
|
@@ -339,9 +442,23 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
339
442
|
const allDrawings = await getAllDrawings();
|
|
340
443
|
const wsDrawings = allDrawings.filter((d) => ws.drawingIds.includes(d.id));
|
|
341
444
|
setDrawings(wsDrawings);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
445
|
+
const lastDrawingId = sessionStorage.getItem("rita-workspace-tab-drawing");
|
|
446
|
+
let active = null;
|
|
447
|
+
if (lastDrawingId) {
|
|
448
|
+
active = wsDrawings.find((d) => d.id === lastDrawingId) || null;
|
|
449
|
+
if (!active) {
|
|
450
|
+
const fromDb = await getDrawing(lastDrawingId);
|
|
451
|
+
if (fromDb && ws.drawingIds.includes(fromDb.id)) {
|
|
452
|
+
active = fromDb;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
if (!active && wsDrawings.length > 0) {
|
|
457
|
+
active = wsDrawings[0];
|
|
458
|
+
}
|
|
459
|
+
if (active) {
|
|
460
|
+
setActiveDrawing2(active);
|
|
461
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", active.id);
|
|
345
462
|
}
|
|
346
463
|
} catch (err) {
|
|
347
464
|
setError(err instanceof Error ? err.message : "Failed to load workspace");
|
|
@@ -357,10 +474,6 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
357
474
|
const allDrawings = await getAllDrawings();
|
|
358
475
|
const wsDrawings = allDrawings.filter((d) => workspace.drawingIds.includes(d.id));
|
|
359
476
|
setDrawings(wsDrawings);
|
|
360
|
-
if (workspace.activeDrawingId) {
|
|
361
|
-
const active = await getDrawing(workspace.activeDrawingId);
|
|
362
|
-
if (active) setActiveDrawing2(active);
|
|
363
|
-
}
|
|
364
477
|
} catch (err) {
|
|
365
478
|
}
|
|
366
479
|
}, [workspace]);
|
|
@@ -370,7 +483,6 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
370
483
|
const defaultName = `${t.newDrawing} ${drawings.length + 1}`;
|
|
371
484
|
const drawing = await createDrawing(name || defaultName);
|
|
372
485
|
await addDrawingToWorkspace(workspace.id, drawing.id);
|
|
373
|
-
await setActiveDrawing(workspace.id, drawing.id);
|
|
374
486
|
setDrawings((prev) => [...prev, drawing]);
|
|
375
487
|
setActiveDrawing2(drawing);
|
|
376
488
|
setWorkspace((prev) => prev ? {
|
|
@@ -378,6 +490,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
378
490
|
drawingIds: [...prev.drawingIds, drawing.id],
|
|
379
491
|
activeDrawingId: drawing.id
|
|
380
492
|
} : null);
|
|
493
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", drawing.id);
|
|
381
494
|
return drawing;
|
|
382
495
|
} catch (err) {
|
|
383
496
|
setError(err instanceof Error ? err.message : "Failed to create drawing");
|
|
@@ -389,9 +502,9 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
389
502
|
try {
|
|
390
503
|
const drawing = await getDrawing(id);
|
|
391
504
|
if (drawing) {
|
|
392
|
-
await setActiveDrawing(workspace.id, id);
|
|
393
505
|
setActiveDrawing2(drawing);
|
|
394
506
|
setWorkspace((prev) => prev ? { ...prev, activeDrawingId: id } : null);
|
|
507
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", id);
|
|
395
508
|
}
|
|
396
509
|
} catch (err) {
|
|
397
510
|
setError(err instanceof Error ? err.message : "Failed to switch drawing");
|
|
@@ -607,6 +720,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
607
720
|
activeDrawing,
|
|
608
721
|
isLoading,
|
|
609
722
|
error,
|
|
723
|
+
isDrawingConflict,
|
|
610
724
|
lang,
|
|
611
725
|
t,
|
|
612
726
|
createNewDrawing,
|
|
@@ -988,11 +1102,15 @@ var DrawingsDialog = ({
|
|
|
988
1102
|
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
989
1103
|
const dragRef = (0, import_react5.useRef)(null);
|
|
990
1104
|
const dialogRef = (0, import_react5.useRef)(null);
|
|
1105
|
+
const prevOpenRef = (0, import_react5.useRef)(false);
|
|
991
1106
|
(0, import_react5.useEffect)(() => {
|
|
992
1107
|
if (open) {
|
|
993
1108
|
refreshDrawings();
|
|
994
|
-
|
|
1109
|
+
if (!prevOpenRef.current) {
|
|
1110
|
+
setPosition(null);
|
|
1111
|
+
}
|
|
995
1112
|
}
|
|
1113
|
+
prevOpenRef.current = open;
|
|
996
1114
|
}, [open, refreshDrawings]);
|
|
997
1115
|
const handleMouseDown = (0, import_react5.useCallback)((e) => {
|
|
998
1116
|
if (e.target.closest("button")) return;
|
|
@@ -1099,17 +1217,16 @@ var DrawingsDialog = ({
|
|
|
1099
1217
|
left: 0,
|
|
1100
1218
|
right: 0,
|
|
1101
1219
|
bottom: 0,
|
|
1102
|
-
backgroundColor:
|
|
1220
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
1103
1221
|
display: position ? "block" : "flex",
|
|
1104
1222
|
alignItems: "center",
|
|
1105
1223
|
justifyContent: "center",
|
|
1106
|
-
zIndex: 9999
|
|
1107
|
-
pointerEvents: position ? "none" : "auto"
|
|
1224
|
+
zIndex: 9999
|
|
1108
1225
|
},
|
|
1109
1226
|
onClick: (e) => {
|
|
1110
|
-
if (
|
|
1227
|
+
if (e.target === e.currentTarget) onClose();
|
|
1111
1228
|
},
|
|
1112
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: dialogRef, className: "rita-workspace-dialog", style:
|
|
1229
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: dialogRef, className: "rita-workspace-dialog", style: dialogStyle, children: [
|
|
1113
1230
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1114
1231
|
"div",
|
|
1115
1232
|
{
|
package/dist/index.mjs
CHANGED
|
@@ -145,7 +145,7 @@ async function setActiveDrawing(workspaceId, drawingId) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
// src/state/WorkspaceContext.tsx
|
|
148
|
-
import { createContext, useContext, useEffect, useState, useCallback } from "react";
|
|
148
|
+
import { createContext, useContext, useEffect, useRef, useState, useCallback } from "react";
|
|
149
149
|
|
|
150
150
|
// src/i18n/translations.ts
|
|
151
151
|
var sv = {
|
|
@@ -261,12 +261,115 @@ function useWorkspaceLang() {
|
|
|
261
261
|
}
|
|
262
262
|
return { lang: context.lang, t: context.t };
|
|
263
263
|
}
|
|
264
|
+
var TAB_ID = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
265
|
+
var TABS_KEY = "rita-workspace-tabs";
|
|
266
|
+
var TAB_CHANNEL = "rita-workspace-tabs";
|
|
267
|
+
function getTabsMap() {
|
|
268
|
+
try {
|
|
269
|
+
const raw = JSON.parse(localStorage.getItem(TABS_KEY) || "{}");
|
|
270
|
+
const result = {};
|
|
271
|
+
for (const [tabId, value] of Object.entries(raw)) {
|
|
272
|
+
if (typeof value === "string") {
|
|
273
|
+
result[tabId] = { drawingId: value, openedAt: 0 };
|
|
274
|
+
} else if (value && typeof value === "object" && "drawingId" in value) {
|
|
275
|
+
result[tabId] = value;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
} catch {
|
|
280
|
+
return {};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function setTabDrawing(drawingId) {
|
|
284
|
+
const tabs = getTabsMap();
|
|
285
|
+
if (drawingId) {
|
|
286
|
+
const existing = tabs[TAB_ID];
|
|
287
|
+
if (existing && existing.drawingId === drawingId) {
|
|
288
|
+
} else {
|
|
289
|
+
tabs[TAB_ID] = { drawingId, openedAt: Date.now() };
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
delete tabs[TAB_ID];
|
|
293
|
+
}
|
|
294
|
+
localStorage.setItem(TABS_KEY, JSON.stringify(tabs));
|
|
295
|
+
}
|
|
296
|
+
function isDrawingOpenedEarlierInOtherTab(drawingId) {
|
|
297
|
+
const tabs = getTabsMap();
|
|
298
|
+
const myEntry = tabs[TAB_ID];
|
|
299
|
+
if (!myEntry) return false;
|
|
300
|
+
const myOpenedAt = myEntry.openedAt;
|
|
301
|
+
return Object.entries(tabs).some(
|
|
302
|
+
([tabId, entry]) => tabId !== TAB_ID && entry.drawingId === drawingId && entry.openedAt <= myOpenedAt
|
|
303
|
+
);
|
|
304
|
+
}
|
|
264
305
|
function WorkspaceProvider({ children, lang = "en" }) {
|
|
265
306
|
const [workspace, setWorkspace] = useState(null);
|
|
266
307
|
const [drawings, setDrawings] = useState([]);
|
|
267
308
|
const [activeDrawing, setActiveDrawing2] = useState(null);
|
|
268
309
|
const [isLoading, setIsLoading] = useState(true);
|
|
269
310
|
const [error, setError] = useState(null);
|
|
311
|
+
const [isDrawingConflict, setIsDrawingConflict] = useState(false);
|
|
312
|
+
const prevConflictRef = useRef(false);
|
|
313
|
+
useEffect(() => {
|
|
314
|
+
if (prevConflictRef.current && !isDrawingConflict && activeDrawing?.id) {
|
|
315
|
+
getDrawing(activeDrawing.id).then((fresh) => {
|
|
316
|
+
if (fresh) {
|
|
317
|
+
setActiveDrawing2(fresh);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
prevConflictRef.current = isDrawingConflict;
|
|
322
|
+
}, [isDrawingConflict, activeDrawing?.id]);
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
const drawingId = activeDrawing?.id || null;
|
|
325
|
+
setTabDrawing(drawingId);
|
|
326
|
+
if (drawingId) {
|
|
327
|
+
setIsDrawingConflict(isDrawingOpenedEarlierInOtherTab(drawingId));
|
|
328
|
+
} else {
|
|
329
|
+
setIsDrawingConflict(false);
|
|
330
|
+
}
|
|
331
|
+
const recheckConflict = () => {
|
|
332
|
+
if (drawingId) {
|
|
333
|
+
setIsDrawingConflict(isDrawingOpenedEarlierInOtherTab(drawingId));
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
let channel = null;
|
|
337
|
+
try {
|
|
338
|
+
channel = new BroadcastChannel(TAB_CHANNEL);
|
|
339
|
+
channel.postMessage({ type: "drawing-changed", tabId: TAB_ID, drawingId });
|
|
340
|
+
channel.onmessage = (event) => {
|
|
341
|
+
if (event.data?.tabId !== TAB_ID) {
|
|
342
|
+
recheckConflict();
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
} catch {
|
|
346
|
+
}
|
|
347
|
+
const onStorage = (e) => {
|
|
348
|
+
if (e.key === TABS_KEY) {
|
|
349
|
+
recheckConflict();
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
window.addEventListener("storage", onStorage);
|
|
353
|
+
return () => {
|
|
354
|
+
channel?.close();
|
|
355
|
+
window.removeEventListener("storage", onStorage);
|
|
356
|
+
};
|
|
357
|
+
}, [activeDrawing?.id]);
|
|
358
|
+
useEffect(() => {
|
|
359
|
+
const onUnload = () => {
|
|
360
|
+
const tabs = getTabsMap();
|
|
361
|
+
delete tabs[TAB_ID];
|
|
362
|
+
localStorage.setItem(TABS_KEY, JSON.stringify(tabs));
|
|
363
|
+
try {
|
|
364
|
+
const channel = new BroadcastChannel(TAB_CHANNEL);
|
|
365
|
+
channel.postMessage({ type: "tab-closed", tabId: TAB_ID });
|
|
366
|
+
channel.close();
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
window.addEventListener("beforeunload", onUnload);
|
|
371
|
+
return () => window.removeEventListener("beforeunload", onUnload);
|
|
372
|
+
}, []);
|
|
270
373
|
const t = getTranslations(lang);
|
|
271
374
|
useEffect(() => {
|
|
272
375
|
async function init() {
|
|
@@ -277,9 +380,23 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
277
380
|
const allDrawings = await getAllDrawings();
|
|
278
381
|
const wsDrawings = allDrawings.filter((d) => ws.drawingIds.includes(d.id));
|
|
279
382
|
setDrawings(wsDrawings);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
383
|
+
const lastDrawingId = sessionStorage.getItem("rita-workspace-tab-drawing");
|
|
384
|
+
let active = null;
|
|
385
|
+
if (lastDrawingId) {
|
|
386
|
+
active = wsDrawings.find((d) => d.id === lastDrawingId) || null;
|
|
387
|
+
if (!active) {
|
|
388
|
+
const fromDb = await getDrawing(lastDrawingId);
|
|
389
|
+
if (fromDb && ws.drawingIds.includes(fromDb.id)) {
|
|
390
|
+
active = fromDb;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (!active && wsDrawings.length > 0) {
|
|
395
|
+
active = wsDrawings[0];
|
|
396
|
+
}
|
|
397
|
+
if (active) {
|
|
398
|
+
setActiveDrawing2(active);
|
|
399
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", active.id);
|
|
283
400
|
}
|
|
284
401
|
} catch (err) {
|
|
285
402
|
setError(err instanceof Error ? err.message : "Failed to load workspace");
|
|
@@ -295,10 +412,6 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
295
412
|
const allDrawings = await getAllDrawings();
|
|
296
413
|
const wsDrawings = allDrawings.filter((d) => workspace.drawingIds.includes(d.id));
|
|
297
414
|
setDrawings(wsDrawings);
|
|
298
|
-
if (workspace.activeDrawingId) {
|
|
299
|
-
const active = await getDrawing(workspace.activeDrawingId);
|
|
300
|
-
if (active) setActiveDrawing2(active);
|
|
301
|
-
}
|
|
302
415
|
} catch (err) {
|
|
303
416
|
}
|
|
304
417
|
}, [workspace]);
|
|
@@ -308,7 +421,6 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
308
421
|
const defaultName = `${t.newDrawing} ${drawings.length + 1}`;
|
|
309
422
|
const drawing = await createDrawing(name || defaultName);
|
|
310
423
|
await addDrawingToWorkspace(workspace.id, drawing.id);
|
|
311
|
-
await setActiveDrawing(workspace.id, drawing.id);
|
|
312
424
|
setDrawings((prev) => [...prev, drawing]);
|
|
313
425
|
setActiveDrawing2(drawing);
|
|
314
426
|
setWorkspace((prev) => prev ? {
|
|
@@ -316,6 +428,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
316
428
|
drawingIds: [...prev.drawingIds, drawing.id],
|
|
317
429
|
activeDrawingId: drawing.id
|
|
318
430
|
} : null);
|
|
431
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", drawing.id);
|
|
319
432
|
return drawing;
|
|
320
433
|
} catch (err) {
|
|
321
434
|
setError(err instanceof Error ? err.message : "Failed to create drawing");
|
|
@@ -327,9 +440,9 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
327
440
|
try {
|
|
328
441
|
const drawing = await getDrawing(id);
|
|
329
442
|
if (drawing) {
|
|
330
|
-
await setActiveDrawing(workspace.id, id);
|
|
331
443
|
setActiveDrawing2(drawing);
|
|
332
444
|
setWorkspace((prev) => prev ? { ...prev, activeDrawingId: id } : null);
|
|
445
|
+
sessionStorage.setItem("rita-workspace-tab-drawing", id);
|
|
333
446
|
}
|
|
334
447
|
} catch (err) {
|
|
335
448
|
setError(err instanceof Error ? err.message : "Failed to switch drawing");
|
|
@@ -545,6 +658,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
545
658
|
activeDrawing,
|
|
546
659
|
isLoading,
|
|
547
660
|
error,
|
|
661
|
+
isDrawingConflict,
|
|
548
662
|
lang,
|
|
549
663
|
t,
|
|
550
664
|
createNewDrawing,
|
|
@@ -567,7 +681,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
567
681
|
import { useState as useState3 } from "react";
|
|
568
682
|
|
|
569
683
|
// src/ui/DrawingList/DrawingListItem.tsx
|
|
570
|
-
import { useState as useState2, useRef, useEffect as useEffect2 } from "react";
|
|
684
|
+
import { useState as useState2, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
571
685
|
|
|
572
686
|
// src/ui/DrawingList/DrawingList.module.css
|
|
573
687
|
var DrawingList_default = {};
|
|
@@ -584,7 +698,7 @@ function DrawingListItem({
|
|
|
584
698
|
}) {
|
|
585
699
|
const [isEditing, setIsEditing] = useState2(false);
|
|
586
700
|
const [editName, setEditName] = useState2(drawing.name);
|
|
587
|
-
const inputRef =
|
|
701
|
+
const inputRef = useRef2(null);
|
|
588
702
|
useEffect2(() => {
|
|
589
703
|
if (isEditing && inputRef.current) {
|
|
590
704
|
inputRef.current.focus();
|
|
@@ -867,7 +981,7 @@ var WorkspaceMenuItems = ({
|
|
|
867
981
|
};
|
|
868
982
|
|
|
869
983
|
// src/ui/Dialog/DrawingsDialog.tsx
|
|
870
|
-
import { useState as useState4, useCallback as useCallback2, useRef as
|
|
984
|
+
import { useState as useState4, useCallback as useCallback2, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
871
985
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
872
986
|
var ActionButton = ({ icon, label, description, onClick, primary }) => /* @__PURE__ */ jsxs4(
|
|
873
987
|
"button",
|
|
@@ -924,13 +1038,17 @@ var DrawingsDialog = ({
|
|
|
924
1038
|
const [editName, setEditName] = useState4("");
|
|
925
1039
|
const [confirmDeleteId, setConfirmDeleteId] = useState4(null);
|
|
926
1040
|
const [position, setPosition] = useState4(null);
|
|
927
|
-
const dragRef =
|
|
928
|
-
const dialogRef =
|
|
1041
|
+
const dragRef = useRef3(null);
|
|
1042
|
+
const dialogRef = useRef3(null);
|
|
1043
|
+
const prevOpenRef = useRef3(false);
|
|
929
1044
|
useEffect3(() => {
|
|
930
1045
|
if (open) {
|
|
931
1046
|
refreshDrawings();
|
|
932
|
-
|
|
1047
|
+
if (!prevOpenRef.current) {
|
|
1048
|
+
setPosition(null);
|
|
1049
|
+
}
|
|
933
1050
|
}
|
|
1051
|
+
prevOpenRef.current = open;
|
|
934
1052
|
}, [open, refreshDrawings]);
|
|
935
1053
|
const handleMouseDown = useCallback2((e) => {
|
|
936
1054
|
if (e.target.closest("button")) return;
|
|
@@ -1037,17 +1155,16 @@ var DrawingsDialog = ({
|
|
|
1037
1155
|
left: 0,
|
|
1038
1156
|
right: 0,
|
|
1039
1157
|
bottom: 0,
|
|
1040
|
-
backgroundColor:
|
|
1158
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
1041
1159
|
display: position ? "block" : "flex",
|
|
1042
1160
|
alignItems: "center",
|
|
1043
1161
|
justifyContent: "center",
|
|
1044
|
-
zIndex: 9999
|
|
1045
|
-
pointerEvents: position ? "none" : "auto"
|
|
1162
|
+
zIndex: 9999
|
|
1046
1163
|
},
|
|
1047
1164
|
onClick: (e) => {
|
|
1048
|
-
if (
|
|
1165
|
+
if (e.target === e.currentTarget) onClose();
|
|
1049
1166
|
},
|
|
1050
|
-
children: /* @__PURE__ */ jsxs4("div", { ref: dialogRef, className: "rita-workspace-dialog", style:
|
|
1167
|
+
children: /* @__PURE__ */ jsxs4("div", { ref: dialogRef, className: "rita-workspace-dialog", style: dialogStyle, children: [
|
|
1051
1168
|
/* @__PURE__ */ jsxs4(
|
|
1052
1169
|
"div",
|
|
1053
1170
|
{
|
|
@@ -1311,14 +1428,14 @@ var DrawingsDialog = ({
|
|
|
1311
1428
|
};
|
|
1312
1429
|
|
|
1313
1430
|
// src/integration/useExcalidrawBridge.ts
|
|
1314
|
-
import { useEffect as useEffect4, useRef as
|
|
1431
|
+
import { useEffect as useEffect4, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
1315
1432
|
function useExcalidrawBridge({
|
|
1316
1433
|
excalidrawAPI,
|
|
1317
1434
|
autoSaveInterval = 2e3
|
|
1318
1435
|
}) {
|
|
1319
1436
|
const { activeDrawing, saveCurrentDrawing } = useWorkspace();
|
|
1320
|
-
const saveTimeoutRef =
|
|
1321
|
-
const lastDrawingIdRef =
|
|
1437
|
+
const saveTimeoutRef = useRef4(null);
|
|
1438
|
+
const lastDrawingIdRef = useRef4(null);
|
|
1322
1439
|
useEffect4(() => {
|
|
1323
1440
|
if (!excalidrawAPI || !activeDrawing) return;
|
|
1324
1441
|
if (lastDrawingIdRef.current === activeDrawing.id) return;
|
|
@@ -1352,7 +1469,7 @@ function useExcalidrawBridge({
|
|
|
1352
1469
|
}
|
|
1353
1470
|
|
|
1354
1471
|
// src/integration/WorkspaceBridge.tsx
|
|
1355
|
-
import { useEffect as useEffect5, useRef as
|
|
1472
|
+
import { useEffect as useEffect5, useRef as useRef5, useCallback as useCallback4 } from "react";
|
|
1356
1473
|
function WorkspaceBridge({
|
|
1357
1474
|
excalidrawAPI,
|
|
1358
1475
|
autoSaveInterval = 2e3,
|
|
@@ -1360,9 +1477,9 @@ function WorkspaceBridge({
|
|
|
1360
1477
|
onDrawingSave
|
|
1361
1478
|
}) {
|
|
1362
1479
|
const { activeDrawing, saveCurrentDrawing } = useWorkspace();
|
|
1363
|
-
const lastDrawingIdRef =
|
|
1364
|
-
const saveTimeoutRef =
|
|
1365
|
-
const isLoadingRef =
|
|
1480
|
+
const lastDrawingIdRef = useRef5(null);
|
|
1481
|
+
const saveTimeoutRef = useRef5(null);
|
|
1482
|
+
const isLoadingRef = useRef5(false);
|
|
1366
1483
|
const saveDrawing = useCallback4(async () => {
|
|
1367
1484
|
if (!excalidrawAPI || !activeDrawing || isLoadingRef.current) return;
|
|
1368
1485
|
try {
|