/* ============================================================================= * B06_Section_Swap_Bus.ts * 상세 갈아끼움 알림판(PLAN 346-2) — 측점 수가 바뀌어 `Section_Store` 가 상세 객체를 갈아끼우면 여기로 알림. * 가져오는 것 없음 — 세션 조작값 맵(`_UI_Page_Link_Session`) · 암 경계 저장소(`_UI_Page_Persist`)가 모듈을 읽을 때 * 붙어도 `Section_Store` 와 돌고 도는 가져오기가 안 생김. * ========================================================================== */ import type { SectionDetailResponse } from "./B06_Section_Api_Types"; /** 새 상세 · 이어 받은 측점의 누가거리 옮김(옛 0.01 m 글 → 새 글 · 조작값 맵을 옮길 때). */ export type DetailListener = ( detail: SectionDetailResponse, moves: ReadonlyMap, ) => void; const anyListeners = new Set(); /** 어느 노선이든 상세가 갈아끼워지면 부름(조정창 값 · 암 경계 옮김 · 다시 그림) — 돌려준 함수로 끊음. */ export function onAnySwap(fn: DetailListener): () => void { anyListeners.add(fn); return () => anyListeners.delete(fn); } /** 알림 한 번 동안 조정창 맵이 옮긴 세션 칸(열쇠 글) — 뒤 차례(`afterAnySwap`)는 그 칸을 다시 안 옮김(415-3). */ const moved = new Set(); const afterListeners = new Set< ( detail: SectionDetailResponse, moves: ReadonlyMap, owned: ReadonlySet, ) => void >(); /** 조정창 맵이 세션 칸을 옮겼다고 적음(`_UI_Page_Link_Session`). */ export function markMovedStates(keys: Iterable): void { for (const key of keys) moved.add(key); } /** 갈아끼움 알림이 다 돈 뒤 부름 — `owned` = 그 사이 조정창 맵이 옮긴 세션 칸. */ export function afterAnySwap( fn: ( detail: SectionDetailResponse, moves: ReadonlyMap, owned: ReadonlySet, ) => void, ): () => void { afterListeners.add(fn); return () => afterListeners.delete(fn); } /** 갈아끼운 쪽(`Section_Store`)이 부름. */ export function emitSwap(detail: SectionDetailResponse, moves: ReadonlyMap): void { moved.clear(); anyListeners.forEach((fn) => fn(detail, moves)); const owned = new Set(moved); afterListeners.forEach((fn) => fn(detail, moves, owned)); }