diff --git a/B05_Profile/B05_Profile_UI_Drainage_Live.ts b/B05_Profile/B05_Profile_UI_Drainage_Live.ts index e83a28ef8..0a92686af 100644 --- a/B05_Profile/B05_Profile_UI_Drainage_Live.ts +++ b/B05_Profile/B05_Profile_UI_Drainage_Live.ts @@ -42,7 +42,6 @@ import { } from "./logic/B05_Profile_Drainage_Live"; import type { DetailRunner } from "./B05_Profile_UI_Drainage_Run"; import { createDrainageSuggest, type DrainageSuggest } from "./B05_Profile_UI_Drainage_Suggest"; -import { pageHistory } from "./B05_Profile_UI_Profile_History"; const MODE_KEY = "drainage-mode"; @@ -53,7 +52,7 @@ export interface DrainageLiveDeps { basinList: HTMLElement; pipeRequest: () => DetailPipeInput[]; runner: DetailRunner; - /** [적용] · [자동 제안] 답이 화면에 오른 뒤 — 세션 초안에 담음. */ + /** [적용] · [자동 제안] 답이 화면에 오른 뒤 — 세션 초안에 담고 사진첩 한 걸음(패널이 콜백으로 이음). */ rememberPipes: () => void; /** 저장 배수유역 다시 받기(열 때와 같은 길 · 조용히) — 답을 화면에 올렸으면 true. */ loadSaved: () => Promise; @@ -117,7 +116,6 @@ export function createDrainageLive(deps: DrainageLiveDeps): DrainageLive { .then((ok) => { if (!ok) return; deps.rememberPipes(); - pageHistory()?.record(); }); }; const suggest = createDrainageSuggest(deps.pipeRequest, (points) => @@ -202,7 +200,6 @@ export function createDrainageLive(deps: DrainageLiveDeps): DrainageLive { if (applied) stale = false; if (applied && proposal) { deps.rememberPipes(); - pageHistory()?.record(); } paint(); }); diff --git a/B05_Profile/B05_Profile_UI_Drainage_Panel.ts b/B05_Profile/B05_Profile_UI_Drainage_Panel.ts index a559d0664..62e613a0f 100644 --- a/B05_Profile/B05_Profile_UI_Drainage_Panel.ts +++ b/B05_Profile/B05_Profile_UI_Drainage_Panel.ts @@ -34,7 +34,6 @@ import { snapStructureStation } from "../common_util/common_util_structure_stati import { createFacilityStore } from "./B05_Profile_UI_Drainage_Facility"; import { mergeFacilityOptions } from "./logic/B05_Profile_UI_Drainage_Facility_Merge"; import { readPendingPipes, writePendingPipes } from "./B05_Profile_Api_Pipes_Draft"; -import { pageReplaying } from "./B05_Profile_UI_Profile_History"; import { buildPipeReports } from "./B05_Profile_UI_Drainage_Report"; import { fillFordHeights, fordWaitsOf, waitsFordHeight } from "./B05_Profile_UI_Drainage_Ford_Fill"; import { createDrainageChrome } from "./B05_Profile_UI_Drainage_Chrome"; @@ -427,7 +426,7 @@ export function createDrainagePanel(callbacks: DrainagePanelCallbacks = {}): Dra basinList, pipeRequest, runner, - rememberPipes, + rememberPipes: () => (rememberPipes(), callbacks.onPipesDrafted?.()), // + 사진첩 한 걸음(369-4) loadSaved: () => run(loadSaved, true), // 초안 버림 = 저장분 조용히(349-0i) }); analyzeButton.addEventListener("click", () => void analyze()); @@ -593,8 +592,9 @@ export function createDrainagePanel(callbacks: DrainagePanelCallbacks = {}): Dra const next = reconcilePipes(pipeEditor.pipes(), chainages); if (!next) return; // 같은 목록 — 되돌아온 것이므로 여기서 끊는다 // 되돌리기 = 그 걸음 초안의 속성 · id · 초안 없는 걸음은 저장분(369) · 구조물 폼은 속성 데려감 - const pending = pageReplaying() ? readPendingPipes(projectId as string) : null; - if (pageReplaying() && !pending) return void run(loadSaved, true); + const replaying = callbacks.isReplaying?.() ?? false; // 종단쪽 약속(369-4) + const pending = replaying ? readPendingPipes(projectId as string) : null; + if (replaying && !pending) return void run(loadSaved, true); const draft = adoptDraftPipes(pending, next); const after = next.map((pipe) => pipe.chainage_m); if (draft) facilityStore.replaceFromResponse(draft); diff --git a/B05_Profile/B05_Profile_UI_Drainage_Panel_Types.ts b/B05_Profile/B05_Profile_UI_Drainage_Panel_Types.ts index 442b186c4..5a0586d03 100644 --- a/B05_Profile/B05_Profile_UI_Drainage_Panel_Types.ts +++ b/B05_Profile/B05_Profile_UI_Drainage_Panel_Types.ts @@ -90,4 +90,9 @@ export interface DrainagePanelCallbacks { /** 배수유역도 우클릭 빈 자리 메뉴 — 사이드 「구조물 배치」와 같은 구조물군 → 종류 * 2단 항목(2026-08-18 일원화). 선택 = 폼 자동 지정(addAt 경유). */ structureMenuItems?: (chainageM: number) => MapContextMenuItem[]; + /** [자동 제안] · 제안 [적용] 관 초안이 화면에 오른 뒤 — 되돌리기 사진첩 한 걸음(346-4 · 369-4). + * 판을 세우는 종단쪽이 넘김 — 판은 종단 패널을 안 가져옴(24-2e). */ + onPipesDrafted?: () => void; + /** 되돌리기 · 다시하기가 세션을 되쓰는 중인가 — 그때 관 목록은 그 걸음 초안(없으면 저장분)으로. */ + isReplaying?: () => boolean; } diff --git a/B05_Profile/B05_Profile_UI_Profile_SideTool.ts b/B05_Profile/B05_Profile_UI_Profile_SideTool.ts index 85e81c343..6b0965a5d 100644 --- a/B05_Profile/B05_Profile_UI_Profile_SideTool.ts +++ b/B05_Profile/B05_Profile_UI_Profile_SideTool.ts @@ -6,6 +6,12 @@ import type { DesignSideFactory } from "../A00_Common/design/design_profile"; import { createDrainageSide } from "./B05_Profile_UI_Drainage_Side"; +import { pageHistory, pageReplaying } from "./B05_Profile_UI_Profile_History"; -/** 오른쪽 판 — 두 보기가 같은 판을 쓴다. */ -export const drainageSide: DesignSideFactory = (host) => createDrainageSide(host); +/** 오른쪽 판 — 두 보기가 같은 판을 쓴다. 되돌리기 이음은 판 대신 여기서(369-4 · 판은 종단 패널을 안 가져옴). */ +export const drainageSide: DesignSideFactory = (host) => + createDrainageSide({ + ...host, + onPipesDrafted: () => pageHistory()?.record(), + isReplaying: pageReplaying, + }); diff --git a/resources/tester/helper_349_drainage_live_flow.cjs b/resources/tester/helper_349_drainage_live_flow.cjs index 5e7f6af17..9946d7eaa 100644 --- a/resources/tester/helper_349_drainage_live_flow.cjs +++ b/resources/tester/helper_349_drainage_live_flow.cjs @@ -105,7 +105,6 @@ const stubs = { currentLanguageIndex: 0, ui_locales: new Proxy({}, { get: (_target, key) => [key, key] }), }, - "./B05_Profile_UI_Profile_History": { pageHistory: () => ({ record: () => (records += 1) }) }, "../A00_Common/b_page_state": { readStateRaw: (key) => state.get(key) ?? null, writeStateRaw: (key, value) => state.set(key, value), @@ -181,7 +180,8 @@ async function main() { basinList: el("list"), pipeRequest: () => pipes, runner, - rememberPipes: () => (remembered += 1), + // 패널이 넘기는 꼴 그대로 — 초안에 담음 + 사진첩 한 걸음(369-4 · onPipesDrafted) + rememberPipes: () => ((remembered += 1), (records += 1)), // 저장분 다시 받기(349-0i) — 답은 시험이 정할 때 옴 loadSaved: () => { savedLoads += 1;