Tint release cards by origin app (Sonarr/Radarr/Plex)
This commit is contained in:
1 parent
102683363f
commit
4737891997
4 files changed
+57
-5
No files matched your search
@@ -269,9 +269,13 @@ in three kinds:
|
||||
date) and one group per `recent` widget (newest first) - each group is a header
|
||||
(title, refresh stamp, per-widget errors) followed by one card per release,
|
||||
laid out as a wrapping grid - then notices, urgent first, then heads-up then
|
||||
info, each group in creation order. The next upcoming release that carries
|
||||
artwork also gets a full-width hero tile above the groups (its relayed thumb
|
||||
plus title and date). Each widget gets its own sidebar button for a
|
||||
info, each group in creation order. Cards are tinted by the app that produced
|
||||
them (Sonarr teal, Radarr violet, Plex orange - separate light/dark shades of
|
||||
each), on the card edge, the source chip, and a legend chip per origin in the
|
||||
group header, so a merged timeline says which app each card came from. The
|
||||
next upcoming release that carries artwork also gets a full-width hero tile
|
||||
above the groups (its relayed thumb plus title and date), ringed in the same
|
||||
origin hue. Each widget gets its own sidebar button for a
|
||||
single-widget view.
|
||||
- Writes are admin-only when OIDC is on, reads any session - same gate as
|
||||
services.
|
||||
|
||||
@@ -233,12 +233,20 @@ function noticeCard(widget) {
|
||||
);
|
||||
}
|
||||
|
||||
// Cards are tinted by the app that produced them, so a merged timeline reads by
|
||||
// source at a glance; an unknown origin stays neutral.
|
||||
const ORIGIN_LABEL = { sonarr: "Sonarr", radarr: "Radarr", plex: "Plex" };
|
||||
|
||||
function originClass(item) {
|
||||
return ORIGIN_LABEL[item ? item.origin : null] ? ` origin-${item.origin}` : "";
|
||||
}
|
||||
|
||||
function releaseCard(item) {
|
||||
const thumb = item.thumb
|
||||
? `<img class="widget-thumb" src="${esc(item.thumb)}" alt="${esc(item.label)}" loading="lazy" />`
|
||||
: "";
|
||||
return (
|
||||
`<div class="release-card">` +
|
||||
`<div class="release-card${originClass(item)}">` +
|
||||
thumb +
|
||||
`<span class="widget-label">${esc(item.label)}</span>` +
|
||||
(item.sub ? `<span class="widget-sub">${esc(item.sub)}</span>` : "") +
|
||||
@@ -286,12 +294,17 @@ function liveCard(widgets, title, ascending) {
|
||||
const refreshed = widgets.map((widget) => (widget.data || {}).fetched_at || "").filter(Boolean);
|
||||
const stamp = refreshed.length ? `refreshed ${clockOf(refreshed.sort()[0])}` : "";
|
||||
const meta = [...notes, stamp].filter(Boolean).join(" · ");
|
||||
const legend = Object.keys(ORIGIN_LABEL)
|
||||
.filter((key) => rows.some((row) => row.origin === key))
|
||||
.map((key) => `<span class="origin-key origin-${key}">${ORIGIN_LABEL[key]}</span>`)
|
||||
.join("");
|
||||
return (
|
||||
`<div class="live-group">` +
|
||||
`<div class="live-head">` +
|
||||
`<span class="icon">${widgetIcon(widgets[0])}</span>` +
|
||||
`<div class="widget-title">${esc(title)}</div>` +
|
||||
`<div class="widget-meta">${esc(meta)}</div>` +
|
||||
(legend ? `<div class="widget-keys">${legend}</div>` : "") +
|
||||
`</div>` +
|
||||
(rows.length ? `<div class="release-cards">${rows.map(releaseCard).join("")}</div>` : "") +
|
||||
(rows.length ? "" : `<div class="widget-empty">${esc(meta || "nothing in the window")}</div>`) +
|
||||
@@ -324,7 +337,7 @@ function heroTile(widgets) {
|
||||
.sort((a, b) => (a.date < b.date ? -1 : 1));
|
||||
const next = upcoming.length ? upcoming[0] : thumbnailed[0];
|
||||
return (
|
||||
`<div class="home-hero">` +
|
||||
`<div class="home-hero${originClass(next)}">` +
|
||||
`<img class="home-hero-img" src="${esc(next.thumb)}" alt="${esc(next.label)}" loading="lazy" />` +
|
||||
`<div class="home-hero-cap">` +
|
||||
`<span class="home-hero-title">${esc(next.label)}</span>` +
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
--success: #3fbf7f;
|
||||
--error: #e0556b;
|
||||
--warning: #d9a441;
|
||||
/* release cards are tinted by the app that produced them */
|
||||
--origin-sonarr: #45c8c2;
|
||||
--origin-radarr: #a97ce8;
|
||||
--origin-plex: #f2813f;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
@@ -20,6 +24,9 @@
|
||||
--fg: #16202e;
|
||||
--muted: #61708a;
|
||||
--accent: #2f6fd0;
|
||||
--origin-sonarr: #127c78;
|
||||
--origin-radarr: #6b3fa8;
|
||||
--origin-plex: #b3541f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +370,31 @@ body {
|
||||
.release-card .widget-sub { color: var(--muted); font-size: 12px; }
|
||||
.release-card .widget-when { font-size: 12px; font-weight: 700; color: var(--muted); }
|
||||
.release-card .widget-src { font-size: 11px; color: var(--accent); }
|
||||
|
||||
/* origin tints: Sonarr teal, Radarr violet, Plex orange. The merged timeline
|
||||
mixes apps, so the card edge, the source chip and a legend chip in the group
|
||||
header all carry the same hue. */
|
||||
.release-card.origin-sonarr { border-left: 3px solid var(--origin-sonarr); }
|
||||
.release-card.origin-radarr { border-left: 3px solid var(--origin-radarr); }
|
||||
.release-card.origin-plex { border-left: 3px solid var(--origin-plex); }
|
||||
.release-card.origin-sonarr .widget-src { color: var(--origin-sonarr); }
|
||||
.release-card.origin-radarr .widget-src { color: var(--origin-radarr); }
|
||||
.release-card.origin-plex .widget-src { color: var(--origin-plex); }
|
||||
.live-head .widget-keys { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
.origin-key {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 1px 7px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid currentColor;
|
||||
color: var(--muted);
|
||||
}
|
||||
.origin-key.origin-sonarr { color: var(--origin-sonarr); }
|
||||
.origin-key.origin-radarr { color: var(--origin-radarr); }
|
||||
.origin-key.origin-plex { color: var(--origin-plex); }
|
||||
.home-hero.origin-sonarr { border: 2px solid var(--origin-sonarr); }
|
||||
.home-hero.origin-radarr { border: 2px solid var(--origin-radarr); }
|
||||
.home-hero.origin-plex { border: 2px solid var(--origin-plex); }
|
||||
.widget-empty { color: var(--muted); font-size: 13px; }
|
||||
|
||||
.home-empty { color: var(--muted); font-size: 14px; }
|
||||
|
||||
@@ -275,6 +275,7 @@ class WidgetData:
|
||||
"label": show or episode_title or "?",
|
||||
"sub": " · ".join(bits),
|
||||
"type": "episode",
|
||||
"origin": "sonarr",
|
||||
"source": widget.name,
|
||||
"thumb": None,
|
||||
}
|
||||
@@ -299,6 +300,7 @@ class WidgetData:
|
||||
"label": label,
|
||||
"sub": RADARR_DATE_LABELS.get(field, ""),
|
||||
"type": "movie",
|
||||
"origin": "radarr",
|
||||
"source": widget.name,
|
||||
"thumb": self._thumb(widget, self._radarr_image(item)),
|
||||
}
|
||||
@@ -333,6 +335,7 @@ class WidgetData:
|
||||
"label": str(item.get("title") or "?"),
|
||||
"sub": " · ".join(bits),
|
||||
"type": str(item.get("type") or "added"),
|
||||
"origin": "plex",
|
||||
"source": widget.name,
|
||||
"thumb": self._thumb(widget, item.get("thumb")),
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user