feat(sidebar): show empty folders and create folders from the sidebar (#999)

Empty folders (tracked in the scan-recorded all_folders list, same source
the move/download destination picker uses) can now be surfaced in the
folder sidebar via a view-options toggle, dimmed when their subtree holds
no models. Folders can be created directly from the sidebar through a new
POST /api/lm/{prefix}/create-folder endpoint with library-root
containment checks; the scanner records the new directory incrementally
so the tree reflects it without a rescan.

The sidebar header moves its view toggles (tree/list, recursive, empty
folders) into a "..." menu to fit the new create-folder button.
This commit is contained in:
Will Miao
2026-09-15 15:14:56 +08:00
parent 2ceb1e2850
commit 9734df15b4
24 changed files with 1260 additions and 173 deletions
+24
View File
@@ -206,11 +206,35 @@
<!-- Sidebar Folder Context Menu -->
<div id="sidebarFolderContextMenu" class="context-menu">
<div class="context-menu-item" data-action="create-subfolder">
<i class="fas fa-folder-plus"></i> <span>{{ t('sidebar.newSubfolder') }}</span>
</div>
<div class="context-menu-item" data-action="check-folder-updates">
<i class="fas fa-bell"></i> <span>{{ t('sidebar.folderUpdateCheck.label') }}</span>
</div>
</div>
<!-- Sidebar View Options Menu -->
<div id="sidebarViewOptionsMenu" class="context-menu">
<div class="context-menu-item" data-action="view-mode-tree">
<i class="fas fa-sitemap"></i> <span>{{ t('sidebar.treeView') }}</span>
<i class="fas fa-check check-indicator" style="margin-left:auto;display:none"></i>
</div>
<div class="context-menu-item" data-action="view-mode-list">
<i class="fas fa-list"></i> <span>{{ t('sidebar.listView') }}</span>
<i class="fas fa-check check-indicator" style="margin-left:auto;display:none"></i>
</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" data-action="toggle-recursive">
<i class="fas fa-code-branch"></i> <span>{{ t('sidebar.recursiveOn') }}</span>
<i class="fas fa-check check-indicator" style="margin-left:auto;display:none"></i>
</div>
<div class="context-menu-item" data-action="toggle-empty-folders">
<i class="fas fa-folder-open"></i> <span>{{ t('sidebar.showEmptyFolders') }}</span>
<i class="fas fa-check check-indicator" style="margin-left:auto;display:none"></i>
</div>
</div>
<div id="nsfwLevelSelector" class="nsfw-level-selector">
<div class="nsfw-level-header">
<h3>{{ t('modals.contentRating.title') }}</h3>