|
218 | 218 | text-shadow: 0 0 8px rgba(0, 240, 255, .6); |
219 | 219 | } |
220 | 220 |
|
| 221 | + #batteryIndicator { |
| 222 | + color: var(--cp-green); |
| 223 | + font-family: "Share Tech Mono", monospace; |
| 224 | + font-size: .9rem; |
| 225 | + text-shadow: 0 0 8px rgba(10, 255, 157, .5); |
| 226 | + } |
| 227 | + |
| 228 | + #batteryIndicator.battery-low { |
| 229 | + color: var(--cp-magenta); |
| 230 | + text-shadow: 0 0 8px rgba(255, 42, 109, .6); |
| 231 | + animation: cp-flicker 3s linear infinite; |
| 232 | + } |
| 233 | + |
221 | 234 | /* ---------- dropdown menu ---------- */ |
222 | 235 | .dropdown-menu { |
223 | 236 | background: var(--cp-panel); |
|
1023 | 1036 | <span id="navbar-heading" data-i18n="title"></span> |
1024 | 1037 | </a> |
1025 | 1038 | <div class="collapse navbar-collapse justify-content-end"> |
| 1039 | + <span class="navbar-text" id="batteryIndicator" data-visible="false"> |
| 1040 | + <i class="fas fa-battery-three-quarters" id="batteryIcon"></i><span id="batteryLevel"></span> |
| 1041 | + </span> |
1026 | 1042 | <ul class="navbar-nav"> |
1027 | 1043 | <li class="nav-item"> |
1028 | 1044 | <button class="btn dropdown-toggle border-0 text-white" id="menuToggle" |
@@ -3193,6 +3209,9 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5> |
3193 | 3209 | if ("ftpStatus" in socketMsg) { |
3194 | 3210 | updateFtpButton(socketMsg.ftpStatus.running); |
3195 | 3211 | } |
| 3212 | + if ("battery" in socketMsg) { |
| 3213 | + updateBatteryIndicator(socketMsg.battery); |
| 3214 | + } |
3196 | 3215 | if ("volume" in socketMsg) { |
3197 | 3216 | volumeSlider.setValue(parseInt(socketMsg.volume)); |
3198 | 3217 | } |
@@ -4260,6 +4279,33 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5> |
4260 | 4279 | } |
4261 | 4280 | return dDisplay + hDisplay + mDisplay; |
4262 | 4281 | } |
| 4282 | + var batteryLowWarned = false; |
| 4283 | + function updateBatteryIndicator(battery) { |
| 4284 | + const indicator = document.getElementById('batteryIndicator'); |
| 4285 | + const level = Math.round(battery.level); |
| 4286 | + let icon = 'fa-battery-empty'; |
| 4287 | + if (level >= 87) { |
| 4288 | + icon = 'fa-battery-full'; |
| 4289 | + } else if (level >= 62) { |
| 4290 | + icon = 'fa-battery-three-quarters'; |
| 4291 | + } else if (level >= 37) { |
| 4292 | + icon = 'fa-battery-half'; |
| 4293 | + } else if (level >= 12) { |
| 4294 | + icon = 'fa-battery-quarter'; |
| 4295 | + } |
| 4296 | + document.getElementById('batteryIcon').className = 'fas ' + icon; |
| 4297 | + document.getElementById('batteryLevel').textContent = level + '%'; |
| 4298 | + indicator.title = battery.voltage.toFixed(2) + ' V'; |
| 4299 | + indicator.classList.toggle('battery-low', battery.low === true); |
| 4300 | + indicator.setAttribute('data-visible', true); |
| 4301 | + if (battery.low && !batteryLowWarned) { |
| 4302 | + batteryLowWarned = true; |
| 4303 | + toaster.warning(i18next.t('toast.batteryLow', { level: level })); |
| 4304 | + } else if (!battery.low) { |
| 4305 | + batteryLowWarned = false; |
| 4306 | + } |
| 4307 | + } |
| 4308 | + |
4263 | 4309 | async function refreshSdCapacity() { |
4264 | 4310 | try { |
4265 | 4311 | const info = await (await fetch("http://" + host + "/info?section=sdcard")).json(); |
|
0 commit comments