fix(498-1 메모리): 평면 편집 키 듣개 둘을 캔버스 수명에 묶음 — 요구 298-3
- B05_Profile_UI_RouteEdit_StructureMarks · B05_Profile_UI_RouteEdit_Keys 의 창 keydown · keyup · blur 듣개를 listenWhileAlive 로 · 다음 키 누름 때만 떨어지던 detach 걷음 - 시험: test_298_3_page_dispose 두 칸 더함 · test_383_2 · helper_399 가 @ui 듣기 틀을 읽음 - 확인: 키 누름 없이 [저장] 다섯 번 GC 뒤 힙 39 → 123 → 205 → 205 → 206 → 206 MB(둘째부터 평탄) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
* 일은 끌기(`_Pointer`)와 같음. 걸음 · 결과 한 줄 셈은 `logic/B05_Profile_RouteEdit_KeyNudge`.
|
||||
* ========================================================================== */
|
||||
|
||||
import { listenWhileAlive } from "@ui/ui_template_window_watch";
|
||||
import { lastPointerWithin } from "../B06_Section/B06_Section_UI_Cross_Panel_Base";
|
||||
import { HOLD_DELAY_MS, HOLD_INTERVAL_MS } from "./B05_Profile_UI_Profile_Edit";
|
||||
import type { RouteEditPointerParams } from "./B05_Profile_UI_RouteEdit_Pointer";
|
||||
@@ -109,14 +110,8 @@ export function bindRouteEditKeys(params: RouteEditPointerParams, dragging: () =
|
||||
params.draw();
|
||||
}
|
||||
|
||||
const detach = (): void => {
|
||||
window.removeEventListener("keydown", onKeyDown, true);
|
||||
window.removeEventListener("keyup", onKeyUp, true);
|
||||
window.removeEventListener("blur", release);
|
||||
};
|
||||
|
||||
function onKeyDown(event: KeyboardEvent): void {
|
||||
if (!canvas.isConnected) return detach();
|
||||
if (!canvas.isConnected) return;
|
||||
if (!isArrowKey(event.key) || !lastPointerWithin(".b05-routeedit")) return; // B06 겹침 평면도 같음(436)
|
||||
const target = event.target as HTMLElement | null;
|
||||
if (target?.closest?.("input, select, textarea, [contenteditable='true']")) return;
|
||||
@@ -147,14 +142,15 @@ export function bindRouteEditKeys(params: RouteEditPointerParams, dragging: () =
|
||||
}
|
||||
|
||||
function onKeyUp(event: KeyboardEvent): void {
|
||||
if (!canvas.isConnected) return detach();
|
||||
if (!canvas.isConnected) return;
|
||||
if (!hold || event.key !== hold.key) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
release();
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", onKeyDown, true);
|
||||
window.addEventListener("keyup", onKeyUp, true);
|
||||
window.addEventListener("blur", release);
|
||||
// 창 듣기는 캔버스 수명에 묶음 — 다시 세운 옛 페이지를 안 붙듦(298-3)
|
||||
listenWhileAlive(window, "keydown", canvas, onKeyDown, true);
|
||||
listenWhileAlive(window, "keyup", canvas, onKeyUp, true);
|
||||
listenWhileAlive(window, "blur", canvas, release);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* ========================================================================== */
|
||||
|
||||
import { pickPx } from "../A00_Common/touch_bridge";
|
||||
import { listenWhileAlive } from "@ui/ui_template_window_watch";
|
||||
import { draftProjectId } from "../A00_Common/design/design_store";
|
||||
import {
|
||||
NO_SELECTION,
|
||||
@@ -365,13 +366,8 @@ export function bindStructureMarks(
|
||||
holdKey = null;
|
||||
finish();
|
||||
};
|
||||
const detach = (): void => {
|
||||
window.removeEventListener("keydown", onKeyDown, true);
|
||||
window.removeEventListener("keyup", onKeyUp, true);
|
||||
window.removeEventListener("blur", release);
|
||||
};
|
||||
function onKeyDown(event: KeyboardEvent): void {
|
||||
if (!canvas.isConnected) return detach();
|
||||
if (!canvas.isConnected) return;
|
||||
const escape = event.key === "Escape";
|
||||
if ((!escape && !isArrowKey(event.key)) || !lastPointerWithin(".b05-routeedit")) return;
|
||||
const target = event.target as HTMLElement | null;
|
||||
@@ -392,12 +388,13 @@ export function bindStructureMarks(
|
||||
}, HOLD_DELAY_MS);
|
||||
}
|
||||
function onKeyUp(event: KeyboardEvent): void {
|
||||
if (!canvas.isConnected) return detach();
|
||||
if (!canvas.isConnected) return;
|
||||
if (event.key === holdKey) release();
|
||||
}
|
||||
window.addEventListener("keydown", onKeyDown, true);
|
||||
window.addEventListener("keyup", onKeyUp, true);
|
||||
window.addEventListener("blur", release);
|
||||
// 창 듣기는 캔버스 수명에 묶음 — 다시 세운 옛 페이지를 안 붙듦(298-3)
|
||||
listenWhileAlive(window, "keydown", canvas, onKeyDown, true);
|
||||
listenWhileAlive(window, "keyup", canvas, onKeyUp, true);
|
||||
listenWhileAlive(window, "blur", canvas, release);
|
||||
|
||||
return {
|
||||
press(px, py) {
|
||||
|
||||
@@ -104,6 +104,8 @@ function loadTs(full) {
|
||||
cache.set(full, box.exports);
|
||||
const localRequire = (request) => {
|
||||
if (STUBS[request]) return STUBS[request];
|
||||
if (request.startsWith("@ui/"))
|
||||
return loadTs(path.join(B05, "..", "ui_template", `${request.slice(4)}.ts`));
|
||||
if (request.startsWith(".")) return loadTs(path.join(path.dirname(full), `${request}.ts`));
|
||||
return require(request);
|
||||
};
|
||||
|
||||
@@ -53,6 +53,8 @@ def test_옛_페이지_풀림_지금_페이지는_들음(out) -> None:
|
||||
"scroll|resize",
|
||||
), # 끌기 동안 pointer 듣기는 끝에 뗌
|
||||
("B05_Profile/B05_Profile_UI_Panel_Settings.ts", "pointerup|keyup"),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_StructureMarks.ts", "keydown|keyup|blur"),
|
||||
("B05_Profile/B05_Profile_UI_RouteEdit_Keys.ts", "keydown|keyup|blur"),
|
||||
],
|
||||
)
|
||||
def test_전역_듣기는_노드_수명으로만(rel: str, types: str) -> None:
|
||||
|
||||
@@ -63,7 +63,9 @@ def test_이음_끌기_걸기_한_줄_창_가로채기() -> None:
|
||||
pointer = _read("B05_Profile_UI_RouteEdit_Pointer.ts")
|
||||
assert pointer.count("bindRouteEditKeys(") == 1
|
||||
keys = _read("B05_Profile_UI_RouteEdit_Keys.ts")
|
||||
assert 'window.addEventListener("keydown", onKeyDown, true)' in keys # 앞서 받음(capture)
|
||||
assert (
|
||||
'listenWhileAlive(window, "keydown", canvas, onKeyDown, true)' in keys
|
||||
) # 앞서 받음(capture)
|
||||
# 마지막 누름이 평면 안 — B06 겹침 평면도 같음(436)
|
||||
assert 'lastPointerWithin(".b05-routeedit")' in keys
|
||||
assert "event.preventDefault();\n event.stopPropagation();" in keys
|
||||
|
||||
Reference in New Issue
Block a user