Reader Fixes and Enhancements (#880)
* Don't show an exception when bookmarking doesn't have anything to change. * Cleaned up the bookmark code a bit. * Implemented fullscreen mode in the web reader. Refactored User Settings to move Password and 3rd Party Clients to a tab rather than accordion. Removed color filters for web reader. * Implemented fullscreen mode into book reader * Added some code for toggling fullscreen which re-renders the screen to ensure the fitting works optimially * Fixed an issue where moving from FitToScreen -> Split (L/R) wouldn't render the screen correctly due to canvas not being reset. * Fixed bad optimization and scaling when drawing fit to screen * Removed left/right highlights on page direction change in favor for icons. Double arrow will dictate the page change. * Reduced overlay auto close time to 3 seconds * Updated the paginging direction overlay to use icons and colors. Added a blur effect on menus * Removed debug flags
This commit is contained in:
parent
ca5c67020e
commit
720c52f494
19 changed files with 1620 additions and 166 deletions
|
|
@ -15,8 +15,3 @@ export enum PAGING_DIRECTION {
|
|||
BACKWARDS = -1,
|
||||
}
|
||||
|
||||
export enum COLOR_FILTER {
|
||||
NONE = '',
|
||||
SEPIA = 'filter-sepia',
|
||||
DARK = 'filter-dark'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="reader">
|
||||
<div class="reader" #reader>
|
||||
<div class="fixed-top overlay" *ngIf="menuOpen" [@slideFromTop]="menuOpen">
|
||||
<div style="display: flex; margin-top: 5px;">
|
||||
<button class="btn btn-icon" style="height: 100%" title="Back" (click)="closeReader()">
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
</ng-container>
|
||||
|
||||
<div (click)="toggleMenu()" class="reading-area">
|
||||
<canvas #content class="{{getFittingOptionClass()}} {{this.colorMode}} {{readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD ? '' : 'd-none'}} "
|
||||
<canvas #content class="{{getFittingOptionClass()}} {{readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD ? '' : 'd-none'}} {{showClickOverlay ? 'blur' : ''}}"
|
||||
ondragstart="return false;" onselectstart="return false;">
|
||||
</canvas>
|
||||
<div class="webtoon-images" *ngIf="readerMode === READER_MODE.WEBTOON && !isLoading">
|
||||
|
|
@ -39,8 +39,18 @@
|
|||
[bookmarkPage]="showBookmarkEffectEvent"></app-infinite-scroller>
|
||||
</div>
|
||||
<ng-container *ngIf="readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD">
|
||||
<div class="{{readerMode === READER_MODE.MANGA_LR ? 'right' : 'bottom'}} {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')"></div>
|
||||
<div class="{{readerMode === READER_MODE.MANGA_LR ? 'left' : 'top'}} {{clickOverlayClass('left')}}" (click)="handlePageChange($event, 'left')"></div>
|
||||
<div class="pagination-area {{readerMode === READER_MODE.MANGA_LR ? 'right' : 'bottom'}} {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')">
|
||||
<div *ngIf="showClickOverlay">
|
||||
<i class="fa fa-angle-{{readingDirection === ReadingDirection.LeftToRight ? 'double-' : ''}}{{readerMode === READER_MODE.MANGA_LR ? 'right' : 'down'}}"
|
||||
title="Next Page" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination-area {{readerMode === READER_MODE.MANGA_LR ? 'left' : 'top'}} {{clickOverlayClass('left')}}" (click)="handlePageChange($event, 'left')">
|
||||
<div *ngIf="showClickOverlay">
|
||||
<i class="fa fa-angle-{{readingDirection === ReadingDirection.RightToLeft ? 'double-' : ''}}{{readerMode === READER_MODE.MANGA_LR ? 'left' : 'up'}}"
|
||||
title="Previous Page" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
|
|
@ -78,9 +88,9 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-icon {{this.colorMode}}" [disabled]="readerMode === READER_MODE.WEBTOON" title="Color Options: {{colorOptionName}}" (click)="toggleColorMode();resetMenuCloseTimer();">
|
||||
<i class="fa fa-palette" aria-hidden="true"></i>
|
||||
<span class="sr-only"></span>
|
||||
<button class="btn btn-icon" title="{{this.isFullscreen ? 'Collapse' : 'Fullscreen'}}" (click)="toggleFullscreen();resetMenuCloseTimer();">
|
||||
<i class="fa {{this.isFullscreen ? 'fa-compress-alt' : 'fa-expand-alt'}}" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{this.isFullscreen ? 'Collapse' : 'Fullscreen'}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ $side-width: 25%;
|
|||
$dash-width: 3px;
|
||||
$pointer-offset: 5px;
|
||||
|
||||
$secondary-color: #CCC;
|
||||
|
||||
|
||||
@media(min-width: 600px) {
|
||||
.overlay .left .i {
|
||||
|
|
@ -18,7 +16,6 @@ $secondary-color: #CCC;
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.btn-icon {
|
||||
color: white;
|
||||
}
|
||||
|
|
@ -35,6 +32,10 @@ canvas {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
left: 48%;
|
||||
|
|
@ -48,14 +49,6 @@ canvas {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.filter-dark {
|
||||
filter: brightness(0.65);
|
||||
}
|
||||
|
||||
.filter-sepia {
|
||||
filter: sepia(80%) hue-rotate(349deg) saturate(200%) brightness(0.65);
|
||||
}
|
||||
|
||||
.bottom-menu {
|
||||
padding: 20px 20px;
|
||||
}
|
||||
|
|
@ -63,6 +56,7 @@ canvas {
|
|||
|
||||
.overlay {
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
|
@ -226,15 +220,28 @@ canvas {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: rgba(65, 225, 100, 0.5) !important;
|
||||
animation: fadein .5s both;
|
||||
}
|
||||
.highlight-2 {
|
||||
background-color: rgba(65, 105, 225, 0.5) !important;
|
||||
animation: fadein .5s both;
|
||||
.pagination-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
i {
|
||||
color: white;
|
||||
font-size: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: rgba(65, 225, 100, 0.5) !important;
|
||||
animation: fadein .5s both;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.highlight-2 {
|
||||
background-color: rgba(65, 105, 225, 0.5) !important;
|
||||
animation: fadein .5s both;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
|
||||
.bookmark-effect {
|
||||
animation: bookmark 0.7s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Inject, OnDestroy, OnInit, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { DOCUMENT, Location } from '@angular/common';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { take, takeUntil } from 'rxjs/operators';
|
||||
import { User } from '../_models/user';
|
||||
|
|
@ -19,7 +19,7 @@ import { Stack } from '../shared/data-structures/stack';
|
|||
import { ChangeContext, LabelType, Options } from '@angular-slider/ngx-slider';
|
||||
import { trigger, state, style, transition, animate } from '@angular/animations';
|
||||
import { ChapterInfo } from './_models/chapter-info';
|
||||
import { COLOR_FILTER, FITTING_OPTION, PAGING_DIRECTION, SPLIT_PAGE_PART } from './_models/reader-enums';
|
||||
import { FITTING_OPTION, PAGING_DIRECTION, SPLIT_PAGE_PART } from './_models/reader-enums';
|
||||
import { pageSplitOptions, scalingOptions } from '../_models/preferences/preferences';
|
||||
import { READER_MODE } from '../_models/preferences/reader-mode';
|
||||
import { MangaFormat } from '../_models/manga-format';
|
||||
|
|
@ -32,7 +32,7 @@ const CHAPTER_ID_NOT_FETCHED = -2;
|
|||
const CHAPTER_ID_DOESNT_EXIST = -1;
|
||||
|
||||
const ANIMATION_SPEED = 200;
|
||||
const OVERLAY_AUTO_CLOSE_TIME = 6000;
|
||||
const OVERLAY_AUTO_CLOSE_TIME = 3000;
|
||||
const CLICK_OVERLAY_TIMEOUT = 3000;
|
||||
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
incognitoMode: boolean = false;
|
||||
|
||||
/**
|
||||
* If this is true, chapters will be fetched in the order of a reading list, rather than natural series order.
|
||||
* If this is true, chapters will be fetched in the order of a reading list, rather than natural series order.
|
||||
*/
|
||||
readingListMode: boolean = false;
|
||||
/**
|
||||
|
|
@ -99,14 +99,15 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
pageSplitOption = PageSplitOption.FitSplit;
|
||||
currentImageSplitPart: SPLIT_PAGE_PART = SPLIT_PAGE_PART.NO_SPLIT;
|
||||
pagingDirection: PAGING_DIRECTION = PAGING_DIRECTION.FORWARD;
|
||||
colorMode: COLOR_FILTER = COLOR_FILTER.NONE;
|
||||
isFullscreen: boolean = false;
|
||||
autoCloseMenu: boolean = true;
|
||||
readerMode: READER_MODE = READER_MODE.MANGA_LR;
|
||||
|
||||
pageSplitOptions = pageSplitOptions;
|
||||
|
||||
isLoading = true;
|
||||
|
||||
isLoading = true;
|
||||
|
||||
@ViewChild('reader') reader!: ElementRef;
|
||||
@ViewChild('content') canvas: ElementRef | undefined;
|
||||
private ctx!: CanvasRenderingContext2D;
|
||||
private canvasImage = new Image();
|
||||
|
|
@ -219,21 +220,21 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
|
||||
|
||||
getPageUrl = (pageNum: number) => this.readerService.getPageUrl(this.chapterId, pageNum);
|
||||
|
||||
|
||||
|
||||
|
||||
get pageBookmarked() {
|
||||
return this.bookmarks.hasOwnProperty(this.pageNum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
get splitIconClass() {
|
||||
if (this.isSplitLeftToRight()) {
|
||||
return 'left-side';
|
||||
} else if (this.isNoSplit()) {
|
||||
return 'none';
|
||||
return 'none';
|
||||
}
|
||||
return 'right-side';
|
||||
}
|
||||
|
|
@ -249,17 +250,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
get colorOptionName() {
|
||||
switch(this.colorMode) {
|
||||
case COLOR_FILTER.NONE:
|
||||
return 'None';
|
||||
case COLOR_FILTER.DARK:
|
||||
return 'Dark';
|
||||
case COLOR_FILTER.SEPIA:
|
||||
return 'Sepia';
|
||||
}
|
||||
}
|
||||
|
||||
get READER_MODE(): typeof READER_MODE {
|
||||
return READER_MODE;
|
||||
}
|
||||
|
|
@ -274,10 +264,10 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
constructor(private route: ActivatedRoute, private router: Router, private accountService: AccountService,
|
||||
public readerService: ReaderService, private location: Location,
|
||||
private formBuilder: FormBuilder, private navService: NavService,
|
||||
private formBuilder: FormBuilder, private navService: NavService,
|
||||
private toastr: ToastrService, private memberService: MemberService,
|
||||
private libraryService: LibraryService, private utilityService: UtilityService,
|
||||
private renderer: Renderer2) {
|
||||
private libraryService: LibraryService, private utilityService: UtilityService,
|
||||
private renderer: Renderer2, @Inject(DOCUMENT) private document: Document) {
|
||||
this.navService.hideNavBar();
|
||||
}
|
||||
|
||||
|
|
@ -295,13 +285,13 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.seriesId = parseInt(seriesId, 10);
|
||||
this.chapterId = parseInt(chapterId, 10);
|
||||
this.incognitoMode = this.route.snapshot.queryParamMap.get('incognitoMode') === 'true';
|
||||
|
||||
|
||||
const readingListId = this.route.snapshot.queryParamMap.get('readingListId');
|
||||
if (readingListId != null) {
|
||||
this.readingListMode = true;
|
||||
this.readingListId = parseInt(readingListId, 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.continuousChaptersStack.push(this.chapterId);
|
||||
|
||||
|
|
@ -325,10 +315,11 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
this.updateForm();
|
||||
|
||||
|
||||
this.generalSettingsForm.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe((changes: SimpleChanges) => {
|
||||
this.autoCloseMenu = this.generalSettingsForm.get('autoCloseMenu')?.value;
|
||||
const needsSplitting = this.isCoverImage();
|
||||
// If we need to split on a menu change, then we need to re-render.
|
||||
// If we need to split on a menu change, then we need to re-render.
|
||||
if (needsSplitting) {
|
||||
this.loadPage();
|
||||
}
|
||||
|
|
@ -341,7 +332,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
// If no user, we can't render
|
||||
// If no user, we can't render
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
});
|
||||
|
|
@ -365,6 +356,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.onDestroy.complete();
|
||||
this.goToPageEvent.complete();
|
||||
this.showBookmarkEffectEvent.complete();
|
||||
this.readerService.exitFullscreen();
|
||||
}
|
||||
|
||||
@HostListener('window:keyup', ['$event'])
|
||||
|
|
@ -407,6 +399,17 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
clickOverlayClass(side: 'right' | 'left') {
|
||||
if (!this.showClickOverlay) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (this.readingDirection === ReadingDirection.LeftToRight) {
|
||||
return side === 'right' ? 'highlight' : 'highlight-2';
|
||||
}
|
||||
return side === 'right' ? 'highlight-2' : 'highlight';
|
||||
}
|
||||
|
||||
init() {
|
||||
this.nextChapterId = CHAPTER_ID_NOT_FETCHED;
|
||||
this.prevChapterId = CHAPTER_ID_NOT_FETCHED;
|
||||
|
|
@ -422,7 +425,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}).pipe(take(1)).subscribe(results => {
|
||||
|
||||
if (this.readingListMode && results.chapterInfo.seriesFormat === MangaFormat.EPUB) {
|
||||
// Redirect to the book reader.
|
||||
// Redirect to the book reader.
|
||||
const params = this.readerService.getQueryParamsObject(this.incognitoMode, this.readingListMode, this.readingListId);
|
||||
this.router.navigate(['library', results.chapterInfo.libraryId, 'series', results.chapterInfo.seriesId, 'book', this.chapterId], {queryParams: params});
|
||||
return;
|
||||
|
|
@ -435,8 +438,8 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
page = this.maxPages;
|
||||
}
|
||||
this.setPageNum(page);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Due to change detection rules in Angular, we need to re-create the options object to apply the change
|
||||
const newOptions: Options = Object.assign({}, this.pageOptions);
|
||||
|
|
@ -448,7 +451,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.updateTitle(results.chapterInfo, type);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// From bookmarks, create map of pages to make lookup time O(1)
|
||||
this.bookmarks = {};
|
||||
|
|
@ -562,7 +565,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
getFittingIcon() {
|
||||
const value = this.getFit();
|
||||
|
||||
|
||||
switch(value) {
|
||||
case FITTING_OPTION.HEIGHT:
|
||||
return 'fa-arrows-alt-v';
|
||||
|
|
@ -608,10 +611,10 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}, OVERLAY_AUTO_CLOSE_TIME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
toggleMenu() {
|
||||
this.menuOpen = !this.menuOpen;
|
||||
|
||||
|
||||
if (this.menuTimeout) {
|
||||
clearTimeout(this.menuTimeout);
|
||||
}
|
||||
|
|
@ -629,8 +632,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @returns If the current model reflects no split of fit split
|
||||
* @remarks Fit to Screen falls under no split
|
||||
*/
|
||||
isNoSplit() {
|
||||
const splitValue = parseInt(this.generalSettingsForm?.get('pageSplitOption')?.value, 10);
|
||||
|
|
@ -717,7 +721,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
if (this.readerMode !== READER_MODE.WEBTOON) {
|
||||
this.loadPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevPage(event?: any) {
|
||||
|
|
@ -745,7 +749,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
if (this.readerMode !== READER_MODE.WEBTOON) {
|
||||
this.loadPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadNextChapter() {
|
||||
|
|
@ -789,7 +793,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
loadChapter(chapterId: number, direction: 'Next' | 'Prev') {
|
||||
if (chapterId >= 0) {
|
||||
this.chapterId = chapterId;
|
||||
this.continuousChaptersStack.push(chapterId);
|
||||
this.continuousChaptersStack.push(chapterId);
|
||||
// Load chapter Id onto route but don't reload
|
||||
const newRoute = this.readerService.getNextChapterUrl(this.router.url, this.chapterId, this.incognitoMode, this.readingListMode, this.readingListId);
|
||||
window.history.replaceState({}, '', newRoute);
|
||||
|
|
@ -804,14 +808,14 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
} else {
|
||||
this.nextPageDisabled = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* There are some hard limits on the size of canvas' that we must cap at. https://github.com/jhildenbiddle/canvas-size#test-results
|
||||
* For Safari, it's 16,777,216, so we cap at 4096x4096 when this happens. The drawImage in render will perform bi-cubic scaling for us.
|
||||
* @returns If we should continue to the render loop
|
||||
* @returns If we should continue to the render loop
|
||||
*/
|
||||
setCanvasSize() {
|
||||
if (this.ctx && this.canvas) {
|
||||
|
|
@ -832,9 +836,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
if (needsScaling) {
|
||||
this.canvas.nativeElement.width = isSafari ? 4_096 : 16_384;
|
||||
this.canvas.nativeElement.height = isSafari ? 4_096 : 16_384;
|
||||
} else if (this.isCoverImage()) {
|
||||
//this.canvas.nativeElement.width = this.canvasImage.width / 2;
|
||||
//this.canvas.nativeElement.height = this.canvasImage.height;
|
||||
} else {
|
||||
this.canvas.nativeElement.width = this.canvasImage.width;
|
||||
this.canvas.nativeElement.height = this.canvasImage.height;
|
||||
|
|
@ -877,21 +878,26 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
let newWidth = windowWidth;
|
||||
let newHeight = newWidth / ratio;
|
||||
if (newHeight > windowHeight) {
|
||||
newHeight = windowHeight;
|
||||
newHeight = windowHeight;
|
||||
newWidth = newHeight * ratio;
|
||||
}
|
||||
|
||||
// Optimization: When the screen is larger than newWidth, allow no split rendering to occur for a better fit
|
||||
if (windowWidth > newWidth) {
|
||||
this.ctx.drawImage(this.canvasImage, 0, 0);
|
||||
//console.log('Using raw draw');
|
||||
this.setCanvasSize();
|
||||
this.ctx.drawImage(this.canvasImage, 0, 0);
|
||||
} else {
|
||||
//console.log('Using scaled draw');
|
||||
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
||||
this.ctx.drawImage(this.canvasImage, 0, 0, newWidth, newHeight);
|
||||
}
|
||||
} else {
|
||||
//console.log('Normal Render')
|
||||
this.ctx.drawImage(this.canvasImage, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reset scroll on non HEIGHT Fits
|
||||
if (this.getFit() !== FITTING_OPTION.HEIGHT) {
|
||||
window.scrollTo(0, 0);
|
||||
|
|
@ -908,13 +914,13 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
const windowHeight = window.innerHeight
|
||||
|| document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
|
||||
|
||||
const needsSplitting = this.isCoverImage();
|
||||
let newScale = this.generalSettingsForm.get('fittingOption')?.value;
|
||||
const widthRatio = windowWidth / (this.canvasImage.width / (needsSplitting ? 2 : 1));
|
||||
const heightRatio = windowHeight / (this.canvasImage.height);
|
||||
|
||||
// Given that we now have image dimensions, assuming this isn't a split image,
|
||||
// Given that we now have image dimensions, assuming this isn't a split image,
|
||||
// Try to reset one time based on who's dimension (width/height) is smaller
|
||||
if (widthRatio < heightRatio) {
|
||||
newScale = FITTING_OPTION.WIDTH;
|
||||
|
|
@ -984,19 +990,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
clickOverlayClass(side: 'right' | 'left') {
|
||||
if (!this.showClickOverlay) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (this.readingDirection === ReadingDirection.LeftToRight) {
|
||||
return side === 'right' ? 'highlight' : 'highlight-2';
|
||||
}
|
||||
return side === 'right' ? 'highlight-2' : 'highlight';
|
||||
}
|
||||
|
||||
sliderDragUpdate(context: ChangeContext) {
|
||||
// This will update the value for value except when in webtoon due to how the webtoon reader
|
||||
// This will update the value for value except when in webtoon due to how the webtoon reader
|
||||
// responds to page changes
|
||||
if (this.readerMode !== READER_MODE.WEBTOON) {
|
||||
this.setPageNum(context.value);
|
||||
|
|
@ -1005,7 +1001,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
sliderPageUpdate(context: ChangeContext) {
|
||||
const page = context.value;
|
||||
|
||||
|
||||
if (page > this.pageNum) {
|
||||
this.pagingDirection = PAGING_DIRECTION.FORWARD;
|
||||
} else {
|
||||
|
|
@ -1049,7 +1045,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
goToPage(pageNum: number) {
|
||||
let page = pageNum;
|
||||
|
||||
|
||||
if (page === undefined || this.pageNum === page) { return; }
|
||||
|
||||
if (page > this.maxPages) {
|
||||
|
|
@ -1079,20 +1075,24 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
return goToPageNum;
|
||||
}
|
||||
|
||||
toggleColorMode() {
|
||||
switch(this.colorMode) {
|
||||
case COLOR_FILTER.NONE:
|
||||
this.colorMode = COLOR_FILTER.DARK;
|
||||
break;
|
||||
case COLOR_FILTER.DARK:
|
||||
this.colorMode = COLOR_FILTER.SEPIA;
|
||||
break;
|
||||
case COLOR_FILTER.SEPIA:
|
||||
this.colorMode = COLOR_FILTER.NONE;
|
||||
break;
|
||||
toggleFullscreen() {
|
||||
this.isFullscreen = this.readerService.checkFullscreenMode();
|
||||
if (this.isFullscreen) {
|
||||
this.readerService.exitFullscreen(() => {
|
||||
this.isFullscreen = false;
|
||||
this.firstPageRendered = false;
|
||||
this.render();
|
||||
});
|
||||
} else {
|
||||
this.readerService.enterFullscreen(this.reader.nativeElement, () => {
|
||||
this.isFullscreen = true;
|
||||
this.firstPageRendered = false;
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
toggleReaderMode() {
|
||||
switch(this.readerMode) {
|
||||
case READER_MODE.MANGA_LR:
|
||||
|
|
@ -1163,4 +1163,14 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.toastr.info('Incognito mode is off. Progress will now start being tracked.');
|
||||
this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
}
|
||||
|
||||
getWindowDimensions() {
|
||||
const windowWidth = window.innerWidth
|
||||
|| document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
const windowHeight = window.innerHeight
|
||||
|| document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
return [windowWidth, windowHeight];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue