mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Merge branch 'develop' of https://github.com/Kareadita/Kavita into develop
This commit is contained in:
commit
8a62d54c0b
@ -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);
|
||||
|
||||
|
@ -23,6 +23,6 @@ public class UpdateLibraryDto
|
||||
[Required]
|
||||
public bool IncludeInSearch { get; init; }
|
||||
[Required]
|
||||
public bool CreateCollections { get; init; }
|
||||
public bool ManageCollections { get; init; }
|
||||
|
||||
}
|
||||
|
135
API/Data/MigrateBrokenGMT1Dates.cs
Normal file
135
API/Data/MigrateBrokenGMT1Dates.cs
Normal file
@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace API.Data;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public static class MigrateBrokenGMT1Dates
|
||||
{
|
||||
public static async Task Migrate(IUnitOfWork unitOfWork, DataContext dataContext, ILogger<Program> 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");
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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; });
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<DirectoryService> 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 =>
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,13 +26,13 @@ public class LogHub : Hub<ILogHub>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -8,15 +8,16 @@ namespace API.SignalR.Presence;
|
||||
|
||||
public interface IPresenceTracker
|
||||
{
|
||||
Task UserConnected(string username, string connectionId);
|
||||
Task UserDisconnected(string username, string connectionId);
|
||||
Task<string[]> GetOnlineAdmins();
|
||||
Task<List<string>> GetConnectionsForUser(string username);
|
||||
Task UserConnected(int userId, string connectionId);
|
||||
Task UserDisconnected(int userId, string connectionId);
|
||||
Task<int[]> GetOnlineAdminIds();
|
||||
Task<List<string>> GetConnectionsForUser(int userId);
|
||||
|
||||
}
|
||||
|
||||
internal class ConnectionDetail
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public List<string> 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<string, ConnectionDetail> OnlineUsers = new Dictionary<string, ConnectionDetail>();
|
||||
private static readonly Dictionary<int, ConnectionDetail> OnlineUsers = new Dictionary<int, ConnectionDetail>();
|
||||
|
||||
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<string>() {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<string[]> GetOnlineAdmins()
|
||||
public Task<int[]> 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<List<string>> GetConnectionsForUser(string username)
|
||||
public Task<List<string>> GetConnectionsForUser(int userId)
|
||||
{
|
||||
List<string> connectionIds;
|
||||
lock (OnlineUsers)
|
||||
{
|
||||
connectionIds = OnlineUsers.GetValueOrDefault(username)?.ConnectionIds;
|
||||
connectionIds = OnlineUsers.GetValueOrDefault(userId)?.ConnectionIds;
|
||||
}
|
||||
|
||||
return Task.FromResult(connectionIds ?? new List<string>());
|
||||
|
@ -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();
|
||||
|
@ -4,7 +4,7 @@
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Company>kavitareader.com</Company>
|
||||
<Product>Kavita</Product>
|
||||
<AssemblyVersion>0.7.0.2</AssemblyVersion>
|
||||
<AssemblyVersion>0.7.1.1</AssemblyVersion>
|
||||
<NeutralLanguage>en</NeutralLanguage>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
</PropertyGroup>
|
||||
|
@ -15,5 +15,5 @@ export interface Library {
|
||||
includeInDashboard: boolean;
|
||||
includeInRecommended: boolean;
|
||||
includeInSearch: boolean;
|
||||
createCollections: boolean;
|
||||
manageCollections: boolean;
|
||||
}
|
@ -96,7 +96,7 @@ export class MessageHubService {
|
||||
private hubConnection!: HubConnection;
|
||||
|
||||
private messagesSource = new ReplaySubject<Message<any>>(1);
|
||||
private onlineUsersSource = new BehaviorSubject<string[]>([]);
|
||||
private onlineUsersSource = new BehaviorSubject<number[]>([]); // 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);
|
||||
});
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
<li *ngFor="let member of members; let idx = index;" class="list-group-item no-hover">
|
||||
<div>
|
||||
<h4>
|
||||
<i class="presence fa fa-circle" title="Active" aria-hidden="true" *ngIf="false && (messageHub.onlineUsers$ | async)?.includes(member.username)"></i>
|
||||
<i class="presence fa fa-circle" title="Active" aria-hidden="true" *ngIf="false && (messageHub.onlineUsers$ | async)?.includes(member.id)"></i>
|
||||
<span id="member-name--{{idx}}">{{member.username | titlecase}} </span>
|
||||
<span *ngIf="member.username === loggedInUsername">
|
||||
<i class="fas fa-star" aria-hidden="true"></i>
|
||||
|
@ -96,7 +96,7 @@
|
||||
<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="manage-collections" role="switch" formControlName="createCollections" class="form-check-input" aria-labelledby="auto-close-label">
|
||||
<input type="checkbox" id="manage-collections" role="switch" formControlName="manageCollections" class="form-check-input" aria-labelledby="auto-close-label">
|
||||
<label class="form-check-label" for="manage-collections">Manage Collections</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
}
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user