Files
pulse-signage/CHANGELOG.md
T
lzstealth c4ae69d25f
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 2m0s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 31s
release: v2.11.2
2026-09-05 18:14:38 +01:00

1259 lines
60 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to this project will be documented in this file.
## 2.11.2 - 2026-09-05
### Changed
- Refreshed the vendored AdminLTE assets to 4.9.1, including the print-layout fixes and extended palette updates.
- Added independently configurable verification, password-reset, and invitation email expiry periods, with an `[[expiry_time]]` template variable.
- Updated default account email templates with inline formatting, action buttons, and links, and improved rendering when both button and URL placeholders are used.
- Shortened user-agent labels across audit logs and account session lists, and removed red/green change highlighting from audit entries.
## 2.11.1 - 2026-09-02
### Added
- Secure administrator invitations that create accounts only after the recipient accepts the invitation.
- Configurable API progress-bar placeholders with AdminLTE and announcement palette colors, custom colors, striped and animated variants, and quoted numeric literals.
- An optional `textless` progress-bar modifier to hide the visible percentage while retaining progress accessibility metadata.
- Configurable progress-bar radius options including `square`, `pill`, `rounded`, and validated `radius(...)` values.
- Arithmetic API placeholder transforms for adding, subtracting, multiplying, and dividing numeric values.
- Time-based progress bars using start and end date/time fields to show elapsed timetable-item progress.
- Audit events for invitation sending and acceptance, email verification, password-reset requests, and account email changes.
- A pending invitations page with invitation-specific Read, Create, Delete, and Allow permissions.
- Invitation deletion and resend actions with confirmation prompts.
- An opt-in Weather audit category for weather-location changes and manually queued refreshes.
- Opt-in per-command Screen Controls auditing, with forward and back navigation grouped together and disabled by default.
- The pending invitations list now supports pagination, search, and sorting, with Users, Roles, and Invitations grouped under expandable User management navigation.
- API progress calculations now support object-wrapped amounts.
### Changed
- Updated the invitation registration page to show fields only for valid tokens, use the themed failure state for invalid links, and pre-fill the invited email and display name.
- Made the invited email visibly disabled, kept the display name editable and required, and aligned invitation actions with the existing user forms.
- Added bold, italic, and underline formatting controls to the user invitation email message template editor.
- Fixed application-settings cleanup SQL so media and icon saves preserve all supported settings and no longer fail with MariaDB placeholder errors.
- Updated API progress bars to inherit the surrounding WYSIWYG text size and text color, preserve rounded corners, and render consistently in the editor preview, player, and thumbnails.
## 2.11.0 - 2026-09-02
### Added
- Optional account emails with administrator verification bypass, email verification, password recovery, and confirmed email changes.
- SMTP configuration and mail delivery for account notifications.
- Autofill restrictions for Bitwarden, LastPass, and 1Password on account profile and new-password fields while preserving current-password autofill.
### Changed
- Updated account email templates and previews to support both line breaks and paragraph spacing.
## 2.10.7 - 2026-09-02
### Added
- API token authentication now reuses access tokens until their expiry and can renew them with a refresh token, including refresh-token rotation.
- API sources can configure a refresh URL, JSON request body, and refresh-token response path.
- Client status badges now show Live, Paused, and Blackout states in the responsive Connected clients view.
### Changed
- Reorganized the API source editor into compact Connection, Authentication, and Latest response cards, with authentication collapsed by default on edit pages.
- Redesigned the Connected clients page for responsive mobile cards with compact controls, expandable search, pairing access, two-line detail clamping, and aligned desktop screen-group controls.
### Fixed
- Fixed client screen moves from mobile cards so the next move disables the clients current screen group rather than its previous one.
- Removed unused Bootstrap Icons font preloads that triggered browser warnings on pages where icons were not rendered.
## 2.10.6 - 2026-08-29
### Added
- Playlist recovery now uses cached browser and server snapshots, reports offline status, and recovers after cached responses.
### Changed
- Refactored the player runtime into focused animation, media, transition, command, playback, and rendering modules.
- Improved player slide transitions and video playback by preloading media, preserving precise durations, pausing outgoing videos during crossfades, and deferring expensive post-render setup.
### Fixed
- Fixed remote player commands and media synchronization so they route through the bridge using the physical player device identity, including announcement and playlist refresh notifications.
- Fixed player media handling for remote bridge uploads and deletes by using the bridge endpoint with explicit player-device authentication.
- Fixed player service-worker caching so ranged media requests bypass stale cached responses and video playback remains reliable.
## 2.10.5 - 2026-08-29
### Fixed
- Fixed intermittent pairing failures while player registration and pairing sessions propagate through the bridge by retrying transient resolution and completion requests.
- Fixed the pairing page so transient submission failures retry automatically and pairing progress uses a single spinner without dimming the form.
- Fixed the player onboarding page so it continues polling until the pairing code and QR code are available.
## 2.10.4 - 2026-08-29
### Fixed
- Fixed remote client move commands so they route through the player bridge to the correct browser tab using the physical player identity and connection ID.
- Removed the obsolete `PLAYER_BASE_URL` configuration fallback; command routing uses `PLAYER_INTERNAL_URL` locally or the player bridge remotely, while `PLAYER_PUBLIC_URL` remains available for kiosk launcher and direct player access.
- Removed the player URL list from screen-group add/edit pages and expanded the remaining form card to full width.
## 2.10.3 - 2026-08-28
### Added
- Remote screens now poll periodically to recover from missed refresh commands after bridge reconnects.
- Screens now use cached playlist snapshots while the bridge or web service is temporarily unavailable.
### Fixed
- Fixed the weather edit preview so the daily forecast is shown initially, the 24-hour forecast is hidden until selected, and the redundant hourly heading is removed.
- Fixed onboarding cleanup so incomplete pairings are retained for the 15-minute pairing-code lifetime while inactive completed bindings are pruned after 24 hours.
- Fixed client-name handling so offline names can be reused, active collisions receive numeric suffixes, and reconnecting players resolve duplicate names consistently.
- Fixed an internal server error when renaming clients by forwarding the available-name resolver to the client command routes.
- Fixed remote client moves to resolve the paired browser client binding before changing its target screen.
- Fixed remote player heartbeats to update the central onboarding bindings for active browser clients without treating the physical player registry ID as a client binding.
- Fixed targeted commands after browser reconnects by falling back to the stable client ID when a transient connection ID is stale.
- Fixed stale browser command connections remaining active indefinitely when the physical player heartbeat was still healthy.
- Fixed media synchronization so generated player caches are excluded while remote image caches remain available to players.
- Fixed weather screen notifications so changes in the fetched data or the current forecast hour trigger a refresh.
- Fixed player runtime script loading and slide rendering so region modules, transitions, and cached playlists initialize consistently.
- Fixed command delivery reporting to require acknowledgement from the receiving browser tab.
- Fixed playlist refresh notifications to target the physical player hosting each screen instead of always targeting the local player.
## 2.10.2 - 2026-08-28
### Added
- Onboarding client heartbeats are now persisted so records inactive for 24 hours can be pruned without relying on player connectivity after the fact.
### Fixed
- Fixed the weather forecast preview to show only its first-fetch message until a successful forecast is available.
## 2.10.1 - 2026-08-28
### Added
- Linear gradient backgrounds to templates, including multiple colours and angle control.
- A visual gradient stop editor with draggable stops, click-to-add support, and stop reordering.
## 2.10.0 - 2026-08-28
### Added
- Secure kiosk onboarding with QR-first and manual pairing flows.
- Browser-specific pairing sessions with expiring pairing codes.
- Circular QR presentation and a compatible QR scanner with decoder fallbacks.
- Responsive player onboarding and a post-pair option to connect another player.
- Stable player identity bindings for paired players and moved-client aliases.
- Per-tab client identities backed by browser session storage for commands, pairing, and screen moves.
- RBAC protection for player pairing through the `pairing.allow` permission.
- A dedicated web onboarding workflow for pairing and managing player setup.
- Pairing entry points now appear in the dashboard and connected clients workflows.
- A mobile-friendly connected clients link is now shown after successful pairing.
- Player keyboard feedback now includes slide navigation, plus `P` pause/unpause and `B` blackout toggles.
### Changed
- Restricted direct screen URLs to the player configured for the requested screen.
- Made pairing QR codes easier to scan by encoding only the short pairing code.
- Made connected-client controls and player pairing UI render independently according to their permissions.
- Removed client identities from onboarding and screen-move URLs; authorized player data now loads after the tab identity handshake.
- Updated connected-client commands and screen moves to resolve tab and registered-player identities reliably.
## 2.9.0 - 2026-08-28
### Added
- API sources, RSS feeds, and weather locations can be enabled or disabled without deleting their cached data.
- Weather slide regions with current, daily, and hourly placeholders, date/time transforms, and Bootstrap weather icon transforms.
- Multiple saved weather locations with provider, coordinate, unit, and refresh settings.
- Separate Allow permissions for manually refreshing API sources, RSS feeds, and weather locations.
- Announcement colour choices and player rendering now include the AdminLTE extended palette colours.
### Changed
- API, RSS, and Weather refresh jobs now skip disabled sources across scheduled, startup, queued, and manual refresh paths, while re-enabling a source resumes refresh scheduling.
- Weather placeholders now show all current fields, or all fields for the first daily/hourly entry before the remaining entries in a Show more section.
- Weather previews, player playback, and slide thumbnails now use cached Weather data and consistent text/icon sizing.
- API, RSS, and Weather lists now show enabled status and their forms provide action-oriented Enable/Disable controls.
- Enable/Disable actions on API, RSS, and Weather forms now run asynchronously without reloading unsaved form changes.
- Weather locations can now be duplicated from the weather list.
- Startup data-source refreshes now respect each API, RSS, and weather source's configured repull interval.
- RSS feeds now persist their last collection timestamp.
- Refreshed the vendored AdminLTE assets to 4.8.5.
- Removed Digital Signage Subheading and top padding.
- API and RSS source saves now preserve cached data without pulling; added explicit manual refresh actions.
## 2.8.7 - 2026-08-22
### Added
- Configurable JSON POST requests and two-step login-then-token authentication for API sources.
## 2.8.6 - 2026-08-18
### Added
- URL fields now provide live validation with inline feedback and explicit HTTP or HTTPS scheme enforcement.
### Fixed
- Prevented Enter in slide editor inputs from implicitly saving the slide.
- Collapsed nested API response JSON sections by default while keeping the root response visible.
## 2.8.5 - 2026-08-17
### Fixed
- Fixed thumbnail capture timing so video assets are ready before the preview canvas is captured.
- Replaced unavailable webpage thumbnails with a subdued placeholder while keeping live webpage previews intact.
## 2.8.4 - 2026-08-17
### Added
- Local caching for API and RSS image placeholders under `player-cache/remote-images` for offline player playback.
- Reconciliation of cached remote images so files no longer referenced by slides are removed.
### Fixed
- Fixed popup preview authentication for background thumbnail capture.
- Fixed thumbnails so they use the same popup-preview canvas and resolve API/RSS placeholders, fonts, styles, and cached images correctly.
- Fixed manual scheduled-task run notifications so they use task-neutral wording.
## 2.8.3 - 2026-08-17
### Added
- API, RSS, Timetable, and Time / Date placeholder help panels with shared transform and date-token documentation.
- Render-time API and RSS image placeholders with proportional sizing and preview-only bounding boxes.
### Changed
- API and RSS regions now preserve authored content when no data source is selected and remain blank when a selected source has no authored content.
- Normal WYSIWYG image insertion remains upload-backed and separate from image placeholder transforms.
## 2.8.2 - 2026-08-16
### Changed
- Standardized update audit events on from/to changes and added readable table diffs for nested JSON, arrays, null values, and empty strings.
- Standardized internal `src/data` imports on the `#src` alias.
## 2.8.1 - 2026-08-16
### Fixed
- Prevented startup and runtime duplicate-key writes from consuming auto-increment values in permission, player, onboarding, settings, and relationship tables.
- Prevented partial timetable schemas from being incorrectly treated as fully migrated during schema version detection.
### Changed
- Renamed the built-in administrator role key to `super-admin`, while allowing its display name and description to be edited without being overwritten on restart.
## 2.8.0 - 2026-08-16
### Added
- Filtered audit-log CSV export with a dedicated `audit-log.export` permission.
- Canvas Sizes as an individual Content audit category.
- Audit events for slide, template, playlist, and screen changes.
- Audit events for System Settings changes.
- Administration audit events for user and role management.
- Audit logging enablement, category selection, and request metadata controls.
- The extensible audit event storage, retention setting, dedicated audit-log permission, and paginated viewer foundation.
- A Defaults settings section for player and announcement defaults.
- A configurable maximum active session limit that removes the oldest sessions first.
- IP address and user-agent metadata to active sessions.
- The option for users to sign out their other active sessions from My Account.
- Persistent administrator-controlled account locking and unlocking.
- Database-backed login rate limiting with configurable attempts, lockout duration, and tracking scope.
- A permissions-gated System Settings page for announcement icon suggestions, media upload limits and MIME types, session lifetime, and password-change policies.
- Configurable forced password changes for newly created users and administrator password resets.
- The database foundation for key-based application settings, including typed defaults and validation.
- All tables now use numeric auto-increment identifiers while retaining natural or relationship keys as unique constraints.
### Changed
- Updated the API and database documentation and added the Docker publish status badge to the project README.
- Renamed the audit export permission to `audit-log.allow`.
- Made Content and Data Sources audit categories opt-in and excluded automatic data-source refreshes from audit logging.
- Split Content audit logging into individual Slides, Templates, Playlists, Screens, and Announcements categories.
- Renamed the System Settings audit category key from `settings` to `system-settings`.
- Split audit administration events into separate Users and Roles categories.
- Split RSS and API data-source refresh defaults.
- Made the default announcement duration use a value and unit selector, matching announcement forms.
- Replaced password strength presets with customizable length, category, and character requirements.
- Session expiration now uses the configured system setting, and user and role administration is grouped under the Settings area.
- Renamed the system settings permissions to the `system-settings.*` namespace and migrated existing role assignments.
## 2.7.6 - 2026-08-15
### Changed
- The announcement icon picker now supports searching the full Bootstrap Icons catalog while still showing the curated suggestion set by default.
### Fixed
- The announcement Play/Stop button now refreshes after saving screen-group changes, so Play stays disabled until the announcement actually has targets again.
## 2.7.5 - 2026-08-15
### Changed
- The About page now reads bundled library versions from package metadata and the vendored AdminLTE stylesheet.
- AdminLTE is now reported as 4.3.1.
- Animate.css is now reported as 4.1.1.
- Bootstrap Icons is now reported as 1.13.1.
- Cropper.js is now reported as 1.6.2.
- Express is now reported as 5.2.1.
- Handlebars is now reported as 4.7.8.
- hls.js is now reported as 1.7.0.
- Multer is now reported as 2.2.0.
- MySQL2 is now reported as 3.23.3.
- Sharp is now reported as 0.35.3.
- TinyMCE is now reported from the vendored package metadata.
- ws is now reported as 8.21.3.
- The runtime and container images now target Node.js 26.
## 2.7.4 - 2026-08-15
### Added
- A new About page.
### Changed
- Refreshed the vendored AdminLTE assets to 4.3.1.
## 2.7.3 - 2026-08-15
### Changed
- The slide image cropper now warns that SVG and GIF files will be rasterized if they are edited, and it keeps the original file only when the full image remains selected.
- The slide image upload flow now accepts PNG, JPG, GIF, WebP, and SVG images, while the WYSIWYG image uploader now matches that same allowlist.
- TIFF is no longer accepted by the WYSIWYG image uploader.
### Fixed
- The player now preserves quoted custom font-family values from rich text content, so fonts with spaces such as Old London render correctly on screens.
## 2.7.2 - 2026-08-14
### Fixed
- HTML and webpage region previews now normalize object-shaped content before rendering, so the player, thumbnails, and popup preview show the intended iframe content instead of leaking raw objects.
- HTML and webpage preview iframes now size explicitly to the full region bounds in the player, thumbnails, and popup preview.
## 2.7.1 - 2026-08-14
### Changed
- The player page now supports keyboard navigation with arrow keys to move between slides.
## 2.7.0 - 2026-08-14
### Added
- The WYSIWYG editor now supports adding small images.
### Changed
- The WYSIWYG image insertion flow also received a small code cleanup to simplify the related helper logic.
- The default table formatting has been applied.
- Timetable regions now use the renamed helpers end to end in the editor and player, including timezone-aware rendering for timetable entry placeholders.
## 2.6.27 - 2026-08-14
### Fixed
- Scheduled task intervals now display the most appropriate exact unit, such as seconds, minutes, hours, or days, while keeping the sort order numeric.
## 2.6.26 - 2026-08-10
### Changed
- API sources and RSS feeds now accept hours as an update interval unit, and the list and background task scheduling paths now format and convert that unit correctly.
## 2.6.25 - 2026-08-10
### Fixed
- Screen group edit now keeps the slug locked after creation, so existing screen group URLs remain stable.
## 2.6.24 - 2026-08-10
### Fixed
- Deferred playlist updates now keep the current slide index when the next playlist snapshot is applied, so playback no longer jumps back to the first slide mid-cycle.
## 2.6.23 - 2026-08-09
### Fixed
- Dashboard quick-action and kiosk-launcher cards now use row spacing instead of extra card padding, so the layout stays consistent at large widths.
- API and RSS refresh jobs now notify affected player screens only when the refreshed data actually changes, so unchanged polls no longer trigger redundant player refreshes.
## 2.6.22 - 2026-08-09
### Changed
- Startup now logs the previously detected schema version, the current app version, and whether pending migrations exist.
### Fixed
- Direct-to-URL player sessions now generate and persist a stable onboarding device id in session storage, so connected screens can still be moved and renamed independently without going through the onboarding flow first.
- The connected-clients move action now tolerates rows that only have a live connection id, which keeps move operations working for screens that skipped onboarding.
## 2.6.21 - 2026-08-09
### Changed
- Startup now logs the previously detected schema version, the current app version, and whether migrations are required.
- The schema documentation now reflects the timetable table rename, the new `o_app_state` table, and startup version tracking.
- Timetable timezone placeholders now use `tz` for the short zone name and `tz_long` for the full IANA zone.
## 2.6.20 - 2026-08-09
### Changed
- Startup now logs the previously detected schema version, the current app version, and whether migrations are required.
## 2.6.19 - 2026-08-09
### Changed
- Timetable editor helpers, routes, and table layout now use timetable-specific naming and tighter card/table styling.
- Connected clients now sort by client identity fields instead of the old IP-based ordering assumption.
## 2.6.18 - 2026-08-09
### Changed
- Timetable tables were renamed from the old `schedule` names to `timetable` names, and existing databases now rename those tables during migration.
- The timetable group editor now uses timetable-specific naming in its shared helpers and keeps the entries table aligned with the standard admin card/table layout.
## 2.6.17 - 2026-08-09
### Changed
- Existing timetable groups and entries are now migrated to Europe/London, and timetable dates are rewritten to UTC using that source timezone so the wall-clock meaning stays intact.
### Fixed
- New timetable groups now default to Europe/London so the timetable editor and saved data start from the same timezone assumption as the migrated rows.
## 2.6.16 - 2026-08-09
### Changed
- Timetable groups now store an IANA time zone and render their entry datetimes in that timetable time zone, so schedules keep the same wall-clock meaning when they are edited from another country.
### Fixed
- Timetable entry date inputs now round-trip through the timetable time zone instead of the browser locale, so saving from Florida while targeting Germany keeps the intended local times.
## 2.6.15 - 2026-08-08
### Fixed
- Slide update media sync on the player now removes uploads that were removed from the slide, so player storage stays aligned with the current slide content.
- Routine player and player-bridge media upload/delete logs were removed to keep remote player and bridge operation quieter.
- Background task descriptions no longer repeat the player slug when the task key already ends with that player name.
## 2.6.14 - 2026-08-08
### Fixed
- Slide updates and template deletes now fan out media sync work across all live players instead of targeting only one player.
## 2.6.13 - 2026-08-08
### Fixed
- The player bundle now keeps the browser-only QR export dependencies lazy-loaded, so the remote player image no longer needs `puppeteer-core` or `@sparticuz/chromium` at startup.
- Remote player startup sync now falls back to `WEB_INTERNAL_URL` when it is configured, which avoids 404s when the bridge is not the correct sync target.
- The player startup sync and media-write info logs were removed to keep normal remote-player operation quieter.
## 2.6.12 - 2026-08-08
### Fixed
- The Docker build inputs now live under `build/`, with separate web and player package manifests so the player image no longer carries the web browser tooling bundle.
- The Docker publish workflow now restores `v2` and `v2.2` style image tags alongside `latest` and the full release tag.
- Remote player sync and upload routing now carry the exact connected player device id through the bridge, so startup media and font jobs target the correct player instance in split-device deployments.
- Player websocket registration now learns the public base URL from the actual screen request origin, so localhost and 127.0.0.1 aliases both keep websocket commands working.
## 2.6.11 - 2026-08-08
### Fixed
- Role edits now save selected permissions from the shared RBAC form, so changes on the role page persist when you submit the form.
- RBAC permission sections now stay open independently in the accordion, so opening one section no longer closes the others.
## 2.6.10 - 2026-08-08
### Fixed
- The onboarding landing page and form no longer restore a previously selected screen, so the screen picker always starts clean while still keeping the saved client name.
## 2.6.9 - 2026-08-08
### Fixed
- The connected-clients view no longer exposes or sorts by client IP, so the table stays focused on the player identity, screen, and playback state.
- The connected-clients dashboard row renderer now keeps the actions column aligned after removing the IP column, so row updates no longer append a duplicate actions cell.
## 2.6.8 - 2026-08-08
### Fixed
- The screen-group command buttons stay disabled until a real target group is selected, so the placeholder "Select Screen Group" state cannot send commands.
## 2.6.7 - 2026-08-08
### Fixed
- Admin client commands now stay on the bridge for remote players, so screen control no longer depends on a public player address.
- The connected-clients screen-group controls now use the same async bulk-command path as the dashboard, including the All Screens option and live pause/blackout toggles.
## 2.6.6 - 2026-08-07
### Fixed
- Timetable entry editing now validates end times locally, requires the end to be at least one minute after the start, and highlights the end field when the value is invalid.
## 2.6.5 - 2026-08-07
### Added
- Multiple players are now supported across the player registry, dashboard snapshots, and screen group management, so a deployment can track more than one connected player at a time.
- The player-agent can now run remotely, which lets a player connect through the bridge instead of requiring everything to stay on the same host.
- The Docker Compose setup now includes a public stack with a player bridge service and a separate remote player stack, so local and split-device deployments share the same documented layout.
- Dedicated local and remote compose manifests now live at `docker-compose/docker-compose.yml` and `docker-compose/docker-compose.remote.yml`, with matching example env files for the two deployment modes.
- Admin client commands now have a dedicated route and test coverage, which keeps dashboard actions aligned with the current player control-plane flow.
### Changed
- Screen group views now show each registered player's public base URL and computed player URL on the edit screen instead of assuming a single local player.
- The dashboard status indicator now reports the connected player count, which makes the live feed status more explicit when several players are online.
- Player command dispatch, playlist playback, and render preloading were tightened so the player keeps using the active web base URL and can warm assets before the slide is shown.
- Playlist video-duration selection now uses the longest matching video region when a slide contains more than one video region.
- Media sync, font sync, and upload sync now follow the newer player-agent workflow, keeping background tasks and dashboard refreshes consistent with split-device deployments.
- The onboarding landing page now shows a built-in QR placeholder and falls back to it when the QR request fails, so the screen never starts blank.
- Upload sync now resolves the player internal base URL once per batch and reuses it for queued upload and delete operations, keeping mirrored media writes pointed at the active player endpoint.
- The connected clients list now defaults to client name, then IP address, so rows stay in a stable order when connection details change.
### Fixed
- Connected clients search results now keep the row action column, because the row template resolves `currentUser` from the parent view context while rendering inside the `clients` loop.
- The move-client modal now carries the row's player base URL through to the redirect step, so clients move correctly even when local and bridge-backed players are mixed.
- Paginated table cards now only apply their minimum height when the table content would otherwise exceed that threshold, which keeps short result sets compact in smaller browser windows.
## 2.6.4 - 2026-08-07
### Fixed
- The screen table no longer stores a player foreign key, and screen/player URLs now resolve from the current player registration instead of a screen assignment.
## 2.6.3 - 2026-08-07
### Fixed
- The screen table no longer enforces a foreign key to the player table, which keeps player assignments flexible while preserving the existing screen schema.
## 2.6.2 - 2026-08-07
### Fixed
- The player registry now upgrades to an integer player id with a separate player identifier so the schema migration can complete cleanly on existing databases.
- Dashboard screen lookups now tolerate the upgraded player table layout during the rollout.
## 2.6.1 - 2026-08-06
### Fixed
### Changed
- The web side now resolves the player base URL from the database-backed player registration record instead of depending on a web-container environment fallback.
- Player registrations now store a separate friendly identifier, so a player can keep the same device key while showing a label like `Shop2`.
## 2.5.14 - 2026-08-06
### Added
- Branded Windows and Linux kiosk launcher downloads on the dashboard, with updated copy that explains the launcher behavior more clearly.
- Kiosk launchers now start the browser in kiosk mode, suppress notifications for Chromium-based browsers, and use the correct Firefox kiosk flag.
## 2.5.13 - 2026-08-05
### Fixed
- Slide and template save forms now allow larger multipart text fields, so rich region content no longer trips Multer's default field-value limit.
## 2.5.12 - 2026-08-05
### Fixed
- The auth route test now loads the alias bootstrap before the login flow, so isolated test runs do not depend on prior module initialization.
- The slide editor now blocks pasted data images in TinyMCE so image content must come through the upload flow.
## 2.5.11 - 2026-08-05
### Fixed
- Single-slide playlists now re-render the active slide immediately when a refresh arrives, instead of waiting for a transition that never happens.
- Playlist create and update flows now redirect to the canonical `/playlists/:id/edit` path after saving.
- Slide preview popups now keep rich-text spacing and line height consistent with the editor preview.
## 2.5.10 - 2026-08-05
### Fixed
- Slide editor rich-text updates now keep the hidden field and preview state in sync after inline formatting actions.
## 2.5.9 - 2026-08-05
### Fixed
- Screen playlist refreshes now wait until the next slide transition before applying a pending update, so one-slide playlists do not swap immediately during a refresh.
- Playlist rows now show the mute control for any playable media region, including RTMP slides, instead of only video regions.
## 2.5.8 - 2026-08-05
### Fixed
- MariaDB migrations now retry alternate foreign-key constraint names when screen-to-player constraint creation reports a duplicate-key error.
## 2.5.7 - 2026-08-05
### Fixed
- QR template backgrounds now use a single solid color only, and the editor no longer exposes a background gradient mode.
## 2.5.6 - 2026-08-05
### Added
- Onboarding QR rendering now uses the vendored `qr-code-styling` library directly, with a wider quiet zone and extra frame padding so the code does not clip at the corners.
### Changed
- The shared QR helper now renders `qr-code-styling` in Node without the old `qrcode` or `qrcode-generator` packages.
- The onboarding QR endpoint now generates the styled QR at request time, and the player onboarding page requests it only after confirming the player is not already onboarded.
- Playlist QR preview backfill now uses the same styled QR helper as onboarding, so playlist snapshots and generated previews stay consistent.
- The onboarding QR layout now keeps the code inset within its frame so the corners have more breathing room.
## 2.5.5 - 2026-08-04
### Added
- A shared Dupe flow was added to most admin create pages and list views, including roles, users, playlists, slides, templates, canvas sizes, announcements, and supported data sources.
### Changed
- RBAC roles now include a Dupe action that opens a copy-on-create flow with the selected permissions already populated.
- Users now include a Dupe action that opens the add-user form with the copied name and roles, while leaving the username blank for a new login.
- User usernames are now editable from the admin users section, while the personal account password page remains unchanged.
- The users form now allows creating an account without assigning any roles.
- Save and New on the users form now returns to the blank create page instead of falling back to the list.
- Password updates now accept a slightly lighter policy of 10 characters with 3 of 4 character classes, and the account and user password forms now describe the updated requirement.
- The slide rich-text editor now groups underline, strikethrough, subscript, and superscript into a single split-button control, with the main button using the underline icon and the dropdown exposing the other text-format actions.
- Chip formatting in the slide rich-text editor now uses a reusable inline-format helper so the chip action continues to sync and mark the editor as edited when applied.
- RSS, API, and timetable placeholder help text now uses the same transform examples, spacing, and typography as the timetable version, with the hint shown after the visible placeholders and before any overflow disclosure.
### Fixed
- Cells and inputs now enforce route-specific character limits on the form itself and on the matching save paths, so overlong values no longer fail at submit time.
- Playlist rows now use a grip drag handle with separate up/down move controls, and the drag grip cursor now changes to grab and grabbing on hover and drag.
- Playlist duration inputs now respect a min-only limit correctly, so the shared limiter no longer coerces values down to 0 when no max attribute is present.
- Playlist row video and mute toggles now use the correct filled/outline Bootstrap button styles for their current state without relying on the `active` class.
- Slides table search now only matches slide titles and template names, and no longer searches within slide content.
- Banner marquee text now measures its real cycle width so top-banner and lower-third announcements loop continuously instead of resetting from a fixed start position.
- Slide editor template selection now stays editable on blank slides until the user makes a real content edit, so TinyMCE hydration no longer locks the canvas immediately.
- Slide editor region cards now share a common header shell, so the image and video chips stay aligned with the other region types on the Video Webpage and HTML RTMP pages.
- Firefox preview popup now centers the preview canvas in normal layout flow and scales from the center, so the popup preview lines up correctly in Chrome and Firefox.
- Canvas size edits now keep the width and height fields locked while the size is in use, and oversized canvas dimensions are rejected at 16384 instead of reaching the save path.
- Schedule rules now start collapsed by default, use the built-in card collapse behavior, and keep validation messages visible without re-highlighting empty paired inputs.
- Timetable group deletes now scan slide content for the actual `timetable_group_id` field, so groups that are still referenced by slides stay protected from deletion.
- Timetable add and edit pages now keep cancel confirmation tied to timetable entry edits, so changes inside the entries table are treated as unsaved form changes.
- Screen add and edit pages now keep the Player URL box in a stable two-column layout, so switching between the forms no longer causes the page to jump or shift.
- Screen add pages now show the secondary Save and Close / Save and New actions, and screen edit delete actions now prompt for confirmation before removing the screen.
- Admin user password resets now keep the selected user in view by returning to that user's edit page after saving.
- Account password saves now refresh the page after the success toast is queued so the confirmation message stays visible.
- Shared toast handling now preserves a pending success message across the redirect so refreshes do not drop the confirmation banner.
- Announcement create and edit pages now keep the save action buttons visible, and the edit-page delete action now prompts for confirmation before deleting.
- Active announcements are now blocked from deletion with a clearer edit-page message that explains why.
- Slide template create now shows the background image remove button and clear flag, matching the edit page behavior.
- Template create now exposes Save & Close and Save & New actions, and template edit delete actions now use the shared action-button helper with a confirmation prompt instead of a separate hidden form.
- The advanced animation modal now shows intro, outro, and loop durations as 1-200% fields, with 100% saving back as 1000ms.
- The advanced animation modal now hard-limits repeat counts to 999 so attention-seeker animations cannot be configured with unbounded loops.
- Template editor region boxes now rerender when the canvas or stage resizes, and region width/height changes now keep the lock ratio, stay within the canvas, and shift back on-canvas instead of spilling over.
- Background tasks and scheduled tasks now render timestamps in 24-hour format, and the background task queue keeps a confirmation prompt before clearing finished items.
## 2.5.4 - 2026-08-03
### Changed
- The API source bearer token field now uses a password input with a right-side toggle to show or hide the token.
### Fixed
- QR code regions now render at the correct size in the slide editor preview, and the QR chip header now matches the other region cards.
- The dashboard onboarding link now uses the player public base URL stored in the database instead of a `/screen/...` URL.
## 2.5.3 - 2026-08-03
### Changed
- The user edit page delete action now shows a confirmation prompt before removing an account.
### Fixed
- Schedule modal cancel now restores the original rule set instead of keeping edits made after the modal opened.
## 2.5.2 - 2026-08-03
### Changed
- Player page auth now writes a cookie for websocket reuse, and player and announcement sockets accept that cookie so they no longer depend on query-string tokens.
- RSS and API region placeholder panels now use shared field-aware chip rendering, with updated spacing and defaults across the slide editor.
- RTMP regions now default audio to enabled in the editor, and the slide rich-text editor no longer allows anchor tags.
### Fixed
- Player websocket auth now falls back to the `pulse_page_auth` cookie when the auth query parameter is unavailable.
## 2.5.1 - 2026-08-03
### Added
- Template regions now include a dedicated advanced animation modal for editing intro, outro, and Attention Seekers settings directly.
### Changed
- Template region animation settings now store as a single JSON object with `intro`, `outro`, and `loop` keys.
- The template editor advanced animation field now edits the JSON object directly instead of separate preset selects.
- Animate.css is now loaded from vendored assets so template previews and player rendering use the local copy.
### Fixed
- Existing databases now migrate legacy animation columns into `animation_json` and then drop the old columns.
## 2.5.0 - 2026-08-03
### Added
- Template regions now support intro, exit, and Attention Seekers animation presets in the editor, with in-canvas preview controls.
### Changed
- The template editor now locks editing while preview playback is running so animation changes are easier to inspect.
### Fixed
- Existing databases now receive the template region animation columns through the versioned migration path.
## 2.4.2 - 2026-08-02
### Added
- Screen-level controls are now shown on the dashboard for quicker access to screen actions.
- Connected clients can now be moved to another screen from the dashboard, and the player redirects to the new screen after the binding updates.
- Playlist slide config now includes a mute toggle for video and RTMP items, and the player honors the stored mute state during playback.
### Changed
- Playlist canvas lock now stores `canvas_id` on `c_playlists` and links directly to `c_canvas_sizes`.
- Playlist add and edit now keep the selected canvas size tied to the playlist form flow, so canvas changes stay consistent while editing.
- RBAC permission sections now follow the same order as the admin sidebar, with section spacing kept in 10-point increments.
- Admin add/edit pages now share form view-model helpers and common form shells across data sources, signage, RBAC, and user settings, reducing duplicated template markup.
- Playlist editing now goes through a shared form page helper with dedicated schedule-rule cards and drag sorting, keeping slide rows and rule state in sync.
- Data sources now use per-section route modules for API sources, RSS feeds, and timetables, while the shared controller only keeps the root `/data-sources` redirect.
- The consolidated admin shell also refreshed shared layout, toast, login, and error rendering to match the newer helper registration flow.
- Connected client row actions now use consistent icon-and-label buttons for pause and blackout across the server-rendered page and live dashboard updates.
### Fixed
- Canvas filtering for playlist slides now follows the selected canvas size id instead of a derived signature.
- Saving API sources and RSS feeds no longer throws an internal server error after the route split, because the shared data-source refresh task service is wired through the web bootstrap again.
## 2.4.1 - 2026-08-02
### Changed
- Playlist canvas size is now stored on `c_playlists.canvas_signature` and the migration backfills existing single-canvas playlists.
### Fixed
- Playlist canvas sizing no longer relies on startup bootstrap logic.
## 2.4.0 - 2026-08-02
### Added
- Playlist slide scheduling now supports multiple OR-ed rule blocks instead of a single date-or-time schedule.
### Changed
- Playlist slide schedule data now stores rule sets in `schedule_rules_json`, and the migration backfills legacy schedule columns before dropping them.
### Fixed
- Legacy `schedule_mode`, date, time, and day columns are removed from `c_playlist_slides` after the new rule schema is installed.
## 2.3.0 - 2026-08-02
### Added
- Shared add/edit form templates now cover API sources, RSS feeds, announcements, canvas sizes, screens, and templates, reducing duplicate page markup.
- Schedule data source CRUD was added for grouped events in the admin UI.
- The schedule region was added for rendering grouped events in slides and player playback.
- Schedule data now flows through `scheduleGroups` in the slide editor and player payloads, letting the schedule region show upcoming or current entries from a selected group.
### Changed
- Admin save actions were standardized around the shared `saveActionButtons` helper, including save, save-and-close, save-and-new, cancel, and delete controls.
- Admin routes and page renderers now route through the shared form/view helpers instead of separate add/edit templates for the refactored sections.
- Toast, error, login, and shared layout rendering were refreshed to line up with the consolidated admin shell and helper registration flow.
### Fixed
- Canvas size defaults now seed only once during bootstrap when `c_canvas_sizes` is empty, instead of running from the schema layout path on every startup.
- The schema bootstrap file is now limited to table layout definitions, with one-time seed data handled by the bootstrap layer.
## 2.2.2 - 2026-08-01
### Fixed
- The theme bootstrap now resolves saved `auto` to an actual dark or light value on first paint, so explicit dark mode no longer flashes white while the page loads.
- The shared app header is now sticky so the top navigation stays visible while scrolling.
## 2.2.1 - 2026-08-01
### Fixed
- Managed-font source files are now tracked correctly so packaged releases include the `src/web/lib/media` module instead of shipping a broken build.
## 2.2.0 - 2026-08-01
### Added
- Announcement management is now wired for the admin UI and player overlay, with color, template, and expiry controls.
- Time / Date regions now render live in the editor and player.
### Changed
- Announcement lists now default-sort by Description and show the affected screens for each announcement.
- Role add and edit pages now include a Cancel action alongside the save buttons.
- Announcement publishing now only targets explicitly assigned screens; unassigned announcements no longer publish globally.
### Fixed
- Announcement screen labels now correctly distinguish No Screens, partial assignments, and All Screens.
- Role duplicate-name validation on edit now checks the correct RBAC table.
## 2.1.1 - 2026-08-01
### Added
- API source latest-response viewing now supports collapsing and expanding all JSON sections from the edit page.
- Placeholder transforms now support basic string helpers like `.upper()`, `.title()`, and `.lower()`.
### Changed
- The API source add page now matches the edit pages section titles and layout more closely.
- API source placeholder suggestions now stay leaf-only, so container paths and arrays are no longer suggested as placeholders.
- Slide editor and player placeholder resolution now share the same parsing and transform logic.
- API source and RSS editor helper text now shows the new placeholder transform syntax.
- API sources, RSS feeds, slides, users, and roles now render their delete actions in a disabled outlined-danger state when deletion is blocked, matching the rest of the admin tables.
- The users edit page no longer wraps all sections in one outer card, so the profile, password, and roles cards render as separate sections.
### Fixed
- API source item-path overrides continue to treat the final path as an array source, while nested object fields remain available for placeholders.
- The API source latest-response panel now opens as a tree view by default instead of a flat JSON blob.
## 2.1.0 - 2026-07-30
### Added
- Screen and dashboard player links now render the full player URL instead of only the player base host.
- Notes near the singleton-player code paths to make the future multi-player migration work easier to revisit.
### Changed
- The player registry now uses a singleton `d_players` row and `d_screens.player_id` points at that shared player record.
- Player startup is now responsible for creating the shared player record, while onboarding and state polling no longer create extra player rows.
- The screen/player binding path was simplified so opening a screen binds it to the shared player record without trying to re-register the player.
- Managed fonts now have dedicated editor/player sync handling, including a scheduled font sweep, sorted font-family lists, the TinyMCE fullscreen button, and shared font stylesheet loading in the WYSIWYG editor.
- Text and RSS region types now own their own default style and fallback behavior instead of relying on shared slide helper fallbacks.
- Image and video region handling was also pushed further into modular per-type modules, keeping their editor, preview, and player logic closer to the region itself instead of the shared slide helper layer.
### Fixed
- Removed several onboarding and runtime code paths that were still inserting or refreshing `d_players` rows during normal player playback.
- Fixed the screen-binding flow so it no longer writes a device UUID into `d_screens.player_id`, which avoided foreign key errors under the shared-player model.
## 2.0.0 - 2026-07-28
### Breaking Changes
- Breaking database schema changes were introduced in this release; existing databases may require migration or recreation before upgrading.
### Added
- Broader player and admin release coverage across onboarding, playlist playback, background task handling, and media-region support.
### Changed
- The database bootstrap and migration flow were reorganized, with shared DB helpers split out to support the newer schema layout.
- Admin and signage views were updated around the newer list, playlist, and RBAC behavior, including playlist scheduling and screen/client actions.
- Player runtime, onboarding, and region rendering were tightened so HTML, image, RSS, RTMP, text, video, and webpage regions follow the newer playback flow.
- Background task, upload sync, and data-source refresh handling were refined across the web app and startup paths.
- Docker, environment, README, and websocket/api documentation were refreshed to match the current release structure.
### Fixed
- Client name checks, playlist editing, and slide/media synchronization paths were adjusted to better preserve existing references during admin and player updates.
## 1.5.16 - 2026-07-26
### Added
- Background task handling was split into dedicated handler and scheduling modules, with startup data-source refreshes and unused-upload cleanup wired through the shared setup flow.
### Changed
- The admin shell, shared theme, and toast presentation were refreshed to match the newer layout and notification styling.
- Playlist scheduling now handles video-duration toggles and already-assigned slides more clearly in the picker and editor UI.
- RBAC and settings views were updated to align with the revised admin layout and shared table behavior.
### Fixed
- Template and slide thumbnail refreshes now run through the background task queue so template-wide thumbnail regeneration stays consistent.
## 1.5.15 - 2026-07-26
### Changed
- Player slide transitions now start and pause video playback around the fade window so video regions stay aligned with the slide boundary.
- Dashboard action cards now use a three-column grid on wider layouts.
### Fixed
- Slide video duration probes now preserve sub-second precision instead of rounding to whole seconds.
## 1.5.14 - 2026-07-26
### Fixed
- Dashboard client action icons now render valid Bootstrap Icon classes without duplicating the `bi-` prefix.
## 1.5.13 - 2026-07-26
### Added
- Shared table helpers for pagination, search, and sorting across the admin and signage views.
### Changed
- Refreshed the shared admin shell and moved common UI behavior into shared layout and helper modules.
- Reworked dashboard, background tasks, RBAC, and signage list pages to use the newer shared table and state flow.
- Updated the admin and player branding assets and tightened the page scripts around the new layout structure.
## 1.5.12 - 2026-07-26
### Changed
- Shared web UI helpers are now loaded once in the admin shell and reused across the dashboard, admin, and template editor.
- Template lists now show slide counts, and the template editor tracks which regions are already in use.
### Fixed
- Template editing now blocks removal of regions that are still referenced by slides.
## 1.5.11 - 2026-07-26
### Added
- Video regions are now supported end to end, including player rendering, admin editing, playlist scheduling, and player sync.
### Changed
- The slide, template, and playlist flows were updated so video content can be created, configured, and scheduled alongside existing region types.
- Player rendering and related media handling now recognize the new video region implementation.
### Fixed
- Region and upload handling were adjusted so video media syncs cleanly through the player and web admin paths.
## 1.5.10 - 2026-07-26
### Added
- Scheduled background tasks now have their own settings page, separate permission gate, and manual run action alongside the main queue view.
- The slide editor now includes a refreshed preview/sidebar layout and a cropper-based image upload flow.
### Changed
- Background task and admin list views now use richer pagination and filtering so queue state, task sources, and recurring jobs stay easier to navigate.
- The admin shell and shared styling were refreshed to support the updated settings pages, slide editor layout, and task table presentation.
### Fixed
- Upload sync and slide thumbnail refresh handling were tightened so slide changes queue follow-up work more reliably.
## 1.5.9 - 2026-07-26
### Fixed
- User creation now keeps the role checkboxes inside the add-user form so selected roles are submitted correctly.
## 1.5.8 - 2026-07-25
### Fixed
- Upload removal requests now authenticate correctly when a deployed player parses a bodyless `DELETE` request as an empty object, which could cause 401s for newly uploaded images.
## 1.5.6 - 2026-07-25
### Changed
- Playlist slide picker now uses a button to reveal already added slides, while still defaulting to showing only available slides.
- Already-added slides in the picker are now labeled and visually muted to make them easier to spot.
### Fixed
- Thumbnails in slide and playlist tables now follow the slide canvas ratio and cap at 5.5rem tall.
- Thumbnail-only table columns are no longer sortable.
## 1.5.5 - 2026-07-25
### Fixed
- Fixed a migration gap that could leave `slides.thumbnail_path` missing on upgraded databases.
## 1.5.4 - 2026-07-25
### Added
- Cropper.js has been added to aid with image uploading.
### Changed
- Upgraded Multer to 2.x to remove the deprecated 1.x dependency warning.
- Tightened a few admin UI details, including slide editor and RBAC list spacing/typography adjustments.
## 1.5.3 - 2026-07-25
### Added
- A modal-based slide picker for playlist editing with search, multi-select, and slide thumbnails.
- Reusable modal and table-pagination helpers for the admin UI.
- Slide thumbnail previews in playlist schedules, with image fallbacks when a thumbnail is missing.
### Changed
- RTMP playback now probes session readiness more aggressively and retries startup before surfacing failures.
- Playlist editing now includes richer scheduling controls, live slide counts, and support for skipping unavailable RTMP slides.
- Admin lists and background task pages now preserve filter and pagination state during AJAX navigation.
- Shared admin shell styling and helpers were refreshed to support the newer list, modal, and pagination UI.
### Fixed
- Player upload sync and route handling now degrade more gracefully when backend services are unavailable.
- RTMP and playlist playback now recover more cleanly when a stream fails to initialize or respond in time.
## 1.5.2 - 2026-07-25
### Fixed
- Fixed player media upload sync so signed upload requests are verified after the request body has been parsed.
## 1.5.1 - 2026-07-25
### Fixed
- Fixed the account page so it can save changes again.
## 1.5.0 - 2026-07-25
### Added
- RTMP slide regions with ffmpeg-to-HLS playback support in the player.
- Service-worker-backed player caching and offline recovery paths for playlists and playback state.
- Broader slide, template, playlist, RSS, and API source support, including richer region handling and background refresh processing.
### Changed
- Reworked the web admin app around a newer modular route and view layout, with shared helpers moving into `src/web/lib`, `src/web/pages`, and `src/web/views`.
- Refreshed the admin shell styling and theme bootstrapping, including local AdminLTE assets, vendored Bootstrap Icons, and earlier theme initialization on first paint.
- Rebuilt RBAC around CRUD permissions and updated the admin screens for roles, users, and action gating.
- Refactored the player onboarding flow, client-name handling, and runtime storage so screen identities persist more reliably across refreshes.
- Tightened duplicate-name checks and other admin-side validation paths.
### Fixed
- Improved player fallback behavior when the database is unavailable.
- Cleaned up player runtime and routing paths so screen lookups and live updates degrade more gracefully.
### Docs and Ops
- Updated Docker, environment, and documentation files to match the current release structure and player/web APIs.
## 1.4.6 - 2026-07-22
### Changed
- Refined RBAC enforcement across the admin UI and route layer, especially for list actions and edit screens.
- Updated the dashboard and admin styling to match the revised permission model and page layout.
- Adjusted database helpers and admin data views to support the newer RBAC and list rendering behavior.
## 1.4.5 - 2026-07-21
### Changed
- Renamed the admin screen commands route to client commands and aligned the dashboard copy with client-focused terminology.
- Updated the RBAC and database helpers to support the revised client command flow.
- Refined the client list view and dashboard interactions around the new client command behavior.
## 1.4.4 - 2026-07-21
### Fixed
- Rendered 404 pages for unmatched routes.
## 1.4.3 - 2026-07-21
### Fixed
- Fixed RBAC client action visibility.
## 1.4.2 - 2026-07-21
### Fixed
- Fixed duplicate permissions cleanup.
## 1.4.1 - 2026-07-21
### Added
- RBAC roles system support.
### Changed
- Version bump to 1.4.1.
### Fixed
- Schema migration audit columns.
## 1.3.4 - 2026-07-21
### Fixed
- Fixed duplicate onboarding client names.
## 1.3.3 - 2026-07-21
### Added
- The first round of modular admin-page work, including a shared admin route layer and refreshed dashboard/list rendering.
### Changed
- Updated the admin shell styling and layout handling for the newer page structure.
- Adjusted package metadata and lockfile state to match the release.
## 1.3.2 - 2026-07-21
### Changed
- Version bump to 1.3.2.
## 1.3.0 - 2026-07-20
### Added
- Split shared helpers, bootstrap logic, route groups, and upload-sync behavior out of `web.js`.
- Split websocket and runtime handling into `runtime.js`.
- Split playlist assembly and revision hashing into `playlist.js`.
- Split onboarding and player HTTP routes into dedicated modules.
- Split render utilities and template loading into `render-helpers.js`.
### Changed
- Kept `web.js` focused on wiring and server startup.
- Kept `player.js` mostly as startup and orchestration.
### Fixed
- Fixed screen playlist reassignment so changing a screen's playlist now triggers a refresh.
- Fixed single-slide playlist refresh behavior so updates do not get stuck behind the current slide.
## 1.1.5 - 2026-07-15
### Fixed
- Fixed text pasting in the admin UI.
## 1.1.4 - 2026-07-15
### Fixed
- Fixed the admin table and playlist reorder UI.
## 1.1.3 - 2026-07-15
### Added
- Playlist drag sorting.
- Local SortableJS.
- Playlist UI updates.
## 1.1.2 - 2026-07-14
### Changed
- Updated the admin layout and frame shell styling.
- Refined `src/web/view.js` so view rendering handles the revised shell structure.
- Adjusted package metadata for the release.
## 1.1.1 - 2026-07-14
### Changed
- Refreshed favicon and layout assets.
## 1.1.0 - 2026-07-14
### Changed
- Refactored the web server and release workflow.
## 1.0.2 - 2026-07-14
### Fixed
- Handled player redirects on screen slug change.
## 1.0.1 - 2026-07-14
### Changed
- Made screen slugs editable.
## 1.0.0 - 2026-07-14
### Fixed
- Initial release.