live: double-click solos a cell to full screen (fullscreen mode)

Double-clicking a grid cell now maximizes that camera ("solo") via a CSS
class on the grid instead of putting the tile into the browser Fullscreen
API. In fullscreen the soloed camera fills the screen; double-clicking
again returns to the grid (staying fullscreen). From windowed mode the
gesture also enters fullscreen so the camera fills the screen. ESC exits
fullscreen natively; on exit the solo state is cleared.

VERSION -> 0.0.121.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 17:32:36 +05:00
parent 44f5aa920f
commit 650a531f21
3 changed files with 39 additions and 11 deletions
+1 -1
View File
@@ -1 +1 @@
0.0.120
0.0.121
+35 -10
View File
@@ -540,14 +540,9 @@ const Live = {
if (this._fsBound) return;
this._fsBound = true;
const onFs = () => {
// дать браузеру применить размеры, затем пересчитать canvas плееров
setTimeout(() => {
document.querySelectorAll(".hevc-player").forEach((b) => {
if (b._wc && typeof b._wc.resize === "function") { try { b._wc.resize(); } catch (e) { /**/ } }
if (b._hevc && typeof b._hevc.resize === "function") { try { b._hevc.resize(); } catch (e) { /**/ } }
});
window.dispatchEvent(new Event("resize"));
}, 120);
// выход из фуллскрина (в т.ч. по ESC) — снять «соло», вернуться к сетке
if (!(document.fullscreenElement || document.webkitFullscreenElement)) this.clearSolo();
this.resizePlayers();
};
document.addEventListener("fullscreenchange", onFs);
document.addEventListener("webkitfullscreenchange", onFs);
@@ -662,10 +657,10 @@ const Live = {
grid.className = "grid";
grid.style.gridTemplateColumns = `repeat(${this.dim}, 1fr)`;
grid.style.gridTemplateRows = `repeat(${this.dim}, 1fr)`;
grid.ondblclick = (e) => { // двойной клик по ячейке → fullscreen
grid.ondblclick = (e) => { // двойной клик по ячейке → «соло» (камера на весь экран)
if (e.target.closest(".tile-btn")) return;
const tile = e.target.closest(".tile");
if (tile) toggleFullscreen(tile);
if (tile) this.toggleSolo(tile);
};
grid.onclick = (e) => { // кнопка переключения на основной поток
const btn = e.target.closest(".tile-btn");
@@ -719,6 +714,36 @@ const Live = {
this.setTileMedia(tile, cam, useMain);
},
resizePlayers() { // пересчитать canvas плееров после смены размера ячейки
setTimeout(() => {
document.querySelectorAll(".hevc-player").forEach((b) => {
if (b._wc && typeof b._wc.resize === "function") { try { b._wc.resize(); } catch (e) { /**/ } }
if (b._hevc && typeof b._hevc.resize === "function") { try { b._hevc.resize(); } catch (e) { /**/ } }
});
window.dispatchEvent(new Event("resize"));
}, 120);
},
clearSolo() {
const grid = document.getElementById("grid");
if (!grid) return;
grid.classList.remove("solo");
grid.querySelectorAll(".tile.solo").forEach((t) => t.classList.remove("solo"));
},
toggleSolo(tile) { // одна камера на весь экран (внутри полноэкранного режима)
const grid = document.getElementById("grid");
const wasSolo = grid.classList.contains("solo") && tile.classList.contains("solo");
this.clearSolo();
if (!wasSolo) { // включить «соло» этой ячейки
grid.classList.add("solo");
tile.classList.add("solo");
// ещё не в полноэкранном — войти, чтобы камера заняла весь экран (выход — ESC)
if (!(document.fullscreenElement || document.webkitFullscreenElement)) toggleFullscreen(grid);
} // повторный двойной клик — назад к сетке (фуллскрин сохраняется)
this.resizePlayers();
},
updateDots() {
document.querySelectorAll(".tile .label[data-cam]").forEach((lbl) => {
const cam = this.cameras.find((c) => c.id === lbl.dataset.cam);
+3
View File
@@ -158,6 +158,9 @@ input[type="date"], input[type="number"], select {
background: #000; overflow: hidden;
grid-auto-rows: 1fr; grid-auto-columns: 1fr; /* все дорожки строго равны */
}
/* «Соло»: одна камера на весь экран (двойной клик по ячейке в полноэкранном режиме) */
.grid.solo { grid-template-columns: 1fr !important; grid-template-rows: 1fr !important; }
.grid.solo > .tile:not(.solo) { display: none; }
.tile {
position: relative; background: #05070a; border: 1px solid var(--border);
display: flex; align-items: center; justify-content: center; overflow: hidden;