Files
DndGamePlayer/app/renderer/shared/playerToken/useNpcMapSpawnDrag.ts
T
2026-08-18 14:42:06 +08:00

57 lines
1.6 KiB
TypeScript

import { useEffect, useMemo, useState } from 'react';
import { ipcChannels } from '../../../shared/ipc/contracts';
import type { NpcMapSpawnDragState } from '../../../shared/types';
import { asNpcId } from '../../../shared/types/ids';
import { getDndApi } from '../dndApi';
const EMPTY: NpcMapSpawnDragState = {
dragging: false,
npcId: null,
hoverNx: null,
hoverNy: null,
};
export function useNpcMapSpawnDrag(): [
NpcMapSpawnDragState,
{
beginDrag: (npcId: string) => Promise<void>;
setHover: (nx: number | null, ny: number | null) => Promise<void>;
commit: () => Promise<boolean>;
cancel: () => Promise<void>;
},
] {
const api = getDndApi();
const [state, setState] = useState<NpcMapSpawnDragState>(EMPTY);
useEffect(() => {
void api.invoke(ipcChannels.npcMapSpawn.getState, {}).then(({ state: s }) => {
setState(s);
});
return api.on(ipcChannels.npcMapSpawn.stateChanged, ({ state: s }) => {
setState(s);
});
}, [api]);
const apiWrap = useMemo(
() => ({
beginDrag: async (npcId: string) => {
await api.invoke(ipcChannels.npcMapSpawn.beginDrag, { npcId: asNpcId(npcId) });
},
setHover: async (nx: number | null, ny: number | null) => {
await api.invoke(ipcChannels.npcMapSpawn.setHover, { nx, ny });
},
commit: async () => {
const res = await api.invoke(ipcChannels.npcMapSpawn.commit, {});
return Boolean(res.spawned);
},
cancel: async () => {
await api.invoke(ipcChannels.npcMapSpawn.cancel, {});
},
}),
[api],
);
return [state, apiWrap];
}