mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Reader Fixes (#951)
* Normalized paths on download controller and when scan is killed due to missing or empty folders, log a critical error. * Tweaked the query for OnDeck to better promote recently added chapters in a series with read progress, but it's still not perfect. * Fixed an issue where up/down key weren't working unless you clicked on the book explicitly * Fixed an issue where infinite scroller was broken in fullscreen mode * When toggling fullscreen mode on infinite scroller, the current page is retained as current position * Fixed an issue where a double render would occur when we didn't need to render as fit split * Stop showing loader when not using fit split
This commit is contained in:
parent
75e1790f58
commit
4645f8e3f2
@ -153,7 +153,7 @@ namespace API.Controllers
|
|||||||
var files = (await _unitOfWork.UserRepository.GetAllBookmarksByIds(downloadBookmarkDto.Bookmarks
|
var files = (await _unitOfWork.UserRepository.GetAllBookmarksByIds(downloadBookmarkDto.Bookmarks
|
||||||
.Select(b => b.Id)
|
.Select(b => b.Id)
|
||||||
.ToList()))
|
.ToList()))
|
||||||
.Select(b => _directoryService.FileSystem.Path.Join(bookmarkDirectory, b.FileName));
|
.Select(b => Parser.Parser.NormalizePath(_directoryService.FileSystem.Path.Join(bookmarkDirectory, b.FileName)));
|
||||||
|
|
||||||
var (fileBytes, _) = await _archiveService.CreateZipForDownload(files,
|
var (fileBytes, _) = await _archiveService.CreateZipForDownload(files,
|
||||||
tempFolder);
|
tempFolder);
|
||||||
|
@ -48,7 +48,7 @@ public interface ISeriesRepository
|
|||||||
Task<bool> DeleteSeriesAsync(int seriesId);
|
Task<bool> DeleteSeriesAsync(int seriesId);
|
||||||
Task<Series> GetSeriesByIdAsync(int seriesId);
|
Task<Series> GetSeriesByIdAsync(int seriesId);
|
||||||
Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds);
|
Task<IList<Series>> GetSeriesByIdsAsync(IList<int> seriesIds);
|
||||||
Task<int[]> GetChapterIdsForSeriesAsync(int[] seriesIds);
|
Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds);
|
||||||
Task<IDictionary<int, IList<int>>> GetChapterIdWithSeriesIdForSeriesAsync(int[] seriesIds);
|
Task<IDictionary<int, IList<int>>> GetChapterIdWithSeriesIdForSeriesAsync(int[] seriesIds);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to add Progress/Rating information to series list.
|
/// Used to add Progress/Rating information to series list.
|
||||||
@ -325,7 +325,7 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int[]> GetChapterIdsForSeriesAsync(int[] seriesIds)
|
public async Task<int[]> GetChapterIdsForSeriesAsync(IList<int> seriesIds)
|
||||||
{
|
{
|
||||||
var volumes = await _context.Volume
|
var volumes = await _context.Volume
|
||||||
.Where(v => seriesIds.Contains(v.SeriesId))
|
.Where(v => seriesIds.Contains(v.SeriesId))
|
||||||
@ -516,6 +516,9 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<IEnumerable<SeriesDto>> GetOnDeck(int userId, int libraryId, UserParams userParams, FilterDto filter)
|
public async Task<IEnumerable<SeriesDto>> GetOnDeck(int userId, int libraryId, UserParams userParams, FilterDto filter)
|
||||||
{
|
{
|
||||||
|
//var allSeriesWithProgress = await _context.AppUserProgresses.Select(p => p.SeriesId).ToListAsync();
|
||||||
|
//var allChapters = await GetChapterIdsForSeriesAsync(allSeriesWithProgress);
|
||||||
|
|
||||||
var query = (await CreateFilteredSearchQueryable(userId, libraryId, filter))
|
var query = (await CreateFilteredSearchQueryable(userId, libraryId, filter))
|
||||||
.Join(_context.AppUserProgresses, s => s.Id, progress => progress.SeriesId, (s, progress) =>
|
.Join(_context.AppUserProgresses, s => s.Id, progress => progress.SeriesId, (s, progress) =>
|
||||||
new
|
new
|
||||||
@ -524,17 +527,21 @@ public class SeriesRepository : ISeriesRepository
|
|||||||
PagesRead = _context.AppUserProgresses.Where(s1 => s1.SeriesId == s.Id && s1.AppUserId == userId)
|
PagesRead = _context.AppUserProgresses.Where(s1 => s1.SeriesId == s.Id && s1.AppUserId == userId)
|
||||||
.Sum(s1 => s1.PagesRead),
|
.Sum(s1 => s1.PagesRead),
|
||||||
progress.AppUserId,
|
progress.AppUserId,
|
||||||
LastModified = _context.AppUserProgresses.Where(p => p.Id == progress.Id && p.AppUserId == userId)
|
LastReadingProgress = _context.AppUserProgresses.Where(p => p.Id == progress.Id && p.AppUserId == userId)
|
||||||
.Max(p => p.LastModified)
|
.Max(p => p.LastModified),
|
||||||
|
// This is only taking into account chapters that have progress on them, not all chapters in said series
|
||||||
|
LastChapterCreated = _context.Chapter.Where(c => progress.ChapterId == c.Id).Max(c => c.Created)
|
||||||
|
//LastChapterCreated = _context.Chapter.Where(c => allChapters.Contains(c.Id)).Max(c => c.Created)
|
||||||
});
|
});
|
||||||
|
// I think I need another Join statement. The problem is the chapters are still limited to progress
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var retSeries = query.Where(s => s.AppUserId == userId
|
var retSeries = query.Where(s => s.AppUserId == userId
|
||||||
&& s.PagesRead > 0
|
&& s.PagesRead > 0
|
||||||
&& s.PagesRead < s.Series.Pages)
|
&& s.PagesRead < s.Series.Pages)
|
||||||
.OrderByDescending(s => s.LastModified) // TODO: This needs to be Chapter Created (Max)
|
.OrderByDescending(s => s.LastReadingProgress)
|
||||||
.ThenByDescending(s => s.Series.LastModified)
|
.ThenByDescending(s => s.LastChapterCreated)
|
||||||
.Select(s => s.Series)
|
.Select(s => s.Series)
|
||||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider)
|
||||||
.AsSplitQuery()
|
.AsSplitQuery()
|
||||||
|
@ -226,14 +226,14 @@ public class ScannerService : IScannerService
|
|||||||
// Check if any of the folder roots are not available (ie disconnected from network, etc) and fail if any of them are
|
// Check if any of the folder roots are not available (ie disconnected from network, etc) and fail if any of them are
|
||||||
if (library.Folders.Any(f => !_directoryService.IsDriveMounted(f.Path)))
|
if (library.Folders.Any(f => !_directoryService.IsDriveMounted(f.Path)))
|
||||||
{
|
{
|
||||||
_logger.LogError("Some of the root folders for library are not accessible. Please check that drives are connected and rescan. Scan will be aborted");
|
_logger.LogCritical("Some of the root folders for library are not accessible. Please check that drives are connected and rescan. Scan will be aborted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Docker instances check if any of the folder roots are not available (ie disconnected volumes, etc) and fail if any of them are
|
// For Docker instances check if any of the folder roots are not available (ie disconnected volumes, etc) and fail if any of them are
|
||||||
if (library.Folders.Any(f => _directoryService.IsDirectoryEmpty(f.Path)))
|
if (library.Folders.Any(f => _directoryService.IsDirectoryEmpty(f.Path)))
|
||||||
{
|
{
|
||||||
_logger.LogError("Some of the root folders for the library are empty. " +
|
_logger.LogCritical("Some of the root folders for the library are empty. " +
|
||||||
"Either your mount has been disconnected or you are trying to delete all series in the library. " +
|
"Either your mount has been disconnected or you are trying to delete all series in the library. " +
|
||||||
"Scan will be aborted. " +
|
"Scan will be aborted. " +
|
||||||
"Check that your mount is connected or change the library's root folder and rescan");
|
"Check that your mount is connected or change the library's root folder and rescan");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="container-flex {{darkMode ? 'dark-mode' : ''}}" style="overflow: auto;" #reader>
|
<div class="container-flex {{darkMode ? 'dark-mode' : ''}} reader-container" [ngStyle]="{overflow: (isFullscreen ? 'auto' : 'visible')}" #reader>
|
||||||
<div class="fixed-top" #stickyTop>
|
<div class="fixed-top" #stickyTop>
|
||||||
<a class="sr-only sr-only-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">Skip to main content</a>
|
<a class="sr-only sr-only-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">Skip to main content</a>
|
||||||
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
||||||
@ -116,10 +116,8 @@
|
|||||||
<div #readingHtml class="book-content" [ngStyle]="{'padding-bottom': topOffset + 20 + 'px', 'margin': '0px 0px'}"
|
<div #readingHtml class="book-content" [ngStyle]="{'padding-bottom': topOffset + 20 + 'px', 'margin': '0px 0px'}"
|
||||||
[innerHtml]="page" *ngIf="page !== undefined"></div>
|
[innerHtml]="page" *ngIf="page !== undefined"></div>
|
||||||
|
|
||||||
<div class="left {{clickOverlayClass('left')}} no-observe" (click)="prevPage()" *ngIf="clickToPaginate">
|
<div class="left {{clickOverlayClass('left')}} no-observe" (click)="prevPage()" *ngIf="clickToPaginate" tabindex="-1"></div>
|
||||||
</div>
|
<div class="right {{clickOverlayClass('right')}} no-observe" (click)="nextPage()" *ngIf="clickToPaginate" tabindex="-1"></div>
|
||||||
<div class="right {{clickOverlayClass('right')}} no-observe" (click)="nextPage()" *ngIf="clickToPaginate">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="page !== undefined && scrollbarNeeded">
|
<div *ngIf="page !== undefined && scrollbarNeeded">
|
||||||
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
||||||
|
@ -159,6 +159,10 @@ $primary-color: #0062cc;
|
|||||||
//overflow: auto; // This will break progress reporting
|
//overflow: auto; // This will break progress reporting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reader-container {
|
||||||
|
outline: none; // Only the reading section itself shouldn't receive any outline. We use it to shift focus in fullscreen mode
|
||||||
|
}
|
||||||
|
|
||||||
.book-content {
|
.book-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -747,6 +747,12 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
this.scrollService.scrollTo(0, this.reader.nativeElement);
|
this.scrollService.scrollTo(0, this.reader.nativeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On fullscreen we need to click the document before arrow keys will scroll down.
|
||||||
|
if (this.isFullscreen) {
|
||||||
|
this.renderer.setAttribute(this.reader.nativeElement, 'tabIndex', '0');
|
||||||
|
this.reader.nativeElement.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPageNum(pageNum: number) {
|
setPageNum(pageNum: number) {
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .img-container {
|
||||||
|
// overflow: auto;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
@keyframes move-up-down {
|
@keyframes move-up-down {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
|
@ -63,6 +63,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
@Input() goToPage: ReplaySubject<number> = new ReplaySubject<number>();
|
@Input() goToPage: ReplaySubject<number> = new ReplaySubject<number>();
|
||||||
@Input() bookmarkPage: ReplaySubject<number> = new ReplaySubject<number>();
|
@Input() bookmarkPage: ReplaySubject<number> = new ReplaySubject<number>();
|
||||||
|
@Input() fullscreenToggled: ReplaySubject<boolean> = new ReplaySubject<boolean>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores and emits all the src urls
|
* Stores and emits all the src urls
|
||||||
@ -152,7 +153,8 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
fromEvent(window, 'scroll')
|
const reader = document.querySelector('.reader') || window;
|
||||||
|
fromEvent(reader, 'scroll')
|
||||||
.pipe(debounceTime(20), takeUntil(this.onDestroy))
|
.pipe(debounceTime(20), takeUntil(this.onDestroy))
|
||||||
.subscribe((event) => this.handleScrollEvent(event));
|
.subscribe((event) => this.handleScrollEvent(event));
|
||||||
|
|
||||||
@ -183,6 +185,13 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.fullscreenToggled) {
|
||||||
|
this.fullscreenToggled.pipe(takeUntil(this.onDestroy)).subscribe(isFullscreen => {
|
||||||
|
this.debugLog('[FullScreen] Fullscreen mode: ', isFullscreen);
|
||||||
|
this.setPageNum(this.pageNum, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="reader" #reader>
|
<div class="reader" #reader [ngStyle]="{overflow: (isFullscreen ? 'auto' : 'visible')}">
|
||||||
<div class="fixed-top overlay" *ngIf="menuOpen" [@slideFromTop]="menuOpen">
|
<div class="fixed-top overlay" *ngIf="menuOpen" [@slideFromTop]="menuOpen">
|
||||||
<div style="display: flex; margin-top: 5px;">
|
<div style="display: flex; margin-top: 5px;">
|
||||||
<button class="btn btn-icon" style="height: 100%" title="Back" (click)="closeReader()">
|
<button class="btn btn-icon" style="height: 100%" title="Back" (click)="closeReader()">
|
||||||
@ -36,7 +36,8 @@
|
|||||||
[urlProvider]="getPageUrl"
|
[urlProvider]="getPageUrl"
|
||||||
(loadNextChapter)="loadNextChapter()"
|
(loadNextChapter)="loadNextChapter()"
|
||||||
(loadPrevChapter)="loadPrevChapter()"
|
(loadPrevChapter)="loadPrevChapter()"
|
||||||
[bookmarkPage]="showBookmarkEffectEvent"></app-infinite-scroller>
|
[bookmarkPage]="showBookmarkEffectEvent"
|
||||||
|
[fullscreenToggled]="fullscreenEvent"></app-infinite-scroller>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD">
|
<ng-container *ngIf="readerMode === READER_MODE.MANGA_LR || readerMode === READER_MODE.MANGA_UD">
|
||||||
<div class="pagination-area {{readerMode === READER_MODE.MANGA_LR ? 'right' : 'bottom'}} {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')">
|
<div class="pagination-area {{readerMode === READER_MODE.MANGA_LR ? 'right' : 'bottom'}} {{clickOverlayClass('right')}}" (click)="handlePageChange($event, 'right')">
|
||||||
|
@ -131,6 +131,10 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
* An event emiter when a bookmark on a page change occurs. Used soley by the webtoon reader.
|
* An event emiter when a bookmark on a page change occurs. Used soley by the webtoon reader.
|
||||||
*/
|
*/
|
||||||
showBookmarkEffectEvent: ReplaySubject<number> = new ReplaySubject<number>();
|
showBookmarkEffectEvent: ReplaySubject<number> = new ReplaySubject<number>();
|
||||||
|
/**
|
||||||
|
* An event emiter when fullscreen mode is toggled. Used soley by the webtoon reader.
|
||||||
|
*/
|
||||||
|
fullscreenEvent: ReplaySubject<boolean> = new ReplaySubject<boolean>();
|
||||||
/**
|
/**
|
||||||
* If the menu is open/visible.
|
* If the menu is open/visible.
|
||||||
*/
|
*/
|
||||||
@ -845,63 +849,67 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderPage() {
|
renderPage() {
|
||||||
if (this.ctx && this.canvas) {
|
if (!this.ctx || !this.canvas) { return; }
|
||||||
this.canvasImage.onload = null;
|
|
||||||
|
|
||||||
this.setCanvasSize();
|
this.canvasImage.onload = null;
|
||||||
|
|
||||||
const needsSplitting = this.isCoverImage();
|
this.setCanvasSize();
|
||||||
this.updateSplitPage();
|
|
||||||
|
|
||||||
if (needsSplitting && this.currentImageSplitPart === SPLIT_PAGE_PART.LEFT_PART) {
|
const needsSplitting = this.isCoverImage();
|
||||||
this.canvas.nativeElement.width = this.canvasImage.width / 2;
|
this.updateSplitPage();
|
||||||
this.ctx.drawImage(this.canvasImage, 0, 0, this.canvasImage.width, this.canvasImage.height, 0, 0, this.canvasImage.width, this.canvasImage.height);
|
|
||||||
} else if (needsSplitting && this.currentImageSplitPart === SPLIT_PAGE_PART.RIGHT_PART) {
|
if (needsSplitting && this.currentImageSplitPart === SPLIT_PAGE_PART.LEFT_PART) {
|
||||||
this.canvas.nativeElement.width = this.canvasImage.width / 2;
|
this.canvas.nativeElement.width = this.canvasImage.width / 2;
|
||||||
this.ctx.drawImage(this.canvasImage, 0, 0, this.canvasImage.width, this.canvasImage.height, -this.canvasImage.width / 2, 0, this.canvasImage.width, this.canvasImage.height);
|
this.ctx.drawImage(this.canvasImage, 0, 0, this.canvasImage.width, this.canvasImage.height, 0, 0, this.canvasImage.width, this.canvasImage.height);
|
||||||
|
} else if (needsSplitting && this.currentImageSplitPart === SPLIT_PAGE_PART.RIGHT_PART) {
|
||||||
|
this.canvas.nativeElement.width = this.canvasImage.width / 2;
|
||||||
|
this.ctx.drawImage(this.canvasImage, 0, 0, this.canvasImage.width, this.canvasImage.height, -this.canvasImage.width / 2, 0, this.canvasImage.width, this.canvasImage.height);
|
||||||
|
} else {
|
||||||
|
if (!this.firstPageRendered && this.scalingOption === ScalingOption.Automatic) {
|
||||||
|
this.updateScalingForFirstPageRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fit Split on a page that needs splitting
|
||||||
|
if (!this.shouldRenderAsFitSplit()) {
|
||||||
|
this.setCanvasSize();
|
||||||
|
this.ctx.drawImage(this.canvasImage, 0, 0);
|
||||||
|
this.isLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const windowWidth = window.innerWidth
|
||||||
|
|| document.documentElement.clientWidth
|
||||||
|
|| document.body.clientWidth;
|
||||||
|
const windowHeight = window.innerHeight
|
||||||
|
|| document.documentElement.clientHeight
|
||||||
|
|| document.body.clientHeight;
|
||||||
|
// If the user's screen is wider than the image, just pretend this is no split, as it will render nicer
|
||||||
|
this.canvas.nativeElement.width = windowWidth;
|
||||||
|
this.canvas.nativeElement.height = windowHeight;
|
||||||
|
const ratio = this.canvasImage.width / this.canvasImage.height;
|
||||||
|
let newWidth = windowWidth;
|
||||||
|
let newHeight = newWidth / ratio;
|
||||||
|
if (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.setCanvasSize();
|
||||||
|
this.ctx.drawImage(this.canvasImage, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
if (!this.firstPageRendered && this.scalingOption === ScalingOption.Automatic) {
|
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
||||||
this.updateScalingForFirstPageRender();
|
this.ctx.drawImage(this.canvasImage, 0, 0, newWidth, newHeight);
|
||||||
}
|
|
||||||
|
|
||||||
// Fit Split on a page that needs splitting
|
|
||||||
if (!this.shouldRenderAsFitSplit()) {
|
|
||||||
this.ctx.drawImage(this.canvasImage, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const windowWidth = window.innerWidth
|
|
||||||
|| document.documentElement.clientWidth
|
|
||||||
|| document.body.clientWidth;
|
|
||||||
const windowHeight = window.innerHeight
|
|
||||||
|| document.documentElement.clientHeight
|
|
||||||
|| document.body.clientHeight;
|
|
||||||
// If the user's screen is wider than the image, just pretend this is no split, as it will render nicer
|
|
||||||
this.canvas.nativeElement.width = windowWidth;
|
|
||||||
this.canvas.nativeElement.height = windowHeight;
|
|
||||||
const ratio = this.canvasImage.width / this.canvasImage.height;
|
|
||||||
let newWidth = windowWidth;
|
|
||||||
let newHeight = newWidth / ratio;
|
|
||||||
if (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.setCanvasSize();
|
|
||||||
this.ctx.drawImage(this.canvasImage, 0, 0);
|
|
||||||
} else {
|
|
||||||
this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
|
||||||
this.ctx.drawImage(this.canvasImage, 0, 0, newWidth, newHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset scroll on non HEIGHT Fits
|
|
||||||
if (this.getFit() !== FITTING_OPTION.HEIGHT) {
|
|
||||||
window.scrollTo(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset scroll on non HEIGHT Fits
|
||||||
|
if (this.getFit() !== FITTING_OPTION.HEIGHT) {
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,12 +1088,14 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
this.readerService.exitFullscreen(() => {
|
this.readerService.exitFullscreen(() => {
|
||||||
this.isFullscreen = false;
|
this.isFullscreen = false;
|
||||||
this.firstPageRendered = false;
|
this.firstPageRendered = false;
|
||||||
|
this.fullscreenEvent.next(false);
|
||||||
this.render();
|
this.render();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.readerService.enterFullscreen(this.reader.nativeElement, () => {
|
this.readerService.enterFullscreen(this.reader.nativeElement, () => {
|
||||||
this.isFullscreen = true;
|
this.isFullscreen = true;
|
||||||
this.firstPageRendered = false;
|
this.firstPageRendered = false;
|
||||||
|
this.fullscreenEvent.next(true);
|
||||||
this.render();
|
this.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user