From 4e2ad6cae773e7b3da026d15d18f40c43575b8a1 Mon Sep 17 00:00:00 2001 From: Zerebos Date: Thu, 21 May 2026 04:03:53 +0000 Subject: [PATCH] Hoist toolbar into Recent, add status bar, dim read chapters, split cover click --- .../recent/components/HistoryPanel.svelte | 141 +---------- src/features/recent/components/Recent.svelte | 141 ++++++++++- .../recent/components/UpdatesPanel.svelte | 219 +++++++++--------- 3 files changed, 255 insertions(+), 246 deletions(-) diff --git a/src/features/recent/components/HistoryPanel.svelte b/src/features/recent/components/HistoryPanel.svelte index 323b8ff..cb0cc86 100644 --- a/src/features/recent/components/HistoryPanel.svelte +++ b/src/features/recent/components/HistoryPanel.svelte @@ -1,8 +1,8 @@
- -
-
- - History -
-
-
- - - {#if search} - - {/if} -
- {#if store.history.length > 0} - - {/if} -
-
- {#if store.readingStats.totalChaptersRead > 0}
@@ -230,100 +201,6 @@ overflow: hidden; } - .header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--sp-4) var(--sp-6); - border-bottom: 1px solid var(--border-dim); - flex-shrink: 0; - } - - .heading-group { - display: flex; - align-items: center; - gap: var(--sp-2); - } - - :global(.heading-icon) { color: var(--text-faint); } - - .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; - } - - .header-right { - display: flex; - align-items: center; - gap: var(--sp-2); - } - - .search-wrap { - position: relative; - display: flex; - align-items: center; - } - - .search-wrap :global(.search-icon) { - position: absolute; - left: 8px; - color: var(--text-faint); - pointer-events: none; - } - - .search { - background: var(--bg-raised); - border: 1px solid var(--border-dim); - border-radius: var(--radius-md); - padding: 4px 26px; - color: var(--text-primary); - font-size: var(--text-xs); - width: 148px; - outline: none; - transition: border-color var(--t-base), width var(--t-base), background var(--t-base); - } - - .search::placeholder { color: var(--text-faint); } - - .search:focus { - border-color: var(--border-strong); - background: var(--bg-elevated); - width: 200px; - } - - .search-clear { - position: absolute; - right: 8px; - color: var(--text-faint); - font-size: 13px; - line-height: 1; - background: none; - border: none; - cursor: pointer; - padding: 2px; - transition: color var(--t-base); - } - - .search-clear:hover { color: var(--text-muted); } - - .clear-btn { - display: flex; align-items: center; gap: 4px; - height: 30px; padding: 0 var(--sp-2); - border-radius: var(--radius-md); border: 1px solid var(--border-dim); - background: var(--bg-raised); color: var(--text-faint); - cursor: pointer; font-family: var(--font-ui); font-size: var(--text-2xs); - letter-spacing: var(--tracking-wide); flex-shrink: 0; - transition: color var(--t-base), background var(--t-base), border-color var(--t-base); - } - .clear-btn:hover { color: var(--color-error); background: var(--color-error-bg); border-color: color-mix(in srgb, var(--color-error) 30%, transparent); } - .clear-btn.confirm { color: var(--color-error); background: var(--color-error-bg); border-color: var(--color-error); } - - .clear-label { font-size: var(--text-2xs); } - .stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); diff --git a/src/features/recent/components/Recent.svelte b/src/features/recent/components/Recent.svelte index 532f06a..e7350e3 100644 --- a/src/features/recent/components/Recent.svelte +++ b/src/features/recent/components/Recent.svelte @@ -1,14 +1,35 @@
Recent +
+ +
+ {#if tab === "updates"} + + {:else} +
+ + historySearch = (e.target as HTMLInputElement).value} + /> + {#if historySearch} + + {/if} +
+ {#if store.history.length > 0} + + {/if} + {/if} +
{#if tab === "updates"} - + updatesRefreshFn = fn} + /> {:else} - + {/if}
@@ -82,6 +142,83 @@ .tab:hover { color: var(--text-muted); } .tab.active { background: var(--accent-muted); color: var(--accent-fg); border-color: var(--accent-dim); } + .header-right { + display: flex; + align-items: center; + gap: var(--sp-2); + margin-left: auto; + } + + .icon-btn { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + border-radius: var(--radius-md); + border: 1px solid var(--border-dim); + background: var(--bg-raised); + color: var(--text-faint); + cursor: pointer; + transition: color var(--t-base), border-color var(--t-base), background var(--t-base); + } + .icon-btn:hover:not(:disabled) { color: var(--text-primary); border-color: var(--border-strong); } + .icon-btn:disabled { opacity: 0.45; cursor: default; } + + .search-wrap { + position: relative; + display: flex; + align-items: center; + } + + .search-wrap :global(.search-icon) { + position: absolute; + left: 8px; + color: var(--text-faint); + pointer-events: none; + } + + .search { + background: var(--bg-raised); + border: 1px solid var(--border-dim); + border-radius: var(--radius-md); + padding: 4px 26px; + color: var(--text-primary); + font-size: var(--text-xs); + width: 148px; + outline: none; + transition: border-color var(--t-base), width var(--t-base), background var(--t-base); + } + .search::placeholder { color: var(--text-faint); } + .search:focus { border-color: var(--border-strong); background: var(--bg-elevated); width: 200px; } + + .search-clear { + position: absolute; + right: 8px; + color: var(--text-faint); + font-size: 13px; + line-height: 1; + background: none; + border: none; + cursor: pointer; + padding: 2px; + transition: color var(--t-base); + } + .search-clear:hover { color: var(--text-muted); } + + .clear-btn { + display: flex; align-items: center; gap: 4px; + height: 28px; padding: 0 var(--sp-2); + border-radius: var(--radius-md); border: 1px solid var(--border-dim); + background: var(--bg-raised); color: var(--text-faint); + cursor: pointer; font-family: var(--font-ui); font-size: var(--text-2xs); + letter-spacing: var(--tracking-wide); flex-shrink: 0; + transition: color var(--t-base), background var(--t-base), border-color var(--t-base); + } + .clear-btn:hover { color: var(--color-error); background: var(--color-error-bg); border-color: color-mix(in srgb, var(--color-error) 30%, transparent); } + .clear-btn.confirm { color: var(--color-error); background: var(--color-error-bg); border-color: var(--color-error); } + .clear-label { font-size: var(--text-2xs); } + .content { flex: 1; min-height: 0; diff --git a/src/features/recent/components/UpdatesPanel.svelte b/src/features/recent/components/UpdatesPanel.svelte index 8d89e2e..2949387 100644 --- a/src/features/recent/components/UpdatesPanel.svelte +++ b/src/features/recent/components/UpdatesPanel.svelte @@ -1,6 +1,6 @@
-
-
- - Library updates - Last updated: {lastUpdatedLabel} +
+
+
+ + {#if loading}Checking for updates…{:else if error}Update check failed{:else}Up to date{/if} + +
+ {#if !loading && lastCheckedLabel} + Last checked: {lastCheckedLabel} +
+ {/if} + {#if !loading && updates.length > 0} + {updates.length} chapter{updates.length === 1 ? "" : "s"} + {/if} +
-
{#if loading && updates.length === 0} @@ -177,36 +188,38 @@
{#each items as item (item.id)} -
+ -
-
- {item.manga?.title ?? "Unknown series"} - {#if !item.isRead} - Unread +
- -
- {#if openingId === item.id} - - {:else} - - {/if} -
- +
+ {#if openingId === item.id} + + {:else} + + {/if} +
+ +
{/each}
@@ -223,60 +236,21 @@ overflow: hidden; } - .header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--sp-4) var(--sp-6); - border-bottom: 1px solid var(--border-dim); - flex-shrink: 0; - } + .bar-wrap { padding: var(--sp-3) var(--sp-6); flex-shrink: 0; } - .heading-group { - display: flex; - align-items: center; - gap: var(--sp-2); - } - - :global(.heading-icon) { color: var(--text-faint); } - - .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; - } - - .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; - justify-content: center; - width: 30px; - height: 30px; - border-radius: var(--radius-md); - border: 1px solid var(--border-dim); - background: var(--bg-raised); - color: var(--text-faint); - cursor: pointer; - transition: color var(--t-base), border-color var(--t-base), background var(--t-base); - } - .icon-btn:hover:not(:disabled) { color: var(--text-primary); border-color: var(--border-strong); } - .icon-btn:disabled { opacity: 0.45; cursor: default; } + .status-bar { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--bg-surface, var(--bg-raised)); border: 1px solid var(--border-strong, var(--border-dim)); border-radius: var(--radius-md); box-shadow: 0 1px 4px rgba(0,0,0,0.25); } + .status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint); flex-shrink: 0; transition: background var(--t-base); } + .status-dot.active { background: var(--accent); animation: pulse 1.6s ease infinite; } + .status-text { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-muted); flex: 1; letter-spacing: var(--tracking-wide); } + .status-right { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; } + .status-detail { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-faint); letter-spacing: var(--tracking-wide); } + .status-count { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--text-faint); letter-spacing: var(--tracking-wide); } + .bar-sep { width: 1px; height: 12px; background: var(--border-dim); flex-shrink: 0; } .timeline { flex: 1; overflow-y: auto; - padding: var(--sp-5) var(--sp-6) var(--sp-6); + padding: var(--sp-4) var(--sp-6) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-5); @@ -316,42 +290,60 @@ } .update-row { - display: grid; - grid-template-columns: 52px minmax(0, 1fr) auto; - align-items: center; - gap: var(--sp-3); - width: 100%; - padding: var(--sp-2); + display: flex; + align-items: stretch; border-radius: var(--radius-lg); border: 1px solid var(--border-dim); background: var(--bg-base); - cursor: pointer; - text-align: left; - transition: background var(--t-base), border-color var(--t-base), transform var(--t-base); + overflow: hidden; + transition: border-color var(--t-base), transform var(--t-base); } - .update-row:hover:not(:disabled) { - background: var(--bg-raised); + .update-row:has(.info-btn:hover:not(:disabled)) { border-color: var(--border-strong); transform: translateY(-1px); } - .update-row:disabled { cursor: default; opacity: 0.8; } + .update-row.read { opacity: 0.5; } - .thumb-wrap { + .thumb-btn { width: 52px; - aspect-ratio: 2 / 3; - border-radius: var(--radius-md); - overflow: hidden; - background: var(--bg-overlay); - border: 1px solid var(--border-dim); + flex-shrink: 0; + padding: var(--sp-2); + background: none; + border: none; + border-right: 1px solid var(--border-dim); + cursor: pointer; + display: flex; + align-items: center; + transition: background var(--t-base); } + .thumb-btn:hover { background: var(--bg-raised); } + :global(.thumb) { width: 100%; - height: 100%; + aspect-ratio: 2 / 3; display: block; object-fit: cover; + border-radius: var(--radius-sm); } + .info-btn { + flex: 1; + min-width: 0; + display: flex; + align-items: center; + gap: var(--sp-3); + padding: var(--sp-2) var(--sp-3); + background: none; + border: none; + cursor: pointer; + text-align: left; + transition: background var(--t-base); + } + .info-btn:hover:not(:disabled) { background: var(--bg-raised); } + .info-btn:disabled { cursor: default; opacity: 0.8; } + .update-info { + flex: 1; min-width: 0; display: flex; flex-direction: column; @@ -409,6 +401,7 @@ align-items: center; justify-content: center; width: 24px; + flex-shrink: 0; } .empty { @@ -447,4 +440,6 @@ font-size: var(--text-xs); color: var(--text-faint); } + + @keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: 0.4 } }