mirror of
https://github.com/owncast/owncast.git
synced 2024-12-21 08:49:16 +03:00
176 lines
6.7 KiB
TypeScript
176 lines
6.7 KiB
TypeScript
/* eslint-disable react/no-danger */
|
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
|
import { Layout, Tabs, Spin } from 'antd';
|
|
import { useEffect, useState } from 'react';
|
|
import cn from 'classnames';
|
|
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
|
|
|
|
import {
|
|
clientConfigStateAtom,
|
|
chatMessagesAtom,
|
|
chatDisplayNameAtom,
|
|
chatUserIdAtom,
|
|
isChatVisibleSelector,
|
|
appStateAtom,
|
|
isOnlineSelector,
|
|
isMobileAtom,
|
|
serverStatusState,
|
|
} from '../../stores/ClientConfigStore';
|
|
import { ClientConfig } from '../../../interfaces/client-config.model';
|
|
import CustomPageContent from '../CustomPageContent/CustomPageContent';
|
|
import OwncastPlayer from '../../video/OwncastPlayer';
|
|
import FollowerCollection from '../Followers/FollowersCollection';
|
|
import s from './Content.module.scss';
|
|
import Sidebar from '../Sidebar';
|
|
import Footer from '../Footer';
|
|
import ChatContainer from '../../chat/ChatContainer';
|
|
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
|
// import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
|
import ActionButtonRow from '../../action-buttons/ActionButtonRow';
|
|
import ActionButton from '../../action-buttons/ActionButton';
|
|
import NotifyReminderPopup from '../NotifyReminderPopup/NotifyReminderPopup';
|
|
import OfflineBanner from '../OfflineBanner/OfflineBanner';
|
|
import { AppStateOptions } from '../../stores/application-state';
|
|
import FollowButton from '../../action-buttons/FollowButton';
|
|
import NotifyButton from '../../action-buttons/NotifyButton';
|
|
import Modal from '../Modal/Modal';
|
|
import BrowserNotifyModal from '../../modals/BrowserNotify/BrowserNotifyModal';
|
|
import StreamInfo from '../../common/StreamInfo';
|
|
import { ServerStatus } from '../../../interfaces/server-status.model';
|
|
import { StatusBar } from '..';
|
|
|
|
const { TabPane } = Tabs;
|
|
const { Content } = Layout;
|
|
|
|
export default function ContentComponent() {
|
|
const appState = useRecoilValue<AppStateOptions>(appStateAtom);
|
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
|
const isChatVisible = useRecoilValue<boolean>(isChatVisibleSelector);
|
|
const [isMobile, setIsMobile] = useRecoilState<boolean | undefined>(isMobileAtom);
|
|
const messages = useRecoilValue<ChatMessage[]>(chatMessagesAtom);
|
|
const online = useRecoilValue<boolean>(isOnlineSelector);
|
|
const chatDisplayName = useRecoilValue<string>(chatDisplayNameAtom);
|
|
const chatUserId = useRecoilValue<string>(chatUserIdAtom);
|
|
const { viewerCount, lastConnectTime, lastDisconnectTime } =
|
|
useRecoilValue<ServerStatus>(serverStatusState);
|
|
const { extraPageContent, version, name, externalActions } = clientConfig;
|
|
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
|
const [showNotifyPopup, setShowNotifyPopup] = useState(false);
|
|
|
|
const externalActionButtons = externalActions.map(action => (
|
|
<ActionButton key={action.url} action={action} />
|
|
));
|
|
|
|
const incrementVisitCounter = () => {
|
|
let visits = parseInt(getLocalStorage(LOCAL_STORAGE_KEYS.userVisitCount), 10);
|
|
if (Number.isNaN(visits)) {
|
|
visits = 0;
|
|
}
|
|
|
|
setLocalStorage(LOCAL_STORAGE_KEYS.userVisitCount, visits + 1);
|
|
|
|
if (visits > 2 && !getLocalStorage(LOCAL_STORAGE_KEYS.hasDisplayedNotificationModal)) {
|
|
setShowNotifyReminder(true);
|
|
}
|
|
};
|
|
|
|
const disableNotifyReminderPopup = () => {
|
|
setShowNotifyPopup(false);
|
|
setShowNotifyReminder(false);
|
|
setLocalStorage(LOCAL_STORAGE_KEYS.hasDisplayedNotificationModal, true);
|
|
};
|
|
|
|
const checkIfMobile = () => {
|
|
const w = window.innerWidth;
|
|
if (isMobile === undefined) {
|
|
if (w <= 768) setIsMobile(true);
|
|
else setIsMobile(false);
|
|
}
|
|
if (!isMobile && w <= 768) setIsMobile(true);
|
|
if (isMobile && w > 768) setIsMobile(false);
|
|
};
|
|
|
|
useEffect(() => {
|
|
incrementVisitCounter();
|
|
checkIfMobile();
|
|
window.addEventListener('resize', checkIfMobile);
|
|
}, []);
|
|
|
|
const rootClassName = cn(s.root, {
|
|
[s.mobile]: isMobile,
|
|
});
|
|
|
|
return (
|
|
<Content className={rootClassName}>
|
|
<div className={s.leftContent}>
|
|
<Spin className={s.loadingSpinner} size="large" spinning={appState.appLoading} />
|
|
<div className={s.topHalf}>
|
|
{online && <OwncastPlayer source="/hls/stream.m3u8" online={online} />}
|
|
{!online && (
|
|
<OfflineBanner
|
|
name={name}
|
|
text="Stream is offline text goes here. Will create a new form to set it in the Admin."
|
|
/>
|
|
)}
|
|
<StatusBar
|
|
online={online}
|
|
lastConnectTime={lastConnectTime}
|
|
lastDisconnectTime={lastDisconnectTime}
|
|
viewerCount={viewerCount}
|
|
/>
|
|
<div className={s.buttonsLogoTitleSection}>
|
|
<ActionButtonRow>
|
|
{externalActionButtons}
|
|
<FollowButton size="small" />
|
|
<NotifyReminderPopup
|
|
visible={showNotifyReminder}
|
|
notificationClicked={() => setShowNotifyPopup(true)}
|
|
notificationClosed={() => disableNotifyReminderPopup()}
|
|
>
|
|
<NotifyButton onClick={() => setShowNotifyPopup(true)} />
|
|
</NotifyReminderPopup>
|
|
</ActionButtonRow>
|
|
|
|
<Modal
|
|
title="Notify"
|
|
visible={showNotifyPopup}
|
|
afterClose={() => disableNotifyReminderPopup()}
|
|
handleCancel={() => disableNotifyReminderPopup()}
|
|
>
|
|
<BrowserNotifyModal />
|
|
</Modal>
|
|
</div>
|
|
<StreamInfo isMobile={isMobile} />
|
|
</div>
|
|
<div className={s.lowerHalf}>
|
|
<Tabs defaultActiveKey="0" style={{ height: '100%' }}>
|
|
{isChatVisible && isMobile && (
|
|
<TabPane tab="Chat" key="0" style={{ height: '100%' }}>
|
|
<div style={{ position: 'relative', height: '100%' }}>
|
|
<div className={s.mobileChat}>
|
|
<ChatContainer
|
|
messages={messages}
|
|
// loading={appState.chatLoading}
|
|
usernameToHighlight={chatDisplayName}
|
|
chatUserId={chatUserId}
|
|
isModerator={false}
|
|
isMobile={isMobile}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</TabPane>
|
|
)}
|
|
<TabPane tab="About" key="2" className={s.pageContentSection}>
|
|
<CustomPageContent content={extraPageContent} />
|
|
</TabPane>
|
|
<TabPane tab="Followers" key="3" className={s.pageContentSection}>
|
|
<FollowerCollection />
|
|
</TabPane>
|
|
</Tabs>
|
|
{!isMobile && <Footer version={version} />}
|
|
</div>
|
|
</div>
|
|
{isChatVisible && !isMobile && <Sidebar />}
|
|
</Content>
|
|
);
|
|
}
|