mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-06-28 16:00:17 +02:00
Update:Syncing playback time when media item is open in player
This commit is contained in:
parent
b4bf10d409
commit
ff4f8324e7
25 changed files with 149 additions and 177 deletions
|
@ -305,9 +305,9 @@ data class PodcastEpisode(
|
|||
.setSubtitle(libraryItemDescription.title)
|
||||
.setExtras(extras)
|
||||
|
||||
libraryItemDescription.iconBitmap?.let {
|
||||
mediaDescriptionBuilder.setIconBitmap(it)
|
||||
}
|
||||
// libraryItemDescription.iconBitmap?.let {
|
||||
// mediaDescriptionBuilder.setIconBitmap(it)
|
||||
// }
|
||||
|
||||
return mediaDescriptionBuilder.build()
|
||||
}
|
||||
|
|
|
@ -110,17 +110,17 @@ class LocalLibraryItem(
|
|||
override fun getMediaDescription(progress:MediaProgressWrapper?, ctx:Context?): MediaDescriptionCompat {
|
||||
val coverUri = getCoverUri()
|
||||
|
||||
var bitmap:Bitmap? = null
|
||||
if (coverContentUrl != null) {
|
||||
ctx?.let {
|
||||
bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
MediaStore.Images.Media.getBitmap(it.contentResolver, coverUri)
|
||||
} else {
|
||||
val source: ImageDecoder.Source = ImageDecoder.createSource(it.contentResolver, coverUri)
|
||||
ImageDecoder.decodeBitmap(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
// var bitmap:Bitmap? = null
|
||||
// if (coverContentUrl != null) {
|
||||
// ctx?.let {
|
||||
// bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
// MediaStore.Images.Media.getBitmap(it.contentResolver, coverUri)
|
||||
// } else {
|
||||
// val source: ImageDecoder.Source = ImageDecoder.createSource(it.contentResolver, coverUri)
|
||||
// ImageDecoder.decodeBitmap(source)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
val extras = Bundle()
|
||||
extras.putLong(
|
||||
|
@ -156,9 +156,9 @@ class LocalLibraryItem(
|
|||
.setSubtitle(authorName)
|
||||
.setExtras(extras)
|
||||
|
||||
bitmap?.let {
|
||||
mediaDescriptionBuilder.setIconBitmap(bitmap)
|
||||
}
|
||||
// bitmap?.let {
|
||||
// mediaDescriptionBuilder.setIconBitmap(bitmap)
|
||||
// }
|
||||
|
||||
return mediaDescriptionBuilder.build()
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package com.audiobookshelf.app.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.ImageDecoder
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import com.audiobookshelf.app.BuildConfig
|
||||
import com.audiobookshelf.app.R
|
||||
|
@ -168,16 +165,16 @@ class PlaybackSession(
|
|||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, getCoverUri().toString())
|
||||
|
||||
// Local covers get bitmap
|
||||
if (localLibraryItem?.coverContentUrl != null) {
|
||||
val bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
MediaStore.Images.Media.getBitmap(ctx.contentResolver, getCoverUri())
|
||||
} else {
|
||||
val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, getCoverUri())
|
||||
ImageDecoder.decodeBitmap(source)
|
||||
}
|
||||
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
|
||||
metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap)
|
||||
}
|
||||
// if (localLibraryItem?.coverContentUrl != null) {
|
||||
// val bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
// MediaStore.Images.Media.getBitmap(ctx.contentResolver, getCoverUri())
|
||||
// } else {
|
||||
// val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, getCoverUri())
|
||||
// ImageDecoder.decodeBitmap(source)
|
||||
// }
|
||||
// metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap)
|
||||
// metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap)
|
||||
// }
|
||||
|
||||
return metadataBuilder.build()
|
||||
}
|
||||
|
|
|
@ -215,7 +215,6 @@ class MediaProgressSyncer(val playerNotificationService: PlayerNotificationServi
|
|||
val listeningTimeToAdd = diffSinceLastSync / 1000L
|
||||
|
||||
val syncData = MediaProgressSyncData(listeningTimeToAdd,currentPlaybackDuration,currentTime)
|
||||
|
||||
currentPlaybackSession?.syncData(syncData)
|
||||
|
||||
if (currentPlaybackSession?.progress?.isNaN() == true) {
|
||||
|
@ -243,11 +242,6 @@ class MediaProgressSyncer(val playerNotificationService: PlayerNotificationServi
|
|||
// Send sync to server also if connected to this server and local item belongs to this server
|
||||
if (hasNetworkConnection && shouldSyncServer && !it.libraryItemId.isNullOrEmpty() && it.serverConnectionConfigId != null && DeviceManager.serverConnectionConfig?.id == it.serverConnectionConfigId) {
|
||||
apiHandler.sendLocalProgressSync(it) { syncSuccess, errorMsg ->
|
||||
Log.d(
|
||||
tag,
|
||||
"Local progress sync data sent to server $currentDisplayTitle for time $currentTime"
|
||||
)
|
||||
|
||||
if (syncSuccess) {
|
||||
failedSyncs = 0
|
||||
playerNotificationService.alertSyncSuccess()
|
||||
|
|
|
@ -4,9 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.app.*
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.ImageDecoder
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorManager
|
||||
import android.net.ConnectivityManager
|
||||
|
@ -14,7 +12,6 @@ import android.net.Network
|
|||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest
|
||||
import android.os.*
|
||||
import android.provider.MediaStore
|
||||
import android.provider.Settings
|
||||
import android.support.v4.media.MediaBrowserCompat
|
||||
import android.support.v4.media.MediaDescriptionCompat
|
||||
|
@ -292,18 +289,18 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
return MediaDescriptionCompat.Builder().build()
|
||||
}
|
||||
|
||||
val coverUri = currentPlaybackSession!!.getCoverUri()
|
||||
var coverUri = currentPlaybackSession!!.getCoverUri()
|
||||
|
||||
var bitmap:Bitmap? = null
|
||||
// var bitmap:Bitmap? = null
|
||||
// Local covers get bitmap
|
||||
if (currentPlaybackSession!!.localLibraryItem?.coverContentUrl != null) {
|
||||
bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
MediaStore.Images.Media.getBitmap(ctx.contentResolver, coverUri)
|
||||
} else {
|
||||
val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, coverUri)
|
||||
ImageDecoder.decodeBitmap(source)
|
||||
}
|
||||
}
|
||||
// if (currentPlaybackSession!!.localLibraryItem?.coverContentUrl != null) {
|
||||
// bitmap = if (Build.VERSION.SDK_INT < 28) {
|
||||
// MediaStore.Images.Media.getBitmap(ctx.contentResolver, coverUri)
|
||||
// } else {
|
||||
// val source: ImageDecoder.Source = ImageDecoder.createSource(ctx.contentResolver, coverUri)
|
||||
// ImageDecoder.decodeBitmap(source)
|
||||
// }
|
||||
// }
|
||||
|
||||
// Fix for local images crashing on Android 11 for specific devices
|
||||
// https://stackoverflow.com/questions/64186578/android-11-mediastyle-notification-crash/64232958#64232958
|
||||
|
@ -325,9 +322,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
.setTitle(currentPlaybackSession!!.displayTitle)
|
||||
.setIconUri(coverUri)
|
||||
|
||||
bitmap?.let {
|
||||
mediaDescriptionBuilder.setIconBitmap(it)
|
||||
}
|
||||
// bitmap?.let {
|
||||
// mediaDescriptionBuilder.setIconBitmap(it)
|
||||
// }
|
||||
|
||||
return mediaDescriptionBuilder.build()
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
castClick() {
|
||||
if (this.$store.state.playerIsLocal) {
|
||||
if (this.$store.getters['getIsCurrentSessionLocal']) {
|
||||
this.$eventBus.$emit('cast-local-item')
|
||||
return
|
||||
}
|
||||
|
|
|
@ -574,8 +574,8 @@ export default {
|
|||
AbsAudioPlayer.seek({ value: Math.floor(time) })
|
||||
|
||||
if (this.$refs.playedTrack) {
|
||||
var perc = time / this.totalDuration
|
||||
var ptWidth = Math.round(perc * this.trackWidth)
|
||||
const perc = time / this.totalDuration
|
||||
const ptWidth = Math.round(perc * this.trackWidth)
|
||||
this.$refs.playedTrack.style.width = ptWidth + 'px'
|
||||
|
||||
this.$refs.playedTrack.classList.remove('bg-gray-200')
|
||||
|
@ -721,7 +721,7 @@ export default {
|
|||
AbsAudioPlayer.closePlayback()
|
||||
},
|
||||
endPlayback() {
|
||||
this.$store.commit('setPlayerItem', null)
|
||||
this.$store.commit('setPlaybackSession', null)
|
||||
this.showFullscreen = false
|
||||
this.isEnded = false
|
||||
this.isLoading = false
|
||||
|
@ -767,7 +767,7 @@ export default {
|
|||
this.isEnded = false
|
||||
this.isLoading = true
|
||||
this.syncStatus = 0
|
||||
this.$store.commit('setPlayerItem', this.playbackSession)
|
||||
this.$store.commit('setPlaybackSession', this.playbackSession)
|
||||
|
||||
// Set track width
|
||||
this.$nextTick(() => {
|
||||
|
|
|
@ -110,7 +110,7 @@ export default {
|
|||
},
|
||||
streamProgress(data) {
|
||||
if (!data.numSegments) return
|
||||
var chunks = data.chunks
|
||||
const chunks = data.chunks
|
||||
if (this.$refs.audioPlayer) {
|
||||
this.$refs.audioPlayer.setChunksReady(chunks, data.numSegments)
|
||||
}
|
||||
|
@ -265,8 +265,7 @@ export default {
|
|||
this.$store.commit('globals/updateLocalMediaProgress', localMediaProgress)
|
||||
},
|
||||
onMediaPlayerChanged(data) {
|
||||
var mediaPlayer = data.value
|
||||
this.$store.commit('setMediaPlayer', mediaPlayer)
|
||||
this.$store.commit('setMediaPlayer', data.value)
|
||||
},
|
||||
onReady() {
|
||||
// The UI is reporting elsewhere we are ready
|
||||
|
@ -283,6 +282,9 @@ export default {
|
|||
this.$store.commit('setIsFirstAudioLoad', false) // Only run this once on app launch
|
||||
AbsAudioPlayer.onReady()
|
||||
}
|
||||
},
|
||||
playbackTimeUpdate(currentTime) {
|
||||
this.$refs.audioPlayer?.seek(currentTime)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -300,6 +302,7 @@ export default {
|
|||
this.$eventBus.$on('close-stream', this.closeStreamOnly)
|
||||
this.$eventBus.$on('cast-local-item', this.castLocalItem)
|
||||
this.$eventBus.$on('user-settings', this.settingsUpdated)
|
||||
this.$eventBus.$on('playback-time-update', this.playbackTimeUpdate)
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.onLocalMediaProgressUpdateListener) this.onLocalMediaProgressUpdateListener.remove()
|
||||
|
@ -313,6 +316,7 @@ export default {
|
|||
this.$eventBus.$off('close-stream', this.closeStreamOnly)
|
||||
this.$eventBus.$off('cast-local-item', this.castLocalItem)
|
||||
this.$eventBus.$off('user-settings', this.settingsUpdated)
|
||||
this.$eventBus.$off('playback-time-update', this.playbackTimeUpdate)
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -213,7 +213,7 @@ export default {
|
|||
return this.mediaMetadata.series
|
||||
},
|
||||
seriesSequence() {
|
||||
return this.series ? this.series.sequence : null
|
||||
return this.series?.sequence || null
|
||||
},
|
||||
recentEpisode() {
|
||||
// Only added to item when getting currently listening podcasts
|
||||
|
@ -232,14 +232,14 @@ export default {
|
|||
},
|
||||
booksInSeries() {
|
||||
// Only added to item object when collapseSeries is enabled
|
||||
return this.collapsedSeries ? this.collapsedSeries.numBooks : 0
|
||||
return this.collapsedSeries?.numBooks || 0
|
||||
},
|
||||
seriesSequenceList() {
|
||||
return this.collapsedSeries ? this.collapsedSeries.seriesSequenceList : null
|
||||
return this.collapsedSeries?.seriesSequenceList || null
|
||||
},
|
||||
libraryItemIdsInSeries() {
|
||||
// Only added to item object when collapseSeries is enabled
|
||||
return this.collapsedSeries ? this.collapsedSeries.libraryItemIds || [] : []
|
||||
return this.collapsedSeries?.libraryItemIds || []
|
||||
},
|
||||
displayTitle() {
|
||||
if (this.recentEpisode) return this.recentEpisode.title
|
||||
|
@ -291,20 +291,18 @@ export default {
|
|||
showError() {
|
||||
return this.numMissingParts || this.isMissing || this.isInvalid
|
||||
},
|
||||
playerIsLocal() {
|
||||
return !!this.$store.state.playerIsLocal
|
||||
},
|
||||
localLibraryItemId() {
|
||||
if (this.isLocal) return this.libraryItemId
|
||||
return this.localLibraryItem ? this.localLibraryItem.id : null
|
||||
return this.localLibraryItem?.id || null
|
||||
},
|
||||
localEpisode() {
|
||||
if (!this.recentEpisode || !this.localLibraryItem) return null
|
||||
// Current recentEpisode is only implemented server side so this will always be the serverEpisodeId
|
||||
return this.localLibraryItem.media.episodes.find((ep) => ep.serverEpisodeId === this.recentEpisode.id)
|
||||
},
|
||||
isStreaming() {
|
||||
if (this.isPodcast) {
|
||||
if (this.playerIsLocal) {
|
||||
// Check is streaming local version of this episode
|
||||
return false // episode cards not implemented for local yet
|
||||
}
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItemId, this.recentEpisode.id)
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.recentEpisode.id)
|
||||
} else {
|
||||
return false // not yet necessary for books
|
||||
}
|
||||
|
@ -380,8 +378,7 @@ export default {
|
|||
showHasLocalDownload() {
|
||||
if (this.localLibraryItem || this.isLocal) {
|
||||
if (this.recentEpisode && !this.isLocal) {
|
||||
const localEpisode = this.localLibraryItem.media.episodes.find((ep) => ep.serverEpisodeId === this.recentEpisode.id)
|
||||
return !!localEpisode
|
||||
return !!this.localEpisode
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
@ -436,19 +433,16 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
if (this.localLibraryItem) {
|
||||
const localEpisode = this.localLibraryItem.media.episodes.find((ep) => ep.serverEpisodeId === this.recentEpisode.id)
|
||||
if (localEpisode) {
|
||||
if (this.localEpisode) {
|
||||
// Play episode locally
|
||||
eventBus.$emit('play-item', {
|
||||
libraryItemId: this.localLibraryItemId,
|
||||
episodeId: localEpisode.id,
|
||||
episodeId: this.localEpisode.id,
|
||||
serverLibraryItemId: this.libraryItemId,
|
||||
serverEpisodeId: this.recentEpisode.id
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
eventBus.$emit('play-item', { libraryItemId: this.libraryItemId, episodeId: this.recentEpisode.id })
|
||||
},
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fixed left-0 h-8 w-full bg-primary px-4 flex items-center text-white/80" :style="{ bottom: playerLibraryItemId ? '120px' : '0px' }">
|
||||
<div class="fixed left-0 h-8 w-full bg-primary px-4 flex items-center text-white/80" :style="{ bottom: isPlayerOpen ? '120px' : '0px' }">
|
||||
<div class="flex-grow" />
|
||||
<p class="text-xs">{{ page }} / {{ numPages }}</p>
|
||||
</div>
|
||||
|
@ -148,8 +148,8 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div id="epub-frame" class="w-full">
|
||||
<div id="viewer" class="h-full w-full"></div>
|
||||
|
||||
<div class="fixed left-0 h-8 w-full px-4 flex items-center" :class="isLightTheme ? 'bg-white text-black' : 'bg-primary text-white/80'" :style="{ bottom: playerLibraryItemId ? '120px' : '0px' }">
|
||||
<div class="fixed left-0 h-8 w-full px-4 flex items-center" :class="isLightTheme ? 'bg-white text-black' : 'bg-primary text-white/80'" :style="{ bottom: isPlayerOpen ? '120px' : '0px' }">
|
||||
<div class="flex-grow" />
|
||||
<p class="text-xs">{{ progress }}%</p>
|
||||
</div>
|
||||
|
@ -37,7 +37,7 @@ export default {
|
|||
}
|
||||
},
|
||||
watch: {
|
||||
playerLibraryItemId() {
|
||||
isPlayerOpen() {
|
||||
this.updateHeight()
|
||||
}
|
||||
},
|
||||
|
@ -65,11 +65,11 @@ export default {
|
|||
}
|
||||
return null
|
||||
},
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
},
|
||||
readerHeightOffset() {
|
||||
return this.playerLibraryItemId ? 204 : 84
|
||||
return this.isPlayerOpen ? 204 : 104
|
||||
},
|
||||
/** @returns {Array<ePub.NavItem>} */
|
||||
chapters() {
|
||||
|
|
|
@ -23,9 +23,6 @@ export default {
|
|||
return {}
|
||||
},
|
||||
computed: {
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
},
|
||||
userToken() {
|
||||
return this.$store.getters['user/getToken']
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fixed left-0 h-8 w-full bg-primary px-4 flex items-center text-white/80" :style="{ bottom: playerLibraryItemId ? '120px' : '0px' }">
|
||||
<div class="fixed left-0 h-8 w-full bg-primary px-4 flex items-center text-white/80" :style="{ bottom: isPlayerOpen ? '120px' : '0px' }">
|
||||
<div class="flex-grow" />
|
||||
<p class="text-xs">{{ page }} / {{ numPages }}</p>
|
||||
</div>
|
||||
|
@ -114,8 +114,8 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="show" :data-theme="ereaderTheme" class="group fixed top-0 left-0 right-0 layout-wrapper w-full z-40 pt-8 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black" :class="{ 'reader-player-open': !!playerLibraryItemId }">
|
||||
<div v-if="show" :data-theme="ereaderTheme" class="group fixed top-0 left-0 right-0 layout-wrapper w-full z-40 pt-8 data-[theme=dark]:bg-primary data-[theme=dark]:text-white data-[theme=light]:bg-white data-[theme=light]:text-black" :class="{ 'reader-player-open': isPlayerOpen }">
|
||||
<!-- toolbar -->
|
||||
<div class="h-32 pt-10 w-full px-2 fixed top-0 left-0 z-30 transition-transform bg-bg text-white" :class="showingToolbar ? 'translate-y-0' : '-translate-y-32'" @touchstart.stop @mousedown.stop @touchend.stop @mouseup.stop>
|
||||
<div class="flex items-center mb-2">
|
||||
|
@ -213,8 +213,8 @@ export default {
|
|||
}
|
||||
return `${serverAddress}/api/items/${this.selectedLibraryItem.id}/ebook`
|
||||
},
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
},
|
||||
keepProgress() {
|
||||
return this.$store.state.ereaderKeepProgress
|
||||
|
|
|
@ -74,7 +74,7 @@ export default {
|
|||
return !this.isMissing && !this.isInvalid && this.tracks.length
|
||||
},
|
||||
isStreaming() {
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItemId)
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId)
|
||||
},
|
||||
streamIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && this.isStreaming
|
||||
|
|
|
@ -102,8 +102,8 @@ export default {
|
|||
return !this.isMissing && !this.isInvalid && (this.tracks.length || this.episode)
|
||||
},
|
||||
isStreaming() {
|
||||
if (this.localLibraryItem && this.$store.getters['getIsEpisodeStreaming'](this.localLibraryItem.id, this.localEpisode?.id)) return true
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItem.id, this.episodeId)
|
||||
if (this.localLibraryItem && this.localEpisode && this.$store.getters['getIsMediaStreaming'](this.localLibraryItem.id, this.localEpisode.id)) return true
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItem.id, this.episodeId)
|
||||
},
|
||||
streamIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && this.isStreaming
|
||||
|
|
|
@ -114,14 +114,7 @@ export default {
|
|||
return this.$secondsToTimestamp(this.episode.duration)
|
||||
},
|
||||
isStreaming() {
|
||||
if (this.playerIsLocal && this.localLibraryItemId && this.localEpisode) {
|
||||
// Check is streaming local version of this episode
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.localLibraryItemId, this.localEpisode.id)
|
||||
}
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
playerIsLocal() {
|
||||
return !!this.$store.state.playerIsLocal
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
streamIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && this.isStreaming
|
||||
|
|
|
@ -117,14 +117,7 @@ export default {
|
|||
return this.$secondsToTimestamp(this.episode.duration)
|
||||
},
|
||||
isStreaming() {
|
||||
if (this.playerIsLocal && this.localLibraryItemId && this.localEpisode) {
|
||||
// Check is streaming local version of this episode
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.localLibraryItemId, this.localEpisode.id)
|
||||
}
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
playerIsLocal() {
|
||||
return !!this.$store.state.playerIsLocal
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
streamIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && this.isStreaming
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="w-full layout-wrapper bg-bg text-white">
|
||||
<app-appbar />
|
||||
<div id="content" class="overflow-hidden relative" :class="playerIsOpen ? 'playerOpen' : ''">
|
||||
<div id="content" class="overflow-hidden relative" :class="isPlayerOpen ? 'playerOpen' : ''">
|
||||
<Nuxt />
|
||||
|
||||
<div v-if="attemptingConnection" class="absolute top-0 left-0 z-50 w-full h-full flex items-center justify-center">
|
||||
|
@ -57,11 +57,8 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
playerIsOpen() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
},
|
||||
readerIsOpen() {
|
||||
return this.$store.state.showReader
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
},
|
||||
routeName() {
|
||||
return this.$route.name
|
||||
|
@ -86,7 +83,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
initialStream(stream) {
|
||||
if (this.$refs.streamContainer && this.$refs.streamContainer.audioPlayerReady) {
|
||||
if (this.$refs.streamContainer?.audioPlayerReady) {
|
||||
this.$refs.streamContainer.streamOpen(stream)
|
||||
}
|
||||
},
|
||||
|
@ -234,8 +231,16 @@ export default {
|
|||
this.$store.commit('user/setUser', user)
|
||||
}
|
||||
},
|
||||
async userMediaProgressUpdated(prog) {
|
||||
console.log(`[default] userMediaProgressUpdate checking for local media progress ${prog.id}`)
|
||||
async userMediaProgressUpdated(payload) {
|
||||
const prog = payload.data // MediaProgress
|
||||
console.log(`[default] userMediaProgressUpdate checking for local media progress ${payload.id}`)
|
||||
|
||||
// Check if this media item is currently open in the player, paused, and this progress update is coming from a different session
|
||||
const isMediaOpenInPlayer = this.$store.getters['getIsMediaStreaming'](prog.libraryItemId, prog.episodeId)
|
||||
if (isMediaOpenInPlayer && this.$store.getters['getCurrentPlaybackSessionId'] !== payload.sessionId && !this.$store.state.playerIsPlaying) {
|
||||
console.log('[default] userMediaProgressUpdated for current open media item', payload.data.currentTime)
|
||||
this.$eventBus.$emit('playback-time-update', payload.data.currentTime)
|
||||
}
|
||||
|
||||
// Update local media progress if exists
|
||||
const localProg = await this.$db.getLocalMediaProgressForServerItem({ libraryItemId: prog.libraryItemId, episodeId: prog.episodeId })
|
||||
|
@ -287,7 +292,7 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
if (newLocalMediaProgress && newLocalMediaProgress.id) {
|
||||
if (newLocalMediaProgress?.id) {
|
||||
console.log(`[default] local media progress updated for ${newLocalMediaProgress.id}`)
|
||||
this.$store.commit('globals/updateLocalMediaProgress', newLocalMediaProgress)
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ export default {
|
|||
})
|
||||
},
|
||||
streaming() {
|
||||
return !!this.playableBooks.find((b) => this.$store.getters['getIsItemStreaming'](b.id))
|
||||
return !!this.playableBooks.find((b) => this.$store.getters['getIsMediaStreaming'](b.id))
|
||||
},
|
||||
showPlayButton() {
|
||||
return this.playableBooks.length
|
||||
|
|
|
@ -209,14 +209,7 @@ export default {
|
|||
return this.$store.getters['globals/getLibraryItemCoverSrcById'](this.libraryItemId)
|
||||
},
|
||||
isPlaying() {
|
||||
if (this.playerIsLocal && this.localLibraryItemId && this.localEpisodeId) {
|
||||
// Check is streaming local version of this episode
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.localLibraryItemId, this.localEpisodeId)
|
||||
}
|
||||
return this.$store.getters['getIsEpisodeStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
playerIsLocal() {
|
||||
return !!this.$store.state.playerIsLocal
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId, this.episode.id)
|
||||
},
|
||||
playerIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && this.isPlaying
|
||||
|
|
|
@ -326,11 +326,11 @@ export default {
|
|||
return this.userItemProgress ? this.userItemProgress.finishedAt : 0
|
||||
},
|
||||
isStreaming() {
|
||||
return this.isPlaying && !this.$store.state.playerIsLocal
|
||||
return this.isPlaying && !this.$store.getters['getIsCurrentSessionLocal']
|
||||
},
|
||||
isPlaying() {
|
||||
if (this.localLibraryItemId && this.$store.getters['getIsItemStreaming'](this.localLibraryItemId)) return true
|
||||
return this.$store.getters['getIsItemStreaming'](this.libraryItemId)
|
||||
if (this.localLibraryItemId && this.$store.getters['getIsMediaStreaming'](this.localLibraryItemId)) return true
|
||||
return this.$store.getters['getIsMediaStreaming'](this.libraryItemId)
|
||||
},
|
||||
playerIsPlaying() {
|
||||
return this.$store.state.playerIsPlaying && (this.isStreaming || this.isPlaying)
|
||||
|
|
|
@ -108,7 +108,7 @@
|
|||
<p class="text-lg text-center px-8">{{ failed ? 'Failed to get local library item ' + localLibraryItemId : 'Loading..' }}</p>
|
||||
</div>
|
||||
|
||||
<div v-if="orderChanged" class="fixed left-0 w-full py-4 px-4 bg-bg box-shadow-book flex items-center" :style="{ bottom: playerLibraryItemId ? '120px' : '0px' }">
|
||||
<div v-if="orderChanged" class="fixed left-0 w-full py-4 px-4 bg-bg box-shadow-book flex items-center" :style="{ bottom: isPlayerOpen ? '120px' : '0px' }">
|
||||
<div class="flex-grow" />
|
||||
<ui-btn small color="success" @click="saveTrackOrder">Save Order</ui-btn>
|
||||
</div>
|
||||
|
@ -156,8 +156,8 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
playerLibraryItemId() {
|
||||
return this.$store.state.playerLibraryItemId
|
||||
isPlayerOpen() {
|
||||
return this.$store.getters['getIsPlayerOpen']
|
||||
},
|
||||
isIos() {
|
||||
return this.$platform === 'ios'
|
||||
|
|
|
@ -88,11 +88,10 @@ class ServerSocket extends EventEmitter {
|
|||
this.emit('user_updated', data)
|
||||
}
|
||||
|
||||
onUserItemProgressUpdated(data) {
|
||||
console.log('[SOCKET] User Item Progress Updated', JSON.stringify(data))
|
||||
var progress = data.data
|
||||
this.$store.commit('user/updateUserMediaProgress', progress)
|
||||
this.emit('user_media_progress_updated', progress)
|
||||
onUserItemProgressUpdated(payload) {
|
||||
console.log('[SOCKET] User Item Progress Updated', JSON.stringify(payload))
|
||||
this.$store.commit('user/updateUserMediaProgress', payload.data)
|
||||
this.emit('user_media_progress_updated', payload)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@ import { AbsAudioPlayer } from '@/plugins/capacitor'
|
|||
|
||||
export const state = () => ({
|
||||
deviceData: null,
|
||||
playerLibraryItemId: null,
|
||||
playerEpisodeId: null,
|
||||
playerIsLocal: false,
|
||||
currentPlaybackSession: null,
|
||||
playerIsPlaying: false,
|
||||
playerIsFullscreen: false,
|
||||
isCasting: false,
|
||||
|
@ -30,16 +28,33 @@ export const state = () => ({
|
|||
})
|
||||
|
||||
export const getters = {
|
||||
getCurrentPlaybackSessionId: state => {
|
||||
return state.currentPlaybackSession?.id || null
|
||||
},
|
||||
getIsPlayerOpen: state => {
|
||||
return !!state.currentPlaybackSession
|
||||
},
|
||||
getIsCurrentSessionLocal: state => {
|
||||
return state.currentPlaybackSession?.playMethod == this.$constants.PlayMethod.LOCAL
|
||||
},
|
||||
getIsMediaStreaming: state => (libraryItemId, episodeId) => {
|
||||
if (!state.playerLibraryItemId) return null
|
||||
if (!episodeId) return state.playerLibraryItemId == libraryItemId
|
||||
return state.playerLibraryItemId == libraryItemId && state.playerEpisodeId == episodeId
|
||||
},
|
||||
getIsItemStreaming: state => libraryItemId => {
|
||||
return state.playerLibraryItemId == libraryItemId
|
||||
},
|
||||
getIsEpisodeStreaming: state => (libraryItemId, episodeId) => {
|
||||
return state.playerLibraryItemId == libraryItemId && state.playerEpisodeId == episodeId
|
||||
if (!state.currentPlaybackSession || !libraryItemId) return false
|
||||
|
||||
// Check using local library item id and local episode id
|
||||
const isLocalLibraryItemId = libraryItemId.startsWith('local_')
|
||||
if (isLocalLibraryItemId) {
|
||||
if (state.currentPlaybackSession.localLibraryItem?.id !== libraryItemId) {
|
||||
return false
|
||||
}
|
||||
if (!episodeId) return true
|
||||
return state.currentPlaybackSession.localEpisodeId === episodeId
|
||||
}
|
||||
|
||||
if (state.currentPlaybackSession.libraryItemId !== libraryItemId) {
|
||||
return false
|
||||
}
|
||||
if (!episodeId) return true
|
||||
return state.currentPlaybackSession.episodeId === episodeId
|
||||
},
|
||||
getServerSetting: state => key => {
|
||||
if (!state.serverSettings) return null
|
||||
|
@ -96,19 +111,10 @@ export const mutations = {
|
|||
setLastItemScrollData(state, data) {
|
||||
state.lastItemScrollData = data
|
||||
},
|
||||
setPlayerItem(state, playbackSession) {
|
||||
state.playerIsLocal = playbackSession ? playbackSession.playMethod == this.$constants.PlayMethod.LOCAL : false
|
||||
setPlaybackSession(state, playbackSession) {
|
||||
state.currentPlaybackSession = playbackSession
|
||||
|
||||
if (state.playerIsLocal) {
|
||||
state.playerLibraryItemId = playbackSession ? playbackSession.localLibraryItem.id || null : null
|
||||
state.playerEpisodeId = playbackSession ? playbackSession.localEpisodeId || null : null
|
||||
} else {
|
||||
state.playerLibraryItemId = playbackSession ? playbackSession.libraryItemId || null : null
|
||||
state.playerEpisodeId = playbackSession ? playbackSession.episodeId || null : null
|
||||
}
|
||||
|
||||
var mediaPlayer = playbackSession ? playbackSession.mediaPlayer : null
|
||||
state.isCasting = mediaPlayer === "cast-player"
|
||||
state.isCasting = playbackSession?.mediaPlayer === "cast-player"
|
||||
},
|
||||
setMediaPlayer(state, mediaPlayer) {
|
||||
state.isCasting = mediaPlayer === 'cast-player'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue