From f4a21e6974b025c4406a2682f9b0a387f63d54f4 Mon Sep 17 00:00:00 2001
From: Tot Maxim
Date: Mon, 11 May 2026 14:22:05 +0300
Subject: [PATCH] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?=
=?UTF-8?q?=D0=B5=D0=BD=20=D0=BB=D0=B0=D0=B3=20=D0=BB=D0=B5=D0=B9=D0=B0?=
=?UTF-8?q?=D1=83=D1=82=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
cmd/server/web/css/style.css | 49 ++++---------------
cmd/server/web/js/layout.js | 91 +++++++++++++-----------------------
2 files changed, 42 insertions(+), 98 deletions(-)
diff --git a/cmd/server/web/css/style.css b/cmd/server/web/css/style.css
index 06f0da8..5961092 100644
--- a/cmd/server/web/css/style.css
+++ b/cmd/server/web/css/style.css
@@ -218,7 +218,7 @@ h1 {
opacity: 0;
}
-/* ===== SPLIT LAYOUT ===== */
+/* ===== SPLIT LAYOUT (FIXED) ===== */
.layout {
display: flex;
height: calc(100vh - 60px);
@@ -227,44 +227,44 @@ h1 {
padding: 0;
}
+/* панели */
.panel {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
+/* LEFT */
.left {
- flex: 1 1 auto;
+ flex: 1;
min-width: 300px;
padding: 10px;
- transition: flex 0.3s ease;
}
+/* RIGHT */
.right {
flex: 0 0 40%;
min-width: 0;
background: black;
position: relative;
- transition: flex 0.3s ease, min-width 0.3s ease, opacity 0.3s ease;
overflow: hidden;
}
.right.hidden {
flex: 0 0 0 !important;
- min-width: 0 !important;
width: 0 !important;
+ min-width: 0 !important;
opacity: 0;
pointer-events: none;
}
-/* DRAG BAR */
+/* ===== RESIZER ===== */
.resizer {
width: 8px;
min-width: 8px;
cursor: col-resize;
background: #00ff88;
opacity: 0.3;
- transition: opacity 0.2s, width 0.3s ease, min-width 0.3s ease;
flex-shrink: 0;
z-index: 10;
}
@@ -273,10 +273,6 @@ h1 {
opacity: 0.8;
}
-.resizer:active {
- opacity: 1;
-}
-
.resizer.hidden {
width: 0 !important;
min-width: 0 !important;
@@ -284,24 +280,12 @@ h1 {
pointer-events: none;
}
-/* Когда камера скрыта, левая панель занимает всё пространство */
-.layout:has(.right.hidden) .left {
- flex: 1 1 100% !important;
-}
-
-/* ===== CAMERA ===== */
+/* камера */
.cam-modal {
height: 100%;
display: flex;
flex-direction: column;
background: black;
- opacity: 1;
- transition: opacity 0.2s ease;
-}
-
-.right.hidden .cam-modal {
- opacity: 0;
- transition: opacity 0.2s ease;
}
.cam-header {
@@ -319,19 +303,12 @@ h1 {
background: black;
}
-.cam-loading {
- display: flex;
- align-items: center;
- justify-content: center;
- color: #00ff88;
-}
-
-/* ===== CAMERA BUTTON ===== */
+/* кнопка камеры */
.cam-btn {
position: fixed;
top: 20px;
right: 20px;
- z-index: 1001;
+ z-index: 9999;
padding: 10px 15px;
background: rgba(0, 0, 0, 0.8);
color: #00ff88;
@@ -343,16 +320,10 @@ h1 {
display: flex;
align-items: center;
gap: 8px;
- transition: all 0.3s;
}
.cam-btn:hover {
background: rgba(0, 255, 136, 0.2);
- box-shadow: 0 0 15px rgba(0, 255, 136, 0.3);
-}
-
-.cam-btn-icon {
- font-size: 18px;
}
/* ===== MOBILE ===== */
diff --git a/cmd/server/web/js/layout.js b/cmd/server/web/js/layout.js
index 632c8df..7a1613f 100644
--- a/cmd/server/web/js/layout.js
+++ b/cmd/server/web/js/layout.js
@@ -1,51 +1,38 @@
//layout.js
let leftPanel, rightPanel, dragBar;
let isDragging = false;
+let pendingX = null;
export function initResize() {
leftPanel = document.getElementById("leftPanel");
rightPanel = document.getElementById("rightPanel");
dragBar = document.getElementById("dragBar");
- if (!leftPanel || !rightPanel || !dragBar) {
- console.warn("[layout] Элементы не найдены");
- return;
- }
+ if (!leftPanel || !rightPanel || !dragBar) return;
- console.log("[layout] Инициализация ресайза");
-
- // Загрузка сохранённых пропорций
const savedRatio = localStorage.getItem('layoutRatio');
if (savedRatio) {
- const ratio = parseFloat(savedRatio);
- applyRatio(ratio);
+ applyRatio(parseFloat(savedRatio));
}
dragBar.addEventListener("mousedown", (e) => {
if (rightPanel.classList.contains("hidden")) return;
-
- console.log("[layout] mousedown на resizer");
+
isDragging = true;
document.body.style.cursor = "col-resize";
- document.body.style.userSelect = "none";
e.preventDefault();
- e.stopPropagation();
});
document.addEventListener("mouseup", () => {
- if (isDragging) {
- console.log("[layout] mouseup - конец перетаскивания");
- isDragging = false;
- document.body.style.cursor = "default";
- document.body.style.userSelect = "";
-
- // Сохраняем пропорции только если камера открыта
- if (!rightPanel.classList.contains("hidden")) {
- const total = window.innerWidth;
- const leftWidth = leftPanel.getBoundingClientRect().width;
- const ratio = leftWidth / total;
- localStorage.setItem('layoutRatio', ratio.toString());
- }
+ if (!isDragging) return;
+
+ isDragging = false;
+ document.body.style.cursor = "default";
+
+ if (!rightPanel.classList.contains("hidden")) {
+ const total = window.innerWidth;
+ const leftWidth = leftPanel.getBoundingClientRect().width;
+ localStorage.setItem('layoutRatio', leftWidth / total);
}
});
@@ -53,58 +40,44 @@ export function initResize() {
if (!isDragging) return;
if (rightPanel.classList.contains("hidden")) return;
- const total = window.innerWidth;
- let leftWidth = e.clientX;
+ pendingX = e.clientX;
- const minWidth = 300;
- if (leftWidth < minWidth) leftWidth = minWidth;
- if (leftWidth > total - minWidth) leftWidth = total - minWidth;
+ requestAnimationFrame(() => {
+ if (pendingX === null) return;
- const rightWidth = total - leftWidth - dragBar.offsetWidth;
+ const total = window.innerWidth;
+ let leftWidth = pendingX;
- leftPanel.style.flex = `0 0 ${leftWidth}px`;
- leftPanel.style.width = `${leftWidth}px`;
- rightPanel.style.flex = `0 0 ${rightWidth}px`;
- rightPanel.style.width = `${rightWidth}px`;
- });
+ const min = 300;
+ if (leftWidth < min) leftWidth = min;
+ if (leftWidth > total - min) leftWidth = total - min;
- window.addEventListener("resize", () => {
- if (rightPanel.classList.contains("hidden")) return;
-
- const total = window.innerWidth;
- const leftWidth = leftPanel.getBoundingClientRect().width;
- const ratio = leftWidth / total;
- if (ratio > 0.2 && ratio < 0.8) {
- applyRatio(ratio);
- }
+ const rightWidth = total - leftWidth - dragBar.offsetWidth;
+
+ leftPanel.style.flex = `0 0 ${leftWidth}px`;
+ rightPanel.style.flex = `0 0 ${rightWidth}px`;
+
+ pendingX = null;
+ });
});
}
function applyRatio(ratio) {
const total = window.innerWidth;
const leftWidth = Math.floor(total * ratio);
- const rightWidth = total - leftWidth - dragBar.offsetWidth;
-
+ const rightWidth = total - leftWidth;
+
leftPanel.style.flex = `0 0 ${leftWidth}px`;
- leftPanel.style.width = `${leftWidth}px`;
rightPanel.style.flex = `0 0 ${rightWidth}px`;
- rightPanel.style.width = `${rightWidth}px`;
}
export function updateResizerVisibility() {
if (!dragBar || !rightPanel) return;
-
+
if (rightPanel.classList.contains("hidden")) {
dragBar.classList.add("hidden");
- // Сбрасываем инлайн-стили левой панели, чтобы CSS flex заработал
- leftPanel.style.flex = "";
- leftPanel.style.width = "";
+ leftPanel.style.flex = "1";
} else {
dragBar.classList.remove("hidden");
- // Восстанавливаем сохранённые пропорции
- const savedRatio = localStorage.getItem('layoutRatio');
- if (savedRatio) {
- applyRatio(parseFloat(savedRatio));
- }
}
}
\ No newline at end of file