diff --git a/API/Controllers/LibraryController.cs b/API/Controllers/LibraryController.cs index 316431c6d..acb275fa3 100644 --- a/API/Controllers/LibraryController.cs +++ b/API/Controllers/LibraryController.cs @@ -334,7 +334,7 @@ public class LibraryController : BaseApiController library.IncludeInDashboard = dto.IncludeInDashboard; library.IncludeInRecommended = dto.IncludeInRecommended; library.IncludeInSearch = dto.IncludeInSearch; - library.ManageCollections = dto.CreateCollections; + library.ManageCollections = dto.ManageCollections; _unitOfWork.LibraryRepository.Update(library); diff --git a/API/DTOs/UpdateLibraryDto.cs b/API/DTOs/UpdateLibraryDto.cs index 6a9b7c72d..977616497 100644 --- a/API/DTOs/UpdateLibraryDto.cs +++ b/API/DTOs/UpdateLibraryDto.cs @@ -23,6 +23,6 @@ public class UpdateLibraryDto [Required] public bool IncludeInSearch { get; init; } [Required] - public bool CreateCollections { get; init; } + public bool ManageCollections { get; init; } } diff --git a/API/Data/MigrateBrokenGMT1Dates.cs b/API/Data/MigrateBrokenGMT1Dates.cs new file mode 100644 index 000000000..2427874d6 --- /dev/null +++ b/API/Data/MigrateBrokenGMT1Dates.cs @@ -0,0 +1,135 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace API.Data; + +/// +/// v0.7 introduced UTC dates and GMT+1 users would sometimes have dates stored as '0000-12-31 23:00:00'. +/// This Migration will update those dates. +/// +public static class MigrateBrokenGMT1Dates +{ + public static async Task Migrate(IUnitOfWork unitOfWork, DataContext dataContext, ILogger logger) + { + // if current version is > 0.7, then we can exit and not perform + var settings = await unitOfWork.SettingsRepository.GetSettingsDtoAsync(); + if (Version.Parse(settings.InstallVersion) > new Version(0, 7, 0, 2)) + { + return; + } + logger.LogCritical("Running MigrateBrokenGMT1Dates migration. Please be patient, this may take some time depending on the size of your library. Do not abort, this can break your Database"); + + #region Series + logger.LogInformation("Updating Dates on Series..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE Series SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE Series SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + UPDATE Series SET LastChapterAddedUtc = '0001-01-01 00:00:00' WHERE LastChapterAddedUtc = '0000-12-31 23:00:00'; + UPDATE Series SET LastFolderScannedUtc = '0001-01-01 00:00:00' WHERE LastFolderScannedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Series...Done"); + #endregion + + #region Library + logger.LogInformation("Updating Dates on Libraries..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE Library SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE Library SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Libraries...Done"); + #endregion + + #region Volume + try + { + logger.LogInformation("Updating Dates on Volumes..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE Volume SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE Volume SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Volumes...Done"); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Updating Dates on Volumes...Failed"); + } + #endregion + + #region Chapter + try + { + logger.LogInformation("Updating Dates on Chapters..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE Chapter SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE Chapter SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Chapters...Done"); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Updating Dates on Chapters...Failed"); + } + #endregion + + #region AppUserBookmark + logger.LogInformation("Updating Dates on Bookmarks..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE AppUserBookmark SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE AppUserBookmark SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Bookmarks...Done"); + #endregion + + #region AppUserProgress + logger.LogInformation("Updating Dates on Progress..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE AppUserProgresses SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE AppUserProgresses SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Progress...Done"); + #endregion + + #region Device + logger.LogInformation("Updating Dates on Device..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE Device SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE Device SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + UPDATE Device SET LastUsedUtc = '0001-01-01 00:00:00' WHERE LastUsedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on Device...Done"); + #endregion + + #region MangaFile + logger.LogInformation("Updating Dates on MangaFile..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE MangaFile SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE MangaFile SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + UPDATE MangaFile SET LastFileAnalysisUtc = '0001-01-01 00:00:00' WHERE LastFileAnalysisUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on MangaFile...Done"); + #endregion + + #region ReadingList + logger.LogInformation("Updating Dates on ReadingList..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE ReadingList SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE ReadingList SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on ReadingList...Done"); + #endregion + + #region SiteTheme + logger.LogInformation("Updating Dates on SiteTheme..."); + await dataContext.Database.ExecuteSqlRawAsync(@" + UPDATE SiteTheme SET CreatedUtc = '0001-01-01 00:00:00' WHERE CreatedUtc = '0000-12-31 23:00:00'; + UPDATE SiteTheme SET LastModifiedUtc = '0001-01-01 00:00:00' WHERE LastModifiedUtc = '0000-12-31 23:00:00'; + "); + logger.LogInformation("Updating Dates on SiteTheme...Done"); + #endregion + + logger.LogInformation("MigrateBrokenGMT1Dates migration finished"); + + } +} diff --git a/API/Extensions/StringExtensions.cs b/API/Extensions/StringExtensions.cs index b172c0e46..18c5ad989 100644 --- a/API/Extensions/StringExtensions.cs +++ b/API/Extensions/StringExtensions.cs @@ -4,7 +4,8 @@ namespace API.Extensions; public static class StringExtensions { - private static readonly Regex SentenceCaseRegex = new Regex(@"(^[a-z])|\.\s+(.)", RegexOptions.ExplicitCapture | RegexOptions.Compiled); + private static readonly Regex SentenceCaseRegex = new Regex(@"(^[a-z])|\.\s+(.)", + RegexOptions.ExplicitCapture | RegexOptions.Compiled, Services.Tasks.Scanner.Parser.Parser.RegexTimeout); public static string SentenceCase(this string value) { diff --git a/API/Program.cs b/API/Program.cs index 50da97005..8ecc83d27 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -44,12 +44,11 @@ public class Program .CreateBootstrapLogger(); var directoryService = new DirectoryService(null, new FileSystem()); - // Before anything, check if JWT has been generated properly or if user still has default if (!Configuration.CheckIfJwtTokenSet() && Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != Environments.Development) { - Console.WriteLine("Generating JWT TokenKey for encrypting user sessions..."); + Log.Logger.Information("Generating JWT TokenKey for encrypting user sessions..."); var rBytes = new byte[128]; RandomNumberGenerator.Create().GetBytes(rBytes); Configuration.JwtToken = Convert.ToBase64String(rBytes).Replace("/", string.Empty); @@ -174,7 +173,7 @@ public class Program webBuilder.UseKestrel((opts) => { var ipAddresses = Configuration.IpAddresses; - if (ipAddresses == null || ipAddresses.Length == 0) + if (string.IsNullOrEmpty(ipAddresses)) { opts.ListenAnyIP(HttpPort, options => { options.Protocols = HttpProtocols.Http1AndHttp2; }); } diff --git a/API/Services/BookmarkService.cs b/API/Services/BookmarkService.cs index 3b280f251..b79f4923d 100644 --- a/API/Services/BookmarkService.cs +++ b/API/Services/BookmarkService.cs @@ -216,7 +216,7 @@ public class BookmarkService : IBookmarkService foreach (var chapter in chapters) { var newFile = await SaveAsWebP(coverDirectory, chapter.CoverImage, coverDirectory); - chapter.CoverImage = newFile; + chapter.CoverImage = Path.GetFileName(newFile); _unitOfWork.ChapterRepository.Update(chapter); await _unitOfWork.CommitAsync(); await _eventHub.SendMessageAsync(MessageFactory.NotificationProgress, @@ -272,7 +272,6 @@ public class BookmarkService : IBookmarkService { // Convert target file to webp then delete original target file and update bookmark - var originalFile = filename; try { var targetFile = await _imageService.ConvertToWebP(fullSourcePath, fullTargetDirectory); @@ -283,7 +282,7 @@ public class BookmarkService : IBookmarkService catch (Exception ex) { _logger.LogError(ex, "Could not convert image {FilePath}", filename); - newFilename = originalFile; + newFilename = filename; } } catch (Exception ex) diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index 25119dbe0..0d4b9eeae 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -90,9 +90,11 @@ public class DirectoryService : IDirectoryService private static readonly Regex ExcludeDirectories = new Regex( @"@eaDir|\.DS_Store|\.qpkg|__MACOSX|@Recently-Snapshot|@recycle", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + RegexOptions.Compiled | RegexOptions.IgnoreCase, + Tasks.Scanner.Parser.Parser.RegexTimeout); private static readonly Regex FileCopyAppend = new Regex(@"\(\d+\)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + RegexOptions.Compiled | RegexOptions.IgnoreCase, + Tasks.Scanner.Parser.Parser.RegexTimeout); public static readonly string BackupDirectory = Path.Join(Directory.GetCurrentDirectory(), "config", "backups"); public DirectoryService(ILogger logger, IFileSystem fileSystem) @@ -203,7 +205,8 @@ public class DirectoryService : IDirectoryService if (fileNameRegex != string.Empty) { - var reSearchPattern = new Regex(fileNameRegex, RegexOptions.IgnoreCase); + var reSearchPattern = new Regex(fileNameRegex, RegexOptions.IgnoreCase, + Tasks.Scanner.Parser.Parser.RegexTimeout); return FileSystem.Directory.EnumerateFiles(path, "*", searchOption) .Where(file => { diff --git a/API/SignalR/EventHub.cs b/API/SignalR/EventHub.cs index 1f7790581..d5820ab09 100644 --- a/API/SignalR/EventHub.cs +++ b/API/SignalR/EventHub.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using API.Data; using API.SignalR.Presence; using Microsoft.AspNetCore.SignalR; @@ -36,8 +37,8 @@ public class EventHub : IEventHub var users = _messageHub.Clients.All; if (onlyAdmins) { - var admins = await _presenceTracker.GetOnlineAdmins(); - users = _messageHub.Clients.Users(admins); + var admins = await _presenceTracker.GetOnlineAdminIds(); + users = _messageHub.Clients.Users(admins.Select(i => i.ToString()).ToArray()); } diff --git a/API/SignalR/LogHub.cs b/API/SignalR/LogHub.cs index 15a30afdb..5158a389f 100644 --- a/API/SignalR/LogHub.cs +++ b/API/SignalR/LogHub.cs @@ -26,13 +26,13 @@ public class LogHub : Hub public override async Task OnConnectedAsync() { - await _tracker.UserConnected(Context.User.GetUsername(), Context.ConnectionId); + await _tracker.UserConnected(Context.User.GetUserId(), Context.ConnectionId); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { - await _tracker.UserDisconnected(Context.User.GetUsername(), Context.ConnectionId); + await _tracker.UserDisconnected(Context.User.GetUserId(), Context.ConnectionId); await base.OnDisconnectedAsync(exception); } diff --git a/API/SignalR/MessageHub.cs b/API/SignalR/MessageHub.cs index e56dfeaa0..23ceaa8be 100644 --- a/API/SignalR/MessageHub.cs +++ b/API/SignalR/MessageHub.cs @@ -22,7 +22,7 @@ public class MessageHub : Hub public override async Task OnConnectedAsync() { - await _tracker.UserConnected(Context.User.GetUsername(), Context.ConnectionId); + await _tracker.UserConnected(Context.User.GetUserId(), Context.ConnectionId); var currentUsers = await PresenceTracker.GetOnlineUsers(); await Clients.All.SendAsync(MessageFactory.OnlineUsers, currentUsers); @@ -33,7 +33,7 @@ public class MessageHub : Hub public override async Task OnDisconnectedAsync(Exception exception) { - await _tracker.UserDisconnected(Context.User.GetUsername(), Context.ConnectionId); + await _tracker.UserDisconnected(Context.User.GetUserId(), Context.ConnectionId); var currentUsers = await PresenceTracker.GetOnlineUsers(); await Clients.All.SendAsync(MessageFactory.OnlineUsers, currentUsers); diff --git a/API/SignalR/Presence/PresenceTracker.cs b/API/SignalR/Presence/PresenceTracker.cs index 0760cff8a..1e9f930f3 100644 --- a/API/SignalR/Presence/PresenceTracker.cs +++ b/API/SignalR/Presence/PresenceTracker.cs @@ -8,15 +8,16 @@ namespace API.SignalR.Presence; public interface IPresenceTracker { - Task UserConnected(string username, string connectionId); - Task UserDisconnected(string username, string connectionId); - Task GetOnlineAdmins(); - Task> GetConnectionsForUser(string username); + Task UserConnected(int userId, string connectionId); + Task UserDisconnected(int userId, string connectionId); + Task GetOnlineAdminIds(); + Task> GetConnectionsForUser(int userId); } internal class ConnectionDetail { + public string UserName { get; set; } public List ConnectionIds { get; set; } public bool IsAdmin { get; set; } } @@ -28,28 +29,29 @@ internal class ConnectionDetail public class PresenceTracker : IPresenceTracker { private readonly IUnitOfWork _unitOfWork; - private static readonly Dictionary OnlineUsers = new Dictionary(); + private static readonly Dictionary OnlineUsers = new Dictionary(); public PresenceTracker(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } - public async Task UserConnected(string username, string connectionId) + public async Task UserConnected(int userId, string connectionId) { - var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(username); + var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId); if (user == null) return; var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user); lock (OnlineUsers) { - if (OnlineUsers.ContainsKey(username)) + if (OnlineUsers.ContainsKey(userId)) { - OnlineUsers[username].ConnectionIds.Add(connectionId); + OnlineUsers[userId].ConnectionIds.Add(connectionId); } else { - OnlineUsers.Add(username, new ConnectionDetail() + OnlineUsers.Add(userId, new ConnectionDetail() { + UserName = user.UserName, ConnectionIds = new List() {connectionId}, IsAdmin = isAdmin }); @@ -61,17 +63,17 @@ public class PresenceTracker : IPresenceTracker await _unitOfWork.CommitAsync(); } - public Task UserDisconnected(string username, string connectionId) + public Task UserDisconnected(int userId, string connectionId) { lock (OnlineUsers) { - if (!OnlineUsers.ContainsKey(username)) return Task.CompletedTask; + if (!OnlineUsers.ContainsKey(userId)) return Task.CompletedTask; - OnlineUsers[username].ConnectionIds.Remove(connectionId); + OnlineUsers[userId].ConnectionIds.Remove(connectionId); - if (OnlineUsers[username].ConnectionIds.Count == 0) + if (OnlineUsers[userId].ConnectionIds.Count == 0) { - OnlineUsers.Remove(username); + OnlineUsers.Remove(userId); } } return Task.CompletedTask; @@ -82,15 +84,15 @@ public class PresenceTracker : IPresenceTracker string[] onlineUsers; lock (OnlineUsers) { - onlineUsers = OnlineUsers.OrderBy(k => k.Key).Select(k => k.Key).ToArray(); + onlineUsers = OnlineUsers.OrderBy(k => k.Value.UserName).Select(k => k.Value.UserName).ToArray(); } return Task.FromResult(onlineUsers); } - public Task GetOnlineAdmins() + public Task GetOnlineAdminIds() { - string[] onlineUsers; + int[] onlineUsers; lock (OnlineUsers) { onlineUsers = OnlineUsers.Where(pair => pair.Value.IsAdmin).OrderBy(k => k.Key).Select(k => k.Key).ToArray(); @@ -100,12 +102,12 @@ public class PresenceTracker : IPresenceTracker return Task.FromResult(onlineUsers); } - public Task> GetConnectionsForUser(string username) + public Task> GetConnectionsForUser(int userId) { List connectionIds; lock (OnlineUsers) { - connectionIds = OnlineUsers.GetValueOrDefault(username)?.ConnectionIds; + connectionIds = OnlineUsers.GetValueOrDefault(userId)?.ConnectionIds; } return Task.FromResult(connectionIds ?? new List()); diff --git a/API/Startup.cs b/API/Startup.cs index b20025815..f84ef6387 100644 --- a/API/Startup.cs +++ b/API/Startup.cs @@ -234,6 +234,9 @@ public class Startup await MigrateUserProgressLibraryId.Migrate(unitOfWork, logger); await MigrateToUtcDates.Migrate(unitOfWork, dataContext, logger); + // v0.7 + await MigrateBrokenGMT1Dates.Migrate(unitOfWork, dataContext, logger); + // Update the version in the DB after all migrations are run var installVersion = await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.InstallVersion); installVersion.Value = BuildInfo.Version.ToString(); diff --git a/UI/Web/src/app/_models/library.ts b/UI/Web/src/app/_models/library.ts index 059e505c7..8f229b4df 100644 --- a/UI/Web/src/app/_models/library.ts +++ b/UI/Web/src/app/_models/library.ts @@ -15,5 +15,5 @@ export interface Library { includeInDashboard: boolean; includeInRecommended: boolean; includeInSearch: boolean; - createCollections: boolean; -} \ No newline at end of file + manageCollections: boolean; +} diff --git a/UI/Web/src/app/_services/message-hub.service.ts b/UI/Web/src/app/_services/message-hub.service.ts index 635425336..8aed98ab0 100644 --- a/UI/Web/src/app/_services/message-hub.service.ts +++ b/UI/Web/src/app/_services/message-hub.service.ts @@ -96,7 +96,7 @@ export class MessageHubService { private hubConnection!: HubConnection; private messagesSource = new ReplaySubject>(1); - private onlineUsersSource = new BehaviorSubject([]); + private onlineUsersSource = new BehaviorSubject([]); // UserIds /** * Any events that come from the backend @@ -142,7 +142,7 @@ export class MessageHubService { .start() .catch(err => console.error(err)); - this.hubConnection.on(EVENTS.OnlineUsers, (usernames: string[]) => { + this.hubConnection.on(EVENTS.OnlineUsers, (usernames: number[]) => { this.onlineUsersSource.next(usernames); }); diff --git a/UI/Web/src/app/admin/manage-users/manage-users.component.html b/UI/Web/src/app/admin/manage-users/manage-users.component.html index 12cd37cf2..2c32c009d 100644 --- a/UI/Web/src/app/admin/manage-users/manage-users.component.html +++ b/UI/Web/src/app/admin/manage-users/manage-users.component.html @@ -39,7 +39,7 @@
  • - + {{member.username | titlecase}} diff --git a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.html b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.html index 029164789..236652626 100644 --- a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.html +++ b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.html @@ -11,9 +11,9 @@

    - Last Scanned: + Last Scanned: Never {{library.lastScanned | date: 'short'}} @@ -79,7 +79,7 @@

    Library image should not be large. Aim for a small file, 32x32 pixels in size. Kavita does not perform validation on size.

    -
    - +
    @@ -169,7 +169,7 @@ - + diff --git a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts index 0773539a3..af9099ce2 100644 --- a/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts +++ b/UI/Web/src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component.ts @@ -52,7 +52,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { selectedFolders: string[] = []; madeChanges = false; libraryTypes: string[] = [] - + isAddLibrary = false; setupStep = StepID.General; private readonly onDestroy = new Subject(); @@ -62,7 +62,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { get StepID() { return StepID; } constructor(public utilityService: UtilityService, private uploadService: UploadService, private modalService: NgbModal, - private settingService: SettingsService, public modal: NgbActiveModal, private confirmService: ConfirmService, + private settingService: SettingsService, public modal: NgbActiveModal, private confirmService: ConfirmService, private libraryService: LibraryService, private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef, private imageService: ImageService) { } @@ -85,7 +85,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { } this.libraryForm.get('name')?.valueChanges.pipe( - debounceTime(100), + debounceTime(100), distinctUntilChanged(), switchMap(name => this.libraryService.libraryNameExists(name)), tap(exists => { @@ -93,7 +93,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { if (!exists || isExistingName) { this.libraryForm.get('name')?.setErrors(null); } else { - this.libraryForm.get('name')?.setErrors({duplicateName: true}) + this.libraryForm.get('name')?.setErrors({duplicateName: true}) } this.cdRef.markForCheck(); }), @@ -108,7 +108,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { this.onDestroy.next(); this.onDestroy.complete(); } - + setValues() { if (this.library !== undefined) { @@ -118,7 +118,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { this.libraryForm.get('includeInDashboard')?.setValue(this.library.includeInDashboard); this.libraryForm.get('includeInRecommended')?.setValue(this.library.includeInRecommended); this.libraryForm.get('includeInSearch')?.setValue(this.library.includeInSearch); - this.libraryForm.get('createCollections')?.setValue(this.library.createCollections); + this.libraryForm.get('manageCollections')?.setValue(this.library.manageCollections); this.selectedFolders = this.library.folders; this.madeChanges = false; this.cdRef.markForCheck(); @@ -155,7 +155,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { model.type = parseInt(model.type, 10); if (model.type !== this.library.type) { - if (!await this.confirmService.confirm(`Changing library type will trigger a new scan with different parsing rules and may lead to + if (!await this.confirmService.confirm(`Changing library type will trigger a new scan with different parsing rules and may lead to series being re-created and hence you may loose progress and bookmarks. You should backup before you do this. Are you sure you want to continue?`)) return; } @@ -217,7 +217,7 @@ export class LibrarySettingsModalComponent implements OnInit, OnDestroy { isNextDisabled() { switch (this.setupStep) { - case StepID.General: + case StepID.General: return this.libraryForm.get('name')?.invalid || this.libraryForm.get('type')?.invalid; case StepID.Folder: return this.selectedFolders.length === 0; diff --git a/openapi.json b/openapi.json index 572f52d8d..06aec3b21 100644 --- a/openapi.json +++ b/openapi.json @@ -7,7 +7,7 @@ "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "0.6.1.41" + "version": "0.7.0.2" }, "servers": [ { @@ -14070,13 +14070,13 @@ }, "UpdateLibraryDto": { "required": [ - "createCollections", "folders", "folderWatching", "id", "includeInDashboard", "includeInRecommended", "includeInSearch", + "manageCollections", "name", "type" ], @@ -14111,7 +14111,7 @@ "includeInSearch": { "type": "boolean" }, - "createCollections": { + "manageCollections": { "type": "boolean" } },