Display never re-shows a slide's content if its id is unchanged, even when the HTML changed #21

Closed
opened 2026-08-13 20:06:47 +00:00 by paulloth1 · 1 comment
paulloth1 commented 2026-08-13 20:06:47 +00:00 (Migrated from github.com)

Problem

display.html's applySlide() (around line 104-112) dedups purely on slide id:

function applySlide(data) {
  if (data.id === lastId) {
    return; // same slide already showing, don't touch the DOM (avoids img/video reload flicker)
  }
  ...
}

This is correct for avoiding flicker within a single slide's display window (the backend holds the same id + html for the whole rotation_interval_seconds, and the client polls every 5s — re-applying identical HTML every poll would be wasteful/flickery).

But backend/rotation.py's _rotation_step() re-renders every enabled slide from scratch on every lap of the rotation loop (shown_any/set_current around line 139-159) — so a slide with dynamic content (RSS feed, weather widget, departure board, anything server-rendered) gets genuinely new html on its next lap, while keeping the exact same id. The client-side dedup has no way to tell "same id, same content" apart from "same id, refreshed content" — it always takes the fast path and never updates the DOM.

With the site's current 10-slide rotation this is masked, since many different ids cycle through between two occurrences of the same slide, resetting lastId in between. But it's a real bug that will bite:

  • Any deployment with only 1-2 enabled slides (the same id could plausibly be polled twice in a row across a lap boundary).
  • Even in the current 10-slide setup, it's fragile — disabling slides down to just the RSS ones, or any future single-slide "ticker mode" use case, would silently freeze the display on stale content forever (rotation keeps re-rendering server-side, but the client-visible screen never updates).

Suggested fix

Compare data.html (or a cheap hash of it) in addition to data.id — only short-circuit when both are unchanged from last time. Something like:

if (data.id === lastId && data.html === lastHtml) {
  return;
}

(lastHtml is already tracked, just not consulted in this check.)

Where

backend/templates/display.html:104-112

## Problem `display.html`'s `applySlide()` (around line 104-112) dedups purely on slide id: ```js function applySlide(data) { if (data.id === lastId) { return; // same slide already showing, don't touch the DOM (avoids img/video reload flicker) } ... } ``` This is correct for avoiding flicker *within* a single slide's display window (the backend holds the same `id` + `html` for the whole `rotation_interval_seconds`, and the client polls every 5s — re-applying identical HTML every poll would be wasteful/flickery). But `backend/rotation.py`'s `_rotation_step()` re-renders every enabled slide from scratch on every lap of the rotation loop (`shown_any`/`set_current` around line 139-159) — so a slide with dynamic content (RSS feed, weather widget, departure board, anything server-rendered) gets genuinely new `html` on its next lap, while keeping the exact same `id`. The client-side dedup has no way to tell "same id, same content" apart from "same id, refreshed content" — it always takes the fast path and never updates the DOM. With the site's current 10-slide rotation this is masked, since many different ids cycle through between two occurrences of the same slide, resetting `lastId` in between. But it's a real bug that will bite: - Any deployment with only 1-2 enabled slides (the same id could plausibly be polled twice in a row across a lap boundary). - Even in the current 10-slide setup, it's fragile — disabling slides down to just the RSS ones, or any future single-slide "ticker mode" use case, would silently freeze the display on stale content forever (rotation keeps re-rendering server-side, but the client-visible screen never updates). ## Suggested fix Compare `data.html` (or a cheap hash of it) in addition to `data.id` — only short-circuit when *both* are unchanged from last time. Something like: ```js if (data.id === lastId && data.html === lastHtml) { return; } ``` (`lastHtml` is already tracked, just not consulted in this check.) ## Where `backend/templates/display.html:104-112`
paulloth1 commented 2026-08-13 20:13:14 +00:00 (Migrated from github.com)

Fixed and deployed. applySlide() in display.html now short-circuits only when both id AND html are unchanged. Verified the fix doesn't regress first-load (lastId starts undefined) or the iframe-reset path (calls showHtml directly, bypassing applySlide entirely). kiosk.service restarted since this touches the template the kiosk browser loads once at startup.

Fixed and deployed. applySlide() in display.html now short-circuits only when both id AND html are unchanged. Verified the fix doesn't regress first-load (lastId starts undefined) or the iframe-reset path (calls showHtml directly, bypassing applySlide entirely). kiosk.service restarted since this touches the template the kiosk browser loads once at startup.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
paul_loth/krautspaceTV#21
No description provided.