diff --git a/app/static/app.js b/app/static/app.js index 3ccbd3d..270d1ae 100644 --- a/app/static/app.js +++ b/app/static/app.js @@ -180,6 +180,36 @@ return title; } + function parseIsoDateOnly(value) { + const text = (value || "").toString().trim(); + const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text); + if (!m) return null; + const year = Number(m[1]); + const month = Number(m[2]); + const day = Number(m[3]); + if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) return null; + const dt = new Date(year, month - 1, day); + if (Number.isNaN(dt.getTime())) return null; + return dt; + } + + function formatDateDdMmYyyy(value) { + const dt = parseIsoDateOnly(value); + if (!dt) return ""; + const day = String(dt.getDate()).padStart(2, "0"); + const month = String(dt.getMonth() + 1).padStart(2, "0"); + const year = dt.getFullYear(); + return `${day}-${month}-${year}`; + } + + function isFutureAiredDate(value) { + const aired = parseIsoDateOnly(value); + if (!aired) return false; + const today = new Date(); + const todayOnly = new Date(today.getFullYear(), today.getMonth(), today.getDate()); + return aired.getTime() > todayOnly.getTime(); + } + function basename(pathText) { const text = (pathText || "").toString(); const normalized = text.replace(/\\/g, "/"); @@ -649,7 +679,21 @@ const li = document.createElement("li"); const left = document.createElement("span"); - left.textContent = episode.label || `${episode.season_number}x${episode.episode_number} ${episode.title}`; + left.className = "episode-main"; + const title = document.createElement("div"); + title.className = "episode-title"; + title.textContent = compactEpisodeText(episode); + left.appendChild(title); + + const formattedDate = formatDateDdMmYyyy(episode.aired); + if (formattedDate) { + const dateLine = document.createElement("div"); + const future = isFutureAiredDate(episode.aired); + dateLine.className = future ? "episode-date episode-date-future" : "episode-date"; + dateLine.textContent = `${future ? "Airing" : "Aired"} ${formattedDate}`; + left.appendChild(dateLine); + } + const right = document.createElement("div"); right.appendChild(makeBtn("Add", async () => { const payload = { diff --git a/app/static/styles.css b/app/static/styles.css index 9e0b46c..0741c15 100644 --- a/app/static/styles.css +++ b/app/static/styles.css @@ -337,6 +337,28 @@ button.secondary { height: 100%; } +#episodesList .episode-main { + display: flex; + flex-direction: column; + min-width: 0; +} + +#episodesList .episode-title { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#episodesList .episode-date { + margin-top: 2px; + font-size: 12px; + color: var(--text-muted); +} + +#episodesList .episode-date-future { + color: var(--button-primary-bg); +} + .badge { display: inline-block; font-size: 11px; diff --git a/data/session_state.sqlite3 b/data/session_state.sqlite3 index 1a892b9..b869528 100644 Binary files a/data/session_state.sqlite3 and b/data/session_state.sqlite3 differ