Просмотр исходного кода

Alternative fix to detecting when to stop a playlist, fixes #15701 and #15702

Torkel Ödegaard 6 лет назад
Родитель
Сommit
3375c72d56

+ 23 - 2
public/app/features/playlist/playlist_srv.ts

@@ -7,6 +7,7 @@ import coreModule from '../../core/core_module';
 import appEvents from 'app/core/app_events';
 import locationUtil from 'app/core/utils/location_util';
 import kbn from 'app/core/utils/kbn';
+import { store } from 'app/store/store';
 
 export class PlaylistSrv {
   private cancelPromise: any;
@@ -15,6 +16,8 @@ export class PlaylistSrv {
   private interval: number;
   private startUrl: string;
   private numberOfLoops = 0;
+  private storeUnsub: () => void;
+  private validPlaylistUrl: string;
   isPlaying: boolean;
 
   /** @ngInject */
@@ -39,15 +42,16 @@ export class PlaylistSrv {
     const dash = this.dashboards[this.index];
     const queryParams = this.$location.search();
     const filteredParams = _.pickBy(queryParams, value => value !== null);
+    const nextDashboardUrl = locationUtil.stripBaseFromUrl(dash.url);
 
     // this is done inside timeout to make sure digest happens after
     // as this can be called from react
     this.$timeout(() => {
-      const stripedUrl = locationUtil.stripBaseFromUrl(dash.url);
-      this.$location.url(stripedUrl + '?' + toUrlParams(filteredParams));
+      this.$location.url(nextDashboardUrl + '?' + toUrlParams(filteredParams));
     });
 
     this.index++;
+    this.validPlaylistUrl = nextDashboardUrl;
     this.cancelPromise = this.$timeout(() => this.next(), this.interval);
   }
 
@@ -56,6 +60,15 @@ export class PlaylistSrv {
     this.next();
   }
 
+  // Detect url changes not caused by playlist srv and stop playlist
+  storeUpdated() {
+    const state = store.getState();
+
+    if (state.location.path !== this.validPlaylistUrl) {
+      this.stop();
+    }
+  }
+
   start(playlistId) {
     this.stop();
 
@@ -63,6 +76,10 @@ export class PlaylistSrv {
     this.index = 0;
     this.isPlaying = true;
 
+    // setup location tracking
+    this.storeUnsub = store.subscribe(() => this.storeUpdated());
+    this.validPlaylistUrl = this.$location.path();
+
     appEvents.emit('playlist-started');
 
     return this.backendSrv.get(`/api/playlists/${playlistId}`).then(playlist => {
@@ -85,6 +102,10 @@ export class PlaylistSrv {
     this.index = 0;
     this.isPlaying = false;
 
+    if (this.storeUnsub) {
+      this.storeUnsub();
+    }
+
     if (this.cancelPromise) {
       this.$timeout.cancel(this.cancelPromise);
     }

+ 39 - 0
public/app/features/playlist/specs/playlist_srv.test.ts

@@ -1,4 +1,14 @@
+import configureMockStore from 'redux-mock-store';
 import { PlaylistSrv } from '../playlist_srv';
+import { setStore } from 'app/store/store';
+
+const mockStore = configureMockStore();
+
+setStore(
+  mockStore({
+    location: {},
+  })
+);
 
 const dashboards = [{ url: 'dash1' }, { url: 'dash2' }];
 
@@ -19,6 +29,7 @@ const createPlaylistSrv = (): [PlaylistSrv, { url: jest.MockInstance<any, any> }
   const mockLocation = {
     url: jest.fn(),
     search: () => ({}),
+    path: () => '/playlists/1',
   };
 
   const mockTimeout = jest.fn();
@@ -96,4 +107,32 @@ describe('PlaylistSrv', () => {
     expect(hrefMock).toHaveBeenCalledTimes(3);
     expect(hrefMock).toHaveBeenLastCalledWith(initialUrl);
   });
+
+  it('storeUpdated should stop playlist when navigating away', async () => {
+    await srv.start(1);
+
+    srv.storeUpdated();
+
+    expect(srv.isPlaying).toBe(false);
+  });
+
+  it('storeUpdated should not stop playlist when navigating to next dashboard', async () => {
+    await srv.start(1);
+
+    srv.next();
+
+    setStore(
+      mockStore({
+        location: {
+          path: 'dash2',
+        },
+      })
+    );
+
+    expect((srv as any).validPlaylistUrl).toBe('dash2');
+
+    srv.storeUpdated();
+
+    expect(srv.isPlaying).toBe(true);
+  });
 });