replayView.tsx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import {Fragment, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import {useReplayContext} from 'sentry/components/replays/replayContext';
  5. import ReplayController from 'sentry/components/replays/replayController';
  6. import ReplayCurrentUrl from 'sentry/components/replays/replayCurrentUrl';
  7. import ReplayPlayer from 'sentry/components/replays/replayPlayer';
  8. import ReplayProcessingError from 'sentry/components/replays/replayProcessingError';
  9. import {IconChevron} from 'sentry/icons';
  10. import {t} from 'sentry/locale';
  11. import {space} from 'sentry/styles/space';
  12. import useIsFullscreen from 'sentry/utils/window/useIsFullscreen';
  13. import Breadcrumbs from 'sentry/views/replays/detail/breadcrumbs';
  14. import BrowserOSIcons from 'sentry/views/replays/detail/browserOSIcons';
  15. import FluidHeight from 'sentry/views/replays/detail/layout/fluidHeight';
  16. type Props = {
  17. toggleFullscreen: () => void;
  18. };
  19. function ReplayView({toggleFullscreen}: Props) {
  20. const isFullscreen = useIsFullscreen();
  21. const [isSidebarOpen, setIsSidebarOpen] = useState(true);
  22. const {isFetching, replay} = useReplayContext();
  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. {!isFetching && replay?.hasProcessingErrors() ? (
  41. <ReplayProcessingError processingErrors={replay.processingErrors()} />
  42. ) : (
  43. <Panel>
  44. <ReplayPlayer />
  45. </Panel>
  46. )}
  47. </PlayerContainer>
  48. {isFullscreen && isSidebarOpen ? (
  49. <BreadcrumbContainer>
  50. <Breadcrumbs />
  51. </BreadcrumbContainer>
  52. ) : null}
  53. </PlayerBreadcrumbContainer>
  54. {isFullscreen ? <ReplayController toggleFullscreen={toggleFullscreen} /> : null}
  55. </Fragment>
  56. );
  57. }
  58. const Panel = styled(FluidHeight)`
  59. background: ${p => p.theme.background};
  60. border-radius: ${p => p.theme.borderRadius};
  61. border: 1px solid ${p => p.theme.border};
  62. box-shadow: ${p => p.theme.dropShadowMedium};
  63. `;
  64. const ContextContainer = styled('div')`
  65. display: grid;
  66. grid-auto-flow: column;
  67. grid-template-columns: 1fr max-content max-content;
  68. align-items: center;
  69. gap: ${space(1)};
  70. `;
  71. const PlayerContainer = styled('div')`
  72. display: grid;
  73. grid-auto-flow: row;
  74. grid-template-rows: auto 1fr;
  75. gap: ${space(1)};
  76. flex-grow: 1;
  77. `;
  78. const BreadcrumbContainer = styled('div')`
  79. width: 25%;
  80. `;
  81. const PlayerBreadcrumbContainer = styled('div')`
  82. display: flex;
  83. flex-direction: row;
  84. height: 100%;
  85. gap: ${space(1)};
  86. `;
  87. export default ReplayView;