MainWindow skeleton

This commit is contained in:
2022-04-03 09:22:24 +02:00
parent 7ff3898bd9
commit b6b8a7b3f8
28 changed files with 432 additions and 105 deletions

View File

@@ -7,6 +7,7 @@ namespace FileTime.App.Core
{
ObservableCollection<ITabViewModel> Tabs { get; }
ITabViewModel? SelectedTab { get; }
IObservable<ITabViewModel?> SelectedTabObservable { get; }
IObservable<string?> SearchText { get; }
void AddTab(ITabViewModel tabViewModel);

View File

@@ -1,6 +1,9 @@
using FileTime.Core.Models;
using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface IContainerSizeContainerViewModel : IItemViewModel
public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel, int>
{
long Size { get; set; }
}

View File

@@ -1,6 +1,9 @@
using FileTime.Core.Models;
using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface IContainerViewModel : IItemViewModel
public interface IContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel, int>
{
}
}

View File

@@ -1,6 +1,9 @@
using FileTime.Core.Models;
using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface IElementViewModel : IItemViewModel
public interface IElementViewModel : IItemViewModel, IInitable<IElement, ITabViewModel, int>
{
long? Size { get; set; }
}

View File

@@ -1,6 +1,9 @@
using FileTime.Core.Models;
using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface IFileViewModel : IElementViewModel
public interface IFileViewModel : IElementViewModel, IInitable<IFileElement, ITabViewModel, int>
{
}
}

View File

@@ -2,13 +2,15 @@ using System.Reactive.Subjects;
using FileTime.App.Core.Models;
using FileTime.App.Core.Models.Enums;
using FileTime.Core.Models;
using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface IItemViewModel
public interface IItemViewModel : IInitable<IItem, ITabViewModel, int>
{
IItem? BaseItem { get; set; }
IObservable<IReadOnlyList<ItemNamePart>>? DisplayName { get; set; }
string? DisplayNameText { get; set; }
IObservable<bool>? IsSelected { get; set; }
IObservable<bool>? IsMarked { get; set; }
BehaviorSubject<bool> IsAlternative { get; }

View File

@@ -5,12 +5,14 @@ using InitableService;
namespace FileTime.App.Core.ViewModels
{
public interface ITabViewModel : IInitable<ITab>
public interface ITabViewModel : IInitable<ITab, int>
{
ITab? Tab { get; }
int TabNumber { get; }
IObservable<bool> IsSelected { get; }
IObservable<IContainer?>? CurrentLocation { get; }
IObservable<IItemViewModel?>? CurrentSelectedItem { get; }
IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; }
IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
ITab? Tab { get; }
}
}

View File

@@ -10,15 +10,31 @@ namespace FileTime.App.Core
public abstract partial class AppStateBase : IAppState
{
private readonly BehaviorSubject<string?> _searchText = new(null);
private readonly BehaviorSubject<ITabViewModel?> _selectedTabObservable = new(null);
private ITabViewModel? _selectedTab;
public ObservableCollection<ITabViewModel> Tabs { get; } = new();
public IObservable<string?> SearchText { get; private set; }
[Property]
private ITabViewModel? _selectedTab;
public IObservable<ITabViewModel?> SelectedTabObservable { get; private set; }
public ITabViewModel? SelectedTab
{
get => _selectedTab;
private set
{
if (value != _selectedTab)
{
_selectedTab = value;
OnPropertyChanged(nameof(SelectedTab));
_selectedTabObservable.OnNext(value);
}
}
}
partial void OnInitialize()
{
SearchText = _searchText.AsObservable();
SelectedTabObservable = _selectedTabObservable.AsObservable();
}
public void AddTab(ITabViewModel tabViewModel)
@@ -45,5 +61,10 @@ namespace FileTime.App.Core
{
_searchText.OnNext(searchText);
}
public void SetSelectedTab(ITabViewModel tabToSelect)
{
SelectedTab = tabToSelect;
}
}
}

