Add offline cache & preload, Save/add-to-playlist UI, Settings page; player stream fallback + progressive-first ordering; protocol-asset feature; refresh Windows installers

This commit is contained in:
Jonathan Sykes
2026-06-14 11:36:01 +08:00
parent 5375843c82
commit 63560a8e61
12 changed files with 766 additions and 35 deletions

View File

@@ -405,7 +405,31 @@ input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.25); }
}
.sel select:hover { border-color: var(--accent); }
.now-meta { margin-top: 18px; }
.now-meta {
margin-top: 18px;
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
}
.np-text { min-width: 0; }
.np-actions { display: flex; gap: 8px; flex-shrink: 0; }
.np-btn {
background: var(--bg-3);
border: 1px solid var(--line);
color: var(--text-2);
border-radius: 9px;
padding: 9px 14px;
cursor: pointer;
font-family: var(--ui);
font-size: 13px;
font-weight: 600;
white-space: nowrap;
transition: all 0.16s var(--ease);
}
.np-btn:hover { color: var(--text); border-color: var(--accent); background: var(--bg-2); transform: translateY(-1px); }
.np-btn:disabled { opacity: 0.6; cursor: default; transform: none; }
.np-btn.done { color: #7ee0a8; border-color: rgba(126,224,168,0.35); }
.np-title {
font-family: var(--display);
font-weight: 700;
@@ -539,20 +563,98 @@ input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.25); }
}
.card-channel { font-size: 12px; color: var(--text-dim); margin-top: 5px; }
.card-menu {
background: transparent;
border: 1px solid transparent;
color: var(--text-dim);
background: var(--bg-3);
border: 1px solid var(--line);
color: var(--text-2);
border-radius: 8px;
width: 30px; height: 30px;
width: 32px; height: 32px;
cursor: pointer;
align-self: center;
flex-shrink: 0;
font-size: 17px;
font-size: 19px;
line-height: 1;
transition: all 0.16s;
opacity: 0;
opacity: 0.9;
}
.card:hover .card-menu { opacity: 1; }
.card-menu:hover { color: var(--accent-bright); border-color: var(--accent); background: var(--bg-3); }
.card-menu:hover { color: #fff; border-color: var(--accent); background: var(--accent); }
/* Saved-offline badge on cards */
.saved-badge {
position: absolute; left: 5px; bottom: 5px;
display: none;
align-items: center; justify-content: center;
width: 18px; height: 18px;
background: rgba(126, 224, 168, 0.92);
color: #06281a;
font-size: 10px; font-weight: 700;
border-radius: 5px;
backdrop-filter: blur(2px);
}
.card.cached .saved-badge { display: flex; }
.card.downloading .saved-badge {
display: flex;
background: rgba(255, 200, 80, 0.92);
color: #2a1d00;
animation: pulse 1s ease-in-out infinite;
}
.card.downloading .saved-badge::before { content: "⏳"; }
.card.downloading .saved-badge { font-size: 0; }
.card.downloading .saved-badge::before { font-size: 10px; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }
/* ===================== Settings page ===================== */
.settings { display: flex; flex-direction: column; gap: 18px; padding: 4px 6px 28px; }
.set-group {
background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 16px 18px;
}
.set-group-title {
font-family: var(--mono);
font-size: 10px; font-weight: 700;
text-transform: uppercase; letter-spacing: 0.16em;
color: var(--accent);
margin-bottom: 14px;
}
.set-row {
display: flex; align-items: center; justify-content: space-between;
gap: 14px;
padding: 10px 0;
border-top: 1px solid var(--line-soft);
}
.set-group .set-row:first-of-type { border-top: none; }
.set-row > span { display: flex; flex-direction: column; gap: 3px; color: var(--text); font-size: 13.5px; font-weight: 500; }
.set-row small { color: var(--text-dim); font-size: 11.5px; font-weight: 400; line-height: 1.4; max-width: 280px; }
.set-row input[type="range"] { width: 150px; }
.set-row input[type="checkbox"] { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
.set-select {
background: var(--bg-3); color: var(--text);
border: 1px solid var(--line); border-radius: 9px;
padding: 8px 10px; font-family: var(--mono); font-size: 12px; cursor: pointer;
}
.set-select:hover { border-color: var(--accent); }
.set-stat { font-family: var(--mono); font-size: 12px; color: var(--text-2); }
.set-actions { padding-top: 14px; }
.cache-list { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.cache-empty { color: var(--text-dim); font-size: 12.5px; padding: 8px 0; }
.cache-item {
display: flex; align-items: center; gap: 10px;
padding: 8px 10px;
background: var(--bg-3);
border: 1px solid var(--line-soft);
border-radius: 8px;
}
.cache-item .ci-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
.cache-item .ci-size { font-family: var(--mono); font-size: 11px; color: var(--text-dim); }
.cache-item .ci-del {
background: transparent; border: 1px solid var(--line);
color: var(--text-dim); width: 24px; height: 24px;
border-radius: 6px; cursor: pointer; font-size: 12px; line-height: 1;
transition: all 0.16s;
}
.cache-item .ci-del:hover { color: #fff; background: var(--accent); border-color: var(--accent); }
/* ===================== Modal ===================== */
.modal-backdrop {