97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { sse } from "@/lib/realtime/sse";
|
|
import { startRealtimeRefresh } from "@/lib/realtime/realtime-refresh";
|
|
|
|
type FormRealtimeRefreshProps = {
|
|
topic: "forms" | "submissions";
|
|
formId?: string;
|
|
debounceMs?: number;
|
|
};
|
|
|
|
type UploadRealtimeRefreshProps = {
|
|
topic: "uploads";
|
|
debounceMs?: number;
|
|
};
|
|
|
|
type LeaderboardRealtimeRefreshProps =
|
|
| {
|
|
topic: "leaderboards";
|
|
leaderboard: "xp";
|
|
channelId?: never;
|
|
debounceMs?: number;
|
|
}
|
|
| {
|
|
topic: "leaderboards";
|
|
leaderboard: "vc";
|
|
channelId?: string;
|
|
debounceMs?: number;
|
|
}
|
|
| {
|
|
topic: "leaderboards";
|
|
leaderboard: "profile";
|
|
channelId?: never;
|
|
debounceMs?: number;
|
|
};
|
|
|
|
type RealtimeRefreshProps =
|
|
| FormRealtimeRefreshProps
|
|
| UploadRealtimeRefreshProps
|
|
| LeaderboardRealtimeRefreshProps;
|
|
|
|
export function RealtimeRefresh(props: RealtimeRefreshProps) {
|
|
const router = useRouter();
|
|
const topic = props.topic;
|
|
const formId = topic === "forms" || topic === "submissions" ? props.formId : undefined;
|
|
const leaderboard = topic === "leaderboards" ? props.leaderboard : undefined;
|
|
const channelId = topic === "leaderboards" ? props.channelId : undefined;
|
|
const debounceMs = props.debounceMs ?? (topic === "leaderboards" ? 500 : 150);
|
|
|
|
useEffect(() => {
|
|
const filter = topic === "leaderboards"
|
|
? leaderboard === "profile"
|
|
? { kind: "profile" as const }
|
|
: leaderboard === "xp"
|
|
? { kind: "xp" as const }
|
|
: { kind: "vc" as const, channelId }
|
|
: topic === "uploads"
|
|
? { kind: "uploads" as const }
|
|
: { kind: "form" as const, formId };
|
|
|
|
return startRealtimeRefresh({
|
|
filter,
|
|
debounceMs,
|
|
refresh: () => router.refresh(),
|
|
subscribe(emit) {
|
|
const options = { onopen: () => emit({ kind: "open" }) };
|
|
|
|
if (topic === "forms") {
|
|
return sse.forms.sub(
|
|
"update",
|
|
(event) => emit({ kind: "form", formId: event.formId }),
|
|
options,
|
|
);
|
|
}
|
|
if (topic === "submissions") {
|
|
return sse.submissions.sub(
|
|
"update",
|
|
(event) => emit({ kind: "form", formId: event.formId }),
|
|
options,
|
|
);
|
|
}
|
|
if (topic === "uploads") {
|
|
return sse.uploads.sub("update", () => emit({ kind: "upload" }), options);
|
|
}
|
|
return sse.leaderboards.subMany({
|
|
xp: () => emit({ kind: "xp" }),
|
|
vc: (event) => emit({ kind: "vc", channelId: event.channelId }),
|
|
}, options);
|
|
},
|
|
});
|
|
}, [channelId, debounceMs, formId, leaderboard, router, topic]);
|
|
|
|
return null;
|
|
}
|