Integrate updates into recent activity page

This commit is contained in:
Zerebos
2026-05-21 03:29:13 +00:00
parent d025d07e07
commit 9e56b1176c
6 changed files with 129 additions and 17 deletions
@@ -0,0 +1,90 @@
<script lang="ts">
import HistoryPanel from "./HistoryPanel.svelte";
import UpdatesPanel from "./UpdatesPanel.svelte";
type RecentTab = "updates" | "history";
let tab = $state<RecentTab>("updates");
</script>
<div class="root anim-fade-in">
<div class="header">
<span class="heading">Recent</span>
<div class="tabs">
<button class="tab" class:active={tab === "updates"} onclick={() => tab = "updates"}>
Updates
</button>
<button class="tab" class:active={tab === "history"} onclick={() => tab = "history"}>
Reading history
</button>
</div>
</div>
<div class="content">
{#if tab === "updates"}
<UpdatesPanel />
{:else}
<HistoryPanel />
{/if}
</div>
</div>
<style>
.root {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.header {
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;
}
.heading {
font-family: var(--font-ui);
font-size: var(--text-xs);
font-weight: var(--weight-medium);
color: var(--text-muted);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
}
.tabs {
display: flex;
gap: 2px;
background: var(--bg-raised);
border: 1px solid var(--border-dim);
border-radius: var(--radius-md);
padding: 2px;
}
.tab {
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);
color: var(--text-faint);
white-space: nowrap;
transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
border: 1px solid transparent;
}
.tab:hover { color: var(--text-muted); }
.tab.active { background: var(--accent-muted); color: var(--accent-fg); border-color: var(--accent-dim); }
.content {
flex: 1;
min-height: 0;
overflow: hidden;
}
</style>
@@ -4,7 +4,7 @@
import { gql } from "@api/client";
import { GET_RECENTLY_UPDATED, GET_CHAPTERS } from "@api/queries";
import { store, openReader, setActiveManga, addToast } from "@store/state.svelte";
import { dayLabel, timeAgo } from "@core/util";
import { dayLabel } from "@core/util";
import { buildReaderChapterList } from "@features/series/lib/chapterList";
import Thumbnail from "@shared/manga/Thumbnail.svelte";
import type { Chapter, Manga } from "@types";
@@ -48,6 +48,24 @@
return Array.from(map.entries()).map(([label, items]) => ({ label, items })) as UpdateGroup[];
});
const lastUpdatedTs = $derived(
store.lastLibraryRefresh > 0
? store.lastLibraryRefresh
: (updates.length > 0 ? fetchedAtMs(updates[0]) : null)
);
const lastUpdatedLabel = $derived(
lastUpdatedTs
? new Date(lastUpdatedTs).toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
})
: "Never"
);
function mangaStub(item: RecentUpdate): Manga {
return {
id: item.manga?.id ?? item.mangaId,
@@ -116,7 +134,8 @@
<div class="header">
<div class="heading-group">
<ArrowsClockwise size={13} weight="light" class="heading-icon" />
<span class="heading">Updates</span>
<span class="heading">Library updates</span>
<span class="last-updated">Last updated: {lastUpdatedLabel}</span>
</div>
<button class="icon-btn" onclick={loadUpdates} disabled={loading} title="Refresh updates">
{#if loading}<CircleNotch size={14} weight="light" class="anim-spin" />
@@ -173,12 +192,11 @@
<span class="chapter-title">{chapterLabel(item)}</span>
<div class="meta-row">
<span>{timeAgo(fetchedAtMs(item))}</span>
{#if (item.lastPageRead ?? 0) > 0 && !item.isRead}
<span>· Resume p.{item.lastPageRead}</span>
{/if}
</div>
{#if (item.lastPageRead ?? 0) > 0 && !item.isRead}
<div class="meta-row">
<span>Resume p.{item.lastPageRead}</span>
</div>
{/if}
</div>
<div class="row-end">
@@ -231,6 +249,14 @@
text-transform: uppercase;
}
.last-updated {
font-family: var(--font-ui);
font-size: var(--text-2xs);
color: var(--text-faint);
letter-spacing: var(--tracking-wide);
text-transform: none;
}
.icon-btn {
display: flex;
align-items: center;
+2 -5
View File
@@ -1,7 +1,6 @@
<script lang="ts">
import { store } from "@store/state.svelte";
import Sidebar from "@shared/chrome/Sidebar.svelte";
import RecentActivity from "@shared/chrome/RecentActivity.svelte";
import Library from "@features/library/components/Library.svelte";
import SeriesDetail from "@features/series/components/SeriesDetail.svelte";
import Home from "@features/home/components/Home.svelte";
@@ -10,7 +9,7 @@
import Downloads from "@features/downloads/components/Downloads.svelte";
import Extensions from "@features/extensions/components/Extensions.svelte";
import Tracking from "@features/tracking/components/Tracking.svelte";
import Updates from "@features/updates/components/Updates.svelte";
import Recent from "@features/recent/components/Recent.svelte";
</script>
<div class="frame">
@@ -25,12 +24,10 @@
<Home />
{:else if store.navPage === "library"}
<Library />
{:else if store.navPage === "updates"}
<Updates />
{:else if store.navPage === "search"}
<Search />
{:else if store.navPage === "history"}
<RecentActivity />
<Recent />
{:else if store.navPage === "downloads"}
<Downloads />
{:else if store.navPage === "extensions"}
+2 -3
View File
@@ -1,14 +1,13 @@
<script lang="ts">
import { House, Books, MagnifyingGlass, ArrowsClockwise, ClockCounterClockwise, DownloadSimple, PuzzlePiece, GearSix, ChartLineUp } from "phosphor-svelte";
import { House, Books, MagnifyingGlass, ClockCounterClockwise, DownloadSimple, PuzzlePiece, GearSix, ChartLineUp } from "phosphor-svelte";
import { store } from "@store/state.svelte";
import type { NavPage } from "@store/state.svelte";
const TABS: { id: NavPage; label: string; icon: any }[] = [
{ id: "home", label: "Home", icon: House },
{ id: "library", label: "Library", icon: Books },
{ id: "updates", label: "Updates", icon: ArrowsClockwise },
{ id: "search", label: "Search", icon: MagnifyingGlass },
{ id: "history", label: "History", icon: ClockCounterClockwise },
{ id: "history", label: "Recent", icon: ClockCounterClockwise },
{ id: "downloads", label: "Downloads", icon: DownloadSimple },
{ id: "extensions", label: "Extensions", icon: PuzzlePiece },
{ id: "tracking", label: "Tracking", icon: ChartLineUp },
+1 -1
View File
@@ -1,5 +1,5 @@
export type NavPage =
| "home" | "library" | "updates" | "sources" | "explore"
| "home" | "library" | "sources" | "explore"
| "downloads" | "extensions" | "history" | "search" | "tracking";
class AppStore {