diff --git a/API/Controllers/SeriesController.cs b/API/Controllers/SeriesController.cs
index 6e37da199..4433ade21 100644
--- a/API/Controllers/SeriesController.cs
+++ b/API/Controllers/SeriesController.cs
@@ -383,7 +383,7 @@ public class SeriesController : BaseApiController
///
///
/// Do not rely on this API externally. May change without hesitation.
- [ResponseCache(CacheProfileName = "Hour", VaryByQueryKeys = new [] {"seriesId"})]
+ [ResponseCache(CacheProfileName = "5Minute", VaryByQueryKeys = new [] {"seriesId"})]
[HttpGet("series-detail")]
public async Task> GetSeriesDetailBreakdown(int seriesId)
{
diff --git a/API/Extensions/ApplicationServiceExtensions.cs b/API/Extensions/ApplicationServiceExtensions.cs
index bece2e76d..ba2e2f6cf 100644
--- a/API/Extensions/ApplicationServiceExtensions.cs
+++ b/API/Extensions/ApplicationServiceExtensions.cs
@@ -7,13 +7,11 @@ using API.Services.Tasks.Metadata;
using API.Services.Tasks.Scanner;
using API.SignalR;
using API.SignalR.Presence;
-using Kavita.Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
namespace API.Extensions;
diff --git a/API/Services/Tasks/ScannerService.cs b/API/Services/Tasks/ScannerService.cs
index 31cca7645..18cb219e0 100644
--- a/API/Services/Tasks/ScannerService.cs
+++ b/API/Services/Tasks/ScannerService.cs
@@ -9,7 +9,6 @@ using API.Data;
using API.Data.Repositories;
using API.Entities;
using API.Entities.Enums;
-using API.Extensions;
using API.Helpers;
using API.Parser;
using API.Services.Tasks.Metadata;
diff --git a/API/Startup.cs b/API/Startup.cs
index a608563a4..00351a3fa 100644
--- a/API/Startup.cs
+++ b/API/Startup.cs
@@ -17,6 +17,7 @@ using API.Services.Tasks;
using API.SignalR;
using Hangfire;
using Hangfire.MemoryStorage;
+using Hangfire.Storage.SQLite;
using Kavita.Common;
using Kavita.Common.EnvironmentInfo;
using Microsoft.AspNetCore.Builder;
@@ -176,7 +177,7 @@ public class Startup
services.AddHangfire(configuration => configuration
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
- .UseMemoryStorage()); // UseSQLiteStorage - SQLite has some issues around resuming jobs when aborted
+ .UseSQLiteStorage("config/Hangfire.db")); // UseSQLiteStorage - SQLite has some issues around resuming jobs when aborted
// Add the processing server as IHostedService
services.AddHangfireServer(options =>
diff --git a/UI/Web/src/app/_services/device.service.ts b/UI/Web/src/app/_services/device.service.ts
index d67193e4c..52e1c5aad 100644
--- a/UI/Web/src/app/_services/device.service.ts
+++ b/UI/Web/src/app/_services/device.service.ts
@@ -1,6 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { ReplaySubject, shareReplay, take, tap } from 'rxjs';
+import { ReplaySubject, shareReplay, tap } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Device } from '../_models/device/device';
import { DevicePlatform } from '../_models/device/device-platform';
@@ -19,8 +19,11 @@ export class DeviceService {
constructor(private httpClient: HttpClient, private accountService: AccountService) {
// Ensure we are authenticated before we make an authenticated api call.
- this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
- if (!user) return;
+ this.accountService.currentUser$.subscribe(user => {
+ if (!user) {
+ this.devicesSource.next([]);
+ return;
+ }
this.httpClient.get(this.baseUrl + 'device', {}).subscribe(data => {
this.devicesSource.next(data);
diff --git a/UI/Web/src/app/_services/theme.service.ts b/UI/Web/src/app/_services/theme.service.ts
index fb2bc61c4..8414150cc 100644
--- a/UI/Web/src/app/_services/theme.service.ts
+++ b/UI/Web/src/app/_services/theme.service.ts
@@ -78,7 +78,7 @@ export class ThemeService implements OnDestroy {
this.themeCache = themes;
this.themesSource.next(themes);
this.currentTheme$.pipe(take(1)).subscribe(theme => {
- if (!themes.includes(theme)) {
+ if (themes.filter(t => t.id === theme.id).length === 0) {
this.setTheme(this.defaultTheme);
this.toastr.info('The active theme no longer exists. Please refresh the page.');
}
diff --git a/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.html b/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.html
index 548d2b7e8..06e8cc07e 100644
--- a/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.html
+++ b/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.html
@@ -18,7 +18,7 @@
-
+
diff --git a/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.ts b/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.ts
index 53984b200..5b5aa9bfe 100644
--- a/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.ts
+++ b/UI/Web/src/app/cards/card-item/card-actionables/card-actionables.component.ts
@@ -77,6 +77,13 @@ export class CardActionablesComponent implements OnInit {
subMenu.open();
}
+ closeAllSubmenus() {
+ Object.keys(this.submenu).forEach(key => {
+ this.submenu[key].close();
+ delete this.submenu[key];
+ });
+ }
+
performDynamicClick(event: any, action: ActionItem, dynamicItem: any) {
action._extra = dynamicItem;
this.performAction(event, action);
diff --git a/UI/Web/src/app/series-detail/series-detail.component.ts b/UI/Web/src/app/series-detail/series-detail.component.ts
index 6909eb7ae..b342b519c 100644
--- a/UI/Web/src/app/series-detail/series-detail.component.ts
+++ b/UI/Web/src/app/series-detail/series-detail.component.ts
@@ -368,7 +368,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
break;
case Action.SendTo:
{
- const chapterIds = this.volumes.map(v => v.chapters.map(c => c.id)).flat()
+ const chapterIds = [...this.volumes.map(v => v.chapters.map(c => c.id)).flat(), ...this.specials.map(c => c.id)]
const device = (action._extra!.data as Device);
this.actionService.sendToDevice(chapterIds, device);
break;