mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Add:Buttons to add/remove podcast episodes from player queue
This commit is contained in:
		
							parent
							
								
									92e3e0ef6e
								
							
						
					
					
						commit
						3357ccfaf3
					
				@ -159,8 +159,8 @@ export default {
 | 
				
			|||||||
        return i.libraryItemId === libraryItemId
 | 
					        return i.libraryItemId === libraryItemId
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      if (currentQueueIndex < 0) {
 | 
					      if (currentQueueIndex < 0) {
 | 
				
			||||||
        console.error('Media finished not found in queue', this.playerQueueItems)
 | 
					        console.error('Media finished not found in queue - using first in queue', this.playerQueueItems)
 | 
				
			||||||
        return
 | 
					        currentQueueIndex = -1
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (currentQueueIndex === this.playerQueueItems.length - 1) {
 | 
					      if (currentQueueIndex === this.playerQueueItems.length - 1) {
 | 
				
			||||||
        console.log('Finished last item in queue')
 | 
					        console.log('Finished last item in queue')
 | 
				
			||||||
 | 
				
			|||||||
@ -324,8 +324,18 @@ export default {
 | 
				
			|||||||
      if (this.recentEpisode) return false // Dont show podcast error on episode card
 | 
					      if (this.recentEpisode) return false // Dont show podcast error on episode card
 | 
				
			||||||
      return this.numInvalidAudioFiles || this.numMissingParts || this.isMissing || this.isInvalid
 | 
					      return this.numInvalidAudioFiles || this.numMissingParts || this.isMissing || this.isInvalid
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    libraryItemIdStreaming() {
 | 
				
			||||||
 | 
					      return this.store.getters['getLibraryItemIdStreaming']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    isStreaming() {
 | 
					    isStreaming() {
 | 
				
			||||||
      return this.store.getters['getlibraryItemIdStreaming'] === this.libraryItemId
 | 
					      return this.libraryItemIdStreaming === this.libraryItemId
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    isQueued() {
 | 
				
			||||||
 | 
					      const episodeId = this.recentEpisode ? this.recentEpisode.id : null
 | 
				
			||||||
 | 
					      return this.store.getters['getIsMediaQueued'](this.libraryItemId, episodeId)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    isStreamingFromDifferentLibrary() {
 | 
				
			||||||
 | 
					      return this.store.getters['getIsStreamingFromDifferentLibrary']
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    showReadButton() {
 | 
					    showReadButton() {
 | 
				
			||||||
      return !this.isSelectionMode && !this.showPlayButton && this.hasEbook && (this.showExperimentalFeatures || this.enableEReader)
 | 
					      return !this.isSelectionMode && !this.showPlayButton && this.hasEbook && (this.showExperimentalFeatures || this.enableEReader)
 | 
				
			||||||
@ -408,6 +418,19 @@ export default {
 | 
				
			|||||||
            text: this.$strings.ButtonRemoveFromContinueListening
 | 
					            text: this.$strings.ButtonRemoveFromContinueListening
 | 
				
			||||||
          })
 | 
					          })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.libraryItemIdStreaming && !this.isStreamingFromDifferentLibrary) {
 | 
				
			||||||
 | 
					          if (!this.isQueued) {
 | 
				
			||||||
 | 
					            items.push({
 | 
				
			||||||
 | 
					              func: 'addToQueue',
 | 
				
			||||||
 | 
					              text: this.$strings.ButtonQueueAddItem
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          } else if (!this.isStreaming) {
 | 
				
			||||||
 | 
					            items.push({
 | 
				
			||||||
 | 
					              func: 'removeFromQueue',
 | 
				
			||||||
 | 
					              text: this.$strings.ButtonQueueRemoveItem
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return items
 | 
					        return items
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -666,6 +689,25 @@ export default {
 | 
				
			|||||||
          this.processing = false
 | 
					          this.processing = false
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    addToQueue() {
 | 
				
			||||||
 | 
					      if (this.recentEpisode) {
 | 
				
			||||||
 | 
					        const queueItem = {
 | 
				
			||||||
 | 
					          libraryItemId: this.libraryItemId,
 | 
				
			||||||
 | 
					          libraryId: this.libraryId,
 | 
				
			||||||
 | 
					          episodeId: this.recentEpisode.id,
 | 
				
			||||||
 | 
					          title: this.recentEpisode.title,
 | 
				
			||||||
 | 
					          subtitle: this.mediaMetadata.title,
 | 
				
			||||||
 | 
					          caption: this.recentEpisode.publishedAt ? `Published ${this.$formatDate(this.recentEpisode.publishedAt, 'MMM do, yyyy')}` : 'Unknown publish date',
 | 
				
			||||||
 | 
					          duration: this.recentEpisode.audioFile.duration || null,
 | 
				
			||||||
 | 
					          coverPath: this.media.coverPath || null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.store.commit('addItemToQueue', queueItem)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    removeFromQueue() {
 | 
				
			||||||
 | 
					      const episodeId = this.recentEpisode ? this.recentEpisode.id : null
 | 
				
			||||||
 | 
					      this.store.commit('removeItemFromQueue', { libraryItemId: this.libraryItemId, episodeId })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    openCollections() {
 | 
					    openCollections() {
 | 
				
			||||||
      this.store.commit('setSelectedLibraryItem', this.libraryItem)
 | 
					      this.store.commit('setSelectedLibraryItem', this.libraryItem)
 | 
				
			||||||
      this.store.commit('globals/setShowCollectionsModal', true)
 | 
					      this.store.commit('globals/setShowCollectionsModal', true)
 | 
				
			||||||
@ -761,6 +803,7 @@ export default {
 | 
				
			|||||||
              if (!podcastProgress || !podcastProgress.isFinished) {
 | 
					              if (!podcastProgress || !podcastProgress.isFinished) {
 | 
				
			||||||
                queueItems.push({
 | 
					                queueItems.push({
 | 
				
			||||||
                  libraryItemId: this.libraryItemId,
 | 
					                  libraryItemId: this.libraryItemId,
 | 
				
			||||||
 | 
					                  libraryId: this.libraryId,
 | 
				
			||||||
                  episodeId: episode.id,
 | 
					                  episodeId: episode.id,
 | 
				
			||||||
                  title: episode.title,
 | 
					                  title: episode.title,
 | 
				
			||||||
                  subtitle: this.mediaMetadata.title,
 | 
					                  subtitle: this.mediaMetadata.title,
 | 
				
			||||||
 | 
				
			|||||||
@ -59,11 +59,7 @@ export default {
 | 
				
			|||||||
      this.show = false
 | 
					      this.show = false
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    removeItem(item) {
 | 
					    removeItem(item) {
 | 
				
			||||||
      const updatedQueue = this.playerQueueItems.filter((i) => {
 | 
					      this.$store.commit('removeItemFromQueue', item)
 | 
				
			||||||
        if (!i.episodeId) return i.libraryItemId !== item.libraryItemId
 | 
					 | 
				
			||||||
        return i.libraryItemId !== item.libraryItemId || i.episodeId !== item.episodeId
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      this.$store.commit('setPlayerQueueItems', updatedQueue)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@
 | 
				
			|||||||
        </ui-tooltip>
 | 
					        </ui-tooltip>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <button v-if="playerQueueItems.length" class="outline-none text-gray-300 mx-1 lg:mx-2 hover:text-white" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showPlayerQueueItems')">
 | 
					        <button v-if="playerQueueItems.length" class="outline-none text-gray-300 mx-1 lg:mx-2 hover:text-white" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showPlayerQueueItems')">
 | 
				
			||||||
          <span class="material-icons text-2xl sm:text-3xl">playlist_play</span>
 | 
					          <span class="material-icons text-2xl sm:text-3xl">queue_music</span>
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,10 @@
 | 
				
			|||||||
            <p class="pl-2 pr-1 text-sm font-semibold">{{ timeRemaining }}</p>
 | 
					            <p class="pl-2 pr-1 text-sm font-semibold">{{ timeRemaining }}</p>
 | 
				
			||||||
          </button>
 | 
					          </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <button v-if="libraryItemIdStreaming && !isStreamingFromDifferentLibrary" class="h-8 w-8 flex justify-center items-center mx-2" :class="isQueued ? 'text-success' : ''" @click.stop="queueBtnClick">
 | 
				
			||||||
 | 
					            <span class="material-icons-outlined">{{ isQueued ? 'playlist_add_check' : 'playlist_add' }}</span>
 | 
				
			||||||
 | 
					          </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <ui-tooltip :text="userIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="top">
 | 
					          <ui-tooltip :text="userIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="top">
 | 
				
			||||||
            <ui-read-icon-btn :disabled="isProcessingReadUpdate" :is-read="userIsFinished" borderless class="mx-1 mt-0.5" @click="toggleFinished" />
 | 
					            <ui-read-icon-btn :disabled="isProcessingReadUpdate" :is-read="userIsFinished" borderless class="mx-1 mt-0.5" @click="toggleFinished" />
 | 
				
			||||||
          </ui-tooltip>
 | 
					          </ui-tooltip>
 | 
				
			||||||
@ -83,9 +87,18 @@ export default {
 | 
				
			|||||||
    duration() {
 | 
					    duration() {
 | 
				
			||||||
      return this.$secondsToTimestamp(this.episode.duration)
 | 
					      return this.$secondsToTimestamp(this.episode.duration)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    libraryItemIdStreaming() {
 | 
				
			||||||
 | 
					      return this.$store.getters['getLibraryItemIdStreaming']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    isStreamingFromDifferentLibrary() {
 | 
				
			||||||
 | 
					      return this.$store.getters['getIsStreamingFromDifferentLibrary']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    isStreaming() {
 | 
					    isStreaming() {
 | 
				
			||||||
      return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.episode.id)
 | 
					      return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.episode.id)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    isQueued() {
 | 
				
			||||||
 | 
					      return this.$store.getters['getIsMediaQueued'](this.libraryItemId, this.episode.id)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    streamIsPlaying() {
 | 
					    streamIsPlaying() {
 | 
				
			||||||
      return this.$store.state.streamIsPlaying && this.isStreaming
 | 
					      return this.$store.state.streamIsPlaying && this.isStreaming
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -169,6 +182,15 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    removeClick() {
 | 
					    removeClick() {
 | 
				
			||||||
      this.$emit('remove', this.episode)
 | 
					      this.$emit('remove', this.episode)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    queueBtnClick() {
 | 
				
			||||||
 | 
					      if (this.isQueued) {
 | 
				
			||||||
 | 
					        // Remove from queue
 | 
				
			||||||
 | 
					        this.$store.commit('removeItemFromQueue', { libraryItemId: this.libraryItemId, episodeId: this.episode.id })
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // Add to queue
 | 
				
			||||||
 | 
					        this.$emit('addToQueue', this.episode)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <p v-if="!episodes.length" class="py-4 text-center text-lg">{{ $strings.MessageNoEpisodes }}</p>
 | 
					    <p v-if="!episodes.length" class="py-4 text-center text-lg">{{ $strings.MessageNoEpisodes }}</p>
 | 
				
			||||||
    <template v-for="episode in episodesSorted">
 | 
					    <template v-for="episode in episodesSorted">
 | 
				
			||||||
      <tables-podcast-episode-table-row ref="episodeRow" :key="episode.id" :episode="episode" :library-item-id="libraryItem.id" :selection-mode="isSelectionMode" class="item" @play="playEpisode" @remove="removeEpisode" @edit="editEpisode" @view="viewEpisode" @selected="episodeSelected" />
 | 
					      <tables-podcast-episode-table-row ref="episodeRow" :key="episode.id" :episode="episode" :library-item-id="libraryItem.id" :selection-mode="isSelectionMode" class="item" @play="playEpisode" @remove="removeEpisode" @edit="editEpisode" @view="viewEpisode" @selected="episodeSelected" @addToQueue="addEpisodeToQueue" />
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <modals-podcast-remove-episode v-model="showPodcastRemoveModal" @input="removeEpisodeModalToggled" :library-item="libraryItem" :episodes="episodesToRemove" @clearSelected="clearSelected" />
 | 
					    <modals-podcast-remove-episode v-model="showPodcastRemoveModal" @input="removeEpisodeModalToggled" :library-item="libraryItem" :episodes="episodesToRemove" @clearSelected="clearSelected" />
 | 
				
			||||||
@ -131,6 +131,19 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
 | 
					    addEpisodeToQueue(episode) {
 | 
				
			||||||
 | 
					      const queueItem = {
 | 
				
			||||||
 | 
					        libraryItemId: this.libraryItem.id,
 | 
				
			||||||
 | 
					        libraryId: this.libraryItem.libraryId,
 | 
				
			||||||
 | 
					        episodeId: episode.id,
 | 
				
			||||||
 | 
					        title: episode.title,
 | 
				
			||||||
 | 
					        subtitle: this.mediaMetadata.title,
 | 
				
			||||||
 | 
					        caption: episode.publishedAt ? `Published ${this.$formatDate(episode.publishedAt, 'MMM do, yyyy')}` : 'Unknown publish date',
 | 
				
			||||||
 | 
					        duration: episode.audioFile.duration || null,
 | 
				
			||||||
 | 
					        coverPath: this.media.coverPath || null
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.$store.commit('addItemToQueue', queueItem)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    toggleBatchFinished() {
 | 
					    toggleBatchFinished() {
 | 
				
			||||||
      this.processing = true
 | 
					      this.processing = true
 | 
				
			||||||
      var newIsFinished = !this.selectedIsFinished
 | 
					      var newIsFinished = !this.selectedIsFinished
 | 
				
			||||||
@ -189,6 +202,7 @@ export default {
 | 
				
			|||||||
        if (!podcastProgress || !podcastProgress.isFinished) {
 | 
					        if (!podcastProgress || !podcastProgress.isFinished) {
 | 
				
			||||||
          queueItems.push({
 | 
					          queueItems.push({
 | 
				
			||||||
            libraryItemId: this.libraryItem.id,
 | 
					            libraryItemId: this.libraryItem.id,
 | 
				
			||||||
 | 
					            libraryId: this.libraryItem.libraryId,
 | 
				
			||||||
            episodeId: episode.id,
 | 
					            episodeId: episode.id,
 | 
				
			||||||
            title: episode.title,
 | 
					            title: episode.title,
 | 
				
			||||||
            subtitle: this.mediaMetadata.title,
 | 
					            subtitle: this.mediaMetadata.title,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="page" :class="streamLibraryItem ? 'streaming' : ''">
 | 
					  <div class="page" :class="libraryItemIdStreaming ? 'streaming' : ''">
 | 
				
			||||||
    <app-book-shelf-toolbar page="recent-episodes" />
 | 
					    <app-book-shelf-toolbar page="recent-episodes" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div id="bookshelf" class="w-full overflow-y-auto px-2 py-6 sm:px-4 md:p-12 relative">
 | 
					    <div id="bookshelf" class="w-full overflow-y-auto px-2 py-6 sm:px-4 md:p-12 relative">
 | 
				
			||||||
@ -18,11 +18,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
              <p class="text-sm text-gray-200 mb-4">{{ episode.subtitle }}</p>
 | 
					              <p class="text-sm text-gray-200 mb-4">{{ episode.subtitle }}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <button class="h-8 px-4 border border-white border-opacity-20 hover:bg-white hover:bg-opacity-10 rounded-full flex items-center justify-center cursor-pointer focus:outline-none" :class="episode.progress && episode.progress.isFinished ? 'text-white text-opacity-40' : ''" @click.stop="playClick(episode)">
 | 
					              <div class="flex items-center">
 | 
				
			||||||
                <span v-if="episodeIdStreaming === episode.id" class="material-icons" :class="streamIsPlaying ? '' : 'text-success'">{{ streamIsPlaying ? 'pause' : 'play_arrow' }}</span>
 | 
					                <button class="h-8 px-4 border border-white border-opacity-20 hover:bg-white hover:bg-opacity-10 rounded-full flex items-center justify-center cursor-pointer focus:outline-none" :class="episode.progress && episode.progress.isFinished ? 'text-white text-opacity-40' : ''" @click.stop="playClick(episode)">
 | 
				
			||||||
                <span v-else class="material-icons text-success">play_arrow</span>
 | 
					                  <span v-if="episodeIdStreaming === episode.id" class="material-icons" :class="streamIsPlaying ? '' : 'text-success'">{{ streamIsPlaying ? 'pause' : 'play_arrow' }}</span>
 | 
				
			||||||
                <p class="pl-2 pr-1 text-sm font-semibold">{{ getButtonText(episode) }}</p>
 | 
					                  <span v-else class="material-icons text-success">play_arrow</span>
 | 
				
			||||||
              </button>
 | 
					                  <p class="pl-2 pr-1 text-sm font-semibold">{{ getButtonText(episode) }}</p>
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <button v-if="libraryItemIdStreaming && !isStreamingFromDifferentLibrary" class="h-8 w-8 flex justify-center items-center mx-2" :class="playerQueueEpisodeIdMap[episode.id] ? 'text-success' : ''" @click.stop="queueBtnClick(episode)">
 | 
				
			||||||
 | 
					                  <span class="material-icons-outlined">{{ playerQueueEpisodeIdMap[episode.id] ? 'playlist_add_check' : 'playlist_add' }}</span>
 | 
				
			||||||
 | 
					                </button>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <div v-if="episode.progress" class="absolute bottom-0 left-0 h-0.5 pointer-events-none bg-warning" :style="{ width: episode.progress.progress * 100 + '%' }" />
 | 
					            <div v-if="episode.progress" class="absolute bottom-0 left-0 h-0.5 pointer-events-none bg-warning" :style="{ width: episode.progress.progress * 100 + '%' }" />
 | 
				
			||||||
@ -63,9 +69,6 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    streamLibraryItem() {
 | 
					 | 
				
			||||||
      return this.$store.state.streamLibraryItem
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    bookCoverAspectRatio() {
 | 
					    bookCoverAspectRatio() {
 | 
				
			||||||
      return this.$store.getters['libraries/getBookCoverAspectRatio']
 | 
					      return this.$store.getters['libraries/getBookCoverAspectRatio']
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -78,6 +81,9 @@ export default {
 | 
				
			|||||||
    streamIsPlaying() {
 | 
					    streamIsPlaying() {
 | 
				
			||||||
      return this.$store.state.streamIsPlaying
 | 
					      return this.$store.state.streamIsPlaying
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    isStreamingFromDifferentLibrary() {
 | 
				
			||||||
 | 
					      return this.$store.getters['getIsStreamingFromDifferentLibrary']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    episodesMapped() {
 | 
					    episodesMapped() {
 | 
				
			||||||
      return this.recentEpisodes.map((ep) => {
 | 
					      return this.recentEpisodes.map((ep) => {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
@ -85,6 +91,16 @@ export default {
 | 
				
			|||||||
          progress: this.$store.getters['user/getUserMediaProgress'](ep.libraryItemId, ep.id)
 | 
					          progress: this.$store.getters['user/getUserMediaProgress'](ep.libraryItemId, ep.id)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    playerQueueItems() {
 | 
				
			||||||
 | 
					      return this.$store.state.playerQueueItems || []
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    playerQueueEpisodeIdMap() {
 | 
				
			||||||
 | 
					      const episodeIds = {}
 | 
				
			||||||
 | 
					      this.playerQueueItems.forEach((i) => {
 | 
				
			||||||
 | 
					        if (i.episodeId) episodeIds[i.episodeId] = true
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      return episodeIds
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
@ -124,6 +140,7 @@ export default {
 | 
				
			|||||||
        if (!episode.progress || !episode.isFinished) {
 | 
					        if (!episode.progress || !episode.isFinished) {
 | 
				
			||||||
          queueItems.push({
 | 
					          queueItems.push({
 | 
				
			||||||
            libraryItemId: episode.libraryItemId,
 | 
					            libraryItemId: episode.libraryItemId,
 | 
				
			||||||
 | 
					            libraryId: episode.libraryId,
 | 
				
			||||||
            episodeId: episode.id,
 | 
					            episodeId: episode.id,
 | 
				
			||||||
            title: episode.title,
 | 
					            title: episode.title,
 | 
				
			||||||
            subtitle: episode.podcast.metadata.title,
 | 
					            subtitle: episode.podcast.metadata.title,
 | 
				
			||||||
@ -152,6 +169,25 @@ export default {
 | 
				
			|||||||
      this.recentEpisodes = episodePayload.episodes || []
 | 
					      this.recentEpisodes = episodePayload.episodes || []
 | 
				
			||||||
      this.totalEpisodes = episodePayload.total
 | 
					      this.totalEpisodes = episodePayload.total
 | 
				
			||||||
      this.currentPage = page
 | 
					      this.currentPage = page
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    queueBtnClick(episode) {
 | 
				
			||||||
 | 
					      if (this.playerQueueEpisodeIdMap[episode.id]) {
 | 
				
			||||||
 | 
					        // Remove from queue
 | 
				
			||||||
 | 
					        this.$store.commit('removeItemFromQueue', { libraryItemId: episode.libraryItemId, episodeId: episode.id })
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        // Add to queue
 | 
				
			||||||
 | 
					        const queueItem = {
 | 
				
			||||||
 | 
					          libraryItemId: episode.libraryItemId,
 | 
				
			||||||
 | 
					          libraryId: episode.libraryId,
 | 
				
			||||||
 | 
					          episodeId: episode.id,
 | 
				
			||||||
 | 
					          title: episode.title,
 | 
				
			||||||
 | 
					          subtitle: episode.podcast.metadata.title,
 | 
				
			||||||
 | 
					          caption: episode.publishedAt ? `Published ${this.$formatDate(episode.publishedAt, 'MMM do, yyyy')}` : 'Unknown publish date',
 | 
				
			||||||
 | 
					          duration: episode.duration || null,
 | 
				
			||||||
 | 
					          coverPath: episode.podcast.coverPath || null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.$store.commit('addItemToQueue', queueItem)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  mounted() {
 | 
					  mounted() {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,11 +41,21 @@ export const getters = {
 | 
				
			|||||||
  getLibraryItemIdStreaming: state => {
 | 
					  getLibraryItemIdStreaming: state => {
 | 
				
			||||||
    return state.streamLibraryItem ? state.streamLibraryItem.id : null
 | 
					    return state.streamLibraryItem ? state.streamLibraryItem.id : null
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  getIsStreamingFromDifferentLibrary: (state, getters, rootState) => {
 | 
				
			||||||
 | 
					    if (!state.streamLibraryItem) return false
 | 
				
			||||||
 | 
					    return state.streamLibraryItem.libraryId !== rootState.libraries.currentLibraryId
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  getIsMediaStreaming: state => (libraryItemId, episodeId) => {
 | 
					  getIsMediaStreaming: state => (libraryItemId, episodeId) => {
 | 
				
			||||||
    if (!state.streamLibraryItem) return null
 | 
					    if (!state.streamLibraryItem) return null
 | 
				
			||||||
    if (!episodeId) return state.streamLibraryItem.id == libraryItemId
 | 
					    if (!episodeId) return state.streamLibraryItem.id == libraryItemId
 | 
				
			||||||
    return state.streamLibraryItem.id == libraryItemId && state.streamEpisodeId == episodeId
 | 
					    return state.streamLibraryItem.id == libraryItemId && state.streamEpisodeId == episodeId
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  getIsMediaQueued: state => (libraryItemId, episodeId) => {
 | 
				
			||||||
 | 
					    return state.playerQueueItems.some(i => {
 | 
				
			||||||
 | 
					      if (!episodeId) return i.libraryItemId === libraryItemId
 | 
				
			||||||
 | 
					      return i.libraryItemId === libraryItemId && i.episodeId === episodeId
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  getBookshelfView: state => {
 | 
					  getBookshelfView: state => {
 | 
				
			||||||
    if (!state.serverSettings || isNaN(state.serverSettings.bookshelfView)) return Constants.BookshelfView.STANDARD
 | 
					    if (!state.serverSettings || isNaN(state.serverSettings.bookshelfView)) return Constants.BookshelfView.STANDARD
 | 
				
			||||||
    return state.serverSettings.bookshelfView
 | 
					    return state.serverSettings.bookshelfView
 | 
				
			||||||
@ -159,6 +169,21 @@ export const mutations = {
 | 
				
			|||||||
  setPlayerQueueItems(state, items) {
 | 
					  setPlayerQueueItems(state, items) {
 | 
				
			||||||
    state.playerQueueItems = items || []
 | 
					    state.playerQueueItems = items || []
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  removeItemFromQueue(state, item) {
 | 
				
			||||||
 | 
					    state.playerQueueItems = state.playerQueueItems.filter((i) => {
 | 
				
			||||||
 | 
					      if (!i.episodeId) return i.libraryItemId !== item.libraryItemId
 | 
				
			||||||
 | 
					      return i.libraryItemId !== item.libraryItemId || i.episodeId !== item.episodeId
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  addItemToQueue(state, item) {
 | 
				
			||||||
 | 
					    const exists = state.playerQueueItems.some(i => {
 | 
				
			||||||
 | 
					      if (!i.episodeId) return i.libraryItemId === item.libraryItemId
 | 
				
			||||||
 | 
					      return i.libraryItemId === item.libraryItemId && i.episodeId === item.episodeId
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    if (!exists) {
 | 
				
			||||||
 | 
					      state.playerQueueItems.push(item)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  setPlayerQueueAutoPlay(state, autoPlay) {
 | 
					  setPlayerQueueAutoPlay(state, autoPlay) {
 | 
				
			||||||
    state.playerQueueAutoPlay = !!autoPlay
 | 
					    state.playerQueueAutoPlay = !!autoPlay
 | 
				
			||||||
    localStorage.setItem('playerQueueAutoPlay', !!autoPlay ? '1' : '0')
 | 
					    localStorage.setItem('playerQueueAutoPlay', !!autoPlay ? '1' : '0')
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,8 @@
 | 
				
			|||||||
  "ButtonPurgeAllCache": "Purge All Cache",
 | 
					  "ButtonPurgeAllCache": "Purge All Cache",
 | 
				
			||||||
  "ButtonPurgeItemsCache": "Purge Items Cache",
 | 
					  "ButtonPurgeItemsCache": "Purge Items Cache",
 | 
				
			||||||
  "ButtonPurgeMediaProgress": "Purge Media Progress",
 | 
					  "ButtonPurgeMediaProgress": "Purge Media Progress",
 | 
				
			||||||
 | 
					  "ButtonQueueAddItem": "Add to queue",
 | 
				
			||||||
 | 
					  "ButtonQueueRemoveItem": "Remove from queue",
 | 
				
			||||||
  "ButtonQuickMatch": "Quick Match",
 | 
					  "ButtonQuickMatch": "Quick Match",
 | 
				
			||||||
  "ButtonRead": "Read",
 | 
					  "ButtonRead": "Read",
 | 
				
			||||||
  "ButtonRemove": "Remove",
 | 
					  "ButtonRemove": "Remove",
 | 
				
			||||||
 | 
				
			|||||||
@ -602,6 +602,7 @@ class LibraryController {
 | 
				
			|||||||
        const ep = _ep.toJSONExpanded()
 | 
					        const ep = _ep.toJSONExpanded()
 | 
				
			||||||
        ep.podcast = libraryItem.media.toJSONMinified()
 | 
					        ep.podcast = libraryItem.media.toJSONMinified()
 | 
				
			||||||
        ep.libraryItemId = libraryItem.id
 | 
					        ep.libraryItemId = libraryItem.id
 | 
				
			||||||
 | 
					        ep.libraryId = libraryItem.libraryId
 | 
				
			||||||
        return ep
 | 
					        return ep
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      allUnfinishedEpisodes.push(...unfinishedEpisodes)
 | 
					      allUnfinishedEpisodes.push(...unfinishedEpisodes)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user