feat: notification batching, per-folder mute, and global pause

Debounce embedding/tagging completion notifications per folder (6s window)
so rapid file additions from downloaders fire one notification instead of
one per file. Add per-folder mute via the sidebar context menu and a global
pause toggle in Settings > General, both persisted across restarts.
This commit is contained in:
2026-06-11 06:28:16 +01:00
parent b89e7406e9
commit a34d38d9d3
6 changed files with 200 additions and 27 deletions
+10 -1
View File
@@ -11,18 +11,22 @@ interface ContextMenuState {
function FolderContextMenu({
menu,
folder,
isMuted,
onClose,
onRename,
onReindex,
onLocate,
onToggleMute,
onRemove,
}: {
menu: ContextMenuState;
folder: Folder;
isMuted: boolean;
onClose: () => void;
onRename: () => void;
onReindex: () => void;
onLocate: () => void;
onToggleMute: () => void;
onRemove: () => void;
}) {
const ref = useRef<HTMLDivElement>(null);
@@ -61,6 +65,7 @@ function FolderContextMenu({
>
{item("Reindex", onReindex)}
{item("Rename", onRename)}
{item(isMuted ? "Unmute notifications" : "Mute notifications", onToggleMute)}
{folder.scan_error && item("Locate Folder", onLocate)}
<div className="my-1 border-t border-white/[0.06]" />
{item("Remove from app", onRemove, true)}
@@ -77,7 +82,9 @@ function FolderItem({
selected: boolean;
progress: IndexProgress | undefined;
}) {
const { selectFolder, removeFolder, reindexFolder, renameFolder, updateFolderPath } = useGalleryStore();
const { selectFolder, removeFolder, reindexFolder, renameFolder, updateFolderPath, toggleMutedFolder } = useGalleryStore();
const mutedFolderIds = useGalleryStore((state) => state.mutedFolderIds);
const isMuted = mutedFolderIds.includes(folder.id);
const isIndexing = progress && !progress.done;
const isMissing = !!folder.scan_error && !isIndexing;
@@ -250,10 +257,12 @@ function FolderItem({
<FolderContextMenu
menu={contextMenu}
folder={folder}
isMuted={isMuted}
onClose={() => setContextMenu(null)}
onRename={() => setRenaming(true)}
onReindex={() => void reindexFolder(folder.id)}
onLocate={() => void handleLocateFolder()}
onToggleMute={() => toggleMutedFolder(folder.id)}
onRemove={() => setConfirmingRemoval(true)}
/>
)}