mirror of
https://github.com/Kareadita/Kavita.git
synced 2026-01-10 14:10:21 -05:00
* Navigate users to library page instead of home to prevent history block. * Cleaned up the Contributing to describe new code structure * Fixed a critical bug for how we find files for a chapter download (use ChapterId for lookup, not MangaFile.Id). Refactored how downloading works on the UI side to use the backend's filename whenever possible, else provide a custom name (and use backend's extension) for bundled downloads. * Fixed a bug where scroll intersection wasn't working on books without a table of content, even though it should have. * If user is using a direct url and hits an authentication guard, cache the url, allow authentication, then redirect them to said url * Added a transaction for bookmarking due to a rare case (in dev machines) where bookmark progress can duplicate * Re-enabled webtoon preference in reader settings. Refactored gotopage into it's own, dedicated handler to simplify logic. * Moved the prefetching code to occur whenever the page number within infinite scroller changes. This results in an easier to understand functioning. * Fixed isElementVisible() which was not properly calculating element visibility * GoToPage going forwards is working as expected, going backwards is completly broken * After performing a gotopage, make sure we update the scrolling direction based on the delta. * Removed some stuff thats not used, split the prefetching code up into separate functions to prepare for a rewrite. * Reworked prefetching to ensure we have a buffer of pages around ourselves. It is not fully tested, but working much better than previous implementation. Will be enhanced with DOM Pruning. * Cleaned up some old cruft from the backend code * Cleaned up the webtoon page change handler to use setPageNum, which will handle the correct prefetching of next/prev chapter * More cleanup around the codebase * Refactored the code to use a map to keep track of what is loaded or not, which works better than max/min in cases where you jump to a page that doesn't have anything preloaded and loads images out of order * Fixed a bad placement of code for when you are unauthenticated, the code will now redirect to the original location you requested before you had to login. * Some cleanup. Fixed the scrolling issue with prev page, spec seems to not work on intersection observer. using 0.01 instead of 0.0.
130 lines
8.0 KiB
HTML
130 lines
8.0 KiB
HTML
<div class="reader">
|
|
<div class="fixed-top overlay" *ngIf="menuOpen" [@slideFromTop]="menuOpen">
|
|
<div style="display: flex">
|
|
<button class="btn btn-icon" style="height: 100%" title="Back" (click)="closeReader()">
|
|
<i class="fa fa-arrow-left" aria-hidden="true"></i>
|
|
<span class="sr-only">Back</span>
|
|
</button>
|
|
|
|
<div>
|
|
<div style="font-weight: bold;">{{title}}</div>
|
|
<div class="subtitle">
|
|
{{subtitle}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ng-container *ngIf="isLoading">
|
|
<div class="spinner-border text-secondary loading" role="status">
|
|
<span class="invisible">Loading...</span>
|
|
</div>
|
|
</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'}}"
|
|
ondragstart="return false;" onselectstart="return false;">
|
|
</canvas>
|
|
<div class="webtoon-images" *ngIf="readerMode === READER_MODE.WEBTOON && !isLoading">
|
|
<app-infinite-scroller [pageNum]="pageNum" [bufferPages]="5" [goToPage]="goToPageEvent" (pageNumberChange)="handleWebtoonPageChange($event)" [totalPages]="maxPages" [urlProvider]="getPageUrl"></app-infinite-scroller>
|
|
</div>
|
|
<ng-container *ngIf="readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD"> <!--; else webtoonClickArea; TODO: See if people want this mode WEBTOON_WITH_CLICKS-->
|
|
<div class="{{readerMode === READER_MODE.MANGA_LR ? 'right' : 'top'}} {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')"></div>
|
|
<div class="{{readerMode === READER_MODE.MANGA_LR ? 'left' : 'bottom'}} {{clickOverlayClass('left')}}" (click)="handlePageChange($event, 'left')"></div>
|
|
</ng-container>
|
|
<ng-template #webtoonClickArea>
|
|
<div class="top {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')"></div>
|
|
<div class="right {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')"></div>
|
|
<div class="left {{clickOverlayClass('left')}}" (click)="handlePageChange($event, 'left')"></div>
|
|
<div class="bottom {{clickOverlayClass('left')}}" (click)="handlePageChange($event, 'left')"></div>
|
|
</ng-template>
|
|
</div>
|
|
|
|
<div class="fixed-bottom overlay" *ngIf="menuOpen" [@slideFromBottom]="menuOpen">
|
|
<div class="form-group" *ngIf="pageOptions != undefined && pageOptions.ceil != undefined && pageOptions.ceil > 0">
|
|
<span class="sr-only" id="slider-info"></span>
|
|
<div class="row no-gutters">
|
|
<button class="btn btn-small btn-icon col-1" [disabled]="prevChapterDisabled" (click)="loadPrevChapter();resetMenuCloseTimer();" title="Prev Chapter/Volume"><i class="fa fa-fast-backward" aria-hidden="true"></i></button>
|
|
<button class="btn btn-small btn-icon col-1" [disabled]="prevPageDisabled || pageNum === 0" (click)="goToPage(0);resetMenuCloseTimer();" title="First Page"><i class="fa fa-step-backward" aria-hidden="true"></i></button>
|
|
<div class="col custom-slider">
|
|
<ngx-slider [options]="pageOptions" [value]="pageNum" aria-describedby="slider-info" [manualRefresh]="refreshSlider" (userChangeEnd)="sliderPageUpdate($event);startMenuCloseTimer()" (userChangeStart)="cancelMenuCloseTimer();"></ngx-slider>
|
|
</div>
|
|
<button class="btn btn-small btn-icon col-2" [disabled]="nextPageDisabled || pageNum >= maxPages - 1" (click)="goToPage(this.maxPages);resetMenuCloseTimer();" title="Last Page"><i class="fa fa-step-forward" aria-hidden="true"></i></button>
|
|
<button class="btn btn-small btn-icon col-1" [disabled]="nextChapterDisabled" (click)="loadNextChapter();resetMenuCloseTimer();" title="Next Chapter/Volume"><i class="fa fa-fast-forward" aria-hidden="true"></i></button>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
<div class="row pt-4 ml-2 mr-2">
|
|
<div class="col">
|
|
<button class="btn btn-icon" (click)="setReadingDirection();resetMenuCloseTimer();" aria-describedby="reading-direction" title="Reading Direction: {{readingDirection === ReadingDirection.LeftToRight ? 'Left to Right' : 'Right to Left'}}">
|
|
<i class="fa fa-angle-double-{{readingDirection === ReadingDirection.LeftToRight ? 'right' : 'left'}}" aria-hidden="true"></i>
|
|
<span id="reading-direction" class="sr-only">{{readingDirection === ReadingDirection.LeftToRight ? 'Left to Right' : 'Right to Left'}}</span>
|
|
</button>
|
|
</div>
|
|
<div class="col">
|
|
<button class="btn btn-icon" title="Reading Mode" (click)="toggleReaderMode();resetMenuCloseTimer();">
|
|
<i class="fa {{readerModeIcon}}" aria-hidden="true"></i>
|
|
<span class="sr-only">Reading Mode</span>
|
|
</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>
|
|
</div>
|
|
<div class="col">
|
|
<button class="btn btn-icon" title="Settings" (click)="settingsOpen = !settingsOpen;resetMenuCloseTimer();">
|
|
<i class="fa fa-sliders-h" aria-hidden="true"></i>
|
|
<span class="sr-only">Settings</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="bottom-menu" *ngIf="settingsOpen && generalSettingsForm">
|
|
<form [formGroup]="generalSettingsForm">
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<label for="page-splitting">Image Splitting</label>
|
|
<div class="split fa fa-image">
|
|
<div class="{{splitIconClass}}"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="form-group">
|
|
<select class="form-control" id="page-splitting" formControlName="pageSplitOption">
|
|
<option [value]="1">Right to Left</option>
|
|
<option [value]="0">Left to Right</option>
|
|
<option [value]="2">None</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<label for="page-fitting">Image Scaling</label> <i class="fa {{getFittingIcon()}}" aria-hidden="true"></i>
|
|
</div>
|
|
<div class="col-6">
|
|
<select class="form-control" id="page-fitting" formControlName="fittingOption">
|
|
<option value="full-height">Height</option>
|
|
<option value="full-width">Width</option>
|
|
<option value="original">Original</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-2 mb-2">
|
|
<div class="col-6">
|
|
<label for="autoCloseMenu" class="form-check-label">Auto Close Menu</label>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="form-check">
|
|
<input id="autoCloseMenu" type="checkbox" aria-label="Admin" class="form-check-input" formControlName="autoCloseMenu">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div> |