From 2e20e0997da7c1e7ba416b89e57ade8649afdf83 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 3 Jul 2025 20:08:44 +0000 Subject: [PATCH 1/9] Add replay duration display for playback speed options Co-authored-by: jasmin.kassas --- replay-duration-plan.md | 182 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 replay-duration-plan.md diff --git a/replay-duration-plan.md b/replay-duration-plan.md new file mode 100644 index 00000000000000..829286178fb629 --- /dev/null +++ b/replay-duration-plan.md @@ -0,0 +1,182 @@ +# Plan: Add Updated Replay Duration to Playback Speed Options + +## Overview +Add adjusted replay duration display next to each playback speed option in the Replay Details page Settings dropdown. For example, if a replay duration is 20 minutes and the playback speed is 2x, show "10 minutes" next to the 2x option. + +## Current Implementation Analysis + +### Key Components +1. **ReplayPreferenceDropdown** (`/static/app/components/replays/preferences/replayPreferenceDropdown.tsx`) + - Contains the Settings gear icon dropdown + - Manages playback speed options using `CompositeSelect.Region` + - Currently displays speed options as `${option}x` (e.g., "0.1x", "0.25x", "1x", "2x") + +2. **ReplayController** (`/static/app/components/replays/replayController.tsx`) + - Contains the `ReplayPreferenceDropdown` component + - Defines default speed options: `[0.1, 0.25, 0.5, 1, 2, 4, 8, 16]` + +3. **Duration Access** + - Replay duration is available via `useReplayContext()` hook + - `replay.getDurationMs()` returns duration in milliseconds + - Duration formatting is handled by `Duration` component from `sentry/components/duration/duration` + +## Implementation Plan + +### Step 1: Modify ReplayPreferenceDropdown Component + +**File**: `/static/app/components/replays/preferences/replayPreferenceDropdown.tsx` + +**Changes**: +1. Import `useReplayContext` to access replay duration +2. Import `Duration` component for consistent formatting +3. Create a helper function to calculate adjusted duration +4. Modify the speed options mapping to include duration display +5. Only show duration when replay data is loaded (not fetching) + +**Key Logic**: +```typescript +// Calculate adjusted duration for each speed +const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { + return originalDurationMs / speed; +}; + +// Check if we should show duration (data is loaded and duration is available) +const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; +``` + +**Option Label Format**: +- When duration is available: `"2x (10:00)"` +- When duration is not available: `"2x"` (current behavior) + +### Step 2: Update Option Rendering Logic + +**Current**: +```typescript +options={speedOptions.map(option => ({ + label: `${option}x`, + value: option, +}))} +``` + +**New**: +```typescript +options={speedOptions.map(option => { + const baseLabel = `${option}x`; + + if (shouldShowDuration) { + const adjustedDurationMs = calculateAdjustedDuration(replay.getDurationMs(), option); + const durationDisplay = formatDuration({ + duration: [adjustedDurationMs, 'ms'], + precision: 'sec', + style: 'mm:ss' + }); + return { + label: `${baseLabel} (${durationDisplay})`, + value: option, + }; + } + + return { + label: baseLabel, + value: option, + }; +})} +``` + +### Step 3: Handle Edge Cases + +**Considerations**: +1. **Loading State**: Don't show duration when `isLoading` or `isFetching` is true +2. **Zero Duration**: Don't show duration if `replay.getDurationMs()` returns 0 or undefined +3. **Performance**: Calculations are lightweight (simple division), no memoization needed +4. **Formatting**: Use existing duration formatting utilities for consistency +5. **Accessibility**: Ensure screen readers can properly read the duration information + +### Step 4: Styling Considerations + +**Current UI**: Uses `CompositeSelect.Region` which handles option styling automatically + +**Potential Enhancements** (if needed): +- Duration text could be styled with a lighter color to differentiate from speed +- Consider truncating very long durations or using abbreviated format for compact display + +### Step 5: Testing Strategy + +**Unit Tests**: +- Test duration calculation for various speeds +- Test that duration only shows when data is available +- Test edge cases (zero duration, very long durations, decimal speeds) + +**Manual Testing**: +- Verify behavior during loading state +- Test with various replay durations (short, medium, long) +- Verify accessibility with screen readers +- Test on different screen sizes (compact mode) + +## Dependencies Required + +**New Imports**: +```typescript +import {useReplayContext} from 'sentry/components/replays/replayContext'; +import formatDuration from 'sentry/utils/duration/formatDuration'; +``` + +**No Breaking Changes**: This is purely additive functionality that gracefully degrades when data is not available. + +## Expected Behavior + +### Before Implementation +``` +Settings > Playback Speed: +• 0.1x +• 0.25x +• 0.5x +✓ 1x +• 2x +• 4x +• 8x +• 16x +``` + +### After Implementation (with 20-minute replay) +``` +Settings > Playback Speed: +• 0.1x (3:20:00) +• 0.25x (1:20:00) +• 0.5x (40:00) +✓ 1x (20:00) +• 2x (10:00) +• 4x (5:00) +• 8x (2:30) +• 16x (1:15) +``` + +### During Loading (no change) +``` +Settings > Playback Speed: +• 0.1x +• 0.25x +• 0.5x +✓ 1x +• 2x +• 4x +• 8x +• 16x +``` + +## Files to Modify + +1. **Primary**: `/static/app/components/replays/preferences/replayPreferenceDropdown.tsx` + - Add duration calculation and display logic + +2. **Tests** (if they exist): + - Update existing tests for `replayPreferenceDropdown` + - Add new tests for duration calculation + +## Implementation Priority + +**High Priority**: Core functionality (calculate and display duration) +**Medium Priority**: Edge case handling and formatting refinements +**Low Priority**: Styling enhancements and advanced accessibility features + +This plan provides a clean, maintainable solution that enhances user experience without disrupting existing functionality. From 9ed0bbd1231073df063a296268d7c340f7f05fe7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 3 Jul 2025 20:15:32 +0000 Subject: [PATCH 2/9] Add replay duration display to playback speed options Co-authored-by: jasmin.kassas --- replay-duration-plan.md | 182 ------------------ .../preferences/replayPreferenceDropdown.tsx | 36 +++- 2 files changed, 32 insertions(+), 186 deletions(-) delete mode 100644 replay-duration-plan.md diff --git a/replay-duration-plan.md b/replay-duration-plan.md deleted file mode 100644 index 829286178fb629..00000000000000 --- a/replay-duration-plan.md +++ /dev/null @@ -1,182 +0,0 @@ -# Plan: Add Updated Replay Duration to Playback Speed Options - -## Overview -Add adjusted replay duration display next to each playback speed option in the Replay Details page Settings dropdown. For example, if a replay duration is 20 minutes and the playback speed is 2x, show "10 minutes" next to the 2x option. - -## Current Implementation Analysis - -### Key Components -1. **ReplayPreferenceDropdown** (`/static/app/components/replays/preferences/replayPreferenceDropdown.tsx`) - - Contains the Settings gear icon dropdown - - Manages playback speed options using `CompositeSelect.Region` - - Currently displays speed options as `${option}x` (e.g., "0.1x", "0.25x", "1x", "2x") - -2. **ReplayController** (`/static/app/components/replays/replayController.tsx`) - - Contains the `ReplayPreferenceDropdown` component - - Defines default speed options: `[0.1, 0.25, 0.5, 1, 2, 4, 8, 16]` - -3. **Duration Access** - - Replay duration is available via `useReplayContext()` hook - - `replay.getDurationMs()` returns duration in milliseconds - - Duration formatting is handled by `Duration` component from `sentry/components/duration/duration` - -## Implementation Plan - -### Step 1: Modify ReplayPreferenceDropdown Component - -**File**: `/static/app/components/replays/preferences/replayPreferenceDropdown.tsx` - -**Changes**: -1. Import `useReplayContext` to access replay duration -2. Import `Duration` component for consistent formatting -3. Create a helper function to calculate adjusted duration -4. Modify the speed options mapping to include duration display -5. Only show duration when replay data is loaded (not fetching) - -**Key Logic**: -```typescript -// Calculate adjusted duration for each speed -const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { - return originalDurationMs / speed; -}; - -// Check if we should show duration (data is loaded and duration is available) -const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; -``` - -**Option Label Format**: -- When duration is available: `"2x (10:00)"` -- When duration is not available: `"2x"` (current behavior) - -### Step 2: Update Option Rendering Logic - -**Current**: -```typescript -options={speedOptions.map(option => ({ - label: `${option}x`, - value: option, -}))} -``` - -**New**: -```typescript -options={speedOptions.map(option => { - const baseLabel = `${option}x`; - - if (shouldShowDuration) { - const adjustedDurationMs = calculateAdjustedDuration(replay.getDurationMs(), option); - const durationDisplay = formatDuration({ - duration: [adjustedDurationMs, 'ms'], - precision: 'sec', - style: 'mm:ss' - }); - return { - label: `${baseLabel} (${durationDisplay})`, - value: option, - }; - } - - return { - label: baseLabel, - value: option, - }; -})} -``` - -### Step 3: Handle Edge Cases - -**Considerations**: -1. **Loading State**: Don't show duration when `isLoading` or `isFetching` is true -2. **Zero Duration**: Don't show duration if `replay.getDurationMs()` returns 0 or undefined -3. **Performance**: Calculations are lightweight (simple division), no memoization needed -4. **Formatting**: Use existing duration formatting utilities for consistency -5. **Accessibility**: Ensure screen readers can properly read the duration information - -### Step 4: Styling Considerations - -**Current UI**: Uses `CompositeSelect.Region` which handles option styling automatically - -**Potential Enhancements** (if needed): -- Duration text could be styled with a lighter color to differentiate from speed -- Consider truncating very long durations or using abbreviated format for compact display - -### Step 5: Testing Strategy - -**Unit Tests**: -- Test duration calculation for various speeds -- Test that duration only shows when data is available -- Test edge cases (zero duration, very long durations, decimal speeds) - -**Manual Testing**: -- Verify behavior during loading state -- Test with various replay durations (short, medium, long) -- Verify accessibility with screen readers -- Test on different screen sizes (compact mode) - -## Dependencies Required - -**New Imports**: -```typescript -import {useReplayContext} from 'sentry/components/replays/replayContext'; -import formatDuration from 'sentry/utils/duration/formatDuration'; -``` - -**No Breaking Changes**: This is purely additive functionality that gracefully degrades when data is not available. - -## Expected Behavior - -### Before Implementation -``` -Settings > Playback Speed: -• 0.1x -• 0.25x -• 0.5x -✓ 1x -• 2x -• 4x -• 8x -• 16x -``` - -### After Implementation (with 20-minute replay) -``` -Settings > Playback Speed: -• 0.1x (3:20:00) -• 0.25x (1:20:00) -• 0.5x (40:00) -✓ 1x (20:00) -• 2x (10:00) -• 4x (5:00) -• 8x (2:30) -• 16x (1:15) -``` - -### During Loading (no change) -``` -Settings > Playback Speed: -• 0.1x -• 0.25x -• 0.5x -✓ 1x -• 2x -• 4x -• 8x -• 16x -``` - -## Files to Modify - -1. **Primary**: `/static/app/components/replays/preferences/replayPreferenceDropdown.tsx` - - Add duration calculation and display logic - -2. **Tests** (if they exist): - - Update existing tests for `replayPreferenceDropdown` - - Add new tests for duration calculation - -## Implementation Priority - -**High Priority**: Core functionality (calculate and display duration) -**Medium Priority**: Edge case handling and formatting refinements -**Low Priority**: Styling enhancements and advanced accessibility features - -This plan provides a clean, maintainable solution that enhances user experience without disrupting existing functionality. diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index ff68b87f371e8c..888157466bb3c3 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -1,7 +1,9 @@ import {Button} from 'sentry/components/core/button'; import {CompositeSelect} from 'sentry/components/core/compactSelect/composite'; +import {useReplayContext} from 'sentry/components/replays/replayContext'; import {IconSettings} from 'sentry/icons'; import {t} from 'sentry/locale'; +import formatDuration from 'sentry/utils/duration/formatDuration'; import {useReplayPrefs} from 'sentry/utils/replays/playback/providers/replayPreferencesContext'; import {toTitleCase} from 'sentry/utils/string/toTitleCase'; @@ -17,9 +19,18 @@ export default function ReplayPreferenceDropdown({ isLoading?: boolean; }) { const [prefs, setPrefs] = useReplayPrefs(); + const {isFetching, replay} = useReplayContext(); const SKIP_OPTION_VALUE = 'skip'; + // Calculate adjusted duration for each speed + const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { + return originalDurationMs / speed; + }; + + // Check if we should show duration (data is loaded and duration is available) + const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; + return ( setPrefs({playbackSpeed: opt.value})} - options={speedOptions.map(option => ({ - label: `${option}x`, - value: option, - }))} + options={speedOptions.map(option => { + const baseLabel = `${option}x`; + + if (shouldShowDuration) { + const adjustedDurationMs = calculateAdjustedDuration(replay.getDurationMs(), option); + const durationDisplay = formatDuration({ + duration: [adjustedDurationMs, 'ms'], + precision: 'sec', + style: 'h:mm:ss' + }); + return { + label: `${baseLabel} (${durationDisplay})`, + value: option, + }; + } + + return { + label: baseLabel, + value: option, + }; + })} /> Date: Thu, 3 Jul 2025 20:18:21 +0000 Subject: [PATCH 3/9] :hammer_and_wrench: apply pre-commit fixes --- .../replays/preferences/replayPreferenceDropdown.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index 888157466bb3c3..f2a1513f316770 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -29,7 +29,8 @@ export default function ReplayPreferenceDropdown({ }; // Check if we should show duration (data is loaded and duration is available) - const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; + const shouldShowDuration = + !isLoading && !isFetching && replay && replay.getDurationMs() > 0; return ( Date: Thu, 3 Jul 2025 20:44:51 +0000 Subject: [PATCH 4/9] Update replay preference dropdown label formatting Co-authored-by: jasmin.kassas --- .../components/replays/preferences/replayPreferenceDropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index f2a1513f316770..2af9db59dd5a54 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -63,7 +63,7 @@ export default function ReplayPreferenceDropdown({ style: 'h:mm:ss', }); return { - label: `${baseLabel} (${durationDisplay})`, + label: `${baseLabel} ${durationDisplay}`, value: option, }; } From fedc864d39851d33a13df854394cfdfd089fff5c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 3 Jul 2025 20:50:04 +0000 Subject: [PATCH 5/9] Remove duration calculation from replay preference dropdown Co-authored-by: jasmin.kassas --- .../preferences/replayPreferenceDropdown.tsx | 40 ++----------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index 2af9db59dd5a54..ff68b87f371e8c 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -1,9 +1,7 @@ import {Button} from 'sentry/components/core/button'; import {CompositeSelect} from 'sentry/components/core/compactSelect/composite'; -import {useReplayContext} from 'sentry/components/replays/replayContext'; import {IconSettings} from 'sentry/icons'; import {t} from 'sentry/locale'; -import formatDuration from 'sentry/utils/duration/formatDuration'; import {useReplayPrefs} from 'sentry/utils/replays/playback/providers/replayPreferencesContext'; import {toTitleCase} from 'sentry/utils/string/toTitleCase'; @@ -19,19 +17,9 @@ export default function ReplayPreferenceDropdown({ isLoading?: boolean; }) { const [prefs, setPrefs] = useReplayPrefs(); - const {isFetching, replay} = useReplayContext(); const SKIP_OPTION_VALUE = 'skip'; - // Calculate adjusted duration for each speed - const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { - return originalDurationMs / speed; - }; - - // Check if we should show duration (data is loaded and duration is available) - const shouldShowDuration = - !isLoading && !isFetching && replay && replay.getDurationMs() > 0; - return ( setPrefs({playbackSpeed: opt.value})} - options={speedOptions.map(option => { - const baseLabel = `${option}x`; - - if (shouldShowDuration) { - const adjustedDurationMs = calculateAdjustedDuration( - replay.getDurationMs(), - option - ); - const durationDisplay = formatDuration({ - duration: [adjustedDurationMs, 'ms'], - precision: 'sec', - style: 'h:mm:ss', - }); - return { - label: `${baseLabel} ${durationDisplay}`, - value: option, - }; - } - - return { - label: baseLabel, - value: option, - }; - })} + options={speedOptions.map(option => ({ + label: `${option}x`, + value: option, + }))} /> Date: Thu, 3 Jul 2025 20:55:02 +0000 Subject: [PATCH 6/9] Add playback speed duration display in replay preferences dropdown Co-authored-by: jasmin.kassas --- .../preferences/replayPreferenceDropdown.tsx | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index ff68b87f371e8c..888157466bb3c3 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -1,7 +1,9 @@ import {Button} from 'sentry/components/core/button'; import {CompositeSelect} from 'sentry/components/core/compactSelect/composite'; +import {useReplayContext} from 'sentry/components/replays/replayContext'; import {IconSettings} from 'sentry/icons'; import {t} from 'sentry/locale'; +import formatDuration from 'sentry/utils/duration/formatDuration'; import {useReplayPrefs} from 'sentry/utils/replays/playback/providers/replayPreferencesContext'; import {toTitleCase} from 'sentry/utils/string/toTitleCase'; @@ -17,9 +19,18 @@ export default function ReplayPreferenceDropdown({ isLoading?: boolean; }) { const [prefs, setPrefs] = useReplayPrefs(); + const {isFetching, replay} = useReplayContext(); const SKIP_OPTION_VALUE = 'skip'; + // Calculate adjusted duration for each speed + const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { + return originalDurationMs / speed; + }; + + // Check if we should show duration (data is loaded and duration is available) + const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; + return ( setPrefs({playbackSpeed: opt.value})} - options={speedOptions.map(option => ({ - label: `${option}x`, - value: option, - }))} + options={speedOptions.map(option => { + const baseLabel = `${option}x`; + + if (shouldShowDuration) { + const adjustedDurationMs = calculateAdjustedDuration(replay.getDurationMs(), option); + const durationDisplay = formatDuration({ + duration: [adjustedDurationMs, 'ms'], + precision: 'sec', + style: 'h:mm:ss' + }); + return { + label: `${baseLabel} (${durationDisplay})`, + value: option, + }; + } + + return { + label: baseLabel, + value: option, + }; + })} /> Date: Thu, 3 Jul 2025 20:56:13 +0000 Subject: [PATCH 7/9] :hammer_and_wrench: apply pre-commit fixes --- .../replays/preferences/replayPreferenceDropdown.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index 888157466bb3c3..f2a1513f316770 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -29,7 +29,8 @@ export default function ReplayPreferenceDropdown({ }; // Check if we should show duration (data is loaded and duration is available) - const shouldShowDuration = !isLoading && !isFetching && replay && replay.getDurationMs() > 0; + const shouldShowDuration = + !isLoading && !isFetching && replay && replay.getDurationMs() > 0; return ( Date: Thu, 3 Jul 2025 21:06:24 +0000 Subject: [PATCH 8/9] Round up adjusted replay duration calculation for more accurate timing Co-authored-by: jasmin.kassas --- .../replays/preferences/replayPreferenceDropdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index f2a1513f316770..c1cc62e631b24d 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -23,9 +23,9 @@ export default function ReplayPreferenceDropdown({ const SKIP_OPTION_VALUE = 'skip'; - // Calculate adjusted duration for each speed + // Calculate adjusted duration for each speed (rounded up) const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { - return originalDurationMs / speed; + return Math.ceil(originalDurationMs / speed); }; // Check if we should show duration (data is loaded and duration is available) From 03d41893cdad9f9bb7814d752aec1ed2817f1342 Mon Sep 17 00:00:00 2001 From: Michelle Zhang <56095982+michellewzhang@users.noreply.github.com> Date: Mon, 7 Jul 2025 15:49:33 -0700 Subject: [PATCH 9/9] :recycle: fix rounding and update style --- .../preferences/replayPreferenceDropdown.tsx | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx index c1cc62e631b24d..c5f6299ea755dd 100644 --- a/static/app/components/replays/preferences/replayPreferenceDropdown.tsx +++ b/static/app/components/replays/preferences/replayPreferenceDropdown.tsx @@ -1,5 +1,8 @@ +import styled from '@emotion/styled'; + import {Button} from 'sentry/components/core/button'; import {CompositeSelect} from 'sentry/components/core/compactSelect/composite'; +import {Flex} from 'sentry/components/core/layout'; import {useReplayContext} from 'sentry/components/replays/replayContext'; import {IconSettings} from 'sentry/icons'; import {t} from 'sentry/locale'; @@ -23,9 +26,14 @@ export default function ReplayPreferenceDropdown({ const SKIP_OPTION_VALUE = 'skip'; - // Calculate adjusted duration for each speed (rounded up) + // Calculate adjusted duration for each speed, rounded up to the nearest second. + // Returns in seconds const calculateAdjustedDuration = (originalDurationMs: number, speed: number) => { - return Math.ceil(originalDurationMs / speed); + if (speed === 1) { + return originalDurationMs / 1000; + } + + return Math.ceil(originalDurationMs / speed / 1000); }; // Check if we should show duration (data is loaded and duration is available) @@ -58,12 +66,17 @@ export default function ReplayPreferenceDropdown({ option ); const durationDisplay = formatDuration({ - duration: [adjustedDurationMs, 'ms'], + duration: [adjustedDurationMs, 'sec'], precision: 'sec', style: 'h:mm:ss', }); return { - label: `${baseLabel} (${durationDisplay})`, + label: ( + + {baseLabel} + {durationDisplay} + + ), value: option, }; } @@ -100,3 +113,7 @@ export default function ReplayPreferenceDropdown({ ); } + +const DurationDisplay = styled('span')` + color: ${p => p.theme.subText}; +`;