Boot splash and periodic announcement banner

Splash: resources/splash/splash.gif built into the binary, played once by
SplashOverlay over a black cover present from the first frame (no UI
flash), then fades into the UI; hides icons loading. GIF, so no
QtMultimedia/gstreamer. Toggle: splash.enabled.

Banner (InfoBanner): metro-style band that fades/slides in with a hold
pictogram; text that does not fit runs as a seamless ticker for two
rounds. Never takes touches; hidden during splash and settings. Config
section banner (enabled, text, intervalSec, showSec, position,
accentColor), editable in the web UI and on-device settings; shown once
after saving.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-10 10:58:16 +00:00
co-authored by Claude Opus 5.5
parent ec84133417
commit f07e153f09
22 changed files with 753 additions and 3 deletions
+37
View File
@@ -214,6 +214,43 @@
</div>
</div>
<div class="card">
<h2>Объявление и заставка</h2>
<p class="hint">Объявление периодически плавно появляется поверх кнопок, как табло в метро, и не мешает нажатиям. Длинный текст прокручивается бегущей строкой. После сохранения объявление один раз показывается на экране.</p>
<label class="banner-text-label">Текст объявления
<textarea id="banner-text" rows="3" maxlength="200" placeholder="Для вызова клининга удерживайте кнопку">{{ config.banner.text }}</textarea>
<span class="hint"><span id="banner-text-count">0</span>/200. Переносы строк заменяются пробелами: на экране текст идёт в одну строку.</span>
</label>
<div class="grid-form">
<label class="check">
<input type="checkbox" id="splash-enabled" {% if config.splash.enabled %}checked{% endif %}>
Заставка при запуске
</label>
<label class="check">
<input type="checkbox" id="banner-enabled" {% if config.banner.enabled %}checked{% endif %}>
Показывать объявление
</label>
<label>Раз в, сек (30–3600)
<input type="number" id="banner-interval" min="30" max="3600" step="10" value="{{ config.banner.intervalSec }}">
</label>
<label>Длительность показа, сек (3–60)
<input type="number" id="banner-show" min="3" max="60" value="{{ config.banner.showSec }}">
</label>
<label>Положение
<select id="banner-position">
<option value="bottom" {% if config.banner.position != 'top' %}selected{% endif %}>Снизу</option>
<option value="top" {% if config.banner.position == 'top' %}selected{% endif %}>Сверху</option>
</select>
</label>
<label>Цвет полосы
<input type="color" id="banner-accent" value="{{ config.banner.accentColor|default('#e4002b', true) }}">
</label>
</div>
<div class="card-actions compact">
<button id="save-banner" class="primary">Сохранить</button>
</div>
</div>
<div class="card">
<h2>Иконки</h2>
<div class="row">