|
|
|
|
@@ -15,6 +15,7 @@ import { Chapter, Page } from "../../services/parsers/rulib/rulib.chapter.dto";
|
|
|
|
|
import { IRulibChapter } from "../../services/parsers/rulib/rulib.chapters.dto";
|
|
|
|
|
import { SearchService } from "../../services/search.service";
|
|
|
|
|
import { ScaleImageComponent } from "../scale-image/scale-image.component";
|
|
|
|
|
import { LazyLoadDirective } from "./lazyscroll.directive";
|
|
|
|
|
import { CachedPage, CachedPages } from "./reader.dto";
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
@@ -22,13 +23,13 @@ import { CachedPage, CachedPages } from "./reader.dto";
|
|
|
|
|
templateUrl: "./reader.component.html",
|
|
|
|
|
styleUrls: ["./reader.component.less"],
|
|
|
|
|
standalone: true,
|
|
|
|
|
imports: [CommonModule, ScaleImageComponent, RouterLink],
|
|
|
|
|
imports: [CommonModule, ScaleImageComponent, RouterLink, LazyLoadDirective],
|
|
|
|
|
})
|
|
|
|
|
export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
//FIXME: Scrolling to top when manhwa
|
|
|
|
|
pages: Page[] = [];
|
|
|
|
|
currentPageIndex = 0;
|
|
|
|
|
cachedPages: CachedPages = {};
|
|
|
|
|
cachedPages: CachedPages = new Map<number, CachedPage>();
|
|
|
|
|
imageUrl: string = "";
|
|
|
|
|
isManhwa = false;
|
|
|
|
|
currentChapterInfo: Chapter | null = null;
|
|
|
|
|
@@ -53,7 +54,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get manhwaPages() {
|
|
|
|
|
return Object.values(this.cachedPages) as CachedPage[];
|
|
|
|
|
return this.cachedPages.values();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngAfterViewInit(): void {
|
|
|
|
|
@@ -79,11 +80,11 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
this.router.navigate(["/"]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.isManhwa$.pipe(takeUntil(this.destroy$)).subscribe((isManhwa) => {
|
|
|
|
|
this.isManhwa = isManhwa;
|
|
|
|
|
if (isManhwa) this.initManhwaScroll();
|
|
|
|
|
else this.noManhwaScroll();
|
|
|
|
|
});
|
|
|
|
|
// this.isManhwa$.pipe(takeUntil(this.destroy$)).subscribe((isManhwa) => {
|
|
|
|
|
// this.isManhwa = isManhwa;
|
|
|
|
|
// if (isManhwa) this.initManhwaScroll();
|
|
|
|
|
// else this.noManhwaScroll();
|
|
|
|
|
// });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleScrollManhwa(event: Event) {
|
|
|
|
|
@@ -154,7 +155,6 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
this.cachePage(index); // Кэшируем текущую и соседние страницы
|
|
|
|
|
if (!this.isManhwa$.value) this.unloadCachedPages(index); // Сгружаем ненужные страницы из кэша
|
|
|
|
|
if (!this.isManhwa$.value) {
|
|
|
|
|
console.log("scroll");
|
|
|
|
|
const container = document.querySelector("app-reader");
|
|
|
|
|
if (container) {
|
|
|
|
|
container.scrollTo({
|
|
|
|
|
@@ -163,7 +163,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!this.cachedPages[index]?.imageData) {
|
|
|
|
|
if (!this.cachedPages.get(index)?.imageData) {
|
|
|
|
|
// Если страница не закэширована, загружаем её
|
|
|
|
|
this.fetchAndCachePage(index)
|
|
|
|
|
.pipe(takeUntil(this.destroy$))
|
|
|
|
|
@@ -181,7 +181,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
const nextChapterIndex = Math.min(thisChapterIndex + 1, this.chaptersInfo.length - 1);
|
|
|
|
|
const nextChapter = this.chaptersInfo[nextChapterIndex];
|
|
|
|
|
if (nextChapter !== this.chaptersInfo[thisChapterIndex]) {
|
|
|
|
|
this.cachedPages = [];
|
|
|
|
|
this.cachedPages.clear();
|
|
|
|
|
this.router.navigate(["/", "reader"], {
|
|
|
|
|
queryParams: {
|
|
|
|
|
url: this.url,
|
|
|
|
|
@@ -197,7 +197,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
const prevChapterIndex = Math.max(thisChapterIndex - 1, 0);
|
|
|
|
|
const prevChapter = this.chaptersInfo[prevChapterIndex];
|
|
|
|
|
if (prevChapter !== this.chaptersInfo[thisChapterIndex]) {
|
|
|
|
|
this.cachedPages = [];
|
|
|
|
|
this.cachedPages.clear();
|
|
|
|
|
this.router.navigate(["/", "reader"], {
|
|
|
|
|
queryParams: {
|
|
|
|
|
url: this.url,
|
|
|
|
|
@@ -229,7 +229,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isPageCached(index: number): boolean {
|
|
|
|
|
return !!this.cachedPages[index]?.imageData;
|
|
|
|
|
return !!this.cachedPages.get(index)?.imageData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Загрузка и сохранение изображения в кэш
|
|
|
|
|
@@ -239,15 +239,12 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
.pipe(
|
|
|
|
|
map((imageData) => {
|
|
|
|
|
const url = this.getImageUrl(imageData);
|
|
|
|
|
this.cachedPages = {
|
|
|
|
|
...this.cachedPages,
|
|
|
|
|
[index]: {
|
|
|
|
|
...this.pages[index],
|
|
|
|
|
imageData,
|
|
|
|
|
imageUrl: url,
|
|
|
|
|
isManhwa: +this.pages[index].ratio < 0.5,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
this.cachedPages.set(index, {
|
|
|
|
|
...this.pages[index],
|
|
|
|
|
imageData,
|
|
|
|
|
imageUrl: url,
|
|
|
|
|
isManhwa: +this.pages[index].ratio < 0.5,
|
|
|
|
|
});
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
@@ -257,7 +254,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
for (const key in this.cachedPages) {
|
|
|
|
|
const pageIndex = +key;
|
|
|
|
|
if (index - pageIndex > 2) {
|
|
|
|
|
delete this.cachedPages[pageIndex];
|
|
|
|
|
this.cachedPages.delete(pageIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -273,7 +270,7 @@ export class ReaderComponent implements AfterViewInit, OnDestroy {
|
|
|
|
|
|
|
|
|
|
// Обновляем изображение на странице
|
|
|
|
|
private updateImage() {
|
|
|
|
|
const currentPage = this.cachedPages[this.currentPageIndex];
|
|
|
|
|
const currentPage = this.cachedPages.get(this.currentPageIndex);
|
|
|
|
|
if (currentPage && currentPage.imageData && !this.isManhwa$.value) {
|
|
|
|
|
const blob = new Blob([currentPage.imageData], { type: "image/jpeg" });
|
|
|
|
|
const urlCreator = window.URL || window.webkitURL;
|
|
|
|
|
|