Refactor PLib video library manager to use ReactiveUI, replacing CommunityToolkit.Mvvm. Update dependencies, enhance thumbnail caching logic, and improve UI responsiveness with reactive commands. Remove obsolete PLib.slnx file and update README.md to reflect changes.

This commit is contained in:
Leonid Pershin
2026-08-08 11:37:36 +03:00
parent bf4a3bb922
commit 625eae7ead
18 changed files with 693 additions and 359 deletions
@@ -24,6 +24,9 @@ public sealed class LibraryServiceTests
_thumbnails.GetOrCreateAsync(Arg.Any<string>(), Arg.Any<TimeSpan?>(), Arg.Any<CancellationToken>())
.Returns(callInfo => $@"C:\cache\{Path.GetFileNameWithoutExtension(callInfo.Arg<string>())}.jpg");
// By default every remembered poster frame is still on disk.
_thumbnails.IsAvailable(Arg.Any<string?>()).Returns(true);
}
[Fact]
@@ -94,6 +97,36 @@ public sealed class LibraryServiceTests
_repository.Items.Single().ThumbnailPath.ShouldBe(@"C:\cache\a.jpg");
}
[Fact]
public async Task A_poster_frame_that_disappeared_from_the_cache_is_generated_again()
{
var indexed = new VideoItem(@"C:\videos\a.mp4", "a", 5_000, DateTimeOffset.UnixEpoch);
indexed.ApplyTechnicalInfo(new VideoTechnicalInfo(TimeSpan.FromMinutes(1), 1280, 720, "h264"));
indexed.AttachThumbnail(@"C:\cache\deleted.jpg");
_repository.Seed(indexed);
_thumbnails.IsAvailable(@"C:\cache\deleted.jpg").Returns(false);
GivenFilesOnDisk(File(@"C:\videos\a.mp4", sizeInBytes: 5_000));
await CollectAsync(CreateService());
await _thumbnails.Received(1)
.GetOrCreateAsync(@"C:\videos\a.mp4", Arg.Any<TimeSpan?>(), Arg.Any<CancellationToken>());
_repository.Items.Single().ThumbnailPath.ShouldBe(@"C:\cache\a.jpg");
}
[Fact]
public async Task Cached_frames_nothing_points_at_are_purged_once_the_scan_is_whole()
{
GivenFilesOnDisk(File(@"C:\videos\a.mp4"));
await CollectAsync(CreateService());
await _thumbnails.Received(1).PurgeUnusedAsync(
Arg.Is<IReadOnlyCollection<string>>(paths => paths != null && paths.SequenceEqual(new[] { @"C:\cache\a.jpg" })),
Arg.Any<CancellationToken>());
}
[Fact]
public async Task The_same_file_reached_through_two_overlapping_roots_is_only_added_once()
{