Skip to content

Commit f41bb72

Browse files
fhirschmannclaude
andcommitted
feat: blinking OK indicator instead of success toast
Replace the generic 'action performed successfully' toast with a short blinking 'OK' next to the battery indicator in the navbar. Specific success toasts (backup/clean/upload) are kept. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 11ade33 commit f41bb72

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ neon logo that doubles as the SVG favicon ([`8d9725c`](../../commit/8d9725c)):
6767
| PWA support: web app manifest + app icon, "add to home screen" with proper icon and name | [`a59fe0b`](../../commit/a59fe0b) |
6868
| Full backup: export/import of all settings + RFID assignments as JSON, WiFi credentials optional | [`7f2e4ae`](../../commit/7f2e4ae) |
6969
| Equalizer profiles: dropdown presets (Flat / Music / Audiobook-Speech / Deep voices / Custom) on top of the 3-band tone control; speech presets cut bass and lift mids/highs so deep narrator voices stay intelligible, persisted in NVS. Profiles can also be assigned per file or directory (right-click in the file browser) — e.g. set the speech profile for all Bibi Blocksberg episodes at once. The active profile can be cycled with the bindable command **154** (button/RFID modifier) and set/reported via the MQTT topic `equalizer` (`flat`/`music`/`speech`/`voiceBoost`) | [`300b9dd`](../../commit/300b9dd) |
70+
| Blinking "OK" indicator next to the battery replaces the generic "action successful" toast | [`0870ccc`](../../commit/0870ccc) |
7071
| SD card cleanup: removes macOS metadata (`.DS_Store`, `._*`, Spotlight/Trashes) with one click | [`5f38a51`](../../commit/5f38a51) |
7172
| Live log: the log dialog refreshes every 2 s and follows the end of the log | [`d326faa`](../../commit/d326faa) |
7273
| Drag & drop: upload files by dropping them from the file manager onto the file tree | [`e4972fe`](../../commit/e4972fe) |

html/management.html

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,32 @@
235235
animation: cp-flicker 3s linear infinite;
236236
}
237237

238+
/* blinking "OK" confirmation shown next to the battery after an action succeeds */
239+
#actionOk {
240+
color: var(--cp-green);
241+
font-family: "Share Tech Mono", monospace;
242+
font-weight: 700;
243+
font-size: .9rem;
244+
letter-spacing: 1px;
245+
text-shadow: 0 0 10px rgba(10, 255, 157, .8);
246+
margin-right: 12px;
247+
opacity: 0;
248+
}
249+
250+
#actionOk.show {
251+
animation: ok-blink 1.6s ease-in-out;
252+
}
253+
254+
@keyframes ok-blink {
255+
0% { opacity: 0; }
256+
12% { opacity: 1; }
257+
28% { opacity: .15; }
258+
44% { opacity: 1; }
259+
60% { opacity: .15; }
260+
76% { opacity: 1; }
261+
100% { opacity: 0; }
262+
}
263+
238264
/* ---------- dropdown menu ---------- */
239265
.dropdown-menu {
240266
background: var(--cp-panel);
@@ -1045,6 +1071,7 @@
10451071
<span id="navbar-heading" data-i18n="title"></span>
10461072
</a>
10471073
<div class="collapse navbar-collapse justify-content-end">
1074+
<span class="navbar-text" id="actionOk" aria-hidden="true"><i class="fas fa-check"></i> OK</span>
10481075
<span class="navbar-text" id="batteryIndicator" data-visible="false">
10491076
<i class="fas fa-battery-three-quarters" id="batteryIcon"></i><span id="batteryLevel"></span>
10501077
</span>
@@ -2488,6 +2515,18 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
24882515
error: msg => toaster.toast(msg, 'text-bg-danger')
24892516
}
24902517

2518+
// Briefly blink an "OK" next to the battery indicator to confirm an action
2519+
// succeeded -- replaces the noisy generic "action performed successfully" toast.
2520+
function flashActionOk() {
2521+
const el = document.getElementById('actionOk');
2522+
if (!el) return;
2523+
el.classList.remove('show');
2524+
// force a reflow so the animation restarts even on rapid consecutive actions
2525+
void el.offsetWidth;
2526+
el.classList.add('show');
2527+
el.addEventListener('animationend', () => el.classList.remove('show'), { once: true });
2528+
}
2529+
24912530
i18next.use(i18nextHttpBackend).init({
24922531
backend: {
24932532
loadPath: "http://" + host + "/locales/{{lng}}.json"
@@ -3333,7 +3372,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
33333372
}
33343373
if ("status" in socketMsg) {
33353374
if (socketMsg.status == "ok") {
3336-
toaster.success(i18next.t("toast.success"));
3375+
flashActionOk();
33373376
}
33383377
if (socketMsg.status == "dropout") {
33393378
toaster.warning(i18next.t("toast.dropout"));
@@ -3852,7 +3891,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
38523891
method: "DELETE"
38533892
});
38543893
if (response.ok) {
3855-
toaster.success(i18next.t("toast.success"));
3894+
flashActionOk();
38563895
rebuildRFIDList();
38573896
} else {
38583897
toaster.error(response.statusText);
@@ -3866,7 +3905,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
38663905
method: "POST"
38673906
});
38683907
if (response.ok) {
3869-
toaster.success(i18next.t("toast.success"));
3908+
flashActionOk();
38703909
await rebuildRFIDList();
38713910
} else {
38723911
toaster.error(response.statusText);
@@ -3885,7 +3924,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
38853924
body: formData
38863925
});
38873926
if (response.ok) {
3888-
toaster.success(i18next.t("toast.success"));
3927+
flashActionOk();
38893928
rebuildRFIDList();
38903929
} else {
38913930
toaster.error(response.statusText);
@@ -4615,7 +4654,7 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
46154654
})
46164655
});
46174656
if (response.ok) {
4618-
toaster.success(i18next.t("toast.success"));
4657+
flashActionOk();
46194658
document.getElementById('wwwPassword').value = '';
46204659
refreshSecurityStatus();
46214660
} else {

0 commit comments

Comments
 (0)