Fix: Library FolderSetting Re-Vamp

This commit is contained in:
Youwes09
2026-05-10 12:07:00 -05:00
parent 244447da9b
commit 6d921944ac
5 changed files with 259 additions and 144 deletions
@@ -1,7 +1,7 @@
<script lang="ts">
import {
MagnifyingGlass, Books, DownloadSimple, Folder, FolderSimple,
SortAscending, CaretUp, CaretDown, ArrowsClockwise, Star, X,
SortAscending, CaretUp, CaretDown, ArrowsClockwise, Star, X, CheckSquare,
} from "phosphor-svelte";
import LibraryFilters from "./LibraryFilters.svelte";
import type { Category } from "@types";
@@ -16,6 +16,10 @@
hasActiveFilters: boolean;
anims: boolean;
visibleCategories: Category[];
visibleTabIds: string[];
virtualTabIds: string[];
folderTabIds: string[];
completedCatId: number | null;
counts: Record<string, number>;
search: string;
activeDragKind: "tab" | null;
@@ -44,8 +48,8 @@
let {
tab, tabSortMode, tabSortDir, tabStatus, tabFilters, hasActiveFilters,
anims, visibleCategories, counts, search, refreshing,
refreshProgress, refreshDone, activeDragKind, dragInsertIdx,
anims, visibleCategories, visibleTabIds, virtualTabIds, folderTabIds, completedCatId,
counts, search, refreshing, refreshProgress, refreshDone, activeDragKind, dragInsertIdx,
dragTabId, dragOverTabId, sortPanelOpen, filterPanelOpen,
tabsEl = $bindable(),
onSearchChange, onTabChange, onSortChange, onSortDirToggle, onStatusChange,
@@ -67,53 +71,43 @@
const ALL_SORT_MODES: LibrarySortMode[] = [
"az", "unreadCount", "totalChapters", "recentlyAdded", "recentlyRead", "latestFetched", "latestUploaded",
];
const activeCatId = $derived(
tab !== "library" && tab !== "downloaded" ? Number(tab) : null
);
</script>
<div class="header">
<span class="heading">Library</span>
<div class="tabs" class:tabs-anims={anims} bind:this={tabsEl}>
{#each [["library", "Saved"], ["downloaded", "Downloaded"]] as [f, label]}
<button class="tab" class:active={tab === f} onclick={() => onTabChange(f)}>
{#if f === "library"}<Books size={11} weight="bold" />
{:else if f === "downloaded"}<DownloadSimple size={11} weight="bold" />{/if}
{label}
<span class="tab-count">{counts[f] ?? 0}</span>
</button>
{#each visibleTabIds as id, idx}
{@const cat = visibleCategories.find(c => String(c.id) === id)}
{#if id === "library" || id === "downloaded" || cat}
{#if cat && dragInsertIdx === idx && activeDragKind === "tab"}
<div class="tab-insert-bar" aria-hidden="true"></div>
{/if}
<button
class="tab"
class:active={tab === id}
class:tab-dragging={cat && dragTabId === cat.id}
draggable={!!cat && id !== String(completedCatId)}
onclick={() => onTabChange(id)}
ondragstart={cat && id !== String(completedCatId) ? (e) => onTabDragStart(e, cat) : undefined}
ondragover={cat && id !== String(completedCatId) ? (e) => onTabDragOver(e, cat, idx) : undefined}
ondragleave={cat && id !== String(completedCatId) ? onTabDragLeave : undefined}
ondrop={cat && id !== String(completedCatId) ? (e) => onTabDrop(e, cat) : undefined}
ondragend={cat && id !== String(completedCatId) ? onTabDragEnd : undefined}
>
{#if id === "library"}<Books size={11} weight="bold" />
{:else if id === "downloaded"}<DownloadSimple size={11} weight="bold" />
{:else if cat && id === String(completedCatId)}<CheckSquare size={11} weight="bold" />
{:else if cat}<Folder size={11} weight="bold" />
{/if}
{id === "library" ? "Saved" : id === "downloaded" ? "Downloaded" : (cat?.name ?? id)}
<span class="tab-count">{counts[id] ?? 0}</span>
</button>
{#if cat && id !== String(completedCatId) && dragInsertIdx === idx + 1 && activeDragKind === "tab" && idx === visibleTabIds.length - 1}
<div class="tab-insert-bar" aria-hidden="true"></div>
{/if}
{/if}
{/each}
{#if visibleCategories.length > 0}
<div class="tab-separator" aria-hidden="true"></div>
<div class="tabs-scroll">
{#each visibleCategories as cat, idx}
{#if dragInsertIdx === idx && activeDragKind === "tab"}
<div class="tab-insert-bar" aria-hidden="true"></div>
{/if}
<button
class="tab"
class:active={tab === String(cat.id)}
class:tab-dragging={dragTabId === cat.id}
draggable="true"
onclick={() => onTabChange(String(cat.id))}
ondragstart={(e) => onTabDragStart(e, cat)}
ondragover={(e) => onTabDragOver(e, cat, idx)}
ondragleave={onTabDragLeave}
ondrop={(e) => onTabDrop(e, cat)}
ondragend={onTabDragEnd}
>
<Folder size={11} weight="bold" />
{cat.name}
<span class="tab-count">{counts[String(cat.id)] ?? 0}</span>
</button>
{#if dragInsertIdx === idx + 1 && activeDragKind === "tab" && idx === visibleCategories.length - 1}
<div class="tab-insert-bar" aria-hidden="true"></div>
{/if}
{/each}
</div>
{/if}
</div>
<div class="header-right">
@@ -204,10 +198,8 @@
.header { position: relative; z-index: 100; display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-4) var(--sp-6); border-bottom: 1px solid var(--border-dim); flex-shrink: 0; min-width: 0; }
.header-right { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; flex-shrink: 0; }
.heading { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-faint); letter-spacing: var(--tracking-wider); text-transform: uppercase; flex-shrink: 0; }
.tabs { display: flex; align-items: center; gap: 2px; background: var(--bg-raised); border: 1px solid var(--border-dim); border-radius: var(--radius-md); padding: 2px; position: relative; flex-shrink: 1; min-width: 0; overflow: hidden; }
.tabs-scroll { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; min-width: 0; flex-shrink: 1; }
.tabs-scroll::-webkit-scrollbar { display: none; }
.tab-separator { width: 1px; height: 16px; background: var(--border-dim); flex-shrink: 0; margin: 0 2px; }
.tabs { display: flex; align-items: center; gap: 2px; background: var(--bg-raised); border: 1px solid var(--border-dim); border-radius: var(--radius-md); padding: 2px; position: relative; flex-shrink: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab { position: relative; z-index: 1; display: flex; align-items: center; gap: 5px; font-family: var(--font-ui); font-size: var(--text-2xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; padding: 4px 10px; border-radius: var(--radius-sm); border: 1px solid transparent; color: var(--text-faint); white-space: nowrap; transition: background var(--t-base), color var(--t-base), border-color var(--t-base); cursor: grab; flex-shrink: 0; }
.tab:hover { color: var(--text-muted); }
.tab.active { background: var(--accent-muted); color: var(--accent-fg); border-color: var(--accent-dim); }