Bookmarking Pages within the Reader (#469)
# Added - Added: Added the ability to bookmark certain pages within the manga (image) reader and later download them from the series context menu. # Fixed - Fixed: Fixed an issue where after adding a new folder to an existing library, a scan wouldn't be kicked off - Fixed: In some cases, after clicking the background of a modal, the modal would close, but state wouldn't be handled as if cancel was pushed # Changed - Changed: Admin contextual actions on cards will now be separated by a line to help differentiate. - Changed: Performance enhancement on an API used before reading # Dev - Bumped dependencies to latest versions ============================================= * Bumped versions of dependencies and refactored bookmark to progress. * Refactored method names in UI from bookmark to progress to prepare for new bookmark entity * Basic code is done, user can now bookmark a page (currently image reader only). * Comments and pipes * Some accessibility for new bookmark button * Fixed up the APIs to work correctly, added a new modal to quickly explore bookmarks (not implemented, not final). * Cleanup on the UI side to get the modal to look decent * Added dismissed handlers for modals where appropriate * Refactored UI to only show number of bookmarks across files to simplify delivery. Admin actionables are now separated by hr vs non-admin actions. * Basic API implemented, now to implement the ability to actually extract files. * Implemented the ability to download bookmarks. * Fixed a bug where adding a new folder to an existing library would not trigger a scan library task. * Fixed an issue that could cause bookmarked pages to get copied out of order. * Added handler from series-card component
This commit is contained in:
parent
d1d7df9291
commit
e9ec6671d5
49 changed files with 1860 additions and 241 deletions
|
|
@ -114,15 +114,14 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
currentPageAnchor: string = '';
|
||||
intersectionObserver: IntersectionObserver = new IntersectionObserver((entries) => this.handleIntersection(entries), { threshold: [1] });
|
||||
/**
|
||||
* Last seen bookmark part path
|
||||
* Last seen progress part path
|
||||
*/
|
||||
lastSeenScrollPartPath: string = '';
|
||||
|
||||
// Temp hack: Override background color for reader and restore it onDestroy
|
||||
/**
|
||||
* Hack: Override background color for reader and restore it onDestroy
|
||||
*/
|
||||
originalBodyColor: string | undefined;
|
||||
|
||||
|
||||
|
||||
darkModeStyles = `
|
||||
*:not(input), *:not(select), *:not(code), *:not(:link), *:not(.ngx-toastr) {
|
||||
color: #dcdcdc !important;
|
||||
|
|
@ -198,11 +197,11 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
/**
|
||||
* After the page has loaded, setup the scroll handler. The scroll handler has 2 parts. One is if there are page anchors setup (aka page anchor elements linked with the
|
||||
* table of content) then we calculate what has already been reached and grab the last reached one to bookmark. If page anchors aren't setup (toc missing), then try to bookmark
|
||||
* table of content) then we calculate what has already been reached and grab the last reached one to save progress. If page anchors aren't setup (toc missing), then try to save progress
|
||||
* based on the last seen scroll part (xpath).
|
||||
*/
|
||||
ngAfterViewInit() {
|
||||
// check scroll offset and if offset is after any of the "id" markers, bookmark it
|
||||
// check scroll offset and if offset is after any of the "id" markers, save progress
|
||||
fromEvent(window, 'scroll')
|
||||
.pipe(debounceTime(200), takeUntil(this.onDestroy)).subscribe((event) => {
|
||||
if (this.isLoading) return;
|
||||
|
|
@ -215,7 +214,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
const alreadyReached = Object.values(this.pageAnchors).filter((i: number) => i <= verticalOffset);
|
||||
if (alreadyReached.length > 0) {
|
||||
this.currentPageAnchor = Object.keys(this.pageAnchors)[alreadyReached.length - 1];
|
||||
this.readerService.bookmark(this.seriesId, this.volumeId, this.chapterId, this.pageNum, this.lastSeenScrollPartPath).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum, this.lastSeenScrollPartPath).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
return;
|
||||
} else {
|
||||
this.currentPageAnchor = '';
|
||||
|
|
@ -223,7 +222,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
|
||||
if (this.lastSeenScrollPartPath !== '') {
|
||||
this.readerService.bookmark(this.seriesId, this.volumeId, this.chapterId, this.pageNum, this.lastSeenScrollPartPath).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum, this.lastSeenScrollPartPath).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -279,7 +278,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
forkJoin({
|
||||
chapter: this.seriesService.getChapter(this.chapterId),
|
||||
bookmark: this.readerService.getBookmark(this.chapterId),
|
||||
progress: this.readerService.getProgress(this.chapterId),
|
||||
chapters: this.bookService.getBookChapters(this.chapterId),
|
||||
info: this.bookService.getBookInfo(this.chapterId)
|
||||
}).pipe(take(1)).subscribe(results => {
|
||||
|
|
@ -287,17 +286,17 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.volumeId = results.chapter.volumeId;
|
||||
this.maxPages = results.chapter.pages;
|
||||
this.chapters = results.chapters;
|
||||
this.pageNum = results.bookmark.pageNum;
|
||||
this.pageNum = results.progress.pageNum;
|
||||
this.bookTitle = results.info;
|
||||
|
||||
|
||||
if (this.pageNum >= this.maxPages) {
|
||||
this.pageNum = this.maxPages - 1;
|
||||
this.readerService.bookmark(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
}
|
||||
|
||||
// Check if user bookmark has part, if so load it so we scroll to it
|
||||
this.loadPage(results.bookmark.bookScrollId || undefined);
|
||||
// Check if user progress has part, if so load it so we scroll to it
|
||||
this.loadPage(results.progress.bookScrollId || undefined);
|
||||
}, () => {
|
||||
setTimeout(() => {
|
||||
this.closeReader();
|
||||
|
|
@ -484,7 +483,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
loadPage(part?: string | undefined, scrollTop?: number | undefined) {
|
||||
this.isLoading = true;
|
||||
|
||||
this.readerService.bookmark(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */});
|
||||
|
||||
this.bookService.getBookPage(this.chapterId, this.pageNum).pipe(take(1)).subscribe(content => {
|
||||
this.page = this.domSanitizer.bypassSecurityTrustHtml(content);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue