import {useRef} from 'react'; import styled from '@emotion/styled'; import ErrorBoundary from 'sentry/components/errorBoundary'; import ReplayTimeline from 'sentry/components/replays/breadcrumbs/replayTimeline'; import ReplayController from 'sentry/components/replays/replayController'; import ReplayView from 'sentry/components/replays/replayView'; import {space} from 'sentry/styles/space'; import {LayoutKey} from 'sentry/utils/replays/hooks/useReplayLayout'; import {useDimensions} from 'sentry/utils/useDimensions'; import useOrganization from 'sentry/utils/useOrganization'; import useFullscreen from 'sentry/utils/window/useFullscreen'; import FluidHeight from 'sentry/views/replays/detail/layout/fluidHeight'; import FluidPanel from 'sentry/views/replays/detail/layout/fluidPanel'; import FocusArea from 'sentry/views/replays/detail/layout/focusArea'; import FocusTabs from 'sentry/views/replays/detail/layout/focusTabs'; import SplitPanel from 'sentry/views/replays/detail/layout/splitPanel'; const MIN_CONTENT_WIDTH = 340; const MIN_SIDEBAR_WIDTH = 325; const MIN_VIDEO_HEIGHT = 200; const MIN_CONTENT_HEIGHT = 180; const DIVIDER_SIZE = 16; type Props = { layout?: LayoutKey; }; function ReplayLayout({layout = LayoutKey.TOPBAR}: Props) { const fullscreenRef = useRef(null); const {toggle: toggleFullscreen} = useFullscreen({ elementRef: fullscreenRef, }); const measureRef = useRef(null); const {width, height} = useDimensions({elementRef: measureRef}); const organization = useOrganization(); const hasNewTimeline = organization.features.includes('session-replay-new-timeline'); const timeline = hasNewTimeline ? null : ( ); const video = ( ); const controller = hasNewTimeline ? ( ) : null; if (layout === LayoutKey.VIDEO_ONLY) { return ( {timeline} {video} {controller} ); } const focusArea = ( }> ); const hasSize = width + height > 0; if (layout === LayoutKey.NO_VIDEO) { return ( {timeline} {hasSize ? {focusArea} : null} ); } if (layout === LayoutKey.SIDEBAR_LEFT) { return ( {timeline} {hasSize ? ( {video}, default: width * 0.5, min: MIN_SIDEBAR_WIDTH, max: width - MIN_CONTENT_WIDTH, }} right={focusArea} /> ) : null} {controller} ); } // layout === 'topbar' return ( {timeline} {hasSize ? ( {video}, default: (height - DIVIDER_SIZE) * 0.5, min: MIN_VIDEO_HEIGHT, max: height - DIVIDER_SIZE - MIN_CONTENT_HEIGHT, }} bottom={focusArea} /> ) : null} {controller} ); } const BodyContent = styled('main')` background: ${p => p.theme.background}; width: 100%; height: 100%; display: grid; grid-template-rows: auto 1fr; gap: ${space(2)}; overflow: hidden; padding: ${space(2)}; `; const SmallMarginFocusTabs = styled(FocusTabs)` margin-bottom: ${space(1)}; `; const VideoSection = styled(FluidHeight)` background: ${p => p.theme.background}; gap: ${space(1)}; :fullscreen { padding: ${space(1)}; } `; const PanelContainer = styled('div')` width: 100%; height: 100%; position: relative; display: grid; overflow: auto; &.disable-iframe-pointer iframe { pointer-events: none !important; } `; export default ReplayLayout;