diff --git a/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js index 0e4fc98d1..ee90a5e35 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js +++ b/dashboard-ui/bower_components/emby-webcomponents/listview/listview.js @@ -142,6 +142,20 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan return html; } + function getRightButtonsHtml(options) { + + var html = ''; + + for (var i = 0, length = options.rightButtons.length; i < length; i++) { + + var button = options.rightButtons[i]; + + html += ''; + } + + return html; + } + function getListViewHtml(options) { var items = options.items; @@ -406,9 +420,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan html += ''; } - if (options.recordButton) { - - html += ''; + if (options.rightButtons) { + html += getRightButtonsHtml(options); } if (options.enableUserDataButtons !== false) { diff --git a/dashboard-ui/bower_components/emby-webcomponents/playback/playbackmanager.js b/dashboard-ui/bower_components/emby-webcomponents/playback/playbackmanager.js index 7e2390429..ec6f7240a 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/playback/playbackmanager.js +++ b/dashboard-ui/bower_components/emby-webcomponents/playback/playbackmanager.js @@ -2215,7 +2215,12 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g } } - self.setCurrentPlaylistIndex = function (i) { + self.setCurrentPlaylistIndex = function (i, player) { + + player = player || currentPlayer; + if (player && !enableLocalPlaylistManagement(player)) { + return player.setCurrentPlaylistIndex(i); + } var newItem = playlist[i]; @@ -2228,7 +2233,43 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g }); }; - self.getCurrentPlaylistIndex = function (i) { + self.removeFromPlaylist = function (index, player) { + + if (index < 0) { + throw new Error('Invalid playlist index'); + } + + player = player || currentPlayer; + if (player && !enableLocalPlaylistManagement(player)) { + return player.removeFromPlaylist(i); + } + + if (playlist.length <= 1) { + return self.stop(); + } + + var isCurrentIndex = self.getCurrentPlaylistIndex(player) === index; + + playlist.splice(index, 1); + + events.trigger(player, 'playlistitemremove', [ + { + index: index + }]); + + if (isCurrentIndex) { + return self.setCurrentPlaylistIndex(Math.min(index, playlist.length - 1), player); + } + + return Promise.resolve(); + }; + + self.getCurrentPlaylistIndex = function (i, player) { + + player = player || currentPlayer; + if (player && !enableLocalPlaylistManagement(player)) { + return player.getCurrentPlaylistIndex(); + } return currentPlaylistIndex; }; @@ -2241,7 +2282,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g } repeatMode = value; - events.trigger(self, 'repeatmodechange'); + events.trigger(player, 'repeatmodechange'); }; self.getRepeatMode = function (player) { diff --git a/dashboard-ui/bower_components/emby-webcomponents/shortcuts.js b/dashboard-ui/bower_components/emby-webcomponents/shortcuts.js index 70d0bf10d..29dacc278 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/shortcuts.js +++ b/dashboard-ui/bower_components/emby-webcomponents/shortcuts.js @@ -330,6 +330,20 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'embyRouter', 'g else if (action === 'addtoplaylist') { getItem(target).then(addToPlaylist); } + + else if (action === 'custom') { + + var customAction = target.getAttribute('data-customaction'); + + card.dispatchEvent(new CustomEvent('action-' + customAction, { + detail: { + item: getItem(target), + index: parseInt(card.getAttribute('data-index') || '-1') + }, + cancelable: false, + bubbles: true + })); + } } function addToPlaylist(item) { diff --git a/dashboard-ui/components/remotecontrol.js b/dashboard-ui/components/remotecontrol.js index 0c0294be9..cb47d3750 100644 --- a/dashboard-ui/components/remotecontrol.js +++ b/dashboard-ui/components/remotecontrol.js @@ -262,13 +262,11 @@ var self = this; var playlistNeedsRefresh = true; - var isEnabled; function toggleRepeat(player) { - - if (player && lastPlayerState) { - var state = lastPlayerState; - switch ((state.PlayState || {}).RepeatMode) { + + if (player) { + switch (playbackManager.getRepeatMode(player)) { case 'RepeatNone': playbackManager.setRepeatMode('RepeatAll', player); break; @@ -329,21 +327,26 @@ context.classList.add('hideVideoButtons'); } + updateRepeatModeDisplay(playState.RepeatMode); + updateNowPlayingInfo(context, state); + } + + function updateRepeatModeDisplay(repeatMode) { + + var context = dlg; var toggleRepeatButton = context.querySelector('.repeatToggleButton'); - if (playState.RepeatMode == 'RepeatAll') { + if (repeatMode == 'RepeatAll') { toggleRepeatButton.innerHTML = "repeat"; toggleRepeatButton.classList.add('nowPlayingPageRepeatActive'); } - else if (playState.RepeatMode == 'RepeatOne') { + else if (repeatMode == 'RepeatOne') { toggleRepeatButton.innerHTML = "repeat_one"; toggleRepeatButton.classList.add('nowPlayingPageRepeatActive'); } else { toggleRepeatButton.innerHTML = "repeat"; toggleRepeatButton.classList.remove('nowPlayingPageRepeatActive'); } - - updateNowPlayingInfo(context, state); } function updatePlayerVolumeState(context, isMuted, volumeLevel) { @@ -471,14 +474,20 @@ function loadPlaylist(context, player) { getPlaylistItems(player).then(function (items) { - + var html = ''; html += listView.getListViewHtml({ items: items, smallIcon: true, action: 'setplaylistindex', - enableUserDataButtons: false + enableUserDataButtons: false, + rightButtons: [ + { + icon: '', + title: globalize.translate('ButtonRemove'), + id: 'remove' + }] }); playlistNeedsRefresh = false; @@ -514,6 +523,23 @@ loadPlaylist(dlg, player); } + function onRepeatModeChange(e) { + + var player = this; + + updateRepeatModeDisplay(playbackManager.getRepeatMode(player)); + } + + function onPlaylistUpdate(e) { + + var player = this; + + playbackManager.getPlayerState(player).then(function (state) { + + onStateChanged.call(player, { type: 'init' }, state); + }); + } + function onPlaybackStopped(e, state) { console.log('remotecontrol event: ' + e.type); @@ -568,7 +594,8 @@ events.off(player, 'playbackstart', onPlaybackStart); events.off(player, 'statechange', onPlaybackStart); - events.off(player, 'repeatmodechange', onPlaybackStart); + events.off(player, 'repeatmodechange', onRepeatModeChange); + events.off(player, 'playlistitemremove', onPlaylistUpdate); events.off(player, 'playbackstop', onPlaybackStopped); events.off(player, 'volumechange', onVolumeChanged); events.off(player, 'pause', onPlayPauseStateChanged); @@ -596,9 +623,8 @@ events.on(player, 'playbackstart', onPlaybackStart); events.on(player, 'statechange', onPlaybackStart); - // TODO: Replace this with smaller changes on repeatmodechange. - // For now go cheap and just refresh the entire component - events.on(player, 'repeatmodechange', onPlaybackStart); + events.on(player, 'repeatmodechange', onRepeatModeChange); + events.on(player, 'playlistitemremove', onPlaylistUpdate); events.on(player, 'playbackstop', onPlaybackStopped); events.on(player, 'volumechange', onVolumeChanged); events.on(player, 'pause', onPlayPauseStateChanged); @@ -740,6 +766,10 @@ playbackManager.toggleMute(currentPlayer); }); + context.querySelector('.playlist').addEventListener('action-remove', function (e) { + + playbackManager.removeFromPlaylist(e.detail.index, currentPlayer); + }); } function onPlayerChange() { diff --git a/dashboard-ui/scripts/nowplayingbar.js b/dashboard-ui/scripts/nowplayingbar.js index 09edcf170..0edbe2bf5 100644 --- a/dashboard-ui/scripts/nowplayingbar.js +++ b/dashboard-ui/scripts/nowplayingbar.js @@ -188,9 +188,8 @@ toggleRepeatButton.addEventListener('click', function () { if (currentPlayer) { - var state = lastPlayerState || {}; - switch ((state.PlayState || {}).RepeatMode) { + switch (playbackManager.getRepeatMode(currentPlayer)) { case 'RepeatAll': playbackManager.setRepeatMode('RepeatOne', currentPlayer); break; @@ -344,17 +343,7 @@ toggleRepeatButton.classList.remove('hide'); } - if (playState.RepeatMode == 'RepeatAll') { - toggleRepeatButtonIcon.innerHTML = "repeat"; - toggleRepeatButton.classList.add('repeatActive'); - } - else if (playState.RepeatMode == 'RepeatOne') { - toggleRepeatButtonIcon.innerHTML = "repeat_one"; - toggleRepeatButton.classList.add('repeatActive'); - } else { - toggleRepeatButtonIcon.innerHTML = "repeat"; - toggleRepeatButton.classList.remove('repeatActive'); - } + updateRepeatModeDisplay(playState.RepeatMode); updatePlayerVolumeState(playState.IsMuted, playState.VolumeLevel); @@ -368,6 +357,21 @@ updateNowPlayingInfo(state); } + function updateRepeatModeDisplay(repeatMode) { + + if (repeatMode == 'RepeatAll') { + toggleRepeatButtonIcon.innerHTML = "repeat"; + toggleRepeatButton.classList.add('repeatActive'); + } + else if (repeatMode == 'RepeatOne') { + toggleRepeatButtonIcon.innerHTML = "repeat_one"; + toggleRepeatButton.classList.add('repeatActive'); + } else { + toggleRepeatButtonIcon.innerHTML = "repeat"; + toggleRepeatButton.classList.remove('repeatActive'); + } + } + function updateTimeDisplay(positionTicks, runtimeTicks) { // See bindEvents for why this is necessary @@ -576,6 +580,13 @@ onStateChanged.call(player, e, state); } + function onRepeatModeChange(e) { + + var player = this; + + updateRepeatModeDisplay(playbackManager.getRepeatMode(player)); + } + function showNowPlayingBar() { getNowPlayingBar().then(slideUp); @@ -681,7 +692,7 @@ if (player) { events.off(player, 'playbackstart', onPlaybackStart); events.off(player, 'statechange', onPlaybackStart); - events.off(player, 'repeatmodechange', onPlaybackStart); + events.off(player, 'repeatmodechange', onRepeatModeChange); events.off(player, 'playbackstop', onPlaybackStopped); events.off(player, 'volumechange', onVolumeChanged); events.off(player, 'pause', onPlayPauseStateChanged); @@ -725,9 +736,7 @@ events.on(player, 'playbackstart', onPlaybackStart); events.on(player, 'statechange', onPlaybackStart); - // TODO: Replace this with smaller changes on repeatmodechange. - // For now go cheap and just refresh the entire component - events.on(player, 'repeatmodechange', onPlaybackStart); + events.on(player, 'repeatmodechange', onRepeatModeChange); events.on(player, 'playbackstop', onPlaybackStopped); events.on(player, 'volumechange', onVolumeChanged); events.on(player, 'pause', onPlayPauseStateChanged);