mirror of
https://github.com/gotson/komga.git
synced 2026-05-09 05:10:19 +02:00
parent
84ff250030
commit
93cec4e4e5
6 changed files with 55 additions and 1 deletions
11
komga-webui/package-lock.json
generated
11
komga-webui/package-lock.json
generated
|
|
@ -12,6 +12,7 @@
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"date-fns": "^2.19.0",
|
"date-fns": "^2.19.0",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
|
"js-file-downloader": "^1.1.16",
|
||||||
"language-tags": "^1.0.5",
|
"language-tags": "^1.0.5",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"qs": "^6.9.4",
|
"qs": "^6.9.4",
|
||||||
|
|
@ -13480,6 +13481,11 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/js-file-downloader": {
|
||||||
|
"version": "1.1.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-file-downloader/-/js-file-downloader-1.1.16.tgz",
|
||||||
|
"integrity": "sha512-vj4ZpHvFJI7J7SluyreHzaAVZDrPulRcwjMMOUve1KOEB4oxYAiQZXzgmu2lPbMTqKlf7U91MNZYRMTq7DsMfQ=="
|
||||||
|
},
|
||||||
"node_modules/js-message": {
|
"node_modules/js-message": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
||||||
|
|
@ -32242,6 +32248,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"js-file-downloader": {
|
||||||
|
"version": "1.1.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-file-downloader/-/js-file-downloader-1.1.16.tgz",
|
||||||
|
"integrity": "sha512-vj4ZpHvFJI7J7SluyreHzaAVZDrPulRcwjMMOUve1KOEB4oxYAiQZXzgmu2lPbMTqKlf7U91MNZYRMTq7DsMfQ=="
|
||||||
|
},
|
||||||
"js-message": {
|
"js-message": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"date-fns": "^2.19.0",
|
"date-fns": "^2.19.0",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
|
"js-file-downloader": "^1.1.16",
|
||||||
"language-tags": "^1.0.5",
|
"language-tags": "^1.0.5",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"qs": "^6.9.4",
|
"qs": "^6.9.4",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
"cycling_page_layout": "Cycling Page Layout",
|
"cycling_page_layout": "Cycling Page Layout",
|
||||||
"cycling_scale": "Cycling Scale",
|
"cycling_scale": "Cycling Scale",
|
||||||
"cycling_side_padding": "Cycling Side Padding",
|
"cycling_side_padding": "Cycling Side Padding",
|
||||||
|
"download_current_page": "Download current page",
|
||||||
"end_of_book": "You've reached the end of the book.",
|
"end_of_book": "You've reached the end of the book.",
|
||||||
"from_series_metadata": "from series metadata",
|
"from_series_metadata": "from series metadata",
|
||||||
"move_next": "Click or press \"Next\" again to move to the next book.",
|
"move_next": "Click or press \"Next\" again to move to the next book.",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,19 @@
|
||||||
>
|
>
|
||||||
<v-icon>mdi-cog</v-icon>
|
<v-icon>mdi-cog</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
<v-menu offset-y>
|
||||||
|
<template v-slot:activator="{ on }">
|
||||||
|
<v-btn icon v-on="on" @click.prevent="">
|
||||||
|
<v-icon>mdi-dots-vertical</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item @click="downloadCurrentPage">
|
||||||
|
<v-list-item-title>{{ $t('bookreader.download_current_page') }}</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
</v-slide-y-transition>
|
</v-slide-y-transition>
|
||||||
|
|
||||||
|
|
@ -290,6 +303,7 @@ import {shortcutsSettingsContinuous} from '@/functions/shortcuts/continuous-read
|
||||||
import {BookDto, PageDto, PageDtoWithUrl} from '@/types/komga-books'
|
import {BookDto, PageDto, PageDtoWithUrl} from '@/types/komga-books'
|
||||||
import {Context, ContextOrigin} from '@/types/context'
|
import {Context, ContextOrigin} from '@/types/context'
|
||||||
import {SeriesDto} from "@/types/komga-series";
|
import {SeriesDto} from "@/types/komga-series";
|
||||||
|
import jsFileDownloader from "js-file-downloader"
|
||||||
|
|
||||||
const cookieFit = 'webreader.fit'
|
const cookieFit = 'webreader.fit'
|
||||||
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'
|
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'
|
||||||
|
|
@ -484,6 +498,9 @@ export default Vue.extend({
|
||||||
contextReadList (): boolean {
|
contextReadList (): boolean {
|
||||||
return this.context.origin === ContextOrigin.READLIST
|
return this.context.origin === ContextOrigin.READLIST
|
||||||
},
|
},
|
||||||
|
currentPage(): PageDtoWithUrl {
|
||||||
|
return this.pages[this.page - 1]
|
||||||
|
},
|
||||||
|
|
||||||
animations: {
|
animations: {
|
||||||
get: function (): boolean {
|
get: function (): boolean {
|
||||||
|
|
@ -782,6 +799,12 @@ export default Vue.extend({
|
||||||
async markProgress (page: number) {
|
async markProgress (page: number) {
|
||||||
await this.$komgaBooks.updateReadProgress(this.bookId, { page: page })
|
await this.$komgaBooks.updateReadProgress(this.bookId, { page: page })
|
||||||
},
|
},
|
||||||
|
downloadCurrentPage() {
|
||||||
|
new jsFileDownloader({
|
||||||
|
url: this.currentPage.url,
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,11 @@ class ContentDetector(
|
||||||
|
|
||||||
fun isImage(mediaType: String): Boolean =
|
fun isImage(mediaType: String): Boolean =
|
||||||
mediaType.startsWith("image/")
|
mediaType.startsWith("image/")
|
||||||
|
|
||||||
|
fun mediaTypeToExtension(mediaType: String): String? =
|
||||||
|
try {
|
||||||
|
tika.mimeRepository.forName(mediaType).extension
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import org.gotson.komga.domain.persistence.ReadListRepository
|
||||||
import org.gotson.komga.domain.service.BookLifecycle
|
import org.gotson.komga.domain.service.BookLifecycle
|
||||||
import org.gotson.komga.infrastructure.image.ImageType
|
import org.gotson.komga.infrastructure.image.ImageType
|
||||||
import org.gotson.komga.infrastructure.jooq.UnpagedSorted
|
import org.gotson.komga.infrastructure.jooq.UnpagedSorted
|
||||||
|
import org.gotson.komga.infrastructure.mediacontainer.ContentDetector
|
||||||
import org.gotson.komga.infrastructure.security.KomgaPrincipal
|
import org.gotson.komga.infrastructure.security.KomgaPrincipal
|
||||||
import org.gotson.komga.infrastructure.swagger.PageableAsQueryParam
|
import org.gotson.komga.infrastructure.swagger.PageableAsQueryParam
|
||||||
import org.gotson.komga.infrastructure.swagger.PageableWithoutSortAsQueryParam
|
import org.gotson.komga.infrastructure.swagger.PageableWithoutSortAsQueryParam
|
||||||
|
|
@ -78,7 +79,8 @@ class BookController(
|
||||||
private val bookMetadataRepository: BookMetadataRepository,
|
private val bookMetadataRepository: BookMetadataRepository,
|
||||||
private val mediaRepository: MediaRepository,
|
private val mediaRepository: MediaRepository,
|
||||||
private val bookDtoRepository: BookDtoRepository,
|
private val bookDtoRepository: BookDtoRepository,
|
||||||
private val readListRepository: ReadListRepository
|
private val readListRepository: ReadListRepository,
|
||||||
|
private val contentDetector: ContentDetector,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@PageableAsQueryParam
|
@PageableAsQueryParam
|
||||||
|
|
@ -342,6 +344,15 @@ class BookController(
|
||||||
val pageContent = bookLifecycle.getBookPage(book, pageNum, convertFormat)
|
val pageContent = bookLifecycle.getBookPage(book, pageNum, convertFormat)
|
||||||
|
|
||||||
ResponseEntity.ok()
|
ResponseEntity.ok()
|
||||||
|
.headers(
|
||||||
|
HttpHeaders().apply {
|
||||||
|
val extension = contentDetector.mediaTypeToExtension(pageContent.mediaType) ?: "jpeg"
|
||||||
|
val imageFileName = "${book.name}-$pageNum$extension"
|
||||||
|
contentDisposition = ContentDisposition.builder("inline")
|
||||||
|
.filename(imageFileName)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
)
|
||||||
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
|
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
|
||||||
.setNotModified(media)
|
.setNotModified(media)
|
||||||
.body(pageContent.content)
|
.body(pageContent.content)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue