mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 09:19:56 -05:00
Fix: Library Mappings
This commit is contained in:
@@ -393,7 +393,7 @@
|
||||
{:else}
|
||||
<LibraryToolbar
|
||||
tab={libraryState.tab}
|
||||
tabSortMode={libraryState.tabSort[libraryState.tab]?.mode ?? 'alphabetical'}
|
||||
tabSortMode={libraryState.tabSort[libraryState.tab]?.mode ?? 'az'}
|
||||
tabSortDir={libraryState.tabSort[libraryState.tab]?.dir ?? 'asc'}
|
||||
tabStatus={libraryState.tabStatus[libraryState.tab] ?? 'ALL'}
|
||||
tabFilters={libraryState.tabFilters[libraryState.tab] ?? {}}
|
||||
@@ -423,7 +423,6 @@
|
||||
onFilterPanelToggle={() => filterPanelOpen = !filterPanelOpen}
|
||||
onRefresh={startRefresh}
|
||||
onCancelRefresh={cancelRefresh}
|
||||
onRefreshCategory={refreshCategory}
|
||||
onOpenDownloadsFolder={openDownloadsFolder}
|
||||
onTabDragStart={onTabDragStart}
|
||||
onTabDragOver={onTabDragOver}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { CheckSquare, Trash, Folder } from 'phosphor-svelte'
|
||||
import Thumbnail from '$lib/components/shared/manga/Thumbnail.svelte'
|
||||
import { settingsState } from '$lib/state/settings.svelte'
|
||||
import type { Manga, Category } from '$lib/types'
|
||||
|
||||
interface Props {
|
||||
@@ -27,6 +28,9 @@
|
||||
|
||||
let movePanelOpen = $state(false)
|
||||
|
||||
const statsAlways = $derived(settingsState.settings.libraryStatsAlways ?? false)
|
||||
const cropCovers = $derived(settingsState.settings.libraryCropCovers ?? true)
|
||||
|
||||
function onDocDown(e: MouseEvent) {
|
||||
if (movePanelOpen && !(e.target as HTMLElement).closest('.move-wrap')) movePanelOpen = false
|
||||
}
|
||||
@@ -114,10 +118,11 @@
|
||||
class="card"
|
||||
class:card-selected={isSelected}
|
||||
class:select-mode={selectMode}
|
||||
class:stats-always={statsAlways}
|
||||
onclick={(e) => onCardClick(e, m)}
|
||||
oncontextmenu={(e) => onCardContextMenu(e, m)}
|
||||
>
|
||||
<div class="cover-wrap" class:completed={isCompleted}>
|
||||
<div class="cover-wrap" class:completed={isCompleted} class:cover-contain={!cropCovers}>
|
||||
<Thumbnail src={m.thumbnailUrl} alt={m.title} class="cover" id={m.id} />
|
||||
<div class="overlay">
|
||||
<div class="badges">
|
||||
@@ -236,6 +241,7 @@
|
||||
.cover-wrap.completed { box-shadow: inset 0 -2px 0 0 var(--accent); }
|
||||
|
||||
:global(.cover) { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.cover-contain :global(.cover) { object-fit: contain; }
|
||||
|
||||
.overlay {
|
||||
position: absolute; bottom: 0; left: 0; right: 0; z-index: 2;
|
||||
@@ -245,6 +251,7 @@
|
||||
transition: opacity 0.18s ease;
|
||||
}
|
||||
.card:not(.select-mode):hover .overlay { opacity: 1; }
|
||||
.stats-always .overlay { opacity: 1; }
|
||||
|
||||
.badges { display: flex; align-items: flex-end; justify-content: space-between; gap: 4px; flex-wrap: wrap; }
|
||||
.badge {
|
||||
|
||||
@@ -4,21 +4,19 @@
|
||||
SortAscending, CaretUp, CaretDown, ArrowsClockwise, Star, X, CheckSquare,
|
||||
} from "phosphor-svelte";
|
||||
import LibraryFilters from "./LibraryFilters.svelte";
|
||||
import type { Category } from "@types";
|
||||
import type { LibrarySortMode, LibrarySortDir, LibraryStatusFilter, LibraryContentFilter } from "@store/state.svelte";
|
||||
import type { Category } from "$lib/types";
|
||||
import type { LibrarySortOption, LibrarySortDir, LibraryStatusFilter, LibraryContentFilter } from "$lib/state/library.svelte";
|
||||
|
||||
interface Props {
|
||||
tab: string;
|
||||
tabSortMode: LibrarySortMode;
|
||||
tabSortMode: LibrarySortOption;
|
||||
tabSortDir: LibrarySortDir;
|
||||
tabStatus: LibraryStatusFilter;
|
||||
tabFilters: Partial<Record<LibraryContentFilter, boolean>>;
|
||||
hasActiveFilters: boolean;
|
||||
anims: boolean;
|
||||
anims?: boolean;
|
||||
visibleCategories: Category[];
|
||||
visibleTabIds: string[];
|
||||
virtualTabIds: string[];
|
||||
folderTabIds: string[];
|
||||
completedCatId: number | null;
|
||||
counts: Record<string, number>;
|
||||
search: string;
|
||||
@@ -35,7 +33,7 @@
|
||||
tabsEl: HTMLDivElement;
|
||||
onSearchChange: (v: string) => void;
|
||||
onTabChange: (f: string) => void;
|
||||
onSortChange: (mode: LibrarySortMode) => void;
|
||||
onSortChange: (mode: LibrarySortOption) => void;
|
||||
onSortDirToggle: () => void;
|
||||
onStatusChange: (s: LibraryStatusFilter) => void;
|
||||
onFilterToggle: (f: LibraryContentFilter) => void;
|
||||
@@ -44,7 +42,6 @@
|
||||
onFilterPanelToggle: () => void;
|
||||
onRefresh: () => void;
|
||||
onCancelRefresh: () => void;
|
||||
onRefreshCategory: (catId: number) => void;
|
||||
onOpenDownloadsFolder: () => void;
|
||||
onTabDragStart: (e: DragEvent, id: string) => void;
|
||||
onTabDragOver: (e: DragEvent, id: string, idx: number) => void;
|
||||
@@ -55,13 +52,13 @@
|
||||
|
||||
let {
|
||||
tab, tabSortMode, tabSortDir, tabStatus, tabFilters, hasActiveFilters,
|
||||
anims, visibleCategories, visibleTabIds, virtualTabIds, folderTabIds, completedCatId,
|
||||
anims = false, visibleCategories, visibleTabIds, completedCatId,
|
||||
counts, search, refreshing, refreshProgress, refreshDone, refreshingCatId,
|
||||
activeDragKind, dragInsertIdx, dragTabId, dragOverTabId, sortPanelOpen, filterPanelOpen,
|
||||
tabsEl = $bindable(),
|
||||
onSearchChange, onTabChange, onSortChange, onSortDirToggle, onStatusChange,
|
||||
onFilterToggle, onFiltersClear, onSortPanelToggle, onFilterPanelToggle,
|
||||
onRefresh, onCancelRefresh, onRefreshCategory, onOpenDownloadsFolder,
|
||||
onRefresh, onCancelRefresh, onOpenDownloadsFolder,
|
||||
onTabDragStart, onTabDragOver, onTabDragLeave, onTabDrop, onTabDragEnd,
|
||||
}: Props = $props();
|
||||
|
||||
@@ -85,18 +82,18 @@
|
||||
else if (ol + ow > pl + cw) tabsEl.scrollTo({ left: ol + ow - cw, behavior: "smooth" });
|
||||
});
|
||||
|
||||
const SORT_LABELS: Record<LibrarySortMode, string> = {
|
||||
const SORT_LABELS: Record<LibrarySortOption, string> = {
|
||||
az: "A–Z",
|
||||
unreadCount: "Unread chapters",
|
||||
totalChapters: "Total chapters",
|
||||
recentlyAdded: "Recently added",
|
||||
recentlyRead: "Recently read",
|
||||
dateAdded: "Recently added",
|
||||
lastRead: "Recently read",
|
||||
latestFetched: "Latest fetched chapter",
|
||||
latestUploaded: "Latest uploaded chapter",
|
||||
};
|
||||
|
||||
const ALL_SORT_MODES: LibrarySortMode[] = [
|
||||
"az", "unreadCount", "totalChapters", "recentlyAdded", "recentlyRead", "latestFetched", "latestUploaded",
|
||||
const ALL_SORT_MODES: LibrarySortOption[] = [
|
||||
"az", "unreadCount", "totalChapters", "dateAdded", "lastRead", "latestFetched", "latestUploaded",
|
||||
];
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import type { Category } from "$lib/types";
|
||||
import { settingsState, updateSettings } from "$lib/state/settings.svelte";
|
||||
|
||||
export type LibrarySortOption =
|
||||
| "alphabetical"
|
||||
| "unread"
|
||||
| "az"
|
||||
| "unreadCount"
|
||||
| "lastRead"
|
||||
| "dateAdded"
|
||||
| "totalChapters"
|
||||
@@ -153,11 +153,11 @@ class LibraryState {
|
||||
if (f.downloaded) items = items.filter(m => (m.downloadCount ?? 0) > 0);
|
||||
if (f.bookmarked) items = items.filter(m => (m.bookmarkCount ?? 0) > 0);
|
||||
|
||||
const { mode, dir } = this.tabSort[tab] ?? { mode: "alphabetical" as LibrarySortOption, dir: "asc" as LibrarySortDir };
|
||||
const { mode, dir } = this.tabSort[tab] ?? { mode: "az" as LibrarySortOption, dir: "asc" as LibrarySortDir };
|
||||
|
||||
const sorted = [...items].sort((a, b) => {
|
||||
switch (mode) {
|
||||
case "unread": return (b.unreadCount ?? 0) - (a.unreadCount ?? 0);
|
||||
case "unreadCount": return (b.unreadCount ?? 0) - (a.unreadCount ?? 0);
|
||||
case "lastRead": return (b.lastReadAt ?? 0) - (a.lastReadAt ?? 0);
|
||||
case "dateAdded": return (b.addedAt ?? 0) - (a.addedAt ?? 0);
|
||||
case "totalChapters": return (b.chapters?.totalCount ?? 0) - (a.chapters?.totalCount ?? 0);
|
||||
@@ -185,7 +185,7 @@ class LibraryState {
|
||||
|
||||
toggleTabSortDir(tab: string) {
|
||||
const prev = this.tabSort[tab];
|
||||
const mode = prev?.mode ?? "alphabetical";
|
||||
const mode = prev?.mode ?? "az";
|
||||
const dir = prev?.dir === "asc" ? "desc" : "asc";
|
||||
this.setTabSort(tab, mode, dir);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user