Angular 16 (#2007)
* Removed adv, which isn't needed. * Updated zone * Updated to angular 16 * Updated to angular 16 (partially) * Updated to angular 16 * Package update for Angular 16 (and other dependencies) is complete. * Replaced all takeUntil(this.onDestroy) with new takeUntilDestroyed() * Updated all inputs that have ! to be required and deleted all unit tests. * Corrected how takeUntilDestroyed() is supposed to be implemented.
This commit is contained in:
parent
9bc8361381
commit
9c06cccd35
87 changed files with 3964 additions and 20426 deletions
|
|
@ -15,7 +15,7 @@ import { CollectionTagService } from 'src/app/_services/collection-tag.service';
|
|||
})
|
||||
export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
|
||||
|
||||
@Input() title!: string;
|
||||
@Input({required: true}) title!: string;
|
||||
/**
|
||||
* Series Ids to add to Collection Tag
|
||||
*/
|
||||
|
|
@ -33,14 +33,14 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
|
|||
@ViewChild('title') inputElem!: ElementRef<HTMLInputElement>;
|
||||
|
||||
|
||||
constructor(private modal: NgbActiveModal, private collectionService: CollectionTagService,
|
||||
constructor(private modal: NgbActiveModal, private collectionService: CollectionTagService,
|
||||
private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.listForm.addControl('title', new FormControl(this.title, []));
|
||||
this.listForm.addControl('filterQuery', new FormControl('', []));
|
||||
|
||||
|
||||
this.loading = true;
|
||||
this.cdRef.markForCheck();
|
||||
this.collectionService.allTags().subscribe(tags => {
|
||||
|
|
@ -77,7 +77,7 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
|
|||
this.toastr.success('Series added to ' + tag.title + ' collection');
|
||||
this.modal.close();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
filterList = (listItem: ReadingList) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
|
@ -14,6 +23,7 @@ import { ImageService } from 'src/app/_services/image.service';
|
|||
import { LibraryService } from 'src/app/_services/library.service';
|
||||
import { SeriesService } from 'src/app/_services/series.service';
|
||||
import { UploadService } from 'src/app/_services/upload.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
|
||||
enum TabID {
|
||||
|
|
@ -28,9 +38,9 @@ enum TabID {
|
|||
styleUrls: ['./edit-collection-tags.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
||||
export class EditCollectionTagsComponent implements OnInit {
|
||||
|
||||
@Input() tag!: CollectionTag;
|
||||
@Input({required: true}) tag!: CollectionTag;
|
||||
series: Array<Series> = [];
|
||||
selections!: SelectionModel<Series>;
|
||||
isLoading: boolean = true;
|
||||
|
|
@ -42,8 +52,7 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
active = TabID.General;
|
||||
imageUrls: Array<string> = [];
|
||||
selectedCover: string = '';
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
get hasSomeSelected() {
|
||||
return this.selections != null && this.selections.hasSomeSelected();
|
||||
|
|
@ -57,7 +66,7 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
return TabID;
|
||||
}
|
||||
|
||||
constructor(public modal: NgbActiveModal, private seriesService: SeriesService,
|
||||
constructor(public modal: NgbActiveModal, private seriesService: SeriesService,
|
||||
private collectionService: CollectionTagService, private toastr: ToastrService,
|
||||
private confirmSerivce: ConfirmService, private libraryService: LibraryService,
|
||||
private imageService: ImageService, private uploadService: UploadService,
|
||||
|
|
@ -76,7 +85,7 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
|
||||
this.collectionTagForm.get('title')?.valueChanges.pipe(
|
||||
debounceTime(100),
|
||||
debounceTime(100),
|
||||
distinctUntilChanged(),
|
||||
switchMap(name => this.collectionService.tagNameExists(name)),
|
||||
tap(exists => {
|
||||
|
|
@ -84,22 +93,17 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
if (!exists || isExistingName) {
|
||||
this.collectionTagForm.get('title')?.setErrors(null);
|
||||
} else {
|
||||
this.collectionTagForm.get('title')?.setErrors({duplicateName: true})
|
||||
this.collectionTagForm.get('title')?.setErrors({duplicateName: true})
|
||||
}
|
||||
this.cdRef.markForCheck();
|
||||
}),
|
||||
takeUntil(this.onDestroy)
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
).subscribe();
|
||||
|
||||
this.imageUrls.push(this.imageService.randomize(this.imageService.getCollectionCoverImage(this.tag.id)));
|
||||
this.loadSeries();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
onPageChange(pageNum: number) {
|
||||
this.pagination.currentPage = pageNum;
|
||||
this.loadSeries();
|
||||
|
|
@ -153,7 +157,7 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
const unselectedIds = this.selections.unselected().map(s => s.id);
|
||||
const tag = this.collectionTagForm.value;
|
||||
tag.id = this.tag.id;
|
||||
|
||||
|
||||
if (unselectedIds.length == this.series.length && !await this.confirmSerivce.confirm('Warning! No series are selected, saving will delete the tag. Are you sure you want to continue?')) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -162,11 +166,11 @@ export class EditCollectionTagsComponent implements OnInit, OnDestroy {
|
|||
this.collectionService.updateTag(tag),
|
||||
this.collectionService.updateSeriesForTag(tag, this.selections.unselected().map(s => s.id))
|
||||
];
|
||||
|
||||
|
||||
if (selectedIndex > 0) {
|
||||
apis.push(this.uploadService.updateCollectionCoverImage(this.tag.id, this.selectedCover));
|
||||
}
|
||||
|
||||
|
||||
forkJoin(apis).subscribe(() => {
|
||||
this.modal.close({success: true, coverImageUpdated: selectedIndex > 0});
|
||||
this.toastr.success('Tag updated');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { forkJoin, Observable, of, Subject } from 'rxjs';
|
||||
|
|
@ -21,6 +30,7 @@ import { LibraryService } from 'src/app/_services/library.service';
|
|||
import { MetadataService } from 'src/app/_services/metadata.service';
|
||||
import { SeriesService } from 'src/app/_services/series.service';
|
||||
import { UploadService } from 'src/app/_services/upload.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
enum TabID {
|
||||
General = 0,
|
||||
|
|
@ -38,9 +48,9 @@ enum TabID {
|
|||
styleUrls: ['./edit-series-modal.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
||||
export class EditSeriesModalComponent implements OnInit {
|
||||
|
||||
@Input() series!: Series;
|
||||
@Input({required: true}) series!: Series;
|
||||
seriesVolumes: any[] = [];
|
||||
isLoadingVolumes = false;
|
||||
/**
|
||||
|
|
@ -56,9 +66,7 @@ export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
|||
editSeriesForm!: FormGroup;
|
||||
libraryName: string | undefined = undefined;
|
||||
size: number = 0;
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
// Typeaheads
|
||||
ageRatingSettings: TypeaheadSettings<AgeRatingDto> = new TypeaheadSettings();
|
||||
|
|
@ -117,16 +125,16 @@ export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
|||
private libraryService: LibraryService,
|
||||
private collectionService: CollectionTagService,
|
||||
private uploadService: UploadService,
|
||||
private metadataService: MetadataService,
|
||||
private metadataService: MetadataService,
|
||||
private readonly cdRef: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.imageUrls.push(this.imageService.getSeriesCoverImage(this.series.id));
|
||||
|
||||
this.libraryService.getLibraryNames().pipe(takeUntil(this.onDestroy)).subscribe(names => {
|
||||
this.libraryService.getLibraryNames().pipe(takeUntilDestroyed(this.destroyRef)).subscribe(names => {
|
||||
this.libraryName = names[this.series.libraryId];
|
||||
});
|
||||
|
||||
|
||||
this.initSeries = Object.assign({}, this.series);
|
||||
|
||||
this.editSeriesForm = this.fb.group({
|
||||
|
|
@ -180,41 +188,41 @@ export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
this.editSeriesForm.get('name')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('name')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.series.nameLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.editSeriesForm.get('sortName')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('sortName')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.series.sortNameLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.editSeriesForm.get('localizedName')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('localizedName')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.series.localizedNameLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.editSeriesForm.get('summary')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('summary')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.metadata.summaryLocked = true;
|
||||
this.metadata.summary = val;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
|
||||
this.editSeriesForm.get('ageRating')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('ageRating')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.metadata.ageRating = parseInt(val + '', 10);
|
||||
this.metadata.ageRatingLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.editSeriesForm.get('publicationStatus')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('publicationStatus')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.metadata.publicationStatus = parseInt(val + '', 10);
|
||||
this.metadata.publicationStatusLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.editSeriesForm.get('releaseYear')?.valueChanges.pipe(takeUntil(this.onDestroy)).subscribe(val => {
|
||||
this.editSeriesForm.get('releaseYear')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => {
|
||||
this.metadata.releaseYear = parseInt(val + '', 10);
|
||||
this.metadata.releaseYearLocked = true;
|
||||
this.cdRef.markForCheck();
|
||||
|
|
@ -257,10 +265,6 @@ export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
setupTypeaheads() {
|
||||
forkJoin([
|
||||
|
|
@ -490,7 +494,7 @@ export class EditSeriesModalComponent implements OnInit, OnDestroy {
|
|||
.filter(v => v !== null && v !== '')
|
||||
.join(',');
|
||||
|
||||
|
||||
|
||||
|
||||
const apis = [
|
||||
this.seriesService.updateMetadata(this.metadata, this.collectionTags)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { Action, ActionFactoryService, ActionItem } from 'src/app/_services/action-factory.service';
|
||||
import { BulkSelectionService } from '../bulk-selection.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
@Component({
|
||||
selector: 'app-bulk-operations',
|
||||
|
|
@ -9,16 +19,15 @@ import { BulkSelectionService } from '../bulk-selection.service';
|
|||
styleUrls: ['./bulk-operations.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class BulkOperationsComponent implements OnInit, OnDestroy {
|
||||
export class BulkOperationsComponent implements OnInit {
|
||||
|
||||
@Input() actionCallback!: (action: ActionItem<any>, data: any) => void;
|
||||
@Input({required: true}) actionCallback!: (action: ActionItem<any>, data: any) => void;
|
||||
|
||||
topOffset: number = 56;
|
||||
hasMarkAsRead: boolean = false;
|
||||
hasMarkAsUnread: boolean = false;
|
||||
actions: Array<ActionItem<any>> = [];
|
||||
|
||||
private onDestory: Subject<void> = new Subject();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
get Action() {
|
||||
return Action;
|
||||
|
|
@ -28,7 +37,7 @@ export class BulkOperationsComponent implements OnInit, OnDestroy {
|
|||
private actionFactoryService: ActionFactoryService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.bulkSelectionService.actions$.pipe(takeUntil(this.onDestory)).subscribe(actions => {
|
||||
this.bulkSelectionService.actions$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(actions => {
|
||||
// We need to do a recursive callback apply
|
||||
this.actions = this.actionFactoryService.applyCallbackToList(actions, this.actionCallback.bind(this));
|
||||
this.hasMarkAsRead = this.actionFactoryService.hasAction(this.actions, Action.MarkAsRead);
|
||||
|
|
@ -37,11 +46,6 @@ export class BulkOperationsComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestory.next();
|
||||
this.onDestory.complete();
|
||||
}
|
||||
|
||||
handleActionCallback(action: ActionItem<any>, data: any) {
|
||||
this.actionCallback(action, data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NgbActiveOffcanvas } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
|
@ -24,9 +33,10 @@ import { MetadataService } from 'src/app/_services/metadata.service';
|
|||
import { ReaderService } from 'src/app/_services/reader.service';
|
||||
import { SeriesService } from 'src/app/_services/series.service';
|
||||
import { UploadService } from 'src/app/_services/upload.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
enum TabID {
|
||||
General = 0,
|
||||
General = 0,
|
||||
Metadata = 1,
|
||||
Cover = 2,
|
||||
Files = 3
|
||||
|
|
@ -38,13 +48,14 @@ enum TabID {
|
|||
styleUrls: ['./card-detail-drawer.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
||||
export class CardDetailDrawerComponent implements OnInit {
|
||||
|
||||
@Input() parentName = '';
|
||||
@Input() seriesId: number = 0;
|
||||
@Input() libraryId: number = 0;
|
||||
@Input() data!: Volume | Chapter;
|
||||
|
||||
@Input({required: true}) data!: Volume | Chapter;
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
/**
|
||||
* If this is a volume, this will be first chapter for said volume.
|
||||
*/
|
||||
|
|
@ -63,7 +74,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
|
||||
actions: ActionItem<any>[] = [];
|
||||
chapterActions: ActionItem<Chapter>[] = [];
|
||||
libraryType: LibraryType = LibraryType.Manga;
|
||||
libraryType: LibraryType = LibraryType.Manga;
|
||||
|
||||
|
||||
tabs = [{title: 'General', disabled: false}, {title: 'Metadata', disabled: false}, {title: 'Cover', disabled: false}, {title: 'Info', disabled: false}];
|
||||
|
|
@ -74,8 +85,6 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
|
||||
download$: Observable<Download> | null = null;
|
||||
downloadInProgress: boolean = false;
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
get MangaFormat() {
|
||||
return MangaFormat;
|
||||
|
|
@ -97,16 +106,15 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
return TabID;
|
||||
}
|
||||
|
||||
constructor(public utilityService: UtilityService,
|
||||
public imageService: ImageService, private uploadService: UploadService, private toastr: ToastrService,
|
||||
private accountService: AccountService, private actionFactoryService: ActionFactoryService,
|
||||
constructor(public utilityService: UtilityService,
|
||||
public imageService: ImageService, private uploadService: UploadService, private toastr: ToastrService,
|
||||
private accountService: AccountService, private actionFactoryService: ActionFactoryService,
|
||||
private actionService: ActionService, private router: Router, private libraryService: LibraryService,
|
||||
private seriesService: SeriesService, private readerService: ReaderService, public metadataService: MetadataService,
|
||||
public activeOffcanvas: NgbActiveOffcanvas, private downloadService: DownloadService, private readonly cdRef: ChangeDetectorRef,
|
||||
private deviceSerivce: DeviceService) {
|
||||
private seriesService: SeriesService, private readerService: ReaderService,
|
||||
public activeOffcanvas: NgbActiveOffcanvas, private downloadService: DownloadService, private readonly cdRef: ChangeDetectorRef) {
|
||||
this.isAdmin$ = this.accountService.currentUser$.pipe(
|
||||
takeUntil(this.onDestroy),
|
||||
map(user => (user && this.accountService.hasAdminRole(user)) || false),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
map(user => (user && this.accountService.hasAdminRole(user)) || false),
|
||||
shareReplay()
|
||||
);
|
||||
}
|
||||
|
|
@ -133,7 +141,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this))
|
||||
.filter(item => item.action !== Action.Edit);
|
||||
this.chapterActions.push({title: 'Read', action: Action.Read, callback: this.handleChapterActionCallback.bind(this), requiresAdmin: false, children: []});
|
||||
this.chapterActions.push({title: 'Read', action: Action.Read, callback: this.handleChapterActionCallback.bind(this), requiresAdmin: false, children: []});
|
||||
if (this.isChapter) {
|
||||
const chapter = this.utilityService.asChapter(this.data);
|
||||
this.chapterActions = this.actionFactoryService.filterSendToAction(this.chapterActions, chapter);
|
||||
|
|
@ -146,7 +154,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
|
||||
|
||||
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
|
||||
this.chapters.forEach((c: Chapter) => {
|
||||
c.files.sort((a: MangaFile, b: MangaFile) => collator.compare(a.filePath, b.filePath));
|
||||
|
|
@ -157,10 +165,6 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.activeOffcanvas.close();
|
||||
|
|
@ -193,7 +197,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
|||
if (this.seriesId === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.actionService.markChapterAsRead(this.libraryId, this.seriesId, chapter, () => { this.cdRef.markForCheck(); });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, OnChanges {
|
|||
ngOnChanges(): void {
|
||||
this.jumpBarKeysToRender = [...this.jumpBarKeys];
|
||||
this.resizeJumpBar();
|
||||
|
||||
|
||||
// Don't resume jump key when there is a custom sort order, as it won't work
|
||||
if (!this.hasCustomSort()) {
|
||||
if (!this.hasResumedJumpKey && this.jumpBarKeysToRender.length > 0) {
|
||||
|
|
@ -124,7 +124,7 @@ export class CardDetailLayoutComponent implements OnInit, OnDestroy, OnChanges {
|
|||
if (resumeKey === '') return;
|
||||
const keys = this.jumpBarKeysToRender.filter(k => k.key === resumeKey);
|
||||
if (keys.length < 1) return;
|
||||
|
||||
|
||||
this.hasResumedJumpKey = true;
|
||||
setTimeout(() => this.scrollTo(keys[0]), 100);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { filter, map, takeUntil } from 'rxjs/operators';
|
||||
import { DownloadEvent, DownloadService } from 'src/app/shared/_services/download.service';
|
||||
|
|
@ -19,6 +30,7 @@ import { LibraryService } from 'src/app/_services/library.service';
|
|||
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
|
||||
import { ScrollService } from 'src/app/_services/scroll.service';
|
||||
import { BulkSelectionService } from '../bulk-selection.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
@Component({
|
||||
selector: 'app-card-item',
|
||||
|
|
@ -26,7 +38,7 @@ import { BulkSelectionService } from '../bulk-selection.service';
|
|||
styleUrls: ['./card-item.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class CardItemComponent implements OnInit, OnDestroy {
|
||||
export class CardItemComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Card item url. Will internally handle error and missing covers
|
||||
|
|
@ -59,7 +71,7 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
/**
|
||||
* This is the entity we are representing. It will be returned if an action is executed.
|
||||
*/
|
||||
@Input() entity!: Series | Volume | Chapter | CollectionTag | PageBookmark | RecentlyAddedItem;
|
||||
@Input({required: true}) entity!: Series | Volume | Chapter | CollectionTag | PageBookmark | RecentlyAddedItem;
|
||||
/**
|
||||
* If the entity is selected or not.
|
||||
*/
|
||||
|
|
@ -115,17 +127,17 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
selectionInProgress: boolean = false;
|
||||
|
||||
private user: User | undefined;
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
get MangaFormat(): typeof MangaFormat {
|
||||
return MangaFormat;
|
||||
}
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
constructor(public imageService: ImageService, private libraryService: LibraryService,
|
||||
public utilityService: UtilityService, private downloadService: DownloadService,
|
||||
public bulkSelectionService: BulkSelectionService,
|
||||
private messageHub: MessageHubService, private accountService: AccountService,
|
||||
private messageHub: MessageHubService, private accountService: AccountService,
|
||||
private scrollService: ScrollService, private readonly cdRef: ChangeDetectorRef,
|
||||
private actionFactoryService: ActionFactoryService) {}
|
||||
|
||||
|
|
@ -136,14 +148,14 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
if (this.suppressLibraryLink === false) {
|
||||
if (!this.suppressLibraryLink) {
|
||||
if (this.entity !== undefined && this.entity.hasOwnProperty('libraryId')) {
|
||||
this.libraryId = (this.entity as Series).libraryId;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
if (this.libraryId !== undefined && this.libraryId > 0) {
|
||||
this.libraryService.getLibraryName(this.libraryId).pipe(takeUntil(this.onDestroy)).subscribe(name => {
|
||||
this.libraryService.getLibraryName(this.libraryId).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(name => {
|
||||
this.libraryName = name;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
|
@ -176,18 +188,18 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
this.filterSendTo();
|
||||
this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {
|
||||
this.accountService.currentUser$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(user => {
|
||||
this.user = user;
|
||||
});
|
||||
|
||||
this.messageHub.messages$.pipe(filter(event => event.event === EVENTS.UserProgressUpdate),
|
||||
map(evt => evt.payload as UserProgressUpdateEvent), takeUntil(this.onDestroy)).subscribe(updateEvent => {
|
||||
map(evt => evt.payload as UserProgressUpdateEvent), takeUntilDestroyed(this.destroyRef)).subscribe(updateEvent => {
|
||||
if (this.user === undefined || this.user.username !== updateEvent.username) return;
|
||||
if (this.utilityService.isChapter(this.entity) && updateEvent.chapterId !== this.entity.id) return;
|
||||
if (this.utilityService.isVolume(this.entity) && updateEvent.volumeId !== this.entity.id) return;
|
||||
if (this.utilityService.isSeries(this.entity) && updateEvent.seriesId !== this.entity.id) return;
|
||||
|
||||
// For volume or Series, we can't just take the event
|
||||
// For volume or Series, we can't just take the event
|
||||
if (this.utilityService.isChapter(this.entity)) {
|
||||
const c = this.utilityService.asChapter(this.entity);
|
||||
c.pagesRead = updateEvent.pagesRead;
|
||||
|
|
@ -212,7 +224,7 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.detectChanges();
|
||||
});
|
||||
|
||||
this.download$ = this.downloadService.activeDownloads$.pipe(takeUntil(this.onDestroy), map((events) => {
|
||||
this.download$ = this.downloadService.activeDownloads$.pipe(takeUntilDestroyed(this.destroyRef), map((events) => {
|
||||
if(this.utilityService.isSeries(this.entity)) return events.find(e => e.entityType === 'series' && e.subTitle === this.downloadService.downloadSubtitle('series', (this.entity as Series))) || null;
|
||||
if(this.utilityService.isVolume(this.entity)) return events.find(e => e.entityType === 'volume' && e.subTitle === this.downloadService.downloadSubtitle('volume', (this.entity as Volume))) || null;
|
||||
if(this.utilityService.isChapter(this.entity)) return events.find(e => e.entityType === 'chapter' && e.subTitle === this.downloadService.downloadSubtitle('chapter', (this.entity as Chapter))) || null;
|
||||
|
|
@ -223,10 +235,6 @@ export class CardItemComponent implements OnInit, OnDestroy {
|
|||
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
@HostListener('touchmove', ['$event'])
|
||||
onTouchMove(event: TouchEvent) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export class DownloadIndicatorComponent {
|
|||
/**
|
||||
* Observable that represents when the download completes
|
||||
*/
|
||||
@Input() download$!: Observable<Download | DownloadEvent | null> | null;
|
||||
@Input({required: true}) download$!: Observable<Download | DownloadEvent | null> | null;
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { map, Subject, Observable, of, firstValueFrom, takeUntil, ReplaySubject } from 'rxjs';
|
||||
import { UtilityService } from 'src/app/shared/_services/utility.service';
|
||||
|
|
@ -10,6 +20,7 @@ import { ImageService } from 'src/app/_services/image.service';
|
|||
import { LibraryService } from 'src/app/_services/library.service';
|
||||
import { SearchService } from 'src/app/_services/search.service';
|
||||
import { SeriesService } from 'src/app/_services/series.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
interface RelationControl {
|
||||
series: {id: number, name: string} | undefined; // Will add type as well
|
||||
|
|
@ -23,11 +34,11 @@ interface RelationControl {
|
|||
styleUrls: ['./edit-series-relation.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class EditSeriesRelationComponent implements OnInit, OnDestroy {
|
||||
export class EditSeriesRelationComponent implements OnInit {
|
||||
|
||||
@Input() series!: Series;
|
||||
@Input({required: true}) series!: Series;
|
||||
/**
|
||||
* This will tell the component to save based on it's internal state
|
||||
* This will tell the component to save based on its internal state
|
||||
*/
|
||||
@Input() save: EventEmitter<void> = new EventEmitter();
|
||||
|
||||
|
|
@ -39,15 +50,14 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy {
|
|||
libraryNames: {[key:number]: string} = {};
|
||||
|
||||
focusTypeahead = new EventEmitter();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
get RelationKind() {
|
||||
return RelationKind;
|
||||
}
|
||||
|
||||
|
||||
private onDestroy: Subject<void> = new Subject<void>();
|
||||
|
||||
constructor(private seriesService: SeriesService, private utilityService: UtilityService,
|
||||
constructor(private seriesService: SeriesService, private utilityService: UtilityService,
|
||||
public imageService: ImageService, private libraryService: LibraryService, private searchService: SearchService,
|
||||
private readonly cdRef: ChangeDetectorRef) {}
|
||||
|
||||
|
|
@ -74,12 +84,7 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
||||
this.save.pipe(takeUntil(this.onDestroy)).subscribe(() => this.saveState());
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
this.save.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => this.saveState());
|
||||
}
|
||||
|
||||
setupRelationRows(relations: Array<Series>, kind: RelationKind) {
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ import { ImageService } from 'src/app/_services/image.service';
|
|||
})
|
||||
export class EntityInfoCardsComponent implements OnInit, OnDestroy {
|
||||
|
||||
@Input() entity!: Volume | Chapter;
|
||||
@Input({required: true}) entity!: Volume | Chapter;
|
||||
/**
|
||||
* This will pull extra information
|
||||
* This will pull extra information
|
||||
*/
|
||||
@Input() includeMetadata: boolean = false;
|
||||
|
||||
|
|
@ -84,19 +84,19 @@ export class EntityInfoCardsComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.totalPages = this.chapter.pages;
|
||||
if (!this.isChapter) {
|
||||
this.totalPages = this.utilityService.asVolume(this.entity).pages;
|
||||
}
|
||||
|
||||
|
||||
this.totalWordCount = this.chapter.wordCount;
|
||||
if (!this.isChapter) {
|
||||
this.totalWordCount = this.utilityService.asVolume(this.entity).chapters.map(c => c.wordCount).reduce((sum, d) => sum + d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (this.isChapter) {
|
||||
this.readingTime.minHours = this.chapter.minHoursToRead;
|
||||
this.readingTime.maxHours = this.chapter.maxHoursToRead;
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ export class EntityTitleComponent implements OnInit {
|
|||
*/
|
||||
@Input() libraryType: LibraryType = LibraryType.Manga;
|
||||
@Input() seriesName: string = '';
|
||||
@Input() entity!: Volume | Chapter;
|
||||
@Input({required: true}) entity!: Volume | Chapter;
|
||||
/**
|
||||
* When generating the title, should this prepend 'Volume number' before the Chapter wording
|
||||
*/
|
||||
@Input() includeVolume: boolean = false;
|
||||
/**
|
||||
* When a titleName (aka a title) is avaliable on the entity, show it over Volume X Chapter Y
|
||||
* When a titleName (aka a title) is available on the entity, show it over Volume X Chapter Y
|
||||
*/
|
||||
@Input() prioritizeTitleName: boolean = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { map, Observable, Subject, takeUntil } from 'rxjs';
|
||||
import { Download } from 'src/app/shared/_models/download';
|
||||
|
|
@ -9,6 +19,7 @@ import { LibraryType } from 'src/app/_models/library';
|
|||
import { RelationKind } from 'src/app/_models/series-detail/relation-kind';
|
||||
import { Volume } from 'src/app/_models/volume';
|
||||
import { Action, ActionItem } from 'src/app/_services/action-factory.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
@Component({
|
||||
selector: 'app-list-item',
|
||||
|
|
@ -16,12 +27,12 @@ import { Action, ActionItem } from 'src/app/_services/action-factory.service';
|
|||
styleUrls: ['./list-item.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ListItemComponent implements OnInit, OnDestroy {
|
||||
export class ListItemComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Volume or Chapter to render
|
||||
*/
|
||||
@Input() entity!: Volume | Chapter;
|
||||
@Input({required: true}) entity!: Volume | Chapter;
|
||||
/**
|
||||
* Image to show
|
||||
*/
|
||||
|
|
@ -59,7 +70,7 @@ export class ListItemComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
@Input() includeVolume: boolean = false;
|
||||
/**
|
||||
* Show's the title if avaible on entity
|
||||
* Show's the title if available on entity
|
||||
*/
|
||||
@Input() showTitle: boolean = true;
|
||||
/**
|
||||
|
|
@ -68,24 +79,23 @@ export class ListItemComponent implements OnInit, OnDestroy {
|
|||
@Input() blur: boolean = false;
|
||||
|
||||
@Output() read: EventEmitter<void> = new EventEmitter<void>();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
actionInProgress: boolean = false;
|
||||
summary: string = '';
|
||||
isChapter: boolean = false;
|
||||
|
||||
|
||||
|
||||
download$: Observable<DownloadEvent | null> | null = null;
|
||||
downloadInProgress: boolean = false;
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
get Title() {
|
||||
if (this.isChapter) return (this.entity as Chapter).titleName;
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
constructor(private utilityService: UtilityService, private downloadService: DownloadService,
|
||||
constructor(private utilityService: UtilityService, private downloadService: DownloadService,
|
||||
private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
@ -99,21 +109,16 @@ export class ListItemComponent implements OnInit, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
|
||||
|
||||
this.download$ = this.downloadService.activeDownloads$.pipe(takeUntil(this.onDestroy), map((events) => {
|
||||
this.download$ = this.downloadService.activeDownloads$.pipe(takeUntilDestroyed(this.destroyRef), map((events) => {
|
||||
if(this.utilityService.isVolume(this.entity)) return events.find(e => e.entityType === 'volume' && e.subTitle === this.downloadService.downloadSubtitle('volume', (this.entity as Volume))) || null;
|
||||
if(this.utilityService.isChapter(this.entity)) return events.find(e => e.entityType === 'chapter' && e.subTitle === this.downloadService.downloadSubtitle('chapter', (this.entity as Chapter))) || null;
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
performAction(action: ActionItem<any>) {
|
||||
if (action.action == Action.Download) {
|
||||
if (this.downloadInProgress === true) {
|
||||
if (this.downloadInProgress) {
|
||||
this.toastr.info('Download is already in progress. Please wait.');
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ import { RelationKind } from 'src/app/_models/series-detail/relation-kind';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SeriesCardComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@Input() data!: Series;
|
||||
@Input({required: true}) data!: Series;
|
||||
@Input() libraryId = 0;
|
||||
@Input() suppressLibraryLink = false;
|
||||
/**
|
||||
* If the entity is selected or not.
|
||||
* If the entity is selected or not.
|
||||
*/
|
||||
@Input() selected: boolean = false;
|
||||
/**
|
||||
|
|
@ -51,7 +51,7 @@ export class SeriesCardComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
constructor(private router: Router, private cdRef: ChangeDetectorRef,
|
||||
private seriesService: SeriesService, private toastr: ToastrService,
|
||||
private modalService: NgbModal, private imageService: ImageService,
|
||||
private modalService: NgbModal, private imageService: ImageService,
|
||||
private actionFactoryService: ActionFactoryService,
|
||||
private actionService: ActionService) {}
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ export class SeriesCardComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.data.pagesRead = 0;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
||||
this.dataChanged.emit(series);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import { debounceTime, filter, map, Subject, takeUntil } from 'rxjs';
|
||||
import { FilterQueryParam } from 'src/app/shared/_services/filter-utilities.service';
|
||||
import { UtilityService } from 'src/app/shared/_services/utility.service';
|
||||
|
|
@ -11,6 +22,7 @@ import { AccountService } from 'src/app/_services/account.service';
|
|||
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
|
||||
import { MetadataService } from 'src/app/_services/metadata.service';
|
||||
import { ReaderService } from 'src/app/_services/reader.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
@Component({
|
||||
selector: 'app-series-info-cards',
|
||||
|
|
@ -18,10 +30,10 @@ import { ReaderService } from 'src/app/_services/reader.service';
|
|||
styleUrls: ['./series-info-cards.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SeriesInfoCardsComponent implements OnInit, OnChanges, OnDestroy {
|
||||
export class SeriesInfoCardsComponent implements OnInit, OnChanges {
|
||||
|
||||
@Input() series!: Series;
|
||||
@Input() seriesMetadata!: SeriesMetadata;
|
||||
@Input({required: true}) series!: Series;
|
||||
@Input({required: true}) seriesMetadata!: SeriesMetadata;
|
||||
@Input() hasReadingProgress: boolean = false;
|
||||
@Input() readingTimeLeft: HourEstimateRange | undefined;
|
||||
/**
|
||||
|
|
@ -31,8 +43,7 @@ export class SeriesInfoCardsComponent implements OnInit, OnChanges, OnDestroy {
|
|||
@Output() goTo: EventEmitter<{queryParamName: FilterQueryParam, filter: any}> = new EventEmitter();
|
||||
|
||||
readingTime: HourEstimateRange = {avgHours: 0, maxHours: 0, minHours: 0};
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
get MangaFormat() {
|
||||
return MangaFormat;
|
||||
|
|
@ -42,16 +53,16 @@ export class SeriesInfoCardsComponent implements OnInit, OnChanges, OnDestroy {
|
|||
return FilterQueryParam;
|
||||
}
|
||||
|
||||
constructor(public utilityService: UtilityService, public metadataService: MetadataService,
|
||||
private readerService: ReaderService, private readonly cdRef: ChangeDetectorRef,
|
||||
constructor(public utilityService: UtilityService, public metadataService: MetadataService,
|
||||
private readerService: ReaderService, private readonly cdRef: ChangeDetectorRef,
|
||||
private messageHub: MessageHubService, private accountService: AccountService) {
|
||||
// Listen for progress events and re-calculate getTimeLeft
|
||||
this.messageHub.messages$.pipe(filter(event => event.event === EVENTS.UserProgressUpdate),
|
||||
map(evt => evt.payload as UserProgressUpdateEvent),
|
||||
debounceTime(500),
|
||||
takeUntil(this.onDestroy))
|
||||
takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(updateEvent => {
|
||||
this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {
|
||||
this.accountService.currentUser$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(user => {
|
||||
if (user === undefined || user.username !== updateEvent.username) return;
|
||||
if (updateEvent.seriesId !== this.series.id) return;
|
||||
this.getReadingTimeLeft();
|
||||
|
|
@ -73,10 +84,6 @@ export class SeriesInfoCardsComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
handleGoTo(queryParamName: FilterQueryParam, filter: any) {
|
||||
this.goTo.emit({queryParamName, filter});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue