import {ReactNode} from 'react';
import styled from '@emotion/styled';
import UserBadge from 'sentry/components/idBadge/userBadge';
import * as Layout from 'sentry/components/layouts/thirds';
import DeleteButton from 'sentry/components/replays/header/deleteButton';
import DetailsPageBreadcrumbs from 'sentry/components/replays/header/detailsPageBreadcrumbs';
import FeedbackButton from 'sentry/components/replays/header/feedbackButton';
import HeaderPlaceholder from 'sentry/components/replays/header/headerPlaceholder';
import ReplayMetaData from 'sentry/components/replays/header/replayMetaData';
import ShareButton from 'sentry/components/replays/shareButton';
import FrameWalker from 'sentry/components/replays/walker/frameWalker';
import StringWalker from 'sentry/components/replays/walker/stringWalker';
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {ReplayFrame} from 'sentry/utils/replays/types';
import type {ReplayError, ReplayRecord} from 'sentry/views/replays/types';
type Props = {
children: ReactNode;
orgSlug: string;
projectSlug: string | null;
replayErrors: ReplayError[];
replayRecord: undefined | ReplayRecord;
frames?: ReplayFrame[];
};
function Page({
children,
frames,
orgSlug,
replayRecord,
projectSlug,
replayErrors,
}: Props) {
const title = replayRecord
? `${replayRecord.id} — Session Replay — ${orgSlug}`
: `Session Replay — ${orgSlug}`;
const header = (
{replayRecord?.id && projectSlug && (
)}
{replayRecord ? (
{replayRecord.user.display_name || t('Unknown User')}
}
user={{
name: replayRecord.user.display_name || '',
email: replayRecord.user.email || '',
username: replayRecord.user.username || '',
ip_address: replayRecord.user.ip || '',
id: replayRecord.user.id || '',
}}
// this is the subheading for the avatar, so displayEmail in this case is a misnomer
displayEmail={
{frames?.length ? (
) : (
)}
}
/>
) : (
)}
);
return (
{header}
{children}
);
}
const Header = styled(Layout.Header)`
gap: ${space(1)};
padding-bottom: ${space(1.5)};
@media (min-width: ${p => p.theme.breakpoints.medium}) {
gap: ${space(1)} ${space(3)};
padding: ${space(2)} ${space(2)} ${space(1.5)} ${space(2)};
}
`;
const Cols = styled('div')`
display: flex;
flex-direction: column;
gap: ${space(0.25)};
`;
// TODO(replay); This could make a lot of sense to put inside HeaderActions by default
const ButtonActionsWrapper = styled(Layout.HeaderActions)`
flex-direction: row;
justify-content: flex-end;
gap: ${space(1)};
@media (max-width: ${p => p.theme.breakpoints.medium}) {
margin-bottom: 0;
}
`;
const FullViewport = styled('div')`
height: 100vh;
width: 100%;
display: grid;
grid-template-rows: auto 1fr;
overflow: hidden;
/*
* The footer component is a sibling of this div.
* Remove it so the replay can take up the
* entire screen.
*/
~ footer {
display: none;
}
/*
TODO: Set \`body { overflow: hidden; }\` so that the body doesn't wiggle
when you try to scroll something that is non-scrollable.
*/
`;
export default Page;