mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-19 00:18:56 +01:00
Update:Audio player visible when ereader is open #1800 and adding zoom to PDF reader
This commit is contained in:
parent
2cc23b6d6b
commit
2fa73f7a8d
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="w-full h-full">
|
||||
<div v-show="showPageMenu" v-click-outside="clickOutside" class="pagemenu absolute top-9 right-20 rounded-md overflow-y-auto bg-bg shadow-lg z-20 border border-gray-400 w-52">
|
||||
<div v-show="showPageMenu" v-click-outside="clickOutside" class="pagemenu absolute top-9 left-8 rounded-md overflow-y-auto bg-bg shadow-lg z-20 border border-gray-400 w-52">
|
||||
<div v-for="(file, index) in pages" :key="file" class="w-full cursor-pointer hover:bg-black-200 px-2 py-1" :class="page === index ? 'bg-black-200' : ''" @click="setPage(index)">
|
||||
<p class="text-sm truncate">{{ file }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="showInfoMenu" v-click-outside="clickOutside" class="pagemenu absolute top-9 right-10 rounded-md overflow-y-auto bg-bg shadow-lg z-20 border border-gray-400 w-96">
|
||||
<div v-show="showInfoMenu" v-click-outside="clickOutside" class="pagemenu absolute top-9 left-20 rounded-md overflow-y-auto bg-bg shadow-lg z-20 border border-gray-400 w-96">
|
||||
<div v-for="key in comicMetadataKeys" :key="key" class="w-full px-2 py-1">
|
||||
<p class="text-xs">
|
||||
<strong>{{ key }}</strong
|
||||
@ -14,17 +14,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="comicMetadata" class="absolute top-0 right-52 bg-bg text-gray-100 border-b border-l border-r border-gray-400 hover:bg-black-200 cursor-pointer rounded-b-md w-10 h-9 flex items-center justify-center text-center z-20" @mousedown.prevent @click.stop.prevent="showInfoMenu = !showInfoMenu">
|
||||
<div v-if="comicMetadata" class="absolute top-0 left-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 hover:bg-black-200 cursor-pointer rounded-b-md w-10 h-9 flex items-center justify-center text-center z-20" @mousedown.prevent @click.stop.prevent="showInfoMenu = !showInfoMenu">
|
||||
<span class="material-icons text-xl">more</span>
|
||||
</div>
|
||||
<div class="absolute top-0 bg-bg text-gray-100 border-b border-l border-r border-gray-400 hover:bg-black-200 cursor-pointer rounded-b-md w-10 h-9 flex items-center justify-center text-center z-20" style="right: 156px" @mousedown.prevent @click.stop.prevent="showPageMenu = !showPageMenu">
|
||||
<div class="absolute top-0 left-8 bg-bg text-gray-100 border-b border-l border-r border-gray-400 hover:bg-black-200 cursor-pointer rounded-b-md w-10 h-9 flex items-center justify-center text-center z-20" @mousedown.prevent @click.stop.prevent="showPageMenu = !showPageMenu">
|
||||
<span class="material-icons text-xl">menu</span>
|
||||
</div>
|
||||
<div class="absolute top-0 right-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 rounded-b-md px-2 h-9 flex items-center text-center z-20">
|
||||
<div class="absolute top-0 right-16 bg-bg text-gray-100 border-b border-l border-r border-gray-400 rounded-b-md px-2 h-9 flex items-center text-center z-20">
|
||||
<p class="font-mono">{{ page + 1 }} / {{ numPages }}</p>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden m-auto comicwrapper relative">
|
||||
<div class="overflow-hidden w-full h-full relative">
|
||||
<div v-show="canGoPrev" class="absolute top-0 left-0 h-full w-1/2 hover:opacity-100 opacity-0 z-10 cursor-pointer" @click.stop.prevent="prev" @mousedown.prevent>
|
||||
<div class="flex items-center justify-center h-full w-1/2">
|
||||
<span v-show="loadedFirstPage" class="material-icons text-5xl text-white cursor-pointer text-opacity-30 hover:text-opacity-90">arrow_back_ios</span>
|
||||
@ -36,17 +36,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="h-full flex justify-center">
|
||||
<img v-if="mainImg" :src="mainImg" class="object-contain comicimg" />
|
||||
<img v-if="mainImg" :src="mainImg" class="object-contain h-full m-auto" />
|
||||
</div>
|
||||
|
||||
<div v-show="loading" class="w-full h-full absolute top-0 left-0 flex items-center justify-center z-10">
|
||||
<ui-loading-indicator />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div v-show="loading" class="w-screen h-screen absolute top-0 left-0 bg-black bg-opacity-20 flex items-center justify-center">
|
||||
<ui-loading-indicator />
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -61,7 +57,12 @@ Archive.init({
|
||||
|
||||
export default {
|
||||
props: {
|
||||
url: String
|
||||
url: String,
|
||||
libraryItem: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
playerOpen: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -249,15 +250,6 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
.pagemenu {
|
||||
max-height: calc(100vh - 60px);
|
||||
}
|
||||
.comicimg {
|
||||
height: calc(100vh - 40px);
|
||||
margin: auto;
|
||||
}
|
||||
.comicwrapper {
|
||||
width: 100vw;
|
||||
height: calc(100vh - 40px);
|
||||
margin-top: 20px;
|
||||
max-height: calc(100% - 48px);
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="h-full w-full">
|
||||
<div id="epub-reader" class="h-full w-full">
|
||||
<div class="h-full flex items-center justify-center">
|
||||
<div style="width: 100px; max-width: 100px" class="h-full hidden sm:flex items-center overflow-x-hidden justify-center">
|
||||
<span v-if="hasPrev" class="material-icons text-white text-opacity-50 hover:text-opacity-80 cursor-pointer text-6xl" @mousedown.prevent @click="prev">chevron_left</span>
|
||||
@ -28,17 +28,24 @@ export default {
|
||||
libraryItem: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
playerOpen: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
windowWidth: 0,
|
||||
windowHeight: 0,
|
||||
/** @type {ePub.Book} */
|
||||
book: null,
|
||||
/** @type {ePub.Rendition} */
|
||||
rendition: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
playerOpen() {
|
||||
this.resize()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** @returns {string} */
|
||||
libraryItemId() {
|
||||
@ -64,6 +71,10 @@ export default {
|
||||
readerWidth() {
|
||||
if (this.windowWidth < 640) return this.windowWidth
|
||||
return this.windowWidth - 200
|
||||
},
|
||||
readerHeight() {
|
||||
if (this.windowHeight < 400 || !this.playerOpen) return this.windowHeight
|
||||
return this.windowHeight - 164
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -203,13 +214,13 @@ export default {
|
||||
/** @type {ePub.Book} */
|
||||
reader.book = new ePub(reader.url, {
|
||||
width: this.readerWidth,
|
||||
height: window.innerHeight - 50
|
||||
height: this.readerHeight - 50
|
||||
})
|
||||
|
||||
/** @type {ePub.Rendition} */
|
||||
reader.rendition = reader.book.renderTo('viewer', {
|
||||
width: this.readerWidth,
|
||||
height: window.innerHeight * 0.8
|
||||
height: this.readerHeight * 0.8
|
||||
})
|
||||
|
||||
// load saved progress
|
||||
@ -253,17 +264,19 @@ export default {
|
||||
},
|
||||
resize() {
|
||||
this.windowWidth = window.innerWidth
|
||||
this.rendition?.resize(this.readerWidth, window.innerHeight * 0.8)
|
||||
this.windowHeight = window.innerHeight
|
||||
this.rendition?.resize(this.readerWidth, this.readerHeight * 0.8)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.windowWidth = window.innerWidth
|
||||
this.windowHeight = window.innerHeight
|
||||
window.addEventListener('resize', this.resize)
|
||||
this.initEpub()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.book?.destroy()
|
||||
},
|
||||
mounted() {
|
||||
this.windowWidth = window.innerWidth
|
||||
window.addEventListener('resize', this.resize)
|
||||
this.initEpub()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="w-full h-full">
|
||||
<div class="h-full max-h-full w-full">
|
||||
<div class="ebook-viewer absolute overflow-y-scroll left-0 right-0 top-12 w-full max-w-4xl m-auto z-10 border border-black border-opacity-20 shadow-md bg-white">
|
||||
<div class="ebook-viewer absolute overflow-y-scroll left-0 right-0 top-16 w-full max-w-4xl m-auto z-10 border border-black border-opacity-20 shadow-md bg-white">
|
||||
<iframe title="html-viewer" width="100%"> Loading </iframe>
|
||||
</div>
|
||||
</div>
|
||||
@ -15,7 +15,12 @@ import defaultCss from '@/assets/ebooks/basic.js'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
url: String
|
||||
url: String,
|
||||
libraryItem: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
playerOpen: Boolean
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
|
@ -11,13 +11,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="absolute top-0 right-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 rounded-b-md px-2 h-9 flex items-center text-center">
|
||||
<div class="absolute top-0 right-20 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 flex items-center text-center">
|
||||
<p class="font-mono">{{ page }} / {{ numPages }}</p>
|
||||
</div>
|
||||
<div class="absolute top-0 right-40 bg-bg text-gray-100 border-b border-l border-r border-gray-400 z-20 rounded-b-md px-2 h-9 flex items-center text-center">
|
||||
<ui-icon-btn icon="zoom_out" :size="8" :disabled="!canScaleDown" borderless class="mr-px" @click="zoomOut" />
|
||||
<ui-icon-btn icon="zoom_in" :size="8" :disabled="!canScaleUp" borderless class="ml-px" @click="zoomIn" />
|
||||
</div>
|
||||
|
||||
<div :style="{ height: pdfHeight + 'px' }" class="overflow-hidden m-auto">
|
||||
<div class="flex items-center justify-center">
|
||||
<div :style="{ width: pdfWidth + 'px', height: pdfHeight + 'px' }" class="w-full h-full overflow-auto">
|
||||
<div :style="{ width: pdfWidth + 'px', height: pdfHeight + 'px' }" class="overflow-auto">
|
||||
<div v-if="loadedRatio > 0 && loadedRatio < 1" style="background-color: green; color: white; text-align: center" :style="{ width: loadedRatio * 100 + '%' }">{{ Math.floor(loadedRatio * 100) }}%</div>
|
||||
<pdf ref="pdf" class="m-auto z-10 border border-black border-opacity-20 shadow-md" :src="url" :page="page" :rotate="rotate" @progress="progressEvt" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
|
||||
</div>
|
||||
@ -41,10 +45,14 @@ export default {
|
||||
libraryItem: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
playerOpen: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
windowWidth: 0,
|
||||
windowHeight: 0,
|
||||
scale: 1,
|
||||
rotate: 0,
|
||||
loadedRatio: 0,
|
||||
page: 1,
|
||||
@ -55,11 +63,18 @@ export default {
|
||||
libraryItemId() {
|
||||
return this.libraryItem?.id
|
||||
},
|
||||
fitToPageWidth() {
|
||||
return this.pdfHeight * 0.6
|
||||
},
|
||||
pdfWidth() {
|
||||
return this.pdfHeight * 0.6667
|
||||
return this.fitToPageWidth * this.scale
|
||||
},
|
||||
pdfHeight() {
|
||||
return window.innerHeight - 120
|
||||
if (this.windowHeight < 400 || !this.playerOpen) return this.windowHeight - 120
|
||||
return this.windowHeight - 284
|
||||
},
|
||||
maxScale() {
|
||||
return Math.floor((this.windowWidth * 10) / this.fitToPageWidth) / 10
|
||||
},
|
||||
canGoNext() {
|
||||
return this.page < this.numPages
|
||||
@ -67,6 +82,12 @@ export default {
|
||||
canGoPrev() {
|
||||
return this.page > 1
|
||||
},
|
||||
canScaleUp() {
|
||||
return this.scale < this.maxScale
|
||||
},
|
||||
canScaleDown() {
|
||||
return this.scale > 1
|
||||
},
|
||||
userMediaProgress() {
|
||||
if (!this.libraryItemId) return
|
||||
return this.$store.getters['user/getUserMediaProgress'](this.libraryItemId)
|
||||
@ -76,6 +97,12 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
zoomIn() {
|
||||
this.scale += 0.1
|
||||
},
|
||||
zoomOut() {
|
||||
this.scale -= 0.1
|
||||
},
|
||||
updateProgress() {
|
||||
if (!this.numPages) {
|
||||
console.error('Num pages not loaded')
|
||||
@ -113,8 +140,19 @@ export default {
|
||||
},
|
||||
error(err) {
|
||||
console.error(err)
|
||||
},
|
||||
resize() {
|
||||
this.windowWidth = window.innerWidth
|
||||
this.windowHeight = window.innerHeight
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
mounted() {
|
||||
this.windowWidth = window.innerWidth
|
||||
this.windowHeight = window.innerHeight
|
||||
window.addEventListener('resize', this.resize)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-if="show" class="w-screen h-screen fixed top-0 left-0 z-60 bg-primary text-white">
|
||||
<div v-if="show" id="reader" class="absolute top-0 left-0 w-full z-60 bg-primary text-white" :class="{ 'reader-player-open': !!streamLibraryItem }">
|
||||
<div class="absolute top-4 left-4 z-20">
|
||||
<span v-if="hasToC && !tocOpen" ref="tocButton" class="material-icons cursor-pointer text-2xl" @click="toggleToC">menu</span>
|
||||
</div>
|
||||
@ -17,7 +17,7 @@
|
||||
<span class="material-icons cursor-pointer text-2xl" @click="close">close</span>
|
||||
</div>
|
||||
|
||||
<component v-if="componentName" ref="readerComponent" :is="componentName" :url="ebookUrl" :library-item="selectedLibraryItem" />
|
||||
<component v-if="componentName" ref="readerComponent" :is="componentName" :url="ebookUrl" :library-item="selectedLibraryItem" :player-open="!!streamLibraryItem" />
|
||||
|
||||
<!-- TOC side nav -->
|
||||
<div v-if="tocOpen" class="w-full h-full fixed inset-0 bg-black/20 z-20" @click.stop.prevent="toggleToC"></div>
|
||||
@ -72,6 +72,9 @@ export default {
|
||||
else if (this.ebookType === 'comic') return 'readers-comic-reader'
|
||||
return null
|
||||
},
|
||||
streamLibraryItem() {
|
||||
return this.$store.state.streamLibraryItem
|
||||
},
|
||||
hasToC() {
|
||||
return this.isEpub
|
||||
},
|
||||
@ -191,11 +194,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ebook-viewer {
|
||||
height: calc(100% - 96px);
|
||||
}
|
||||
.tocContent {
|
||||
height: calc(100% - 36px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
#reader {
|
||||
height: 100%;
|
||||
}
|
||||
#reader.reader-player-open {
|
||||
height: calc(100% - 164px);
|
||||
}
|
||||
@media (max-height: 400px) {
|
||||
#reader.reader-player-open {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -35,7 +35,7 @@ export const getters = {
|
||||
return state.serverSettings[key]
|
||||
},
|
||||
getLibraryItemIdStreaming: state => {
|
||||
return state.streamLibraryItem ? state.streamLibraryItem.id : null
|
||||
return state.streamLibraryItem?.id || null
|
||||
},
|
||||
getIsStreamingFromDifferentLibrary: (state, getters, rootState) => {
|
||||
if (!state.streamLibraryItem) return false
|
||||
|
Loading…
Reference in New Issue
Block a user