using System.Globalization; using PLib.Application.Library; using PLib.Domain.Videos; using ReactiveUI; using RxVoid = ReactiveUI.Primitives.RxVoid; namespace PLib.Desktop.ViewModels; /// One tag, performer, studio or collection in a browsing tab. public sealed class LabelSummaryViewModel { public LabelSummaryViewModel(LabelSummary summary, Action open) { ArgumentNullException.ThrowIfNull(summary); Id = summary.Id; Name = summary.Name; Kind = summary.Kind; VideoCount = summary.VideoCount; CountText = VideoCount.ToString(CultureInfo.CurrentCulture); OpenCommand = ReactiveCommand.Create(() => open(this)); } public Guid Id { get; } public string Name { get; } public LabelKind Kind { get; } public int VideoCount { get; } public string CountText { get; } /// Narrows the video grid down to this label and switches to it. public ReactiveCommand OpenCommand { get; } public bool Matches(string term) => Name.Contains(term, StringComparison.CurrentCultureIgnoreCase); } /// An order for the entity lists, and how to read it. public sealed record EntitySortOption(string Label, Comparison Compare) { public static IReadOnlyList All { get; } = [ new("Сначала частые", (x, y) => { var byCount = y.VideoCount.CompareTo(x.VideoCount); return byCount != 0 ? byCount : Name(x, y); }), new("По названию", Name), ]; /// /// Culture-aware and case-insensitive, so Cyrillic and Latin names land where a reader /// expects rather than in ordinal order. /// private static int Name(LabelSummaryViewModel x, LabelSummaryViewModel y) => string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase); }