296 lines
12 KiB
TypeScript
296 lines
12 KiB
TypeScript
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, OnInit} from '@angular/core';
|
|
import {ReadingProfileService} from "../../_services/reading-profile.service";
|
|
import {
|
|
bookLayoutModes, bookWritingStyles, layoutModes,
|
|
pageSplitOptions, pdfScrollModes,
|
|
pdfSpreadModes, pdfThemes,
|
|
readingDirections, readingModes,
|
|
ReadingProfile, scalingOptions
|
|
} from "../../_models/preferences/reading-profiles";
|
|
import {translate, TranslocoDirective} from "@jsverse/transloco";
|
|
import {NgStyle, NgTemplateOutlet, TitleCasePipe} from "@angular/common";
|
|
import {VirtualScrollerModule} from "@iharbeck/ngx-virtual-scroller";
|
|
import {User} from "../../_models/user";
|
|
import {AccountService} from "../../_services/account.service";
|
|
import {debounceTime, distinctUntilChanged, take, tap} from "rxjs/operators";
|
|
import {SentenceCasePipe} from "../../_pipes/sentence-case.pipe";
|
|
import {FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms";
|
|
import {BookService} from "../../book-reader/_services/book.service";
|
|
import {BookPageLayoutMode} from "../../_models/readers/book-page-layout-mode";
|
|
import {PdfTheme} from "../../_models/preferences/pdf-theme";
|
|
import {PdfScrollMode} from "../../_models/preferences/pdf-scroll-mode";
|
|
import {PdfSpreadMode} from "../../_models/preferences/pdf-spread-mode";
|
|
import {bookColorThemes} from "../../book-reader/_components/reader-settings/reader-settings.component";
|
|
import {BookPageLayoutModePipe} from "../../_pipes/book-page-layout-mode.pipe";
|
|
import {LayoutModePipe} from "../../_pipes/layout-mode.pipe";
|
|
import {PageSplitOptionPipe} from "../../_pipes/page-split-option.pipe";
|
|
import {PdfScrollModePipe} from "../../_pipes/pdf-scroll-mode.pipe";
|
|
import {PdfSpreadModePipe} from "../../_pipes/pdf-spread-mode.pipe";
|
|
import {PdfThemePipe} from "../../_pipes/pdf-theme.pipe";
|
|
import {ReaderModePipe} from "../../_pipes/reading-mode.pipe";
|
|
import {ReadingDirectionPipe} from "../../_pipes/reading-direction.pipe";
|
|
import {ScalingOptionPipe} from "../../_pipes/scaling-option.pipe";
|
|
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
|
|
import {SettingSwitchComponent} from "../../settings/_components/setting-switch/setting-switch.component";
|
|
import {WritingStylePipe} from "../../_pipes/writing-style.pipe";
|
|
import {ColorPickerDirective} from "ngx-color-picker";
|
|
import {
|
|
NgbNav,
|
|
NgbNavItem,
|
|
NgbNavLinkBase,
|
|
NgbNavContent,
|
|
NgbNavOutlet
|
|
} from "@ng-bootstrap/ng-bootstrap";
|
|
import {filter} from "rxjs";
|
|
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|
import {LoadingComponent} from "../../shared/loading/loading.component";
|
|
import {ReadingProfileLibrarySelectionComponent} from "./_components/library-selection/reading-profile-library-selection.component";
|
|
|
|
enum TabId {
|
|
ImageReader = "image-reader",
|
|
BookReader = "book-reader",
|
|
PdfReader = "pdf-reader",
|
|
Series = "series",
|
|
Libraries = "libraries",
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-manage-reading-profiles',
|
|
imports: [
|
|
TranslocoDirective,
|
|
NgTemplateOutlet,
|
|
VirtualScrollerModule,
|
|
SentenceCasePipe,
|
|
BookPageLayoutModePipe,
|
|
FormsModule,
|
|
LayoutModePipe,
|
|
PageSplitOptionPipe,
|
|
PdfScrollModePipe,
|
|
PdfSpreadModePipe,
|
|
PdfThemePipe,
|
|
ReactiveFormsModule,
|
|
ReaderModePipe,
|
|
ReadingDirectionPipe,
|
|
ScalingOptionPipe,
|
|
SettingItemComponent,
|
|
SettingSwitchComponent,
|
|
TitleCasePipe,
|
|
WritingStylePipe,
|
|
NgStyle,
|
|
ColorPickerDirective,
|
|
NgbNav,
|
|
NgbNavItem,
|
|
NgbNavLinkBase,
|
|
NgbNavContent,
|
|
NgbNavOutlet,
|
|
LoadingComponent,
|
|
ReadingProfileLibrarySelectionComponent
|
|
],
|
|
templateUrl: './manage-reading-profiles.component.html',
|
|
styleUrl: './manage-reading-profiles.component.scss',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class ManageReadingProfilesComponent implements OnInit {
|
|
|
|
virtualScrollerBreakPoint = 20;
|
|
|
|
fontFamilies: Array<string> = [];
|
|
readingProfiles: ReadingProfile[] = [];
|
|
user!: User;
|
|
activeTabId = TabId.ImageReader;
|
|
loading = true;
|
|
|
|
selectedProfile: ReadingProfile | null = null;
|
|
readingProfileForm: FormGroup | null = null;
|
|
bookColorThemesTranslated = bookColorThemes.map(o => {
|
|
const d = {...o};
|
|
d.name = translate('theme.' + d.translationKey);
|
|
return d;
|
|
});
|
|
|
|
constructor(
|
|
private readingProfileService: ReadingProfileService,
|
|
private cdRef: ChangeDetectorRef,
|
|
private accountService: AccountService,
|
|
private bookService: BookService,
|
|
private destroyRef: DestroyRef,
|
|
) {
|
|
this.fontFamilies = this.bookService.getFontFamilies().map(f => f.title);
|
|
this.cdRef.markForCheck();
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
|
if (user) {
|
|
this.user = user;
|
|
console.log(this.user.preferences.defaultReadingProfileId);
|
|
}
|
|
});
|
|
|
|
this.readingProfileService.all().subscribe(profiles => {
|
|
this.readingProfiles = profiles;
|
|
this.loading = false;
|
|
this.setupForm();
|
|
this.cdRef.markForCheck();
|
|
});
|
|
|
|
}
|
|
|
|
delete(id: number) {
|
|
this.readingProfileService.delete(id).subscribe(() => {
|
|
this.selectProfile(undefined);
|
|
this.readingProfiles = this.readingProfiles.filter(o => o.id !== id);
|
|
this.cdRef.markForCheck();
|
|
});
|
|
}
|
|
|
|
setDefault(id: number) {
|
|
this.readingProfileService.setDefault(id).subscribe(() => {
|
|
this.user.preferences.defaultReadingProfileId = id;
|
|
this.cdRef.markForCheck();
|
|
})
|
|
}
|
|
|
|
get widthOverwriteLabel() {
|
|
const rawVal = this.readingProfileForm?.get('widthOverride')!.value;
|
|
if (!rawVal) {
|
|
return translate('off');
|
|
}
|
|
|
|
const val = parseInt(rawVal);
|
|
return (val <= 0) ? '' : val + '%'
|
|
}
|
|
|
|
setupForm() {
|
|
if (this.selectedProfile == null) {
|
|
return;
|
|
}
|
|
|
|
|
|
this.readingProfileForm = new FormGroup({})
|
|
|
|
if (this.fontFamilies.indexOf(this.selectedProfile.bookReaderFontFamily) < 0) {
|
|
this.selectedProfile.bookReaderFontFamily = 'default';
|
|
}
|
|
|
|
this.readingProfileForm.addControl('name', new FormControl(this.selectedProfile.name, Validators.required));
|
|
|
|
|
|
// Image reader
|
|
this.readingProfileForm.addControl('readingDirection', new FormControl(this.selectedProfile.readingDirection, []));
|
|
this.readingProfileForm.addControl('scalingOption', new FormControl(this.selectedProfile.scalingOption, []));
|
|
this.readingProfileForm.addControl('pageSplitOption', new FormControl(this.selectedProfile.pageSplitOption, []));
|
|
this.readingProfileForm.addControl('autoCloseMenu', new FormControl(this.selectedProfile.autoCloseMenu, []));
|
|
this.readingProfileForm.addControl('showScreenHints', new FormControl(this.selectedProfile.showScreenHints, []));
|
|
this.readingProfileForm.addControl('readerMode', new FormControl(this.selectedProfile.readerMode, []));
|
|
this.readingProfileForm.addControl('layoutMode', new FormControl(this.selectedProfile.layoutMode, []));
|
|
this.readingProfileForm.addControl('emulateBook', new FormControl(this.selectedProfile.emulateBook, []));
|
|
this.readingProfileForm.addControl('swipeToPaginate', new FormControl(this.selectedProfile.swipeToPaginate, []));
|
|
this.readingProfileForm.addControl('backgroundColor', new FormControl(this.selectedProfile.backgroundColor, []));
|
|
this.readingProfileForm.addControl('allowAutomaticWebtoonReaderDetection', new FormControl(this.selectedProfile.allowAutomaticWebtoonReaderDetection, []));
|
|
this.readingProfileForm.addControl('widthOverride', new FormControl(this.selectedProfile.widthOverride, [Validators.min(0), Validators.max(100)]));
|
|
|
|
// Epub reader
|
|
this.readingProfileForm.addControl('bookReaderFontFamily', new FormControl(this.selectedProfile.bookReaderFontFamily, []));
|
|
this.readingProfileForm.addControl('bookReaderFontSize', new FormControl(this.selectedProfile.bookReaderFontSize, []));
|
|
this.readingProfileForm.addControl('bookReaderLineSpacing', new FormControl(this.selectedProfile.bookReaderLineSpacing, []));
|
|
this.readingProfileForm.addControl('bookReaderMargin', new FormControl(this.selectedProfile.bookReaderMargin, []));
|
|
this.readingProfileForm.addControl('bookReaderReadingDirection', new FormControl(this.selectedProfile.bookReaderReadingDirection, []));
|
|
this.readingProfileForm.addControl('bookReaderWritingStyle', new FormControl(this.selectedProfile.bookReaderWritingStyle, []))
|
|
this.readingProfileForm.addControl('bookReaderTapToPaginate', new FormControl(this.selectedProfile.bookReaderTapToPaginate, []));
|
|
this.readingProfileForm.addControl('bookReaderLayoutMode', new FormControl(this.selectedProfile.bookReaderLayoutMode || BookPageLayoutMode.Default, []));
|
|
this.readingProfileForm.addControl('bookReaderThemeName', new FormControl(this.selectedProfile.bookReaderThemeName || bookColorThemes[0].name, []));
|
|
this.readingProfileForm.addControl('bookReaderImmersiveMode', new FormControl(this.selectedProfile.bookReaderImmersiveMode, []));
|
|
|
|
// Pdf reader
|
|
this.readingProfileForm.addControl('pdfTheme', new FormControl(this.selectedProfile.pdfTheme || PdfTheme.Dark, []));
|
|
this.readingProfileForm.addControl('pdfScrollMode', new FormControl(this.selectedProfile.pdfScrollMode || PdfScrollMode.Vertical, []));
|
|
this.readingProfileForm.addControl('pdfSpreadMode', new FormControl(this.selectedProfile.pdfSpreadMode || PdfSpreadMode.None, []));
|
|
|
|
// Auto save
|
|
this.readingProfileForm.valueChanges.pipe(
|
|
debounceTime(500),
|
|
distinctUntilChanged(),
|
|
filter(_ => this.readingProfileForm!.valid),
|
|
takeUntilDestroyed(this.destroyRef),
|
|
tap(_ => {
|
|
if (this.selectedProfile!.id == 0) {
|
|
this.readingProfileService.createProfile(this.packData()).subscribe({
|
|
next: createdProfile => {
|
|
this.selectedProfile = createdProfile;
|
|
this.readingProfiles.push(createdProfile);
|
|
this.cdRef.markForCheck();
|
|
},
|
|
error: err => {
|
|
console.log(err);
|
|
}
|
|
})
|
|
} else {
|
|
const profile = this.packData();
|
|
this.readingProfileService.updateProfile(profile).subscribe({
|
|
next: _ => {
|
|
this.readingProfiles = this.readingProfiles.map(p => {
|
|
if (p.id !== profile.id) return p;
|
|
return profile;
|
|
});
|
|
this.cdRef.markForCheck();
|
|
},
|
|
error: err => {
|
|
console.log(err);
|
|
}
|
|
})
|
|
}
|
|
}),
|
|
).subscribe();
|
|
}
|
|
|
|
private packData(): ReadingProfile {
|
|
const data: ReadingProfile = this.readingProfileForm!.getRawValue();
|
|
data.id = this.selectedProfile!.id;
|
|
return data;
|
|
}
|
|
|
|
handleBackgroundColorChange(color: string) {
|
|
if (!this.readingProfileForm || !this.selectedProfile) return;
|
|
|
|
this.readingProfileForm.markAsDirty();
|
|
this.readingProfileForm.markAsTouched();
|
|
this.selectedProfile.backgroundColor = color;
|
|
this.readingProfileForm.get('backgroundColor')?.setValue(color);
|
|
this.cdRef.markForCheck();
|
|
}
|
|
|
|
selectProfile(profile: ReadingProfile | undefined | null) {
|
|
if (profile === undefined) {
|
|
this.selectedProfile = null;
|
|
this.cdRef.markForCheck();
|
|
return;
|
|
}
|
|
|
|
this.selectedProfile = profile;
|
|
this.setupForm();
|
|
this.cdRef.markForCheck();
|
|
}
|
|
|
|
addNew() {
|
|
const defaultProfile = this.readingProfiles.find(f => f.id === this.user.preferences.defaultReadingProfileId);
|
|
this.selectedProfile = {...defaultProfile!};
|
|
this.selectedProfile.id = 0;
|
|
this.selectedProfile.name = "New Profile #" + (this.readingProfiles.length + 1);
|
|
this.setupForm();
|
|
this.cdRef.markForCheck();
|
|
}
|
|
|
|
protected readonly readingDirections = readingDirections;
|
|
protected readonly pdfSpreadModes = pdfSpreadModes;
|
|
protected readonly pageSplitOptions = pageSplitOptions;
|
|
protected readonly bookLayoutModes = bookLayoutModes;
|
|
protected readonly pdfThemes = pdfThemes;
|
|
protected readonly scalingOptions = scalingOptions;
|
|
protected readonly layoutModes = layoutModes;
|
|
protected readonly readerModes = readingModes;
|
|
protected readonly bookWritingStyles = bookWritingStyles;
|
|
protected readonly pdfScrollModes = pdfScrollModes;
|
|
|
|
protected readonly TabId = TabId;
|
|
}
|