import { DesktopWindows as DesktopWindowsIcon, PowerOffOutlined as PowerOffOutlinedIcon, } from '@mui/icons-material'; import { Box, IconButton as MUIIconButton, IconButtonProps as MUIIconButtonProps, } from '@mui/material'; import { FC, ReactNode, useEffect, useMemo, useState } from 'react'; import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import { BORDER_RADIUS, GREY } from '../../lib/consts/DEFAULT_THEME'; import FlexBox from '../FlexBox'; import IconButton, { IconButtonProps } from '../IconButton'; import { InnerPanel, InnerPanelHeader, Panel, PanelHeader } from '../Panels'; import Spinner from '../Spinner'; import { BodyText, HeaderText } from '../Text'; type PreviewOptionalProps = { externalPreview?: string; headerEndAdornment?: ReactNode; isExternalPreviewStale?: boolean; isFetchPreview?: boolean; isShowControls?: boolean; isUseInnerPanel?: boolean; onClickConnectButton?: IconButtonProps['onClick']; onClickPreview?: MUIIconButtonProps['onClick']; serverName?: string; }; type PreviewProps = PreviewOptionalProps & { serverUUID: string; }; const PREVIEW_DEFAULT_PROPS: Required< Omit > & Pick = { externalPreview: '', headerEndAdornment: null, isExternalPreviewStale: false, isFetchPreview: true, isShowControls: true, isUseInnerPanel: false, onClickConnectButton: undefined, onClickPreview: undefined, serverName: '', }; const PreviewPanel: FC<{ isUseInnerPanel: boolean }> = ({ children, isUseInnerPanel, }) => isUseInnerPanel ? ( {children} ) : ( {children} ); const PreviewPanelHeader: FC<{ isUseInnerPanel: boolean; text: string | undefined; }> = ({ children, isUseInnerPanel, text }) => isUseInnerPanel ? ( {text ? : <>} {children} ) : ( {text ? : <>} {children} ); const Preview: FC = ({ externalPreview = PREVIEW_DEFAULT_PROPS.externalPreview, headerEndAdornment, isExternalPreviewStale = PREVIEW_DEFAULT_PROPS.isExternalPreviewStale, isFetchPreview = PREVIEW_DEFAULT_PROPS.isFetchPreview, isShowControls = PREVIEW_DEFAULT_PROPS.isShowControls, isUseInnerPanel = PREVIEW_DEFAULT_PROPS.isUseInnerPanel, onClickPreview: previewClickHandler, serverName, serverUUID, onClickConnectButton: connectButtonClickHandle = previewClickHandler, }) => { const [isPreviewLoading, setIsPreviewLoading] = useState(true); const [isPreviewStale, setIsPreviewStale] = useState(false); const [preview, setPreview] = useState(''); const previewButtonContent = useMemo( () => preview ? ( ) : ( ), [isPreviewStale, isUseInnerPanel, preview], ); useEffect(() => { if (isFetchPreview) { (async () => { try { const response = await fetch( `${API_BASE_URL}/server/${serverUUID}?ss`, { method: 'GET', headers: { 'Content-Type': 'application/json', }, }, ); const { screenshot: fetchedScreenshot } = await response.json(); setPreview(fetchedScreenshot); setIsPreviewStale(false); } catch { setIsPreviewStale(true); } finally { setIsPreviewLoading(false); } })(); } else if (externalPreview) { setPreview(externalPreview); setIsPreviewStale(isExternalPreviewStale); setIsPreviewLoading(false); } }, [externalPreview, isExternalPreviewStale, isFetchPreview, serverUUID]); return ( {headerEndAdornment} :first-child': { flexGrow: 1 } }}> {/* Box wrapper below is required to keep external preview size sane. */} {isPreviewLoading ? ( ) : ( {previewButtonContent} )} {isShowControls && ( )} ); }; Preview.defaultProps = PREVIEW_DEFAULT_PROPS; export default Preview;