diff --git a/src/lib/ui/chrome/Sidebar.svelte b/src/lib/ui/chrome/Sidebar.svelte index 9f4716a..88e71f7 100644 --- a/src/lib/ui/chrome/Sidebar.svelte +++ b/src/lib/ui/chrome/Sidebar.svelte @@ -2,7 +2,7 @@ import { page } from '$app/stores' import { House, Books, MagnifyingGlass, - DownloadSimple, PuzzlePiece, GearSix, ChartLineUp, + DownloadSimple, PuzzlePiece, GearSix, ChartLineUp, ClockCounterClockwise, } from 'phosphor-svelte' import logoUrl from '$lib/assets/moku-icon-wordmark.svg' @@ -13,6 +13,7 @@ { path: '/downloads', label: 'Downloads', icon: DownloadSimple }, { path: '/extensions', label: 'Extensions', icon: PuzzlePiece }, { path: '/tracking', label: 'Tracking', icon: ChartLineUp }, + { path: '/history', label: 'History', icon: ClockCounterClockwise }, ] as const const TAB_SIZE = 36 @@ -42,7 +43,7 @@ {#if activeIndex >= 0}
{/if} - {#each TABS as tab} + {#each TABS as tab (tab.path)} + import { onMount } from 'svelte' + import { BookOpen, Books, ClockCounterClockwise, DownloadSimple } from 'phosphor-svelte' + import { loadLibrary } from '$lib/request-manager/manga' + import { downloadCount } from '$lib/state/downloads.svelte' + import { historyState, initHistoryState } from '$lib/state/history.svelte' + import { libraryState } from '$lib/state/library.svelte' - \ No newline at end of file + const recentHistory = $derived(historyState.history.slice(0, 8)) + + const stats = $derived.by(() => [ + { + label: 'Library Manga', + value: libraryState.items.length, + icon: Books, + }, + { + label: 'Chapters Read', + value: historyState.readingStats.totalChaptersRead, + icon: BookOpen, + }, + { + label: 'Active Downloads', + value: downloadCount, + icon: DownloadSimple, + }, + { + label: 'Current Streak', + value: historyState.readingStats.currentStreakDays, + icon: ClockCounterClockwise, + suffix: 'days', + }, + ]) + + onMount(async () => { + await initHistoryState() + + if (libraryState.items.length === 0) { + await loadLibrary({ inLibrary: true }) + } + }) + + function formatTimestamp(value: number): string { + if (!value) return 'Unknown' + return new Date(value).toLocaleString() + } + + +
+
+
+

Dashboard

+

Welcome back

+

Quick read stats and recent progress across your library.

+
+
+
+ +
+ {#each stats as stat (stat.label)} +
+
+

{stat.label}

+

+ {stat.value} + {#if stat.suffix} + {stat.suffix} + {/if} +

+
+ {/each} +
+ +
+
+

Recent Activity

+ Open full history +
+ + {#if recentHistory.length === 0} +
No recent reading activity yet.
+ {:else} + + {/if} +
+
+ + \ No newline at end of file diff --git a/src/routes/browse/+page.svelte b/src/routes/browse/+page.svelte index 1834d07..09ac407 100644 --- a/src/routes/browse/+page.svelte +++ b/src/routes/browse/+page.svelte @@ -1 +1,268 @@ -

browse

\ No newline at end of file + + +
+
+
+

Browse Sources

+

{filteredSources.length} available

+
+ +
+ + + + + +
+
+ + {#if extensionsState.error} +
+

Unable to load sources.

+ {extensionsState.error} + +
+ {:else if filteredSources.length === 0} +
No sources match the current filters.
+ {:else} + + {/if} +
+ + diff --git a/src/routes/browse/[sourceId]/+page.svelte b/src/routes/browse/[sourceId]/+page.svelte new file mode 100644 index 0000000..d6d1e1a --- /dev/null +++ b/src/routes/browse/[sourceId]/+page.svelte @@ -0,0 +1,252 @@ + + +
+
+
+ + + All sources + +

{currentSource?.displayName ?? 'Source'}

+

+ {currentSource?.lang?.toUpperCase() ?? 'N/A'} + {#if currentSource?.isNsfw} + · NSFW + {/if} +

+
+ +
+ + +
+ + + Page {page} + + +
+
+
+ + {#if extensionsState.browseError} +
+

Unable to browse this source.

+ {extensionsState.browseError} + +
+ {:else if extensionsState.browseLoading && extensionsState.browseResults.length === 0} +
Loading manga...
+ {:else if extensionsState.browseResults.length === 0} +
No manga found on this page.
+ {:else} +
+ {#each extensionsState.browseResults as manga (manga.id)} + + {/each} +
+ {/if} +
+ + diff --git a/src/routes/downloads/+page.svelte b/src/routes/downloads/+page.svelte index 4c7d13c..56ad628 100644 --- a/src/routes/downloads/+page.svelte +++ b/src/routes/downloads/+page.svelte @@ -1 +1,300 @@ -

downloads

\ No newline at end of file + + +
+
+
+

Downloads

+

{downloadCount} total · {activeDownloads.length} active · {queuedDownloads.length} queued

+
+ +
+ + +
+
+ + {#if downloadsState.error} +
+

Unable to load downloads.

+ {downloadsState.error} + +
+ {:else if downloadsState.items.length === 0} +
+ + Nothing in the queue. +
+ {:else} + + {/if} +
+ + \ No newline at end of file diff --git a/src/routes/extensions/+page.svelte b/src/routes/extensions/+page.svelte index c5a99ce..7c81e09 100644 --- a/src/routes/extensions/+page.svelte +++ b/src/routes/extensions/+page.svelte @@ -1 +1,350 @@ -

extensions

\ No newline at end of file + + +
+
+
+

Extensions

+

{filteredExtensions.length} shown · {extensionsState.items.length} total

+
+ +
+ + + + + + + + +
+
+ + {#if extensionsState.error} +
+

Unable to load extensions.

+ {extensionsState.error} + +
+ {:else if extensionsState.loading && extensionsState.items.length === 0} +
Loading extensions...
+ {:else if filteredExtensions.length === 0} +
No extensions match the current filters.
+ {:else} + + {/if} +
+ + \ No newline at end of file diff --git a/src/routes/history/+page.svelte b/src/routes/history/+page.svelte new file mode 100644 index 0000000..5cbc8d8 --- /dev/null +++ b/src/routes/history/+page.svelte @@ -0,0 +1,296 @@ + + +
+
+
+

History

+

+ {historyState.history.length} reads · + {historyState.bookmarks.length} bookmarks · + {historyState.readingStats.totalChaptersRead} chapters completed +

+
+ +
+ + +
+ + +
+ + +
+
+ + {#if historyStatus.loading} +
Loading history...
+ {:else if historyStatus.error} +
+

Unable to load local history data.

+ {historyStatus.error} +
+ {:else if tab === 'history' && filteredHistory.length === 0} +
No reading history matches your filter.
+ {:else if tab === 'bookmarks' && filteredBookmarks.length === 0} +
No bookmarks match your filter.
+ {:else if tab === 'history'} + + {:else} + + {/if} +
+ + diff --git a/src/routes/tracking/+page.svelte b/src/routes/tracking/+page.svelte index 9b95035..82148a8 100644 --- a/src/routes/tracking/+page.svelte +++ b/src/routes/tracking/+page.svelte @@ -1 +1,301 @@ -

tracking

\ No newline at end of file + + +
+
+
+

Tracking

+

{visibleTrackers.length} trackers · {records.length} records

+
+ +
+ + + + + +
+
+ + {#if trackingState.error} +
+

Unable to load tracking data.

+ {trackingState.error} + +
+ {:else if trackingState.loading && trackingState.trackers.length === 0} +
Loading trackers...
+ {:else if records.length === 0} +
No tracked entries match the current filters.
+ {:else} + + {/if} +
+ + \ No newline at end of file