Refactor SelectedTab to DeclarativeProperty
This commit is contained in:
@@ -8,16 +8,15 @@ namespace FileTime.App.Core.ViewModels;
|
||||
public interface IAppState
|
||||
{
|
||||
ReadOnlyObservableCollection<ITabViewModel> Tabs { get; }
|
||||
IObservable<ITabViewModel?> SelectedTab { get; }
|
||||
IDeclarativeProperty<ITabViewModel?> SelectedTab { get; }
|
||||
IObservable<string?> SearchText { get; }
|
||||
IDeclarativeProperty<ViewMode> ViewMode { get; }
|
||||
DeclarativeProperty<string?> RapidTravelText { get; }
|
||||
ITabViewModel? CurrentSelectedTab { get; }
|
||||
ITimelineViewModel TimelineViewModel { get; }
|
||||
|
||||
void AddTab(ITabViewModel tabViewModel);
|
||||
void RemoveTab(ITabViewModel tabViewModel);
|
||||
void SetSearchText(string? searchText);
|
||||
Task SwitchViewModeAsync(ViewMode newViewMode);
|
||||
void SetSelectedTab(ITabViewModel tabToSelect);
|
||||
Task SetSelectedTabAsync(ITabViewModel tabToSelect);
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public class TabPersistenceService : ITabPersistenceService
|
||||
.SkipWhile(t => t.TabNumber <= tabStates.ActiveTabNumber);
|
||||
|
||||
var tabToActivate = optimalTabs.Concat(suboptimalTabs).FirstOrDefault();
|
||||
if (tabToActivate is not null) _appState.SetSelectedTab(tabToActivate);
|
||||
if (tabToActivate is not null) await _appState.SetSelectedTabAsync(tabToActivate);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public class TabPersistenceService : ITabPersistenceService
|
||||
|
||||
return new TabStates(
|
||||
tabStates,
|
||||
_appState.CurrentSelectedTab?.TabNumber
|
||||
_appState.SelectedTab.Value?.TabNumber
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +345,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase
|
||||
await _userCommandHandlerService.HandleCommandAsync(ExitRapidTravelCommand.Instance);
|
||||
}
|
||||
|
||||
_appState.SetSelectedTab(tabViewModel!);
|
||||
await _appState.SetSelectedTabAsync(tabViewModel!);
|
||||
}
|
||||
|
||||
private Task CloseTab()
|
||||
|
||||
@@ -15,17 +15,16 @@ namespace FileTime.App.Core.ViewModels;
|
||||
public abstract partial class AppStateBase : IAppState
|
||||
{
|
||||
private readonly BehaviorSubject<string?> _searchText = new(null);
|
||||
private readonly BehaviorSubject<ITabViewModel?> _selectedTab = new(null);
|
||||
private readonly DeclarativeProperty<ITabViewModel?> _selectedTab = new();
|
||||
private readonly DeclarativeProperty<ViewMode> _viewMode = new(Models.Enums.ViewMode.Default);
|
||||
private readonly SourceList<ITabViewModel> _tabs = new();
|
||||
private readonly ObservableCollection<ITabViewModel> _tabs = new();
|
||||
|
||||
public IDeclarativeProperty<ViewMode> ViewMode { get; private set; }
|
||||
|
||||
public ReadOnlyObservableCollection<ITabViewModel> Tabs { get; private set; }
|
||||
public IObservable<string?> SearchText { get; private set; }
|
||||
|
||||
public IObservable<ITabViewModel?> SelectedTab { get; private set; }
|
||||
public ITabViewModel? CurrentSelectedTab { get; private set; }
|
||||
public IDeclarativeProperty<ITabViewModel?> SelectedTab { get; private set; }
|
||||
public DeclarativeProperty<string?> RapidTravelText { get; private set; }
|
||||
|
||||
partial void OnInitialize()
|
||||
@@ -33,37 +32,28 @@ public abstract partial class AppStateBase : IAppState
|
||||
RapidTravelText = new("");
|
||||
ViewMode = _viewMode;
|
||||
|
||||
var tabsObservable = _tabs.Connect();
|
||||
|
||||
SearchText = _searchText.AsObservable();
|
||||
SelectedTab = Observable.CombineLatest(tabsObservable.ToCollection(), _selectedTab.DistinctUntilChanged(), GetSelectedTab);
|
||||
SelectedTab = DeclarativePropertyHelpers.CombineLatest<ObservableCollection<ITabViewModel>, ITabViewModel, ITabViewModel>(
|
||||
_tabs.Watch(),
|
||||
_selectedTab,
|
||||
(tabs, selectedTab) => Task.FromResult(GetSelectedTab(tabs, selectedTab))
|
||||
);
|
||||
|
||||
SelectedTab.Subscribe(t =>
|
||||
{
|
||||
_selectedTab.OnNext(t);
|
||||
CurrentSelectedTab = t;
|
||||
});
|
||||
|
||||
tabsObservable
|
||||
.Bind(out var collection)
|
||||
.DisposeMany()
|
||||
.Subscribe();
|
||||
|
||||
Tabs = collection;
|
||||
Tabs = new ReadOnlyObservableCollection<ITabViewModel>(_tabs);
|
||||
}
|
||||
|
||||
public void AddTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
if (_tabs.Items.Any(t => t.TabNumber == tabViewModel.TabNumber))
|
||||
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.Items.Count(t => t.TabNumber < tabViewModel.TabNumber);
|
||||
var index = _tabs.Count(t => t.TabNumber < tabViewModel.TabNumber);
|
||||
_tabs.Insert(index, tabViewModel);
|
||||
}
|
||||
|
||||
public void RemoveTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
if (!_tabs.Items.Contains(tabViewModel)) return;
|
||||
if (!_tabs.Contains(tabViewModel)) return;
|
||||
|
||||
_tabs.Remove(tabViewModel);
|
||||
}
|
||||
@@ -72,7 +62,7 @@ public abstract partial class AppStateBase : IAppState
|
||||
|
||||
public async Task SwitchViewModeAsync(ViewMode newViewMode) => await _viewMode.SetValue(newViewMode);
|
||||
|
||||
public void SetSelectedTab(ITabViewModel tabToSelect) => _selectedTab.OnNext(tabToSelect);
|
||||
public async Task SetSelectedTabAsync(ITabViewModel tabToSelect) => await _selectedTab.SetValue(tabToSelect);
|
||||
|
||||
private ITabViewModel? GetSelectedTab(IEnumerable<ITabViewModel> tabs, ITabViewModel? expectedSelectedTab)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract partial class ItemViewModel : IItemViewModel
|
||||
{
|
||||
ItemViewModelType.Main => _appState.RapidTravelText.Map(async (s, _) =>
|
||||
_appState.ViewMode.Value != Models.Enums.ViewMode.RapidTravel
|
||||
&& _appState.CurrentSelectedTab?.CurrentLocation.Value?.Provider is IItemNameConverterProvider nameConverterProvider
|
||||
&& _appState.SelectedTab.Value?.CurrentLocation.Value?.Provider is IItemNameConverterProvider nameConverterProvider
|
||||
? (IReadOnlyList<ItemNamePart>) await nameConverterProvider.GetItemNamePartsAsync(item)
|
||||
: _itemNameConverterService.GetDisplayName(item.DisplayName, s)
|
||||
),
|
||||
|
||||
@@ -7,16 +7,25 @@ public class CollectionRepeaterProperty<TCollection, TItem> : DeclarativePropert
|
||||
{
|
||||
private TCollection? _currentCollection;
|
||||
|
||||
public CollectionRepeaterProperty(IDeclarativeProperty<TCollection?> from)
|
||||
public CollectionRepeaterProperty(IDeclarativeProperty<TCollection?> from) : base(from.Value)
|
||||
{
|
||||
_currentCollection = from.Value;
|
||||
if (from.Value is { } value)
|
||||
{
|
||||
value.CollectionChanged += HandleCollectionChanged;
|
||||
}
|
||||
|
||||
AddDisposable(from.Subscribe(Handle));
|
||||
}
|
||||
|
||||
public CollectionRepeaterProperty(TCollection? collection) : base(collection)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
_currentCollection = collection;
|
||||
collection.CollectionChanged += HandleCollectionChanged;
|
||||
}
|
||||
|
||||
private void HandleCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
var t = Task.Run(async () => await NotifySubscribersAsync(Value));
|
||||
@@ -29,6 +38,7 @@ public class CollectionRepeaterProperty<TCollection, TItem> : DeclarativePropert
|
||||
{
|
||||
currentCollection.CollectionChanged -= HandleCollectionChanged;
|
||||
}
|
||||
|
||||
if (collection is { } newCollection)
|
||||
{
|
||||
newCollection.CollectionChanged -= HandleCollectionChanged;
|
||||
|
||||
@@ -70,6 +70,19 @@ public static class DeclarativePropertyExtensions
|
||||
where TCollection : IList<TItem>, INotifyCollectionChanged
|
||||
=> new CollectionRepeaterProperty<TCollection?, TItem>(collection);
|
||||
|
||||
public static IDeclarativeProperty<TCollection?> Watch<TCollection, TItem>(
|
||||
this TCollection collection)
|
||||
where TCollection : IList<TItem>, INotifyCollectionChanged
|
||||
=> new CollectionRepeaterProperty<TCollection?, TItem>(collection);
|
||||
|
||||
public static IDeclarativeProperty<ObservableCollection<TItem>?> Watch<TItem>(
|
||||
this ObservableCollection<TItem> collection)
|
||||
=> new CollectionRepeaterProperty<ObservableCollection<TItem>?, TItem>(collection);
|
||||
|
||||
public static IDeclarativeProperty<ReadOnlyObservableCollection<TItem>?> Watch<TItem>(
|
||||
this ReadOnlyObservableCollection<TItem> collection)
|
||||
=> new CollectionRepeaterProperty<ReadOnlyObservableCollection<TItem>?, TItem>(collection);
|
||||
|
||||
|
||||
public static IDeclarativeProperty<TResult?> CombineLatest<T1, T2, TResult>(
|
||||
this IDeclarativeProperty<T1> prop1,
|
||||
|
||||
Reference in New Issue
Block a user