140 lines
4.8 KiB
TypeScript
140 lines
4.8 KiB
TypeScript
"use client";
|
|
import { fitMapSelection, mapSearchNavigationOptions } from "@/features/map-search/lib/map-navigation";
|
|
|
|
import type { useFloodPredictionMap } from "@/features/fldng-predc-prst/lib/use-flood-prediction-map";
|
|
import {
|
|
useEffect,
|
|
type MutableRefObject,
|
|
type Dispatch,
|
|
type SetStateAction,
|
|
} from "react";
|
|
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
|
import { WINDOW_POPUP_MESSAGE_TYPE } from "@/features/window-popup/model/types";
|
|
|
|
type MapRuntimeBridgeOptions = {
|
|
/** 공통 Gis가 생성한 지도 참조. 생성/파괴 소유권은 Gis에 유지한다. */
|
|
gisMaps: MutableRefObject<any>;
|
|
setMapReady: Dispatch<SetStateAction<boolean>>;
|
|
handleFloodPredictionPopupSelection: ReturnType<
|
|
typeof useFloodPredictionMap
|
|
>["handleFloodPredictionPopupSelection"];
|
|
};
|
|
|
|
/** 지도 준비 감지와 정보검색/GIS 업로드 메시지 연결을 소유한다.
|
|
* 기존 300ms 준비 polling 및 callback 변경 시 구독 갱신/정리 순서를 보존한다.
|
|
* 지도 객체 자체를 별도로 만들거나 전역 store에 저장하지 않는다.
|
|
*/
|
|
export function useMapRuntimeBridge({
|
|
gisMaps,
|
|
setMapReady,
|
|
handleFloodPredictionPopupSelection,
|
|
}: MapRuntimeBridgeOptions) {
|
|
useEffect(() => {
|
|
const timer = window.setInterval(() => {
|
|
if (gisMaps.current) {
|
|
setMapReady(true);
|
|
window.clearInterval(timer);
|
|
}
|
|
}, 300);
|
|
|
|
const handlePopupMessage = async (event: MessageEvent) => {
|
|
if (event.origin !== window.location.origin) return;
|
|
|
|
const data = event.data;
|
|
const core = GisApp.Module.layer as any;
|
|
|
|
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SELECT_FEATURE) {
|
|
const layerNm = data.payload?.layerNm;
|
|
const fid = data.payload?.fid;
|
|
if (!layerNm || !fid || !core?.showSearchResultsFromGeoJSON) return;
|
|
|
|
await core.showSearchResultsFromGeoJSON(layerNm, fid, mapSearchNavigationOptions(gisMaps.current));
|
|
return;
|
|
}
|
|
|
|
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_MULTIPLE) {
|
|
const layerNm = data.payload?.layerNm;
|
|
const fidsRaw = data.payload?.fids;
|
|
if (!layerNm || !fidsRaw || !core?.showMultipleSearchResultsFromGeoJSON)
|
|
return;
|
|
|
|
let fids: string[] = [];
|
|
try {
|
|
fids = JSON.parse(fidsRaw);
|
|
} catch (error) {
|
|
console.error("다중 시설 메시지 파싱 실패:", error);
|
|
return;
|
|
}
|
|
|
|
await core.showMultipleSearchResultsFromGeoJSON(layerNm, fids, mapSearchNavigationOptions(gisMaps.current));
|
|
return;
|
|
}
|
|
|
|
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_FIT_EXTENT) {
|
|
const extent = Array.isArray(data.payload?.extent)
|
|
? data.payload.extent.map(Number)
|
|
: [];
|
|
const map = gisMaps.current;
|
|
if (
|
|
extent.length !== 4 ||
|
|
extent.some((value: number) => !Number.isFinite(value)) ||
|
|
!map?.getView
|
|
) {
|
|
return;
|
|
}
|
|
fitMapSelection(map, extent, {
|
|
duration: 300,
|
|
padding: [50, 50, 50, 50],
|
|
maxZoom: 16,
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (
|
|
data?.type === WINDOW_POPUP_MESSAGE_TYPE.MAP_SEARCH_SHOW_FLOOD_GROUP
|
|
) {
|
|
await handleFloodPredictionPopupSelection(data.payload, {
|
|
source: event.source as Window | null,
|
|
origin: event.origin,
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.GIS_UPLOAD_COMPLETED) {
|
|
const rawLayerTypeNames = data.payload?.refreshLayerTypeNames;
|
|
let layerTypeNames = ["tb_ms_swage_ppl"];
|
|
if (rawLayerTypeNames) {
|
|
try {
|
|
const parsed = JSON.parse(rawLayerTypeNames);
|
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
layerTypeNames = parsed
|
|
.map((item) => String(item ?? "").trim())
|
|
.filter(Boolean);
|
|
}
|
|
} catch (error) {
|
|
console.error("GIS 업로드 레이어 refresh 메시지 파싱 실패:", error);
|
|
}
|
|
}
|
|
|
|
const refreshTargetNames = new Set(layerTypeNames);
|
|
gisMaps.current?.getAllLayers?.().forEach((layer: any) => {
|
|
const layerTypeName = String(layer?.get?.("lyrTyNm") ?? "").trim();
|
|
if (!refreshTargetNames.has(layerTypeName)) return;
|
|
|
|
const source = layer.getSource?.();
|
|
source?.updateParams?.({ _t: Date.now() });
|
|
source?.refresh?.();
|
|
source?.changed?.();
|
|
layer.changed?.();
|
|
});
|
|
}
|
|
};
|
|
|
|
window.addEventListener("message", handlePopupMessage);
|
|
return () => {
|
|
window.clearInterval(timer);
|
|
window.removeEventListener("message", handlePopupMessage);
|
|
};
|
|
}, [gisMaps, setMapReady, handleFloodPredictionPopupSelection]);
|
|
}
|