diff --git a/app/static/app.js b/app/static/app.js index 9fa0adf..0523bd1 100644 --- a/app/static/app.js +++ b/app/static/app.js @@ -222,7 +222,24 @@ const data = await api(`/api/tvdb/series/${encodeURIComponent(state.selectedSeries.id)}/episodes?order_type=aired`); state.episodes = data.items || []; el.episodesList.innerHTML = ""; + let previousSeasonKey = null; state.episodes.forEach((episode) => { + const seasonNum = Number(episode.season_number); + const seasonKey = Number.isFinite(seasonNum) ? String(seasonNum) : "unknown"; + if (previousSeasonKey === null || seasonKey !== previousSeasonKey) { + const seasonHeader = document.createElement("li"); + seasonHeader.className = "season-header"; + if (seasonNum === 0) { + seasonHeader.textContent = "Specials"; + } else if (Number.isFinite(seasonNum)) { + seasonHeader.textContent = `Season ${seasonNum}`; + } else { + seasonHeader.textContent = "Season Unknown"; + } + el.episodesList.appendChild(seasonHeader); + previousSeasonKey = seasonKey; + } + const li = document.createElement("li"); const left = document.createElement("span"); left.textContent = episode.label || `${episode.season_number}x${episode.episode_number} ${episode.title}`; diff --git a/app/static/styles.css b/app/static/styles.css index 7d114e6..94d45f9 100644 --- a/app/static/styles.css +++ b/app/static/styles.css @@ -8,6 +8,10 @@ body { font-family: "Segoe UI", Tahoma, sans-serif; background: #f2f4f8; color: #1a1f2b; + height: 100vh; + overflow: hidden; + display: flex; + flex-direction: column; } .topbar { @@ -34,6 +38,9 @@ body { gap: 12px; padding: 12px; align-items: start; + flex: 1; + min-height: 0; + overflow: hidden; } .panel { @@ -46,6 +53,16 @@ body { flex-direction: column; } +#panelEpisodes, +#panelSelectedEpisodes, +#panelSelectedFiles { + height: 100%; + min-height: 0; + max-height: 100%; + align-self: stretch; + overflow: hidden; +} + .panel h2 { margin: 0 0 10px; font-size: 16px; @@ -133,11 +150,36 @@ button.secondary { .linked-list-wrap { flex: 1; - min-height: 240px; - max-height: 440px; + min-height: 0; + overflow: hidden; } .linked-list { + flex: 1; + height: 100%; + max-height: none; + overflow-y: auto; +} + +#panelEpisodes .panel-body, +#panelSelectedEpisodes .panel-body, +#panelSelectedFiles .panel-body { + flex: 1; + min-height: 0; + overflow: hidden; +} + +#panelEpisodes .linked-list-wrap, +#panelSelectedEpisodes .linked-list-wrap, +#panelSelectedFiles .linked-list-wrap { + flex: 1; + min-height: 0; +} + +#panelEpisodes .linked-list-wrap .list, +#panelSelectedEpisodes .linked-list-wrap .list, +#panelSelectedFiles .linked-list-wrap .list { + max-height: none; height: 100%; } @@ -157,6 +199,15 @@ button.secondary { background: #e0f2fe; } +.list li.season-header { + background: #eef2ff; + border-bottom: 1px solid #dbe4fb; + color: #1e293b; + font-weight: 700; + justify-content: flex-start; + padding: 8px; +} + .panel-footer { position: sticky; bottom: 0; @@ -268,6 +319,12 @@ button.secondary { grid-template-columns: 1fr; } + #panelEpisodes, + #panelSelectedEpisodes, + #panelSelectedFiles { + min-height: 420px; + } + .modal-grid { grid-template-columns: 1fr; } diff --git a/app/templates/index.html b/app/templates/index.html index 641a574..999be2c 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -24,11 +24,18 @@
-

2. Episodes

-
- +
+

2. Episodes

+ +
+
+
+ +
+
+
    +
    -
    diff --git a/data/session_state.sqlite3 b/data/session_state.sqlite3 index f64aa68..3ef3d5b 100644 Binary files a/data/session_state.sqlite3 and b/data/session_state.sqlite3 differ