From 3157cb965015a01aba586f49f2469edf8312c152 Mon Sep 17 00:00:00 2001 From: AlexsandrSnytkin Date: Fri, 18 Sep 2026 21:06:28 +0700 Subject: [PATCH] fix(ui): make block deletion reliable --- ui_server.py | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/ui_server.py b/ui_server.py index 46539fd..125b503 100644 --- a/ui_server.py +++ b/ui_server.py @@ -2318,6 +2318,13 @@ HTML = """ selectConfigBlock(configBlocks.find(candidate => !configBlockState(candidate)) || null); } function setConfigBlockState(block, state) { setConfigBlockStates([block], state); } + function deleteSelectedConfigBlocks() { + const items = [...selectedConfigBlocks].filter(block => configBlocks.includes(block) && !configBlockState(block)); + if (!items.length) return false; + setConfigBlockStates(items, 'deleted'); + setText('configLayoutState', `${items.length} блок${items.length === 1 ? '' : 'а'} перемещён${items.length === 1 ? '' : 'ы'} в корзину`); + return true; + } function focusConfigBlock(block, item, event) { if (!block || configBlockState(block)) return; if (event?.ctrlKey || event?.metaKey) { @@ -2675,17 +2682,24 @@ HTML = """ setTrashHover(moveEvent); updateConfigCanvasHeight(); }; + let finished = false; const end = endEvent => { + if (finished) return; + finished = true; block.releasePointerCapture?.(event.pointerId); block.removeEventListener('pointermove', move); block.removeEventListener('pointerup', end); block.removeEventListener('pointercancel', end); + window.removeEventListener('pointerup', end); + window.removeEventListener('pointercancel', end); group.forEach(item => item.classList.remove('is-dragging')); finishConfigDrag(block, endEvent, dragged, group); }; block.addEventListener('pointermove', move); block.addEventListener('pointerup', end, {once: true}); block.addEventListener('pointercancel', end, {once: true}); + window.addEventListener('pointerup', end); + window.addEventListener('pointercancel', end); } function resetConfigLayout() { const custom = {}; @@ -3029,6 +3043,13 @@ HTML = """ selectNetworkBlock(networkBlocks.find(candidate => !networkState(candidate)) || null); } function setNetworkBlockState(block, state) { setNetworkBlockStates([block], state); } + function deleteSelectedNetworkBlocks() { + const items = [...selectedNetworkBlocks].filter(block => networkBlocks.includes(block) && !networkState(block)); + if (!items.length) return false; + setNetworkBlockStates(items, 'deleted'); + setText('networkLayoutState', `${items.length} блок${items.length === 1 ? '' : 'а'} перемещён${items.length === 1 ? '' : 'ы'} в корзину`); + return true; + } function createNetworkBlock(templateKey, title, existingKey = '') { const template = networkBlocks.find(block => block.dataset.custom !== 'true' && block.dataset.section === templateKey); if (!template || !networkCanvas) return null; @@ -3145,17 +3166,24 @@ HTML = """ if (trash) trash.classList.toggle('is-over', networkTrashDrop(moveEvent)); updateNetworkCanvasHeight(); }; + let finished = false; const end = endEvent => { + if (finished) return; + finished = true; block.releasePointerCapture?.(event.pointerId); block.removeEventListener('pointermove', move); block.removeEventListener('pointerup', end); block.removeEventListener('pointercancel', end); + window.removeEventListener('pointerup', end); + window.removeEventListener('pointercancel', end); group.forEach(item => item.classList.remove('is-dragging')); finishNetworkDrag(block, endEvent, dragged, group); }; block.addEventListener('pointermove', move); block.addEventListener('pointerup', end, {once: true}); block.addEventListener('pointercancel', end, {once: true}); + window.addEventListener('pointerup', end); + window.addEventListener('pointercancel', end); } function makeNetworkBlockInteractive(block) { if (!block || block._networkInteractive) return; @@ -4396,10 +4424,19 @@ HTML = """ if (e.target === $('playerOverlay')) closePlayer(); }); document.addEventListener('keydown', e => { - if (e.key !== 'Escape') return; - if (!$('playerOverlay').hidden) closePlayer(); - else if (!$('logDrawer').hidden) setLogsOpen(false); - else if (!$('appearancePanel').hidden) setAppearanceOpen(false); + if (e.key === 'Escape') { + if (!$('playerOverlay').hidden) closePlayer(); + else if (!$('logDrawer').hidden) setLogsOpen(false); + else if (!$('appearancePanel').hidden) setAppearanceOpen(false); + return; + } + if (e.key !== 'Delete' && e.key !== 'Backspace') return; + const target = e.target; + if (target instanceof Element && target.closest('input, select, textarea, button, [contenteditable="true"]')) return; + const settingsVisible = !$('settingsTab')?.hidden; + const networkVisible = !$('modelTab')?.hidden; + const removed = settingsVisible ? deleteSelectedConfigBlocks() : networkVisible ? deleteSelectedNetworkBlocks() : false; + if (removed) e.preventDefault(); }); $('logsToggle').addEventListener('click', () => setLogsOpen($('logDrawer').hidden)); $('logsClose').addEventListener('click', () => setLogsOpen(false));