2026-07-26 16:55:20 +07:00
|
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
2026-07-26 16:14:32 +07:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
};
|
|
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
export function useMediaState() {
|
|
|
|
|
return useQuery<MediaState>({
|
|
|
|
|
queryKey: ["media-state"],
|
|
|
|
|
queryFn: () => voiceApi.getMediaStatus(),
|
|
|
|
|
retry: false,
|
|
|
|
|
refetchInterval: 10_000,
|
|
|
|
|
});
|
2026-07-26 16:14:32 +07:00
|
|
|
}
|
|
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
export function useMediaQueue() {
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: (url: string) => voiceApi.mediaQueue(url, "music"),
|
|
|
|
|
onSuccess: (data) => qc.setQueryData(["media-state"], data),
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
export function useMediaSkip() {
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: () => voiceApi.mediaSkip(),
|
|
|
|
|
onSuccess: (data) => qc.setQueryData(["media-state"], data),
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
export function useMediaStop() {
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: () => voiceApi.mediaStop(),
|
|
|
|
|
onSuccess: (data) => qc.setQueryData(["media-state"], data),
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
export function useMediaVolume() {
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: (volume: number) => voiceApi.mediaVolume(volume),
|
|
|
|
|
onSuccess: (data) => qc.setQueryData(["media-state"], data),
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
/** Subscribe to WS media_state events to keep cache fresh */
|
|
|
|
|
export function useMediaWsSync(ws: WsHook) {
|
|
|
|
|
const qc = useQueryClient();
|
|
|
|
|
useEffectFn(ws, qc);
|
|
|
|
|
}
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
import { useEffect } from "react";
|
2026-07-26 16:14:32 +07:00
|
|
|
|
2026-07-26 16:55:20 +07:00
|
|
|
function useEffectFn(ws: WsHook, qc: ReturnType<typeof useQueryClient>) {
|
2026-07-26 16:46:53 +07:00
|
|
|
useEffect(() => {
|
2026-07-26 16:55:20 +07:00
|
|
|
const unsub = ws.on("media_state", (data) => {
|
|
|
|
|
qc.setQueryData(["media-state"], data as MediaState);
|
|
|
|
|
});
|
|
|
|
|
return unsub;
|
|
|
|
|
}, [ws, qc]);
|
2026-07-26 16:14:32 +07:00
|
|
|
}
|