Merge remote-tracking branch 'origin/sub_laptop_8' into main_laptop_1
This commit is contained in:
@@ -42,7 +42,7 @@ import {
|
||||
type EditedCurve,
|
||||
type EditedNode,
|
||||
} from "./logic/B05_Profile_UI_RouteEdit_Curve";
|
||||
import { drawRouteEditScene, polylineLengthM } from "./B05_Profile_UI_RouteEdit_Render";
|
||||
import { drawRouteEditScene, polylineLengthM, watchTheme } from "./B05_Profile_UI_RouteEdit_Render";
|
||||
import { bindNodeSplice, bindRouteEditNavigation } from "./B05_Profile_UI_RouteEdit_Input";
|
||||
import { bindRouteEditPointer } from "./B05_Profile_UI_RouteEdit_Pointer";
|
||||
import { createCrossPreview } from "./B05_Profile_UI_RouteEdit_Cross";
|
||||
@@ -271,6 +271,7 @@ export async function mountRouteEditor(
|
||||
viewMemory.flush();
|
||||
closed = true;
|
||||
sizeWatch.disconnect();
|
||||
themeWatch();
|
||||
historyControls.dispose(); // 단축키는 창(window)에 달려 있어 안 떼면 떠난 뒤에도 산다.
|
||||
curveLabelBox.destroy();
|
||||
overlay.remove();
|
||||
@@ -305,6 +306,7 @@ export async function mountRouteEditor(
|
||||
// 칸 크기를 따라감 — 창 크기 · 아래 종단 판 끌기 · 좌측 접기 모두(345-3).
|
||||
const sizeWatch = new ResizeObserver(() => resize());
|
||||
sizeWatch.observe(overlay.querySelector<HTMLElement>(".b05-routeedit__canvas-wrap")!);
|
||||
const themeWatch = watchTheme(() => draw()); // 밝음 · 어두움 바꿈 — 색 다시 읽어 그림(349).
|
||||
let viewWanted = false; // 자료를 읽었다 — 칸 크기가 서면 보던 화면(18 ③) · 없으면 노선 전체로.
|
||||
function openView(): void {
|
||||
if (!viewWanted || !meta || view.width <= 0) return;
|
||||
|
||||
@@ -131,6 +131,26 @@ function upright(
|
||||
context.restore();
|
||||
}
|
||||
|
||||
/** 테마 바꿈(`data-theme` · 시스템 밝음/어두움)마다 부름(349) — 그리기가 그릴 때마다 토큰을
|
||||
* 다시 읽으므로 다시 그리기만 하면 바탕 · 등고선 · 노선 · 발자국 색이 바뀜. 돌려준 함수로 뗌. */
|
||||
export function watchTheme(onChange: () => void): () => void {
|
||||
// 다음 프레임에 — 공용 색 캐시(`themeColor`)가 같은 알림에서 먼저 비워지게.
|
||||
let frame = 0;
|
||||
const later = (): void => {
|
||||
cancelAnimationFrame(frame);
|
||||
frame = requestAnimationFrame(onChange);
|
||||
};
|
||||
const observer = new MutationObserver(later);
|
||||
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
|
||||
const system = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
system.addEventListener("change", later);
|
||||
return () => {
|
||||
cancelAnimationFrame(frame);
|
||||
observer.disconnect();
|
||||
system.removeEventListener("change", later);
|
||||
};
|
||||
}
|
||||
|
||||
export function drawRouteEditScene(context: CanvasRenderingContext2D, scene: RouteEditScene): void {
|
||||
const { view, toScreen } = scene;
|
||||
const style = getComputedStyle(document.documentElement);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"""349 — 밝음 · 어두움을 바꾸면 노선 편집 평면 캔버스를 다시 그림(바탕 · 등고선 · 노선 · 발자국 색).
|
||||
|
||||
그리기는 그릴 때마다 테마 토큰을 다시 읽음 — 테마 바꿈 알림에 다시 그리기만 붙었는지 글로 봄.
|
||||
./venv/Scripts/python.exe -m pytest resources/tester/test_349_routeedit_theme_redraw.py -q
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
B05 = ROOT / "B05_Profile"
|
||||
RENDER = (B05 / "B05_Profile_UI_RouteEdit_Render.ts").read_text(encoding="utf-8")
|
||||
EDITOR = (B05 / "B05_Profile_UI_RouteEdit.ts").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _body(text: str, head: str) -> str:
|
||||
at = text.index(head)
|
||||
return text[at : text.index("\n}", at)]
|
||||
|
||||
|
||||
def test_테마_알림_받아_다음_프레임에_다시_그림() -> None:
|
||||
watch = _body(RENDER, "export function watchTheme(")
|
||||
assert 'attributeFilter: ["data-theme"]' in watch # 단추로 바꿈
|
||||
assert 'matchMedia("(prefers-color-scheme: dark)")' in watch # 시스템 바꿈
|
||||
# 공용 색 캐시가 먼저 비워지게 다음 프레임에 · 뗄 때 모두 뗌
|
||||
assert "requestAnimationFrame(onChange)" in watch
|
||||
assert "observer.disconnect();" in watch and 'removeEventListener("change", later)' in watch
|
||||
|
||||
|
||||
def test_편집기가_붙이고_떠날_때_뗌() -> None:
|
||||
assert "const themeWatch = watchTheme(() => draw());" in EDITOR
|
||||
dispose = _body(EDITOR, "const dispose = (): void => {")
|
||||
assert "themeWatch();" in dispose
|
||||
assert len(EDITOR.splitlines()) <= 700
|
||||
|
||||
|
||||
def test_그릴_때마다_토큰을_다시_읽음() -> None:
|
||||
scene = _body(RENDER, "export function drawRouteEditScene(")
|
||||
assert "const style = getComputedStyle(document.documentElement);" in scene
|
||||
assert 'style.getPropertyValue("--color-surface")' in scene # 바탕
|
||||
assert 'style.getPropertyValue("--map-contour-major")' in scene # 등고선
|
||||
assert 'style.getPropertyValue("--map-route")' in scene # 노선
|
||||
footprint = (B05 / "B05_Profile_UI_RouteEdit_Footprint.ts").read_text(encoding="utf-8")
|
||||
assert "context.strokeStyle = style.getPropertyValue(token).trim() || fallback;" in footprint
|
||||
Reference in New Issue
Block a user