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:
@@ -548,6 +548,28 @@ $("#save-feedback")?.addEventListener("click", async () => {
|
||||
} catch (e) { flash(e.message, true); }
|
||||
});
|
||||
|
||||
// ---------- Banner + splash ----------
|
||||
function syncBannerCount() {
|
||||
const t = $("#banner-text"), c = $("#banner-text-count");
|
||||
if (t && c) c.textContent = t.value.length;
|
||||
}
|
||||
$("#banner-text")?.addEventListener("input", syncBannerCount);
|
||||
syncBannerCount();
|
||||
$("#save-banner")?.addEventListener("click", async () => {
|
||||
try {
|
||||
await api("PUT", "/api/banner", {
|
||||
splashEnabled: $("#splash-enabled").checked,
|
||||
enabled: $("#banner-enabled").checked,
|
||||
text: $("#banner-text").value,
|
||||
intervalSec: parseInt($("#banner-interval").value, 10),
|
||||
showSec: parseInt($("#banner-show").value, 10),
|
||||
position: $("#banner-position").value,
|
||||
accentColor: $("#banner-accent").value,
|
||||
});
|
||||
flash("Объявление сохранено");
|
||||
} catch (e) { flash(e.message, true); }
|
||||
});
|
||||
|
||||
// ---------- Icons ----------
|
||||
$("#upload-icon")?.addEventListener("click", async () => {
|
||||
const file = $("#icon-file").files[0];
|
||||
|
||||
@@ -105,6 +105,16 @@ main {
|
||||
label { display: flex; flex-direction: column; gap: 5px; font-size: 0.88em; color: var(--muted); }
|
||||
label.check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); }
|
||||
label.label-range { gap: 6px; }
|
||||
.banner-text-label { margin-bottom: 14px; }
|
||||
.banner-text-label textarea {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
min-height: 4.5em;
|
||||
resize: vertical;
|
||||
font: inherit;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.label-caption {
|
||||
display: block;
|
||||
font-size: 0.88em;
|
||||
@@ -117,7 +127,7 @@ label.label-range { gap: 6px; }
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="number"], input[type="password"], select {
|
||||
input[type="text"], input[type="number"], input[type="password"], select, textarea {
|
||||
background: var(--bg-input);
|
||||
border: 1px solid var(--border-strong);
|
||||
color: var(--text);
|
||||
@@ -126,7 +136,7 @@ input[type="text"], input[type="number"], input[type="password"], select {
|
||||
font: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
input:focus, select:focus { border-color: var(--accent); outline: none; }
|
||||
input:focus, select:focus, textarea:focus { border-color: var(--accent); outline: none; }
|
||||
input[type="color"] {
|
||||
width: 48px; height: 34px; padding: 2px;
|
||||
background: var(--bg-input); border: 1px solid var(--border-strong);
|
||||
|
||||
Reference in New Issue
Block a user