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

71 lines
1.8 KiB
TypeScript
Raw Normal View History

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { voiceApi } from "@/lib/api";
import type { MediaState } from "@/lib/types";
import type { WsEventType } from "@/lib/ws/types";
type WsHook = {
on: <E extends WsEventType>(
eventType: E,
handler: (data: unknown) => void,
) => () => void;
};
export function useMediaState() {
return useQuery<MediaState>({
queryKey: ["media-state"],
queryFn: () => voiceApi.getMediaStatus(),
retry: false,
refetchInterval: 10_000,
});
}
export function useMediaQueue() {
const qc = useQueryClient();
return useMutation({
mutationFn: (url: string) => voiceApi.mediaQueue(url, "music"),
onSuccess: (data) => qc.setQueryData(["media-state"], data),
});
}
export function useMediaSkip() {
const qc = useQueryClient();
return useMutation({
mutationFn: () => voiceApi.mediaSkip(),
onSuccess: (data) => qc.setQueryData(["media-state"], data),
});
}
export function useMediaStop() {
const qc = useQueryClient();
return useMutation({
mutationFn: () => voiceApi.mediaStop(),
onSuccess: (data) => qc.setQueryData(["media-state"], data),
});
}
export function useMediaVolume() {
const qc = useQueryClient();
return useMutation({
mutationFn: (volume: number) => voiceApi.mediaVolume(volume),
onSuccess: (data) => qc.setQueryData(["media-state"], data),
});
}
/** Subscribe to WS media_state events to keep cache fresh */
export function useMediaWsSync(ws: WsHook) {
const qc = useQueryClient();
useEffectFn(ws, qc);
}
import { useEffect } from "react";
function useEffectFn(ws: WsHook, qc: ReturnType<typeof useQueryClient>) {
useEffect(() => {
const unsub = ws.on("media_state", (data) => {
qc.setQueryData(["media-state"], data as MediaState);
});
return unsub;
}, [ws, qc]);
}