mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update chapter track progress bar, timestamps, hide chapter ticks. Update mobile responsiveness for player
This commit is contained in:
		
							parent
							
								
									644882e04f
								
							
						
					
					
						commit
						ccc82520a9
					
				| @ -1,30 +1,30 @@ | |||||||
| <template> | <template> | ||||||
|   <div v-if="streamLibraryItem" id="streamContainer" class="w-full fixed bottom-0 left-0 right-0 h-48 sm:h-44 md:h-40 z-40 bg-primary px-4 pb-1 md:pb-4 pt-2"> |   <div v-if="streamLibraryItem" id="streamContainer" class="w-full fixed bottom-0 left-0 right-0 h-48 sm:h-44 md:h-40 z-40 bg-primary px-4 pb-1 md:pb-4 pt-2"> | ||||||
|     <div id="videoDock" /> |     <div id="videoDock" /> | ||||||
|     <nuxt-link v-if="!playerHandler.isVideo" :to="`/item/${streamLibraryItem.id}`" class="absolute left-4 cursor-pointer" :style="{ top: bookCoverPosTop + 'px' }"> |     <nuxt-link v-if="!playerHandler.isVideo" :to="`/item/${streamLibraryItem.id}`" class="absolute left-1 sm:left-4 cursor-pointer" :style="{ top: bookCoverPosTop + 'px' }"> | ||||||
|       <covers-book-cover :library-item="streamLibraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" /> |       <covers-book-cover :library-item="streamLibraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" /> | ||||||
|     </nuxt-link> |     </nuxt-link> | ||||||
|     <div class="flex items-start mb-6 md:mb-0" :class="playerHandler.isVideo ? 'ml-4 pl-96' : 'pl-24'"> |     <div class="flex items-start mb-6 md:mb-0" :class="playerHandler.isVideo ? 'ml-4 pl-96' : 'pl-20 sm:pl-24'"> | ||||||
|       <div> |       <div> | ||||||
|         <nuxt-link :to="`/item/${streamLibraryItem.id}`" class="hover:underline cursor-pointer text-base sm:text-lg"> |         <nuxt-link :to="`/item/${streamLibraryItem.id}`" class="hover:underline cursor-pointer text-sm sm:text-lg"> | ||||||
|           {{ title }} |           {{ title }} | ||||||
|         </nuxt-link> |         </nuxt-link> | ||||||
|         <div v-if="!playerHandler.isVideo" class="text-gray-400 flex items-center"> |         <div v-if="!playerHandler.isVideo" class="text-gray-400 flex items-center"> | ||||||
|           <span class="material-icons text-sm">person</span> |           <span class="material-icons text-sm">person</span> | ||||||
|           <p v-if="podcastAuthor">{{ podcastAuthor }}</p> |           <p v-if="podcastAuthor" class="pl-1 sm:pl-1.5 text-xs sm:text-base">{{ podcastAuthor }}</p> | ||||||
|           <p v-else-if="authors.length" class="pl-1.5 text-sm sm:text-base"> |           <p v-else-if="authors.length" class="pl-1 sm:pl-1.5 text-xs sm:text-base"> | ||||||
|             <nuxt-link v-for="(author, index) in authors" :key="index" :to="`/author/${author.id}`" class="hover:underline">{{ author.name }}<span v-if="index < authors.length - 1">, </span></nuxt-link> |             <nuxt-link v-for="(author, index) in authors" :key="index" :to="`/author/${author.id}`" class="hover:underline">{{ author.name }}<span v-if="index < authors.length - 1">, </span></nuxt-link> | ||||||
|           </p> |           </p> | ||||||
|           <p v-else class="text-sm sm:text-base cursor-pointer pl-2">Unknown</p> |           <p v-else class="text-xs sm:text-base cursor-pointer pl-1 sm:pl-1.5">Unknown</p> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div class="text-gray-400 flex items-center"> |         <div class="text-gray-400 flex items-center"> | ||||||
|           <span class="material-icons text-xs">schedule</span> |           <span class="material-icons text-xs">schedule</span> | ||||||
|           <p class="font-mono text-sm pl-2 pb-px">{{ totalDurationPretty }}</p> |           <p class="font-mono text-xs sm:text-sm pl-1 sm:pl-1.5 pb-px">{{ totalDurationPretty }}</p> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <div class="flex-grow" /> |       <div class="flex-grow" /> | ||||||
|       <span class="material-icons px-2 py-1 md:p-4 cursor-pointer" @click="closePlayer">close</span> |       <span class="material-icons sm:px-2 py-1 md:p-4 cursor-pointer text-xl sm:text-2xl" @click="closePlayer">close</span> | ||||||
|     </div> |     </div> | ||||||
|     <player-ui |     <player-ui | ||||||
|       ref="audioPlayer" |       ref="audioPlayer" | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="relative ml-8" v-click-outside="clickOutside"> |   <div ref="wrapper" class="relative ml-4 sm:ml-8" v-click-outside="clickOutside"> | ||||||
|     <div class="flex items-center justify-center text-gray-300 cursor-pointer h-full" @mousedown.prevent @mouseup.prevent @click="setShowMenu(true)"> |     <div class="flex items-center justify-center text-gray-300 cursor-pointer h-full" @mousedown.prevent @mouseup.prevent @click="setShowMenu(true)"> | ||||||
|       <span class="font-mono uppercase text-gray-200">{{ playbackRate.toFixed(1) }}<span class="text-lg">⨯</span></span> |       <span class="font-mono uppercase text-gray-200 text-sm sm:text-base">{{ playbackRate.toFixed(1) }}<span class="text-base sm:text-lg">⨯</span></span> | ||||||
|     </div> |     </div> | ||||||
|     <div v-show="showMenu" class="absolute -top-20 left-0 z-20 bg-bg border-black-200 border shadow-xl rounded-lg" style="left: -92px"> |     <div v-show="showMenu" class="absolute -top-20 z-20 bg-bg border-black-200 border shadow-xl rounded-lg" :style="{ left: menuLeft + 'px' }"> | ||||||
|       <div class="absolute -bottom-2 left-0 right-0 w-full flex justify-center"> |       <div class="absolute -bottom-1.5 right-0 w-full flex justify-center" :style="{ left: arrowLeft + 'px' }"> | ||||||
|         <div class="arrow-down" /> |         <div class="arrow-down" /> | ||||||
|       </div> |       </div> | ||||||
|       <div class="flex items-center h-9 relative overflow-hidden rounded-lg" style="width: 220px"> |       <div class="flex items-center h-9 relative overflow-hidden rounded-lg" style="width: 220px"> | ||||||
| @ -19,7 +19,7 @@ | |||||||
|       <div class="w-full py-1 px-4"> |       <div class="w-full py-1 px-4"> | ||||||
|         <div class="flex items-center justify-between"> |         <div class="flex items-center justify-between"> | ||||||
|           <ui-icon-btn :disabled="!canDecrement" icon="remove" @click="decrement" /> |           <ui-icon-btn :disabled="!canDecrement" icon="remove" @click="decrement" /> | ||||||
|           <p class="px-2 text-3xl">{{ playbackRate }}<span class="text-2xl">⨯</span></p> |           <p class="px-2 text-2xl sm:text-3xl">{{ playbackRate }}<span class="text-2xl">⨯</span></p> | ||||||
|           <ui-icon-btn :disabled="!canIncrement" icon="add" @click="increment" /> |           <ui-icon-btn :disabled="!canIncrement" icon="add" @click="increment" /> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| @ -40,7 +40,9 @@ export default { | |||||||
|       showMenu: false, |       showMenu: false, | ||||||
|       currentPlaybackRate: 0, |       currentPlaybackRate: 0, | ||||||
|       MIN_SPEED: 0.5, |       MIN_SPEED: 0.5, | ||||||
|       MAX_SPEED: 3 |       MAX_SPEED: 3, | ||||||
|  |       menuLeft: -92, | ||||||
|  |       arrowLeft: 0 | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   computed: { |   computed: { | ||||||
| @ -80,8 +82,22 @@ export default { | |||||||
|       var newPlaybackRate = this.playbackRate - 0.1 |       var newPlaybackRate = this.playbackRate - 0.1 | ||||||
|       this.playbackRate = Number(newPlaybackRate.toFixed(1)) |       this.playbackRate = Number(newPlaybackRate.toFixed(1)) | ||||||
|     }, |     }, | ||||||
|  |     updateMenuPositions() { | ||||||
|  |       if (!this.$refs.wrapper) return | ||||||
|  |       const boundingBox = this.$refs.wrapper.getBoundingClientRect() | ||||||
|  | 
 | ||||||
|  |       if (boundingBox.left + 110 > window.innerWidth - 10) { | ||||||
|  |         this.menuLeft = window.innerWidth - 230 - boundingBox.left | ||||||
|  | 
 | ||||||
|  |         this.arrowLeft = Math.abs(this.menuLeft) - 92 | ||||||
|  |       } else { | ||||||
|  |         this.menuLeft = -92 | ||||||
|  |         this.arrowLeft = 0 | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     setShowMenu(val) { |     setShowMenu(val) { | ||||||
|       if (val) { |       if (val) { | ||||||
|  |         this.updateMenuPositions() | ||||||
|         this.currentPlaybackRate = this.playbackRate |         this.currentPlaybackRate = this.playbackRate | ||||||
|       } else if (this.currentPlaybackRate !== this.playbackRate) { |       } else if (this.currentPlaybackRate !== this.playbackRate) { | ||||||
|         this.$emit('change', this.playbackRate) |         this.$emit('change', this.playbackRate) | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="relative" v-click-outside="clickOutside" @mouseover="mouseover" @mouseleave="mouseleave"> |   <div class="relative" v-click-outside="clickOutside" @mouseover="mouseover" @mouseleave="mouseleave"> | ||||||
|     <div class="cursor-pointer" @mousedown.prevent @mouseup.prevent @click="clickVolumeIcon"> |     <div class="cursor-pointer text-gray-300 hover:text-white" @mousedown.prevent @mouseup.prevent @click="clickVolumeIcon"> | ||||||
|       <span class="material-icons text-3xl">{{ volumeIcon }}</span> |       <span class="material-icons text-2xl sm:text-3xl">{{ volumeIcon }}</span> | ||||||
|     </div> |     </div> | ||||||
|     <transition name="menux"> |     <transition name="menux"> | ||||||
|       <div v-show="isOpen" class="volumeMenu h-6 absolute bottom-2 w-28 px-2 bg-bg shadow-sm rounded-lg" style="left: -116px"> |       <div v-show="isOpen" class="volumeMenu h-6 absolute bottom-2 w-28 px-2 bg-bg shadow-sm rounded-lg" style="left: -116px"> | ||||||
|  | |||||||
| @ -3,21 +3,21 @@ | |||||||
|     <div class="flex-grow" /> |     <div class="flex-grow" /> | ||||||
|     <template v-if="!loading"> |     <template v-if="!loading"> | ||||||
|       <div class="cursor-pointer flex items-center justify-center text-gray-300 mr-4 md:mr-8" @mousedown.prevent @mouseup.prevent @click.stop="prevChapter"> |       <div class="cursor-pointer flex items-center justify-center text-gray-300 mr-4 md:mr-8" @mousedown.prevent @mouseup.prevent @click.stop="prevChapter"> | ||||||
|         <span class="material-icons text-3xl">first_page</span> |         <span class="material-icons text-2xl sm:text-3xl">first_page</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="cursor-pointer flex items-center justify-center text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpBackward"> |       <div class="cursor-pointer flex items-center justify-center text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpBackward"> | ||||||
|         <span class="material-icons text-3xl">replay_10</span> |         <span class="material-icons text-2xl sm:text-3xl">replay_10</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="cursor-pointer p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-4 md:mx-8" :class="seekLoading ? 'animate-spin' : ''" @mousedown.prevent @mouseup.prevent @click.stop="playPause"> |       <div class="cursor-pointer p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-4 md:mx-8" :class="seekLoading ? 'animate-spin' : ''" @mousedown.prevent @mouseup.prevent @click.stop="playPause"> | ||||||
|         <span class="material-icons">{{ seekLoading ? 'autorenew' : paused ? 'play_arrow' : 'pause' }}</span> |         <span class="material-icons">{{ seekLoading ? 'autorenew' : paused ? 'play_arrow' : 'pause' }}</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="cursor-pointer flex items-center justify-center text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpForward"> |       <div class="cursor-pointer flex items-center justify-center text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpForward"> | ||||||
|         <span class="material-icons text-3xl">forward_10</span> |         <span class="material-icons text-2xl sm:text-3xl">forward_10</span> | ||||||
|       </div> |       </div> | ||||||
|       <div class="flex items-center justify-center ml-4 md:ml-8" :class="hasNextChapter ? 'text-gray-300 cursor-pointer' : 'text-gray-500'" @mousedown.prevent @mouseup.prevent @click.stop="nextChapter"> |       <div class="flex items-center justify-center ml-4 md:ml-8" :class="hasNextChapter ? 'text-gray-300 cursor-pointer' : 'text-gray-500'" @mousedown.prevent @mouseup.prevent @click.stop="nextChapter"> | ||||||
|         <span class="material-icons text-3xl">last_page</span> |         <span class="material-icons text-2xl sm:text-3xl">last_page</span> | ||||||
|       </div> |       </div> | ||||||
|       <controls-playback-speed-control v-model="playbackRate" @input="playbackRateUpdated" @change="playbackRateChanged" /> |       <controls-playback-speed-control v-model="playbackRateInput" @input="playbackRateUpdated" @change="playbackRateChanged" /> | ||||||
|     </template> |     </template> | ||||||
|     <template v-else> |     <template v-else> | ||||||
|       <div class="cursor-pointer p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-8 animate-spin"> |       <div class="cursor-pointer p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-8 animate-spin"> | ||||||
| @ -40,7 +40,16 @@ export default { | |||||||
|   data() { |   data() { | ||||||
|     return {} |     return {} | ||||||
|   }, |   }, | ||||||
|   computed: {}, |   computed: { | ||||||
|  |     playbackRateInput: { | ||||||
|  |       get() { | ||||||
|  |         return this.playbackRate | ||||||
|  |       }, | ||||||
|  |       set(val) { | ||||||
|  |         this.$emit('update:playbackRate', val) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     playPause() { |     playPause() { | ||||||
|       this.$emit('playPause') |       this.$emit('playPause') | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
|       <div ref="trackCursor" class="h-full w-0.5 bg-gray-50 absolute top-0 left-0 opacity-0 pointer-events-none" /> |       <div ref="trackCursor" class="h-full w-0.5 bg-gray-50 absolute top-0 left-0 opacity-0 pointer-events-none" /> | ||||||
|       <div v-if="loading" class="h-full w-1/4 absolute left-0 top-0 loadingTrack pointer-events-none bg-white bg-opacity-25" /> |       <div v-if="loading" class="h-full w-1/4 absolute left-0 top-0 loadingTrack pointer-events-none bg-white bg-opacity-25" /> | ||||||
|     </div> |     </div> | ||||||
|     <div ref="track" class="w-full h-2 relative overflow-hidden"> |     <div class="w-full h-2 relative overflow-hidden" :class="useChapterTrack ? 'opacity-0' : ''"> | ||||||
|       <template v-for="(tick, index) in chapterTicks"> |       <template v-for="(tick, index) in chapterTicks"> | ||||||
|         <div :key="index" :style="{ left: tick.left + 'px' }" class="absolute top-0 w-px bg-white bg-opacity-30 h-1 pointer-events-none" /> |         <div :key="index" :style="{ left: tick.left + 'px' }" class="absolute top-0 w-px bg-white bg-opacity-30 h-1 pointer-events-none" /> | ||||||
|       </template> |       </template> | ||||||
| @ -34,6 +34,10 @@ export default { | |||||||
|     chapters: { |     chapters: { | ||||||
|       type: Array, |       type: Array, | ||||||
|       default: () => [] |       default: () => [] | ||||||
|  |     }, | ||||||
|  |     currentChapter: { | ||||||
|  |       type: Object, | ||||||
|  |       default: () => {} | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
| @ -46,7 +50,8 @@ export default { | |||||||
|       trackOffsetLeft: 16, // Track is 16px from edge |       trackOffsetLeft: 16, // Track is 16px from edge | ||||||
|       playedTrackWidth: 0, |       playedTrackWidth: 0, | ||||||
|       readyTrackWidth: 0, |       readyTrackWidth: 0, | ||||||
|       bufferTrackWidth: 0 |       bufferTrackWidth: 0, | ||||||
|  |       useChapterTrack: false | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
| @ -57,8 +62,22 @@ export default { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   computed: {}, |   computed: { | ||||||
|  |     currentChapterDuration() { | ||||||
|  |       if (!this.currentChapter) return 0 | ||||||
|  |       return this.currentChapter.end - this.currentChapter.start | ||||||
|  |     }, | ||||||
|  |     currentChapterStart() { | ||||||
|  |       if (!this.currentChapter) return 0 | ||||||
|  |       return this.currentChapter.start | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     setUseChapterTrack(useChapterTrack) { | ||||||
|  |       this.useChapterTrack = useChapterTrack | ||||||
|  |       this.updateBufferTrack() | ||||||
|  |       this.updatePlayedTrackWidth() | ||||||
|  |     }, | ||||||
|     clickTrack(e) { |     clickTrack(e) { | ||||||
|       if (this.loading) return |       if (this.loading) return | ||||||
| 
 | 
 | ||||||
| @ -76,7 +95,10 @@ export default { | |||||||
|       this.updateBufferTrack() |       this.updateBufferTrack() | ||||||
|     }, |     }, | ||||||
|     updateBufferTrack() { |     updateBufferTrack() { | ||||||
|       var bufferlen = (this.bufferTime / this.duration) * this.trackWidth |       const time = this.useChapterTrack ? Math.max(0, this.bufferTime - this.currentChapterStart) : this.bufferTime | ||||||
|  |       const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration | ||||||
|  | 
 | ||||||
|  |       var bufferlen = (time / duration) * this.trackWidth | ||||||
|       bufferlen = Math.round(bufferlen) |       bufferlen = Math.round(bufferlen) | ||||||
|       if (this.bufferTrackWidth === bufferlen || !this.$refs.bufferTrack) return |       if (this.bufferTrackWidth === bufferlen || !this.$refs.bufferTrack) return | ||||||
|       if (this.$refs.bufferTrack) this.$refs.bufferTrack.style.width = bufferlen + 'px' |       if (this.$refs.bufferTrack) this.$refs.bufferTrack.style.width = bufferlen + 'px' | ||||||
| @ -97,8 +119,10 @@ export default { | |||||||
|       this.updatePlayedTrackWidth() |       this.updatePlayedTrackWidth() | ||||||
|     }, |     }, | ||||||
|     updatePlayedTrackWidth() { |     updatePlayedTrackWidth() { | ||||||
|       var perc = this.currentTime / this.duration |       const time = this.useChapterTrack ? Math.max(0, this.currentTime - this.currentChapterStart) : this.currentTime | ||||||
|       var ptWidth = Math.round(perc * this.trackWidth) |       const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration | ||||||
|  | 
 | ||||||
|  |       var ptWidth = Math.round((time / duration) * this.trackWidth) | ||||||
|       if (this.playedTrackWidth === ptWidth) { |       if (this.playedTrackWidth === ptWidth) { | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
| @ -116,9 +140,9 @@ export default { | |||||||
|     }, |     }, | ||||||
|     mousemoveTrack(e) { |     mousemoveTrack(e) { | ||||||
|       var offsetX = e.offsetX |       var offsetX = e.offsetX | ||||||
|       var time = (offsetX / this.trackWidth) * this.duration |  | ||||||
| 
 | 
 | ||||||
|       console.log('Mousemove track', this.trackWidth, this.duration) |       const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration | ||||||
|  |       const time = (offsetX / this.trackWidth) * duration | ||||||
| 
 | 
 | ||||||
|       if (this.$refs.hoverTimestamp) { |       if (this.$refs.hoverTimestamp) { | ||||||
|         var width = this.$refs.hoverTimestamp.clientWidth |         var width = this.$refs.hoverTimestamp.clientWidth | ||||||
|  | |||||||
| @ -1,44 +1,48 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="w-full -mt-6"> |   <div class="w-full -mt-6"> | ||||||
|     <div class="w-full relative mb-1"> |     <div class="w-full relative mb-1"> | ||||||
|       <div class="absolute -top-10 md:top-0 right-0 md:right-2 flex items-center h-full"> |       <div class="absolute -top-10 md:top-0 right-0 lg:right-2 flex items-center h-full"> | ||||||
|         <!-- <span class="material-icons text-2xl cursor-pointer" @click="toggleFullscreen(true)">expand_less</span> --> |         <!-- <span class="material-icons text-2xl cursor-pointer" @click="toggleFullscreen(true)">expand_less</span> --> | ||||||
| 
 | 
 | ||||||
|         <controls-volume-control ref="volumeControl" v-model="volume" @input="setVolume" class="mx-2 hidden md:block" /> |         <controls-volume-control ref="volumeControl" v-model="volume" @input="setVolume" class="mx-2 hidden md:block" /> | ||||||
| 
 | 
 | ||||||
|         <div class="cursor-pointer text-gray-300 mx-1 md:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showSleepTimer')"> |         <div class="cursor-pointer text-gray-300 hover:text-white mx-1 lg:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showSleepTimer')"> | ||||||
|           <span v-if="!sleepTimerSet" class="material-icons" style="font-size: 1.7rem">snooze</span> |           <span v-if="!sleepTimerSet" class="material-icons text-2xl sm:text-2.5xl">snooze</span> | ||||||
|           <div v-else class="flex items-center"> |           <div v-else class="flex items-center"> | ||||||
|             <span class="material-icons text-lg text-warning">snooze</span> |             <span class="material-icons text-lg text-warning">snooze</span> | ||||||
|             <p class="text-xl text-warning font-mono font-semibold text-center px-0.5 pb-0.5" style="min-width: 30px">{{ sleepTimerRemainingString }}</p> |             <p class="text-xl text-warning font-mono font-semibold text-center px-0.5 pb-0.5" style="min-width: 30px">{{ sleepTimerRemainingString }}</p> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div v-if="!isPodcast" class="cursor-pointer text-gray-300 mx-1 md:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showBookmarks')"> |         <div v-if="!isPodcast" class="cursor-pointer text-gray-300 hover:text-white mx-1 lg:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showBookmarks')"> | ||||||
|           <span class="material-icons" style="font-size: 1.7rem">{{ bookmarks.length ? 'bookmarks' : 'bookmark_border' }}</span> |           <span class="material-icons text-2xl sm:text-2.5xl">{{ bookmarks.length ? 'bookmarks' : 'bookmark_border' }}</span> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div v-if="chapters.length" class="cursor-pointer text-gray-300 mx-1 md:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="showChapters"> |         <div v-if="chapters.length" class="cursor-pointer text-gray-300 hover:text-white mx-1 lg:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="showChapters"> | ||||||
|           <span class="material-icons text-3xl">format_list_bulleted</span> |           <span class="material-icons text-2xl sm:text-3xl">format_list_bulleted</span> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <div v-if="chapters.length" class="cursor-pointer text-gray-300 mx-1 md:mx-2" @mousedown.prevent @mouseup.prevent @click.stop="setUseChapterTrack"> |         <ui-tooltip v-if="chapters.length" direction="top" :text="useChapterTrack ? 'Use full track' : 'Use chapter track'"> | ||||||
|           <span class="material-icons text-3xl">timelapse</span> |           <div class="cursor-pointer text-gray-300 mx-1 lg:mx-2 hover:text-white" @mousedown.prevent @mouseup.prevent @click.stop="setUseChapterTrack"> | ||||||
|  |             <span class="material-icons text-2xl sm:text-3xl transform transition-transform" :class="useChapterTrack ? 'rotate-180' : ''">timelapse</span> | ||||||
|           </div> |           </div> | ||||||
|  |         </ui-tooltip> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|       <player-playback-controls :loading="loading" :seek-loading="seekLoading" :playback-rate="playbackRate" :paused="paused" :has-next-chapter="hasNextChapter" @prevChapter="prevChapter" @nextChapter="nextChapter" @jumpForward="jumpForward" @jumpBackward="jumpBackward" @setPlaybackRate="setPlaybackRate" @playPause="playPause" /> |       <player-playback-controls :loading="loading" :seek-loading="seekLoading" :playback-rate.sync="playbackRate" :paused="paused" :has-next-chapter="hasNextChapter" @prevChapter="prevChapter" @nextChapter="nextChapter" @jumpForward="jumpForward" @jumpBackward="jumpBackward" @setPlaybackRate="setPlaybackRate" @playPause="playPause" /> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <player-track-bar ref="trackbar" :loading="loading" :chapters="chapters" :duration="duration" @seek="seek" /> |     <player-track-bar ref="trackbar" :loading="loading" :chapters="chapters" :duration="duration" :current-chapter="currentChapter" @seek="seek" /> | ||||||
| 
 | 
 | ||||||
|     <div class="flex"> |     <div class="flex"> | ||||||
|       <p ref="currentTimestamp" class="font-mono text-sm text-gray-100 pointer-events-auto">00:00:00</p> |       <p ref="currentTimestamp" class="font-mono text-xxs sm:text-sm text-gray-100 pointer-events-auto">00:00:00</p> | ||||||
|       <p class="font-mono text-sm text-gray-100 pointer-events-auto"> / {{ progressPercent }}%</p> |       <p class="font-mono text-sm hidden sm:block text-gray-100 pointer-events-auto"> / {{ progressPercent }}%</p> | ||||||
|       <div class="flex-grow" /> |       <div class="flex-grow" /> | ||||||
|       <p class="text-sm text-gray-300 pt-0.5">{{ currentChapterName }}</p> |       <p class="text-xs sm:text-sm text-gray-300 pt-0.5"> | ||||||
|  |         {{ currentChapterName }} <span v-if="useChapterTrack" class="text-xs text-gray-400"> ({{ currentChapterIndex + 1 }} of {{ chapters.length }})</span> | ||||||
|  |       </p> | ||||||
|       <div class="flex-grow" /> |       <div class="flex-grow" /> | ||||||
|       <p class="font-mono text-sm text-gray-100 pointer-events-auto">{{ timeRemainingPretty }}</p> |       <p class="font-mono text-xxs sm:text-sm text-gray-100 pointer-events-auto">{{ timeRemainingPretty }}</p> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <modals-chapters-modal v-model="showChaptersModal" :current-chapter="currentChapter" :chapters="chapters" @select="selectChapter" /> |     <modals-chapters-modal v-model="showChaptersModal" :current-chapter="currentChapter" :chapters="chapters" @select="selectChapter" /> | ||||||
| @ -104,8 +108,11 @@ export default { | |||||||
|       return '-' + this.$secondsToTimestamp(this.timeRemaining) |       return '-' + this.$secondsToTimestamp(this.timeRemaining) | ||||||
|     }, |     }, | ||||||
|     progressPercent() { |     progressPercent() { | ||||||
|       if (!this.duration) return 0 |       const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration | ||||||
|       return Math.round((100 * this.currentTime) / this.duration) |       const time = this.useChapterTrack ? Math.max(this.currentTime - this.currentChapterStart) : this.currentTime | ||||||
|  | 
 | ||||||
|  |       if (!duration) return 0 | ||||||
|  |       return Math.round((100 * time) / duration) | ||||||
|     }, |     }, | ||||||
|     currentChapter() { |     currentChapter() { | ||||||
|       return this.chapters.find((chapter) => chapter.start <= this.currentTime && this.currentTime < chapter.end) |       return this.chapters.find((chapter) => chapter.start <= this.currentTime && this.currentTime < chapter.end) | ||||||
| @ -114,7 +121,12 @@ export default { | |||||||
|       return this.currentChapter ? this.currentChapter.title : '' |       return this.currentChapter ? this.currentChapter.title : '' | ||||||
|     }, |     }, | ||||||
|     currentChapterDuration() { |     currentChapterDuration() { | ||||||
|       return (this.currentChapter.end - this.currentChapter.start) |       if (!this.currentChapter) return 0 | ||||||
|  |       return this.currentChapter.end - this.currentChapter.start | ||||||
|  |     }, | ||||||
|  |     currentChapterStart() { | ||||||
|  |       if (!this.currentChapter) return 0 | ||||||
|  |       return this.currentChapter.start | ||||||
|     }, |     }, | ||||||
|     isFullscreen() { |     isFullscreen() { | ||||||
|       return this.$store.state.playerIsFullscreen |       return this.$store.state.playerIsFullscreen | ||||||
| @ -207,11 +219,12 @@ export default { | |||||||
|     setUseChapterTrack() { |     setUseChapterTrack() { | ||||||
|       var useChapterTrack = !this.useChapterTrack |       var useChapterTrack = !this.useChapterTrack | ||||||
|       this.useChapterTrack = useChapterTrack |       this.useChapterTrack = useChapterTrack | ||||||
|  |       if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(useChapterTrack) | ||||||
| 
 | 
 | ||||||
|       this.$emit('useChapterTrack', useChapterTrack) |  | ||||||
|       this.$store.dispatch('user/updateUserSettings', { useChapterTrack }).catch((err) => { |       this.$store.dispatch('user/updateUserSettings', { useChapterTrack }).catch((err) => { | ||||||
|         console.error('Failed to update settings', err) |         console.error('Failed to update settings', err) | ||||||
|       }) |       }) | ||||||
|  |       this.updateTimestamp() | ||||||
|     }, |     }, | ||||||
|     seek(time) { |     seek(time) { | ||||||
|       this.$emit('seek', time) |       this.$emit('seek', time) | ||||||
| @ -260,7 +273,8 @@ export default { | |||||||
|         console.error('No timestamp el') |         console.error('No timestamp el') | ||||||
|         return |         return | ||||||
|       } |       } | ||||||
|       var currTimeClean = this.$secondsToTimestamp(this.currentTime) |       const time = this.useChapterTrack ? Math.max(0, this.currentTime - this.currentChapterStart) : this.currentTime | ||||||
|  |       var currTimeClean = this.$secondsToTimestamp(time) | ||||||
|       ts.innerText = currTimeClean |       ts.innerText = currTimeClean | ||||||
|     }, |     }, | ||||||
|     setBufferTime(bufferTime) { |     setBufferTime(bufferTime) { | ||||||
| @ -273,8 +287,8 @@ export default { | |||||||
|     init() { |     init() { | ||||||
|       this.playbackRate = this.$store.getters['user/getUserSetting']('playbackRate') || 1 |       this.playbackRate = this.$store.getters['user/getUserSetting']('playbackRate') || 1 | ||||||
|       this.useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false |       this.useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false | ||||||
|  |       if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack) | ||||||
|       this.$emit('setPlaybackRate', this.playbackRate) |       this.$emit('setPlaybackRate', this.playbackRate) | ||||||
|       this.$emit('useChapterTrack', this.useChapterTrack) |  | ||||||
|     }, |     }, | ||||||
|     settingsUpdated(settings) { |     settingsUpdated(settings) { | ||||||
|       if (settings.playbackRate && this.playbackRate !== settings.playbackRate) { |       if (settings.playbackRate && this.playbackRate !== settings.playbackRate) { | ||||||
|  | |||||||
| @ -53,7 +53,7 @@ export default { | |||||||
|       var tooltip = document.createElement('div') |       var tooltip = document.createElement('div') | ||||||
|       this.tooltipId = String(Math.floor(Math.random() * 10000)) |       this.tooltipId = String(Math.floor(Math.random() * 10000)) | ||||||
|       tooltip.id = this.tooltipId |       tooltip.id = this.tooltipId | ||||||
|       tooltip.className = 'tooltip-wrapper absolute px-2 py-1 text-white pointer-events-none text-xs rounded shadow-lg max-w-xs' |       tooltip.className = 'tooltip-wrapper absolute px-2 py-1 text-white pointer-events-none text-xs rounded shadow-lg max-w-xs text-center hidden sm:block' | ||||||
|       tooltip.style.zIndex = 100 |       tooltip.style.zIndex = 100 | ||||||
|       tooltip.style.backgroundColor = 'rgba(0,0,0,0.85)' |       tooltip.style.backgroundColor = 'rgba(0,0,0,0.85)' | ||||||
|       tooltip.innerHTML = this.text |       tooltip.innerHTML = this.text | ||||||
|  | |||||||
| @ -80,7 +80,8 @@ module.exports = { | |||||||
|         book: ['Gentium Book Basic', 'serif'] |         book: ['Gentium Book Basic', 'serif'] | ||||||
|       }, |       }, | ||||||
|       fontSize: { |       fontSize: { | ||||||
|         xxs: '0.625rem' |         xxs: '0.625rem', | ||||||
|  |         '2.5xl': '1.6875rem' | ||||||
|       }, |       }, | ||||||
|       zIndex: { |       zIndex: { | ||||||
|         '50': 50 |         '50': 50 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user