Polishing and Bugfixes (#613)

* Added a new field to Library for showing Last Scan time for a library.

Manage library page now shows last scan for each library. Tweaked the websocket code to make scan progress a bit more reliable.

* Updated docnet to provide ARM support from our recent PR. Pi users can now have a version for PDF support out of the box.

* Parser is now culture invariant to hopefully fix an issue on Italian systems not detecting . correctly

* Added the ability for the collection detail page to update when a new series is added.

* Fixed an issue where multiple chapters stacked in a volume and reading in incognito, wouldn't sort the chapters and would open the wrong one.

* Code smell
This commit is contained in:
Joseph Milazzo 2021-10-01 08:13:55 -07:00 committed by GitHub
parent 1ff1be2eb9
commit ce2f4b6a9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1267 additions and 160 deletions

View file

@ -0,0 +1,4 @@
export interface SeriesAddedToCollectionEvent {
tagId: number;
seriesId: number;
}

View file

@ -7,7 +7,7 @@ export enum LibraryType {
export interface Library {
id: number;
name: string;
coverImage: string;
lastScanned: string;
type: LibraryType;
folders: string[];
}

View file

@ -17,7 +17,8 @@ export enum EVENTS {
RefreshMetadata = 'RefreshMetadata',
SeriesAdded = 'SeriesAdded',
ScanLibraryProgress = 'ScanLibraryProgress',
OnlineUsers = 'OnlineUsers'
OnlineUsers = 'OnlineUsers',
SeriesAddedToCollection = 'SeriesAddedToCollection'
}
export interface Message<T> {
@ -85,6 +86,13 @@ export class MessageHubService {
this.scanLibrary.emit(resp.body);
});
this.hubConnection.on(EVENTS.SeriesAddedToCollection, resp => {
this.messagesSource.next({
event: EVENTS.SeriesAddedToCollection,
payload: resp.body
});
});
this.hubConnection.on(EVENTS.SeriesAdded, resp => {
this.messagesSource.next({
event: EVENTS.SeriesAdded,

View file

@ -20,6 +20,13 @@
</div>
<div>Type: {{libraryType(library.type)}}</div>
<div>Shared Folders: {{library.folders.length + ' folders'}}</div>
<div>
Last Scanned:
<span *ngIf="library.lastScanned == '0001-01-01T00:00:00'; else activeDate">Never</span>
<ng-template #activeDate>
{{library.lastScanned | date: 'MM/dd/yyyy'}}
</ng-template>
</div>
</li>
<li *ngIf="loading" class="list-group-item">
<div class="spinner-border text-secondary" role="status">

View file

@ -2,12 +2,12 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { take, takeUntil, takeWhile } from 'rxjs/operators';
import { ConfirmService } from 'src/app/shared/confirm.service';
import { ScanLibraryProgressEvent } from 'src/app/_models/events/scan-library-progress-event';
import { Library, LibraryType } from 'src/app/_models/library';
import { LibraryService } from 'src/app/_services/library.service';
import { MessageHubService } from 'src/app/_services/message-hub.service';
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
import { LibraryEditorModalComponent } from '../_modals/library-editor-modal/library-editor-modal.component';
@Component({
@ -35,9 +35,10 @@ export class ManageLibraryComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.getLibraries();
this.hubService.scanLibrary.subscribe((event: ScanLibraryProgressEvent) => {
this.scanInProgress[event.libraryId] = event.progress !== 100;
// when a progress event comes in, show it on the UI next to library
this.hubService.messages$.pipe(takeWhile(event => event.event === EVENTS.ScanLibraryProgress)).subscribe((event) => {
const scanEvent = event.payload as ScanLibraryProgressEvent;
this.scanInProgress[scanEvent.libraryId] = scanEvent.progress !== 100;
});
}

View file

@ -1,14 +1,16 @@
import { Component, HostListener, OnInit } from '@angular/core';
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, ActivatedRoute } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { take } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { debounceTime, take, takeUntil, takeWhile } from 'rxjs/operators';
import { BulkSelectionService } from 'src/app/cards/bulk-selection.service';
import { UpdateFilterEvent } from 'src/app/cards/card-detail-layout/card-detail-layout.component';
import { EditCollectionTagsComponent } from 'src/app/cards/_modals/edit-collection-tags/edit-collection-tags.component';
import { KEY_CODES } from 'src/app/shared/_services/utility.service';
import { CollectionTag } from 'src/app/_models/collection-tag';
import { SeriesAddedToCollectionEvent } from 'src/app/_models/events/series-added-to-collection-event';
import { Pagination } from 'src/app/_models/pagination';
import { Series } from 'src/app/_models/series';
import { FilterItem, mangaFormatFilters, SeriesFilter } from 'src/app/_models/series-filter';
@ -17,6 +19,7 @@ import { Action, ActionFactoryService, ActionItem } from 'src/app/_services/acti
import { ActionService } from 'src/app/_services/action.service';
import { CollectionTagService } from 'src/app/_services/collection-tag.service';
import { ImageService } from 'src/app/_services/image.service';
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
import { SeriesService } from 'src/app/_services/series.service';
@Component({
@ -24,7 +27,7 @@ import { SeriesService } from 'src/app/_services/series.service';
templateUrl: './collection-detail.component.html',
styleUrls: ['./collection-detail.component.scss']
})
export class CollectionDetailComponent implements OnInit {
export class CollectionDetailComponent implements OnInit, OnDestroy {
collectionTag!: CollectionTag;
tagImage: string = '';
@ -40,6 +43,8 @@ export class CollectionDetailComponent implements OnInit {
mangaFormat: null
};
private onDestory: Subject<void> = new Subject<void>();
bulkActionCallback = (action: Action, data: any) => {
const selectedSeriesIndexies = this.bulkSelectionService.getSelectedCardsForSource('series');
const selectedSeries = this.series.filter((series, index: number) => selectedSeriesIndexies.includes(index + ''));
@ -68,7 +73,7 @@ export class CollectionDetailComponent implements OnInit {
constructor(public imageService: ImageService, private collectionService: CollectionTagService, private router: Router, private route: ActivatedRoute,
private seriesService: SeriesService, private toastr: ToastrService, private actionFactoryService: ActionFactoryService,
private modalService: NgbModal, private titleService: Title, private accountService: AccountService,
public bulkSelectionService: BulkSelectionService, private actionService: ActionService) {
public bulkSelectionService: BulkSelectionService, private actionService: ActionService, private messageHub: MessageHubService) {
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
@ -88,6 +93,18 @@ export class CollectionDetailComponent implements OnInit {
ngOnInit(): void {
this.collectionTagActions = this.actionFactoryService.getCollectionTagActions(this.handleCollectionActionCallback.bind(this));
this.messageHub.messages$.pipe(takeWhile(event => event.event === EVENTS.SeriesAddedToCollection), takeUntil(this.onDestory), debounceTime(2000)).subscribe(event => {
const collectionEvent = event.payload as SeriesAddedToCollectionEvent;
if (collectionEvent.tagId === this.collectionTag.id) {
this.loadPage();
}
});
}
ngOnDestroy() {
this.onDestory.next();
this.onDestory.complete();
}
@HostListener('document:keydown.shift', ['$event'])

View file

@ -259,7 +259,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
break;
case(Action.IncognitoRead):
if (volume.chapters != undefined && volume.chapters?.length >= 1) {
this.openChapter(volume.chapters[0], true);
this.openChapter(volume.chapters.sort(this.utilityService.sortChapters)[0], true);
}
break;
default: