mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Podcast episode player fixes, episode table ui updates
This commit is contained in:
		
							parent
							
								
									0e665e2091
								
							
						
					
					
						commit
						12027b9a76
					
				| @ -187,3 +187,15 @@ Bookshelf Label | ||||
|   opacity: 1; | ||||
|   filter: blur(20px); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| .episode-subtitle { | ||||
|   word-break: break-word; | ||||
|   overflow: hidden; | ||||
|   text-overflow: ellipsis; | ||||
|   display: -webkit-box; | ||||
|   line-height: 16px; /* fallback */ | ||||
|   max-height: 32px; /* fallback */ | ||||
|   -webkit-line-clamp: 2; /* number of lines to show */ | ||||
|   -webkit-box-orient: vertical; | ||||
| } | ||||
| @ -34,9 +34,6 @@ | ||||
|             <div class="p-1 w-full"> | ||||
|               <ui-text-input-with-label v-model="fullPath" label="Podcast Path" readonly /> | ||||
|             </div> | ||||
|             <div class="p-2 w-full"> | ||||
|               <ui-checkbox v-model="podcast.autoDownloadEpisodes" label="Auto Download Episodes" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="w-full md:w-1/2 p-4"> | ||||
| @ -59,6 +56,9 @@ | ||||
|       </div> | ||||
|       <div class="flex items-center py-4"> | ||||
|         <div class="flex-grow" /> | ||||
|         <div class="px-4"> | ||||
|           <ui-checkbox v-model="podcast.autoDownloadEpisodes" label="Auto Download Episodes" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" /> | ||||
|         </div> | ||||
|         <ui-btn color="success" :disabled="disableSubmit" @click="submit">{{ buttonText }}</ui-btn> | ||||
|       </div> | ||||
|     </div> | ||||
| @ -262,14 +262,4 @@ export default { | ||||
| #episodes-scroll { | ||||
|   max-height: calc(80vh - 200px); | ||||
| } | ||||
| .episode-subtitle { | ||||
|   word-break: break-word; | ||||
|   overflow: hidden; | ||||
|   text-overflow: ellipsis; | ||||
|   display: -webkit-box; | ||||
|   line-height: 16px; /* fallback */ | ||||
|   max-height: 32px; /* fallback */ | ||||
|   -webkit-line-clamp: 2; /* number of lines to show */ | ||||
|   -webkit-box-orient: vertical; | ||||
| } | ||||
| </style> | ||||
| @ -10,13 +10,13 @@ | ||||
|         <p class="text-sm font-semibold"> | ||||
|           {{ title }} | ||||
|         </p> | ||||
|         <p class="text-sm"> | ||||
|         <p class="text-sm text-gray-200 episode-subtitle mt-1.5 mb-0.5"> | ||||
|           {{ description }} | ||||
|         </p> | ||||
|         <div class="flex items-center pt-2"> | ||||
|           <div 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" :class="userIsFinished ? 'text-white text-opacity-40' : ''" @click="playClick"> | ||||
|             <span class="material-icons">{{ streamIsPlaying ? 'pause' : 'play_arrow' }}</span> | ||||
|             <p class="pl-2 pr-1 text-sm">{{ timeRemaining }}</p> | ||||
|             <span class="material-icons" :class="streamIsPlaying ? '' : 'text-success'">{{ streamIsPlaying ? 'pause' : 'play_arrow' }}</span> | ||||
|             <p class="pl-2 pr-1 text-sm font-semibold">{{ timeRemaining }}</p> | ||||
|           </div> | ||||
| 
 | ||||
|           <ui-tooltip :text="userIsFinished ? 'Mark as Not Finished' : 'Mark as Finished'" direction="top"> | ||||
| @ -37,7 +37,7 @@ | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <div v-if="!userIsFinished" class="absolute bottom-0 left-0 h-1 bg-warning" :style="{ width: itemProgressPercent * 100 + '%' }" /> | ||||
|     <div v-if="!userIsFinished" class="absolute bottom-0 left-0 h-0.5 bg-warning" :style="{ width: itemProgressPercent * 100 + '%' }" /> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| @ -75,7 +75,9 @@ export default { | ||||
|       return this.episode.title || '' | ||||
|     }, | ||||
|     description() { | ||||
|       return this.episode.description || '' | ||||
|       if (this.episode.subtitle) return this.episode.subtitle | ||||
|       var desc = this.episode.description || '' | ||||
|       return desc | ||||
|     }, | ||||
|     duration() { | ||||
|       return this.$secondsToTimestamp(this.episode.duration) | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| <template> | ||||
|   <div class="w-full py-6"> | ||||
|     <p class="text-lg mb-0 font-semibold">Episodes</p> | ||||
|     <p v-if="!episodes.length" class="py-4 text-center text-lg"> | ||||
|       No Episodes | ||||
|     </p> | ||||
|     <draggable v-model="episodesCopy" v-bind="dragOptions" class="list-group" handle=".drag-handle" draggable=".item" tag="div" @start="drag = true" @end="drag = false" @update="draggableUpdate"> | ||||
|       <transition-group type="transition" :name="!drag ? 'episode' : null"> | ||||
|         <template v-for="episode in episodesCopy"> | ||||
|  | ||||
| @ -40,6 +40,10 @@ | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="flex-grow px-1 pt-6"> | ||||
|           <ui-checkbox v-model="autoDownloadEpisodes" label="Auto Download New Episodes" checkbox-bg="primary" border-color="gray-600" label-class="pl-2 text-base font-semibold" /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </form> | ||||
|   </div> | ||||
| @ -193,6 +197,11 @@ export default { | ||||
|       if (!this.stringArrayEqual(this.newTags, this.media.tags || [])) { | ||||
|         updatePayload.tags = [...this.newTags] | ||||
|       } | ||||
| 
 | ||||
|       if (this.media.autoDownloadEpisodes !== this.autoDownloadEpisodes) { | ||||
|         updatePayload.autoDownloadEpisodes = !!this.autoDownloadEpisodes | ||||
|       } | ||||
| 
 | ||||
|       return { | ||||
|         updatePayload, | ||||
|         hasChanges: !!Object.keys(updatePayload).length | ||||
|  | ||||
| @ -110,7 +110,7 @@ | ||||
|           <div class="flex items-center justify-center md:justify-start pt-4"> | ||||
|             <ui-btn v-if="showPlayButton" :disabled="streaming" color="success" :padding-x="4" small class="flex items-center h-9 mr-2" @click="startStream"> | ||||
|               <span v-show="!streaming" class="material-icons -ml-2 pr-1 text-white">play_arrow</span> | ||||
|               {{ streaming ? 'Streaming' : 'Play' }} | ||||
|               {{ streaming ? 'Playing' : 'Play' }} | ||||
|             </ui-btn> | ||||
|             <ui-btn v-else-if="isMissing || isInvalid" color="error" :padding-x="4" small class="flex items-center h-9 mr-2"> | ||||
|               <span v-show="!streaming" class="material-icons -ml-2 pr-1 text-white">error</span> | ||||
|  | ||||
| @ -62,6 +62,7 @@ class PodcastController { | ||||
| 
 | ||||
|     // Download and save cover image
 | ||||
|     if (payload.media.metadata.imageUrl) { | ||||
|       // TODO: Scan cover image to library files
 | ||||
|       var coverResponse = await this.coverManager.downloadCoverFromUrl(libraryItem, payload.media.metadata.imageUrl) | ||||
|       if (coverResponse) { | ||||
|         if (coverResponse.error) { | ||||
|  | ||||
| @ -84,9 +84,11 @@ class PodcastManager { | ||||
|       Logger.error(`[PodcastManager] Podcast Episode finished but library item was not found ${this.currentDownload.libraryItem.id}`) | ||||
|       return false | ||||
|     } | ||||
| 
 | ||||
|     var podcastEpisode = this.currentDownload.podcastEpisode | ||||
|     podcastEpisode.audioFile = audioFile | ||||
|     libraryItem.media.addPodcastEpisode(podcastEpisode) | ||||
|     libraryItem.libraryFiles.push(libraryFile) | ||||
|     libraryItem.updatedAt = Date.now() | ||||
|     await this.db.updateLibraryItem(libraryItem) | ||||
|     this.emitter('item_updated', libraryItem.toJSONExpanded()) | ||||
|  | ||||
| @ -24,7 +24,7 @@ class PodcastEpisodeDownload { | ||||
|   } | ||||
| 
 | ||||
|   get targetRelPath() { | ||||
|     return Path.join(this.libraryItem.relPath, this.targetFilename) | ||||
|     return this.targetFilename | ||||
|   } | ||||
| 
 | ||||
|   setData(podcastEpisode, libraryItem) { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| const Path = require('path') | ||||
| 
 | ||||
| const { encodeUriPath } = require('../../utils/index') | ||||
| class AudioTrack { | ||||
|   constructor() { | ||||
|     this.index = null | ||||
| @ -26,7 +26,7 @@ class AudioTrack { | ||||
|     this.startOffset = startOffset | ||||
|     this.duration = audioFile.duration | ||||
|     this.title = audioFile.metadata.filename || '' | ||||
|     this.contentUrl = Path.join(`/s/item/${itemId}`, audioFile.metadata.relPath) | ||||
|     this.contentUrl = Path.join(`/s/item/${itemId}`, encodeUriPath(audioFile.metadata.relPath)) | ||||
|     this.mimeType = audioFile.mimeType | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| const Logger = require('../../Logger') | ||||
| const PodcastEpisode = require('../entities/PodcastEpisode') | ||||
| const PodcastMetadata = require('../metadata/PodcastMetadata') | ||||
| const { areEquivalent, copyValue } = require('../../utils/index') | ||||
|  | ||||
| @ -18,6 +18,7 @@ class StaticRouter { | ||||
| 
 | ||||
|       var remainingPath = req.params['0'] | ||||
|       var fullPath = Path.join(item.path, remainingPath) | ||||
|       console.log('fullpath', fullPath) | ||||
|       res.sendFile(fullPath) | ||||
|     }) | ||||
|   } | ||||
|  | ||||
| @ -117,4 +117,8 @@ module.exports.copyValue = (val) => { | ||||
|     } | ||||
|     return final | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| module.exports.encodeUriPath = (path) => { | ||||
|   return path.replace(/\\/g, '/').replace(/%/g, '%25').replace(/#/g, '%23') | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user