feat(workspace): trash for notes

Deleting a note (or its folder) moves it to the trash instead of erasing
it. Trashed notes leave the tree, search, export and stats and are hidden
from everyone they were shared with; the owner sees them read-only with a
restore banner. New endpoints list, restore, purge and empty the trash;
restoring recreates a deleted folder. Sidebar entry and mobile menu item
with counter, list view with two-tap permanent delete.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-29 07:57:42 +01:00
1 parent 344f5e4ab2
commit f69f74fdc7
15 files changed
+649 -40

No files matched your search

+11 -3
View File
@@ -549,14 +549,22 @@ func (s *Store) DocRole(userID, docID string) string {
if userID == "" {
return ""
}
var ownerID, sharedFolderID, folderOwner string
var ownerID, sharedFolderID, folderOwner, archivedBy string
var archived bool
err := s.db.QueryRow(
`SELECT d.user_id, d.shared_folder_id, COALESCE(wsf.owner_id, '')
`SELECT d.user_id, d.shared_folder_id, COALESCE(wsf.owner_id, ''), d.is_archived, d.archived_by
FROM documents d LEFT JOIN workspace_shared_folders wsf ON wsf.id = d.shared_folder_id
WHERE d.id = ?`, docID).Scan(&ownerID, &sharedFolderID, &folderOwner)
WHERE d.id = ?`, docID).Scan(&ownerID, &sharedFolderID, &folderOwner, &archived, &archivedBy)
if err != nil {
return ""
}
if archived {
// In the trash: read-only for the owner and whoever trashed it, hidden from everyone else
if ownerID == userID || archivedBy == userID {
return DocRoleViewer
}
return ""
}
if ownerID == userID {
return DocRoleOwner
}