import React, { FC, ReactNode, useContext, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import Link from 'next/link'; import Head from 'next/head'; import { differenceInSeconds } from 'date-fns'; import { useRouter } from 'next/router'; import { Layout, Menu, Popover, Alert, Typography, Button, Space, Tooltip } from 'antd'; import { SettingOutlined, HomeOutlined, LineChartOutlined, ToolOutlined, PlayCircleFilled, MinusSquareFilled, QuestionCircleOutlined, MessageOutlined, ExperimentOutlined, EditOutlined, } from '@ant-design/icons'; import classNames from 'classnames'; import { upgradeVersionAvailable } from '../utils/apis'; import { parseSecondsToDurationString } from '../utils/format'; import { OwncastLogo } from './common/OwncastLogo/OwncastLogo'; import { ServerStatusContext } from '../utils/server-status-context'; import { AlertMessageContext } from '../utils/alert-message-context'; import { TextFieldWithSubmit } from './config/TextFieldWithSubmit'; import { TEXTFIELD_PROPS_STREAM_TITLE } from '../utils/config-constants'; import { ComposeFederatedPost } from './ComposeFederatedPost'; import { UpdateArgs } from '../types/config-section'; import FediverseIcon from '../assets/images/fediverse-black.png'; export type MainLayoutProps = { children: ReactNode; }; export const MainLayout: FC = ({ children }) => { const context = useContext(ServerStatusContext); const { serverConfig, online, broadcaster, versionNumber } = context || {}; const { instanceDetails, chatDisabled, federation } = serverConfig; const { enabled: federationEnabled } = federation; const [currentStreamTitle, setCurrentStreamTitle] = useState(''); const [postModalDisplayed, setPostModalDisplayed] = useState(false); const alertMessage = useContext(AlertMessageContext); const router = useRouter(); const { route } = router || {}; const { Header, Footer, Content, Sider } = Layout; const [upgradeVersion, setUpgradeVersion] = useState(''); const checkForUpgrade = async () => { try { const result = await upgradeVersionAvailable(versionNumber); setUpgradeVersion(result); } catch (error) { console.log('==== error', error); } }; useEffect(() => { checkForUpgrade(); }, [versionNumber]); useEffect(() => { setCurrentStreamTitle(instanceDetails.streamTitle); }, [instanceDetails]); const handleStreamTitleChanged = ({ value }: UpdateArgs) => { setCurrentStreamTitle(value); }; const handleCreatePostButtonPressed = () => { setPostModalDisplayed(true); }; const appClass = classNames({ 'app-container': true, online, }); const upgradeVersionString = `${upgradeVersion}` || ''; const upgradeMessage = `Upgrade to v${upgradeVersionString}`; const openMenuItems = upgradeVersion ? ['utilities-menu'] : []; const clearAlertMessage = () => { alertMessage.setMessage(null); }; const headerAlertMessage = alertMessage.message ? ( ) : null; // status indicator items const streamDurationString = broadcaster ? parseSecondsToDurationString(differenceInSeconds(new Date(), new Date(broadcaster.time))) : ''; const currentThumbnail = online ? ( current thumbnail ) : null; const statusIcon = online ? : ; const statusMessage = online ? `Online ${streamDurationString}` : 'Offline'; const popoverTitle = Thumbnail; const statusIndicator = (
{statusMessage} {statusIcon}
); const statusIndicatorWithThumb = online ? ( {statusIndicator} ) : ( statusIndicator ); const integrationsMenu = [ { label: Webhooks, key: 'webhooks', }, { label: Access Tokens, key: 'access-tokens', }, { label: External Actions, key: 'actions', }, ]; const chatMenu = [ { label: Messages, key: 'messages', }, { label: Users, key: 'chat-users', }, { label: Emojis, key: 'emojis', }, ]; const utilitiesMenu = [ { label: Hardware, key: 'hardware-info', }, { label: Stream Health, key: 'stream-health', }, { label: Logs, key: 'logs', }, federationEnabled && { label: Social Actions, key: 'federation-activities', }, ]; const configurationMenu = [ { label: General, key: 'config-public-details', }, { label: Server Setup, key: 'config-server-details', }, { label: Stream Keys, key: 'config-streamkeys', }, { label: Video, key: 'config-video', }, { label: Chat, key: 'config-chat', }, { label: Social, key: 'config-federation', }, { label: Notifications, key: 'config-notify', }, { label: Appearance, key: 'config-appearance', }, { label: S3 Storage, key: 'config-storage', }, ]; const menuItems = [ { label: Home, icon: , key: 'home' }, { label: Viewers, icon: , key: 'viewer-info', }, !chatDisabled && { label: Chat & Users, icon: , children: chatMenu, }, federationEnabled && { key: 'fediverse-followers', label: Followers, icon: ( fediverse icon ), }, { key: 'configuration', label: 'Configuration', icon: , children: configurationMenu, }, { key: 'utilities', label: 'Utilities', icon: , children: utilitiesMenu, }, { key: 'integrations', label: 'Integrations', icon: , children: integrationsMenu, }, upgradeVersion && { key: 'upgrade', label: {upgradeMessage}, }, { key: 'help', label: 'Help', icon: , }, ]; return ( Owncast Admin

Owncast Admin

{headerAlertMessage} {children}
setPostModalDisplayed(false)} /> ); }; MainLayout.propTypes = { children: PropTypes.element.isRequired, };