diff --git a/API/Services/Tasks/Scanner/ParseScannedFiles.cs b/API/Services/Tasks/Scanner/ParseScannedFiles.cs
index 0c8fd8670..111dc71af 100644
--- a/API/Services/Tasks/Scanner/ParseScannedFiles.cs
+++ b/API/Services/Tasks/Scanner/ParseScannedFiles.cs
@@ -73,7 +73,8 @@ namespace API.Services.Tasks.Scanner
info = Parser.Parser.Parse(path, rootPath, type);
}
- if (info == null)
+ // If we couldn't match, log. But don't log if the file parses as a cover image
+ if (info == null || !(Parser.Parser.IsImage(path) || Parser.Parser.IsCoverImage(path)))
{
_logger.LogWarning("[Scanner] Could not parse series from {Path}", path);
return;
diff --git a/UI/Web/src/app/in-progress/in-progress.component.html b/UI/Web/src/app/in-progress/in-progress.component.html
index ebae6ff8b..f4ca791f0 100644
--- a/UI/Web/src/app/in-progress/in-progress.component.html
+++ b/UI/Web/src/app/in-progress/in-progress.component.html
@@ -1,14 +1,14 @@
-
-
+
-
-
-
-
-
\ No newline at end of file
+
+
+
+
diff --git a/UI/Web/src/app/in-progress/in-progress.component.ts b/UI/Web/src/app/in-progress/in-progress.component.ts
index 164309c27..a247ff4ab 100644
--- a/UI/Web/src/app/in-progress/in-progress.component.ts
+++ b/UI/Web/src/app/in-progress/in-progress.component.ts
@@ -1,11 +1,15 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, HostListener, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, ActivatedRoute } from '@angular/router';
import { take } from 'rxjs/operators';
+import { BulkSelectionService } from '../cards/bulk-selection.service';
import { UpdateFilterEvent } from '../cards/card-detail-layout/card-detail-layout.component';
+import { KEY_CODES } from '../shared/_services/utility.service';
import { Pagination } from '../_models/pagination';
import { Series } from '../_models/series';
import { FilterItem, SeriesFilter, mangaFormatFilters } from '../_models/series-filter';
+import { Action } from '../_services/action-factory.service';
+import { ActionService } from '../_services/action.service';
import { SeriesService } from '../_services/series.service';
@Component({
@@ -16,7 +20,7 @@ import { SeriesService } from '../_services/series.service';
export class InProgressComponent implements OnInit {
isLoading: boolean = true;
- recentlyAdded: Series[] = [];
+ series: Series[] = [];
pagination!: Pagination;
libraryId!: number;
filters: Array = mangaFormatFilters;
@@ -24,7 +28,8 @@ export class InProgressComponent implements OnInit {
mangaFormat: null
};
- constructor(private router: Router, private route: ActivatedRoute, private seriesService: SeriesService, private titleService: Title) {
+ constructor(private router: Router, private route: ActivatedRoute, private seriesService: SeriesService, private titleService: Title,
+ private actionService: ActionService, public bulkSelectionService: BulkSelectionService) {
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.titleService.setTitle('Kavita - In Progress');
if (this.pagination === undefined || this.pagination === null) {
@@ -33,6 +38,20 @@ export class InProgressComponent implements OnInit {
this.loadPage();
}
+ @HostListener('document:keydown.shift', ['$event'])
+ handleKeypress(event: KeyboardEvent) {
+ if (event.key === KEY_CODES.SHIFT) {
+ this.bulkSelectionService.isShiftDown = true;
+ }
+ }
+
+ @HostListener('document:keyup.shift', ['$event'])
+ handleKeyUp(event: KeyboardEvent) {
+ if (event.key === KEY_CODES.SHIFT) {
+ this.bulkSelectionService.isShiftDown = false;
+ }
+ }
+
ngOnInit() {}
seriesClicked(series: Series) {
@@ -61,7 +80,7 @@ export class InProgressComponent implements OnInit {
}
this.isLoading = true;
this.seriesService.getInProgress(this.libraryId, this.pagination?.currentPage, this.pagination?.itemsPerPage, this.filter).pipe(take(1)).subscribe(series => {
- this.recentlyAdded = series.result;
+ this.series = series.result;
this.pagination = series.pagination;
this.isLoading = false;
window.scrollTo(0, 0);
@@ -73,4 +92,35 @@ export class InProgressComponent implements OnInit {
return urlParams.get('page');
}
+ bulkActionCallback = (action: Action, data: any) => {
+ const selectedSeriesIndexies = this.bulkSelectionService.getSelectedCardsForSource('series');
+ const selectedSeries = this.series.filter((series, index: number) => selectedSeriesIndexies.includes(index + ''));
+
+ switch (action) {
+ case Action.AddToReadingList:
+ this.actionService.addMultipleSeriesToReadingList(selectedSeries, () => {
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ case Action.AddToCollection:
+ this.actionService.addMultipleSeriesToCollectionTag(selectedSeries, () => {
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ case Action.MarkAsRead:
+ this.actionService.markMultipleSeriesAsRead(selectedSeries, () => {
+ this.loadPage();
+ this.bulkSelectionService.deselectAll();
+ });
+
+ break;
+ case Action.MarkAsUnread:
+ this.actionService.markMultipleSeriesAsUnread(selectedSeries, () => {
+ this.loadPage();
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ }
+ }
+
}
diff --git a/UI/Web/src/app/library-detail/library-detail.component.html b/UI/Web/src/app/library-detail/library-detail.component.html
index 6d7885385..d01cec915 100644
--- a/UI/Web/src/app/library-detail/library-detail.component.html
+++ b/UI/Web/src/app/library-detail/library-detail.component.html
@@ -9,6 +9,6 @@
(pageChange)="onPageChange($event)"
>
-
+
diff --git a/UI/Web/src/app/recently-added/recently-added.component.html b/UI/Web/src/app/recently-added/recently-added.component.html
index b9bfbec74..93952f73e 100644
--- a/UI/Web/src/app/recently-added/recently-added.component.html
+++ b/UI/Web/src/app/recently-added/recently-added.component.html
@@ -1,14 +1,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/Web/src/app/recently-added/recently-added.component.ts b/UI/Web/src/app/recently-added/recently-added.component.ts
index 4615f610a..22ea98b59 100644
--- a/UI/Web/src/app/recently-added/recently-added.component.ts
+++ b/UI/Web/src/app/recently-added/recently-added.component.ts
@@ -1,11 +1,18 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
-import { take } from 'rxjs/operators';
+import { Subject } from 'rxjs';
+import { debounceTime, take, takeUntil, takeWhile } from 'rxjs/operators';
+import { BulkSelectionService } from '../cards/bulk-selection.service';
import { UpdateFilterEvent } from '../cards/card-detail-layout/card-detail-layout.component';
+import { KEY_CODES } from '../shared/_services/utility.service';
+import { SeriesAddedEvent } from '../_models/events/series-added-event';
import { Pagination } from '../_models/pagination';
import { Series } from '../_models/series';
import { FilterItem, mangaFormatFilters, SeriesFilter } from '../_models/series-filter';
+import { Action, ActionFactoryService } from '../_services/action-factory.service';
+import { ActionService } from '../_services/action.service';
+import { MessageHubService } from '../_services/message-hub.service';
import { SeriesService } from '../_services/series.service';
/**
@@ -16,10 +23,10 @@ import { SeriesService } from '../_services/series.service';
templateUrl: './recently-added.component.html',
styleUrls: ['./recently-added.component.scss']
})
-export class RecentlyAddedComponent implements OnInit {
+export class RecentlyAddedComponent implements OnInit, OnDestroy {
isLoading: boolean = true;
- recentlyAdded: Series[] = [];
+ series: Series[] = [];
pagination!: Pagination;
libraryId!: number;
@@ -28,7 +35,10 @@ export class RecentlyAddedComponent implements OnInit {
mangaFormat: null
};
- constructor(private router: Router, private route: ActivatedRoute, private seriesService: SeriesService, private titleService: Title) {
+ onDestroy: Subject = new Subject();
+
+ constructor(private router: Router, private route: ActivatedRoute, private seriesService: SeriesService, private titleService: Title,
+ private actionService: ActionService, public bulkSelectionService: BulkSelectionService, private hubService: MessageHubService) {
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.titleService.setTitle('Kavita - Recently Added');
if (this.pagination === undefined || this.pagination === null) {
@@ -37,7 +47,30 @@ export class RecentlyAddedComponent implements OnInit {
this.loadPage();
}
- ngOnInit() {}
+ @HostListener('document:keydown.shift', ['$event'])
+ handleKeypress(event: KeyboardEvent) {
+ if (event.key === KEY_CODES.SHIFT) {
+ this.bulkSelectionService.isShiftDown = true;
+ }
+ }
+
+ @HostListener('document:keyup.shift', ['$event'])
+ handleKeyUp(event: KeyboardEvent) {
+ if (event.key === KEY_CODES.SHIFT) {
+ this.bulkSelectionService.isShiftDown = false;
+ }
+ }
+
+ ngOnInit() {
+ this.hubService.seriesAdded.pipe(takeWhile(event => event.libraryId === this.libraryId), debounceTime(6000), takeUntil(this.onDestroy)).subscribe((event: SeriesAddedEvent) => {
+ this.loadPage();
+ });
+ }
+
+ ngOnDestroy() {
+ this.onDestroy.next();
+ this.onDestroy.complete();
+ }
seriesClicked(series: Series) {
this.router.navigate(['library', this.libraryId, 'series', series.id]);
@@ -65,7 +98,7 @@ export class RecentlyAddedComponent implements OnInit {
}
this.isLoading = true;
this.seriesService.getRecentlyAdded(this.libraryId, this.pagination?.currentPage, this.pagination?.itemsPerPage, this.filter).pipe(take(1)).subscribe(series => {
- this.recentlyAdded = series.result;
+ this.series = series.result;
this.pagination = series.pagination;
this.isLoading = false;
window.scrollTo(0, 0);
@@ -76,4 +109,35 @@ export class RecentlyAddedComponent implements OnInit {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('page');
}
+
+ bulkActionCallback = (action: Action, data: any) => {
+ const selectedSeriesIndexies = this.bulkSelectionService.getSelectedCardsForSource('series');
+ const selectedSeries = this.series.filter((series, index: number) => selectedSeriesIndexies.includes(index + ''));
+
+ switch (action) {
+ case Action.AddToReadingList:
+ this.actionService.addMultipleSeriesToReadingList(selectedSeries, () => {
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ case Action.AddToCollection:
+ this.actionService.addMultipleSeriesToCollectionTag(selectedSeries, () => {
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ case Action.MarkAsRead:
+ this.actionService.markMultipleSeriesAsRead(selectedSeries, () => {
+ this.loadPage();
+ this.bulkSelectionService.deselectAll();
+ });
+
+ break;
+ case Action.MarkAsUnread:
+ this.actionService.markMultipleSeriesAsUnread(selectedSeries, () => {
+ this.loadPage();
+ this.bulkSelectionService.deselectAll();
+ });
+ break;
+ }
+ }
}