From 8a988d6b5a148d4374c5eb158bf295c563f53daf Mon Sep 17 00:00:00 2001 From: Ezequiel Victorero Date: Thu, 27 Feb 2025 09:14:37 -0300 Subject: [PATCH] Playlists: Add support for back button (#101374) --- .../app/features/playlist/PlaylistSrv.test.ts | 26 ++++++++++++- public/app/features/playlist/PlaylistSrv.ts | 38 +++++++++++++------ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/public/app/features/playlist/PlaylistSrv.test.ts b/public/app/features/playlist/PlaylistSrv.test.ts index 687b5e39156..3620f3a1e02 100644 --- a/public/app/features/playlist/PlaylistSrv.test.ts +++ b/public/app/features/playlist/PlaylistSrv.test.ts @@ -1,4 +1,3 @@ -// @ts-ignore import { Store } from 'redux'; import configureMockStore from 'redux-mock-store'; @@ -139,4 +138,29 @@ describe('PlaylistSrv', () => { expect((srv as any).validPlaylistUrl).toBe('/url/to/bbb'); expect(srv.state.isPlaying).toBe(true); }); + + it('should replace playlist start page in history when starting playlist', async () => { + // Start at playlists page + locationService.push('/playlists'); + + // Navigate to playlist start page + locationService.push('/playlists/play/foo'); + + // Start the playlist + await srv.start('foo'); + + // Get history entries + const history = locationService.getHistory(); + const entries = (history as unknown as { entries: Location[] }).entries; + + // The current entry should be the first dashboard + expect(entries[entries.length - 1].pathname).toBe('/url/to/aaa'); + + // The previous entry should be the playlists page, not the start page + expect(entries[entries.length - 2].pathname).toBe('/playlists'); + + // Verify the start page (/playlists/play/foo) is not in history + const hasStartPage = entries.some((entry: { pathname: string }) => entry.pathname === '/playlists/play/foo'); + expect(hasStartPage).toBe(false); + }); }); diff --git a/public/app/features/playlist/PlaylistSrv.ts b/public/app/features/playlist/PlaylistSrv.ts index d11f817a369..99b839c857c 100644 --- a/public/app/features/playlist/PlaylistSrv.ts +++ b/public/app/features/playlist/PlaylistSrv.ts @@ -39,6 +39,28 @@ export class PlaylistSrv extends StateManagerBase { this.api = getPlaylistAPI(); } + private navigateToDashboard(replaceHistoryEntry = false) { + const url = this.urls[this.index]; + const queryParams = locationService.getSearchObject(); + const filteredParams = pickBy(queryParams, (value: unknown, key: string) => queryParamsToPreserve[key]); + const nextDashboardUrl = locationUtil.stripBaseFromUrl(url); + + this.index++; + this.validPlaylistUrl = nextDashboardUrl; + this.nextTimeoutId = setTimeout(() => this.next(), this.interval); + + const urlWithParams = nextDashboardUrl + '?' + urlUtil.toUrlParams(filteredParams); + + // When starting the playlist from the PlaylistStartPage component using the playlist URL, we want to replace the + // history entry to support the back button + // When starting the playlist from the playlist modal, we want to push a new history entry + if (replaceHistoryEntry) { + locationService.getHistory().replace(urlWithParams); + } else { + locationService.push(urlWithParams); + } + } + next() { clearTimeout(this.nextTimeoutId); @@ -55,16 +77,7 @@ export class PlaylistSrv extends StateManagerBase { this.index = 0; } - const url = this.urls[this.index]; - const queryParams = locationService.getSearchObject(); - const filteredParams = pickBy(queryParams, (value: unknown, key: string) => queryParamsToPreserve[key]); - const nextDashboardUrl = locationUtil.stripBaseFromUrl(url); - - this.index++; - this.validPlaylistUrl = nextDashboardUrl; - this.nextTimeoutId = setTimeout(() => this.next(), this.interval); - - locationService.push(nextDashboardUrl + '?' + urlUtil.toUrlParams(filteredParams)); + this.navigateToDashboard(); } prev() { @@ -115,7 +128,10 @@ export class PlaylistSrv extends StateManagerBase { this.urls = urls; this.setState({ isPlaying: true }); - this.next(); + + // Replace current history entry with first dashboard instead of pushing + // this is to avoid the back button to go back to the playlist start page which causes a redirection + this.navigateToDashboard(true); return; }