Holiday Bugfixes (#1762)
* Don't show "not much going on" when we are actively downloading * Swipe to paginate is now behind a flag in the user preferences. * Added a new server setting for host name, if the server sits behind a reverse proxy. If this is set, email link generation will use it and will not perform any checks on accessibility (thus email will always send) * Refactored the code that checks if the server is accessible to check if host name is set, and thus return rue if so. * Added back the system drawing library for markdown parsing. * Fixed a validation error * Fixed a bug where folder watching could get re-triggered when it was disabled at a server level. * Made the manga reader loader absolute positioned for better visibility * Indentation
This commit is contained in:
parent
2a47029209
commit
5e9bbd0768
31 changed files with 1986 additions and 49 deletions
|
|
@ -19,6 +19,7 @@ export interface Preferences {
|
|||
backgroundColor: string;
|
||||
showScreenHints: boolean;
|
||||
emulateBook: boolean;
|
||||
swipeToPaginate: boolean;
|
||||
|
||||
// Book Reader
|
||||
bookReaderMargin: number;
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ export interface ServerSettings {
|
|||
totalBackups: number;
|
||||
totalLogs: number;
|
||||
enableFolderWatching: boolean;
|
||||
hostName: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="container-fluid">
|
||||
<form [formGroup]="settingsForm" *ngIf="serverSettings !== undefined">
|
||||
<p class="text-warning pt-2">Port and Swagger require a manual restart of Kavita to take effect.</p>
|
||||
<p class="text-warning pt-2">Changing Port requires a manual restart of Kavita to take effect.</p>
|
||||
<div class="mb-3">
|
||||
<label for="settings-cachedir" class="form-label">Cache Directory</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="cacheDirectoryTooltip" role="button" tabindex="0"></i>
|
||||
<ng-template #cacheDirectoryTooltip>Where the server place temporary files when reading. This will be cleaned up on a regular basis.</ng-template>
|
||||
|
|
@ -20,6 +20,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="settings-hostname" class="form-label">Host Name</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="hostNameTooltip" role="button" tabindex="0"></i>
|
||||
<ng-template #hostNameTooltip>Domain Name (of Reverse Proxy). If set, email generation will always use this.</ng-template>
|
||||
<span class="visually-hidden" id="settings-hostname-help">Domain Name (of Reverse Proxy). If set, email generation will always use this.</span>
|
||||
<input id="settings-hostname" aria-describedby="settings-hostname-help" class="form-control" formControlName="hostName" type="text"
|
||||
[class.is-invalid]="settingsForm.get('hostName')?.invalid && settingsForm.get('hostName')?.touched">
|
||||
<div id="hostname-validations" class="invalid-feedback" *ngIf="settingsForm.dirty || settingsForm.touched">
|
||||
<div *ngIf="settingsForm.get('hostName')?.errors?.pattern">
|
||||
Host name must start with http(s) and not end in /
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-0 mb-2">
|
||||
<div class="col-md-3 col-sm-12 pe-2">
|
||||
<label for="settings-port" class="form-label">Port</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="portTooltip" role="button" tabindex="0"></i>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ export class ManageSettingsComponent implements OnInit {
|
|||
this.settingsForm.addControl('totalLogs', new FormControl(this.serverSettings.totalLogs, [Validators.required, Validators.min(1), Validators.max(30)]));
|
||||
this.settingsForm.addControl('enableFolderWatching', new FormControl(this.serverSettings.enableFolderWatching, [Validators.required]));
|
||||
this.settingsForm.addControl('convertBookmarkToWebP', new FormControl(this.serverSettings.convertBookmarkToWebP, []));
|
||||
this.settingsForm.addControl('hostName', new FormControl(this.serverSettings.hostName, [Validators.pattern(/^(http:|https:)+[^\s]+[\w]$/)]));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +70,7 @@ export class ManageSettingsComponent implements OnInit {
|
|||
this.settingsForm.get('totalLogs')?.setValue(this.serverSettings.totalLogs);
|
||||
this.settingsForm.get('enableFolderWatching')?.setValue(this.serverSettings.enableFolderWatching);
|
||||
this.settingsForm.get('convertBookmarkToWebP')?.setValue(this.serverSettings.convertBookmarkToWebP);
|
||||
this.settingsForm.get('hostName')?.setValue(this.serverSettings.hostName);
|
||||
this.settingsForm.markAsPristine();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,14 +134,12 @@ export class ManageUsersComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
await this.confirmService.alert(
|
||||
'Please click this link to confirm your email. You must confirm to be able to login. You may need to log out of the current account before clicking. <br/> <a href="' + email + '" target="_blank" rel="noopener noreferrer">' + email + '</a>');
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setup(member: Member) {
|
||||
this.accountService.getInviteUrl(member.id, false).subscribe(url => {
|
||||
console.log('Invite Url: ', url);
|
||||
if (url) {
|
||||
this.router.navigateByUrl(url);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-loading [loading]="isLoading"></app-loading>
|
||||
<app-loading [loading]="isLoading" [absolute]="true"></app-loading>
|
||||
<div class="reading-area"
|
||||
ngSwipe (swipeEnd)="onSwipeEnd($event)" (swipeMove)="onSwipeMove($event)"
|
||||
[ngStyle]="{'background-color': backgroundColor, 'height': readerMode === ReaderMode.Webtoon ? 'inherit' : 'calc(var(--vh)*100)'}" #readingArea>
|
||||
|
|
@ -233,6 +233,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" id="swipe-to-paginate" formControlName="swipeToPaginate" class="form-check-input" >
|
||||
<label class="form-check-label" for="swipe-to-paginate">Swipe Enabled</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-12">
|
||||
<div class="mb-3">
|
||||
|
|
@ -251,8 +260,10 @@
|
|||
<input type="range" class="form-range" id="darkness"
|
||||
min="10" max="100" step="1" formControlName="darkness">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<button class="btn btn-primary" (click)="savePref()">Save to Preferences</button>
|
||||
<button class="btn btn-primary" (click)="savePref()">Save Globally</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -467,7 +467,8 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
fittingOption: new FormControl(this.mangaReaderService.translateScalingOption(this.scalingOption)),
|
||||
layoutMode: new FormControl(this.layoutMode),
|
||||
darkness: new FormControl(100),
|
||||
emulateBook: new FormControl(this.user.preferences.emulateBook)
|
||||
emulateBook: new FormControl(this.user.preferences.emulateBook),
|
||||
swipeToPaginate: new FormControl(this.user.preferences.swipeToPaginate)
|
||||
});
|
||||
|
||||
this.readerModeSubject.next(this.readerMode);
|
||||
|
|
@ -973,6 +974,8 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
|
||||
triggerSwipePagination(direction: KeyDirection) {
|
||||
if (!this.generalSettingsForm.get('swipeToPaginate')?.value) return;
|
||||
|
||||
switch(direction) {
|
||||
case KeyDirection.Down:
|
||||
this.nextPage();
|
||||
|
|
@ -1097,6 +1100,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
|
||||
this.resetSwipeModifiers();
|
||||
|
||||
this.isLoading = true;
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
this.pagingDirectionSubject.next(PAGING_DIRECTION.FORWARD);
|
||||
|
||||
|
|
@ -1125,6 +1131,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
this.resetSwipeModifiers();
|
||||
|
||||
this.isLoading = true;
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
this.pagingDirectionSubject.next(PAGING_DIRECTION.BACKWARDS);
|
||||
|
||||
|
||||
|
|
@ -1241,6 +1250,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
// Originally this was only for fit to height, but when swiping was introduced, it made more sense to do it always to reset to the same view
|
||||
this.readingArea.nativeElement.scroll(0,0);
|
||||
|
||||
this.isLoading = false;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
|
@ -1601,6 +1611,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
data.autoCloseMenu = this.autoCloseMenu;
|
||||
data.readingDirection = this.readingDirection;
|
||||
data.emulateBook = modelSettings.emulateBook;
|
||||
data.swipeToPaginate = modelSettings.swipeToPaginate;
|
||||
this.accountService.updatePreferences(data).subscribe((updatedPrefs) => {
|
||||
this.toastr.success('User preferences updated');
|
||||
if (this.user) {
|
||||
|
|
|
|||
|
|
@ -165,9 +165,13 @@
|
|||
<li class="list-group-item dark-menu-item" *ngIf="onlineUsers.length > 1">
|
||||
<div>{{onlineUsers.length}} Users online</div>
|
||||
</li>
|
||||
<li class="list-group-item dark-menu-item" *ngIf="activeEvents === 0 && onlineUsers.length <= 1">Not much going on here</li>
|
||||
<li class="list-group-item dark-menu-item" *ngIf="debugMode">Active Events: {{activeEvents}}</li>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="downloadService.activeDownloads$ | async as activeDownloads">
|
||||
<li class="list-group-item dark-menu-item" *ngIf="activeEvents === 0 && activeDownloads.length === 0">Not much going on here</li>
|
||||
</ng-container>
|
||||
|
||||
</ul>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
|
@ -55,7 +55,8 @@ export class EventsWidgetComponent implements OnInit, OnDestroy {
|
|||
|
||||
constructor(public messageHub: MessageHubService, private modalService: NgbModal,
|
||||
private accountService: AccountService, private confirmService: ConfirmService,
|
||||
private readonly cdRef: ChangeDetectorRef, public downloadService: DownloadService) { }
|
||||
private readonly cdRef: ChangeDetectorRef, public downloadService: DownloadService) {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.onDestroy.next();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export class TimeAgoPipe implements PipeTransform, OnDestroy {
|
|||
const seconds = Math.round(Math.abs((now.getTime() - d.getTime()) / 1000));
|
||||
const timeToUpdate = (Number.isNaN(seconds)) ? 1000 : this.getSecondsUntilUpdate(seconds) * 1000;
|
||||
|
||||
this.timer = this.ngZone.runOutsideAngular(() => {
|
||||
this.timer = this.ngZone.runOutsideAngular(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return window.setTimeout(() => {
|
||||
this.ngZone.run(() => this.changeDetectorRef.markForCheck());
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
<ng-container *ngIf="loading">
|
||||
<ng-container *ngIf="absolute; else relative">
|
||||
<div class="position-absolute top-50 start-50 translate-middle" style="z-index: 999">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #relative>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
|
@ -10,10 +10,15 @@ export class LoadingComponent implements OnInit {
|
|||
|
||||
@Input() loading: boolean = false;
|
||||
@Input() message: string = '';
|
||||
/**
|
||||
* Uses absolute positioning to ensure it loads over content
|
||||
*/
|
||||
@Input() absolute: boolean = false;
|
||||
|
||||
constructor(private readonly cdRef: ChangeDetectorRef) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('absolute: ', this.absolute);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,6 +179,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12 pe-2 mb-2">
|
||||
<div class="mb-3 mt-1">
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" id="swipe-to-paginate" role="switch" formControlName="swipeToPaginate" class="form-check-input" [value]="true">
|
||||
<label class="form-check-label me-1" for="swipe-to-paginate">Swipe to Paginate</label><i class="fa fa-info-circle" aria-hidden="true" placement="top" ngbTooltip="Should swiping on the screen cause the next or previous page to be triggered" role="button" tabindex="0"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
this.settingsForm.addControl('readerMode', new FormControl(this.user.preferences.readerMode, []));
|
||||
this.settingsForm.addControl('layoutMode', new FormControl(this.user.preferences.layoutMode, []));
|
||||
this.settingsForm.addControl('emulateBook', new FormControl(this.user.preferences.emulateBook, []));
|
||||
this.settingsForm.addControl('swipeToPaginate', new FormControl(this.user.preferences.swipeToPaginate, []));
|
||||
|
||||
this.settingsForm.addControl('bookReaderFontFamily', new FormControl(this.user.preferences.bookReaderFontFamily, []));
|
||||
this.settingsForm.addControl('bookReaderFontSize', new FormControl(this.user.preferences.bookReaderFontSize, []));
|
||||
|
|
@ -187,6 +188,7 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
this.settingsForm.get('promptForDownloadSize')?.setValue(this.user.preferences.promptForDownloadSize);
|
||||
this.settingsForm.get('noTransitions')?.setValue(this.user.preferences.noTransitions);
|
||||
this.settingsForm.get('emulateBook')?.setValue(this.user.preferences.emulateBook);
|
||||
this.settingsForm.get('swipeToPaginate')?.setValue(this.user.preferences.swipeToPaginate);
|
||||
this.cdRef.markForCheck();
|
||||
this.settingsForm.markAsPristine();
|
||||
}
|
||||
|
|
@ -217,7 +219,8 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
blurUnreadSummaries: modelSettings.blurUnreadSummaries,
|
||||
promptForDownloadSize: modelSettings.promptForDownloadSize,
|
||||
noTransitions: modelSettings.noTransitions,
|
||||
emulateBook: modelSettings.emulateBook
|
||||
emulateBook: modelSettings.emulateBook,
|
||||
swipeToPaginate: modelSettings.swipeToPaginate
|
||||
};
|
||||
|
||||
this.observableHandles.push(this.accountService.updatePreferences(data).subscribe((updatedPrefs) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue