< Summary

Information
Class: MyNet.UI.ViewModels.FileHistory.RecentFilesViewModel
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/FileHistory/RecentFilesViewModel.cs
Tag: 323_28699572109
Line coverage
0%
Covered lines: 0
Uncovered lines: 66
Coverable lines: 66
Total lines: 155
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)0%7280%
get_SearchText()0%620%
set_SearchText(...)100%210%
ReloadAsync()100%210%
CreateCollection()100%210%
CreateListOptions(...)100%210%
OnRecentFilesChanged(...)100%210%
CreateItemViewModel(...)100%210%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/ViewModels/FileHistory/RecentFilesViewModel.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="RecentFilesViewModel.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Linq;
 10using System.Reactive.Disposables;
 11using System.Threading;
 12using System.Threading.Tasks;
 13using System.Windows.Input;
 14using MyNet.IO.FileHistory;
 15using MyNet.Observable.Collections;
 16using MyNet.UI.Commands;
 17using MyNet.UI.Dialogs;
 18using MyNet.UI.Notifications;
 19using MyNet.UI.Services;
 20using MyNet.UI.Services.FileHistory;
 21using MyNet.UI.ViewModels.List;
 22
 23namespace MyNet.UI.ViewModels.FileHistory;
 24
 25/// <summary>
 26/// View model for the recent-files list.
 27/// </summary>
 28public sealed class RecentFilesViewModel : ListViewModelBase<RecentFileViewModel, ExtendedCollection<RecentFileViewModel
 29{
 30    private readonly IRecentFilesOperations _recentFilesOperations;
 31    private readonly IRecentFileCommandsService _recentFileCommandsService;
 32    private readonly IDialogService _dialogService;
 33    private readonly INotificationPublisher _notificationPublisher;
 34    private readonly RecentFilesListOptions _listOptions;
 035    private readonly Dictionary<string, RecentFileViewModel> _entries = new(StringComparer.OrdinalIgnoreCase);
 36
 37    /// <summary>
 38    /// Initializes a new instance of the <see cref="RecentFilesViewModel"/> class.
 39    /// </summary>
 40    public RecentFilesViewModel(
 41        IRecentFilesOperations recentFilesOperations,
 42        IRecentFileCommandsService recentFileCommandsService,
 43        IDialogService dialogService,
 44        INotificationPublisher notificationPublisher,
 45        ICommandFactory? commandFactory = null)
 046        : base(CreateCollection(), CreateListOptions(out var listOptions).Filters, listOptions.Sorting)
 47    {
 048        _recentFilesOperations = recentFilesOperations ?? throw new ArgumentNullException(nameof(recentFilesOperations))
 049        _recentFileCommandsService = recentFileCommandsService ?? throw new ArgumentNullException(nameof(recentFileComma
 050        _dialogService = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
 051        _notificationPublisher = notificationPublisher ?? throw new ArgumentNullException(nameof(notificationPublisher))
 052        _listOptions = listOptions;
 53
 054        var commands = commandFactory.GetOrDefault();
 055        OpenCommand = commands.Create<RecentFileViewModel?>(async item =>
 056        {
 057            if (item is not null)
 058                await item.OpenAsync().ConfigureAwait(false);
 059        },
 060            item => item is not null);
 61
 062        RemoveItemsCommand = commands.Create<IEnumerable<RecentFileViewModel>>(async items =>
 063        {
 064            foreach (var item in items ?? [])
 065                await _recentFilesOperations.RemoveAsync(item.Path).ConfigureAwait(false);
 066        });
 67
 68        ReloadCommand = commands.Create(() => ReloadAsync());
 69
 070        _recentFilesOperations.Changed += OnRecentFilesChanged;
 71        Disposables.Add(Disposable.Create(() => _recentFilesOperations.Changed -= OnRecentFilesChanged));
 72
 073        _ = ReloadAsync();
 074    }
 75
 76    /// <summary>
 77    /// Gets the command that opens a recent file.
 78    /// </summary>
 79    public ICommand OpenCommand { get; }
 80
 81    /// <summary>
 82    /// Gets the command that removes items from the recent-files list.
 83    /// </summary>
 84    public ICommand RemoveItemsCommand { get; }
 85
 86    /// <summary>
 87    /// Gets the command that reloads the list from storage.
 88    /// </summary>
 89    public ICommand ReloadCommand { get; }
 90
 91    /// <summary>
 92    /// Gets or sets the search text applied to name and path.
 93    /// </summary>
 94    public string SearchText
 95    {
 096        get => _listOptions.NameFilter.Value ?? string.Empty;
 097        set => _listOptions.SetSearchText(value);
 98    }
 99
 100    /// <summary>
 101    /// Reloads items from the recent-files service.
 102    /// </summary>
 0103    public async Task ReloadAsync(CancellationToken cancellationToken = default) => await ExecuteSafeAsync(async ct =>
 0104    {
 0105        var files = await _recentFilesOperations.GetAllAsync(ct).ConfigureAwait(false);
 0106        var items = new List<RecentFileViewModel>(files.Count);
 0107        var activePaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
 0108
 0109        foreach (var file in files)
 0110        {
 0111            activePaths.Add(file.Path);
 0112
 0113            if (!_entries.TryGetValue(file.Path, out var viewModel))
 0114            {
 0115                viewModel = CreateItemViewModel(file);
 0116                _entries[file.Path] = viewModel;
 0117            }
 0118            else
 0119            {
 0120                viewModel.Update(file);
 0121            }
 0122
 0123            items.Add(viewModel);
 0124        }
 0125
 0126        foreach (var path in _entries.Keys.Where(path => !activePaths.Contains(path)).ToList())
 0127            _entries.Remove(path);
 0128
 0129        Collection.Set(items);
 0130
 0131        foreach (var viewModel in items.Where(x => x.Image is null))
 0132            await viewModel.LoadImageAsync(ct).ConfigureAwait(false);
 0133    },
 0134        cancellationToken).ConfigureAwait(false);
 135
 136    private static ExtendedCollection<RecentFileViewModel> CreateCollection() =>
 0137        ExtendedCollection.Create<RecentFileViewModel>();
 138
 139    private static RecentFilesListOptions CreateListOptions(out RecentFilesListOptions options)
 140    {
 0141        options = RecentFilesListOptions.Create();
 0142        return options;
 143    }
 144
 0145    private void OnRecentFilesChanged(object? sender, EventArgs e) => _ = ReloadAsync();
 146
 147    private RecentFileViewModel CreateItemViewModel(RecentFile file) =>
 0148        new(
 0149            file,
 0150            _recentFilesOperations,
 0151            _recentFileCommandsService,
 0152            _dialogService,
 0153            _notificationPublisher);
 154}
 155