Add theatre-mode dialog for the frame header preview thumbnail
Clicking the small preview thumbnail now opens an enlarged version in a dialog (fresh render, same as the old click-to-refresh), closable via the X button or a backdrop click -- mirroring #widget-dialog's existing pattern.
This commit is contained in:
@@ -60,17 +60,51 @@
|
||||
|
||||
// Live "how it's displaying" thumbnail. A real composite render (same
|
||||
// pipeline /frame/image uses), not a cached snapshot, so it's on a slow
|
||||
// poll and also click-to-refresh rather than something tighter like the
|
||||
// 10s device-status poll -- no need to hit Immich/calendar/whiteboard
|
||||
// sources that often just for a header thumbnail.
|
||||
// poll rather than something tighter like the 10s device-status poll --
|
||||
// no need to hit Immich/calendar/whiteboard sources that often just for
|
||||
// a header thumbnail. Click enlarges it in a dialog (which also fetches
|
||||
// a fresh render); clicking the enlarged image refreshes it again.
|
||||
(function () {
|
||||
var thumb = document.getElementById('frame-preview-thumb');
|
||||
var dialog = document.getElementById('frame-preview-dialog');
|
||||
var bigImg = document.getElementById('frame-preview-dialog-img');
|
||||
var closeBtn = document.getElementById('frame-preview-dialog-close');
|
||||
if (!thumb || !window.FRAME_BASE_API) return;
|
||||
|
||||
function refresh() {
|
||||
thumb.src = `${window.FRAME_BASE_API}/preview?t=${Date.now()}`;
|
||||
function previewUrl() {
|
||||
return `${window.FRAME_BASE_API}/preview?t=${Date.now()}`;
|
||||
}
|
||||
function refreshThumb() {
|
||||
thumb.src = previewUrl();
|
||||
}
|
||||
// Opening the dialog (or clicking the big image inside it) fetches a
|
||||
// fresh render and keeps the header thumb in sync, so this single path
|
||||
// covers both "enlarge" and the old click-to-refresh behavior.
|
||||
function refreshBig() {
|
||||
var url = previewUrl();
|
||||
bigImg.src = url;
|
||||
thumb.src = url;
|
||||
}
|
||||
|
||||
thumb.addEventListener('click', function () {
|
||||
if (!dialog) { refreshThumb(); return; }
|
||||
refreshBig();
|
||||
dialog.showModal();
|
||||
});
|
||||
refreshThumb();
|
||||
setInterval(refreshThumb, 60000);
|
||||
|
||||
if (dialog && bigImg && closeBtn) {
|
||||
bigImg.addEventListener('click', refreshBig);
|
||||
closeBtn.addEventListener('click', function () { dialog.close(); });
|
||||
// Same backdrop-click-to-close trick as #widget-dialog: a click that
|
||||
// lands on the dialog element itself (not its content box) means the
|
||||
// backdrop was hit.
|
||||
dialog.addEventListener('click', function (e) {
|
||||
if (e.target !== dialog) return;
|
||||
var rect = dialog.getBoundingClientRect();
|
||||
var inside = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
|
||||
if (!inside) dialog.close();
|
||||
});
|
||||
}
|
||||
thumb.addEventListener('click', refresh);
|
||||
refresh();
|
||||
setInterval(refresh, 60000);
|
||||
})();
|
||||
|
||||
@@ -652,6 +652,36 @@ code {
|
||||
}
|
||||
.frame-preview-thumb:hover { opacity: 0.8; }
|
||||
|
||||
.frame-preview-dialog {
|
||||
position: fixed;
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 14px;
|
||||
background: var(--surface);
|
||||
box-shadow: var(--shadow-hover);
|
||||
line-height: 0; /* avoid a baseline gap under the image */
|
||||
}
|
||||
.frame-preview-dialog::backdrop { background: var(--overlay); }
|
||||
.frame-preview-dialog img {
|
||||
display: block;
|
||||
max-width: min(90vw, 900px);
|
||||
max-height: min(85vh, 900px);
|
||||
width: auto;
|
||||
height: auto;
|
||||
border-radius: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#frame-preview-dialog-close {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 18px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.control-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -7,5 +7,10 @@
|
||||
<button type="button" class="btn-inline" id="frame-name-save">Save</button>
|
||||
<button type="button" class="btn-inline secondary" id="frame-name-cancel">Cancel</button>
|
||||
</span>
|
||||
<img id="frame-preview-thumb" class="frame-preview-thumb" alt="Live preview of what the frame is displaying" title="What the frame is currently displaying -- click to refresh">
|
||||
<img id="frame-preview-thumb" class="frame-preview-thumb" alt="Live preview of what the frame is displaying" title="What the frame is currently displaying -- click to enlarge">
|
||||
|
||||
<dialog id="frame-preview-dialog" class="frame-preview-dialog">
|
||||
<button type="button" id="frame-preview-dialog-close" class="icon-btn" aria-label="Close" title="Close">×</button>
|
||||
<img id="frame-preview-dialog-img" alt="Live preview of what the frame is displaying" title="Click to refresh">
|
||||
</dialog>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user