replayView.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import {Fragment, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import ReplayController from 'sentry/components/replays/replayController';
  5. import ReplayCurrentUrl from 'sentry/components/replays/replayCurrentUrl';
  6. import ReplayPlayer from 'sentry/components/replays/replayPlayer';
  7. import {IconChevron} from 'sentry/icons';
  8. import {t} from 'sentry/locale';
  9. import {space} from 'sentry/styles/space';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import useIsFullscreen from 'sentry/utils/window/useIsFullscreen';
  12. import Breadcrumbs from 'sentry/views/replays/detail/breadcrumbs';
  13. import BrowserOSIcons from 'sentry/views/replays/detail/browserOSIcons';
  14. import FluidHeight from 'sentry/views/replays/detail/layout/fluidHeight';
  15. type Props = {
  16. toggleFullscreen: () => void;
  17. };
  18. function ReplayView({toggleFullscreen}: Props) {
  19. const organization = useOrganization();
  20. const hasNewTimeline = organization.features.includes('session-replay-new-timeline');
  21. const isFullscreen = useIsFullscreen();
  22. const [isSidebarOpen, setIsSidebarOpen] = useState(true);
  23. return (
  24. <Fragment>
  25. <PlayerBreadcrumbContainer>
  26. <PlayerContainer>
  27. <ContextContainer>
  28. <ReplayCurrentUrl />
  29. <BrowserOSIcons />
  30. {isFullscreen ? (
  31. <Button
  32. size="sm"
  33. onClick={() => setIsSidebarOpen(!isSidebarOpen)}
  34. icon={<IconChevron direction={isSidebarOpen ? 'right' : 'left'} />}
  35. >
  36. {isSidebarOpen ? t('Collapse Sidebar') : t('Open Sidebar')}
  37. </Button>
  38. ) : null}
  39. </ContextContainer>
  40. <Panel>
  41. <ReplayPlayer />
  42. </Panel>
  43. </PlayerContainer>
  44. {isFullscreen && isSidebarOpen ? (
  45. <BreadcrumbContainer>
  46. <Breadcrumbs />
  47. </BreadcrumbContainer>
  48. ) : null}
  49. </PlayerBreadcrumbContainer>
  50. {isFullscreen || !hasNewTimeline ? (
  51. <ReplayController toggleFullscreen={toggleFullscreen} />
  52. ) : null}
  53. </Fragment>
  54. );
  55. }
  56. const Panel = styled(FluidHeight)`
  57. background: ${p => p.theme.background};
  58. border-radius: ${p => p.theme.borderRadius};
  59. border: 1px solid ${p => p.theme.border};
  60. box-shadow: ${p => p.theme.dropShadowMedium};
  61. `;
  62. const ContextContainer = styled('div')`
  63. display: grid;
  64. grid-auto-flow: column;
  65. grid-template-columns: 1fr max-content max-content;
  66. align-items: center;
  67. gap: ${space(1)};
  68. `;
  69. const PlayerContainer = styled('div')`
  70. display: grid;
  71. grid-auto-flow: row;
  72. grid-template-rows: auto 1fr;
  73. gap: ${space(1)};
  74. flex-grow: 1;
  75. `;
  76. const BreadcrumbContainer = styled('div')`
  77. width: 25%;
  78. `;
  79. const PlayerBreadcrumbContainer = styled('div')`
  80. display: flex;
  81. flex-direction: row;
  82. height: 100%;
  83. gap: ${space(1)};
  84. `;
  85. export default ReplayView;