advplyr.audiobookshelf-app/components/readers/PdfReader.vue

168 lines
5.4 KiB
Vue
Raw Normal View History

2022-12-06 17:07:27 -06:00
<template>
2023-03-06 10:58:08 -06:00
<div class="w-full h-full pt-6 relative">
2022-12-06 17:07:27 -06:00
<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 class="material-icons text-5xl text-white cursor-pointer text-opacity-30 hover:text-opacity-90">arrow_back_ios</span>
</div>
</div>
<div v-show="canGoNext" class="absolute top-0 right-0 h-full w-1/2 hover:opacity-100 opacity-0 z-10 cursor-pointer" @click.stop.prevent="next" @mousedown.prevent>
<div class="flex items-center justify-center h-full w-1/2 ml-auto">
<span class="material-icons text-5xl text-white cursor-pointer text-opacity-30 hover:text-opacity-90">arrow_forward_ios</span>
</div>
</div>
<div class="absolute top-0 right-1 bg-bg text-gray-100 border-b border-l border-r border-gray-400 rounded-b-md px-2 h-6 flex items-center text-center">
<p class="font-mono text-xs">{{ page }} / {{ numPages }}</p>
</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 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 bg-white" :src="pdfDocInitParams" :page="page" :rotate="rotate" @progress="loadedRatio = $event" @error="error" @num-pages="numPagesLoaded" @link-clicked="page = $event" @loaded="loadedEvt"></pdf>
2022-12-06 17:07:27 -06:00
</div>
</div>
</div>
</div>
</template>
<script>
import pdf from '@teckel/vue-pdf'
2022-12-06 17:07:27 -06:00
export default {
components: {
pdf
},
props: {
url: String,
libraryItem: {
type: Object,
default: () => {}
},
2023-06-11 11:12:52 -05:00
isLocal: Boolean,
keepProgress: Boolean
2022-12-06 17:07:27 -06:00
},
data() {
return {
rotate: 0,
loadedRatio: 0,
page: 1,
numPages: 0
}
},
computed: {
userToken() {
return this.$store.getters['user/getToken']
},
localLibraryItem() {
if (this.isLocal) return this.libraryItem
return this.libraryItem.localLibraryItem || null
},
localLibraryItemId() {
return this.localLibraryItem?.id
},
serverLibraryItemId() {
if (!this.isLocal) return this.libraryItem.id
// Check if local library item is connected to the current server
if (!this.libraryItem.serverAddress || !this.libraryItem.libraryItemId) return null
if (this.$store.getters['user/getServerAddress'] === this.libraryItem.serverAddress) {
return this.libraryItem.libraryItemId
}
return null
},
2022-12-06 17:07:27 -06:00
pdfWidth() {
return this.pdfHeight * 0.6667
},
pdfHeight() {
return window.innerHeight - 120
},
canGoNext() {
return this.page < this.numPages
},
canGoPrev() {
return this.page > 1
},
userItemProgress() {
if (this.isLocal) return this.localItemProgress
return this.serverItemProgress
},
localItemProgress() {
return this.$store.getters['globals/getLocalMediaProgressById'](this.localLibraryItemId)
},
serverItemProgress() {
return this.$store.getters['user/getUserMediaProgress'](this.serverLibraryItemId)
},
savedPage() {
2023-06-11 11:12:52 -05:00
if (!this.keepProgress) return 0
// Validate ebookLocation is a number
if (!this.userItemProgress?.ebookLocation || isNaN(this.userItemProgress.ebookLocation)) return 0
return Number(this.userItemProgress.ebookLocation)
},
pdfDocInitParams() {
return {
url: this.url,
httpHeaders: {
Authorization: `Bearer ${this.userToken}`
}
}
2022-12-06 17:07:27 -06:00
}
},
methods: {
async updateProgress() {
2023-06-11 11:12:52 -05:00
if (!this.keepProgress) return
if (!this.numPages) {
console.error('Num pages not loaded')
return
}
2023-06-11 11:12:52 -05:00
const payload = {
ebookLocation: String(this.page),
ebookProgress: Math.max(0, Math.min(1, (Number(this.page) - 1) / Number(this.numPages)))
}
// Update local item
if (this.localLibraryItemId) {
const localPayload = {
localLibraryItemId: this.localLibraryItemId,
...payload
}
const localResponse = await this.$db.updateLocalEbookProgress(localPayload)
if (localResponse.localMediaProgress) {
this.$store.commit('globals/updateLocalMediaProgress', localResponse.localMediaProgress)
}
}
// Update server item
if (this.serverLibraryItemId) {
this.$axios.$patch(`/api/me/progress/${this.serverLibraryItemId}`, payload).catch((error) => {
console.error('PdfReader.updateProgress failed:', error)
})
}
},
loadedEvt() {
if (this.savedPage && this.savedPage > 0 && this.savedPage <= this.numPages) {
this.page = this.savedPage
}
},
2022-12-06 17:07:27 -06:00
numPagesLoaded(e) {
this.numPages = e
},
prev() {
if (this.page <= 1) return
this.page--
this.updateProgress()
2022-12-06 17:07:27 -06:00
},
next() {
if (this.page >= this.numPages) return
this.page++
this.updateProgress()
2022-12-06 17:07:27 -06:00
},
error(err) {
console.error(err)
}
},
mounted() {}
}
</script>