Manga Reader Refresh (#1137)

* Refactored manga reader to use a regular image element for all cases except for split page rendering

* Fixed a weird issue where ordering of routes broke redireciton in one case.

* Added comments to a lot of the enums and refactored READER_MODE to be ReaderMode and much more clearer on function.

* Added bookmark effect on image renderer

* Implemented keyboard shortcut modal

* Introduced the new layout mode into the manga reader, updated preferences, and updated bookmark to work for said functionality. Need to implement renderer now

* Hooked in ability to show double pages but all the css is broken. Committing for help from Robbie.

* Fixed an issue where Language tag in metadata edit wasn't being updated

* Fixed up some styling on mobile for edit series detail

* Some css fixes

* Hooked in ability to set background color on reader (not implemented in reader). Optimized some code in ArchiveService to avoid extra memory allocations.

* Hooked in background color, generated the migration

* Fixed a bug when paging to cover images, full height would be used instead of full-width for cover images

* New option in reader to show screen hints (on by default). You can disable in user preferences which will stop showing pagination overlay hints

* Lots of fixes for double rendering mode

* Bumped the amount of cached pages to 8

* Fixed an issue where dropdowns weren't being locked on form manipulation
This commit is contained in:
Joseph Milazzo 2022-03-07 11:35:27 -06:00 committed by GitHub
parent 3dedbb1465
commit 2a4d0d1cd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 3607 additions and 226 deletions

View file

@ -94,14 +94,49 @@
</select>
</div>
</div>
<div class="row g-0">
<div class="col-md-6 col-sm-12 pe-2 mb-2">
<label for="settings-layoutmode-option" class="form-label">Layout Mode</label>&nbsp;<i class="fa fa-info-circle" aria-hidden="true" placement="right" [ngbTooltip]="layoutModeTooltip" role="button" tabindex="0"></i>
<ng-template #layoutModeTooltip>Render a single image to the screen to two side-by-side images</ng-template>
<span class="visually-hidden" id="settings-layoutmode-option-help"><ng-container [ngTemplateOutlet]="layoutModeTooltip"></ng-container></span>
<select class="form-select" aria-describedby="manga-header" formControlName="layoutMode" id="settings-layoutmode-option">
<option *ngFor="let opt of layoutModes" [value]="opt.value">{{opt.text | titlecase}}</option>
</select>
</div>
<div class="col-md-6 col-sm-12 pe-2 mb-2">
<label for="settings-backgroundcolor-option" class="form-label">Background Color</label>
<input [value]="user.preferences.backgroundColor"
class="form-control"
(colorPickerChange)="settingsForm.markAsTouched()"
[style.background]="user.preferences.backgroundColor"
[cpAlphaChannel]="'disabled'"
[(colorPicker)]="user.preferences.backgroundColor"/>
</div>
</div>
<div class="mb-3">
<label id="auto-close-label" class="form-label"></label>
<div class="mb-3">
<div class="form-check form-switch">
<input type="checkbox" id="auto-close" formControlName="autoCloseMenu" class="form-check-input" [value]="true" aria-labelledby="auto-close-label">
<label class="form-check-label" for="auto-close">Auto Close Menu</label>
<div class="row g-0">
<div class="col-md-6 col-sm-12 pe-2 mb-2">
<div class="mb-3">
<label id="auto-close-label" class="form-label"></label>
<div class="mb-3">
<div class="form-check form-switch">
<input type="checkbox" id="auto-close" formControlName="autoCloseMenu" class="form-check-input" [value]="true" aria-labelledby="auto-close-label">
<label class="form-check-label" for="auto-close">Auto Close Menu</label>
</div>
</div>
</div>
</div>
<div class="col-md-6 col-sm-12 pe-2 mb-2">
<div class="mb-3">
<label id="show-screen-hints-label" class="form-label"></label>
<div class="mb-3">
<div class="form-check form-switch">
<input type="checkbox" id="show-screen-hints" formControlName="showScreenHints" class="form-check-input" [value]="true" aria-labelledby="auto-close-label">
<label class="form-check-label" for="show-screen-hints">Show Screen Hints</label>
</div>
</div>
</div>
</div>
</div>

View file

@ -5,12 +5,13 @@ import { take } from 'rxjs/operators';
import { Options } from '@angular-slider/ngx-slider';
import { Title } from '@angular/platform-browser';
import { BookService } from 'src/app/book-reader/book.service';
import { readingDirections, scalingOptions, pageSplitOptions, readingModes, Preferences } from 'src/app/_models/preferences/preferences';
import { readingDirections, scalingOptions, pageSplitOptions, readingModes, Preferences, layoutModes } from 'src/app/_models/preferences/preferences';
import { User } from 'src/app/_models/user';
import { AccountService } from 'src/app/_services/account.service';
import { NavService } from 'src/app/_services/nav.service';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { SettingsService } from 'src/app/admin/settings.service';
import { forkJoin } from 'rxjs';
@Component({
selector: 'app-user-preferences',
@ -23,6 +24,7 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
scalingOptions = scalingOptions;
pageSplitOptions = pageSplitOptions;
readingModes = readingModes;
layoutModes = layoutModes;
settingsForm: FormGroup = new FormGroup({});
passwordChangeForm: FormGroup = new FormGroup({});
@ -63,8 +65,11 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
opdsEnabled: boolean = false;
makeUrl: (val: string) => string = (val: string) => {return this.transformKeyToOpdsUrl(val)};
backgroundColor: any; // TODO: Hook into user pref
constructor(private accountService: AccountService, private toastr: ToastrService, private bookService: BookService,
private navService: NavService, private titleService: Title, private route: ActivatedRoute, private settingsService: SettingsService) {
private navService: NavService, private titleService: Title, private route: ActivatedRoute, private settingsService: SettingsService,
private router: Router) {
this.fontFamilies = this.bookService.getFontFamilies();
this.route.fragment.subscribe(frag => {
@ -83,31 +88,41 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.titleService.setTitle('Kavita - User Preferences');
this.accountService.currentUser$.pipe(take(1)).subscribe((user) => {
if (user) {
this.user = user;
this.isAdmin = this.accountService.hasAdminRole(user);
this.hasChangePasswordRole = this.accountService.hasChangePasswordRole(user);
if (this.fontFamilies.indexOf(this.user.preferences.bookReaderFontFamily) < 0) {
this.user.preferences.bookReaderFontFamily = 'default';
}
this.settingsForm.addControl('readingDirection', new FormControl(user.preferences.readingDirection, []));
this.settingsForm.addControl('scalingOption', new FormControl(user.preferences.scalingOption, []));
this.settingsForm.addControl('pageSplitOption', new FormControl(user.preferences.pageSplitOption, []));
this.settingsForm.addControl('autoCloseMenu', new FormControl(user.preferences.autoCloseMenu, []));
this.settingsForm.addControl('readerMode', new FormControl(user.preferences.readerMode, []));
this.settingsForm.addControl('bookReaderDarkMode', new FormControl(user.preferences.bookReaderDarkMode, []));
this.settingsForm.addControl('bookReaderFontFamily', new FormControl(user.preferences.bookReaderFontFamily, []));
this.settingsForm.addControl('bookReaderFontSize', new FormControl(user.preferences.bookReaderFontSize, []));
this.settingsForm.addControl('bookReaderLineSpacing', new FormControl(user.preferences.bookReaderLineSpacing, []));
this.settingsForm.addControl('bookReaderMargin', new FormControl(user.preferences.bookReaderMargin, []));
this.settingsForm.addControl('bookReaderReadingDirection', new FormControl(user.preferences.bookReaderReadingDirection, []));
this.settingsForm.addControl('bookReaderTapToPaginate', new FormControl(!!user.preferences.bookReaderTapToPaginate, []));
this.settingsForm.addControl('theme', new FormControl(user.preferences.theme, []));
forkJoin({
user: this.accountService.currentUser$.pipe(take(1)),
pref: this.accountService.getPreferences()
}).subscribe(results => {
if (results.user === undefined) {
this.router.navigateByUrl('/login');
return;
}
this.user = results.user;
this.user.preferences = results.pref;
this.isAdmin = this.accountService.hasAdminRole(results.user);
this.hasChangePasswordRole = this.accountService.hasChangePasswordRole(results.user);
if (this.fontFamilies.indexOf(this.user.preferences.bookReaderFontFamily) < 0) {
this.user.preferences.bookReaderFontFamily = 'default';
}
this.settingsForm.addControl('readingDirection', new FormControl(this.user.preferences.readingDirection, []));
this.settingsForm.addControl('scalingOption', new FormControl(this.user.preferences.scalingOption, []));
this.settingsForm.addControl('pageSplitOption', new FormControl(this.user.preferences.pageSplitOption, []));
this.settingsForm.addControl('autoCloseMenu', new FormControl(this.user.preferences.autoCloseMenu, []));
this.settingsForm.addControl('showScreenHints', new FormControl(this.user.preferences.showScreenHints, []));
this.settingsForm.addControl('readerMode', new FormControl(this.user.preferences.readerMode, []));
this.settingsForm.addControl('layoutMode', new FormControl(this.user.preferences.layoutMode, []));
this.settingsForm.addControl('bookReaderDarkMode', new FormControl(this.user.preferences.bookReaderDarkMode, []));
this.settingsForm.addControl('bookReaderFontFamily', new FormControl(this.user.preferences.bookReaderFontFamily, []));
this.settingsForm.addControl('bookReaderFontSize', new FormControl(this.user.preferences.bookReaderFontSize, []));
this.settingsForm.addControl('bookReaderLineSpacing', new FormControl(this.user.preferences.bookReaderLineSpacing, []));
this.settingsForm.addControl('bookReaderMargin', new FormControl(this.user.preferences.bookReaderMargin, []));
this.settingsForm.addControl('bookReaderReadingDirection', new FormControl(this.user.preferences.bookReaderReadingDirection, []));
this.settingsForm.addControl('bookReaderTapToPaginate', new FormControl(!!this.user.preferences.bookReaderTapToPaginate, []));
this.settingsForm.addControl('theme', new FormControl(this.user.preferences.theme, []));
});
this.passwordChangeForm.addControl('password', new FormControl('', [Validators.required]));
@ -131,7 +146,9 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
this.settingsForm.get('readingDirection')?.setValue(this.user.preferences.readingDirection);
this.settingsForm.get('scalingOption')?.setValue(this.user.preferences.scalingOption);
this.settingsForm.get('autoCloseMenu')?.setValue(this.user.preferences.autoCloseMenu);
this.settingsForm.get('showScreenHints')?.setValue(this.user.preferences.showScreenHints);
this.settingsForm.get('readerMode')?.setValue(this.user.preferences.readerMode);
this.settingsForm.get('layoutMode')?.setValue(this.user.preferences.layoutMode);
this.settingsForm.get('pageSplitOption')?.setValue(this.user.preferences.pageSplitOption);
this.settingsForm.get('bookReaderDarkMode')?.setValue(this.user.preferences.bookReaderDarkMode);
this.settingsForm.get('bookReaderFontFamily')?.setValue(this.user.preferences.bookReaderFontFamily);
@ -157,7 +174,10 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
scalingOption: parseInt(modelSettings.scalingOption, 10),
pageSplitOption: parseInt(modelSettings.pageSplitOption, 10),
autoCloseMenu: modelSettings.autoCloseMenu,
readerMode: parseInt(modelSettings.readerMode),
readerMode: parseInt(modelSettings.readerMode, 10),
layoutMode: parseInt(modelSettings.layoutMode, 10),
showScreenHints: modelSettings.showScreenHints,
backgroundColor: this.user.preferences.backgroundColor,
bookReaderDarkMode: modelSettings.bookReaderDarkMode,
bookReaderFontFamily: modelSettings.bookReaderFontFamily,
bookReaderLineSpacing: modelSettings.bookReaderLineSpacing,

View file

@ -10,7 +10,8 @@ import { ApiKeyComponent } from './api-key/api-key.component';
import { SharedModule } from '../shared/shared.module';
import { ThemeManagerComponent } from './theme-manager/theme-manager.component';
import { SiteThemeProviderPipe } from './_pipes/site-theme-provider.pipe';
import { PipeModule } from '../pipe/pipe.module';
import { ColorPickerModule } from 'ngx-color-picker';
@ -30,7 +31,9 @@ import { SiteThemeProviderPipe } from './_pipes/site-theme-provider.pipe';
NgbTooltipModule,
NgxSliderModule,
UserSettingsRoutingModule,
SharedModule // SentenceCase pipe
//SharedModule, // SentenceCase pipe
PipeModule,
ColorPickerModule, // User prefernces background color
],
exports: [
SiteThemeProviderPipe