mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Kavita+ Tweaks (#2595)
This commit is contained in:
parent
e21144bf6b
commit
3dcf7750f7
14
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
14
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help us improve
|
||||
title: ""
|
||||
title: "Bug Title Here" # Add a title field
|
||||
labels: ["needs-triage"]
|
||||
assignees:
|
||||
body:
|
||||
@ -16,7 +16,7 @@ body:
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what steps you took so we can try to reproduce.
|
||||
description: Also tell us what steps you took so we can try to reproduce.
|
||||
placeholder: Tell us what you see!
|
||||
value: ""
|
||||
validations:
|
||||
@ -52,7 +52,7 @@ body:
|
||||
- type: dropdown
|
||||
id: desktop-OS
|
||||
attributes:
|
||||
label: If issue being seen on Desktop, what OS are you running where you see the issue?
|
||||
label: If the issue is being seen on Desktop, what OS are you running where you see the issue?
|
||||
multiple: false
|
||||
options:
|
||||
- Windows
|
||||
@ -61,7 +61,7 @@ body:
|
||||
- type: dropdown
|
||||
id: desktop-browsers
|
||||
attributes:
|
||||
label: If issue being seen in the UI, what browsers are you seeing the problem on?
|
||||
label: If the issue is being seen in the UI, what browsers are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Firefox
|
||||
@ -71,7 +71,7 @@ body:
|
||||
- type: dropdown
|
||||
id: mobile-OS
|
||||
attributes:
|
||||
label: If issue being seen on Mobile, what OS are you running where you see the issue?
|
||||
label: If the issue is being seen on Mobile, what OS are you running where you see the issue?
|
||||
multiple: false
|
||||
options:
|
||||
- Android
|
||||
@ -79,7 +79,7 @@ body:
|
||||
- type: dropdown
|
||||
id: mobile-browsers
|
||||
attributes:
|
||||
label: If issue being seen on UI, what browsers are you seeing the problem on?
|
||||
label: If the issue is being seen on the UI, what browsers are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Firefox
|
||||
@ -97,7 +97,7 @@ body:
|
||||
attributes:
|
||||
label: Additional Notes
|
||||
description: Any other information about the issue not covered in this form?
|
||||
placeholder: e.g. Running Kavita on a raspberry pi, updating from X version, using LSIO container, etc
|
||||
placeholder: e.g. Running Kavita on a Raspberry Pi, updating from X version, using LSIO container, etc
|
||||
value: ""
|
||||
validations:
|
||||
required: true
|
||||
|
@ -10,8 +10,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.11" />
|
||||
<PackageReference Include="BenchmarkDotNet.Annotations" Version="0.13.11" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
|
||||
<PackageReference Include="BenchmarkDotNet.Annotations" Version="0.13.12" />
|
||||
<PackageReference Include="NSubstitute" Version="5.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="20.0.4" />
|
||||
<PackageReference Include="TestableIO.System.IO.Abstractions.Wrappers" Version="20.0.4" />
|
||||
<PackageReference Include="xunit" Version="2.6.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.5">
|
||||
<PackageReference Include="xunit" Version="2.6.5" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
@ -292,6 +292,7 @@ public class MangaParserTests
|
||||
[InlineData("Accel World Chapter 001 Volume 002", "1")]
|
||||
[InlineData("Bleach 001-003", "1-3")]
|
||||
[InlineData("Accel World Volume 2", "0")]
|
||||
[InlineData("Historys Strongest Disciple Kenichi_v11_c90-98", "90-98")]
|
||||
public void ParseChaptersTest(string filename, string expected)
|
||||
{
|
||||
Assert.Equal(expected, API.Services.Tasks.Scanner.Parser.Parser.ParseChapter(filename));
|
||||
|
@ -53,7 +53,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@ -63,26 +63,26 @@
|
||||
<PackageReference Include="ExCSS" Version="4.2.4" />
|
||||
<PackageReference Include="Flurl" Version="3.0.7" />
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
<PackageReference Include="Hangfire" Version="1.8.6" />
|
||||
<PackageReference Include="Hangfire" Version="1.8.7" />
|
||||
<PackageReference Include="Hangfire.InMemory" Version="0.6.0" />
|
||||
<PackageReference Include="Hangfire.MaximumConcurrentExecutions" Version="1.1.0" />
|
||||
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
||||
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.3.4" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
|
||||
<PackageReference Include="Hangfire.Storage.SQLite" Version="0.4.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.57" />
|
||||
<PackageReference Include="MarkdownDeep.NET.Core" Version="1.5.0.4" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.6" />
|
||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
|
||||
<PackageReference Include="MimeTypeMapOfficial" Version="1.0.17" />
|
||||
<PackageReference Include="Nager.ArticleNumber" Version="1.0.7" />
|
||||
<PackageReference Include="NetVips" Version="2.4.0" />
|
||||
<PackageReference Include="NetVips.Native" Version="8.15.0" />
|
||||
<PackageReference Include="NReco.Logging.File" Version="1.1.7" />
|
||||
<PackageReference Include="NReco.Logging.File" Version="1.2.0" />
|
||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.2.0-dev-00752" />
|
||||
@ -92,17 +92,17 @@
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.SignalR.Core" Version="0.1.2" />
|
||||
<PackageReference Include="SharpCompress" Version="0.34.2" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.1" />
|
||||
<PackageReference Include="SharpCompress" Version="0.35.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.15.0.81779">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.12" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
|
||||
<PackageReference Include="System.IO.Abstractions" Version="20.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.1" />
|
||||
<PackageReference Include="VersOne.Epub" Version="3.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -39,22 +39,27 @@ public class ScrobblingController : BaseApiController
|
||||
_localizationService = localizationService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current user's AniList token
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("anilist-token")]
|
||||
public async Task<ActionResult> GetAniListToken()
|
||||
{
|
||||
// Validate the license
|
||||
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
return Ok(user.AniListAccessToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current user's AniList token
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("update-anilist-token")]
|
||||
public async Task<ActionResult> UpdateAniListToken(AniListUpdateDto dto)
|
||||
{
|
||||
// Validate the license
|
||||
|
||||
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
|
||||
if (user == null) return Unauthorized();
|
||||
|
||||
@ -71,6 +76,11 @@ public class ScrobblingController : BaseApiController
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current Scrobbling token for the given Provider has expired for the current user
|
||||
/// </summary>
|
||||
/// <param name="provider"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("token-expired")]
|
||||
public async Task<ActionResult<bool>> HasTokenExpired(ScrobbleProvider provider)
|
||||
{
|
||||
@ -159,15 +169,20 @@ public class ScrobblingController : BaseApiController
|
||||
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(User.GetUserId(), AppUserIncludes.ScrobbleHolds);
|
||||
if (user == null) return Unauthorized();
|
||||
if (user.ScrobbleHolds.Any(s => s.SeriesId == seriesId))
|
||||
return Ok(await _localizationService.Translate(User.GetUserId(), "nothing-to-do"));
|
||||
return Ok(await _localizationService.Translate(user.Id, "nothing-to-do"));
|
||||
|
||||
var seriesHold = new ScrobbleHoldBuilder().WithSeriesId(seriesId).Build();
|
||||
var seriesHold = new ScrobbleHoldBuilder()
|
||||
.WithSeriesId(seriesId)
|
||||
.Build();
|
||||
user.ScrobbleHolds.Add(seriesHold);
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
try
|
||||
{
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
await _unitOfWork.CommitAsync();
|
||||
|
||||
// When a hold is placed on a series, clear any pre-existing Scrobble Events
|
||||
await _scrobblingService.ClearEventsForSeries(user.Id, seriesId);
|
||||
return Ok();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException ex)
|
||||
|
@ -27,7 +27,7 @@ public interface IScrobbleRepository
|
||||
Task ClearScrobbleErrors();
|
||||
Task<bool> HasErrorForSeries(int seriesId);
|
||||
Task<ScrobbleEvent?> GetEvent(int userId, int seriesId, ScrobbleEventType eventType);
|
||||
Task<IEnumerable<ScrobbleEventDto>> GetUserEvents(int userId);
|
||||
Task<IEnumerable<ScrobbleEvent>> GetUserEventsForSeries(int userId, int seriesId);
|
||||
Task<PagedList<ScrobbleEventDto>> GetUserEvents(int userId, ScrobbleEventFilter filter, UserParams pagination);
|
||||
}
|
||||
|
||||
@ -127,16 +127,17 @@ public class ScrobbleRepository : IScrobbleRepository
|
||||
return await _context.ScrobbleEvent.FirstOrDefaultAsync(e =>
|
||||
e.AppUserId == userId && e.SeriesId == seriesId && e.ScrobbleEventType == eventType);
|
||||
}
|
||||
public async Task<IEnumerable<ScrobbleEventDto>> GetUserEvents(int userId)
|
||||
|
||||
public async Task<IEnumerable<ScrobbleEvent>> GetUserEventsForSeries(int userId, int seriesId)
|
||||
{
|
||||
return await _context.ScrobbleEvent
|
||||
.Where(e => e.AppUserId == userId)
|
||||
.Where(e => e.AppUserId == userId && !e.IsProcessed)
|
||||
.Include(e => e.Series)
|
||||
.OrderBy(e => e.LastModifiedUtc)
|
||||
.AsSplitQuery()
|
||||
.ProjectTo<ScrobbleEventDto>(_mapper.ConfigurationProvider)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<PagedList<ScrobbleEventDto>> GetUserEvents(int userId, ScrobbleEventFilter filter, UserParams pagination)
|
||||
{
|
||||
var query = _context.ScrobbleEvent
|
||||
@ -146,6 +147,7 @@ public class ScrobbleRepository : IScrobbleRepository
|
||||
.WhereIf(!string.IsNullOrEmpty(filter.Query), s =>
|
||||
EF.Functions.Like(s.Series.Name, $"%{filter.Query}%")
|
||||
)
|
||||
.WhereIf(!filter.IncludeReviews, e => e.ScrobbleEventType != ScrobbleEventType.Review)
|
||||
.AsSplitQuery()
|
||||
.ProjectTo<ScrobbleEventDto>(_mapper.ConfigurationProvider);
|
||||
|
||||
|
@ -15,4 +15,8 @@ public class ScrobbleEventFilter
|
||||
/// A query to search against
|
||||
/// </summary>
|
||||
public string Query { get; set; }
|
||||
/// <summary>
|
||||
/// Include reviews in the result - Note: Review Scrobbling is disabled
|
||||
/// </summary>
|
||||
public bool IncludeReviews { get; set; } = false;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ public interface IScrobblingService
|
||||
[AutomaticRetry(Attempts = 3, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||
Task ProcessUpdatesSinceLastSync();
|
||||
Task CreateEventsFromExistingHistory(int userId = 0);
|
||||
Task ClearEventsForSeries(int userId, int seriesId);
|
||||
}
|
||||
|
||||
public class ScrobblingService : IScrobblingService
|
||||
@ -542,6 +543,26 @@ public class ScrobblingService : IScrobblingService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all events (active) that are tied to a now-on hold series
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="seriesId"></param>
|
||||
public async Task ClearEventsForSeries(int userId, int seriesId)
|
||||
{
|
||||
_logger.LogInformation("Clearing Pre-existing Scrobble events for Series {SeriesId} by User {UserId} as Series is now on hold list", seriesId, userId);
|
||||
var events = await _unitOfWork.ScrobbleRepository.GetUserEventsForSeries(userId, seriesId);
|
||||
foreach (var scrobble in events)
|
||||
{
|
||||
_unitOfWork.ScrobbleRepository.Remove(scrobble);
|
||||
}
|
||||
|
||||
await _unitOfWork.CommitAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all events that have been processed that are 7 days old
|
||||
/// </summary>
|
||||
[DisableConcurrentExecution(60 * 60 * 60)]
|
||||
[AutomaticRetry(Attempts = 3, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
||||
public async Task ClearProcessedEvents()
|
||||
@ -594,10 +615,10 @@ public class ScrobblingService : IScrobblingService
|
||||
.Where(e => librariesWithScrobbling.Contains(e.LibraryId))
|
||||
.Where(e => !errors.Contains(e.SeriesId))
|
||||
.ToList();
|
||||
var reviewEvents = (await _unitOfWork.ScrobbleRepository.GetByEvent(ScrobbleEventType.Review))
|
||||
.Where(e => librariesWithScrobbling.Contains(e.LibraryId))
|
||||
.Where(e => !errors.Contains(e.SeriesId))
|
||||
.ToList();
|
||||
// var reviewEvents = (await _unitOfWork.ScrobbleRepository.GetByEvent(ScrobbleEventType.Review))
|
||||
// .Where(e => librariesWithScrobbling.Contains(e.LibraryId))
|
||||
// .Where(e => !errors.Contains(e.SeriesId))
|
||||
// .ToList();
|
||||
var decisions = addToWantToRead
|
||||
.GroupBy(item => new { item.SeriesId, item.AppUserId })
|
||||
.Select(group => new
|
||||
@ -624,7 +645,7 @@ public class ScrobblingService : IScrobblingService
|
||||
await SetAndCheckRateLimit(userRateLimits, user, license.Value);
|
||||
}
|
||||
|
||||
var totalProgress = readEvents.Count + decisions.Count + ratingEvents.Count + decisions.Count + reviewEvents.Count;
|
||||
var totalProgress = readEvents.Count + decisions.Count + ratingEvents.Count + decisions.Count;// + reviewEvents.Count;
|
||||
|
||||
_logger.LogInformation("Found {TotalEvents} Scrobble Events", totalProgress);
|
||||
try
|
||||
@ -671,21 +692,21 @@ public class ScrobblingService : IScrobblingService
|
||||
Year = evt.Series.Metadata.ReleaseYear
|
||||
}));
|
||||
|
||||
progressCounter = await ProcessEvents(reviewEvents, userRateLimits, usersToScrobble.Count, progressCounter,
|
||||
totalProgress, evt => Task.FromResult(new ScrobbleDto()
|
||||
{
|
||||
Format = evt.Format,
|
||||
AniListId = evt.AniListId,
|
||||
MALId = (int?) evt.MalId,
|
||||
ScrobbleEventType = evt.ScrobbleEventType,
|
||||
AniListToken = evt.AppUser.AniListAccessToken,
|
||||
SeriesName = evt.Series.Name,
|
||||
LocalizedSeriesName = evt.Series.LocalizedName,
|
||||
Rating = evt.Rating,
|
||||
Year = evt.Series.Metadata.ReleaseYear,
|
||||
ReviewBody = evt.ReviewBody,
|
||||
ReviewTitle = evt.ReviewTitle
|
||||
}));
|
||||
// progressCounter = await ProcessEvents(reviewEvents, userRateLimits, usersToScrobble.Count, progressCounter,
|
||||
// totalProgress, evt => Task.FromResult(new ScrobbleDto()
|
||||
// {
|
||||
// Format = evt.Format,
|
||||
// AniListId = evt.AniListId,
|
||||
// MALId = (int?) evt.MalId,
|
||||
// ScrobbleEventType = evt.ScrobbleEventType,
|
||||
// AniListToken = evt.AppUser.AniListAccessToken,
|
||||
// SeriesName = evt.Series.Name,
|
||||
// LocalizedSeriesName = evt.Series.LocalizedName,
|
||||
// Rating = evt.Rating,
|
||||
// Year = evt.Series.Metadata.ReleaseYear,
|
||||
// ReviewBody = evt.ReviewBody,
|
||||
// ReviewTitle = evt.ReviewTitle
|
||||
// }));
|
||||
|
||||
progressCounter = await ProcessEvents(decisions, userRateLimits, usersToScrobble.Count, progressCounter,
|
||||
totalProgress, evt => Task.FromResult(new ScrobbleDto()
|
||||
|
@ -49,6 +49,7 @@ public class DefaultParser : IDefaultParser
|
||||
// If library type is Image or this is not a cover image in a non-image library, then use dedicated parsing mechanism
|
||||
if (type == LibraryType.Image || Parser.IsImage(filePath))
|
||||
{
|
||||
// TODO: We can move this up one level
|
||||
return ParseImage(filePath, rootPath, ret);
|
||||
}
|
||||
|
||||
@ -78,7 +79,7 @@ public class DefaultParser : IDefaultParser
|
||||
var edition = Parser.ParseEdition(fileName);
|
||||
if (!string.IsNullOrEmpty(edition))
|
||||
{
|
||||
ret.Series = Parser.CleanTitle(ret.Series.Replace(edition, ""), type is LibraryType.Comic);
|
||||
ret.Series = Parser.CleanTitle(ret.Series.Replace(edition, string.Empty), type is LibraryType.Comic);
|
||||
ret.Edition = edition;
|
||||
}
|
||||
|
||||
|
@ -543,7 +543,7 @@ public static class Parser
|
||||
{
|
||||
// Historys Strongest Disciple Kenichi_v11_c90-98.zip, ...c90.5-100.5
|
||||
new Regex(
|
||||
@"(\b|_)(c|ch)(\.?\s?)(?<Chapter>(\d+(\.\d)?)-?(\d+(\.\d)?)?)",
|
||||
@"(\b|_)(c|ch)(\.?\s?)(?<Chapter>(\d+(\.\d)?)(-\d+(\.\d)?)?)",
|
||||
MatchOptions, RegexTimeout),
|
||||
// [Suihei Kiki]_Kasumi_Otoko_no_Ko_[Taruby]_v1.1.zip
|
||||
new Regex(
|
||||
|
@ -14,7 +14,7 @@
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.15.0.81779">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.16.0.82469">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
636
UI/Web/package-lock.json
generated
636
UI/Web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,17 +13,17 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^17.0.6",
|
||||
"@angular/animations": "^17.0.8",
|
||||
"@angular/cdk": "^17.0.4",
|
||||
"@angular/common": "^17.0.6",
|
||||
"@angular/compiler": "^17.0.6",
|
||||
"@angular/core": "^17.0.6",
|
||||
"@angular/forms": "^17.0.6",
|
||||
"@angular/localize": "^17.0.6",
|
||||
"@angular/platform-browser": "^17.0.6",
|
||||
"@angular/platform-browser-dynamic": "^17.0.6",
|
||||
"@angular/router": "^17.0.6",
|
||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||
"@angular/common": "^17.0.8",
|
||||
"@angular/compiler": "^17.0.8",
|
||||
"@angular/core": "^17.0.8",
|
||||
"@angular/forms": "^17.0.8",
|
||||
"@angular/localize": "^17.0.8",
|
||||
"@angular/platform-browser": "^17.0.8",
|
||||
"@angular/platform-browser-dynamic": "^17.0.8",
|
||||
"@angular/router": "^17.0.8",
|
||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||
"@iharbeck/ngx-virtual-scroller": "^17.0.0",
|
||||
"@iplab/ngx-file-upload": "^17.0.0",
|
||||
"@microsoft/signalr": "^7.0.12",
|
||||
@ -42,7 +42,7 @@
|
||||
"luxon": "^3.4.4",
|
||||
"ng-circle-progress": "^1.7.1",
|
||||
"ng-lazyload-image": "^9.1.3",
|
||||
"ng-select2-component": "^13.0.9",
|
||||
"ng-select2-component": "^14.0.0",
|
||||
"ngx-color-picker": "^16.0.0",
|
||||
"ngx-extended-pdf-viewer": "^18.1.9",
|
||||
"ngx-file-drop": "^16.0.0",
|
||||
@ -58,17 +58,17 @@
|
||||
"zone.js": "^0.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^17.0.7",
|
||||
"@angular-eslint/builder": "^17.1.1",
|
||||
"@angular-eslint/eslint-plugin": "^17.1.1",
|
||||
"@angular-eslint/eslint-plugin-template": "^17.1.1",
|
||||
"@angular-eslint/schematics": "^17.1.1",
|
||||
"@angular-eslint/template-parser": "^17.1.1",
|
||||
"@angular/cli": "^17.0.7",
|
||||
"@angular/compiler-cli": "^17.0.6",
|
||||
"@angular-devkit/build-angular": "^17.0.9",
|
||||
"@angular-eslint/builder": "^17.2.0",
|
||||
"@angular-eslint/eslint-plugin": "^17.2.0",
|
||||
"@angular-eslint/eslint-plugin-template": "^17.2.0",
|
||||
"@angular-eslint/schematics": "^17.2.0",
|
||||
"@angular-eslint/template-parser": "^17.2.0",
|
||||
"@angular/cli": "^17.0.9",
|
||||
"@angular/compiler-cli": "^17.0.8",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/luxon": "^3.3.7",
|
||||
"@types/luxon": "^3.4.0",
|
||||
"@types/node": "^20.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
||||
"@typescript-eslint/parser": "^6.13.0",
|
||||
|
@ -6,6 +6,8 @@ import {environment} from "../../environments/environment";
|
||||
import {SideNavStream} from "../_models/sidenav/sidenav-stream";
|
||||
import {TextResonse} from "../_types/text-response";
|
||||
import {DashboardStream} from "../_models/dashboard/dashboard-stream";
|
||||
import {AccountService} from "./account.service";
|
||||
import {tap} from "rxjs/operators";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -34,9 +36,16 @@ export class NavService {
|
||||
private renderer: Renderer2;
|
||||
baseUrl = environment.apiUrl;
|
||||
|
||||
constructor(@Inject(DOCUMENT) private document: Document, rendererFactory: RendererFactory2, private httpClient: HttpClient) {
|
||||
constructor(@Inject(DOCUMENT) private document: Document, rendererFactory: RendererFactory2, private httpClient: HttpClient, private accountService: AccountService) {
|
||||
this.renderer = rendererFactory.createRenderer(null, null);
|
||||
|
||||
// To avoid flashing, let's check if we are authenticated before we show
|
||||
this.accountService.currentUser$.subscribe(u => {
|
||||
if (u) {
|
||||
this.showNavBar();
|
||||
}
|
||||
});
|
||||
|
||||
const sideNavState = (localStorage.getItem(this.localStorageSideNavKey) === 'true') || false;
|
||||
this.sideNavCollapseSource.next(sideNavState);
|
||||
this.showSideNav();
|
||||
|
@ -84,12 +84,19 @@ export class BookLineOverlayComponent implements OnInit {
|
||||
const selection = window.getSelection();
|
||||
if (!event.target) return;
|
||||
|
||||
|
||||
|
||||
if ((selection === null || selection === undefined || selection.toString().trim() === '' || selection.toString().trim() === this.selectedText)) {
|
||||
if (this.selectedText !== '') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
const isRightClick = (event instanceof MouseEvent && event.button === 2);
|
||||
if (!isRightClick) {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
|
||||
import { Validators, FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
@ -6,6 +6,7 @@ import { AccountService } from 'src/app/_services/account.service';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { SplashContainerComponent } from '../splash-container/splash-container.component';
|
||||
import {TranslocoDirective} from "@ngneat/transloco";
|
||||
import {NavService} from "../../../_services/nav.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-reset-password',
|
||||
@ -17,12 +18,19 @@ import {TranslocoDirective} from "@ngneat/transloco";
|
||||
})
|
||||
export class ResetPasswordComponent {
|
||||
|
||||
private readonly router = inject(Router);
|
||||
private readonly accountService = inject(AccountService);
|
||||
private readonly toastr = inject(ToastrService);
|
||||
private readonly navService = inject(NavService);
|
||||
|
||||
registerForm: FormGroup = new FormGroup({
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
});
|
||||
|
||||
constructor(private router: Router, private accountService: AccountService,
|
||||
private toastr: ToastrService) {}
|
||||
constructor() {
|
||||
this.navService.hideNavBar();
|
||||
this.navService.hideSideNav();
|
||||
}
|
||||
|
||||
submit() {
|
||||
const model = this.registerForm.get('email')?.value;
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="mx-auto login">
|
||||
<div class="mx-auto login" [ngStyle]="{'height': (navService.navbarVisible$ | async) ? 'calc(var(--vh, 1vh) * 100 - 57px)' : 'calc(var(--vh, 1vh) * 100)'}">
|
||||
|
||||
<div class="row row-cols-4 row-cols-md-4 row-cols-sm-2 row-cols-xs-2">
|
||||
<div class="col align-self-center card p-3">
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
|
||||
import {AsyncPipe, NgStyle} from "@angular/common";
|
||||
import {NavService} from "../../../_services/nav.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-splash-container',
|
||||
templateUrl: './splash-container.component.html',
|
||||
styleUrls: ['./splash-container.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
NgStyle,
|
||||
AsyncPipe
|
||||
],
|
||||
standalone: true
|
||||
})
|
||||
export class SplashContainerComponent {}
|
||||
export class SplashContainerComponent {
|
||||
protected readonly navService = inject(NavService);
|
||||
}
|
||||
|
@ -26,6 +26,4 @@ export class UserHoldsComponent {
|
||||
private readonly scrobblingService = inject(ScrobblingService);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
holds$ = this.scrobblingService.getHolds().pipe(takeUntilDestroyed(this.destroyRef), shareReplay());
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
@ -7335,6 +7335,7 @@
|
||||
"tags": [
|
||||
"Scrobbling"
|
||||
],
|
||||
"summary": "Get the current user's AniList token",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success"
|
||||
@ -7347,7 +7348,9 @@
|
||||
"tags": [
|
||||
"Scrobbling"
|
||||
],
|
||||
"summary": "Update the current user's AniList token",
|
||||
"requestBody": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
@ -7378,10 +7381,12 @@
|
||||
"tags": [
|
||||
"Scrobbling"
|
||||
],
|
||||
"summary": "Checks if the current Scrobbling token for the given Provider has expired for the current user",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "provider",
|
||||
"in": "query",
|
||||
"description": "",
|
||||
"schema": {
|
||||
"enum": [
|
||||
0,
|
||||
@ -17178,6 +17183,10 @@
|
||||
"type": "string",
|
||||
"description": "A query to search against",
|
||||
"nullable": true
|
||||
},
|
||||
"includeReviews": {
|
||||
"type": "boolean",
|
||||
"description": "Include reviews in the result - Note: Review Scrobbling is disabled"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
Loading…
x
Reference in New Issue
Block a user