From 6c1898d489cd3acb37af12351ff3d4174691844d Mon Sep 17 00:00:00 2001 From: Sandro Date: Mon, 26 Oct 2026 22:53:51 +0100 Subject: [PATCH] feat(workspace): decouple folder sharing with independent mount points & real-time sync --- .../src/features/workspace/WorkspaceView.tsx | 46 +++-- internal/api/server.go | 10 ++ internal/api/server_test.go | 162 ++++++++++++++++++ internal/storage/sqlite.go | 18 ++ internal/ws/hub.go | 2 + 5 files changed, 225 insertions(+), 13 deletions(-) diff --git a/frontend/src/features/workspace/WorkspaceView.tsx b/frontend/src/features/workspace/WorkspaceView.tsx index 742df91..454c095 100644 --- a/frontend/src/features/workspace/WorkspaceView.tsx +++ b/frontend/src/features/workspace/WorkspaceView.tsx @@ -131,7 +131,8 @@ export const WorkspaceView: React.FC = ({ created.sharedWith?.some( (s) => s.userId === currentUser.id || s.targetId === currentUser.id ) || false; - if (!isOwner && !isShared) { + const isFolderShared = Boolean(created.sharedFolderId || created.isSharedFolder); + if (!isOwner && !isShared && !isFolderShared) { return; } } @@ -146,6 +147,7 @@ export const WorkspaceView: React.FC = ({ } else if (msg.event === 'WORKSPACE_FOLDERS_UPDATED') { api.getFolders().then(setFolders).catch(() => {}); api.getSharedFolders().then(setSharedFolders).catch(() => {}); + api.getDocuments().then(setDocs).catch(() => {}); } }); return unsub; @@ -403,6 +405,24 @@ export const WorkspaceView: React.FC = ({ } }, []); + const handleShareFolderClick = useCallback( + async (folderPath: string, existingSf?: SharedFolder) => { + if (existingSf) { + openFolderShareModal(existingSf); + return; + } + try { + const clean = folderPath.trim().replace(/^\/+|\/+$/g, ''); + const sf = await api.createSharedFolder({ name: clean, mountPath: clean }); + setSharedFolders((prev) => [...prev.filter((f) => f.id !== sf.id), sf]); + openFolderShareModal(sf); + } catch { + // ignore + } + }, + [openFolderShareModal] + ); + const handleToggleRollupTodo = async (doc: Document, blockId: string, currentChecked: boolean) => { triggerHaptic(10); const updatedBlocks = (doc.blocks || []).map((b) => @@ -599,8 +619,8 @@ export const WorkspaceView: React.FC = ({ {/* Scrollable Navigation Tree */}
- {/* Drop target for moving docs to root */} - {draggingDocId && ( + {/* Drop target for moving docs or folders to root */} + {(draggingDocId || draggingFolderPath) && (
{ e.preventDefault(); @@ -727,16 +747,16 @@ export const WorkspaceView: React.FC = ({ > - {sharedFolderObj && ( - - )} +