Something went wrong. Try again.
experiments of a tiny cytube-like player with yt-dlp
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283import { createSignal, createEffect, onSettled } from "solid-js";import { connectWs } from "./ws";import type { RoomState, ChatMessage, ClientMessage } from "./types";
/** Auto-clear an error signal after `ms`, unless the `unless` predicate matches the error. */export function useAutoDismiss( [error, setError]: [() => string | null, (v: string | null) => void], opts: { ms?: number; unless?: (err: string) => boolean } = {},): void { createEffect( () => error(), (err) => { if (!err) return; if (opts.unless?.(err)) return; const timer = setTimeout(() => setError(null), opts.ms ?? 5000); return () => clearTimeout(timer); }, );}
/** Manage WebSocket connection lifecycle for a room. */export function useRoomConnection(roomId: string, userName: string) { const [state, setState] = createSignal<RoomState | null>(null); const [chats, setChats] = createSignal<ChatMessage[]>([]); const [connected, setConnected] = createSignal(false); const [error, setError] = createSignal<string | null>(null); const [sendFn, setSendFn] = createSignal<((msg: ClientMessage) => void) | null>(null); const initialLoad = { current: true };
const startConnecting = () => { if (sendFn()) return;
const send = connectWs(roomId, userName, { onState: (s) => { initialLoad.current = false; setState(s); }, onChat: (msg) => setChats((prev) => { const next = [...prev, msg]; return next.length > 200 ? next.slice(-200) : next; }), onDisconnect: () => { setConnected(false); setSendFn(null); }, onError: (reason) => { setError(reason); }, }); setSendFn(() => send); setConnected(true); setError(null); };
onSettled(() => { startConnecting(); setTimeout(() => { if (initialLoad.current) { setError("Room not found or unavailable"); } }, 8000); });
// Reconnect on disconnect with backoff. createEffect( () => [connected(), sendFn()], ([isConnected, send]) => { if (!isConnected && !send) { const timer = setTimeout(startConnecting, 3000); return () => clearTimeout(timer); } }, );
// Auto-dismiss transient errors, but not "not found". useAutoDismiss([error, setError], { unless: (err) => err.includes("not found") });
const send = (msg: ClientMessage) => sendFn()?.(msg);
return { state, chats, connected, error, setError, send };}