diff --git a/frontend/src/lib/components/Playlist/Playlist.tsx b/frontend/src/lib/components/Playlist/Playlist.tsx index ebdc7b3b710cb..88a9541fb869d 100644 --- a/frontend/src/lib/components/Playlist/Playlist.tsx +++ b/frontend/src/lib/components/Playlist/Playlist.tsx @@ -7,7 +7,7 @@ import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver' import { IconChevronRight } from 'lib/lemon-ui/icons' import { LemonTableLoader } from 'lib/lemon-ui/LemonTable/LemonTableLoader' import { range } from 'lib/utils' -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { DraggableToNotebook } from 'scenes/notebooks/AddToNotebook/DraggableToNotebook' import { Resizer } from '../Resizer/Resizer' @@ -40,6 +40,7 @@ export type PlaylistProps = { onChangeSections?: (activeKeys: string[]) => void 'data-attr'?: string activeItemId?: string + isCollapsed?: boolean } const CounterBadge = ({ @@ -79,12 +80,23 @@ export function Playlist< selectInitialItem, onSelect, onChangeSections, + isCollapsed = false, 'data-attr': dataAttr, }: PlaylistProps): JSX.Element { const [controlledActiveItemId, setControlledActiveItemId] = useState( selectInitialItem && sections[0].items[0] ? sections[0].items[0].id : null ) - const [listCollapsed, setListCollapsed] = useState(false) + const [listCollapsed, setListCollapsed] = useState(isCollapsed) + useEffect( + () => { + if (isCollapsed !== listCollapsed) { + setListCollapsed(isCollapsed) + } + }, + // purposefully only isCollapsed in dependencies + // eslint-disable-next-line react-hooks/exhaustive-deps + [isCollapsed] + ) const playlistListRef = useRef(null) const { ref: playlistRef, size } = useResizeBreakpoints({ 0: 'small', diff --git a/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx b/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx index bc723da0a8660..ed5b43713bba9 100644 --- a/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx +++ b/frontend/src/scenes/session-recordings/player/controller/PlayerController.tsx @@ -1,6 +1,7 @@ -import { IconPause, IconPlay, IconSearch } from '@posthog/icons' +import { IconCollapse45, IconExpand45, IconPause, IconPlay, IconSearch } from '@posthog/icons' import clsx from 'clsx' import { useActions, useValues } from 'kea' +import { useKeyboardHotkeys } from 'lib/hooks/useKeyboardHotkeys' import { IconFullScreen, IconSync } from 'lib/lemon-ui/icons' import { LemonButton } from 'lib/lemon-ui/LemonButton' import { SettingsMenu, SettingsToggle } from 'scenes/session-recordings/components/PanelSettings' @@ -136,6 +137,37 @@ function FullScreen(): JSX.Element { ) } +function Maximise(): JSX.Element { + const { sidebarOpen, playlistOpen } = useValues(playerSettingsLogic) + const { setSidebarOpen, setPlaylistOpen } = useActions(playerSettingsLogic) + + const isMaximised = !sidebarOpen && !playlistOpen + + function onChangeMaximise(): void { + setPlaylistOpen(isMaximised) + setSidebarOpen(isMaximised) + } + + useKeyboardHotkeys( + { + m: { + action: onChangeMaximise, + }, + }, + [] + ) + + return ( + : } + className="text-2xl" + /> + ) +} + export function PlayerController(): JSX.Element { return (
@@ -150,7 +182,8 @@ export function PlayerController(): JSX.Element {
-
+
+
diff --git a/frontend/src/scenes/session-recordings/player/playerSettingsLogic.ts b/frontend/src/scenes/session-recordings/player/playerSettingsLogic.ts index 878114a931c28..98958a186e51b 100644 --- a/frontend/src/scenes/session-recordings/player/playerSettingsLogic.ts +++ b/frontend/src/scenes/session-recordings/player/playerSettingsLogic.ts @@ -32,6 +32,7 @@ export const playerSettingsLogic = kea([ setPreferredSidebarStacking: (stacking: SessionRecordingSidebarStacking) => ({ stacking }), setPlaybackMode: (mode: PlaybackMode) => ({ mode }), setSidebarOpen: (open: boolean) => ({ open }), + setPlaylistOpen: (open: boolean) => ({ open }), setShowMouseTail: (showMouseTail: boolean) => ({ showMouseTail }), }), connect({ @@ -40,6 +41,7 @@ export const playerSettingsLogic = kea([ reducers(({ values }) => ({ showFilters: [true, { persist: true }, { setShowFilters: (_, { showFilters }) => showFilters }], sidebarOpen: [false, { persist: true }, { setSidebarOpen: (_, { open }) => open }], + playlistOpen: [true, { setPlaylistOpen: (_, { open }) => open }], preferredSidebarStacking: [ SessionRecordingSidebarStacking.Horizontal as SessionRecordingSidebarStacking, { persist: true }, diff --git a/frontend/src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx b/frontend/src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx index 1035ac77e766f..cb0864f30131a 100644 --- a/frontend/src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx +++ b/frontend/src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx @@ -7,6 +7,7 @@ import { FEATURE_FLAGS } from 'lib/constants' import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { useNotebookNode } from 'scenes/notebooks/Nodes/NotebookNodeContext' +import { playerSettingsLogic } from 'scenes/session-recordings/player/playerSettingsLogic' import { urls } from 'scenes/urls' import { ReplayTabs, SessionRecordingType } from '~/types' @@ -47,6 +48,8 @@ export function SessionRecordingsPlaylist(props: SessionRecordingPlaylistLogicPr const pinnedDescription = isTestingSaved ? 'Saved' : 'Pinned' + const { playlistOpen } = useValues(playerSettingsLogic) + const notebookNode = useNotebookNode() const sections: PlaylistSection[] = [] @@ -92,6 +95,7 @@ export function SessionRecordingsPlaylist(props: SessionRecordingPlaylistLogicPr )}