Files
FileTime2/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs

95 lines
3.7 KiB
C#

using System.Collections.ObjectModel;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using DeclarativeProperty;
using FileTime.App.Core.Configuration;
using FileTime.App.Core.Models.Enums;
using FileTime.Core.Models.Extensions;
using MoreLinq;
using PropertyChanged.SourceGenerator;
namespace FileTime.App.Core.ViewModels;
public abstract partial class AppStateBase : IAppState
{
private readonly BehaviorSubject<string?> _searchText = new(null);
private readonly DeclarativeProperty<ITabViewModel?> _selectedTab = new(null);
private readonly DeclarativeProperty<ViewMode> _viewMode = new(Models.Enums.ViewMode.Default);
private readonly ObservableCollection<ITabViewModel> _tabs = new();
private readonly DeclarativeProperty<string?> _rapidTravelText;
public IDeclarativeProperty<ViewMode> ViewMode { get; }
public ReadOnlyObservableCollection<ITabViewModel> Tabs { get; }
public IObservable<string?> SearchText { get; }
public IDeclarativeProperty<ITabViewModel?> SelectedTab { get; }
public IDeclarativeProperty<string?> RapidTravelText { get; }
public IDeclarativeProperty<string?> RapidTravelTextDebounced { get; }
public IDeclarativeProperty<string?> ContainerStatus { get; }
[Notify] public List<KeyConfig> PreviousKeys { get; } = new();
[Notify] public bool NoCommandFound { get; set; }
protected AppStateBase()
{
_rapidTravelText = new ("");
RapidTravelText = _rapidTravelText.DistinctUntilChanged();
RapidTravelTextDebounced = RapidTravelText
.Debounce(v =>
string.IsNullOrEmpty(v)
? TimeSpan.Zero
: TimeSpan.FromMilliseconds(200)
, resetTimer: true
);
ViewMode = _viewMode;
SearchText = _searchText.AsObservable();
SelectedTab = DeclarativePropertyHelpers.CombineLatest<ObservableCollection<ITabViewModel>, ITabViewModel, ITabViewModel>(
_tabs.Watch()!,
_selectedTab!,
(tabs, selectedTab) => Task.FromResult(GetSelectedTab(tabs, selectedTab)!)
)!;
Tabs = new ReadOnlyObservableCollection<ITabViewModel>(_tabs);
ContainerStatus = SelectedTab
.Map(t => t?.CurrentLocation)
.Switch()
.Map(c => c?.GetExtension<StatusProviderContainerExtension>()?.GetStatusProperty())
.Switch()!;
}
public void AddTab(ITabViewModel tabViewModel)
{
if (_tabs.Any(t => t.TabNumber == tabViewModel.TabNumber))
throw new ArgumentException($"There is a tab with the same tab number {tabViewModel.TabNumber}.", nameof(tabViewModel));
var index = _tabs.Count(t => t.TabNumber < tabViewModel.TabNumber);
_tabs.Insert(index, tabViewModel);
}
public void RemoveTab(ITabViewModel tabViewModel)
{
if (!_tabs.Contains(tabViewModel)) return;
_tabs.Remove(tabViewModel);
}
public void SetSearchText(string? searchText) => _searchText.OnNext(searchText);
public async Task SwitchViewModeAsync(ViewMode newViewMode) => await _viewMode.SetValue(newViewMode);
public async Task SetSelectedTabAsync(ITabViewModel tabToSelect) => await _selectedTab.SetValue(tabToSelect);
public async Task SetRapidTravelTextAsync(string? text) => await _rapidTravelText.SetValue(text);
private ITabViewModel? GetSelectedTab(IEnumerable<ITabViewModel> tabs, ITabViewModel? expectedSelectedTab)
{
var (preferred, others) =
tabs
.OrderBy(t => t.TabNumber)
.Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0));
return preferred.Concat(others.Reverse()).FirstOrDefault();
}
}