using System.Collections.ObjectModel; using System.Reactive.Linq; using System.Reactive.Subjects; using DeclarativeProperty; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.ViewModels.Timeline; using FileTime.Core.Models.Extensions; using MvvmGen; using MoreLinq; namespace FileTime.App.Core.ViewModels; [ViewModel] [Inject(typeof(ITimelineViewModel), "TimelineViewModel", PropertyAccessModifier = AccessModifier.Public)] public abstract partial class AppStateBase : IAppState { private readonly BehaviorSubject _searchText = new(null); private readonly DeclarativeProperty _selectedTab = new(); private readonly DeclarativeProperty _viewMode = new(Models.Enums.ViewMode.Default); private readonly ObservableCollection _tabs = new(); public IDeclarativeProperty ViewMode { get; private set; } public ReadOnlyObservableCollection Tabs { get; private set; } public IObservable SearchText { get; private set; } public IDeclarativeProperty SelectedTab { get; private set; } public DeclarativeProperty RapidTravelText { get; private set; } public IDeclarativeProperty RapidTravelTextDebounced { get; private set; } public IDeclarativeProperty ContainerStatus { get; private set; } partial void OnInitialize() { RapidTravelText = new(""); RapidTravelTextDebounced = RapidTravelText .Debounce(v => string.IsNullOrEmpty(v) ? TimeSpan.Zero : TimeSpan.FromMilliseconds(200) , resetTimer: true ); ViewMode = _viewMode; SearchText = _searchText.AsObservable(); SelectedTab = DeclarativePropertyHelpers.CombineLatest, ITabViewModel, ITabViewModel>( _tabs.Watch(), _selectedTab, (tabs, selectedTab) => Task.FromResult(GetSelectedTab(tabs, selectedTab)) ); Tabs = new ReadOnlyObservableCollection(_tabs); ContainerStatus = SelectedTab .Map(t => t?.CurrentLocation) .Switch() .Map(c => c?.GetExtension()?.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); private ITabViewModel? GetSelectedTab(IEnumerable tabs, ITabViewModel? expectedSelectedTab) { var (preferred, others) = tabs .OrderBy(t => t.TabNumber) .Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0)); return preferred.Concat(others.Reverse()).FirstOrDefault(); } }