View File

@@ -1,11 +1,22 @@
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using MvvmGen;
namespace FileTime.App.Core.ViewModels
{
[ViewModel]
[ViewModel(GenerateConstructor = false)]
public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel
{
[Property]
private long _size;
public ContainerSizeContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
{
}
public void Init(IContainer item, ITabViewModel parentTab, int index)
{
Init((IItem)item, parentTab, index);
}
}
}

View File

@@ -1,6 +1,19 @@
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using MvvmGen;
namespace FileTime.App.Core.ViewModels
{
public class ContainerViewModel : ItemViewModel, IContainerViewModel
[ViewModel(GenerateConstructor = false)]
public partial class ContainerViewModel : ItemViewModel, IContainerViewModel
{
public ContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
{
}
public void Init(IContainer item, ITabViewModel parentTab, int index)
{
Init((IItem)item, parentTab, index);
}
}
}

View File

@@ -1,11 +1,22 @@
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using MvvmGen;
namespace FileTime.App.Core.ViewModels
{
[ViewModel]
[ViewModel(GenerateConstructor = false)]
public partial class ElementViewModel : ItemViewModel, IElementViewModel
{
[Property]
private long? _size;
public ElementViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
{
}
public void Init(IElement item, ITabViewModel parentTab, int index)
{
Init((IItem)item, parentTab, index);
}
}
}

View File

@@ -1,6 +1,19 @@
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using MvvmGen;
namespace FileTime.App.Core.ViewModels
{
public class FileViewModel : ElementViewModel, IFileViewModel
[ViewModel(GenerateConstructor = false)]
public partial class FileViewModel : ElementViewModel, IFileViewModel
{
public FileViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
{
}
public void Init(IFileElement item, ITabViewModel parentTab, int index)
{
Init((IElement)item, parentTab, index);
}
}
}

View File

@@ -1,12 +1,16 @@
using System.Reactive.Linq;
using System.Reactive.Subjects;
using FileTime.App.Core.Models;
using FileTime.App.Core.Models.Enums;
using FileTime.App.Core.Services;
using FileTime.Core.Models;
using MvvmGen;
namespace FileTime.App.Core.ViewModels
{
[ViewModel]
[Inject(typeof(IAppState), "_appState")]
[Inject(typeof(IItemNameConverterService), "_itemNameConverterService")]
public abstract partial class ItemViewModel : IItemViewModel
{
[Property]
@@ -15,6 +19,9 @@ namespace FileTime.App.Core.ViewModels
[Property]
private IObservable<IReadOnlyList<ItemNamePart>>? _displayName;
[Property]
private string? _displayNameText;
[Property]
private IObservable<bool>? _isSelected;
@@ -32,5 +39,29 @@ namespace FileTime.App.Core.ViewModels
[Property]
private BehaviorSubject<bool> _isAlternative = new(false);
public void Init(IItem item, ITabViewModel parentTab, int index)
{
BaseItem = item;
DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s));
DisplayNameText = item.DisplayName;
IsMarked = parentTab.MarkedItems.Select(m => m.Contains(item.FullName));
IsSelected = parentTab.MarkedItems.Select(m => m.Contains(item.FullName));
IsAlternative.OnNext(index % 2 == 0);
ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode);
Attributes = item.Attributes;
CreatedAt = item.CreatedAt;
}
private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative)
=> (isMarked, isSelected, sAlternative) switch
{
(true, true, _) => ItemViewMode.MarkedSelected,
(true, false, true) => ItemViewMode.MarkedAlternative,
(false, true, _) => ItemViewMode.Selected,
(false, false, true) => ItemViewMode.Alternative,
(true, false, false) => ItemViewMode.Marked,
_ => ItemViewMode.Default
};
}
}

View File

