import * as React from "react"; import {useCallback, useContext, useEffect, useRef, useState} from "react"; import {ClientIconRenderer} from "tc-shared/ui/react-elements/Icons"; import {ClientIcon} from "svg-sprites/client-icons"; import {Registry} from "tc-shared/events"; import { ChannelVideoEvents, ChannelVideoInfo, ChannelVideoStreamState, kLocalVideoId, makeVideoAutoplay, VideoStreamState, VideoSubscribeInfo } from "tc-shared/ui/frames/video/Definitions"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import {LoadingDots} from "tc-shared/ui/react-elements/LoadingDots"; import {ClientTag} from "tc-shared/ui/tree/EntryTags"; import ResizeObserver from "resize-observer-polyfill"; import {LogCategory, logWarn} from "tc-shared/log"; import {spawnContextMenu} from "tc-shared/ui/ContextMenu"; import {VideoBroadcastType} from "tc-shared/connection/VideoConnection"; import {ErrorBoundary} from "tc-shared/ui/react-elements/ErrorBoundary"; import {useTr} from "tc-shared/ui/react-elements/Helper"; const SubscribeContext = React.createContext(undefined); const EventContext = React.createContext>(undefined); const HandlerIdContext = React.createContext(undefined); const cssStyle = require("./Renderer.scss"); const ExpendArrow = () => { const events = useContext(EventContext); const [ expended, setExpended ] = useState(() => { events.fire("query_expended"); return false; }); events.reactUse("notify_expended", event => setExpended(event.expended), undefined, [ setExpended ]); return (
events.fire("action_toggle_expended", { expended: !expended })}>
) }; const VideoInfo = React.memo((props: { videoId: string }) => { const events = useContext(EventContext); const handlerId = useContext(HandlerIdContext); const localVideo = props.videoId === kLocalVideoId; const nameClassList = cssStyle.name + " " + (localVideo ? cssStyle.local : ""); const [ info, setInfo ] = useState<"loading" | ChannelVideoInfo>(() => { events.fire("query_video_info", { videoId: props.videoId }); return "loading"; }); const [ statusIcon, setStatusIcon ] = useState(ClientIcon.PlayerOff); events.reactUse("notify_video_info", event => { if(event.videoId === props.videoId) { setInfo(event.info); setStatusIcon(event.info.statusIcon); } }); events.reactUse("notify_video_info_status", event => { if(event.videoId === props.videoId) { setStatusIcon(event.statusIcon); } }); let clientName; if(info === "loading") { clientName =
loading {props.videoId}
; } else { clientName = ; } return (
{clientName}
); }); const VideoStreamReplay = React.memo((props: { stream: MediaStream | undefined, className: string, streamType: VideoBroadcastType }) => { const refVideo = useRef(); useEffect(() => { let cancelAutoplay; const video = refVideo.current; if(props.stream) { video.style.opacity = "1"; video.srcObject = props.stream; video.muted = true; cancelAutoplay = makeVideoAutoplay(video); } else { video.style.opacity = "0"; } return () => { const video = refVideo.current; if(video) { video.onpause = undefined; video.onended = undefined; } if(cancelAutoplay) { cancelAutoplay(); } } }, [ props.stream ]); let title; if(props.streamType === "camera") { title = useTr("Camera"); } else { title = useTr("Screen"); } return (