TeaWeb/shared/js/ui/AppRenderer.tsx

141 lines
No EOL
5.7 KiB
TypeScript

import * as React from "react";
import {ControlBar2} from "tc-shared/ui/frames/control-bar/Renderer";
import {Registry} from "tc-shared/events";
import {ControlBarEvents} from "tc-shared/ui/frames/control-bar/Definitions";
import {ConnectionListUIEvents} from "tc-shared/ui/frames/connection-handler-list/Definitions";
import {ConnectionHandlerList} from "tc-shared/ui/frames/connection-handler-list/Renderer";
import {ErrorBoundary} from "tc-shared/ui/react-elements/ErrorBoundary";
import {ContextDivider} from "tc-shared/ui/react-elements/ContextDivider";
import {SideBarRenderer} from "tc-shared/ui/frames/SideBarRenderer";
import {SideBarEvents} from "tc-shared/ui/frames/SideBarDefinitions";
import {SideHeaderEvents} from "tc-shared/ui/frames/side/HeaderDefinitions";
import {ServerLogFrame} from "tc-shared/ui/frames/log/Renderer";
import {ServerEventLogUiEvents} from "tc-shared/ui/frames/log/Definitions";
import {FooterRenderer} from "tc-shared/ui/frames/footer/Renderer";
import {HostBanner} from "tc-shared/ui/frames/HostBannerRenderer";
import {HostBannerUiEvents} from "tc-shared/ui/frames/HostBannerDefinitions";
import {AppUiEvents} from "tc-shared/ui/AppDefinitions";
import {useEffect, useState} from "react";
import {ChannelTreeRenderer} from "tc-shared/ui/tree/Renderer";
import {ChannelTreeUIEvents} from "tc-shared/ui/tree/Definitions";
const cssStyle = require("./AppRenderer.scss");
/*
<div class="app-container">
<div class="app">
<!-- navigation bar -->
<div class="container-control-bar">
<div id="control_bar" class="control_bar">
</div>
</div>
<div class="container-connection-handlers" id="connection-handler-list"></div>
<div class="container-app-main">
<div class="container-channel-video" id="channel-video"></div>
<div class="container-channel-chat">
<!-- Channel tree -->
<div class="container-channel-tree">
<div class="hostbanner" id="hostbanner"></div>
<div class="channel-tree" id="channelTree"></div>
</div>
<div class="container-seperator vertical" seperator-id="seperator-channel-chat"></div>
<!-- Chat window -->
<div class="container-chat" id="chat"></div>
</div>
<div class="container-seperator horizontal" seperator-id="seperator-main-log"></div>
<div class="container-bottom">
<div class="container-server-log" id="server-log"></div>
<div class="container-footer" id="container-footer">
</div>
</div> <!-- Selection info -->
</div>
</div>
</div>
*/
const VideoFrame = React.memo((props: { events: Registry<AppUiEvents> }) => {
const refElement = React.useRef<HTMLDivElement>();
const [ container, setContainer ] = useState<HTMLDivElement | undefined>(() => {
props.events.fire("query_video_container");
return undefined;
});
props.events.reactUse("notify_video_container", event => setContainer(event.container));
useEffect(() => {
if(!refElement.current || !container) {
return;
}
refElement.current.replaceWith(container);
return () => container.replaceWith(refElement.current);
});
if(!container) {
return null;
}
return <div ref={refElement} />;
});
const ChannelTree = React.memo((props: { events: Registry<AppUiEvents> }) => {
const [ data, setData ] = useState<{ events: Registry<ChannelTreeUIEvents>, handlerId: string }>(() => {
props.events.fire("query_channel_tree");
return undefined;
});
props.events.reactUse("notify_channel_tree", event => {
setData({ events: event.events, handlerId: event.handlerId });
}, undefined, []);
if(!data?.events) {
return null;
}
return <ChannelTreeRenderer handlerId={data.handlerId} events={data.events} />;
});
export const TeaAppMainView = (props: {
events: Registry<AppUiEvents>
controlBar: Registry<ControlBarEvents>,
connectionList: Registry<ConnectionListUIEvents>,
sidebar: Registry<SideBarEvents>,
sidebarHeader: Registry<SideHeaderEvents>,
log: Registry<ServerEventLogUiEvents>,
hostBanner: Registry<HostBannerUiEvents>
}) => {
return (
<div className={cssStyle.app}>
<ErrorBoundary>
<ControlBar2 events={props.controlBar} className={cssStyle.controlBar} />
</ErrorBoundary>
<ErrorBoundary>
<ConnectionHandlerList events={props.connectionList} />
</ErrorBoundary>
<div className={cssStyle.mainContainer}>
<VideoFrame events={props.events} />
<div className={cssStyle.channelTreeAndSidebar}>
<div className={cssStyle.channelTree}>
<ErrorBoundary>
<HostBanner events={props.hostBanner} />
<ChannelTree events={props.events} />
</ErrorBoundary>
</div>
<ContextDivider id={"channel-chat"} direction={"horizontal"} defaultValue={25} />
<SideBarRenderer events={props.sidebar} eventsHeader={props.sidebarHeader} className={cssStyle.sideBar} />
</div>
<ContextDivider id={"main-log"} direction={"vertical"} defaultValue={75} />
<ErrorBoundary>
<div className={cssStyle.containerLog}>
<ServerLogFrame events={props.log} />
</div>
</ErrorBoundary>
</div>
<FooterRenderer />
</div>
);
}
/* ConnectionHandlerList */