rita-workspace 0.5.33 → 0.5.35
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 +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +156 -6
- package/dist/index.mjs +155 -6
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,8 @@ interface Drawing {
|
|
|
6
6
|
id: string;
|
|
7
7
|
name: string;
|
|
8
8
|
folderId?: string | null;
|
|
9
|
+
/** Manual sort position. Lower = earlier in list. Falls back to createdAt when unset. */
|
|
10
|
+
position?: number;
|
|
9
11
|
elements: unknown[];
|
|
10
12
|
appState: Record<string, unknown>;
|
|
11
13
|
files: Record<string, unknown>;
|
|
@@ -64,6 +66,12 @@ declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' |
|
|
|
64
66
|
declare function deleteDrawing(id: string): Promise<boolean>;
|
|
65
67
|
declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
|
|
66
68
|
declare function moveDrawingToFolder(drawingId: string, folderId: string | null): Promise<Drawing | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* Re-number `position` for the given drawing IDs in the order provided (0..N-1).
|
|
71
|
+
* Drawings not in `orderedIds` are left untouched (caller should pass the full
|
|
72
|
+
* sorted slice that the user reordered, e.g. all root drawings or all in a folder).
|
|
73
|
+
*/
|
|
74
|
+
declare function reorderDrawings(orderedIds: string[]): Promise<void>;
|
|
67
75
|
|
|
68
76
|
declare function createFolder(name: string): Promise<Folder>;
|
|
69
77
|
declare function getFolder(id: string): Promise<Folder | undefined>;
|
|
@@ -123,6 +131,8 @@ interface Translations {
|
|
|
123
131
|
newFolderName: string;
|
|
124
132
|
backupReminder: string;
|
|
125
133
|
days: string;
|
|
134
|
+
autoStartLabel: string;
|
|
135
|
+
autoStartDesc: string;
|
|
126
136
|
shortcutNewDrawing: string;
|
|
127
137
|
}
|
|
128
138
|
declare function getTranslations(langCode?: string): Translations;
|
|
@@ -147,6 +157,9 @@ interface WorkspaceContextValue {
|
|
|
147
157
|
renameFolder: (id: string, name: string) => Promise<void>;
|
|
148
158
|
deleteFolder: (id: string) => Promise<void>;
|
|
149
159
|
moveDrawingToFolder: (drawingId: string, folderId: string | null) => Promise<void>;
|
|
160
|
+
/** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
|
|
161
|
+
* the user reordered (e.g. all root drawings, or all drawings in a folder). */
|
|
162
|
+
reorderDrawings: (orderedIds: string[]) => Promise<void>;
|
|
150
163
|
saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
|
|
151
164
|
saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
|
|
152
165
|
refreshDrawings: () => Promise<void>;
|
|
@@ -388,4 +401,4 @@ interface WorkspacePluginProps {
|
|
|
388
401
|
*/
|
|
389
402
|
declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
|
|
390
403
|
|
|
391
|
-
export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
|
|
404
|
+
export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, reorderDrawings, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ interface Drawing {
|
|
|
6
6
|
id: string;
|
|
7
7
|
name: string;
|
|
8
8
|
folderId?: string | null;
|
|
9
|
+
/** Manual sort position. Lower = earlier in list. Falls back to createdAt when unset. */
|
|
10
|
+
position?: number;
|
|
9
11
|
elements: unknown[];
|
|
10
12
|
appState: Record<string, unknown>;
|
|
11
13
|
files: Record<string, unknown>;
|
|
@@ -64,6 +66,12 @@ declare function updateDrawing(id: string, updates: Partial<Omit<Drawing, 'id' |
|
|
|
64
66
|
declare function deleteDrawing(id: string): Promise<boolean>;
|
|
65
67
|
declare function duplicateDrawing(id: string, newName?: string): Promise<Drawing | undefined>;
|
|
66
68
|
declare function moveDrawingToFolder(drawingId: string, folderId: string | null): Promise<Drawing | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* Re-number `position` for the given drawing IDs in the order provided (0..N-1).
|
|
71
|
+
* Drawings not in `orderedIds` are left untouched (caller should pass the full
|
|
72
|
+
* sorted slice that the user reordered, e.g. all root drawings or all in a folder).
|
|
73
|
+
*/
|
|
74
|
+
declare function reorderDrawings(orderedIds: string[]): Promise<void>;
|
|
67
75
|
|
|
68
76
|
declare function createFolder(name: string): Promise<Folder>;
|
|
69
77
|
declare function getFolder(id: string): Promise<Folder | undefined>;
|
|
@@ -123,6 +131,8 @@ interface Translations {
|
|
|
123
131
|
newFolderName: string;
|
|
124
132
|
backupReminder: string;
|
|
125
133
|
days: string;
|
|
134
|
+
autoStartLabel: string;
|
|
135
|
+
autoStartDesc: string;
|
|
126
136
|
shortcutNewDrawing: string;
|
|
127
137
|
}
|
|
128
138
|
declare function getTranslations(langCode?: string): Translations;
|
|
@@ -147,6 +157,9 @@ interface WorkspaceContextValue {
|
|
|
147
157
|
renameFolder: (id: string, name: string) => Promise<void>;
|
|
148
158
|
deleteFolder: (id: string) => Promise<void>;
|
|
149
159
|
moveDrawingToFolder: (drawingId: string, folderId: string | null) => Promise<void>;
|
|
160
|
+
/** Re-numbers `position` for the given drawing IDs in order. Use the full ordered slice
|
|
161
|
+
* the user reordered (e.g. all root drawings, or all drawings in a folder). */
|
|
162
|
+
reorderDrawings: (orderedIds: string[]) => Promise<void>;
|
|
150
163
|
saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
|
|
151
164
|
saveDrawingById: (id: string, elements: unknown[], appState: Record<string, unknown>, files?: Record<string, unknown>) => Promise<void>;
|
|
152
165
|
refreshDrawings: () => Promise<void>;
|
|
@@ -388,4 +401,4 @@ interface WorkspacePluginProps {
|
|
|
388
401
|
*/
|
|
389
402
|
declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
|
|
390
403
|
|
|
391
|
-
export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
|
|
404
|
+
export { type Drawing, DrawingList, DrawingListItem, type DrawingMeta, DrawingsDialog, type DrawingsDialogProps, type ExcalidrawImperativeAPI, type Folder, Sidebar, type SupportedLanguage, type Translations, type Workspace, WorkspaceBridge, type WorkspaceBridgeProps, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, createFolder, deleteDrawing, deleteFolder, duplicateDrawing, getAllDrawings, getAllDrawingsMeta, getAllFolders, getDB, getDrawing, getFolder, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isDrawingOpenedEarlierInOtherTab, isLanguageSupported, moveDrawingToFolder, removeDrawingFromWorkspace, renameFolder, reorderDrawings, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang, warmDB };
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,7 @@ __export(index_exports, {
|
|
|
59
59
|
moveDrawingToFolder: () => moveDrawingToFolder,
|
|
60
60
|
removeDrawingFromWorkspace: () => removeDrawingFromWorkspace,
|
|
61
61
|
renameFolder: () => renameFolder,
|
|
62
|
+
reorderDrawings: () => reorderDrawings,
|
|
62
63
|
setActiveDrawing: () => setActiveDrawing,
|
|
63
64
|
updateDrawing: () => updateDrawing,
|
|
64
65
|
updateWorkspace: () => updateWorkspace,
|
|
@@ -177,6 +178,17 @@ async function duplicateDrawing(id, newName) {
|
|
|
177
178
|
async function moveDrawingToFolder(drawingId, folderId) {
|
|
178
179
|
return updateDrawing(drawingId, { folderId });
|
|
179
180
|
}
|
|
181
|
+
async function reorderDrawings(orderedIds) {
|
|
182
|
+
const db = await getDB();
|
|
183
|
+
const tx = db.transaction("drawings", "readwrite");
|
|
184
|
+
const store = tx.objectStore("drawings");
|
|
185
|
+
for (let i = 0; i < orderedIds.length; i++) {
|
|
186
|
+
const existing = await store.get(orderedIds[i]);
|
|
187
|
+
if (!existing) continue;
|
|
188
|
+
await store.put({ ...existing, position: i });
|
|
189
|
+
}
|
|
190
|
+
await tx.done;
|
|
191
|
+
}
|
|
180
192
|
|
|
181
193
|
// src/storage/folderStore.ts
|
|
182
194
|
var import_nanoid2 = require("nanoid");
|
|
@@ -315,8 +327,8 @@ var sv = {
|
|
|
315
327
|
// Actions with descriptions
|
|
316
328
|
createNewDrawing: "Skapa ny ritning",
|
|
317
329
|
createNewDrawingDesc: "Skapar en tom ritning i din arbetsyta",
|
|
318
|
-
openFromFile: "
|
|
319
|
-
openFromFileDesc: "
|
|
330
|
+
openFromFile: "Importera ritning fr\xE5n fil",
|
|
331
|
+
openFromFileDesc: "Importerar en sparad ritning fr\xE5n din dator",
|
|
320
332
|
saveAllBackup: "Spara alla ritningar (backup)",
|
|
321
333
|
saveAllBackupDesc: "Ladda ner hela din arbetsyta som backup",
|
|
322
334
|
loadBackup: "L\xE4s in sparad arbetsyta",
|
|
@@ -342,6 +354,9 @@ var sv = {
|
|
|
342
354
|
// Backup reminder
|
|
343
355
|
backupReminder: "Senaste backup:",
|
|
344
356
|
days: "dagar sedan",
|
|
357
|
+
// Auto-start
|
|
358
|
+
autoStartLabel: "Starta Rita i arbetsl\xE4ge",
|
|
359
|
+
autoStartDesc: "Aktivera arbetsl\xE4ge automatiskt n\xE4r Rita \xF6ppnas",
|
|
345
360
|
// Shortcuts
|
|
346
361
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
347
362
|
};
|
|
@@ -365,8 +380,8 @@ var en = {
|
|
|
365
380
|
// Actions with descriptions
|
|
366
381
|
createNewDrawing: "Create new drawing",
|
|
367
382
|
createNewDrawingDesc: "Creates an empty drawing in your workspace",
|
|
368
|
-
openFromFile: "
|
|
369
|
-
openFromFileDesc: "
|
|
383
|
+
openFromFile: "Import drawing from file",
|
|
384
|
+
openFromFileDesc: "Imports a saved drawing from your computer",
|
|
370
385
|
saveAllBackup: "Save all drawings (backup)",
|
|
371
386
|
saveAllBackupDesc: "Download your entire workspace as a backup",
|
|
372
387
|
loadBackup: "Load saved workspace",
|
|
@@ -392,6 +407,9 @@ var en = {
|
|
|
392
407
|
// Backup reminder
|
|
393
408
|
backupReminder: "Last backup:",
|
|
394
409
|
days: "days ago",
|
|
410
|
+
// Auto-start
|
|
411
|
+
autoStartLabel: "Start Rita in workspace mode",
|
|
412
|
+
autoStartDesc: "Automatically enable workspace mode when Rita opens",
|
|
395
413
|
// Shortcuts
|
|
396
414
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
397
415
|
};
|
|
@@ -1251,6 +1269,19 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
1251
1269
|
setError(err instanceof Error ? err.message : "Failed to move drawing");
|
|
1252
1270
|
}
|
|
1253
1271
|
}, []);
|
|
1272
|
+
const reorderDrawings2 = (0, import_react.useCallback)(async (orderedIds) => {
|
|
1273
|
+
const positionMap = new Map(orderedIds.map((id, idx) => [id, idx]));
|
|
1274
|
+
setDrawings((prev) => prev.map(
|
|
1275
|
+
(d) => positionMap.has(d.id) ? { ...d, position: positionMap.get(d.id) } : d
|
|
1276
|
+
));
|
|
1277
|
+
try {
|
|
1278
|
+
await reorderDrawings(orderedIds);
|
|
1279
|
+
broadcastWorkspaceChange();
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
setError(err instanceof Error ? err.message : "Failed to reorder drawings");
|
|
1282
|
+
refreshDrawingsRef.current();
|
|
1283
|
+
}
|
|
1284
|
+
}, []);
|
|
1254
1285
|
const value = {
|
|
1255
1286
|
workspace,
|
|
1256
1287
|
drawings,
|
|
@@ -1270,6 +1301,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
1270
1301
|
renameFolder: renameFolder2,
|
|
1271
1302
|
deleteFolder: deleteFolder2,
|
|
1272
1303
|
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1304
|
+
reorderDrawings: reorderDrawings2,
|
|
1273
1305
|
saveCurrentDrawing,
|
|
1274
1306
|
saveDrawingById,
|
|
1275
1307
|
refreshDrawings,
|
|
@@ -1638,6 +1670,7 @@ var DrawingsDialog = ({
|
|
|
1638
1670
|
renameFolder: renameFolder2,
|
|
1639
1671
|
deleteFolder: deleteFolder2,
|
|
1640
1672
|
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1673
|
+
reorderDrawings: reorderDrawings2,
|
|
1641
1674
|
exportWorkspace,
|
|
1642
1675
|
importWorkspace,
|
|
1643
1676
|
exportDrawingAsExcalidraw,
|
|
@@ -1664,8 +1697,31 @@ var DrawingsDialog = ({
|
|
|
1664
1697
|
const [movingDrawingId, setMovingDrawingId] = (0, import_react5.useState)(null);
|
|
1665
1698
|
const [searchQuery, setSearchQuery] = (0, import_react5.useState)("");
|
|
1666
1699
|
const [isRefreshing, setIsRefreshing] = (0, import_react5.useState)(false);
|
|
1700
|
+
const [autoStart, setAutoStart] = (0, import_react5.useState)(() => {
|
|
1701
|
+
try {
|
|
1702
|
+
return localStorage.getItem("rita-workspace-auto-start") === "true";
|
|
1703
|
+
} catch {
|
|
1704
|
+
return false;
|
|
1705
|
+
}
|
|
1706
|
+
});
|
|
1707
|
+
const handleToggleAutoStart = (0, import_react5.useCallback)(() => {
|
|
1708
|
+
setAutoStart((prev) => {
|
|
1709
|
+
const next = !prev;
|
|
1710
|
+
try {
|
|
1711
|
+
if (next) {
|
|
1712
|
+
localStorage.setItem("rita-workspace-auto-start", "true");
|
|
1713
|
+
} else {
|
|
1714
|
+
localStorage.removeItem("rita-workspace-auto-start");
|
|
1715
|
+
}
|
|
1716
|
+
} catch {
|
|
1717
|
+
}
|
|
1718
|
+
return next;
|
|
1719
|
+
});
|
|
1720
|
+
}, []);
|
|
1667
1721
|
const [draggingDrawingId, setDraggingDrawingId] = (0, import_react5.useState)(null);
|
|
1668
1722
|
const [dropTargetFolderId, setDropTargetFolderId] = (0, import_react5.useState)(null);
|
|
1723
|
+
const [dropTargetDrawingId, setDropTargetDrawingId] = (0, import_react5.useState)(null);
|
|
1724
|
+
const [dropTargetPosition, setDropTargetPosition] = (0, import_react5.useState)(null);
|
|
1669
1725
|
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
1670
1726
|
const dragRef = (0, import_react5.useRef)(null);
|
|
1671
1727
|
const dialogRef = (0, import_react5.useRef)(null);
|
|
@@ -1773,6 +1829,28 @@ var DrawingsDialog = ({
|
|
|
1773
1829
|
setSelectedId(null);
|
|
1774
1830
|
moveDrawingToFolder2(drawingId, folderId);
|
|
1775
1831
|
}, [moveDrawingToFolder2]);
|
|
1832
|
+
const handleReorderDrop = (0, import_react5.useCallback)((draggedId, targetId, pos) => {
|
|
1833
|
+
if (draggedId === targetId) return;
|
|
1834
|
+
const target = drawings.find((d) => d.id === targetId);
|
|
1835
|
+
if (!target) return;
|
|
1836
|
+
const scopeFolderId = target.folderId ?? null;
|
|
1837
|
+
const scope = drawings.filter((d) => (d.folderId ?? null) === scopeFolderId).sort((a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt));
|
|
1838
|
+
const withoutDragged = scope.filter((d) => d.id !== draggedId);
|
|
1839
|
+
const targetIdx = withoutDragged.findIndex((d) => d.id === targetId);
|
|
1840
|
+
if (targetIdx === -1) return;
|
|
1841
|
+
const insertIdx = pos === "before" ? targetIdx : targetIdx + 1;
|
|
1842
|
+
const dragged = drawings.find((d) => d.id === draggedId);
|
|
1843
|
+
if (!dragged) return;
|
|
1844
|
+
if ((dragged.folderId ?? null) !== scopeFolderId) {
|
|
1845
|
+
moveDrawingToFolder2(draggedId, scopeFolderId);
|
|
1846
|
+
}
|
|
1847
|
+
const ordered = [
|
|
1848
|
+
...withoutDragged.slice(0, insertIdx),
|
|
1849
|
+
dragged,
|
|
1850
|
+
...withoutDragged.slice(insertIdx)
|
|
1851
|
+
].map((d) => d.id);
|
|
1852
|
+
reorderDrawings2(ordered);
|
|
1853
|
+
}, [drawings, reorderDrawings2, moveDrawingToFolder2]);
|
|
1776
1854
|
const toggleFolder = (0, import_react5.useCallback)((folderId) => {
|
|
1777
1855
|
setExpandedFolders((prev) => {
|
|
1778
1856
|
const next = new Set(prev);
|
|
@@ -1805,7 +1883,9 @@ var DrawingsDialog = ({
|
|
|
1805
1883
|
const { rootDrawings, drawingsByFolder, filteredFolders } = (0, import_react5.useMemo)(() => {
|
|
1806
1884
|
const query = searchQuery.toLowerCase().trim();
|
|
1807
1885
|
const filtered = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
|
|
1808
|
-
const sorted = [...filtered].sort(
|
|
1886
|
+
const sorted = [...filtered].sort(
|
|
1887
|
+
(a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt)
|
|
1888
|
+
);
|
|
1809
1889
|
const root = sorted.filter((d) => !d.folderId);
|
|
1810
1890
|
const byFolder = {};
|
|
1811
1891
|
for (const folder of folders) {
|
|
@@ -1860,6 +1940,34 @@ var DrawingsDialog = ({
|
|
|
1860
1940
|
onDragEnd: () => {
|
|
1861
1941
|
setDraggingDrawingId(null);
|
|
1862
1942
|
setDropTargetFolderId(null);
|
|
1943
|
+
setDropTargetDrawingId(null);
|
|
1944
|
+
setDropTargetPosition(null);
|
|
1945
|
+
},
|
|
1946
|
+
onDragOver: (e) => {
|
|
1947
|
+
if (!draggingDrawingId || draggingDrawingId === drawing.id) return;
|
|
1948
|
+
e.preventDefault();
|
|
1949
|
+
e.dataTransfer.dropEffect = "move";
|
|
1950
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
1951
|
+
const isBefore = e.clientY < rect.top + rect.height / 2;
|
|
1952
|
+
setDropTargetDrawingId(drawing.id);
|
|
1953
|
+
setDropTargetPosition(isBefore ? "before" : "after");
|
|
1954
|
+
},
|
|
1955
|
+
onDragLeave: (e) => {
|
|
1956
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
1957
|
+
if (dropTargetDrawingId === drawing.id) {
|
|
1958
|
+
setDropTargetDrawingId(null);
|
|
1959
|
+
setDropTargetPosition(null);
|
|
1960
|
+
}
|
|
1961
|
+
},
|
|
1962
|
+
onDrop: (e) => {
|
|
1963
|
+
if (!draggingDrawingId || !dropTargetPosition || draggingDrawingId === drawing.id) return;
|
|
1964
|
+
e.preventDefault();
|
|
1965
|
+
e.stopPropagation();
|
|
1966
|
+
handleReorderDrop(draggingDrawingId, drawing.id, dropTargetPosition);
|
|
1967
|
+
setDraggingDrawingId(null);
|
|
1968
|
+
setDropTargetDrawingId(null);
|
|
1969
|
+
setDropTargetPosition(null);
|
|
1970
|
+
setDropTargetFolderId(null);
|
|
1863
1971
|
},
|
|
1864
1972
|
onMouseEnter: () => setHoveredId(drawing.id),
|
|
1865
1973
|
onMouseLeave: () => setHoveredId(null),
|
|
@@ -1875,6 +1983,7 @@ var DrawingsDialog = ({
|
|
|
1875
1983
|
handleSelect(drawing);
|
|
1876
1984
|
},
|
|
1877
1985
|
style: {
|
|
1986
|
+
position: "relative",
|
|
1878
1987
|
padding: "10px 12px",
|
|
1879
1988
|
display: "flex",
|
|
1880
1989
|
alignItems: "center",
|
|
@@ -1889,6 +1998,16 @@ var DrawingsDialog = ({
|
|
|
1889
1998
|
opacity: draggingDrawingId === drawing.id ? 0.4 : switchingId && switchingId !== drawing.id ? 0.5 : 1
|
|
1890
1999
|
},
|
|
1891
2000
|
children: [
|
|
2001
|
+
dropTargetDrawingId === drawing.id && dropTargetPosition && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
2002
|
+
position: "absolute",
|
|
2003
|
+
left: 4,
|
|
2004
|
+
right: 4,
|
|
2005
|
+
[dropTargetPosition === "before" ? "top" : "bottom"]: -2,
|
|
2006
|
+
height: "3px",
|
|
2007
|
+
backgroundColor: "var(--color-primary, #6c63ff)",
|
|
2008
|
+
borderRadius: "2px",
|
|
2009
|
+
pointerEvents: "none"
|
|
2010
|
+
} }),
|
|
1892
2011
|
renderThumbnail && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: {
|
|
1893
2012
|
width: "64px",
|
|
1894
2013
|
height: "48px",
|
|
@@ -2481,7 +2600,37 @@ var DrawingsDialog = ({
|
|
|
2481
2600
|
onClick: importWorkspace
|
|
2482
2601
|
}
|
|
2483
2602
|
)
|
|
2484
|
-
] })
|
|
2603
|
+
] }),
|
|
2604
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "0 20px 16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2605
|
+
"label",
|
|
2606
|
+
{
|
|
2607
|
+
style: {
|
|
2608
|
+
display: "flex",
|
|
2609
|
+
alignItems: "center",
|
|
2610
|
+
gap: "10px",
|
|
2611
|
+
padding: "10px 12px",
|
|
2612
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
2613
|
+
borderRadius: "8px",
|
|
2614
|
+
cursor: "pointer",
|
|
2615
|
+
userSelect: "none"
|
|
2616
|
+
},
|
|
2617
|
+
children: [
|
|
2618
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2619
|
+
"input",
|
|
2620
|
+
{
|
|
2621
|
+
type: "checkbox",
|
|
2622
|
+
checked: autoStart,
|
|
2623
|
+
onChange: handleToggleAutoStart,
|
|
2624
|
+
style: { width: "16px", height: "16px", cursor: "pointer", flexShrink: 0 }
|
|
2625
|
+
}
|
|
2626
|
+
),
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2628
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: "14px", fontWeight: 500 }, children: t.autoStartLabel }),
|
|
2629
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: "12px", color: "var(--text-secondary-color, #888)", marginTop: "2px" }, children: t.autoStartDesc })
|
|
2630
|
+
] })
|
|
2631
|
+
]
|
|
2632
|
+
}
|
|
2633
|
+
) })
|
|
2485
2634
|
]
|
|
2486
2635
|
}
|
|
2487
2636
|
)
|
|
@@ -2815,6 +2964,7 @@ function WorkspacePlugin(props) {
|
|
|
2815
2964
|
moveDrawingToFolder,
|
|
2816
2965
|
removeDrawingFromWorkspace,
|
|
2817
2966
|
renameFolder,
|
|
2967
|
+
reorderDrawings,
|
|
2818
2968
|
setActiveDrawing,
|
|
2819
2969
|
updateDrawing,
|
|
2820
2970
|
updateWorkspace,
|
package/dist/index.mjs
CHANGED
|
@@ -106,6 +106,17 @@ async function duplicateDrawing(id, newName) {
|
|
|
106
106
|
async function moveDrawingToFolder(drawingId, folderId) {
|
|
107
107
|
return updateDrawing(drawingId, { folderId });
|
|
108
108
|
}
|
|
109
|
+
async function reorderDrawings(orderedIds) {
|
|
110
|
+
const db = await getDB();
|
|
111
|
+
const tx = db.transaction("drawings", "readwrite");
|
|
112
|
+
const store = tx.objectStore("drawings");
|
|
113
|
+
for (let i = 0; i < orderedIds.length; i++) {
|
|
114
|
+
const existing = await store.get(orderedIds[i]);
|
|
115
|
+
if (!existing) continue;
|
|
116
|
+
await store.put({ ...existing, position: i });
|
|
117
|
+
}
|
|
118
|
+
await tx.done;
|
|
119
|
+
}
|
|
109
120
|
|
|
110
121
|
// src/storage/folderStore.ts
|
|
111
122
|
import { nanoid as nanoid2 } from "nanoid";
|
|
@@ -244,8 +255,8 @@ var sv = {
|
|
|
244
255
|
// Actions with descriptions
|
|
245
256
|
createNewDrawing: "Skapa ny ritning",
|
|
246
257
|
createNewDrawingDesc: "Skapar en tom ritning i din arbetsyta",
|
|
247
|
-
openFromFile: "
|
|
248
|
-
openFromFileDesc: "
|
|
258
|
+
openFromFile: "Importera ritning fr\xE5n fil",
|
|
259
|
+
openFromFileDesc: "Importerar en sparad ritning fr\xE5n din dator",
|
|
249
260
|
saveAllBackup: "Spara alla ritningar (backup)",
|
|
250
261
|
saveAllBackupDesc: "Ladda ner hela din arbetsyta som backup",
|
|
251
262
|
loadBackup: "L\xE4s in sparad arbetsyta",
|
|
@@ -271,6 +282,9 @@ var sv = {
|
|
|
271
282
|
// Backup reminder
|
|
272
283
|
backupReminder: "Senaste backup:",
|
|
273
284
|
days: "dagar sedan",
|
|
285
|
+
// Auto-start
|
|
286
|
+
autoStartLabel: "Starta Rita i arbetsl\xE4ge",
|
|
287
|
+
autoStartDesc: "Aktivera arbetsl\xE4ge automatiskt n\xE4r Rita \xF6ppnas",
|
|
274
288
|
// Shortcuts
|
|
275
289
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
276
290
|
};
|
|
@@ -294,8 +308,8 @@ var en = {
|
|
|
294
308
|
// Actions with descriptions
|
|
295
309
|
createNewDrawing: "Create new drawing",
|
|
296
310
|
createNewDrawingDesc: "Creates an empty drawing in your workspace",
|
|
297
|
-
openFromFile: "
|
|
298
|
-
openFromFileDesc: "
|
|
311
|
+
openFromFile: "Import drawing from file",
|
|
312
|
+
openFromFileDesc: "Imports a saved drawing from your computer",
|
|
299
313
|
saveAllBackup: "Save all drawings (backup)",
|
|
300
314
|
saveAllBackupDesc: "Download your entire workspace as a backup",
|
|
301
315
|
loadBackup: "Load saved workspace",
|
|
@@ -321,6 +335,9 @@ var en = {
|
|
|
321
335
|
// Backup reminder
|
|
322
336
|
backupReminder: "Last backup:",
|
|
323
337
|
days: "days ago",
|
|
338
|
+
// Auto-start
|
|
339
|
+
autoStartLabel: "Start Rita in workspace mode",
|
|
340
|
+
autoStartDesc: "Automatically enable workspace mode when Rita opens",
|
|
324
341
|
// Shortcuts
|
|
325
342
|
shortcutNewDrawing: "Ctrl+Alt+N"
|
|
326
343
|
};
|
|
@@ -1180,6 +1197,19 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
1180
1197
|
setError(err instanceof Error ? err.message : "Failed to move drawing");
|
|
1181
1198
|
}
|
|
1182
1199
|
}, []);
|
|
1200
|
+
const reorderDrawings2 = useCallback(async (orderedIds) => {
|
|
1201
|
+
const positionMap = new Map(orderedIds.map((id, idx) => [id, idx]));
|
|
1202
|
+
setDrawings((prev) => prev.map(
|
|
1203
|
+
(d) => positionMap.has(d.id) ? { ...d, position: positionMap.get(d.id) } : d
|
|
1204
|
+
));
|
|
1205
|
+
try {
|
|
1206
|
+
await reorderDrawings(orderedIds);
|
|
1207
|
+
broadcastWorkspaceChange();
|
|
1208
|
+
} catch (err) {
|
|
1209
|
+
setError(err instanceof Error ? err.message : "Failed to reorder drawings");
|
|
1210
|
+
refreshDrawingsRef.current();
|
|
1211
|
+
}
|
|
1212
|
+
}, []);
|
|
1183
1213
|
const value = {
|
|
1184
1214
|
workspace,
|
|
1185
1215
|
drawings,
|
|
@@ -1199,6 +1229,7 @@ function WorkspaceProvider({ children, lang = "en" }) {
|
|
|
1199
1229
|
renameFolder: renameFolder2,
|
|
1200
1230
|
deleteFolder: deleteFolder2,
|
|
1201
1231
|
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1232
|
+
reorderDrawings: reorderDrawings2,
|
|
1202
1233
|
saveCurrentDrawing,
|
|
1203
1234
|
saveDrawingById,
|
|
1204
1235
|
refreshDrawings,
|
|
@@ -1567,6 +1598,7 @@ var DrawingsDialog = ({
|
|
|
1567
1598
|
renameFolder: renameFolder2,
|
|
1568
1599
|
deleteFolder: deleteFolder2,
|
|
1569
1600
|
moveDrawingToFolder: moveDrawingToFolder2,
|
|
1601
|
+
reorderDrawings: reorderDrawings2,
|
|
1570
1602
|
exportWorkspace,
|
|
1571
1603
|
importWorkspace,
|
|
1572
1604
|
exportDrawingAsExcalidraw,
|
|
@@ -1593,8 +1625,31 @@ var DrawingsDialog = ({
|
|
|
1593
1625
|
const [movingDrawingId, setMovingDrawingId] = useState4(null);
|
|
1594
1626
|
const [searchQuery, setSearchQuery] = useState4("");
|
|
1595
1627
|
const [isRefreshing, setIsRefreshing] = useState4(false);
|
|
1628
|
+
const [autoStart, setAutoStart] = useState4(() => {
|
|
1629
|
+
try {
|
|
1630
|
+
return localStorage.getItem("rita-workspace-auto-start") === "true";
|
|
1631
|
+
} catch {
|
|
1632
|
+
return false;
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
const handleToggleAutoStart = useCallback2(() => {
|
|
1636
|
+
setAutoStart((prev) => {
|
|
1637
|
+
const next = !prev;
|
|
1638
|
+
try {
|
|
1639
|
+
if (next) {
|
|
1640
|
+
localStorage.setItem("rita-workspace-auto-start", "true");
|
|
1641
|
+
} else {
|
|
1642
|
+
localStorage.removeItem("rita-workspace-auto-start");
|
|
1643
|
+
}
|
|
1644
|
+
} catch {
|
|
1645
|
+
}
|
|
1646
|
+
return next;
|
|
1647
|
+
});
|
|
1648
|
+
}, []);
|
|
1596
1649
|
const [draggingDrawingId, setDraggingDrawingId] = useState4(null);
|
|
1597
1650
|
const [dropTargetFolderId, setDropTargetFolderId] = useState4(null);
|
|
1651
|
+
const [dropTargetDrawingId, setDropTargetDrawingId] = useState4(null);
|
|
1652
|
+
const [dropTargetPosition, setDropTargetPosition] = useState4(null);
|
|
1598
1653
|
const [position, setPosition] = useState4(null);
|
|
1599
1654
|
const dragRef = useRef3(null);
|
|
1600
1655
|
const dialogRef = useRef3(null);
|
|
@@ -1702,6 +1757,28 @@ var DrawingsDialog = ({
|
|
|
1702
1757
|
setSelectedId(null);
|
|
1703
1758
|
moveDrawingToFolder2(drawingId, folderId);
|
|
1704
1759
|
}, [moveDrawingToFolder2]);
|
|
1760
|
+
const handleReorderDrop = useCallback2((draggedId, targetId, pos) => {
|
|
1761
|
+
if (draggedId === targetId) return;
|
|
1762
|
+
const target = drawings.find((d) => d.id === targetId);
|
|
1763
|
+
if (!target) return;
|
|
1764
|
+
const scopeFolderId = target.folderId ?? null;
|
|
1765
|
+
const scope = drawings.filter((d) => (d.folderId ?? null) === scopeFolderId).sort((a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt));
|
|
1766
|
+
const withoutDragged = scope.filter((d) => d.id !== draggedId);
|
|
1767
|
+
const targetIdx = withoutDragged.findIndex((d) => d.id === targetId);
|
|
1768
|
+
if (targetIdx === -1) return;
|
|
1769
|
+
const insertIdx = pos === "before" ? targetIdx : targetIdx + 1;
|
|
1770
|
+
const dragged = drawings.find((d) => d.id === draggedId);
|
|
1771
|
+
if (!dragged) return;
|
|
1772
|
+
if ((dragged.folderId ?? null) !== scopeFolderId) {
|
|
1773
|
+
moveDrawingToFolder2(draggedId, scopeFolderId);
|
|
1774
|
+
}
|
|
1775
|
+
const ordered = [
|
|
1776
|
+
...withoutDragged.slice(0, insertIdx),
|
|
1777
|
+
dragged,
|
|
1778
|
+
...withoutDragged.slice(insertIdx)
|
|
1779
|
+
].map((d) => d.id);
|
|
1780
|
+
reorderDrawings2(ordered);
|
|
1781
|
+
}, [drawings, reorderDrawings2, moveDrawingToFolder2]);
|
|
1705
1782
|
const toggleFolder = useCallback2((folderId) => {
|
|
1706
1783
|
setExpandedFolders((prev) => {
|
|
1707
1784
|
const next = new Set(prev);
|
|
@@ -1734,7 +1811,9 @@ var DrawingsDialog = ({
|
|
|
1734
1811
|
const { rootDrawings, drawingsByFolder, filteredFolders } = useMemo(() => {
|
|
1735
1812
|
const query = searchQuery.toLowerCase().trim();
|
|
1736
1813
|
const filtered = query ? drawings.filter((d) => d.name.toLowerCase().includes(query)) : drawings;
|
|
1737
|
-
const sorted = [...filtered].sort(
|
|
1814
|
+
const sorted = [...filtered].sort(
|
|
1815
|
+
(a, b) => (a.position ?? a.createdAt) - (b.position ?? b.createdAt)
|
|
1816
|
+
);
|
|
1738
1817
|
const root = sorted.filter((d) => !d.folderId);
|
|
1739
1818
|
const byFolder = {};
|
|
1740
1819
|
for (const folder of folders) {
|
|
@@ -1789,6 +1868,34 @@ var DrawingsDialog = ({
|
|
|
1789
1868
|
onDragEnd: () => {
|
|
1790
1869
|
setDraggingDrawingId(null);
|
|
1791
1870
|
setDropTargetFolderId(null);
|
|
1871
|
+
setDropTargetDrawingId(null);
|
|
1872
|
+
setDropTargetPosition(null);
|
|
1873
|
+
},
|
|
1874
|
+
onDragOver: (e) => {
|
|
1875
|
+
if (!draggingDrawingId || draggingDrawingId === drawing.id) return;
|
|
1876
|
+
e.preventDefault();
|
|
1877
|
+
e.dataTransfer.dropEffect = "move";
|
|
1878
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
1879
|
+
const isBefore = e.clientY < rect.top + rect.height / 2;
|
|
1880
|
+
setDropTargetDrawingId(drawing.id);
|
|
1881
|
+
setDropTargetPosition(isBefore ? "before" : "after");
|
|
1882
|
+
},
|
|
1883
|
+
onDragLeave: (e) => {
|
|
1884
|
+
if (e.currentTarget.contains(e.relatedTarget)) return;
|
|
1885
|
+
if (dropTargetDrawingId === drawing.id) {
|
|
1886
|
+
setDropTargetDrawingId(null);
|
|
1887
|
+
setDropTargetPosition(null);
|
|
1888
|
+
}
|
|
1889
|
+
},
|
|
1890
|
+
onDrop: (e) => {
|
|
1891
|
+
if (!draggingDrawingId || !dropTargetPosition || draggingDrawingId === drawing.id) return;
|
|
1892
|
+
e.preventDefault();
|
|
1893
|
+
e.stopPropagation();
|
|
1894
|
+
handleReorderDrop(draggingDrawingId, drawing.id, dropTargetPosition);
|
|
1895
|
+
setDraggingDrawingId(null);
|
|
1896
|
+
setDropTargetDrawingId(null);
|
|
1897
|
+
setDropTargetPosition(null);
|
|
1898
|
+
setDropTargetFolderId(null);
|
|
1792
1899
|
},
|
|
1793
1900
|
onMouseEnter: () => setHoveredId(drawing.id),
|
|
1794
1901
|
onMouseLeave: () => setHoveredId(null),
|
|
@@ -1804,6 +1911,7 @@ var DrawingsDialog = ({
|
|
|
1804
1911
|
handleSelect(drawing);
|
|
1805
1912
|
},
|
|
1806
1913
|
style: {
|
|
1914
|
+
position: "relative",
|
|
1807
1915
|
padding: "10px 12px",
|
|
1808
1916
|
display: "flex",
|
|
1809
1917
|
alignItems: "center",
|
|
@@ -1818,6 +1926,16 @@ var DrawingsDialog = ({
|
|
|
1818
1926
|
opacity: draggingDrawingId === drawing.id ? 0.4 : switchingId && switchingId !== drawing.id ? 0.5 : 1
|
|
1819
1927
|
},
|
|
1820
1928
|
children: [
|
|
1929
|
+
dropTargetDrawingId === drawing.id && dropTargetPosition && /* @__PURE__ */ jsx6("div", { style: {
|
|
1930
|
+
position: "absolute",
|
|
1931
|
+
left: 4,
|
|
1932
|
+
right: 4,
|
|
1933
|
+
[dropTargetPosition === "before" ? "top" : "bottom"]: -2,
|
|
1934
|
+
height: "3px",
|
|
1935
|
+
backgroundColor: "var(--color-primary, #6c63ff)",
|
|
1936
|
+
borderRadius: "2px",
|
|
1937
|
+
pointerEvents: "none"
|
|
1938
|
+
} }),
|
|
1821
1939
|
renderThumbnail && /* @__PURE__ */ jsx6("div", { style: {
|
|
1822
1940
|
width: "64px",
|
|
1823
1941
|
height: "48px",
|
|
@@ -2410,7 +2528,37 @@ var DrawingsDialog = ({
|
|
|
2410
2528
|
onClick: importWorkspace
|
|
2411
2529
|
}
|
|
2412
2530
|
)
|
|
2413
|
-
] })
|
|
2531
|
+
] }),
|
|
2532
|
+
/* @__PURE__ */ jsx6("div", { style: { padding: "0 20px 16px" }, children: /* @__PURE__ */ jsxs4(
|
|
2533
|
+
"label",
|
|
2534
|
+
{
|
|
2535
|
+
style: {
|
|
2536
|
+
display: "flex",
|
|
2537
|
+
alignItems: "center",
|
|
2538
|
+
gap: "10px",
|
|
2539
|
+
padding: "10px 12px",
|
|
2540
|
+
border: "1px solid var(--default-border-color, #e0e0e0)",
|
|
2541
|
+
borderRadius: "8px",
|
|
2542
|
+
cursor: "pointer",
|
|
2543
|
+
userSelect: "none"
|
|
2544
|
+
},
|
|
2545
|
+
children: [
|
|
2546
|
+
/* @__PURE__ */ jsx6(
|
|
2547
|
+
"input",
|
|
2548
|
+
{
|
|
2549
|
+
type: "checkbox",
|
|
2550
|
+
checked: autoStart,
|
|
2551
|
+
onChange: handleToggleAutoStart,
|
|
2552
|
+
style: { width: "16px", height: "16px", cursor: "pointer", flexShrink: 0 }
|
|
2553
|
+
}
|
|
2554
|
+
),
|
|
2555
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2556
|
+
/* @__PURE__ */ jsx6("div", { style: { fontSize: "14px", fontWeight: 500 }, children: t.autoStartLabel }),
|
|
2557
|
+
/* @__PURE__ */ jsx6("div", { style: { fontSize: "12px", color: "var(--text-secondary-color, #888)", marginTop: "2px" }, children: t.autoStartDesc })
|
|
2558
|
+
] })
|
|
2559
|
+
]
|
|
2560
|
+
}
|
|
2561
|
+
) })
|
|
2414
2562
|
]
|
|
2415
2563
|
}
|
|
2416
2564
|
)
|
|
@@ -2743,6 +2891,7 @@ export {
|
|
|
2743
2891
|
moveDrawingToFolder,
|
|
2744
2892
|
removeDrawingFromWorkspace,
|
|
2745
2893
|
renameFolder,
|
|
2894
|
+
reorderDrawings,
|
|
2746
2895
|
setActiveDrawing,
|
|
2747
2896
|
updateDrawing,
|
|
2748
2897
|
updateWorkspace,
|