Wishlist TV: flank the poster (synopsis | poster | cast) + graceful empty states
Fixes the expanded-show design from the screenshot: - The header is now a 3-column row that flanks the poster: synopsis left, poster middle, cast right — using the wasted horizontal space instead of stacking everything vertically and pushing episodes down. Each side column hides (:empty) when there's nothing, so a collapsed bubble or a cast-less reality show just shows the centered poster (nebula grid unchanged). Stacks on mobile. - Quiet episode-still placeholder (faint icon) instead of loud diagonal stripes for episodes TMDB has no still for. All scoped under .vwsh-nebula; music wishlist untouched.
This commit is contained in:
parent
817de567ed
commit
ce84e715c3
2 changed files with 42 additions and 25 deletions
|
|
@ -2539,12 +2539,17 @@ body[data-side="video"] #soulsync-toggle { display: none; }
|
|||
.vwsh-nebula .wl-orb.orb-md { width: 104px; height: 104px; }
|
||||
.vwsh-nebula .wl-orb.orb-lg { width: 124px; height: 124px; }
|
||||
|
||||
/* show info bar — synopsis (left) + clickable cast bubbles (right), lazy-loaded */
|
||||
.vwsh-nebula .vwsh-info:empty { display: none; }
|
||||
.vwsh-nebula .vwsh-info { display: flex; gap: 20px; align-items: flex-start; text-align: left; margin: 4px 0 18px; }
|
||||
.vwsh-nebula .vwsh-info-syn { flex: 1 1 0; min-width: 0; font-size: 12.5px; line-height: 1.55; color: rgba(255, 255, 255, 0.6);
|
||||
display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.vwsh-nebula .vwsh-info-cast { flex: 0 0 auto; max-width: 48%; display: flex; flex-wrap: wrap; gap: 12px 10px; justify-content: flex-end; }
|
||||
/* expanded header — synopsis (left) · poster (middle) · cast (right). The side
|
||||
columns hide (:empty) when there's nothing, so a collapsed/cast-less show just
|
||||
shows the centered bubble (nebula grid unchanged). */
|
||||
.vwsh-nebula .vwsh-xhead { display: flex; align-items: center; justify-content: center; gap: 24px; width: 100%; }
|
||||
.vwsh-nebula .vwsh-xhead-mid { flex-shrink: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; }
|
||||
.vwsh-nebula .vwsh-info-syn { flex: 0 1 340px; min-width: 0; align-self: center; text-align: left;
|
||||
font-size: 12.5px; line-height: 1.55; color: rgba(255, 255, 255, 0.62);
|
||||
display: -webkit-box; -webkit-line-clamp: 8; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
.vwsh-nebula .vwsh-info-cast { flex: 0 1 340px; min-width: 0; align-self: center; display: flex; flex-wrap: wrap;
|
||||
gap: 12px 10px; align-content: center; justify-content: flex-start; }
|
||||
.vwsh-nebula .vwsh-info-syn:empty, .vwsh-nebula .vwsh-info-cast:empty { display: none; }
|
||||
.vwsh-nebula .vwsh-cast { width: 56px; padding: 0; border: none; background: none; cursor: pointer;
|
||||
display: flex; flex-direction: column; align-items: center; gap: 5px; }
|
||||
.vwsh-nebula .vwsh-cast-img { position: relative; width: 46px; height: 46px; border-radius: 50%; overflow: hidden;
|
||||
|
|
@ -2560,8 +2565,9 @@ body[data-side="video"] #soulsync-toggle { display: none; }
|
|||
text-align: center; line-height: 1.2; max-width: 56px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.vwsh-nebula .vwsh-cast:hover .vwsh-cast-name { color: rgba(255, 255, 255, 0.85); }
|
||||
@media (max-width: 640px) {
|
||||
.vwsh-nebula .vwsh-info { flex-direction: column; }
|
||||
.vwsh-nebula .vwsh-info-cast { max-width: 100%; justify-content: flex-start; }
|
||||
.vwsh-nebula .vwsh-xhead { flex-direction: column; gap: 14px; }
|
||||
.vwsh-nebula .vwsh-info-syn { flex-basis: auto; text-align: center; }
|
||||
.vwsh-nebula .vwsh-info-cast { flex-basis: auto; justify-content: center; }
|
||||
}
|
||||
.vwsh-nebula .vwsh-info-eyebrow { display: block; font-size: 10px; font-weight: 800; text-transform: uppercase;
|
||||
letter-spacing: 0.05em; color: hsl(var(--orb-hue, 230) 80% 76%); margin-bottom: 6px; }
|
||||
|
|
@ -2595,12 +2601,14 @@ body[data-side="video"] #soulsync-toggle { display: none; }
|
|||
border-radius: 10px; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
transition: background 0.15s ease, border-color 0.15s ease; }
|
||||
.vwsh-nebula .vwsh-epc:hover { background: rgba(255, 255, 255, 0.07); border-color: hsla(var(--orb-hue, 230), 60%, 55%, 0.35); }
|
||||
.vwsh-nebula .vwsh-epc-thumb { flex-shrink: 0; width: 92px; height: 52px; border-radius: 6px; overflow: hidden;
|
||||
.vwsh-nebula .vwsh-epc-thumb { position: relative; flex-shrink: 0; width: 92px; height: 52px; border-radius: 6px; overflow: hidden;
|
||||
background: #16161d; border: 1px solid rgba(255, 255, 255, 0.08); }
|
||||
.vwsh-nebula .vwsh-epc-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.vwsh-nebula .vwsh-epc-thumb--none { background: repeating-linear-gradient(135deg,
|
||||
rgba(255, 255, 255, 0.04) 0 6px, rgba(255, 255, 255, 0.07) 6px 12px); }
|
||||
/* no still → a quiet placeholder (faint icon) instead of loud diagonal stripes */
|
||||
.vwsh-nebula .vwsh-epc-thumb--none { background: rgba(255, 255, 255, 0.03); }
|
||||
.vwsh-nebula .vwsh-epc-thumb--none img { display: none; }
|
||||
.vwsh-nebula .vwsh-epc-thumb--none::after { content: '📺'; position: absolute; inset: 0; display: flex;
|
||||
align-items: center; justify-content: center; font-size: 17px; opacity: 0.22; }
|
||||
.vwsh-nebula .vwsh-epc-body { flex: 1; min-width: 0; }
|
||||
.vwsh-nebula .vwsh-epc-title { font-size: 12.5px; font-weight: 700; color: #fff; line-height: 1.3;
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
||||
|
|
|
|||
|
|
@ -102,18 +102,25 @@
|
|||
var gstyle = 'animation-delay:' + Math.min(idx * 45, 700) + 'ms;--orb-hue:' + hue +
|
||||
(sh.poster_url ? ";--vwsh-poster:url('" + esc(sh.poster_url) + "')" : '');
|
||||
var prog = total ? Math.max(0, Math.min(1, (sh.done || 0) / total)) : 0; // #4 acquisition progress
|
||||
// Header is a 3-column row that FLANKS the poster: synopsis (left) · poster
|
||||
// (middle) · cast (right). When collapsed (or no data) the side columns are
|
||||
// empty → hidden → just the centered bubble, so the nebula grid is unchanged.
|
||||
return '<div class="wl-orb-group" data-vwsh-group data-vwsh-tmdb="' + esc(sh.tmdb_id) + '" style="' + gstyle + '">' +
|
||||
'<button class="wl-orb-remove" type="button" data-vwsh-rm="show" data-tmdb="' + esc(sh.tmdb_id) + '" title="Remove show">✕</button>' +
|
||||
'<div class="wl-orb-tooltip">' + esc(sh.title) + '<br><span>' + eps + '</span></div>' +
|
||||
'<div class="wl-orb ' + orbSize(total) + '" data-vwsh-orb style="--vwsh-prog:' + prog + '">' +
|
||||
'<div class="wl-orb-glow"></div>' + img + '<div class="wl-orb-ring"></div>' +
|
||||
'<div class="vwsh-prog"></div>' +
|
||||
'<div class="vwsh-xhead">' +
|
||||
'<div class="vwsh-info-syn" data-vwsh-syn></div>' +
|
||||
'<div class="vwsh-xhead-mid">' +
|
||||
'<div class="wl-orb-tooltip">' + esc(sh.title) + '<br><span>' + eps + '</span></div>' +
|
||||
'<div class="wl-orb ' + orbSize(total) + '" data-vwsh-orb style="--vwsh-prog:' + prog + '">' +
|
||||
'<div class="wl-orb-glow"></div>' + img + '<div class="wl-orb-ring"></div>' +
|
||||
'<div class="vwsh-prog"></div>' +
|
||||
'</div>' +
|
||||
'<div class="wl-orb-label" data-vwsh-open-show data-vwsh-src="' + src + '" data-vwsh-id="' + esc(openId) + '" title="' + esc(sh.title) + '">' + esc(sh.title) + '</div>' +
|
||||
'<div class="wl-orb-meta">' + eps + (sh.done ? ' · ' + sh.done + ' done' : '') + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="vwsh-info-cast" data-vwsh-cast></div>' +
|
||||
'</div>' +
|
||||
'<div class="wl-orb-label" data-vwsh-open-show data-vwsh-src="' + src + '" data-vwsh-id="' + esc(openId) + '" title="' + esc(sh.title) + '">' + esc(sh.title) + '</div>' +
|
||||
'<div class="wl-orb-meta">' + eps + (sh.done ? ' · ' + sh.done + ' done' : '') + '</div>' +
|
||||
'<div class="wl-orb-expanded">' +
|
||||
'<div class="vwsh-info" data-vwsh-info></div>' +
|
||||
'<div class="vwsh-seasons">' + seasons + '</div></div>' +
|
||||
'<div class="wl-orb-expanded"><div class="vwsh-seasons">' + seasons + '</div></div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +148,9 @@
|
|||
}
|
||||
// sel = a selected episode object (episode synopsis + guest cast), or null (show synopsis + show cast).
|
||||
function renderInfoBar(group, tmdb, sel) {
|
||||
var info = group && group.querySelector('[data-vwsh-info]'); if (!info) return;
|
||||
var synEl = group && group.querySelector('[data-vwsh-syn]');
|
||||
var castEl = group && group.querySelector('[data-vwsh-cast]');
|
||||
if (!synEl || !castEl) return;
|
||||
var si = state.showInfo[tmdb] || {};
|
||||
var eyebrow, overview, castArr;
|
||||
if (sel) {
|
||||
|
|
@ -156,10 +165,10 @@
|
|||
} else {
|
||||
eyebrow = ''; overview = si.overview || ''; castArr = si.cast || [];
|
||||
}
|
||||
var left = '<div class="vwsh-info-syn">' +
|
||||
(eyebrow ? '<span class="vwsh-info-eyebrow">' + esc(eyebrow) + '</span>' : '') +
|
||||
esc(overview) + '</div>';
|
||||
info.innerHTML = left + (castArr.length ? '<div class="vwsh-info-cast">' + castBubbles(castArr) + '</div>' : '');
|
||||
// Side columns are independent so each hides (:empty) when it has nothing.
|
||||
synEl.innerHTML = (eyebrow || overview)
|
||||
? ((eyebrow ? '<span class="vwsh-info-eyebrow">' + esc(eyebrow) + '</span>' : '') + esc(overview)) : '';
|
||||
castEl.innerHTML = castArr.length ? castBubbles(castArr) : '';
|
||||
// lazily fetch the episode's guest stars, then re-render if still selected
|
||||
if (sel && sel._guests === undefined) {
|
||||
sel._guests = null;
|
||||
|
|
|
|||
Loading…
Reference in a new issue