diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index 258dff37ad96e..e05314abdd53c 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -178,6 +178,7 @@ export const FEATURE_FLAGS = { FEATURE_FLAG_COHORT_CREATION: 'feature-flag-cohort-creation', // owner: @neilkakkar #team-feature-success INSIGHT_HORIZONTAL_CONTROLS: 'insight-horizontal-controls', // owner: @benjackwhite SURVEYS_OPEN_CHOICE: 'surveys-open-choice', // owner: @ssoonmi, #team-feature-success + ALWAYS_SHOW_SEEKBAR_PREVIEW: 'always-show-seekbar-preview', // owner: @pauldambra } as const export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS] diff --git a/frontend/src/scenes/session-recordings/player/controller/PlayerSeekbarPreview.tsx b/frontend/src/scenes/session-recordings/player/controller/PlayerSeekbarPreview.tsx index 01b857d66bbef..8992f6453d26f 100644 --- a/frontend/src/scenes/session-recordings/player/controller/PlayerSeekbarPreview.tsx +++ b/frontend/src/scenes/session-recordings/player/controller/PlayerSeekbarPreview.tsx @@ -1,5 +1,7 @@ import { BindLogic, useActions, useValues } from 'kea' +import { FEATURE_FLAGS } from 'lib/constants' import useIsHovering from 'lib/hooks/useIsHovering' +import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { colonDelimitedDuration } from 'lib/utils' import { MutableRefObject, useEffect, useRef, useState } from 'react' import { useDebouncedCallback } from 'use-debounce' @@ -11,10 +13,13 @@ import { SessionRecordingPlayerMode, } from '../sessionRecordingPlayerLogic' +const TWENTY_MINUTES_IN_MS = 20 * 60 * 1000 + export type PlayerSeekbarPreviewProps = { minMs: number maxMs: number seekBarRef: MutableRefObject + activeMs: number | null } const PlayerSeekbarPreviewFrame = ({ @@ -22,7 +27,10 @@ const PlayerSeekbarPreviewFrame = ({ minMs, maxMs, isVisible, -}: { percentage: number; isVisible: boolean } & Omit): JSX.Element => { +}: { percentage: number; isVisible: boolean } & Omit< + PlayerSeekbarPreviewProps, + 'seekBarRef' | 'activeMs' +>): JSX.Element => { const { sessionRecordingId, logicProps } = useValues(sessionRecordingPlayerLogic) const seekPlayerLogicProps: SessionRecordingPlayerLogicProps = { @@ -60,7 +68,7 @@ const PlayerSeekbarPreviewFrame = ({ ) } -export function PlayerSeekbarPreview({ minMs, maxMs, seekBarRef }: PlayerSeekbarPreviewProps): JSX.Element { +export function PlayerSeekbarPreview({ minMs, maxMs, seekBarRef, activeMs }: PlayerSeekbarPreviewProps): JSX.Element { const [percentage, setPercentage] = useState(0) const ref = useRef(null) const fixedUnits = maxMs / 1000 > 3600 ? 3 : 2 @@ -68,6 +76,10 @@ export function PlayerSeekbarPreview({ minMs, maxMs, seekBarRef }: PlayerSeekbar const isHovering = useIsHovering(seekBarRef) + const { featureFlags } = useValues(featureFlagLogic) + const alwaysShowSeekbarPreview = !!featureFlags[FEATURE_FLAGS.ALWAYS_SHOW_SEEKBAR_PREVIEW] + const canShowPreview = alwaysShowSeekbarPreview || (typeof activeMs === 'number' && activeMs < TWENTY_MINUTES_IN_MS) + useEffect(() => { if (!seekBarRef?.current) { return @@ -103,12 +115,14 @@ export function PlayerSeekbarPreview({ minMs, maxMs, seekBarRef }: PlayerSeekbar }} >
- + {canShowPreview && ( + + )}
{content}
diff --git a/frontend/src/scenes/session-recordings/player/controller/Seekbar.tsx b/frontend/src/scenes/session-recordings/player/controller/Seekbar.tsx index 670279f1f6d0c..3654cef52eb31 100644 --- a/frontend/src/scenes/session-recordings/player/controller/Seekbar.tsx +++ b/frontend/src/scenes/session-recordings/player/controller/Seekbar.tsx @@ -21,7 +21,7 @@ export function Seekbar(): JSX.Element { const { endTimeMs, thumbLeftPos, bufferPercent, isScrubbing } = useValues(seekbarLogic(logicProps)) const { handleDown, setSlider, setThumb } = useActions(seekbarLogic(logicProps)) - const { sessionPlayerData } = useValues(sessionRecordingDataLogic(logicProps)) + const { sessionPlayerData, sessionPlayerMetaData } = useValues(sessionRecordingDataLogic(logicProps)) const sliderRef = useRef(null) const thumbRef = useRef(null) @@ -80,7 +80,16 @@ export function Seekbar(): JSX.Element { style={{ transform: `translateX(${thumbLeftPos}px)` }} /> - + diff --git a/posthog/session_recordings/models/session_recording.py b/posthog/session_recordings/models/session_recording.py index 5ef51b34c2f1b..ca6bbc7b54d6e 100644 --- a/posthog/session_recordings/models/session_recording.py +++ b/posthog/session_recordings/models/session_recording.py @@ -84,7 +84,6 @@ def load_metadata(self) -> bool: self._metadata = metadata # Some fields of the metadata are persisted fully in the model - # TODO there is more metadata we can add here self.distinct_id = metadata["distinct_id"] self.start_time = metadata["start_time"] self.end_time = metadata["end_time"] @@ -92,6 +91,12 @@ def load_metadata(self) -> bool: self.click_count = metadata["click_count"] self.keypress_count = metadata["keypress_count"] self.set_start_url_from_urls(first_url=metadata["first_url"]) + self.mouse_activity_count = metadata["mouse_activity_count"] + self.active_seconds = metadata["active_seconds"] + self.inactive_seconds = metadata["duration"] - metadata["active_seconds"] + self.console_log_count = metadata["console_log_count"] + self.console_warn_count = metadata["console_warn_count"] + self.console_error_count = metadata["console_error_count"] return True diff --git a/posthog/session_recordings/test/test_session_recordings.py b/posthog/session_recordings/test/test_session_recordings.py index f1d1c22e9e98e..e349741ab1069 100644 --- a/posthog/session_recordings/test/test_session_recordings.py +++ b/posthog/session_recordings/test/test_session_recordings.py @@ -327,12 +327,12 @@ def test_get_single_session_recording_metadata(self): "click_count": 0, "keypress_count": 0, "start_url": None, - "mouse_activity_count": None, - "inactive_seconds": None, - "active_seconds": None, - "console_error_count": None, - "console_log_count": None, - "console_warn_count": None, + "mouse_activity_count": 0, + "inactive_seconds": 30, + "active_seconds": 0, + "console_error_count": 0, + "console_log_count": 0, + "console_warn_count": 0, "person": { "id": p.id, "name": "bob@bob.com",