@@ -17,13 +17,16 @@ namespace FileTime.App.Core.ViewModels
private readonly List<IDisposable> _disposables = new();
private bool disposed;
public ITab? Tab { get; private set; }
public int TabNumber { get; private set; }
public IObservable<bool> IsSelected { get; }
public IObservable<IContainer?>? CurrentLocation { get; private set; }
public IObservable<IItemViewModel?>? CurrentSelectedItem { get; private set; }
public IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; private set; }
public IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
public ITab? Tab { get; private set; }
public TabViewModel(
IServiceProvider serviceProvider,
IItemNameConverterService itemNameConverterService,
@@ -34,10 +37,14 @@ namespace FileTime.App.Core.ViewModels
_appState = appState;
MarkedItems = _markedItems.Select(e => e.ToList()).AsObservable();
IsSelected = _appState.SelectedTabObservable.Select(s => s == this);
}
public void Init(ITab tab)
public void Init(ITab tab, int tabNumber)
{
Tab = tab;
TabNumber = tabNumber;
CurrentLocation = tab.CurrentLocation.AsObservable();
CurrentItems = tab.CurrentItems.Select(items => items.Select(MapItemToViewModel).ToList());
CurrentSelectedItem = Observable.CombineLatest(
@@ -45,61 +52,33 @@ namespace FileTime.App.Core.ViewModels
tab.CurrentSelectedItem,
(currentItems, currentSelectedItemPath) => currentItems.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path));
tab.CurrentLocation.Subscribe((_) => _markedItems.OnNext(Enumerable.Empty<FullName>()));
Tab = tab;
}
private IItemViewModel MapItemToViewModel(IItem item, int index)
{
if (item is IContainer container)
{
var containerViewModel = _serviceProvider.GetRequiredService<IContainerViewModel>();
InitIItemViewModel(containerViewModel, item);
var containerViewModel = _serviceProvider.GetInitableResolver<IContainer, ITabViewModel, int>(container, this, index).GetRequiredService<IContainerViewModel>();
return containerViewModel;
}
else if (item is IFileElement fileElement)
{
var fileViewModel = _serviceProvider.GetRequiredService<IFileViewModel>();
InitIItemViewModel(fileViewModel, item);
var fileViewModel = _serviceProvider.GetInitableResolver<IFileElement, ITabViewModel, int>(fileElement, this, index).GetRequiredService<IFileViewModel>();
fileViewModel.Size = fileElement.Size;
return fileViewModel;
}
else if (item is IElement element)
{
var elementViewModel = _serviceProvider.GetRequiredService<IElementViewModel>();
InitIItemViewModel(elementViewModel, item);
var elementViewModel = _serviceProvider.GetInitableResolver<IElement, ITabViewModel, int>(element, this, index).GetRequiredService<IElementViewModel>();
return elementViewModel;
}
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neighter {nameof(IElement)}");
void InitIItemViewModel(IItemViewModel itemViewModel, IItem item)
{
itemViewModel.BaseItem = item;
itemViewModel.DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s));
itemViewModel.IsMarked = MarkedItems.Select(m => m.Contains(item.FullName));
itemViewModel.IsSelected = MarkedItems.Select(m => m.Contains(item.FullName));
itemViewModel.IsAlternative.OnNext(index % 2 == 0);
itemViewModel.ViewMode = Observable.CombineLatest(itemViewModel.IsMarked, itemViewModel.IsSelected, itemViewModel.IsAlternative, GenerateViewMode);
itemViewModel.Attributes = item.Attributes;
itemViewModel.CreatedAt = item.CreatedAt;
}
}
private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative)
=> (isMarked, isSelected, sAlternative) switch
{
(true, true, _) => ItemViewMode.MarkedSelected,
(true, false, true) => ItemViewMode.MarkedAlternative,
(false, true, _) => ItemViewMode.Selected,
(false, false, true) => ItemViewMode.Alternative,
(true, false, false) => ItemViewMode.Marked,
_ => ItemViewMode.Default
};
~TabViewModel() => Dispose(false);
public void Dispose()