Random Changes and Enhancements (#1819)
* When skipping over folders in a scan, inform the ui * Try out new backout condition for library watcher. * Tweaked the code for folder watching to be more intense on killing if stuck in inotify loop. * Streamlined my implementation of enhanced LibraryWatcher * Added new extension method to make complex where statements cleaner. * Added an implementation to flatten series and not show them if they have relationships defined. Only the parent would show. Currently disabled until i figure out how to apply it. * Added the ability to collapse series that are not the primary entry point to reading. Configurable in library settings, only applies when all libraries in a filter have the property to true. * Exclude from parsing .@_thumb directories, a QNAP system folder. Show number of items a JumpKey has * Refactored some time reading to display in days, months, years or minutes.
This commit is contained in:
parent
8a62d54c0b
commit
df68c50256
23 changed files with 2038 additions and 48 deletions
|
|
@ -16,4 +16,5 @@ export interface Library {
|
|||
includeInRecommended: boolean;
|
||||
includeInSearch: boolean;
|
||||
manageCollections: boolean;
|
||||
collapseSeriesRelationships: boolean;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<ng-template #jumpBar>
|
||||
<div class="jump-bar">
|
||||
<ng-container *ngFor="let jumpKey of jumpBarKeysToRender; let i = index;">
|
||||
<button class="btn btn-link" [ngClass]="{'disabled': hasCustomSort()}" (click)="scrollTo(jumpKey)">
|
||||
<button class="btn btn-link" [ngClass]="{'disabled': hasCustomSort()}" (click)="scrollTo(jumpKey)" [ngbTooltip]="jumpKey.size + ' Series'" placement="left">
|
||||
{{jumpKey.title}}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { SafeStylePipe } from './safe-style.pipe';
|
|||
import { DefaultDatePipe } from './default-date.pipe';
|
||||
import { BytesPipe } from './bytes.pipe';
|
||||
import { TimeAgoPipe } from './time-ago.pipe';
|
||||
import { TimeDurationPipe } from './time-duration.pipe';
|
||||
|
||||
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ import { TimeAgoPipe } from './time-ago.pipe';
|
|||
DefaultDatePipe,
|
||||
BytesPipe,
|
||||
TimeAgoPipe,
|
||||
TimeDurationPipe,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
|
@ -60,7 +62,8 @@ import { TimeAgoPipe } from './time-ago.pipe';
|
|||
SafeStylePipe,
|
||||
DefaultDatePipe,
|
||||
BytesPipe,
|
||||
TimeAgoPipe
|
||||
TimeAgoPipe,
|
||||
TimeDurationPipe
|
||||
]
|
||||
})
|
||||
export class PipeModule { }
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export class TimeAgoPipe implements PipeTransform, OnDestroy {
|
|||
|
||||
private timer: number | null = null;
|
||||
constructor(private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone) {}
|
||||
transform(value:string) {
|
||||
transform(value: string) {
|
||||
this.removeTimer();
|
||||
const d = new Date(value);
|
||||
const now = new Date();
|
||||
|
|
|
|||
26
UI/Web/src/app/pipe/time-duration.pipe.ts
Normal file
26
UI/Web/src/app/pipe/time-duration.pipe.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Converts hours -> days, months, years, etc
|
||||
*/
|
||||
@Pipe({
|
||||
name: 'timeDuration'
|
||||
})
|
||||
export class TimeDurationPipe implements PipeTransform {
|
||||
|
||||
transform(hours: number): string {
|
||||
if (hours === 0) return `${hours} hours`;
|
||||
if (hours < 1) {
|
||||
return `${(hours * 60).toFixed(1)} minutes`;
|
||||
} else if (hours < 24) {
|
||||
return `${hours} hours`;
|
||||
} else if (hours < 720) {
|
||||
return `${(hours / 24).toFixed(1)} days`;
|
||||
} else if (hours < 8760) {
|
||||
return `${(hours / 720).toFixed(1)} months`;
|
||||
} else {
|
||||
return `${(hours / 8760).toFixed(1)} years`;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -106,6 +106,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-sm-12 pe-2 mb-2">
|
||||
<div class="mb-3 mt-1">
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" id="collapse-relationships" role="switch" formControlName="collapseSeriesRelationships" class="form-check-input" aria-labelledby="auto-close-label">
|
||||
<label class="form-check-label" for="collapse-relationships">Collapse Series Relationships</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="accent">
|
||||
Experiemental: Should Kavita show Series that have no relationships or is the parent/prequel
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-sm-12 pe-2 mb-2">
|
||||
<div class="mb-3 mt-1">
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
|
|||
includeInRecommended: new FormControl<boolean>(true, { nonNullable: true, validators: [Validators.required] }),
|
||||
includeInSearch: new FormControl<boolean>(true, { nonNullable: true, validators: [Validators.required] }),
|
||||
manageCollections: new FormControl<boolean>(true, { nonNullable: true, validators: [Validators.required] }),
|
||||
collapseSeriesRelationships: new FormControl<boolean>(false, { nonNullable: true, validators: [Validators.required] }),
|
||||
});
|
||||
|
||||
selectedFolders: string[] = [];
|
||||
|
|
@ -119,6 +120,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy {
|
|||
this.libraryForm.get('includeInRecommended')?.setValue(this.library.includeInRecommended);
|
||||
this.libraryForm.get('includeInSearch')?.setValue(this.library.includeInSearch);
|
||||
this.libraryForm.get('manageCollections')?.setValue(this.library.manageCollections);
|
||||
this.libraryForm.get('collapseSeriesRelationships')?.setValue(this.library.collapseSeriesRelationships);
|
||||
this.selectedFolders = this.library.folders;
|
||||
this.madeChanges = false;
|
||||
this.cdRef.markForCheck();
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
<ng-container>
|
||||
<div class="col-auto mb-2">
|
||||
<app-icon-and-title label="Total Read Time" [clickable]="false" fontClasses="fas fa-eye" title="Total Read Time: {{stats.totalReadingTime | number}}">
|
||||
{{stats.totalReadingTime | compactNumber}} Hours
|
||||
{{stats.totalReadingTime | timeDuration}}
|
||||
</app-icon-and-title>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
<ng-container >
|
||||
<div class="col-auto mb-2">
|
||||
<app-icon-and-title label="Time Spent Reading" [clickable]="false" fontClasses="fas fa-eye" title="Time Spent Reading: {{timeSpentReading | number}}">
|
||||
{{timeSpentReading | compactNumber}} hours
|
||||
{{timeSpentReading | timeDuration}}
|
||||
</app-icon-and-title>
|
||||
</div>
|
||||
<div class="vr d-none d-lg-block m-2"></div>
|
||||
|
|
@ -28,8 +28,8 @@
|
|||
|
||||
<ng-container>
|
||||
<div class="col-auto mb-2">
|
||||
<app-icon-and-title label="Average Hours Read / Week" [clickable]="false" fontClasses="fas fa-eye" title="Average Hours Read / Week: {{avgHoursPerWeekSpentReading | number:'1.0-2'}}">
|
||||
{{avgHoursPerWeekSpentReading | compactNumber | number: '1.0-2'}} hours
|
||||
<app-icon-and-title label="Average Reading / Week" [clickable]="false" fontClasses="fas fa-eye">
|
||||
{{avgHoursPerWeekSpentReading | timeDuration}}
|
||||
</app-icon-and-title>
|
||||
</div>
|
||||
<div class="vr d-none d-lg-block m-2"></div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue