Calendar: view switcher with a Compact (art-hidden) view
Adds a Cards/Compact toggle next to the week filter. Compact drops the 16:9 episode art (.vcal-art) — the big space eater — and tightens the cells so a lot more episodes fit on screen at once; ownership (which the art's ✓ badge used to show) becomes a green left accent stripe on owned cells. Just toggles a class on the stable grid wrapper (no refetch), and the choice persists in localStorage. Calendar-only; music side untouched.
This commit is contained in:
parent
7c1644384d
commit
987cee7cb3
3 changed files with 52 additions and 2 deletions
|
|
@ -962,6 +962,16 @@
|
|||
<button class="vcal-nav-today" type="button" data-video-cal-today>Today</button>
|
||||
<button class="vcal-nav-btn" type="button" data-video-cal-next aria-label="Next week">›</button>
|
||||
</div>
|
||||
<div class="vcal-views" role="group" aria-label="View">
|
||||
<button class="vcal-view-btn vcal-view-btn--on" type="button" data-video-cal-view="cards" title="Card view with episode art">
|
||||
<svg width="13" height="13" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><rect x="1" y="1" width="6" height="6" rx="1.6"/><rect x="9" y="1" width="6" height="6" rx="1.6"/><rect x="1" y="9" width="6" height="6" rx="1.6"/><rect x="9" y="9" width="6" height="6" rx="1.6"/></svg>
|
||||
<span>Cards</span>
|
||||
</button>
|
||||
<button class="vcal-view-btn" type="button" data-video-cal-view="compact" title="Compact view — hide art to fit more episodes">
|
||||
<svg width="13" height="13" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><rect x="1" y="2.4" width="14" height="2.3" rx="1.1"/><rect x="1" y="6.85" width="14" height="2.3" rx="1.1"/><rect x="1" y="11.3" width="14" height="2.3" rx="1.1"/></svg>
|
||||
<span>Compact</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="vcal-filter" role="group" aria-label="Filter">
|
||||
<button class="vcal-filter-btn vcal-filter-btn--on" type="button" data-video-cal-filter="all">All</button>
|
||||
<button class="vcal-filter-btn" type="button" data-video-cal-filter="owned">In library</button>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
var MO = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
var MO_FULL = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
|
||||
'September', 'October', 'November', 'December'];
|
||||
var state = { loaded: false, eps: {}, data: null, offset: 0, filter: 'all' };
|
||||
var state = { loaded: false, eps: {}, data: null, offset: 0, filter: 'all', view: 'cards' };
|
||||
|
||||
function $(s) { return document.querySelector(s); }
|
||||
function esc(s) {
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
: '<span class="vcal-time vcal-time--none">Anytime</span>';
|
||||
var flag = ep.has_file ? '<span class="vcal-flag" title="In your library">✓</span>' : '';
|
||||
var meta = '<span class="vcal-se">' + se + '</span>' + (epTitle ? '<span class="vcal-ep">' + esc(epTitle) + '</span>' : '');
|
||||
return '<a class="vcal-cell" style="--vcal-h:' + hue + ';--i:' + (idx % 24) + '" ' +
|
||||
return '<a class="vcal-cell' + (ep.has_file ? ' vcal-cell--owned' : '') + '" style="--vcal-h:' + hue + ';--i:' + (idx % 24) + '" ' +
|
||||
'href="/video-detail/library/show/' + ep.show_id + '" ' +
|
||||
'data-cal-ep="' + ep.id + '" ' +
|
||||
'title="' + esc(ep.show_title) + (epTitle ? ' — ' + esc(epTitle) : '') + (tl ? ' · ' + tl : '') + '">' +
|
||||
|
|
@ -448,6 +448,10 @@
|
|||
for (var i = 0; i < fbs.length; i++) (function (b) {
|
||||
b.addEventListener('click', function () { state.filter = b.getAttribute('data-video-cal-filter'); render(); });
|
||||
})(fbs[i]);
|
||||
var vbs = document.querySelectorAll('[data-video-cal-view]');
|
||||
for (var k = 0; k < vbs.length; k++) (function (b) {
|
||||
b.addEventListener('click', function () { setView(b.getAttribute('data-video-cal-view')); });
|
||||
})(vbs[k]);
|
||||
var addBtn = $('[data-video-cal-addmissing]');
|
||||
if (addBtn) addBtn.addEventListener('click', addMissing);
|
||||
|
||||
|
|
@ -587,6 +591,21 @@
|
|||
.catch(function () { /* modal already shows payload data */ });
|
||||
}
|
||||
|
||||
// View switcher (cards ↔ compact). Just toggles a class on the stable grid
|
||||
// wrapper — no refetch/re-render needed — and remembers the choice.
|
||||
function setView(v) {
|
||||
state.view = v;
|
||||
try { localStorage.setItem('vcalView', v); } catch (e) { /* private mode */ }
|
||||
applyView();
|
||||
}
|
||||
function applyView() {
|
||||
var grid = $('[data-video-cal-grid]');
|
||||
if (grid) grid.classList.toggle('vcal-view--compact', state.view === 'compact');
|
||||
var vbs = document.querySelectorAll('[data-video-cal-view]');
|
||||
for (var i = 0; i < vbs.length; i++)
|
||||
vbs[i].classList.toggle('vcal-view-btn--on', vbs[i].getAttribute('data-video-cal-view') === state.view);
|
||||
}
|
||||
|
||||
function onPageShown(e) {
|
||||
if (!e || e.detail !== PAGE_ID) return;
|
||||
if (!state.loaded) { state.scrollToNow = true; load(); }
|
||||
|
|
@ -595,6 +614,8 @@
|
|||
|
||||
function init() {
|
||||
wire();
|
||||
try { var sv = localStorage.getItem('vcalView'); if (sv) state.view = sv; } catch (e) { /* private mode */ }
|
||||
applyView();
|
||||
document.addEventListener('soulsync:video-page-shown', onPageShown);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1809,6 +1809,25 @@ body[data-side="video"] #soulsync-toggle { display: none; }
|
|||
padding: 7px 14px; border-radius: 8px; cursor: pointer; transition: all 0.15s ease; }
|
||||
.vcal-filter-btn:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
|
||||
.vcal-filter-btn--on { color: #fff; background: rgba(var(--vcal-accent), 0.9); box-shadow: 0 4px 14px rgba(var(--vcal-accent), 0.32); }
|
||||
/* view switcher (cards ↔ compact) — mirrors the filter pill group, with icons */
|
||||
.vcal-views { display: inline-flex; gap: 3px; padding: 4px; border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.08); }
|
||||
.vcal-view-btn { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent;
|
||||
color: rgba(255, 255, 255, 0.7); font-size: 12.5px; font-weight: 700; padding: 7px 13px; border-radius: 8px;
|
||||
cursor: pointer; transition: all 0.15s ease; }
|
||||
.vcal-view-btn svg { opacity: 0.85; }
|
||||
.vcal-view-btn:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
|
||||
.vcal-view-btn--on { color: #fff; background: rgba(var(--vcal-accent), 0.9); box-shadow: 0 4px 14px rgba(var(--vcal-accent), 0.32); }
|
||||
|
||||
/* Compact view — drop the episode art to fit a lot more on screen */
|
||||
.vcal-grid.vcal-view--compact .vcal-art { display: none; }
|
||||
.vcal-grid.vcal-view--compact .vcal-slot { gap: 8px; padding: 13px 10px; }
|
||||
.vcal-grid.vcal-view--compact .vcal-card { border-radius: 10px; }
|
||||
.vcal-grid.vcal-view--compact .vcal-info { padding: 10px 12px; }
|
||||
.vcal-grid.vcal-view--compact .vcal-show { margin-top: 4px; }
|
||||
/* the art carried the library ✓ — surface ownership as a left accent stripe instead */
|
||||
.vcal-grid.vcal-view--compact .vcal-cell--owned .vcal-card { box-shadow: inset 3px 0 0 #6cd391; }
|
||||
.vcal-grid.vcal-view--compact .vcal-cell--owned .vcal-info { padding-left: 15px; }
|
||||
/* catch-up button: queue already-aired missing episodes to the wishlist */
|
||||
.vcal-addmissing { display: inline-flex; align-items: center; gap: 7px; padding: 9px 16px; border-radius: 11px;
|
||||
border: 1px solid rgba(var(--accent-rgb, 88 101 242), 0.4); cursor: pointer; font-size: 12.5px; font-weight: 800;
|
||||
|
|
|
|||
Loading…
Reference in a new issue