Files
GMW/services/frontend/src/hooks/use-voice.ts
T

79 lines
2.0 KiB
TypeScript
Raw Normal View History

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useCallback, useState } from "react";
import { voiceApi } from "@/lib/api";
import type { ActiveSpeaker, Channel, VoiceStatus } from "@/lib/types";
import type { WsHook } from "@/lib/ws-hook";
export function useVoiceStatus() {
return useQuery<VoiceStatus>({
queryKey: ["voice-status"],
queryFn: () => voiceApi.getStatus(),
retry: false,
});
}
export function useVoiceChannels(guildId: string) {
return useQuery<Channel[]>({
queryKey: ["voice-channels", guildId],
queryFn: () => voiceApi.getVoiceChannels(guildId),
enabled: !!guildId,
});
}
export function useSpeakers() {
const [speakers, setSpeakers] = useState<ActiveSpeaker[]>([]);
const subscribe = useCallback((ws: WsHook) => {
const unsub = ws.on("voice_active_user", (data) => {
const speaker = data as ActiveSpeaker;
setSpeakers((prev) => {
const idx = prev.findIndex((s) => s.userId === speaker.userId);
if (idx >= 0) {
const next = [...prev];
next[idx] = speaker;
return next;
}
return [...prev, speaker];
});
});
return () => {
unsub();
setSpeakers([]);
};
}, []);
return { speakers, subscribe };
}
export function useVoiceConnect() {
const qc = useQueryClient();
return useMutation({
mutationFn: ({
guildId,
channelId,
}: {
guildId: string;
channelId: string;
}) => voiceApi.connect(guildId, channelId),
onSuccess: () => qc.invalidateQueries({ queryKey: ["voice-status"] }),
});
}
export function useVoiceDisconnect() {
const qc = useQueryClient();
return useMutation({
mutationFn: () => voiceApi.disconnect(),
onSuccess: () => qc.invalidateQueries({ queryKey: ["voice-status"] }),
});
}
export function useMicTransmit() {
return useMutation({
mutationFn: (active: boolean) =>
voiceApi.sendCommand(
active ? "voice:transmit:start" : "voice:transmit:stop",
),
});
}