From 09984a4284c6ee9a50c7457ea9271fc36c58b770 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Fri, 31 Jul 2020 09:23:05 +0800 Subject: [PATCH] feat(webreader): better display of landscape images in double page mode, landscape images will be displayed as a single page media analysis must be rerun for this to work closes #123 --- komga-webui/src/functions/page.ts | 3 + komga-webui/src/types/komga-books.ts | 4 +- komga-webui/src/views/BookReader.vue | 158 ++++++++++++++++----------- 3 files changed, 100 insertions(+), 65 deletions(-) create mode 100644 komga-webui/src/functions/page.ts diff --git a/komga-webui/src/functions/page.ts b/komga-webui/src/functions/page.ts new file mode 100644 index 000000000..c4f41c9fd --- /dev/null +++ b/komga-webui/src/functions/page.ts @@ -0,0 +1,3 @@ +export function isPageLandscape (p: PageDto): boolean { + return (p?.width ?? 0) > (p?.height ?? 0) +} diff --git a/komga-webui/src/types/komga-books.ts b/komga-webui/src/types/komga-books.ts index 5cc200dd8..d001475cc 100644 --- a/komga-webui/src/types/komga-books.ts +++ b/komga-webui/src/types/komga-books.ts @@ -23,7 +23,9 @@ interface MediaDto { interface PageDto { number: number, fileName: string, - mediaType: string + mediaType: string, + width?: number, + height?: number, } interface BookMetadataDto { diff --git a/komga-webui/src/views/BookReader.vue b/komga-webui/src/views/BookReader.vue index 28f930a2a..387cb03d0 100644 --- a/komga-webui/src/views/BookReader.vue +++ b/komga-webui/src/views/BookReader.vue @@ -53,30 +53,30 @@ - - - - + + + + @@ -114,24 +114,20 @@ height="100%" > -
- -
@@ -240,7 +236,8 @@ top >
This book has specific reading direction set.
-
Reading direction has been set to {{ readingDirs.find(x => x.value === readingDirection).text }}. +
Reading direction has been set to {{ readingDirectionText(readingDirection as ReadingDirection) }}.
This only applies to this book and will not overwrite your settings.
= 0 && this.carouselPage < this.spreads.length && this.spreads.length > 0) { + return this.spreads[this.carouselPage][0].number + } + return 1 }, canPrev (): boolean { return this.currentSlide > 1 @@ -432,18 +433,8 @@ export default Vue.extend({ imgStyle (): string { return this.imageFit === ImageFit.WIDTH ? 'height:intrinsic' : '' }, - slidesRange (): number[] { - if (!this.doublePages) { - return this.$_.range(1, this.pagesCount + 1) - } - // for double pages the first and last pages are shown as single, while others are doubled - const ret = this.$_.range(2, this.pagesCount, 2) - ret.unshift(1) - ret.push(this.pagesCount) - return ret - }, slidesCount (): number { - return this.slidesRange.length + return this.spreads.length }, pagesCount (): number { return this.pages.length @@ -514,6 +505,34 @@ export default Vue.extend({ this.$cookies.set(cookieSwipe, swipe, Infinity) }, }, + spreads (): PageDto[][] { + if (this.pages.length === 0) return [] + if (this.doublePages) { + const spreads = [] + spreads.push([this.pages[0]]) + const pages = this.$_.drop(this.$_.dropRight(this.pages)) as PageDto[] + while (pages.length > 0) { + const p = pages.shift() as PageDto + if (isPageLandscape(p)) { + spreads.push([p]) + } else { + if (pages.length > 0) { + const p2 = pages.shift() as PageDto + if (isPageLandscape(p2)) { + spreads.push([p]) + spreads.push([p2]) + } else { + spreads.push([p, p2]) + } + } + } + } + spreads.push([this.pages[this.pages.length - 1]]) + return spreads + } else { + return this.pages.map(p => [p]) + } + }, }, methods: { keyPressed (e: KeyboardEvent) { @@ -554,6 +573,9 @@ export default Vue.extend({ this.siblingPrevious = {} as BookDto } }, + readingDirectionText (readingDirection: ReadingDirection): string { + return readingDirs.find(x => x.value === readingDirection).text + }, getPageUrl (page: number): string { if (!this.supportedMediaTypes.includes(this.pages[page - 1].mediaType)) { return bookPageUrl(this.bookId, page, this.convertTo) @@ -614,7 +636,7 @@ export default Vue.extend({ } }, goTo (page: number) { - this.carouselPage = this.doublePages ? this.toDoublePages(page) - 1 : page - 1 + this.carouselPage = this.toSpreadIndex(page) }, goToFirst () { this.goTo(1) @@ -639,35 +661,43 @@ export default Vue.extend({ if (i === this.slidesCount) return this.pagesCount return (i - 1) * 2 }, - toDoublePages (i: number): number { - let ret = Math.floor(i / 2) + 1 - if (i === this.pagesCount && this.pagesCount % 2 === 1) { - ret++ + toSpreadIndex (i: number): number { + if (this.spreads.length > 0) { + if (this.doublePages) { + for (let j = 0; j < this.spreads.length; j++) { + for (let k = 0; k < this.spreads[j].length; k++) { + if (this.spreads[j][k].number === i) { + return j + } + } + } + } else { + return i - 1 + } } - return ret + return i - 1 }, - eagerLoad (p: number): boolean { - return Math.abs(this.currentPage - p) <= 2 + eagerLoad (spreadIndex: number): boolean { + return Math.abs(this.carouselPage - spreadIndex) <= 2 }, - maxWidth (p: number): number | null { + maxWidth (spreadIndex: number): number | null { if (this.imageFit !== ImageFit.WIDTH) { return null } - if (this.doublePages && p !== 1 && p !== this.pagesCount) { + if (this.doublePages && this.spreads[spreadIndex].length === 2) { return this.$vuetify.breakpoint.width / 2 } return this.$vuetify.breakpoint.width }, loadFromCookie (cookieKey: string, setter: (value: any) => void): void { if (this.$cookies.isKey(cookieKey)) { - let value = this.$cookies.get(cookieKey) - setter(value) + setter(this.$cookies.get(cookieKey)) } }, changeReadingDir (dir: ReadingDirection) { this.readingDirection = dir - let i = this.settings.readingDirs.indexOf(this.readingDirection) - let text = this.readingDirs[i].text + const i = this.settings.readingDirs.indexOf(this.readingDirection) + const text = this.readingDirs[i].text this.sendNotification(`Changing Reading Direction to: ${text}`) }, cycleScale () { @@ -682,13 +712,13 @@ export default Vue.extend({ this.doublePages = !this.doublePages this.sendNotification(`${this.doublePages ? 'Enabled' : 'Disabled'} Double Pages`) }, - sendNotification (message:string, timeout: number = 4000) { + sendNotification (message: string, timeout: number = 4000) { this.notification.timeout = 4000 this.notification.message = message this.notification.enabled = true }, async markProgress (page: number) { - this.$komgaBooks.updateReadProgress(this.bookId, { page: page }) + await this.$komgaBooks.updateReadProgress(this.bookId, { page: page }) }, }, })