mirror of
https://github.com/Kareadita/Kavita.git
synced 2026-05-30 19:35:21 -04:00
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:
@@ -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>
|
||||
@@ -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,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs.Account;
|
||||
|
||||
+12
-2
@@ -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,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; }
|
||||
}
|
||||
+3
-3
@@ -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; }
|
||||
}
|
||||
+2
-2
@@ -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!;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace API.DTOs.Device;
|
||||
|
||||
public sealed record SendSeriesToDeviceDto
|
||||
{
|
||||
public int DeviceId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
}
|
||||
@@ -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,4 +1,3 @@
|
||||
using System;
|
||||
using API.Entities.Enums.Font;
|
||||
|
||||
namespace API.DTOs.Font;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using API.DTOs.KavitaPlus.Metadata;
|
||||
|
||||
namespace API.DTOs;
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
using System;
|
||||
using System.Xml.Serialization;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace API.DTOs.OPDS;
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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,5 +1,4 @@
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Metadata;
|
||||
using API.Services.Plus;
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
using System;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.DTOs.ReadingLists;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using API.DTOs.Reader;
|
||||
using API.Entities.Interfaces;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.DTOs.ReadingLists;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using API.DTOs.Recommendation;
|
||||
|
||||
namespace API.DTOs.Scrobbling;
|
||||
#nullable enable
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using API.DTOs.Person;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs;
|
||||
#nullable enable
|
||||
|
||||
public sealed record SeriesMetadataDto
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using API.Entities.Enums;
|
||||
using API.Services;
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace API.DTOs.SideNav;
|
||||
namespace API.DTOs.SideNav;
|
||||
|
||||
public sealed record ExternalSourceDto
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs.SideNav;
|
||||
#nullable enable
|
||||
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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>;
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace API.DTOs.Theme;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices.JavaScript;
|
||||
|
||||
namespace API.DTOs.Update;
|
||||
|
||||
|
||||
+20
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,4 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user