Add Refresh Now button and configurable frame_host
- Trigger endpoint on frame Pi (port 8080) starts birdframe.service - Frame admin panel has a Refresh Now button at the top - frame_host config field lets user set the frame Pi's IP/hostname - Button uses frame_host from config (no hardcoded hostname) Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
@@ -216,6 +216,7 @@ switch ($action) {
|
||||
'quiet_end' => 6,
|
||||
'heal_hours' => 24,
|
||||
'timeout' => 45,
|
||||
'frame_host' => '',
|
||||
'basic_user' => '',
|
||||
'basic_pass' => '',
|
||||
];
|
||||
|
||||
+17
-2
@@ -2435,6 +2435,9 @@
|
||||
.then(function (fc) {
|
||||
adminBody.innerHTML =
|
||||
'<div class="admin-settings">'
|
||||
+ '<div class="menu-row" style="justify-content:center;padding:12px 0">'
|
||||
+ ' <button type="button" id="frameRefreshBtn" class="frame-refresh-btn">Refresh Now</button>'
|
||||
+ '</div>'
|
||||
+ '<div class="frame-section-label">Display</div>'
|
||||
+ frameSegmented('mode', 'Mode', 'how the time window works', fc.mode, [
|
||||
{ v: 'today', label: 'today' },
|
||||
@@ -2465,6 +2468,7 @@
|
||||
+ frameSlider('mat_opening_w', 'Mat width', 'matte opening width (inches, 0=default)', fc.mat_opening_w, 0, 12, 0.5, 1)
|
||||
+ frameSlider('mat_opening_h', 'Mat height', 'matte opening height (inches, 0=default)', fc.mat_opening_h, 0, 14, 0.5, 1)
|
||||
+ frameSlider('mat', 'Extra mat', 'global content shrink inside opening', fc.mat, 0, 0.1, 0.01, 2)
|
||||
+ frameInput('frame_host', 'Frame address', 'IP or hostname of the frame Pi', fc.frame_host || '')
|
||||
+ frameInput('panel', 'Panel driver', 'force driver (blank=auto)', fc.panel || '')
|
||||
+ frameSlider('timeout', 'Timeout', 'seconds to wait for page render', fc.timeout, 10, 120, 5, 0)
|
||||
+ '<div class="frame-section-label">Source</div>'
|
||||
@@ -2481,7 +2485,7 @@
|
||||
+ frameInput('basic_user', 'Username', 'basic auth username', fc.basic_user || '')
|
||||
+ frameInput('basic_pass', 'Password', 'basic auth password', fc.basic_pass || '', true)
|
||||
+ '</div>';
|
||||
wireFrameControls();
|
||||
wireFrameControls(fc);
|
||||
})
|
||||
.catch(function (err) {
|
||||
adminBody.innerHTML =
|
||||
@@ -2549,8 +2553,19 @@
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function wireFrameControls() {
|
||||
function wireFrameControls(fc) {
|
||||
var pending = {};
|
||||
var refreshBtn = document.getElementById('frameRefreshBtn');
|
||||
if (refreshBtn) {
|
||||
refreshBtn.addEventListener('click', function () {
|
||||
refreshBtn.textContent = 'Refreshing...';
|
||||
refreshBtn.disabled = true;
|
||||
fetch('http://' + (fc.frame_host || 'birdpic.local') + ':8080/refresh', { method: 'POST', mode: 'cors' })
|
||||
.then(function () { refreshBtn.textContent = 'Triggered'; })
|
||||
.catch(function () { refreshBtn.textContent = 'Failed (check LAN)'; })
|
||||
.finally(function () { setTimeout(function () { refreshBtn.textContent = 'Refresh Now'; refreshBtn.disabled = false; }, 3000); });
|
||||
});
|
||||
}
|
||||
adminBody.querySelectorAll('.switch[data-frame-key]').forEach(function (sw) {
|
||||
sw.addEventListener('click', function () {
|
||||
var on = sw.getAttribute('aria-checked') !== 'true';
|
||||
|
||||
@@ -1634,3 +1634,17 @@ body.av-local #dd-items { display: block; }
|
||||
}
|
||||
.frame-section-label:first-child { padding-top: 4px; }
|
||||
|
||||
|
||||
.frame-refresh-btn {
|
||||
font: 600 13px/1 var(--sans, ui-sans-serif, system-ui, sans-serif);
|
||||
padding: 10px 24px;
|
||||
border: 1px solid var(--ink-soft, #8a8078);
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--ink, #1a1612);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, opacity 0.15s;
|
||||
}
|
||||
.frame-refresh-btn:hover { background: rgba(26,22,18,0.05); }
|
||||
.frame-refresh-btn:disabled { opacity: 0.5; cursor: default; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user