76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { useState, useCallback, useEffect } from 'react';
|
|
import toast from '@/utils/toast';
|
|
import { FEATURED_STREAM, CHAT_MESSAGES } from './mockData';
|
|
import { liveService } from '@/services/liveService';
|
|
import type { LiveStream } from '@/types';
|
|
import type { LiveViewChatMessage } from './types';
|
|
|
|
export interface UseLiveViewOptions {
|
|
stream?: LiveStream | null;
|
|
streamId?: string | null;
|
|
chatMessages?: LiveViewChatMessage[];
|
|
onSendMessage?: (text: string) => void;
|
|
isLoading?: boolean;
|
|
error?: Error | null;
|
|
}
|
|
|
|
export function useLiveView(options: UseLiveViewOptions = {}) {
|
|
const [stream, setStream] = useState<LiveStream | null>(
|
|
options.stream ?? FEATURED_STREAM,
|
|
);
|
|
const [fetchLoading, setFetchLoading] = useState(false);
|
|
const [fetchError, setFetchError] = useState<Error | null>(null);
|
|
const chatMessages = options.chatMessages ?? CHAT_MESSAGES;
|
|
const [msgInput, setMsgInput] = useState('');
|
|
|
|
// When stream override is provided, use it (e.g. Storybook)
|
|
useEffect(() => {
|
|
if (options.stream !== undefined && options.stream !== null) {
|
|
setStream(options.stream);
|
|
setFetchLoading(false);
|
|
setFetchError(null);
|
|
return;
|
|
}
|
|
if (options.stream === null) {
|
|
setStream(FEATURED_STREAM);
|
|
return;
|
|
}
|
|
// Fetch from API: by streamId or list live streams
|
|
setFetchLoading(true);
|
|
setFetchError(null);
|
|
const promise = options.streamId
|
|
? liveService.getStream(options.streamId)
|
|
: liveService.listStreams(true).then((streams) => streams[0] ?? undefined);
|
|
promise
|
|
.then((s) => setStream(s ?? FEATURED_STREAM))
|
|
.catch((err) => {
|
|
setFetchError(err instanceof Error ? err : new Error(String(err)));
|
|
setStream(FEATURED_STREAM);
|
|
})
|
|
.finally(() => setFetchLoading(false));
|
|
}, [options.stream, options.streamId]);
|
|
|
|
const handleSend = useCallback(() => {
|
|
if (!msgInput.trim()) return;
|
|
if (options.onSendMessage) {
|
|
options.onSendMessage(msgInput);
|
|
} else {
|
|
toast.success('Message sent to chat');
|
|
}
|
|
setMsgInput('');
|
|
}, [msgInput, options.onSendMessage]);
|
|
|
|
const displayStream = stream ?? FEATURED_STREAM;
|
|
const isLoading = options.isLoading ?? fetchLoading;
|
|
const error = options.error ?? fetchError;
|
|
|
|
return {
|
|
stream: displayStream,
|
|
chatMessages,
|
|
msgInput,
|
|
setMsgInput,
|
|
handleSend,
|
|
isLoading,
|
|
error,
|
|
};
|
|
}
|