59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
import {
|
|
useChatToolStore,
|
|
type ChatToolAction,
|
|
} from "@/store/chatToolStore";
|
|
|
|
/**
|
|
* Subscribe to chat tool actions and invoke `handler` for each new action.
|
|
*
|
|
* Usage (inside a component with map access):
|
|
* ```ts
|
|
* useChatToolActionHandler((action) => {
|
|
* switch (action.type) {
|
|
* case "locate_features": handleLocateFeatures(action.ids, action.layer, action.geometryKind); break;
|
|
* case "view_history": openHistoryPanel(action.featureInfos, action.dataType); break;
|
|
* case "view_scada": openScadaPanel(action.featureInfos); break;
|
|
* }
|
|
* });
|
|
* ```
|
|
*/
|
|
export function useChatToolActionHandler(
|
|
handler: (action: ChatToolAction) => void,
|
|
) {
|
|
const handlerRef = useRef(handler);
|
|
const lastHandledSeqRef = useRef(0);
|
|
|
|
useEffect(() => {
|
|
handlerRef.current = handler;
|
|
}, [handler]);
|
|
|
|
useEffect(() => {
|
|
const initialState = useChatToolStore.getState();
|
|
if (
|
|
initialState.lastAction &&
|
|
initialState.actionSeq > lastHandledSeqRef.current &&
|
|
Date.now() - initialState.lastActionAt < 5000
|
|
) {
|
|
lastHandledSeqRef.current = initialState.actionSeq;
|
|
handlerRef.current(initialState.lastAction);
|
|
} else {
|
|
lastHandledSeqRef.current = initialState.actionSeq;
|
|
}
|
|
|
|
const unsubscribe = useChatToolStore.subscribe(
|
|
(state, prevState) => {
|
|
if (
|
|
state.actionSeq !== prevState.actionSeq &&
|
|
state.lastAction &&
|
|
state.actionSeq > lastHandledSeqRef.current
|
|
) {
|
|
lastHandledSeqRef.current = state.actionSeq;
|
|
handlerRef.current(state.lastAction);
|
|
}
|
|
},
|
|
);
|
|
return unsubscribe;
|
|
}, []);
|
|
}
|