Merge remote-tracking branch 'origin/sub_laptop_7' into main_laptop_1

This commit is contained in:
2026-10-17 00:06:22 +09:00
4 changed files with 31 additions and 2 deletions
@@ -23,6 +23,7 @@
* 초안(표준 횡단면 · 첫 계산 결과 · 되살린 노선 초안)은 걸음이 아니라 열 때 모습.
* 쉬는 동안 온 값(364-1) — 손길이 다 찍힌 뒤 새 손길이 닿기 전에 바뀐 칸(뒤에서 오는 파생 값 · 찍을 때만
* 옮겨 적는 관 자리)은 그 손길 직전에 지금 사진으로 덮음 — 판 열기 · 회전 같은 보기 손길이 걸음이 안 됨.
* 씨앗 값(364-1) — 비었을 때만 채우는 값(표준 횡단 · 횡단 보기 첫 열기)은 `seedPageHistory` 로 모든 사진에 넣음.
* ========================================================================== */
/** 조작값 스냅샷 대상 세션 키 접두어. B05·B06은 한 페이지라 함께 뜬다(CLAUDE.md 5장). */
@@ -90,6 +91,9 @@ let gestures = 0;
let active: ProfileHistory | null = null;
/** 마지막에 세운 사진첩의 「쉬는 동안 온 값 덮기」 — 손길이 닿을 때 부름(364-1). */
let rebaseActive: (() => void) | null = null;
let seedActive: ((key: string) => void) | null = null;
/** 비었던 칸을 채운 씨앗 값 — 그 칸이 없는 사진 전부에 넣음(걸음 아님 · 되돌려도 안 지움). */
export const seedPageHistory = (key: string | null): void => void (key && seedActive?.(key));
export const pageHistory = (): ProfileHistory | null => active;
export function setPageHistory(history: ProfileHistory): void {
active = history;
@@ -272,6 +276,10 @@ export function createProfileHistory(
sync();
stack[cursor] = takeSnapshot(stack[cursor]); // 쉬는 동안 온 값 = 지금 걸음의 모습
};
seedActive = (key) => {
const value = isDataKey(key) ? sessionStorage.getItem(key) : null;
if (value !== null) stack.forEach((snapshot) => void (snapshot[key] ??= value));
};
active = history;
return history;
}
+3 -1
View File
@@ -16,7 +16,8 @@
* 기존 호출 코드가 깨지지 않도록 여기서 그대로 다시 내보낸다.
* ========================================================================== */
import { clearState, readState, writeState } from "../A00_Common/b_page_state";
import { clearState, readState, stateKey, writeState } from "../A00_Common/b_page_state";
import { seedPageHistory } from "../B05_Profile/B05_Profile_UI_Profile_History";
import { API_BASE_URL, API_TIMEOUT_MS } from "@config/config_frontend";
import type {
CrossDesign,
@@ -102,6 +103,7 @@ function seedStandardCross(
const stored = context.stored_standard_cross_section;
if (stored && readState<unknown>("std-cross", projectId) === null) {
writeState("std-cross", stored, projectId);
seedPageHistory(stateKey("std-cross", projectId)); // 씨앗 — 되돌리기 걸음 아님(364-1)
}
return context;
}
@@ -21,9 +21,11 @@ import {
clearState,
readState,
readStateRaw,
stateKey,
writeState,
writeStateRaw,
} from "../A00_Common/b_page_state";
import { seedPageHistory } from "../B05_Profile/B05_Profile_UI_Profile_History";
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { createButton, createInputField, createSelectField } from "@ui/ui_template_elements";
import { buildStandardDiagram } from "./B06_Section_UI_Standard_Diagram";
@@ -385,6 +387,7 @@ export function createStandardPanel(
// 옛 저장분이 그룹마다 다른 공통값을 갖고 있으면 토사 기준으로 한 벌로 맞춘다.
unifyCommon(state);
persist();
if (!hadSession) seedPageHistory(stateKey("std-cross", projectId)); // 비었던 칸 채움 = 씨앗(364-1)
renderBody();
/** 소스 표준값을 현재 상태에 전부 덮어쓴다(사용자가 "적용"을 눌렀을 때만 호출). */
+17 -1
View File
@@ -31,7 +31,7 @@ globalThis.sessionStorage = {
};
globalThis.window = new EventTarget();
window.setTimeout = setTimeout;
const { createProfileHistory } = await import("./B05_Profile_UI_Profile_History.js");
const { createProfileHistory, seedPageHistory } = await import("./B05_Profile_UI_Profile_History.js");
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const fire = (type) => window.dispatchEvent(new Event(type));
/** 누르고 놓음 — 보기 손길(세션 안 씀) 또는 편집(누른 동안 write). */
@@ -111,6 +111,17 @@ await click(); // 칸 밖 누름
fire("change");
await wait(450);
out.typedKept = h3.canUndo();
// 씨앗 — 계획고 고친 뒤 [횡단 보기] 첫 열기가 비어 있던 표준 횡단을 채움(누른 사이) = 걸음 아님 · 되돌려도 남음
data.clear();
const h4 = createProfileHistory(() => {});
await click(() => sessionStorage.setItem(K.grade, "g1"));
await click(() => {
sessionStorage.setItem(K.std, "seed");
seedPageHistory(K.std);
});
out.seedSteps = [h4.undo(), h4.canUndo()];
out.seedKept = { std: sessionStorage.getItem(K.std), grade: sessionStorage.getItem(K.grade) };
writeFileSync(process.argv[2], JSON.stringify(out));
"""
@@ -154,6 +165,11 @@ def test_편집만_걸음_되돌리기는_그_편집만(result) -> None:
assert result["noMore"] is True
def test_씨앗_값은_걸음_아님_되돌려도_남음(result) -> None:
assert result["seedSteps"] == [True, False] # 계획고 한 걸음뿐
assert result["seedKept"] == {"std": "seed", "grade": None}
def test_앞_편집은_덮지_않음(result) -> None:
assert result["settleKept"] is True
assert result["typedKept"] is True