mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-09-09 18:23:07 -04:00
Refactored the toc into its own drawer, but need to get a mechanism setup to sync pageNumber, chapterId.
This commit is contained in:
parent
4d4b3c7285
commit
28755bdb34
@ -11,7 +11,11 @@ import {
|
||||
ViewBookmarkDrawerComponent
|
||||
} from "../book-reader/_components/_drawers/view-bookmarks-drawer/view-bookmark-drawer.component";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {ViewTocDrawerComponent} from "../book-reader/_components/_drawers/view-toc-drawer/view-toc-drawer.component";
|
||||
import {
|
||||
LoadPageEvent,
|
||||
ViewTocDrawerComponent
|
||||
} from "../book-reader/_components/_drawers/view-toc-drawer/view-toc-drawer.component";
|
||||
import {UserBreakpoint, UtilityService} from "../shared/_services/utility.service";
|
||||
|
||||
/**
|
||||
* Responsible for opening the different readers and providing any context needed. Handles closing or keeping a stack of menus open.
|
||||
@ -22,6 +26,7 @@ import {ViewTocDrawerComponent} from "../book-reader/_components/_drawers/view-t
|
||||
export class EpubReaderMenuService {
|
||||
|
||||
private readonly offcanvasService = inject(NgbOffcanvas);
|
||||
private readonly utilityService = inject(UtilityService);
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
|
||||
|
||||
@ -38,11 +43,19 @@ export class EpubReaderMenuService {
|
||||
const ref = this.offcanvasService.open(ViewAnnotationDrawerComponent, {position: 'end', panelClass: ''});
|
||||
}
|
||||
|
||||
openTocDrawer() {
|
||||
openViewTocDrawer(chapterId: number, callbackFn: (evt: LoadPageEvent | null) => void) {
|
||||
if (this.offcanvasService.hasOpenOffcanvas()) {
|
||||
this.offcanvasService.dismiss();
|
||||
}
|
||||
const ref = this.offcanvasService.open(ViewTocDrawerComponent, {position: 'end', panelClass: ''});
|
||||
ref.componentInstance.chapterId.set(chapterId);
|
||||
ref.componentInstance.loadPage.subscribe((res: LoadPageEvent | null) => {
|
||||
// Check if we are on mobile to collapse the menu
|
||||
if (this.utilityService.activeUserBreakpoint() <= UserBreakpoint.Mobile) {
|
||||
this.closeAll();
|
||||
}
|
||||
callbackFn(res);
|
||||
});
|
||||
}
|
||||
|
||||
openViewBookmarksDrawer(chapterId: number) {
|
||||
|
@ -30,8 +30,10 @@ export class ViewBookmarkDrawerComponent {
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const id = this.chapterId();
|
||||
console.log('chapter id', id);
|
||||
if (!id) return;
|
||||
if (!id) {
|
||||
console.error('You must pass chapterId');
|
||||
return;
|
||||
}
|
||||
|
||||
this.readerService.getBookmarks(id).subscribe(bookmarks => {
|
||||
this.bookmarks.set(bookmarks);
|
||||
|
@ -8,7 +8,22 @@
|
||||
|
||||
<div class="offcanvas-body">
|
||||
|
||||
Hello
|
||||
|
||||
<ul #subnav="ngbNav" ngbNav [(activeId)]="tocId" class="reader-pills nav nav-pills mb-2" [destroyOnHide]="false">
|
||||
<li [ngbNavItem]="TabID.TableOfContents">
|
||||
<a ngbNavLink>{{t('toc-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-table-of-contents [chapters]="chapters()" [chapterId]="chapterId()!" [pageNum]="pageNum"
|
||||
[currentPageAnchor]="currentPageAnchor" (loadChapter)="loadChapterPage($event)"></app-table-of-contents>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li [ngbNavItem]="TabID.PersonalTableOfContents">
|
||||
<a ngbNavLink>{{t('personal-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-personal-table-of-contents [chapterId]="chapterId()!" [pageNum]="pageNum" (loadChapter)="loadChapterPart($event)"
|
||||
[tocRefresh]="refreshPToC"></app-personal-table-of-contents>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="subnav" class="mt-3"></div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -1,11 +1,53 @@
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject} from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
effect,
|
||||
EventEmitter,
|
||||
inject,
|
||||
model
|
||||
} from '@angular/core';
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {NgbActiveOffcanvas} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {
|
||||
NgbActiveOffcanvas,
|
||||
NgbNav,
|
||||
NgbNavContent,
|
||||
NgbNavItem,
|
||||
NgbNavLink,
|
||||
NgbNavOutlet
|
||||
} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {
|
||||
PersonalTableOfContentsComponent,
|
||||
PersonalToCEvent
|
||||
} from "../../personal-table-of-contents/personal-table-of-contents.component";
|
||||
import {TableOfContentsComponent} from "../../table-of-contents/table-of-contents.component";
|
||||
import {BookChapterItem} from "../../../_models/book-chapter-item";
|
||||
import {BookService} from "../../../_services/book.service";
|
||||
|
||||
|
||||
enum TabID {
|
||||
TableOfContents = 1,
|
||||
PersonalTableOfContents = 2
|
||||
}
|
||||
|
||||
|
||||
export interface LoadPageEvent {
|
||||
pageNumber: number;
|
||||
part: string;
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-view-toc-drawer',
|
||||
imports: [
|
||||
TranslocoDirective
|
||||
TranslocoDirective,
|
||||
PersonalTableOfContentsComponent,
|
||||
NgbNav,
|
||||
NgbNavContent,
|
||||
NgbNavLink,
|
||||
TableOfContentsComponent,
|
||||
NgbNavOutlet,
|
||||
NgbNavItem
|
||||
],
|
||||
templateUrl: './view-toc-drawer.component.html',
|
||||
styleUrl: './view-toc-drawer.component.scss',
|
||||
@ -14,6 +56,73 @@ import {NgbActiveOffcanvas} from "@ng-bootstrap/ng-bootstrap";
|
||||
export class ViewTocDrawerComponent {
|
||||
private readonly activeOffcanvas = inject(NgbActiveOffcanvas);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly bookService = inject(BookService);
|
||||
|
||||
chapterId = model<number>();
|
||||
|
||||
/**
|
||||
* Sub Nav tab id
|
||||
*/
|
||||
tocId: TabID = TabID.TableOfContents;
|
||||
/**
|
||||
* The actual pages from the epub, used for showing on table of contents. This must be here as we need access to it for scroll anchors
|
||||
*/
|
||||
chapters = model<Array<BookChapterItem>>([]);
|
||||
/**
|
||||
* Current Page
|
||||
*/
|
||||
pageNum = 0;
|
||||
|
||||
/**
|
||||
* A anchors that map to the page number. When you click on one of these, we will load a given page up for the user.
|
||||
*/
|
||||
pageAnchors: {[n: string]: number } = {};
|
||||
currentPageAnchor: string = '';
|
||||
|
||||
protected readonly TabID = TabID;
|
||||
|
||||
/**
|
||||
* Used to refresh the Personal PoC
|
||||
*/
|
||||
refreshPToC: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
loadPage: EventEmitter<LoadPageEvent | null> = new EventEmitter<LoadPageEvent | null>();
|
||||
|
||||
constructor() {
|
||||
|
||||
effect(() => {
|
||||
const id = this.chapterId();
|
||||
if (!id) {
|
||||
console.error('You must pass chapterId');
|
||||
return;
|
||||
}
|
||||
|
||||
this.bookService.getBookChapters(id).subscribe(bookChapters => {
|
||||
this.chapters.set(bookChapters);
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* From personal table of contents/bookmark
|
||||
* @param event
|
||||
*/
|
||||
loadChapterPart(event: PersonalToCEvent) {
|
||||
// this.setPageNum(event.pageNum);
|
||||
// this.loadPage(event.scrollPart);
|
||||
// TODO: Emit this event to let the main book reader handle
|
||||
const evt = {pageNumber: event.pageNum, part:event.scrollPart} as LoadPageEvent;
|
||||
this.loadPage.emit(evt);
|
||||
}
|
||||
|
||||
loadChapterPage(event: {pageNum: number, part: string}) {
|
||||
// this.setPageNum(event.pageNum);
|
||||
// this.loadPage('id("' + event.part + '")');
|
||||
// TODO: Emit this event to let the main book reader handle
|
||||
const evt = {pageNumber: event.pageNum, part: `id("${event.part}")`} as LoadPageEvent;
|
||||
this.loadPage.emit(evt);
|
||||
}
|
||||
|
||||
|
||||
close() {
|
||||
|
@ -55,51 +55,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<div body class="drawer-body">
|
||||
<nav role="navigation">
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="reader-pills nav nav-pills mb-2" [destroyOnHide]="false">
|
||||
<li [ngbNavItem]="TabID.Settings">
|
||||
<a ngbNavLink>{{t('settings-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-reader-settings
|
||||
[seriesId]="seriesId"
|
||||
[readingProfile]="readingProfile"
|
||||
(colorThemeUpdate)="updateColorTheme($event)"
|
||||
(styleUpdate)="updateReaderStyles($event)"
|
||||
(clickToPaginateChanged)="showPaginationOverlay($event)"
|
||||
(fullscreen)="toggleFullscreen()"
|
||||
(bookReaderWritingStyle)="updateWritingStyle($event)"
|
||||
(layoutModeUpdate)="updateLayoutMode($event)"
|
||||
(readingDirection)="updateReadingDirection($event)"
|
||||
(immersiveMode)="updateImmersiveMode($event)"
|
||||
></app-reader-settings>
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
<li [ngbNavItem]="TabID.TableOfContents">
|
||||
<a ngbNavLink>{{t('table-of-contents-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<ul #subnav="ngbNav" ngbNav [(activeId)]="tocId" class="reader-pills nav nav-pills mb-2" [destroyOnHide]="false">
|
||||
<li [ngbNavItem]="TabID.TableOfContents">
|
||||
<a ngbNavLink>{{t('toc-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-table-of-contents [chapters]="chapters" [chapterId]="chapterId" [pageNum]="pageNum"
|
||||
[currentPageAnchor]="currentPageAnchor" (loadChapter)="loadChapterPage($event)"></app-table-of-contents>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li [ngbNavItem]="TabID.PersonalTableOfContents">
|
||||
<a ngbNavLink>{{t('bookmarks-header')}}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<app-personal-table-of-contents [chapterId]="chapterId" [pageNum]="pageNum" (loadChapter)="loadChapterPart($event)"
|
||||
[tocRefresh]="refreshPToC"></app-personal-table-of-contents>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="subnav" class="mt-3"></div>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div [ngbNavOutlet]="nav" class="mt-3"></div>
|
||||
<app-reader-settings
|
||||
[seriesId]="seriesId"
|
||||
[readingProfile]="readingProfile"
|
||||
(colorThemeUpdate)="updateColorTheme($event)"
|
||||
(styleUpdate)="updateReaderStyles($event)"
|
||||
(clickToPaginateChanged)="showPaginationOverlay($event)"
|
||||
(fullscreen)="toggleFullscreen()"
|
||||
(bookReaderWritingStyle)="updateWritingStyle($event)"
|
||||
(layoutModeUpdate)="updateLayoutMode($event)"
|
||||
(readingDirection)="updateReadingDirection($event)"
|
||||
(immersiveMode)="updateImmersiveMode($event)"
|
||||
></app-reader-settings>
|
||||
</div>
|
||||
</app-drawer>
|
||||
</div>
|
||||
@ -174,7 +141,7 @@
|
||||
<button class="btn btn-secondary btn-icon me-1" (click)="epubMenuService.openViewAnnotationsDrawer(this.chapterId)">
|
||||
<i class="fa-solid fa-highlighter" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-icon" (click)="epubMenuService.openTocDrawer()">
|
||||
<button class="btn btn-secondary btn-icon" (click)="viewToCDrawer()">
|
||||
<i class="fa-regular fa-rectangle-list" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -44,36 +44,17 @@ import {ThemeService} from 'src/app/_services/theme.service';
|
||||
import {ScrollService} from 'src/app/_services/scroll.service';
|
||||
import {PAGING_DIRECTION} from 'src/app/manga-reader/_models/reader-enums';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {TableOfContentsComponent} from '../table-of-contents/table-of-contents.component';
|
||||
import {
|
||||
NgbNav,
|
||||
NgbNavContent,
|
||||
NgbNavItem,
|
||||
NgbNavItemRole,
|
||||
NgbNavLink,
|
||||
NgbNavOutlet,
|
||||
NgbProgressbar,
|
||||
NgbTooltip
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {NgbProgressbar, NgbTooltip} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {DrawerComponent} from '../../../shared/drawer/drawer.component';
|
||||
import {BookLineOverlayComponent} from "../book-line-overlay/book-line-overlay.component";
|
||||
import {
|
||||
PersonalTableOfContentsComponent,
|
||||
PersonalToCEvent
|
||||
} from "../personal-table-of-contents/personal-table-of-contents.component";
|
||||
import {PersonalToCEvent} from "../personal-table-of-contents/personal-table-of-contents.component";
|
||||
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
||||
import {ReadingProfile} from "../../../_models/preferences/reading-profiles";
|
||||
import {ConfirmService} from "../../../shared/confirm.service";
|
||||
import {EpubHighlightComponent} from "../_annotations/epub-highlight/epub-highlight.component";
|
||||
import {Annotation} from "../../_models/annotation";
|
||||
import {EpubReaderMenuService} from "../../../_services/epub-reader-menu.service";
|
||||
|
||||
|
||||
enum TabID {
|
||||
Settings = 1,
|
||||
TableOfContents = 2,
|
||||
PersonalTableOfContents = 3
|
||||
}
|
||||
import {LoadPageEvent} from "../_drawers/view-toc-drawer/view-toc-drawer.component";
|
||||
|
||||
|
||||
interface HistoryPoint {
|
||||
@ -116,9 +97,9 @@ const elementLevelStyles = ['line-height', 'font-family'];
|
||||
transition('false <=> true', animate('4000ms'))
|
||||
])
|
||||
],
|
||||
imports: [NgTemplateOutlet, DrawerComponent, NgIf, NgbProgressbar, NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink,
|
||||
NgbNavContent, ReaderSettingsComponent, TableOfContentsComponent, NgbNavOutlet, NgStyle, NgClass, NgbTooltip,
|
||||
BookLineOverlayComponent, PersonalTableOfContentsComponent, TranslocoDirective]
|
||||
imports: [NgTemplateOutlet, DrawerComponent, NgIf, NgbProgressbar,
|
||||
ReaderSettingsComponent, NgStyle, NgClass, NgbTooltip,
|
||||
BookLineOverlayComponent, TranslocoDirective]
|
||||
})
|
||||
export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
@ -142,7 +123,6 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
protected readonly BookPageLayoutMode = BookPageLayoutMode;
|
||||
protected readonly WritingStyle = WritingStyle;
|
||||
protected readonly TabID = TabID;
|
||||
protected readonly ReadingDirection = ReadingDirection;
|
||||
protected readonly PAGING_DIRECTION = PAGING_DIRECTION;
|
||||
|
||||
@ -194,14 +174,6 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
* The current page only contains an image. This is used to determine if we should show the image in the center of the screen.
|
||||
*/
|
||||
isSingleImagePage = false;
|
||||
/**
|
||||
* Belongs to the drawer component
|
||||
*/
|
||||
activeTabId: TabID = TabID.Settings;
|
||||
/**
|
||||
* Sub Nav tab id
|
||||
*/
|
||||
tocId: TabID = TabID.TableOfContents;
|
||||
/**
|
||||
* Belongs to drawer component
|
||||
*/
|
||||
@ -1744,4 +1716,14 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
this.isLineOverlayOpen = isOpen;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
||||
viewToCDrawer() {
|
||||
this.epubMenuService.openViewTocDrawer(this.chapterId, (res: LoadPageEvent | null) => {
|
||||
if (res === null) return;
|
||||
|
||||
this.setPageNum(res.pageNumber);
|
||||
this.loadPage(res.part);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -819,7 +819,9 @@
|
||||
|
||||
"view-toc-drawer": {
|
||||
"title": "Table of Contents",
|
||||
"close": "{{common.close}}"
|
||||
"close": "{{common.close}}",
|
||||
"toc-header": "Book",
|
||||
"personal-header": "Personal"
|
||||
},
|
||||
|
||||
"create-annotation-drawer": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user