shareButton.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import {useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {openModal} from 'sentry/actionCreators/modal';
  4. import {Button} from 'sentry/components/button';
  5. import Checkbox from 'sentry/components/checkbox';
  6. import Input from 'sentry/components/input';
  7. import {useReplayContext} from 'sentry/components/replays/replayContext';
  8. import TextCopyInput from 'sentry/components/textCopyInput';
  9. import {IconUpload} from 'sentry/icons';
  10. import {t} from 'sentry/locale';
  11. import {space} from 'sentry/styles/space';
  12. import {formatSecondsToClock, parseClockToSeconds} from 'sentry/utils/formatters';
  13. import getRouteStringFromRoutes from 'sentry/utils/getRouteStringFromRoutes';
  14. import {useRoutes} from 'sentry/utils/useRoutes';
  15. function ShareModal({currentTimeSec, Header, Body}) {
  16. const routes = useRoutes();
  17. const [isCustom, setIsCustom] = useState(false);
  18. const [customSeconds, setSeconds] = useState(currentTimeSec);
  19. const url = new URL(window.location.href);
  20. const {searchParams} = url;
  21. searchParams.set('referrer', getRouteStringFromRoutes(routes));
  22. searchParams.set('t', isCustom ? String(customSeconds) : currentTimeSec);
  23. // Use `value` instead of `defaultValue` so the number resets to
  24. // `currentTimeSec` if the user toggles isCustom
  25. const value = isCustom
  26. ? formatSecondsToClock(customSeconds, {padAll: false})
  27. : formatSecondsToClock(currentTimeSec, {padAll: false});
  28. return (
  29. <div>
  30. <Header>
  31. <h3>Share Replay</h3>
  32. </Header>
  33. <Body>
  34. <StyledTextCopyInput aria-label={t('Deeplink to current timestamp')} size="sm">
  35. {url.toString()}
  36. </StyledTextCopyInput>
  37. <InputRow>
  38. <StyledCheckbox
  39. id="replay_share_custom_time"
  40. name="replay_share_custom_time"
  41. checked={isCustom}
  42. onChange={() => setIsCustom(prev => !prev)}
  43. />
  44. <StyledLabel htmlFor="replay_share_custom_time">{t('Start at')}</StyledLabel>
  45. <StyledInput
  46. name="time"
  47. placeholder=""
  48. disabled={!isCustom}
  49. value={value}
  50. onChange={e => setSeconds(parseClockToSeconds(e.target.value))}
  51. />
  52. </InputRow>
  53. </Body>
  54. </div>
  55. );
  56. }
  57. function ShareButton() {
  58. // Cannot use this hook inside the modal because context will not be wired up
  59. const {currentTime} = useReplayContext();
  60. // floor() to remove ms level precision. It's a cleaner url by default this way.
  61. const currentTimeSec = Math.floor(currentTime / 1000);
  62. return (
  63. <Button
  64. size="xs"
  65. icon={<IconUpload size="xs" />}
  66. onClick={() =>
  67. openModal(deps => <ShareModal currentTimeSec={currentTimeSec} {...deps} />)
  68. }
  69. >
  70. {t('Share')}
  71. </Button>
  72. );
  73. }
  74. const StyledTextCopyInput = styled(TextCopyInput)`
  75. /* Keep height consistent with the other input in the modal */
  76. input {
  77. height: 38px;
  78. }
  79. `;
  80. const InputRow = styled('div')`
  81. margin-top: ${space(2)};
  82. display: flex;
  83. flex-direction: row;
  84. gap: ${space(1)};
  85. align-items: center;
  86. `;
  87. const StyledCheckbox = styled(Checkbox)`
  88. margin: 0 !important;
  89. `;
  90. const StyledLabel = styled('label')`
  91. margin: 0;
  92. `;
  93. const StyledInput = styled(Input)`
  94. width: auto;
  95. max-width: 90px;
  96. `;
  97. export default ShareButton;