diff --git a/frontend/src/scenes/session-recordings/player/PlayerMeta.tsx b/frontend/src/scenes/session-recordings/player/PlayerMeta.tsx
index ac22da5dca85a..bd87a15c6b11e 100644
--- a/frontend/src/scenes/session-recordings/player/PlayerMeta.tsx
+++ b/frontend/src/scenes/session-recordings/player/PlayerMeta.tsx
@@ -1,11 +1,14 @@
import './PlayerMeta.scss'
-import { Link } from '@posthog/lemon-ui'
+import { IconEllipsis, IconTrash } from '@posthog/icons'
+import { IconDownload, IconMagic, IconSearch } from '@posthog/icons'
+import { LemonButton, LemonDialog, LemonMenu, LemonMenuItems, Link } from '@posthog/lemon-ui'
import clsx from 'clsx'
-import { useValues } from 'kea'
+import { useActions, useValues } from 'kea'
import { CopyToClipboardInline } from 'lib/components/CopyToClipboard'
import { TZLabel } from 'lib/components/TZLabel'
import { dayjs } from 'lib/dayjs'
+import { useFeatureFlag } from 'lib/hooks/useFeatureFlag'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton'
import { ProfilePicture } from 'lib/lemon-ui/ProfilePicture'
@@ -23,6 +26,7 @@ import { getCurrentExporterData } from '~/exporter/exporterViewLogic'
import { Logo } from '~/toolbar/assets/Logo'
import { PlayerMetaLinks } from './PlayerMetaLinks'
+import { sessionRecordingDataLogic } from './sessionRecordingDataLogic'
import { sessionRecordingPlayerLogic, SessionRecordingPlayerMode } from './sessionRecordingPlayerLogic'
function SessionPropertyMeta(props: {
@@ -163,7 +167,7 @@ export function PlayerMeta(): JSX.Element {
>
@@ -206,7 +210,12 @@ export function PlayerMeta(): JSX.Element {
- {sessionRecordingId &&
)
}
+
+const MenuActions = (): JSX.Element => {
+ const { logicProps } = useValues(sessionRecordingPlayerLogic)
+ const { exportRecordingToFile, openExplorer, deleteRecording, setIsFullScreen } =
+ useActions(sessionRecordingPlayerLogic)
+ const { fetchSimilarRecordings } = useActions(sessionRecordingDataLogic(logicProps))
+
+ const hasMobileExport = useFeatureFlag('SESSION_REPLAY_EXPORT_MOBILE_DATA')
+ const hasSimilarRecordings = useFeatureFlag('REPLAY_SIMILAR_RECORDINGS')
+
+ const onDelete = (): void => {
+ setIsFullScreen(false)
+ LemonDialog.open({
+ title: 'Delete recording',
+ description: 'Are you sure you want to delete this recording? This cannot be undone.',
+ secondaryButton: {
+ children: 'Cancel',
+ },
+ primaryButton: {
+ children: 'Delete',
+ status: 'danger',
+ onClick: deleteRecording,
+ },
+ })
+ }
+
+ const items: LemonMenuItems = [
+ {
+ label: 'Export to file',
+ onClick: exportRecordingToFile,
+ icon:
,
+ tooltip: 'Export recording to a file. This can be loaded later into PostHog for playback.',
+ },
+ {
+ label: 'Explore DOM',
+ onClick: openExplorer,
+ icon:
,
+ },
+ hasMobileExport && {
+ label: 'Export mobile replay to file',
+ onClick: () => exportRecordingToFile(true),
+ tooltip:
+ 'DEBUG ONLY - Export untransformed recording to a file. This can be loaded later into PostHog for playback.',
+ icon:
,
+ },
+ hasSimilarRecordings && {
+ label: 'Find similar recordings',
+ onClick: fetchSimilarRecordings,
+ icon:
,
+ tooltip: 'DEBUG ONLY - Find similar recordings based on distance calculations via embeddings.',
+ },
+ logicProps.playerKey !== 'modal' && {
+ label: 'Delete recording',
+ status: 'danger',
+ onClick: onDelete,
+ icon:
,
+ },
+ ]
+
+ return (
+
+ } />
+
+ )
+}
diff --git a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
index 04bcabe5b9878..4446dd11c985f 100644
--- a/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
+++ b/frontend/src/scenes/session-recordings/player/PlayerMetaLinks.tsx
@@ -1,9 +1,8 @@
-import { IconNotebook, IconPin, IconPinFilled, IconTrash } from '@posthog/icons'
+import { IconNotebook, IconPin, IconPinFilled } from '@posthog/icons'
import { useActions, useValues } from 'kea'
import { FEATURE_FLAGS } from 'lib/constants'
import { IconComment, IconLink } from 'lib/lemon-ui/icons'
import { LemonButton, LemonButtonProps } from 'lib/lemon-ui/LemonButton'
-import { LemonDialog } from 'lib/lemon-ui/LemonDialog'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { useNotebookNode } from 'scenes/notebooks/Nodes/NotebookNodeContext'
import { NotebookSelectButton } from 'scenes/notebooks/NotebookSelectButton/NotebookSelectButton'
@@ -57,7 +56,7 @@ function PinToPlaylistButton(): JSX.Element {
export function PlayerMetaLinks(): JSX.Element {
const { sessionRecordingId, logicProps } = useValues(sessionRecordingPlayerLogic)
- const { setPause, deleteRecording, setIsFullScreen } = useActions(sessionRecordingPlayerLogic)
+ const { setPause, setIsFullScreen } = useActions(sessionRecordingPlayerLogic)
const nodeLogic = useNotebookNode()
const { closeSessionPlayer } = useActions(sessionPlayerModalLogic())
@@ -76,22 +75,6 @@ export function PlayerMetaLinks(): JSX.Element {
})
}
- const onDelete = (): void => {
- setIsFullScreen(false)
- LemonDialog.open({
- title: 'Delete recording',
- description: 'Are you sure you want to delete this recording? This cannot be undone.',
- secondaryButton: {
- children: 'Cancel',
- },
- primaryButton: {
- children: 'Delete',
- status: 'danger',
- onClick: deleteRecording,
- },
- })
- }
-
const commonProps: Partial
= {
size: 'small',
}
@@ -149,16 +132,6 @@ export function PlayerMetaLinks(): JSX.Element {
) : null}
-
- {logicProps.playerKey !== 'modal' && (
- }
- onClick={onDelete}
- {...commonProps}
- status="danger"
- />
- )}
>
) : null}
diff --git a/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx b/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx
index cd9ab52174438..df5bf7e2a280e 100644
--- a/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx
+++ b/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx
@@ -1,38 +1,29 @@
-import { IconDownload, IconMagic, IconPlay, IconSearch } from '@posthog/icons'
+import { IconPlay } from '@posthog/icons'
import { LemonMenu } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useActions, useValues } from 'kea'
-import { FlaggedFeature } from 'lib/components/FlaggedFeature'
-import { FEATURE_FLAGS } from 'lib/constants'
import { IconFullScreen, IconPause, IconSkipInactivity } from 'lib/lemon-ui/icons'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
-import { More } from 'lib/lemon-ui/LemonButton/More'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import {
PLAYBACK_SPEEDS,
sessionRecordingPlayerLogic,
- SessionRecordingPlayerMode,
} from 'scenes/session-recordings/player/sessionRecordingPlayerLogic'
import { KeyboardShortcut } from '~/layout/navigation-3000/components/KeyboardShortcut'
import { SessionPlayerState } from '~/types'
import { playerSettingsLogic } from '../playerSettingsLogic'
-import { sessionRecordingDataLogic } from '../sessionRecordingDataLogic'
import { SeekSkip, Timestamp } from './PlayerControllerTime'
import { Seekbar } from './Seekbar'
export function PlayerController(): JSX.Element {
- const { playingState, logicProps, isFullScreen } = useValues(sessionRecordingPlayerLogic)
- const { togglePlayPause, exportRecordingToFile, openExplorer, setIsFullScreen } =
- useActions(sessionRecordingPlayerLogic)
- const { fetchSimilarRecordings } = useActions(sessionRecordingDataLogic(logicProps))
+ const { playingState, isFullScreen } = useValues(sessionRecordingPlayerLogic)
+ const { togglePlayPause, setIsFullScreen } = useActions(sessionRecordingPlayerLogic)
const { speed, skipInactivitySetting } = useValues(playerSettingsLogic)
const { setSpeed, setSkipInactivitySetting } = useActions(playerSettingsLogic)
- const mode = logicProps.mode ?? SessionRecordingPlayerMode.Standard
-
const showPause = playingState === SessionPlayerState.PLAY
return (
@@ -105,49 +96,6 @@ export function PlayerController(): JSX.Element {
/>
-
- {mode === SessionRecordingPlayerMode.Standard && (
-