Epub Reading Overlay Re-Design (#2156)
* Removed DeviceId * Dependency updates part 1 * Dependency updates part 2 * Dependency updates part 3 * Dependency updates part 4 * Dependency updates done. Updated all backend and UI ones. * Refactored the book line overlay to sit at the top of the reader. It looks much better and will work a lot better for future work. * Removed an event that was causing series detail to load extra data when it didn't need to after editing series metadata. * Removed one more load request on series detail after updating edit series modal.
This commit is contained in:
parent
96366adbc4
commit
9dc785f031
15 changed files with 575 additions and 771 deletions
|
@ -1,46 +1,44 @@
|
|||
<div #container class="overlay" *ngIf="selectedText.length > 0 || mode !== BookLineOverlayMode.None"
|
||||
[ngStyle]="{ 'top.px': overlayPosition.top, 'left.px': overlayPosition.left }">
|
||||
<div class="overlay" *ngIf="selectedText.length > 0 || mode !== BookLineOverlayMode.None">
|
||||
|
||||
<!-- Todo: close button or something -->
|
||||
<ng-container [ngSwitch]="mode">
|
||||
<ng-container *ngSwitchCase="BookLineOverlayMode.None">
|
||||
<div class="row g-0">
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="copy()">
|
||||
<i class="fa-solid fa-copy" aria-hidden="true"></i>
|
||||
<div>Copy</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="switchMode(BookLineOverlayMode.Bookmark)">
|
||||
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
|
||||
<div>Bookmark</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row g-0 justify-content-between">
|
||||
<ng-container [ngSwitch]="mode">
|
||||
<ng-container *ngSwitchCase="BookLineOverlayMode.None">
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="copy()">
|
||||
<i class="fa-solid fa-copy" aria-hidden="true"></i>
|
||||
<div>Copy</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="switchMode(BookLineOverlayMode.Bookmark)">
|
||||
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
|
||||
<div>Bookmark</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="reset()">
|
||||
<i class="fa-solid fa-times-circle" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="BookLineOverlayMode.Bookmark">
|
||||
<form [formGroup]="bookmarkForm">
|
||||
<div class="input-group">
|
||||
<input id="bookmark-name" class="form-control" formControlName="name" type="text" placeholder="Bookmark Name"
|
||||
[class.is-invalid]="bookmarkForm.get('name')?.invalid && bookmarkForm.get('name')?.touched" aria-describedby="bookmark-name-btn">
|
||||
<button class="btn btn-outline-primary" id="bookmark-name-btn" (click)="createPTOC()">Save</button>
|
||||
<div id="bookmark-name-validations" class="invalid-feedback" *ngIf="bookmarkForm.dirty || bookmarkForm.touched">
|
||||
<div *ngIf="bookmarkForm.get('name')?.errors?.required" role="status">
|
||||
This field is required
|
||||
<div class="col-auto">
|
||||
<button class="btn btn-icon btn-sm" (click)="reset()">
|
||||
<i class="fa-solid fa-times-circle" aria-hidden="true"></i>
|
||||
<div>Close</div>
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="BookLineOverlayMode.Bookmark">
|
||||
<form [formGroup]="bookmarkForm">
|
||||
<div class="input-group">
|
||||
<input id="bookmark-name" class="form-control" formControlName="name" type="text" placeholder="Bookmark Name"
|
||||
[class.is-invalid]="bookmarkForm.get('name')?.invalid && bookmarkForm.get('name')?.touched" aria-describedby="bookmark-name-btn">
|
||||
<button class="btn btn-outline-primary" id="bookmark-name-btn" (click)="createPTOC()">Save</button>
|
||||
<div id="bookmark-name-validations" class="invalid-feedback" *ngIf="bookmarkForm.dirty || bookmarkForm.touched">
|
||||
<div *ngIf="bookmarkForm.get('name')?.errors?.required" role="status">
|
||||
This field is required
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
.overlay {
|
||||
position: absolute;
|
||||
background-color: rgb(0, 0, 0);
|
||||
color: white;
|
||||
background-color: var(--br-actionbar-bg-color);
|
||||
color: var(--bs-body-bg);
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
max-width: 285px; /* Optional: limit the width of the overlay box */
|
||||
z-index: 9999; /* Ensure it's displayed above other elements */
|
||||
z-index: 9999;
|
||||
width: 100vw;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,6 @@ export class BookLineOverlayComponent implements OnInit {
|
|||
|
||||
xPath: string = '';
|
||||
selectedText: string = '';
|
||||
previousSelection: string = '';
|
||||
overlayPosition: { top: number; left: number } = { top: 0, left: 0 };
|
||||
mode: BookLineOverlayMode = BookLineOverlayMode.None;
|
||||
bookmarkForm: FormGroup = new FormGroup({
|
||||
name: new FormControl('', [Validators.required]),
|
||||
|
@ -81,23 +79,13 @@ export class BookLineOverlayComponent implements OnInit {
|
|||
this.selectedText = selection ? selection.toString().trim() : '';
|
||||
|
||||
if (this.selectedText.length > 0 && this.mode === BookLineOverlayMode.None) {
|
||||
// Get x,y coord so we can position overlay
|
||||
if (event.target) {
|
||||
const range = selection!.getRangeAt(0)
|
||||
const rect = range.getBoundingClientRect();
|
||||
const box = getBoundingClientRect(event.target as Element);
|
||||
this.xPath = this.readerService.getXPathTo(event.target);
|
||||
if (this.xPath !== '') {
|
||||
this.xPath = '//' + this.xPath;
|
||||
}
|
||||
|
||||
this.overlayPosition = {
|
||||
top: rect.top + window.scrollY - 64 - rect.height, // 64px is the top menu area
|
||||
left: rect.left + window.scrollX + 30 // Adjust 10 to center the overlay box horizontally
|
||||
};
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.xPath = this.readerService.getXPathTo(event.target);
|
||||
if (this.xPath !== '') {
|
||||
this.xPath = '//' + this.xPath;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
<div class="fixed-top" #stickyTop>
|
||||
<a class="visually-hidden-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">Skip to main content</a>
|
||||
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
|
||||
<app-book-line-overlay [parent]="bookContainerElemRef" *ngIf="page !== undefined"
|
||||
[libraryId]="libraryId"
|
||||
[volumeId]="volumeId"
|
||||
[chapterId]="chapterId"
|
||||
[seriesId]="seriesId"
|
||||
[pageNumber]="pageNum"
|
||||
(refreshToC)="refreshPersonalToC()">
|
||||
</app-book-line-overlay>
|
||||
<app-drawer #commentDrawer="drawer" [(isOpen)]="drawerOpen" [options]="{topOffset: topOffset}">
|
||||
<h5 header>
|
||||
Book Settings
|
||||
|
@ -89,7 +97,7 @@
|
|||
</app-drawer>
|
||||
</div>
|
||||
|
||||
<div #readingSection class="reading-section {{ColumnLayout}} {{WritingStyleClass}}" [ngStyle]="{'width': PageWidthForPagination}" [ngClass]="{'immersive' : immersiveMode || !actionBarVisible}" [@isLoading]="isLoading ? true : false">
|
||||
<div #readingSection class="reading-section {{ColumnLayout}} {{WritingStyleClass}}" [ngStyle]="{'width': PageWidthForPagination}" [ngClass]="{'immersive' : immersiveMode || !actionBarVisible}" [@isLoading]="isLoading">
|
||||
|
||||
<ng-container *ngIf="clickToPaginate">
|
||||
<div class="left {{clickOverlayClass('left')}} no-observe" [ngClass]="{'immersive' : immersiveMode}"
|
||||
|
@ -144,14 +152,4 @@
|
|||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
</div>
|
||||
|
||||
<app-book-line-overlay [parent]="bookContainerElemRef" *ngIf="page !== undefined"
|
||||
[libraryId]="libraryId"
|
||||
[volumeId]="volumeId"
|
||||
[chapterId]="chapterId"
|
||||
[seriesId]="seriesId"
|
||||
[pageNumber]="pageNum"
|
||||
(refreshToC)="refreshPersonalToC()">
|
||||
</app-book-line-overlay>
|
||||
|
|
|
@ -1595,4 +1595,5 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.refreshPToC.emit();
|
||||
}
|
||||
|
||||
protected readonly undefined = undefined;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ import { TagBadgeComponent } from '../../../shared/tag-badge/tag-badge.component
|
|||
import { CardActionablesComponent } from '../../../cards/card-item/card-actionables/card-actionables.component';
|
||||
import { SideNavCompanionBarComponent } from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
||||
|
||||
interface RelatedSeris {
|
||||
interface RelatedSeriesPair {
|
||||
series: Series;
|
||||
relation: RelationKind;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
* Track by function for Chapter to tell when to refresh card data
|
||||
*/
|
||||
trackByChapterIdentity = (index: number, item: Chapter) => `${item.title}_${item.number}_${item.volumeId}_${item.pagesRead}`;
|
||||
trackByRelatedSeriesIdentify = (index: number, item: RelatedSeris) => `${item.series.name}_${item.series.libraryId}_${item.series.pagesRead}_${item.relation}`;
|
||||
trackByRelatedSeriesIdentify = (index: number, item: RelatedSeriesPair) => `${item.series.name}_${item.series.libraryId}_${item.series.pagesRead}_${item.relation}`;
|
||||
trackBySeriesIdentify = (index: number, item: Series) => `${item.name}_${item.libraryId}_${item.pagesRead}`;
|
||||
trackByStoryLineIdentity = (index: number, item: StoryLineItem) => {
|
||||
if (item.isChapter) {
|
||||
|
@ -174,7 +174,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
/**
|
||||
* Related Series. Sorted by backend
|
||||
*/
|
||||
relations: Array<RelatedSeris> = [];
|
||||
relations: Array<RelatedSeriesPair> = [];
|
||||
/**
|
||||
* Recommended Series
|
||||
*/
|
||||
|
@ -342,7 +342,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
this.libraryId = parseInt(libraryId, 10);
|
||||
this.seriesImage = this.imageService.getSeriesCoverImage(this.seriesId);
|
||||
this.cdRef.markForCheck();
|
||||
this.loadSeries(this.seriesId);
|
||||
this.loadSeries(this.seriesId, true);
|
||||
|
||||
this.pageExtrasGroup.get('renderMode')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((val: PageLayoutMode | null) => {
|
||||
if (val == null) return;
|
||||
|
@ -493,7 +493,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
});
|
||||
}
|
||||
|
||||
loadSeries(seriesId: number) {
|
||||
loadSeries(seriesId: number, loadExternal: boolean = false) {
|
||||
this.seriesService.getMetadata(seriesId).subscribe(metadata => {
|
||||
this.seriesMetadata = metadata;
|
||||
this.cdRef.markForCheck();
|
||||
|
@ -517,7 +517,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
this.libraryType = results.libType;
|
||||
this.series = results.series;
|
||||
|
||||
if (this.libraryType !== LibraryType.Comic) {
|
||||
if (this.libraryType !== LibraryType.Comic && loadExternal) {
|
||||
this.loadReviews(true);
|
||||
}
|
||||
|
||||
|
@ -591,7 +591,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
}
|
||||
|
||||
createRelatedSeries(series: Series, relation: RelationKind) {
|
||||
return {series, relation} as RelatedSeris;
|
||||
return {series, relation} as RelatedSeriesPair;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -751,11 +751,6 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||
modalRef.closed.subscribe((closeResult: {success: boolean, series: Series, coverImageUpdate: boolean}) => {
|
||||
window.scrollTo(0, 0);
|
||||
if (closeResult.success) {
|
||||
this.seriesService.getSeries(this.seriesId).subscribe(s => {
|
||||
this.series = s;
|
||||
this.cdRef.detectChanges();
|
||||
});
|
||||
|
||||
this.loadSeries(this.seriesId);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue