Merge main (update-after-download, search button) into beta

This commit is contained in:
Jonathan Sykes
2026-10-11 18:04:18 +08:00
6 changed files with 65 additions and 0 deletions

View File

@@ -8705,10 +8705,34 @@ async function maybeShowUpdateBanner() {
// swap is instant. Purely an optimisation — if it never finishes, applyUpdate // swap is instant. Purely an optimisation — if it never finishes, applyUpdate
// falls back to downloading. // falls back to downloading.
prefetchUpdate(); prefetchUpdate();
// Ask only once the new build is fully on disk, so "Refresh UI" is an
// instant swap. Until then keep downloading quietly and re-check; if the
// download never completes (8 min) ask anyway — Refresh UI then downloads.
_updateSeenAt = _updateSeenAt || Date.now();
if (!(await updateDownloaded()) && Date.now() - _updateSeenAt < 8 * 60 * 1000) {
setTimeout(maybeShowUpdateBanner, 15000);
return;
}
showUpdateBanner(server); showUpdateBanner(server);
} }
} }
let _updateSeenAt = 0;
// Is the new worker installed and holding the complete new shell? No service
// worker support (or no registration) means there is nothing to wait for.
async function updateDownloaded() {
try {
if (!('serviceWorker' in navigator)) return true;
const reg = _swReg || await navigator.serviceWorker.getRegistration();
if (!reg) return true;
if (!reg.waiting) return false;
const SU = window.SwUpdate;
if (!SU) return true;
const st = await SU.askCacheStatus(reg.waiting, { timeoutMs: 4000, setTimeout: (fn, ms) => setTimeout(fn, ms) });
return !!(st && st.ready);
} catch { return false; }
}
// Kicks the service worker into installing the new build in the background. // Kicks the service worker into installing the new build in the background.
// Safe to call repeatedly: update() is a no-op when a worker is already // Safe to call repeatedly: update() is a no-op when a worker is already
// installing or waiting. // installing or waiting.

View File

@@ -4365,3 +4365,18 @@ html[data-layout="bento-hub"] .media-shape-classic { display:none; }
html[data-layout="f7-swipe"] .media-shape-f7-swipe, html[data-layout="f7-swipe"] .media-shape-f7-swipe,
html[data-layout="glass-stage"] .media-shape-glass-stage, html[data-layout="glass-stage"] .media-shape-glass-stage,
html[data-layout="bento-hub"] .media-shape-bento-hub { display:inline; } html[data-layout="bento-hub"] .media-shape-bento-hub { display:inline; }
/* ===== Search button — one icon + label, restyled per layout and colour theme ===== */
.search-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.search-btn::before {
content: ""; width: 17px; height: 17px; flex: none; background: currentColor;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='m16 16 5 5'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='m16 16 5 5'/%3E%3C/svg%3E") center / contain no-repeat;
}
.search-btn { box-shadow: 0 8px 22px -8px var(--accent-glow), inset 0 1px 0 rgba(255, 255, 255, .28); }
.search-btn:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 3px; }
:where(:root[data-theme="light"]) .search-btn { background: var(--accent-deep); box-shadow: 0 2px 8px -2px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .25); }
:where(:root[data-theme="light"]) .search-btn:hover { background: var(--accent); box-shadow: 0 4px 12px -3px rgba(0, 0, 0, .4); }
:where(:root[data-theme="contrast"]) .search-btn { background: #fff; color: #000; border: 2px solid #fff; box-shadow: none; }
:where(:root[data-theme="contrast"]) .search-btn:hover { background: var(--accent-bright); border-color: var(--accent-bright); box-shadow: none; }
:where(:root[data-theme="contrast"]) .search-btn:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

View File

@@ -361,3 +361,6 @@ html[data-layout="bento-hub"] .main { padding-bottom:var(--bento-bottom-clearanc
html[data-layout="bento-hub"] :is(.body,.player-pane,.cards) { padding-bottom:16px; } html[data-layout="bento-hub"] :is(.body,.player-pane,.cards) { padding-bottom:16px; }
html[data-layout="bento-hub"] .modal-backdrop { z-index:600; } html[data-layout="bento-hub"] .modal-backdrop { z-index:600; }
html[data-layout="bento-hub"] .shortcut-overlay { z-index:600; } html[data-layout="bento-hub"] .shortcut-overlay { z-index:600; }
/* Bento draws its own icon span; skip the shared mask icon. */
html[data-layout="bento-hub"] .search-btn::before { display: none; }

View File

@@ -235,3 +235,11 @@ html[data-layout="classic"] .card:has(.card-note-btn) .card-note-btn { grid-colu
html[data-layout="classic"] .card:has(.card-note-btn) .card-menu { grid-column: 4; grid-row: 1; } html[data-layout="classic"] .card:has(.card-note-btn) .card-menu { grid-column: 4; grid-row: 1; }
html[data-layout="classic"] .card:has(.card-note-btn) .card-del { grid-column: 4; grid-row: 2; } html[data-layout="classic"] .card:has(.card-note-btn) .card-del { grid-column: 4; grid-row: 2; }
html[data-layout="classic"] .card:has(.card-note-btn) { column-gap: 8px; } html[data-layout="classic"] .card:has(.card-note-btn) { column-gap: 8px; }
/* Search button: outlined rectangle that fills with the accent on hover. */
html[data-layout="classic"] .search-btn { background: transparent; color: var(--accent); border: 1.5px solid var(--accent); box-shadow: none; }
html[data-layout="classic"] .search-btn:hover { background: var(--accent); color: #fff; transform: none; box-shadow: none; }
html[data-layout="classic"][data-theme="contrast"] .search-btn { background: #fff; color: #000; border-color: #fff; }
html[data-layout="classic"][data-theme="contrast"] .search-btn:hover { background: var(--accent-bright); border-color: var(--accent-bright); color: #000; }
html[data-layout="classic"][data-theme="light"] .search-btn { color: var(--accent-deep); border-color: var(--accent-deep); }
html[data-layout="classic"][data-theme="light"] .search-btn:hover { background: var(--accent-deep); color: #fff; }

View File

@@ -343,3 +343,6 @@ html[data-layout="f7-swipe"] #remoteView, html[data-layout="f7-swipe"] #presente
html[data-layout="f7-swipe"] .list-title-row h2 { font-size: 29px; } html[data-layout="f7-swipe"] .list-title-row h2 { font-size: 29px; }
html[data-layout="f7-swipe"] #cards .card { min-height: 76px; } html[data-layout="f7-swipe"] #cards .card { min-height: 76px; }
} }
/* Search button: plain accent text action (navbar style) — no icon. */
html[data-layout="f7-swipe"] .search-btn::before { display: none; }

View File

@@ -375,3 +375,15 @@ html[data-layout="glass-stage"] .svc-font button { width: 28px; height: 30px; }
html[data-layout="glass-stage"] #controls .ch-badge { cursor: pointer; font-family: var(--mono); transition: background .15s, border-color .15s; } html[data-layout="glass-stage"] #controls .ch-badge { cursor: pointer; font-family: var(--mono); transition: background .15s, border-color .15s; }
html[data-layout="glass-stage"] #controls .ch-badge:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--accent); } html[data-layout="glass-stage"] #controls .ch-badge:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--accent); }
html[data-layout="glass-stage"] #controls .ch-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } html[data-layout="glass-stage"] #controls .ch-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Search button: frosted pill, accent-tinted, with a soft glow. */
html[data-layout="glass-stage"] .search-btn {
background: color-mix(in srgb, var(--accent) 30%, transparent); color: var(--text);
border: 1px solid color-mix(in srgb, var(--accent-bright) 55%, transparent); border-radius: 999px;
-webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4);
box-shadow: 0 6px 22px -8px var(--accent-glow), inset 0 1px 0 rgba(255, 255, 255, .3);
}
html[data-layout="glass-stage"] .search-btn:hover { background: color-mix(in srgb, var(--accent) 48%, transparent); transform: translateY(-1px); }
html[data-layout="glass-stage"][data-theme="contrast"] .search-btn { background: #fff; color: #000; border-color: #fff; }
html[data-layout="glass-stage"][data-theme="light"] .search-btn { background: color-mix(in srgb, var(--accent-deep) 88%, transparent); color: #fff; border-color: color-mix(in srgb, var(--accent-deep) 70%, #fff); }
html[data-layout="glass-stage"][data-theme="light"] .search-btn:hover { background: var(--accent-deep); }