Enhance video library management in PLib by introducing folder change tracking and improving video item metadata handling. Update IVideoRepository to include a method for loading video items with labels. Revise VideoPlayerViewModel to manage playback progress and integrate new UI elements for displaying watched status and resume options. Update MainWindowViewModel to observe folder changes for automatic rescanning. Enhance README.md to document these new features and usage instructions.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
namespace PLib.Domain.Videos;
|
||||
|
||||
/// <summary>What a label is for; the relation to videos is identical either way.</summary>
|
||||
public enum LabelKind
|
||||
{
|
||||
/// <summary>A free-form word used to narrow the grid down.</summary>
|
||||
Tag,
|
||||
|
||||
/// <summary>A named group the user curates and browses as a whole.</summary>
|
||||
Collection,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A named grouping of videos — a tag or a collection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Tags and collections are the same relation: a name, many videos, a video in many of them.
|
||||
/// They differ only in intent, and that intent is <see cref="Kind"/>. One entity means one
|
||||
/// join table, one repository and one set of rules about naming; splitting them later is a
|
||||
/// rename and a migration, whereas keeping two near-identical aggregates in sync from the
|
||||
/// start is a permanent tax.
|
||||
/// </remarks>
|
||||
public sealed class LibraryLabel
|
||||
{
|
||||
private readonly List<VideoItem> _videos = [];
|
||||
|
||||
/// <summary>Required by EF Core materialization; do not use from application code.</summary>
|
||||
private LibraryLabel()
|
||||
{
|
||||
Name = null!;
|
||||
NormalizedName = null!;
|
||||
}
|
||||
|
||||
public LibraryLabel(string name, LabelKind kind)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
|
||||
Id = Guid.CreateVersion7();
|
||||
Kind = kind;
|
||||
CreatedAt = DateTimeOffset.UtcNow;
|
||||
Name = name.Trim();
|
||||
NormalizedName = Normalize(name);
|
||||
}
|
||||
|
||||
public Guid Id { get; private set; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Upper-cased, trimmed name. Uniqueness is enforced on this rather than on
|
||||
/// <see cref="Name"/>, so "Комедия" and "комедия" cannot both exist.
|
||||
/// </summary>
|
||||
public string NormalizedName { get; private set; }
|
||||
|
||||
public LabelKind Kind { get; private set; }
|
||||
|
||||
public DateTimeOffset CreatedAt { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<VideoItem> Videos => _videos;
|
||||
|
||||
public static string Normalize(string name) => name.Trim().ToUpperInvariant();
|
||||
|
||||
public void Rename(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
|
||||
Name = name.Trim();
|
||||
NormalizedName = Normalize(name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user