import { useRecoilState, useRecoilValue } from 'recoil'; import { Layout, Tabs, Spin } from 'antd'; import { FC, useEffect, useState } from 'react'; import classNames from 'classnames'; import dynamic from 'next/dynamic'; import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage'; import { clientConfigStateAtom, chatMessagesAtom, chatDisplayNameAtom, chatUserIdAtom, isChatAvailableSelector, 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/OwncastPlayer'; import styles from './Content.module.scss'; import { Sidebar } from '../Sidebar/Sidebar'; import { Footer } from '../Footer/Footer'; import { ActionButtonRow } from '../../action-buttons/ActionButtonRow/ActionButtonRow'; import { ActionButton } from '../../action-buttons/ActionButton/ActionButton'; import { OfflineBanner } from '../OfflineBanner/OfflineBanner'; import { AppStateOptions } from '../../stores/application-state'; import { FollowButton } from '../../action-buttons/FollowButton'; import { NotifyButton } from '../../action-buttons/NotifyButton'; import { ContentHeader } from '../../common/ContentHeader/ContentHeader'; import { ServerStatus } from '../../../interfaces/server-status.model'; import { Statusbar } from '../Statusbar/Statusbar'; import { ChatMessage } from '../../../interfaces/chat-message.model'; const { TabPane } = Tabs; const { Content: AntContent } = Layout; // Lazy loaded components const Modal = dynamic(() => import('../Modal/Modal').then(mod => mod.Modal)); const BrowserNotifyModal = dynamic(() => import('../../modals/BrowserNotifyModal/BrowserNotifyModal').then(mod => mod.BrowserNotifyModal), ); const NotifyReminderPopup = dynamic(() => import('../NotifyReminderPopup/NotifyReminderPopup').then(mod => mod.NotifyReminderPopup), ); const FollowerCollection = dynamic(() => import('../followers/FollowerCollection/FollowerCollection').then(mod => mod.FollowerCollection), ); // We only need to load the chat container here if we're in mobile or narrow // windows, so lazy loading it makes sense. const ChatContainer = dynamic(() => import('../../chat/ChatContainer/ChatContainer').then(mod => mod.ChatContainer), ); const DesktopContent = ({ name, streamTitle, summary, tags, socialHandles, extraPageContent }) => ( <>
); const MobileContent = ({ name, streamTitle, summary, tags, socialHandles, extraPageContent, messages, chatDisplayName, chatUserId, showChat, }) => (
{showChat && ( )}
); export const Content: FC = () => { const appState = useRecoilValue(appStateAtom); const clientConfig = useRecoilValue(clientConfigStateAtom); const isChatVisible = useRecoilValue(isChatVisibleSelector); const isChatAvailable = useRecoilValue(isChatAvailableSelector); const [isMobile, setIsMobile] = useRecoilState(isMobileAtom); const messages = useRecoilValue(chatMessagesAtom); const online = useRecoilValue(isOnlineSelector); const chatDisplayName = useRecoilValue(chatDisplayNameAtom); const chatUserId = useRecoilValue(chatUserIdAtom); const { viewerCount, lastConnectTime, lastDisconnectTime, streamTitle } = useRecoilValue(serverStatusState); const { extraPageContent, version, name, summary, socialHandles, tags, externalActions, offlineMessage, chatDisabled, federation, notifications, } = clientConfig; const [showNotifyReminder, setShowNotifyReminder] = useState(false); const [showNotifyPopup, setShowNotifyPopup] = useState(false); const { account: fediverseAccount } = federation; const { browser: browserNotifications } = notifications; const { enabled: browserNotificationsEnabled } = browserNotifications; const externalActionButtons = externalActions.map(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 showChat = !chatDisabled && isChatAvailable && isChatVisible; return (
{online && } {!online && !appState.appLoading && ( setShowNotifyPopup(true)} /> )} {online && ( )}
{externalActionButtons} setShowNotifyPopup(true)} notificationClosed={() => disableNotifyReminderPopup()} > setShowNotifyPopup(true)} /> disableNotifyReminderPopup()} handleCancel={() => disableNotifyReminderPopup()} >
{isMobile && isChatVisible ? ( ) : ( )}
{showChat && !isMobile && }
{(!isMobile || !showChat) &&
); }; export default Content;