Misc Fixes (#2155)

* Fixed default token key not being long enough and Kavita auto-generating

* When scheduling nightly backup job, make it run at 2am to ensure everything else has ran.

* Made the overlay system work better on mobile. In order to do this, had to implement my own copy button.

* Tweaked the code to ensure we clear the selection doing anything and clicking off the overlay clears more reliably.

* Cleaned up the overlay code

* Added the ability to view the series that a rating is representing. Requires Kavita+ deployment.

* When calculating overall average rating of server, if only review is yours, don't include it.

When calculating overall average rating of server, scale to percentage (* 20) to match all other rating scales.

* Fixed side nav on mobile without donate link not fully covering the height of the screen

* Only trigger the task conversion warning on Media screen if you've touched the appropriate control.

* Fixed a bug where bookmark directory wasn't able to be changed.

* Fixed a bug where see More wouldn't show if there were just characters due to missing that check.

* Fixed a typo in documentation

* If a chapter has a range 1-6 and is fully read, when calculating highest chapter for Scrobbling, use the 6.
This commit is contained in:
Joe Milazzo 2023-07-23 11:53:16 -05:00 committed by GitHub
parent 9e04276dfd
commit 52d19642f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 121 additions and 52 deletions

View file

@ -5,10 +5,25 @@
<ng-container [ngSwitch]="mode">
<ng-container *ngSwitchCase="BookLineOverlayMode.None">
<div class="row g-0">
<button class="btn btn-icon" (click)="switchMode(BookLineOverlayMode.Bookmark)">
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
<span class="visually-hidden">Create Bookmark</span>
</button>
<div class="col-auto">
<button class="btn btn-icon btn-sm" (click)="copy()">
<i class="fa-solid fa-copy" aria-hidden="true"></i>
<div>Copy</div>
</button>
</div>
<div class="col-auto">
<button class="btn btn-icon btn-sm" (click)="switchMode(BookLineOverlayMode.Bookmark)">
<i class="fa-solid fa-book-bookmark" aria-hidden="true"></i>
<div>Bookmark</div>
</button>
</div>
<div class="col-auto">
<button class="btn btn-icon btn-sm" (click)="reset()">
<i class="fa-solid fa-times-circle" aria-hidden="true"></i>
<span class="visually-hidden">Close</span>
</button>
</div>
</div>
</ng-container>
<ng-container *ngSwitchCase="BookLineOverlayMode.Bookmark">

View file

@ -8,12 +8,13 @@ import {
OnInit, Output,
} from '@angular/core';
import {CommonModule} from '@angular/common';
import {fromEvent, of} from "rxjs";
import {fromEvent, merge, of} from "rxjs";
import {catchError, filter, tap} from "rxjs/operators";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import getBoundingClientRect from "@popperjs/core/lib/dom-utils/getBoundingClientRect";
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
import {ReaderService} from "../../../_services/reader.service";
import {ToastrService} from "ngx-toastr";
enum BookLineOverlayMode {
None = 0,
@ -39,6 +40,7 @@ export class BookLineOverlayComponent implements OnInit {
xPath: string = '';
selectedText: string = '';
previousSelection: string = '';
overlayPosition: { top: number; left: number } = { top: 0, left: 0 };
mode: BookLineOverlayMode = BookLineOverlayMode.None;
bookmarkForm: FormGroup = new FormGroup({
@ -50,47 +52,56 @@ export class BookLineOverlayComponent implements OnInit {
private readonly readerService = inject(ReaderService);
get BookLineOverlayMode() { return BookLineOverlayMode; }
constructor(private elementRef: ElementRef) {}
constructor(private elementRef: ElementRef, private toastr: ToastrService) {}
ngOnInit() {
if (this.parent) {
fromEvent<MouseEvent>(this.parent.nativeElement, 'mouseup')
.pipe(takeUntilDestroyed(this.destroyRef),
tap((event: MouseEvent) => {
const selection = window.getSelection();
if (!event.target) return;
if (this.mode !== BookLineOverlayMode.None && (!selection || selection.toString().trim() === '')) {
this.reset();
return;
}
const mouseUp$ = fromEvent<MouseEvent>(this.parent.nativeElement, 'mouseup');
const touchEnd$ = fromEvent<TouchEvent>(this.parent.nativeElement, 'touchend');
this.selectedText = selection ? selection.toString().trim() : '';
if (this.selectedText.length > 0 && this.mode === BookLineOverlayMode.None) {
// Get x,y coord so we can position overlay
if (event.target) {
const range = selection!.getRangeAt(0)
const rect = range.getBoundingClientRect();
const box = getBoundingClientRect(event.target as Element);
this.xPath = this.readerService.getXPathTo(event.target);
if (this.xPath !== '') {
this.xPath = '//' + this.xPath;
}
this.overlayPosition = {
top: rect.top + window.scrollY - 64 - rect.height, // 64px is the top menu area
left: rect.left + window.scrollX + 30 // Adjust 10 to center the overlay box horizontally
};
}
}
this.cdRef.markForCheck();
}))
.subscribe();
merge(mouseUp$, touchEnd$)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((event: MouseEvent | TouchEvent) => {
this.handleEvent(event);
});
}
}
handleEvent(event: MouseEvent | TouchEvent) {
const selection = window.getSelection();
if (!event.target) return;
if ((!selection || selection.toString().trim() === '' || selection.toString().trim() === this.selectedText)) {
this.reset();
return;
}
this.selectedText = selection ? selection.toString().trim() : '';
if (this.selectedText.length > 0 && this.mode === BookLineOverlayMode.None) {
// Get x,y coord so we can position overlay
if (event.target) {
const range = selection!.getRangeAt(0)
const rect = range.getBoundingClientRect();
const box = getBoundingClientRect(event.target as Element);
this.xPath = this.readerService.getXPathTo(event.target);
if (this.xPath !== '') {
this.xPath = '//' + this.xPath;
}
this.overlayPosition = {
top: rect.top + window.scrollY - 64 - rect.height, // 64px is the top menu area
left: rect.left + window.scrollX + 30 // Adjust 10 to center the overlay box horizontally
};
event.preventDefault();
event.stopPropagation();
}
}
this.cdRef.markForCheck();
}
switchMode(mode: BookLineOverlayMode) {
this.mode = mode;
this.cdRef.markForCheck();
@ -122,7 +133,21 @@ export class BookLineOverlayComponent implements OnInit {
this.mode = BookLineOverlayMode.None;
this.xPath = '';
this.selectedText = '';
const selection = window.getSelection();
if (selection) {
selection.removeAllRanges();
}
this.cdRef.markForCheck();
}
async copy() {
const selection = window.getSelection();
if (selection) {
await navigator.clipboard.writeText(selection.toString());
this.toastr.info('Copied to clipboard');
}
this.reset();
}
}