mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-04-07 01:15:44 +02:00
show a modal with cover images when clicked
This commit is contained in:
parent
0ee6336b02
commit
32616aa441
@ -2,7 +2,7 @@
|
|||||||
<div v-if="streamLibraryItem" id="streamContainer" class="w-full fixed bottom-0 left-0 right-0 h-48 md:h-40 z-50 bg-primary px-2 md: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 md:h-40 z-50 bg-primary px-2 md: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-2 top-2 md:left-4 cursor-pointer">
|
<nuxt-link v-if="!playerHandler.isVideo" :to="`/item/${streamLibraryItem.id}`" class="absolute left-2 top-2 md:left-4 cursor-pointer">
|
||||||
<covers-book-cover :library-item="streamLibraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="coverAspectRatio" />
|
<covers-book-cover :expand-on-click="true" :library-item="streamLibraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="coverAspectRatio" />
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<div class="flex items-start mb-6 md:mb-0" :class="playerHandler.isVideo ? 'ml-4 pl-96' : isSquareCover ? 'pl-18 sm:pl-24' : 'pl-12 sm:pl-16'">
|
<div class="flex items-start mb-6 md:mb-0" :class="playerHandler.isVideo ? 'ml-4 pl-96' : isSquareCover ? 'pl-18 sm:pl-24' : 'pl-12 sm:pl-16'">
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
|
@ -5,7 +5,14 @@
|
|||||||
<div class="absolute cover-bg" ref="coverBg" />
|
<div class="absolute cover-bg" ref="coverBg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img v-if="libraryItem" ref="cover" :src="fullCoverUrl" loading="lazy" @error="imageError" @load="imageLoaded" class="w-full h-full absolute top-0 left-0 z-10 duration-300 transition-opacity" :style="{ opacity: imageReady ? '1' : '0' }" :class="showCoverBg ? 'object-contain' : 'object-fill'" />
|
<img v-if="libraryItem" ref="cover" :src="fullCoverUrl" loading="lazy" draggable="false" @error="imageError" @load="imageLoaded" class="w-full h-full absolute top-0 left-0 z-10 duration-300 transition-opacity" :style="{ opacity: imageReady ? '1' : '0' }" :class="showCoverBg ? 'object-contain' : 'object-fill'" @click="clickCover" />
|
||||||
|
|
||||||
|
<modals-modal v-if="libraryItem && expandOnClick" v-model="showImageModal" name="cover" :width="'90%'" :height="'90%'" :contentMarginTop="0">
|
||||||
|
<div class="w-full h-full" @click="showImageModal = false">
|
||||||
|
<img loading="lazy" :src="rawCoverUrl" class="w-full h-full z-10 object-scale-down" />
|
||||||
|
</div>
|
||||||
|
</modals-modal>
|
||||||
|
|
||||||
<div v-show="loading && libraryItem" class="absolute top-0 left-0 h-full w-full flex items-center justify-center">
|
<div v-show="loading && libraryItem" class="absolute top-0 left-0 h-full w-full flex items-center justify-center">
|
||||||
<p class="text-center" :style="{ fontSize: 0.75 * sizeMultiplier + 'rem' }">{{ title }}</p>
|
<p class="text-center" :style="{ fontSize: 0.75 * sizeMultiplier + 'rem' }">{{ title }}</p>
|
||||||
<div class="absolute top-2 right-2">
|
<div class="absolute top-2 right-2">
|
||||||
@ -43,10 +50,12 @@ export default {
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 120
|
default: 120
|
||||||
},
|
},
|
||||||
|
expandOnClick: Boolean,
|
||||||
bookCoverAspectRatio: Number
|
bookCoverAspectRatio: Number
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
showImageModal: false,
|
||||||
loading: true,
|
loading: true,
|
||||||
imageFailed: false,
|
imageFailed: false,
|
||||||
showCoverBg: false,
|
showCoverBg: false,
|
||||||
@ -102,6 +111,11 @@ export default {
|
|||||||
var store = this.$store || this.$nuxt.$store
|
var store = this.$store || this.$nuxt.$store
|
||||||
return store.getters['globals/getLibraryItemCoverSrc'](this.libraryItem, this.placeholderUrl)
|
return store.getters['globals/getLibraryItemCoverSrc'](this.libraryItem, this.placeholderUrl)
|
||||||
},
|
},
|
||||||
|
rawCoverUrl() {
|
||||||
|
if (!this.libraryItem) return null
|
||||||
|
var store = this.$store || this.$nuxt.$store
|
||||||
|
return store.getters['globals/getLibraryItemCoverSrc'](this.libraryItem, null, true)
|
||||||
|
},
|
||||||
cover() {
|
cover() {
|
||||||
return this.media.coverPath || this.placeholderUrl
|
return this.media.coverPath || this.placeholderUrl
|
||||||
},
|
},
|
||||||
@ -132,6 +146,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
clickCover() {
|
||||||
|
this.showImageModal = true
|
||||||
|
},
|
||||||
setCoverBg() {
|
setCoverBg() {
|
||||||
if (this.$refs.coverBg) {
|
if (this.$refs.coverBg) {
|
||||||
this.$refs.coverBg.style.backgroundImage = `url("${this.fullCoverUrl}")`
|
this.$refs.coverBg.style.backgroundImage = `url("${this.fullCoverUrl}")`
|
||||||
|
@ -3,21 +3,21 @@
|
|||||||
<div class="w-full h-full overflow-y-auto px-2 py-6 lg:p-8">
|
<div class="w-full h-full overflow-y-auto px-2 py-6 lg:p-8">
|
||||||
<div class="flex flex-col lg:flex-row max-w-6xl mx-auto">
|
<div class="flex flex-col lg:flex-row max-w-6xl mx-auto">
|
||||||
<div class="w-full flex justify-center lg:block lg:w-52" style="min-width: 208px">
|
<div class="w-full flex justify-center lg:block lg:w-52" style="min-width: 208px">
|
||||||
<div class="relative" style="height: fit-content">
|
<div class="relative group" style="height: fit-content">
|
||||||
<covers-book-cover :library-item="libraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
<covers-book-cover class="relative group-hover:brightness-75 transition" :expand-on-click="true" :library-item="libraryItem" :width="bookCoverWidth" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||||
|
|
||||||
<!-- Item Progress Bar -->
|
<!-- Item Progress Bar -->
|
||||||
<div v-if="!isPodcast" class="absolute bottom-0 left-0 h-1.5 shadow-sm z-10" :class="userIsFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: 208 * progressPercent + 'px' }"></div>
|
<div v-if="!isPodcast" class="absolute bottom-0 left-0 h-1.5 shadow-sm z-10" :class="userIsFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: 208 * progressPercent + 'px' }"></div>
|
||||||
|
|
||||||
<!-- Item Cover Overlay -->
|
<!-- Item Cover Overlay -->
|
||||||
<div class="absolute top-0 left-0 w-full h-full z-10 bg-black bg-opacity-30 opacity-0 hover:opacity-100 transition-opacity" @mousedown.prevent @mouseup.prevent>
|
<div class="absolute top-0 left-0 w-full h-full z-10 pointer-events-none">
|
||||||
<div v-show="showPlayButton && !isStreaming" class="h-full flex items-center justify-center pointer-events-none">
|
<div v-show="showPlayButton && !isStreaming" class="h-full flex items-center justify-center pointer-events-none">
|
||||||
<div class="hover:text-white text-gray-200 hover:scale-110 transform duration-200 pointer-events-auto cursor-pointer" @click.stop.prevent="playItem">
|
<div class="hover:text-white text-gray-200 hover:scale-110 transform duration-200 pointer-events-auto cursor-pointer" @click.stop.prevent="playItem">
|
||||||
<span class="material-icons text-4xl">play_circle_filled</span>
|
<span class="material-icons text-4xl">play_circle_filled</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="absolute bottom-2.5 right-2.5 z-10 material-icons text-lg cursor-pointer text-white text-opacity-75 hover:text-opacity-100 hover:scale-110 transform duration-200" @click="showEditCover">edit</span>
|
<span class="absolute bottom-2.5 right-2.5 z-10 material-icons text-lg cursor-pointer text-white text-opacity-75 hover:text-opacity-100 hover:scale-110 transform duration-200 pointer-events-auto" @click="showEditCover">edit</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,7 +80,7 @@ export const state = () => ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder = null) => {
|
getLibraryItemCoverSrc: (state, getters, rootState, rootGetters) => (libraryItem, placeholder = null, raw = false) => {
|
||||||
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
|
if (!placeholder) placeholder = `${rootState.routerBasePath}/book_placeholder.jpg`
|
||||||
if (!libraryItem) return placeholder
|
if (!libraryItem) return placeholder
|
||||||
const media = libraryItem.media
|
const media = libraryItem.media
|
||||||
@ -94,7 +94,7 @@ export const getters = {
|
|||||||
const libraryItemId = libraryItem.libraryItemId || libraryItem.id // Workaround for /users/:id page showing media progress covers
|
const libraryItemId = libraryItem.libraryItemId || libraryItem.id // Workaround for /users/:id page showing media progress covers
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') { // Testing
|
if (process.env.NODE_ENV !== 'production') { // Testing
|
||||||
return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}`
|
return `http://localhost:3333${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}${raw ? '&raw=1' : ''}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}`
|
return `${rootState.routerBasePath}/api/items/${libraryItemId}/cover?token=${userToken}&ts=${lastUpdate}`
|
||||||
|
Loading…
Reference in New Issue
Block a user