Progress Overhaul + Profile Page and a LOT more! (#4262)

Co-authored-by: Amelia <77553571+Fesaa@users.noreply.github.com>
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo
2025-12-09 10:00:11 -07:00
committed by GitHub
parent 4ac13f1f25
commit 9f29fa593d
645 changed files with 25585 additions and 4805 deletions
+30
View File
@@ -0,0 +1,30 @@
using System;
using API.Entities.Enums.User;
namespace API.DTOs.Account;
public sealed record AuthKeyDto
{
public int Id { get; set; }
/// <summary>
/// Actual key
/// </summary>
/// <remarks>This is a variable string length from [6-32] alphanumeric characters</remarks>
public required string Key { get; set; }
/// <summary>
/// Name of the key
/// </summary>
public required string Name { get; set; }
public DateTime CreatedAtUtc { get; set; }
/// <summary>
/// An Optional time which the Key expires
/// </summary>
public DateTime? ExpiresAtUtc { get; set; }
public DateTime? LastAccessedAt { get; set; }
/// <summary>
/// Kavita will have a short-lived key
/// </summary>
public AuthKeyProvider Provider { get; set; } = AuthKeyProvider.User;
}
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using API.DTOs.Account;
using API.Entities.Enums;
namespace API.DTOs;
namespace API.DTOs.Account;
#nullable enable
/// <summary>
+13
View File
@@ -0,0 +1,13 @@
using System;
namespace API.DTOs.Account;
#nullable enable
public sealed record MemberInfoDto
{
public int Id { get; set; }
public string Username { get; set; } = string.Empty;
public DateTime Created { get; set; }
public DateTime CreatedUtc { get; set; }
public string? CoverImage { get; set; }
}
@@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
using API.Helpers;
namespace API.DTOs.Account;
#nullable enable
public sealed record RotateAuthKeyRequestDto
{
[Required]
public int KeyLength { get; set; }
public required string Name { get; set; }
public string? ExpiresUtc { get; set; }
}
-1
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using API.Entities.Enums;
namespace API.DTOs.Account;
+12 -2
View File
@@ -38,10 +38,15 @@ public class ChapterDto : IHasReadTimeEstimate, IHasCoverImage
/// </summary>
public ICollection<MangaFileDto> Files { get; init; } = default!;
/// <summary>
/// Calculated at API time. Number of pages read for this Chapter for logged in user.
/// Calculated at API time. Number of pages read for this Chapter for logged-in user.
/// </summary>
public int PagesRead { get; set; }
/// <summary>
/// Total number of complete reads
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public int TotalReads { get; set; }
/// <summary>
/// The last time a chapter was read by current authenticated user
/// </summary>
public DateTime LastReadingProgressUtc { get; set; }
@@ -152,7 +157,12 @@ public class ChapterDto : IHasReadTimeEstimate, IHasCoverImage
public bool LocationLocked { get; set; }
/// <inheritdoc cref="API.Entities.Chapter.CoverArtistLocked"/>
public bool CoverArtistLocked { get; set; }
public bool ReleaseYearLocked { get; set; }
/// <inheritdoc cref="API.Entities.Chapter.ReleaseDateLocked"/>
public bool ReleaseDateLocked { get; set; }
/// <inheritdoc cref="API.Entities.Chapter.TitleNameLocked"/>
public bool TitleNameLocked { get; set; }
/// <inheritdoc cref="API.Entities.Chapter.SortOrderLocked"/>
public bool SortOrderLocked { get; set; }
#endregion
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using API.DTOs.Collection;
namespace API.DTOs.CollectionTags;
+1 -3
View File
@@ -1,6 +1,4 @@
using API.DTOs.Filtering.v2;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums;
namespace API.DTOs.Dashboard;
@@ -0,0 +1,7 @@
namespace API.DTOs.Device.ClientDevice;
public sealed record UpdateClientDeviceNameDto
{
public int DeviceId { get; set; }
public string Name { get; set; }
}
@@ -1,9 +1,9 @@
using System.ComponentModel.DataAnnotations;
using API.Entities.Enums.Device;
namespace API.DTOs.Device;
namespace API.DTOs.Device.EmailDevice;
public sealed record CreateDeviceDto
public sealed record CreateEmailDeviceDto
{
[Required]
public string Name { get; set; } = default!;
@@ -11,7 +11,7 @@ public sealed record CreateDeviceDto
/// Platform of the device. If not know, defaults to "Custom"
/// </summary>
[Required]
public DevicePlatform Platform { get; set; }
public EmailDevicePlatform Platform { get; set; }
[Required]
public string EmailAddress { get; set; } = default!;
@@ -1,12 +1,11 @@
using System;
using API.Entities.Enums.Device;
using API.Entities.Enums.Device;
namespace API.DTOs.Device;
namespace API.DTOs.Device.EmailDevice;
/// <summary>
/// A Device is an entity that can receive data from Kavita (kindle)
/// </summary>
public sealed record DeviceDto
public sealed record EmailDeviceDto
{
/// <summary>
/// The device Id
@@ -25,5 +24,5 @@ public sealed record DeviceDto
/// <summary>
/// Platform (ie) Windows 10
/// </summary>
public DevicePlatform Platform { get; set; }
public EmailDevicePlatform Platform { get; set; }
}
@@ -0,0 +1,7 @@
namespace API.DTOs.Device.EmailDevice;
public sealed record SendSeriesToEmailDeviceDto
{
public int DeviceId { get; set; }
public int SeriesId { get; set; }
}
@@ -1,8 +1,8 @@
using System.Collections.Generic;
namespace API.DTOs.Device;
namespace API.DTOs.Device.EmailDevice;
public sealed record SendToDeviceDto
public sealed record SendToEmailDeviceDto
{
public int DeviceId { get; set; }
public IReadOnlyList<int> ChapterIds { get; set; } = default!;
@@ -1,9 +1,9 @@
using System.ComponentModel.DataAnnotations;
using API.Entities.Enums.Device;
namespace API.DTOs.Device;
namespace API.DTOs.Device.EmailDevice;
public sealed record UpdateDeviceDto
public sealed record UpdateEmailDeviceDto
{
[Required]
public int Id { get; set; }
@@ -13,7 +13,7 @@ public sealed record UpdateDeviceDto
/// Platform of the device. If not know, defaults to "Custom"
/// </summary>
[Required]
public DevicePlatform Platform { get; set; }
public EmailDevicePlatform Platform { get; set; }
[Required]
public string EmailAddress { get; set; } = default!;
}
-7
View File
@@ -1,7 +0,0 @@
namespace API.DTOs.Device;
public sealed record SendSeriesToDeviceDto
{
public int DeviceId { get; set; }
public int SeriesId { get; set; }
}
+3 -1
View File
@@ -87,5 +87,7 @@ public enum AnnotationFilterField
/// This is the text the user wrote
/// </summary>
Comment = 6,
Series = 7
Series = 7,
Likes = 8,
LikedBy = 9,
}
-1
View File
@@ -1,4 +1,3 @@
using System;
using API.Entities.Enums.Font;
namespace API.DTOs.Font;
-1
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using API.DTOs.KavitaPlus.Metadata;
namespace API.DTOs;
+11
View File
@@ -0,0 +1,11 @@
namespace API.DTOs.Internal;
#nullable enable
public sealed record AppSettingsDto
{
public required string TokenKey { get; set; }
public int Port { get; set; }
public string? IpAddresses { get; set; }
public required string BaseUrl { get; set; }
public int Cache { get; set; }
}
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using API.DTOs.KavitaPlus.Metadata;
using API.DTOs.Recommendation;
using API.DTOs.Scrobbling;
using API.DTOs.SeriesDetail;
@@ -1,9 +1,7 @@
using System.Collections.Generic;
using API.DTOs.Settings;
using API.Entities;
using API.Entities.Enums;
using API.Entities.MetadataMatching;
using NotImplementedException = System.NotImplementedException;
namespace API.DTOs.KavitaPlus.Metadata;
@@ -1,6 +1,5 @@
using API.DTOs.Scrobbling;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Services.Plus;
namespace API.DTOs.KavitaPlus.Metadata;
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using API.DTOs.Filtering;
using API.DTOs.Filtering.v2;
using API.Entities.Enums;
namespace API.DTOs.Metadata.Browse.Requests;
#nullable enable
@@ -1,5 +1,4 @@
using API.DTOs.KavitaPlus.Metadata;
using API.DTOs.Recommendation;
namespace API.DTOs.Metadata.Matching;
+1 -2
View File
@@ -1,5 +1,4 @@
using System;
using System.Xml.Serialization;
using System.Xml.Serialization;
namespace API.DTOs.OPDS;
+23
View File
@@ -0,0 +1,23 @@
using System;
namespace API.DTOs.Progress;
public sealed record ClientDeviceDto
{
public int Id { get; set; }
/// <summary>
/// User-friendly name, defaults to generated name like "Chrome on Windows"
/// </summary>
public string FriendlyName { get; set; } = string.Empty;
/// <summary>
/// Most recent stable ClientInfoData (excluding IP/timestamp changes)
/// </summary>
public ClientInfoDto CurrentClientInfo { get; set; } = new();
public DateTime FirstSeenUtc { get; set; }
public DateTime LastSeenUtc { get; set; }
public string OwnerUsername { get; set; }
public int OwnerUserId { get; set; }
}
+70
View File
@@ -0,0 +1,70 @@
using API.Constants;
using API.Entities.Enums;
using API.Entities.Progress;
namespace API.DTOs.Progress;
#nullable enable
public sealed record ClientInfoDto
{
/// <summary>
/// Raw User-Agent string from request header
/// </summary>
public string UserAgent { get; set; } = string.Empty;
/// <summary>
/// Client IP address (respecting X-Forwarded-For if present)
/// </summary>
public string IpAddress { get; set; } = string.Empty;
/// <summary>
/// How the user authenticated (JWT token vs API key)
/// </summary>
public AuthenticationType AuthType { get; set; }
/// <summary>
/// Parsed client type from User-Agent or custom Kavita header
/// Examples: Web App, OPDS Reader, KOReader, Tachiyomi, etc.
/// </summary>
public ClientDeviceType ClientType { get; set; } = ClientDeviceType.Unknown;
/// <summary>
/// Application version (from web app or mobile app)
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// Browser name (Chrome, Firefox, Safari, Edge) - Web clients only
/// </summary>
public string? Browser { get; set; }
/// <summary>
/// Browser version - Web clients only
/// </summary>
public string? BrowserVersion { get; set; }
/// <summary>
/// Platform/OS (Windows, macOS, Linux, iOS, Android)
/// </summary>
public ClientDevicePlatform Platform { get; set; } = ClientDevicePlatform.Unknown;
/// <summary>
/// Device type (Desktop, Mobile, Tablet)
/// </summary>
public string? DeviceType { get; set; }
/// <summary>
/// Screen width in pixels - Web clients only
/// </summary>
public int? ScreenWidth { get; set; }
/// <summary>
/// Screen height in pixels - Web clients only
/// </summary>
public int? ScreenHeight { get; set; }
/// <summary>
/// Screen orientation (portrait, landscape) - Web clients only
/// </summary>
public string? Orientation { get; set; }
}
+13
View File
@@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace API.DTOs.Progress;
public class DailyReadingDataDto
{
public int TotalMinutesRead { get; set; }
public int TotalPagesRead { get; set; }
public int TotalWordsRead { get; set; }
public int LongestSessionMinutes { get; set; }
public IList<int> SeriesIds { get; set; }
public IList<int> ChapterIds { get; set; }
}
@@ -0,0 +1,29 @@
using System;
namespace API.DTOs.Progress;
#nullable enable
public sealed record ReadingActivityDataDto
{
public int ChapterId { get; set; }
public int VolumeId { get; set; }
public int SeriesId { get; set; }
public int LibraryId { get; set; }
public int StartPage { get; set; }
public int EndPage { get; set; }
public DateTime StartTimeUtc { get; set; }
public DateTime? EndTimeUtc { get; set; }
public int PagesRead { get; set; }
/// <summary>
/// Only applicable for Book entries
/// </summary>
public int WordsRead { get; set; }
public int TotalPages { get; set; }
public int TotalWords { get; set; }
public string LibraryName { get; set; }
public string SeriesName { get; set; }
public string ChapterTitle { get; set; }
public ClientInfoDto? ClientInfo { get; set; }
}
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace API.DTOs.Progress;
public sealed record ReadingSessionDto
{
public int Id { get; set; }
public DateTime StartTimeUtc { get; set; }
public DateTime? EndTimeUtc { get; set; }
public bool IsActive { get; set; } = true;
public IList<ReadingActivityDataDto> ActivityData { get; set; }
public int UserId { get; set; }
public string Username { get; set; }
}
+1 -2
View File
@@ -1,5 +1,4 @@
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Services.Plus;
+1 -1
View File
@@ -54,7 +54,7 @@ public sealed record AnnotationDto
public int SelectedSlotIndex { get; set; }
/// <inheritdoc cref="AppUserAnnotation.Likes"/>
public ISet<int> Likes { get; set; }
public IList<int> Likes { get; set; }
public string SeriesName { get; set; }
public string LibraryName { get; set; }
+1 -2
View File
@@ -1,5 +1,4 @@
using System;
using API.Entities.Enums;
using API.Entities.Enums;
using API.Entities.Interfaces;
namespace API.DTOs.ReadingLists;
+1 -2
View File
@@ -1,5 +1,4 @@
using API.DTOs.Reader;
using API.Entities.Interfaces;
using API.Entities.Interfaces;
namespace API.DTOs.ReadingLists;
-1
View File
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel;
using API.DTOs.Recommendation;
namespace API.DTOs.Scrobbling;
#nullable enable
-1
View File
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using API.DTOs.Collection;
using API.DTOs.CollectionTags;
using API.DTOs.Metadata;
using API.DTOs.Person;
using API.DTOs.Reader;
+5 -2
View File
@@ -1,5 +1,4 @@
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums;
using API.Services.Plus;
namespace API.DTOs.SeriesDetail;
@@ -37,6 +36,10 @@ public sealed record UserReviewDto
/// The user who wrote this
/// </summary>
public string Username { get; set; }
/// <summary>
/// UserId of the reviewer, only applicable for <see cref="ScrobbleProvider.Kavita"/>
/// </summary>
public int UserId { get; set; }
public int TotalVotes { get; set; }
public float Rating { get; set; }
public string? RawBody { get; set; }
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using API.DTOs.Person;
namespace API.DTOs.SeriesDetail;
#nullable enable
public sealed record UserReviewExtendedDto
{
public int Id { get; set; }
/// <summary>
/// The main review
/// </summary>
public string Body { get; set; }
/// <summary>
/// The series this is for
/// </summary>
public int SeriesId { get; set; }
public int? ChapterId { get; set; }
/// <summary>
/// The library this series belongs in
/// </summary>
public int LibraryId { get; set; }
/// <summary>
/// The user who wrote this
/// </summary>
public string Username { get; set; }
public float Rating { get; set; }
public SeriesDto Series { get; set; }
public ChapterDto? Chapter { get; set; }
public DateTime CreatedUtc { get; set; }
public ICollection<PersonDto> Writers { get; set; } = [];
}
+30 -9
View File
@@ -21,24 +21,41 @@ public sealed record SeriesDto : IHasReadTimeEstimate, IHasCoverImage
public int Pages { get; init; }
/// <inheritdoc cref="API.Entities.Series.CoverImageLocked"/>
public bool CoverImageLocked { get; set; }
/// <summary>
/// Sum of pages read from linked Volumes. Calculated at API-time.
/// </summary>
public int PagesRead { get; set; }
/// <summary>
/// DateTime representing last time the series was Read. Calculated at API-time.
/// </summary>
public DateTime LatestReadDate { get; set; }
/// <inheritdoc cref="API.Entities.Series.LastChapterAdded"/>
public DateTime LastChapterAdded { get; set; }
/// <inheritdoc cref="API.Entities.Series.LastChapterAddedUtc"/>
public DateTime LastChapterAddedUtc { get; set; }
#region Progress (applied on the fly)
/// <summary>
/// Rating from logged in user. Calculated at API-time.
/// Rating from logged-in user
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public float UserRating { get; set; }
/// <summary>
/// If the user has set the rating or not
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public bool HasUserRated { get; set; }
/// <summary>
/// Min <see cref="ChapterDto.TotalReads"/> across the series
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public int TotalReads { get; set; }
/// <summary>
/// Sum of pages read from linked Volumes. Calculated at API-time.
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public int PagesRead { get; set; }
/// <summary>
/// DateTime representing last time the series was Read. Calculated at API-time.
/// </summary>
/// <remarks>Calculated at API-time</remarks>
public DateTime LatestReadDate { get; set; }
#endregion
/// <inheritdoc cref="API.Entities.Series.Format"/>
public MangaFormat Format { get; set; }
@@ -74,16 +91,20 @@ public sealed record SeriesDto : IHasReadTimeEstimate, IHasCoverImage
public bool IsBlacklisted { get; set; }
#endregion
#region ColorScape
/// <inheritdoc cref="API.Entities.Series.CoverImage"/>
public string? CoverImage { get; set; }
/// <inheritdoc cref="API.Entities.Series.PrimaryColor"/>
public string? PrimaryColor { get; set; } = string.Empty;
/// <inheritdoc cref="API.Entities.Series.SecondaryColor"/>
public string? SecondaryColor { get; set; } = string.Empty;
#endregion
public void ResetColorScape()
{
PrimaryColor = string.Empty;
SecondaryColor = string.Empty;
}
}
+1
View File
@@ -4,6 +4,7 @@ using API.DTOs.Person;
using API.Entities.Enums;
namespace API.DTOs;
#nullable enable
public sealed record SeriesMetadataDto
{
-1
View File
@@ -1,5 +1,4 @@
using System;
using System.Text.Json.Serialization;
using API.Entities.Enums;
using API.Services;
+1 -3
View File
@@ -1,6 +1,4 @@
using System;
namespace API.DTOs.SideNav;
namespace API.DTOs.SideNav;
public sealed record ExternalSourceDto
{
-1
View File
@@ -1,5 +1,4 @@
using API.Entities;
using API.Entities.Enums;
namespace API.DTOs.SideNav;
#nullable enable
+14
View File
@@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace API.DTOs.Statistics;
public sealed record BreakDownDto<T>
{
public IList<StatCount<T>> Data { get; set; }
public int Total { get; set; }
public int TotalOptions { get; set; }
public int Missing { get; set; }
}
+23
View File
@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace API.DTOs.Statistics;
public sealed record MostReadAuthorsDto
{
public int AuthorId { get; init; }
public string AuthorName { get; init; }
public int TotalChaptersRead { get; init; }
public IList<AuthorChapterDto> Chapters { get; init; }
}
public sealed record AuthorChapterDto
{
public int LibraryId { get; set; }
public int SeriesId { get; set; }
public int ChapterId { get; set; }
public string Title { get; set; }
}
+12
View File
@@ -0,0 +1,12 @@
namespace API.DTOs.Statistics;
public sealed record ProfileStatBarDto
{
public int BooksRead { get; set; }
public int ComicsRead { get; set; }
public int PagesRead { get; set; }
public int WordsRead { get; set; }
public int AuthorsRead { get; set; }
public int Reviews { get; set; }
public int Ratings { get; set; }
}
+12
View File
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace API.DTOs.Statistics;
public sealed record ReadTimeByHourDto
{
public DateTime DataSince { get; init; }
public IList<StatCount<int>> Stats { get; init; }
}
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
namespace API.DTOs.Statistics;
#nullable enable
public sealed record ReadingActivityGraphEntryDto
{
public DateTime Date { get; set; }
public int TotalTimeReadingSeconds { get; set; }
public int TotalPages { get; set; }
public int TotalWords { get; set; }
public int TotalChaptersFullyRead { get; set; }
}
public class ReadingActivityGraphDto : Dictionary<string, ReadingActivityGraphEntryDto>;
+11
View File
@@ -0,0 +1,11 @@
namespace API.DTOs.Statistics;
public sealed record ReadingPaceDto
{
public int HoursRead { get; set; }
public int PagesRead { get; set; }
public int WordsRead { get; set; }
public int BooksRead { get; set; }
public int ComicsRead { get; set; }
public int DaysInRange { get; set; }
}
+9
View File
@@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace API.DTOs.Statistics;
public sealed record SpreadStatsDto
{
public List<StatBucketDto> Buckets { get; set; }
public int TotalCount { get; set; }
}
+20
View File
@@ -0,0 +1,20 @@
namespace API.DTOs.Statistics;
/// <summary>
/// A bucket of items (fixed) from 0-X, X-X*2
/// </summary>
public sealed record StatBucketDto
{
public int RangeStart { get; set; }
/// <summary>
/// Null for the last range (1000+)
/// </summary>
public int? RangeEnd { get; set; }
public int Count { get; set; }
/// <summary>
/// Percentage of total chapters
/// </summary>
public decimal Percentage { get; set; }
}
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace API.DTOs.Statistics;
public sealed record StatsFilterDto
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate
{
get;
set => field = value == null || value == DateTime.MinValue ? DateTime.MaxValue : value;
}
private IList<int>? _libraries;
public IList<int> Libraries
{
get => _libraries ?? [];
set => _libraries = value;
}
}
@@ -0,0 +1,7 @@
namespace API.DTOs.Statistics;
public sealed record YearMonthGroupingDto
{
public int Year { get; set; }
public int Month { get; set; }
}
@@ -0,0 +1,11 @@
using System.Collections.Generic;
using API.DTOs.Statistics;
using API.Entities.Enums;
namespace API.DTOs.Stats.V3.ClientDevice;
public sealed record DeviceClientBreakdownDto
{
public IList<StatCount<ClientDeviceType>> Records { get; set; }
public int TotalCount { get; set; }
}
+1 -1
View File
@@ -72,7 +72,7 @@ public sealed record UserStatV3
/// <summary>
/// The number of devices setup and their platforms
/// </summary>
public ICollection<DevicePlatform> DevicePlatforms { get; set; }
public ICollection<EmailDevicePlatform> DevicePlatforms { get; set; }
/// <summary>
/// Roles for this user
/// </summary>
+1 -2
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
namespace API.DTOs.Theme;
-1
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Runtime.InteropServices.JavaScript;
namespace API.DTOs.Update;
+20 -1
View File
@@ -1,13 +1,17 @@
using System;
using System.Collections.Generic;
using API.DTOs.Account;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums.User;
using API.Entities.Interfaces;
using NotImplementedException = System.NotImplementedException;
namespace API.DTOs;
#nullable enable
public sealed record UserDto
public sealed record UserDto : IHasCoverImage
{
public int Id { get; init; }
public string Username { get; init; } = null!;
@@ -21,4 +25,19 @@ public sealed record UserDto
public string KavitaVersion { get; set; }
/// <inheritdoc cref="AppUser.IdentityProvider"/>
public IdentityProvider IdentityProvider { get; init; }
public DateTime Created { get; set; }
public DateTime CreatedUtc { get; set; }
/// <summary>
/// Only System-provided Auth Keys
/// </summary>
public ICollection<AuthKeyDto> AuthKeys { get; set; }
public string? CoverImage { get; set; }
public string? PrimaryColor { get; set; }
public string? SecondaryColor { get; set; }
public void ResetColorScape()
{
PrimaryColor = string.Empty;
SecondaryColor = string.Empty;
}
}
+15 -12
View File
@@ -2,8 +2,8 @@
using System.ComponentModel.DataAnnotations;
using API.DTOs.Theme;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Enums.UserPreferences;
using API.Entities.User;
namespace API.DTOs;
#nullable enable
@@ -19,36 +19,39 @@ public sealed record UserPreferencesDto
public SiteThemeDto? Theme { get; set; }
public PageLayoutMode GlobalPageLayoutMode { get; set; } = PageLayoutMode.Cards;
/// <inheritdoc cref="API.Entities.AppUserPreferences.BlurUnreadSummaries"/>
/// <inheritdoc cref="AppUserPreferences.BlurUnreadSummaries"/>
[Required]
public bool BlurUnreadSummaries { get; set; } = false;
/// <inheritdoc cref="API.Entities.AppUserPreferences.PromptForDownloadSize"/>
/// <inheritdoc cref="AppUserPreferences.PromptForDownloadSize"/>
[Required]
public bool PromptForDownloadSize { get; set; } = true;
/// <inheritdoc cref="API.Entities.AppUserPreferences.NoTransitions"/>
/// <inheritdoc cref="AppUserPreferences.NoTransitions"/>
[Required]
public bool NoTransitions { get; set; } = false;
/// <inheritdoc cref="API.Entities.AppUserPreferences.CollapseSeriesRelationships"/>
/// <inheritdoc cref="AppUserPreferences.CollapseSeriesRelationships"/>
[Required]
public bool CollapseSeriesRelationships { get; set; } = false;
/// <inheritdoc cref="API.Entities.AppUserPreferences.Locale"/>
/// <inheritdoc cref="AppUserPreferences.Locale"/>
[Required]
public string Locale { get; set; }
/// <inheritdoc cref="API.Entities.AppUserPreferences.ColorScapeEnabled"/>
/// <inheritdoc cref="AppUserPreferences.ColorScapeEnabled"/>
[Required]
public bool ColorScapeEnabled { get; set; } = true;
/// <inheritdoc cref="API.Entities.AppUserPreferences.DataSaver"/>
/// <inheritdoc cref="AppUserPreferences.DataSaver"/>
[Required]
public bool DataSaver { get; set; } = false;
/// <inheritdoc cref="API.Entities.AppUserPreferences.CustomKeyBinds"/>
/// <inheritdoc cref="AppUserPreferences.PromptForRereadsAfter"/>
[Required]
public int PromptForRereadsAfter { get; set; }
/// <inheritdoc cref="AppUserPreferences.CustomKeyBinds"/>
[Required]
public Dictionary<KeyBindTarget, IList<KeyBind>> CustomKeyBinds { get; set; } = [];
/// <inheritdoc cref="API.Entities.AppUserPreferences.AniListScrobblingEnabled"/>
/// <inheritdoc cref="AppUserPreferences.AniListScrobblingEnabled"/>
public bool AniListScrobblingEnabled { get; set; }
/// <inheritdoc cref="API.Entities.AppUserPreferences.WantToReadSync"/>
/// <inheritdoc cref="AppUserPreferences.WantToReadSync"/>
public bool WantToReadSync { get; set; }
/// <inheritdoc cref="API.Entities.AppUserPreferences.BookReaderHighlightSlots"/>
/// <inheritdoc cref="AppUserPreferences.BookReaderHighlightSlots"/>
[Required]
public List<HighlightSlot> BookReaderHighlightSlots { get; set; }
-1
View File
@@ -1,4 +1,3 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using API.Entities;
using API.Entities.Enums;
-1
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using API.Entities;
using API.Entities.Interfaces;
using API.Extensions;
using API.Services.Tasks.Scanner.Parser;