UX Pass 5 (#3128)
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
dbc4f35107
commit
c93af3e56f
126 changed files with 1989 additions and 2877 deletions
|
|
@ -1,19 +1,41 @@
|
|||
<ng-container *transloco="let t; read: 'series-detail'">
|
||||
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback" [topOffset]="56"></app-bulk-operations>
|
||||
|
||||
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid" #scrollingBlock>
|
||||
|
||||
@if (volume && series && libraryType !== null) {
|
||||
<div class="row mb-0 mb-xl-3 info-container">
|
||||
<div class="image-container col-5 col-sm-6 col-md-5 col-lg-5 col-xl-2 col-xxl-2 col-xxxl-2 d-none d-sm-block mb-3">
|
||||
<div [ngClass]="mobileSeriesImgBackground === 'true' ? 'mobile-bg' : ''" class="image-container col-5 col-sm-6 col-md-5 col-lg-5 col-xl-2 col-xxl-2 col-xxxl-2 d-none d-sm-block mb-3">
|
||||
|
||||
<app-image [styles]="{'object-fit': 'contain', 'background': 'none', 'max-height': '400px'}" [imageUrl]="coverImage"></app-image>
|
||||
@if (volume.pagesRead < volume.pages && volume.pagesRead > 0) {
|
||||
<div class="progress-banner" ngbTooltip="{{(volume.pagesRead / volume.pages) * 100 | number:'1.0-1'}}%">
|
||||
<ngb-progressbar type="primary" height="5px" [value]="volume.pagesRead" [max]="volume.pages" [showValue]="true"></ngb-progressbar>
|
||||
</div>
|
||||
@if(mobileSeriesImgBackground === 'true') {
|
||||
<app-image [styles]="{'background': 'none'}" [imageUrl]="coverImage"></app-image>
|
||||
} @else {
|
||||
<app-image [styles]="{'object-fit': 'contain', 'background': 'none', 'max-height': '400px'}" [imageUrl]="coverImage"></app-image>
|
||||
}
|
||||
@if (volume.pagesRead < volume.pages && volume.pagesRead > 0) {
|
||||
<div class="progress-banner series" ngbTooltip="{{(volume.pagesRead / volume.pages) * 100 | number:'1.0-1'}}%">
|
||||
<ngb-progressbar type="primary" [value]="volume.pagesRead" [max]="volume.pages" [showValue]="true"></ngb-progressbar>
|
||||
</div>
|
||||
@if (currentlyReadingChapter) {
|
||||
<div class="under-image">
|
||||
{{t('continue-from', {title: ContinuePointTitle})}}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="overlay-information">
|
||||
<div class="overlay-information--centered">
|
||||
<span class="card-title library mx-auto" style="width: auto;" (click)="readVolume()">
|
||||
<!-- Card Image -->
|
||||
<div style="height: 60px; width: 60px;">
|
||||
<i class="fa-solid fa-book text-center" aria-hidden="true" style="font-size: 2rem;line-height: 60px;width: 60px"></i>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-10 col-lg-7 col-md-7 col-xs-8 col-sm-6">
|
||||
|
||||
<div class="col-xl-10 col-lg-7 col-md-12 col-xs-12 col-sm-12">
|
||||
<h4 class="title mb-2">
|
||||
<a routerLink="/library/{{series.libraryId}}/series/{{series.id}}" class="dark-exempt btn-icon">{{series.name}}</a>
|
||||
</h4>
|
||||
|
|
@ -28,7 +50,8 @@
|
|||
[ageRating]="maxAgeRating"
|
||||
[hasReadingProgress]="volume.pagesRead > 0"
|
||||
[readingTimeEntity]="volume"
|
||||
[libraryType]="libraryType">
|
||||
[libraryType]="libraryType"
|
||||
[mangaFormat]="series.format">
|
||||
</app-metadata-detail-row>
|
||||
|
||||
<!-- Rating goes here (after I implement support for rating individual issues -->
|
||||
|
|
@ -77,6 +100,12 @@
|
|||
</div>
|
||||
}
|
||||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<div class="card-actions" [ngbTooltip]="t('more-alt')">
|
||||
<app-card-actionables (actionHandler)="performAction($event)" [actions]="volumeActions" [labelBy]="series.name + ' ' + volume.minNumber" iconClass="fa-ellipsis-h" btnClass="btn-secondary-outline btn"></app-card-actionables>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-auto ms-2 d-none d-md-block">
|
||||
<app-download-button [download$]="download$" [entity]="volume" entityType="volume"></app-download-button>
|
||||
</div>
|
||||
|
|
@ -93,7 +122,7 @@
|
|||
<div class="col-6">
|
||||
<span>{{t('writers-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="volumeCast.writers">
|
||||
<app-badge-expander [items]="volumeCast.writers" [allowToggle]="false" (toggle)="switchTabsToDetail()">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openPerson(FilterField.Writers, item.id)">{{item.name}}</a>
|
||||
</ng-template>
|
||||
|
|
@ -103,7 +132,7 @@
|
|||
<div class="col-6">
|
||||
<span>{{t('cover-artists-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="volumeCast.coverArtists">
|
||||
<app-badge-expander [items]="volumeCast.coverArtists" [allowToggle]="false" (toggle)="switchTabsToDetail()">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openPerson(FilterField.CoverArtist, item.id)">{{item.name}}</a>
|
||||
</ng-template>
|
||||
|
|
@ -113,11 +142,44 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-2 upper-details">
|
||||
<div class="row g-0">
|
||||
<div class="col-6 pe-5">
|
||||
<span class="fw-bold">{{t('genres-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="genres"
|
||||
[itemsTillExpander]="3"
|
||||
[allowToggle]="false"
|
||||
(toggle)="switchTabsToDetail()">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openFilter(FilterField.Genres, item.id)">{{item.title}}</a>
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<span class="fw-bold">{{t('tags-title')}}</span>
|
||||
<div>
|
||||
<app-badge-expander [items]="tags"
|
||||
[itemsTillExpander]="3"
|
||||
[allowToggle]="false"
|
||||
(toggle)="switchTabsToDetail()">
|
||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openFilter(FilterField.Tags, item.id)">{{item.title}}</a>
|
||||
</ng-template>
|
||||
</app-badge-expander>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="carousel-tabs-container">
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="nav nav-tabs mb-2" (navChange)="onNavChange($event)">
|
||||
<div class="carousel-tabs-container mb-2">
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTabId" class="nav nav-tabs" (navChange)="onNavChange($event)">
|
||||
<li [ngbNavItem]="TabID.Chapters">
|
||||
<a ngbNavLink>
|
||||
{{utilityService.formatChapterName(libraryType!, false, false, true)}}
|
||||
|
|
@ -128,7 +190,14 @@
|
|||
<virtual-scroller #scroll [items]="volume.chapters" [bufferAmount]="1" [parentScroll]="scrollingBlock" [childHeight]="1">
|
||||
<div class="card-container row g-0" #container>
|
||||
@for(item of scroll.viewPortItems; let idx = $index; track item.id + '_' + item.pagesRead) {
|
||||
<app-chapter-card class="col-auto mt-2 mb-2" [chapter]="item" [seriesId]="seriesId" [libraryId]="libraryId" [libraryType]="libraryType"></app-chapter-card>
|
||||
<app-chapter-card class="col-auto mt-2 mb-2" [chapter]="item"
|
||||
[seriesId]="seriesId"
|
||||
[libraryId]="libraryId"
|
||||
[libraryType]="libraryType"
|
||||
[actions]="chapterActions"
|
||||
(selection)="bulkSelectionService.handleCardSelection('chapter', scroll.viewPortInfo.startIndexWithBuffer + idx, volume.chapters.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('chapter', scroll.viewPortInfo.startIndexWithBuffer + idx)" [allowSelection]="true"
|
||||
></app-chapter-card>
|
||||
}
|
||||
</div>
|
||||
</virtual-scroller>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle} from "@angular/common";
|
||||
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle, NgClass, DatePipe} from "@angular/common";
|
||||
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
|
||||
import {ImageService} from "../_services/image.service";
|
||||
import {SeriesService} from "../_services/series.service";
|
||||
|
|
@ -16,7 +16,6 @@ import {LibraryService} from "../_services/library.service";
|
|||
import {ThemeService} from "../_services/theme.service";
|
||||
import {DownloadEvent, DownloadService} from "../shared/_services/download.service";
|
||||
import {BulkSelectionService} from "../cards/bulk-selection.service";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {ReaderService} from "../_services/reader.service";
|
||||
import {AccountService} from "../_services/account.service";
|
||||
import {
|
||||
|
|
@ -35,13 +34,12 @@ import {
|
|||
NgbTooltip
|
||||
} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {FilterUtilitiesService} from "../shared/_services/filter-utilities.service";
|
||||
import {Chapter} from "../_models/chapter";
|
||||
import {Chapter, LooseLeafOrDefaultNumber} from "../_models/chapter";
|
||||
import {Series} from "../_models/series";
|
||||
import {LibraryType} from "../_models/library/library";
|
||||
import {forkJoin, map, Observable, shareReplay, tap} from "rxjs";
|
||||
import {forkJoin, map, Observable, tap} from "rxjs";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {TranslocoDirective} from "@jsverse/transloco";
|
||||
import {EditChapterModalComponent} from "../_single-module/edit-chapter-modal/edit-chapter-modal.component";
|
||||
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
||||
import {FilterComparison} from "../_models/metadata/v2/filter-comparison";
|
||||
import {FilterField} from '../_models/metadata/v2/filter-field';
|
||||
import {AgeRating} from '../_models/metadata/age-rating';
|
||||
|
|
@ -78,6 +76,17 @@ import {
|
|||
MetadataDetailRowComponent
|
||||
} from "../series-detail/_components/metadata-detail-row/metadata-detail-row.component";
|
||||
import {DownloadButtonComponent} from "../series-detail/_components/download-button/download-button.component";
|
||||
import {EVENTS, MessageHubService} from "../_services/message-hub.service";
|
||||
import {CoverUpdateEvent} from "../_models/events/cover-update-event";
|
||||
import {ChapterRemovedEvent} from "../_models/events/chapter-removed-event";
|
||||
import {ActionService} from "../_services/action.service";
|
||||
import {VolumeRemovedEvent} from "../_models/events/volume-removed-event";
|
||||
import {CardActionablesComponent} from "../_single-module/card-actionables/card-actionables.component";
|
||||
import {Device} from "../_models/device/device";
|
||||
import {EditChapterModalComponent} from "../_single-module/edit-chapter-modal/edit-chapter-modal.component";
|
||||
import {BulkOperationsComponent} from "../cards/bulk-operations/bulk-operations.component";
|
||||
import {DefaultDatePipe} from "../_pipes/default-date.pipe";
|
||||
import {MangaFormatPipe} from "../_pipes/manga-format.pipe";
|
||||
|
||||
enum TabID {
|
||||
|
||||
|
|
@ -143,6 +152,7 @@ interface VolumeCast extends IHasCast {
|
|||
NgbTooltip,
|
||||
ImageComponent,
|
||||
NgStyle,
|
||||
NgClass,
|
||||
TranslocoDirective,
|
||||
CardItemComponent,
|
||||
VirtualScrollerModule,
|
||||
|
|
@ -153,7 +163,12 @@ interface VolumeCast extends IHasCast {
|
|||
CompactNumberPipe,
|
||||
BadgeExpanderComponent,
|
||||
MetadataDetailRowComponent,
|
||||
DownloadButtonComponent
|
||||
DownloadButtonComponent,
|
||||
CardActionablesComponent,
|
||||
BulkOperationsComponent,
|
||||
DatePipe,
|
||||
DefaultDatePipe,
|
||||
MangaFormatPipe
|
||||
],
|
||||
templateUrl: './volume-detail.component.html',
|
||||
styleUrl: './volume-detail.component.scss',
|
||||
|
|
@ -177,13 +192,16 @@ export class VolumeDetailComponent implements OnInit {
|
|||
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly actionFactoryService = inject(ActionFactoryService);
|
||||
private readonly actionService = inject(ActionService);
|
||||
protected readonly utilityService = inject(UtilityService);
|
||||
private readonly readingListService = inject(ReadingListService);
|
||||
private readonly messageHub = inject(MessageHubService);
|
||||
|
||||
|
||||
protected readonly AgeRating = AgeRating;
|
||||
protected readonly TabID = TabID;
|
||||
protected readonly FilterField = FilterField;
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
|
||||
@ViewChild('scrollingBlock') scrollingBlock: ElementRef<HTMLDivElement> | undefined;
|
||||
@ViewChild('companionBar') companionBar: ElementRef<HTMLDivElement> | undefined;
|
||||
|
|
@ -198,14 +216,51 @@ export class VolumeDetailComponent implements OnInit {
|
|||
libraryType: LibraryType | null = null;
|
||||
activeTabId = TabID.Chapters;
|
||||
readingLists: ReadingList[] = [];
|
||||
mobileSeriesImgBackground: string | undefined;
|
||||
downloadInProgress: boolean = false;
|
||||
|
||||
volumeActions: Array<ActionItem<Chapter>> = this.actionFactoryService.getVolumeActions(this.handleVolumeAction.bind(this));
|
||||
volumeActions: Array<ActionItem<Volume>> = this.actionFactoryService.getVolumeActions(this.handleVolumeAction.bind(this));
|
||||
chapterActions: Array<ActionItem<Chapter>> = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this));
|
||||
|
||||
bulkActionCallback = (action: ActionItem<Chapter>, data: any) => {
|
||||
if (this.volume === null) {
|
||||
return;
|
||||
}
|
||||
const selectedChapterIndexes = this.bulkSelectionService.getSelectedCardsForSource('chapter');
|
||||
const selectedChapterIds = this.volume.chapters.filter((_chapter, index: number) => {
|
||||
return selectedChapterIndexes.includes(index + '');
|
||||
});
|
||||
|
||||
switch (action.action) {
|
||||
case Action.AddToReadingList:
|
||||
this.actionService.addMultipleToReadingList(this.seriesId, [], selectedChapterIds, (success) => {
|
||||
if (success) this.bulkSelectionService.deselectAll();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.MarkAsRead:
|
||||
this.actionService.markMultipleAsRead(this.seriesId, [], selectedChapterIds, () => {
|
||||
this.bulkSelectionService.deselectAll();
|
||||
this.loadVolume();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.MarkAsUnread:
|
||||
this.actionService.markMultipleAsUnread(this.seriesId, [], selectedChapterIds, () => {
|
||||
this.bulkSelectionService.deselectAll();
|
||||
this.loadVolume();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the download we get from download service.
|
||||
*/
|
||||
download$: Observable<DownloadEvent | null> | null = null;
|
||||
showDetailsTab: boolean = true;
|
||||
currentlyReadingChapter: Chapter | undefined = undefined;
|
||||
|
||||
maxAgeRating: AgeRating = AgeRating.Unknown;
|
||||
volumeCast: VolumeCast = {
|
||||
|
|
@ -241,6 +296,34 @@ export class VolumeDetailComponent implements OnInit {
|
|||
genres: Array<Genre> = [];
|
||||
|
||||
|
||||
get ContinuePointTitle() {
|
||||
if (this.currentlyReadingChapter === undefined || !this.volume || this.volume.chapters.length <= 1) return '';
|
||||
|
||||
if (this.currentlyReadingChapter.isSpecial) {
|
||||
return this.currentlyReadingChapter.title;
|
||||
}
|
||||
|
||||
let chapterLocaleKey = 'common.chapter-num-shorthand';
|
||||
switch (this.libraryType) {
|
||||
case LibraryType.ComicVine:
|
||||
case LibraryType.Comic:
|
||||
chapterLocaleKey = 'common.issue-num-shorthand';
|
||||
break;
|
||||
case LibraryType.Book:
|
||||
case LibraryType.Manga:
|
||||
case LibraryType.LightNovel:
|
||||
case LibraryType.Images:
|
||||
chapterLocaleKey = 'common.chapter-num-shorthand';
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.currentlyReadingChapter.minNumber === LooseLeafOrDefaultNumber) {
|
||||
return translate(chapterLocaleKey, {num: this.volume.chapters[0].minNumber});
|
||||
}
|
||||
|
||||
return translate(chapterLocaleKey, {num: this.currentlyReadingChapter.minNumber});
|
||||
}
|
||||
|
||||
|
||||
get ScrollingBlockHeight() {
|
||||
if (this.scrollingBlock === undefined) return 'calc(var(--vh)*100)';
|
||||
|
|
@ -253,9 +336,6 @@ export class VolumeDetailComponent implements OnInit {
|
|||
return 'calc(var(--vh)*100 - ' + totalHeight + 'px)';
|
||||
}
|
||||
|
||||
get UseBookLogic() {
|
||||
return this.libraryType === LibraryType.Book || this.libraryType === LibraryType.LightNovel;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const seriesId = this.route.snapshot.paramMap.get('seriesId');
|
||||
|
|
@ -266,14 +346,36 @@ export class VolumeDetailComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
this.mobileSeriesImgBackground = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--mobile-series-img-background').trim();
|
||||
this.seriesId = parseInt(seriesId, 10);
|
||||
this.volumeId = parseInt(volumeId, 10);
|
||||
this.libraryId = parseInt(libraryId, 10);
|
||||
|
||||
this.coverImage = this.imageService.getVolumeCoverImage(this.volumeId);
|
||||
|
||||
this.messageHub.messages$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(event => {
|
||||
if (event.event === EVENTS.CoverUpdate) {
|
||||
const coverUpdateEvent = event.payload as CoverUpdateEvent;
|
||||
if (coverUpdateEvent.entityType === 'volume' && coverUpdateEvent.id === this.volumeId) {
|
||||
this.themeService.refreshColorScape('volume', coverUpdateEvent.id).subscribe();
|
||||
}
|
||||
} else if (event.event === EVENTS.ChapterRemoved) {
|
||||
const removedEvent = event.payload as ChapterRemovedEvent;
|
||||
if (removedEvent.seriesId !== this.seriesId) return;
|
||||
|
||||
// remove the chapter from the tab
|
||||
if (this.volume) {
|
||||
this.volume.chapters = this.volume.chapters.filter(c => c.id !== removedEvent.chapterId);
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
} else if (event.event === EVENTS.VolumeRemoved) {
|
||||
const removedEvent = event.payload as VolumeRemovedEvent;
|
||||
if (removedEvent.volumeId !== this.volumeId) return;
|
||||
|
||||
// remove the chapter from the tab
|
||||
this.navigateToSeries();
|
||||
}
|
||||
});
|
||||
|
||||
forkJoin({
|
||||
series: this.seriesService.getSeries(this.seriesId),
|
||||
|
|
@ -396,6 +498,9 @@ export class VolumeDetailComponent implements OnInit {
|
|||
.flatMap(c => c.ageRating)
|
||||
);
|
||||
|
||||
this.setContinuePoint();
|
||||
|
||||
|
||||
this.showDetailsTab = hasAnyCast(this.volumeCast) || (this.genres || []).length > 0 || (this.tags || []).length > 0;
|
||||
this.isLoading = false;
|
||||
this.cdRef.markForCheck();
|
||||
|
|
@ -404,10 +509,12 @@ export class VolumeDetailComponent implements OnInit {
|
|||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
readChapter(chapter: Chapter, incognitoMode: boolean = false) {
|
||||
if (this.bulkSelectionService.hasSelections()) return;
|
||||
|
||||
this.readerService.readChapter(this.libraryId, this.seriesId, chapter, incognitoMode);
|
||||
loadVolume() {
|
||||
this.volumeService.getVolumeMetadata(this.volumeId).subscribe(v => {
|
||||
this.volume = v;
|
||||
this.setContinuePoint();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
readVolume(incognitoMode: boolean = false) {
|
||||
|
|
@ -423,9 +530,18 @@ export class VolumeDetailComponent implements OnInit {
|
|||
ref.componentInstance.libraryId = this.libraryId;
|
||||
ref.componentInstance.seriesId = this.series!.id;
|
||||
|
||||
ref.closed.subscribe((res: EditVolumeModalCloseResult) => {
|
||||
// TODO
|
||||
});
|
||||
ref.closed.subscribe(_ => this.setContinuePoint());
|
||||
}
|
||||
|
||||
openEditChapterModal(chapter: Chapter) {
|
||||
const ref = this.modalService.open(EditChapterModalComponent, { size: 'xl' });
|
||||
ref.componentInstance.chapter = chapter;
|
||||
ref.componentInstance.libraryType = this.libraryType;
|
||||
ref.componentInstance.libraryId = this.libraryId;
|
||||
ref.componentInstance.seriesId = this.series!.id;
|
||||
|
||||
ref.closed.subscribe(_ => this.setContinuePoint());
|
||||
|
||||
}
|
||||
|
||||
onNavChange(event: NgbNavChangeEvent) {
|
||||
|
|
@ -436,26 +552,112 @@ export class VolumeDetailComponent implements OnInit {
|
|||
|
||||
updateUrl(activeTab: TabID) {
|
||||
const newUrl = `${this.router.url.split('#')[0]}#${activeTab}`;
|
||||
//this.router.navigateByUrl(newUrl, { onSameUrlNavigation: 'ignore' });
|
||||
window.history.replaceState({}, '', newUrl);
|
||||
}
|
||||
|
||||
openPerson(field: FilterField, value: number) {
|
||||
this.filterUtilityService.applyFilter(['all-series'], field, FilterComparison.Equal, `${value}`).subscribe();
|
||||
}
|
||||
|
||||
handleVolumeAction(action: ActionItem<Volume>) {
|
||||
// TODO: Implement actionables
|
||||
performAction(action: ActionItem<Volume>) {
|
||||
if (typeof action.callback === 'function') {
|
||||
action.callback(action, this.volume!);
|
||||
}
|
||||
}
|
||||
|
||||
handleChapterActionCallback(action: ActionItem<Chapter>, chapter: Chapter) {
|
||||
switch (action.action) {
|
||||
case Action.Delete:
|
||||
case(Action.MarkAsRead):
|
||||
this.actionService.markChapterAsRead(this.libraryId, this.seriesId, chapter, _ => this.setContinuePoint());
|
||||
break;
|
||||
case Action.MarkAsRead:
|
||||
case(Action.MarkAsUnread):
|
||||
this.actionService.markChapterAsUnread(this.libraryId, this.seriesId, chapter, _ => this.setContinuePoint());
|
||||
break;
|
||||
case Action.MarkAsUnread:
|
||||
case(Action.Edit):
|
||||
this.openEditChapterModal(chapter);
|
||||
break;
|
||||
case Action.MarkAsRead:
|
||||
case(Action.AddToReadingList):
|
||||
this.actionService.addChapterToReadingList(chapter, this.seriesId, () => {/* No Operation */ });
|
||||
break;
|
||||
case(Action.IncognitoRead):
|
||||
this.readerService.readChapter(this.libraryId, this.seriesId, chapter, true);
|
||||
break;
|
||||
case (Action.SendTo):
|
||||
const device = (action._extra!.data as Device);
|
||||
this.actionService.sendToDevice([chapter.id], device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
async handleVolumeAction(action: ActionItem<Volume>) {
|
||||
switch (action.action) {
|
||||
case Action.Delete:
|
||||
await this.actionService.deleteVolume(this.volumeId, (res) => {
|
||||
if (!res) return;
|
||||
this.navigateToSeries();
|
||||
});
|
||||
break;
|
||||
case Action.MarkAsRead:
|
||||
this.actionService.markVolumeAsRead(this.seriesId, this.volume!, res => {
|
||||
this.volume!.pagesRead = this.volume!.pages;
|
||||
this.setContinuePoint();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.MarkAsUnread:
|
||||
this.actionService.markVolumeAsUnread(this.seriesId, this.volume!, res => {
|
||||
this.volume!.pagesRead = 0;
|
||||
this.setContinuePoint();
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.AddToReadingList:
|
||||
break;
|
||||
case Action.Download:
|
||||
if (this.downloadInProgress) return;
|
||||
this.downloadService.download('volume', this.volume!, (d) => {
|
||||
this.downloadInProgress = !!d;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
break;
|
||||
case Action.IncognitoRead:
|
||||
this.readVolume(true);
|
||||
break;
|
||||
case Action.SendTo:
|
||||
const chapterIds = this.volume!.chapters.map(c => c.id);
|
||||
const device = (action._extra!.data as Device);
|
||||
this.actionService.sendToDevice(chapterIds, device);
|
||||
break;
|
||||
case Action.Edit:
|
||||
this.openEditModal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
openFilter(field: FilterField, value: string | number) {
|
||||
this.filterUtilityService.applyFilter(['all-series'], field, FilterComparison.Equal, `${value}`).subscribe();
|
||||
}
|
||||
|
||||
|
||||
switchTabsToDetail() {
|
||||
this.activeTabId = TabID.Details;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
navigateToSeries() {
|
||||
this.router.navigate(['library', this.libraryId, 'series', this.seriesId]);
|
||||
}
|
||||
|
||||
setContinuePoint() {
|
||||
if (!this.volume) return;
|
||||
|
||||
const chaptersWithProgress = this.volume.chapters.filter(c => c.pagesRead < c.pages);
|
||||
if (chaptersWithProgress.length > 0 && this.volume.chapters.length > 1) {
|
||||
this.currentlyReadingChapter = chaptersWithProgress[0];
|
||||
console.log('Updating currentlyReading chapter', this.currentlyReadingChapter)
|
||||
this.cdRef.markForCheck();
|
||||
} else {
|
||||
this.currentlyReadingChapter = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue