MainWindow skeleton
This commit is contained in:
@@ -7,6 +7,7 @@ namespace FileTime.App.Core
|
|||||||
{
|
{
|
||||||
ObservableCollection<ITabViewModel> Tabs { get; }
|
ObservableCollection<ITabViewModel> Tabs { get; }
|
||||||
ITabViewModel? SelectedTab { get; }
|
ITabViewModel? SelectedTab { get; }
|
||||||
|
IObservable<ITabViewModel?> SelectedTabObservable { get; }
|
||||||
IObservable<string?> SearchText { get; }
|
IObservable<string?> SearchText { get; }
|
||||||
|
|
||||||
void AddTab(ITabViewModel tabViewModel);
|
void AddTab(ITabViewModel tabViewModel);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
public interface IContainerSizeContainerViewModel : IItemViewModel
|
public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel, int>
|
||||||
{
|
{
|
||||||
long Size { get; set; }
|
long Size { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
public interface IContainerViewModel : IItemViewModel
|
public interface IContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel, int>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
public interface IElementViewModel : IItemViewModel
|
public interface IElementViewModel : IItemViewModel, IInitable<IElement, ITabViewModel, int>
|
||||||
{
|
{
|
||||||
long? Size { get; set; }
|
long? Size { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
public interface IFileViewModel : IElementViewModel
|
public interface IFileViewModel : IElementViewModel, IInitable<IFileElement, ITabViewModel, int>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,13 +2,15 @@ using System.Reactive.Subjects;
|
|||||||
using FileTime.App.Core.Models;
|
using FileTime.App.Core.Models;
|
||||||
using FileTime.App.Core.Models.Enums;
|
using FileTime.App.Core.Models.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
public interface IItemViewModel
|
public interface IItemViewModel : IInitable<IItem, ITabViewModel, int>
|
||||||
{
|
{
|
||||||
IItem? BaseItem { get; set; }
|
IItem? BaseItem { get; set; }
|
||||||
IObservable<IReadOnlyList<ItemNamePart>>? DisplayName { get; set; }
|
IObservable<IReadOnlyList<ItemNamePart>>? DisplayName { get; set; }
|
||||||
|
string? DisplayNameText { get; set; }
|
||||||
IObservable<bool>? IsSelected { get; set; }
|
IObservable<bool>? IsSelected { get; set; }
|
||||||
IObservable<bool>? IsMarked { get; set; }
|
IObservable<bool>? IsMarked { get; set; }
|
||||||
BehaviorSubject<bool> IsAlternative { get; }
|
BehaviorSubject<bool> IsAlternative { get; }
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ using InitableService;
|
|||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
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<IContainer?>? CurrentLocation { get; }
|
||||||
IObservable<IItemViewModel?>? CurrentSelectedItem { get; }
|
IObservable<IItemViewModel?>? CurrentSelectedItem { get; }
|
||||||
IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; }
|
IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; }
|
||||||
IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
|
IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
|
||||||
ITab? Tab { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,15 +10,31 @@ namespace FileTime.App.Core
|
|||||||
public abstract partial class AppStateBase : IAppState
|
public abstract partial class AppStateBase : IAppState
|
||||||
{
|
{
|
||||||
private readonly BehaviorSubject<string?> _searchText = new(null);
|
private readonly BehaviorSubject<string?> _searchText = new(null);
|
||||||
|
private readonly BehaviorSubject<ITabViewModel?> _selectedTabObservable = new(null);
|
||||||
|
private ITabViewModel? _selectedTab;
|
||||||
|
|
||||||
public ObservableCollection<ITabViewModel> Tabs { get; } = new();
|
public ObservableCollection<ITabViewModel> Tabs { get; } = new();
|
||||||
public IObservable<string?> SearchText { get; private set; }
|
public IObservable<string?> SearchText { get; private set; }
|
||||||
|
|
||||||
[Property]
|
public IObservable<ITabViewModel?> SelectedTabObservable { get; private set; }
|
||||||
private ITabViewModel? _selectedTab;
|
public ITabViewModel? SelectedTab
|
||||||
|
{
|
||||||
|
get => _selectedTab;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (value != _selectedTab)
|
||||||
|
{
|
||||||
|
_selectedTab = value;
|
||||||
|
OnPropertyChanged(nameof(SelectedTab));
|
||||||
|
_selectedTabObservable.OnNext(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
partial void OnInitialize()
|
partial void OnInitialize()
|
||||||
{
|
{
|
||||||
SearchText = _searchText.AsObservable();
|
SearchText = _searchText.AsObservable();
|
||||||
|
SelectedTabObservable = _selectedTabObservable.AsObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddTab(ITabViewModel tabViewModel)
|
public void AddTab(ITabViewModel tabViewModel)
|
||||||
@@ -45,5 +61,10 @@ namespace FileTime.App.Core
|
|||||||
{
|
{
|
||||||
_searchText.OnNext(searchText);
|
_searchText.OnNext(searchText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetSelectedTab(ITabViewModel tabToSelect)
|
||||||
|
{
|
||||||
|
SelectedTab = tabToSelect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
using MvvmGen;
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
[ViewModel]
|
[ViewModel(GenerateConstructor = false)]
|
||||||
public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel
|
public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel
|
||||||
{
|
{
|
||||||
[Property]
|
[Property]
|
||||||
private long _size;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
using MvvmGen;
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
[ViewModel]
|
[ViewModel(GenerateConstructor = false)]
|
||||||
public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
||||||
{
|
{
|
||||||
[Property]
|
[Property]
|
||||||
private long? _size;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using FileTime.App.Core.Models;
|
using FileTime.App.Core.Models;
|
||||||
using FileTime.App.Core.Models.Enums;
|
using FileTime.App.Core.Models.Enums;
|
||||||
|
using FileTime.App.Core.Services;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using MvvmGen;
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels
|
namespace FileTime.App.Core.ViewModels
|
||||||
{
|
{
|
||||||
[ViewModel]
|
[ViewModel]
|
||||||
|
[Inject(typeof(IAppState), "_appState")]
|
||||||
|
[Inject(typeof(IItemNameConverterService), "_itemNameConverterService")]
|
||||||
public abstract partial class ItemViewModel : IItemViewModel
|
public abstract partial class ItemViewModel : IItemViewModel
|
||||||
{
|
{
|
||||||
[Property]
|
[Property]
|
||||||
@@ -15,6 +19,9 @@ namespace FileTime.App.Core.ViewModels
|
|||||||
[Property]
|
[Property]
|
||||||
private IObservable<IReadOnlyList<ItemNamePart>>? _displayName;
|
private IObservable<IReadOnlyList<ItemNamePart>>? _displayName;
|
||||||
|
|
||||||
|
[Property]
|
||||||
|
private string? _displayNameText;
|
||||||
|
|
||||||
[Property]
|
[Property]
|
||||||
private IObservable<bool>? _isSelected;
|
private IObservable<bool>? _isSelected;
|
||||||
|
|
||||||
@@ -32,5 +39,29 @@ namespace FileTime.App.Core.ViewModels
|
|||||||
|
|
||||||
[Property]
|
[Property]
|
||||||
private BehaviorSubject<bool> _isAlternative = new(false);
|
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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,13 +17,16 @@ namespace FileTime.App.Core.ViewModels
|
|||||||
private readonly List<IDisposable> _disposables = new();
|
private readonly List<IDisposable> _disposables = new();
|
||||||
private bool disposed;
|
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<IContainer?>? CurrentLocation { get; private set; }
|
||||||
public IObservable<IItemViewModel?>? CurrentSelectedItem { get; private set; }
|
public IObservable<IItemViewModel?>? CurrentSelectedItem { get; private set; }
|
||||||
public IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; private set; }
|
public IObservable<IReadOnlyList<IItemViewModel>>? CurrentItems { get; private set; }
|
||||||
public IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
|
public IObservable<IReadOnlyList<FullName>> MarkedItems { get; }
|
||||||
|
|
||||||
public ITab? Tab { get; private set; }
|
|
||||||
|
|
||||||
public TabViewModel(
|
public TabViewModel(
|
||||||
IServiceProvider serviceProvider,
|
IServiceProvider serviceProvider,
|
||||||
IItemNameConverterService itemNameConverterService,
|
IItemNameConverterService itemNameConverterService,
|
||||||
@@ -34,10 +37,14 @@ namespace FileTime.App.Core.ViewModels
|
|||||||
_appState = appState;
|
_appState = appState;
|
||||||
|
|
||||||
MarkedItems = _markedItems.Select(e => e.ToList()).AsObservable();
|
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();
|
CurrentLocation = tab.CurrentLocation.AsObservable();
|
||||||
CurrentItems = tab.CurrentItems.Select(items => items.Select(MapItemToViewModel).ToList());
|
CurrentItems = tab.CurrentItems.Select(items => items.Select(MapItemToViewModel).ToList());
|
||||||
CurrentSelectedItem = Observable.CombineLatest(
|
CurrentSelectedItem = Observable.CombineLatest(
|
||||||
@@ -45,61 +52,33 @@ namespace FileTime.App.Core.ViewModels
|
|||||||
tab.CurrentSelectedItem,
|
tab.CurrentSelectedItem,
|
||||||
(currentItems, currentSelectedItemPath) => currentItems.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path));
|
(currentItems, currentSelectedItemPath) => currentItems.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path));
|
||||||
tab.CurrentLocation.Subscribe((_) => _markedItems.OnNext(Enumerable.Empty<FullName>()));
|
tab.CurrentLocation.Subscribe((_) => _markedItems.OnNext(Enumerable.Empty<FullName>()));
|
||||||
|
|
||||||
Tab = tab;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IItemViewModel MapItemToViewModel(IItem item, int index)
|
private IItemViewModel MapItemToViewModel(IItem item, int index)
|
||||||
{
|
{
|
||||||
if (item is IContainer container)
|
if (item is IContainer container)
|
||||||
{
|
{
|
||||||
var containerViewModel = _serviceProvider.GetRequiredService<IContainerViewModel>();
|
var containerViewModel = _serviceProvider.GetInitableResolver<IContainer, ITabViewModel, int>(container, this, index).GetRequiredService<IContainerViewModel>();
|
||||||
InitIItemViewModel(containerViewModel, item);
|
|
||||||
|
|
||||||
return containerViewModel;
|
return containerViewModel;
|
||||||
}
|
}
|
||||||
else if (item is IFileElement fileElement)
|
else if (item is IFileElement fileElement)
|
||||||
{
|
{
|
||||||
var fileViewModel = _serviceProvider.GetRequiredService<IFileViewModel>();
|
var fileViewModel = _serviceProvider.GetInitableResolver<IFileElement, ITabViewModel, int>(fileElement, this, index).GetRequiredService<IFileViewModel>();
|
||||||
InitIItemViewModel(fileViewModel, item);
|
|
||||||
fileViewModel.Size = fileElement.Size;
|
fileViewModel.Size = fileElement.Size;
|
||||||
|
|
||||||
return fileViewModel;
|
return fileViewModel;
|
||||||
}
|
}
|
||||||
else if (item is IElement element)
|
else if (item is IElement element)
|
||||||
{
|
{
|
||||||
var elementViewModel = _serviceProvider.GetRequiredService<IElementViewModel>();
|
var elementViewModel = _serviceProvider.GetInitableResolver<IElement, ITabViewModel, int>(element, this, index).GetRequiredService<IElementViewModel>();
|
||||||
InitIItemViewModel(elementViewModel, item);
|
|
||||||
|
|
||||||
return elementViewModel;
|
return elementViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neighter {nameof(IElement)}");
|
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);
|
~TabViewModel() => Dispose(false);
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ namespace FileTime.Core.Models
|
|||||||
{
|
{
|
||||||
public interface IContainer : IItem
|
public interface IContainer : IItem
|
||||||
{
|
{
|
||||||
IReadOnlyList<IAbsolutePath> Items { get; }
|
IObservable<IReadOnlyList<IAbsolutePath>> Items { get; }
|
||||||
|
IObservable<bool> IsLoading { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Services;
|
using FileTime.Core.Services;
|
||||||
|
|
||||||
@@ -16,5 +18,9 @@ namespace FileTime.Core.Models
|
|||||||
bool CanRename,
|
bool CanRename,
|
||||||
string? Attributes,
|
string? Attributes,
|
||||||
IContentProvider Provider,
|
IContentProvider Provider,
|
||||||
IReadOnlyList<IAbsolutePath> Items) : IContainer;
|
IObservable<IReadOnlyList<IAbsolutePath>> Items) : IContainer
|
||||||
|
{
|
||||||
|
BehaviorSubject<bool> IsLoading { get; } = new BehaviorSubject<bool>(false);
|
||||||
|
IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
@@ -5,9 +7,9 @@ namespace FileTime.Core.Services
|
|||||||
{
|
{
|
||||||
public abstract class ContentProviderBase : IContentProvider
|
public abstract class ContentProviderBase : IContentProvider
|
||||||
{
|
{
|
||||||
protected List<IAbsolutePath> Items { get; set; } = new List<IAbsolutePath>();
|
protected BehaviorSubject<IReadOnlyList<IAbsolutePath>> Items { get; } = new BehaviorSubject<IReadOnlyList<IAbsolutePath>>(new List<IAbsolutePath>());
|
||||||
|
|
||||||
IReadOnlyList<IAbsolutePath> IContainer.Items => Items;
|
IObservable<IReadOnlyList<IAbsolutePath>> IContainer.Items => Items;
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
@@ -33,6 +35,10 @@ namespace FileTime.Core.Services
|
|||||||
|
|
||||||
public string? Attributes => null;
|
public string? Attributes => null;
|
||||||
|
|
||||||
|
protected BehaviorSubject<bool> IsLoading { get; } = new(false);
|
||||||
|
|
||||||
|
IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable();
|
||||||
|
|
||||||
protected ContentProviderBase(string name)
|
protected ContentProviderBase(string name)
|
||||||
{
|
{
|
||||||
DisplayName = Name = name;
|
DisplayName = Name = name;
|
||||||
|
|||||||
@@ -15,31 +15,38 @@ namespace FileTime.Core.Services
|
|||||||
public Tab()
|
public Tab()
|
||||||
{
|
{
|
||||||
CurrentLocation = _currentLocation.AsObservable();
|
CurrentLocation = _currentLocation.AsObservable();
|
||||||
CurrentItems = _currentLocation
|
CurrentItems =
|
||||||
.Select(c =>
|
Observable.Merge(
|
||||||
Observable.FromAsync(async () =>
|
_currentLocation
|
||||||
c == null
|
.Where(c => c is not null)
|
||||||
? Enumerable.Empty<IItem>()
|
.Select(c => c!.Items)
|
||||||
: await c.Items
|
.Switch()
|
||||||
.ToAsyncEnumerable()
|
.Select(
|
||||||
.SelectAwait(
|
i => Observable.FromAsync(async () =>
|
||||||
async i =>
|
await i
|
||||||
{
|
.ToAsyncEnumerable()
|
||||||
try
|
.SelectAwait(
|
||||||
|
async i =>
|
||||||
{
|
{
|
||||||
//TODO: force create by AbsolutePath name
|
try
|
||||||
return await i.ContentProvider.GetItemByFullNameAsync(i.Path);
|
{
|
||||||
|
//TODO: force create by AbsolutePath name
|
||||||
|
return await i.ContentProvider.GetItemByFullNameAsync(i.Path);
|
||||||
|
}
|
||||||
|
catch { return null!; }
|
||||||
}
|
}
|
||||||
catch { return null!; }
|
)
|
||||||
}
|
.Where(i => i != null)
|
||||||
|
.ToListAsync()
|
||||||
)
|
)
|
||||||
.Where(i => i != null)
|
)
|
||||||
.ToListAsync()
|
.Merge(Constants.MaximumObservableMergeOperations),
|
||||||
)
|
_currentLocation
|
||||||
)
|
.Where(c => c is null)
|
||||||
.Merge(Constants.MaximumObservableMergeOperations);
|
.Select(c => Enumerable.Empty<IItem>())
|
||||||
CurrentSelectedItem = CurrentLocation.Select(GetSelectedItemByLocation).Merge(_currentSelectedItem).Throttle(TimeSpan.FromMilliseconds(500));
|
);
|
||||||
|
|
||||||
|
CurrentSelectedItem = CurrentLocation.Select(GetSelectedItemByLocation).Switch().Merge(_currentSelectedItem).Throttle(TimeSpan.FromMilliseconds(500));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(IContainer currentLocation)
|
public void Init(IContainer currentLocation)
|
||||||
@@ -47,9 +54,9 @@ namespace FileTime.Core.Services
|
|||||||
_currentLocation.OnNext(currentLocation);
|
_currentLocation.OnNext(currentLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IAbsolutePath? GetSelectedItemByLocation(IContainer? currentLocation)
|
private IObservable<IAbsolutePath?> GetSelectedItemByLocation(IContainer? currentLocation)
|
||||||
{
|
{
|
||||||
return currentLocation?.Items[0];
|
return currentLocation?.Items?.Select(i => i.FirstOrDefault()) ?? Observable.Never((IAbsolutePath?)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeLocation(IContainer newLocation)
|
public void ChangeLocation(IContainer newLocation)
|
||||||
|
|||||||
@@ -132,6 +132,9 @@
|
|||||||
<converters:GetFileExtensionConverter x:Key="GetFileExtensionConverter"/>
|
<converters:GetFileExtensionConverter x:Key="GetFileExtensionConverter"/>
|
||||||
<converters:FormatSizeConverter x:Key="FormatSizeConverter"/>
|
<converters:FormatSizeConverter x:Key="FormatSizeConverter"/>
|
||||||
<converters:DateTimeConverter x:Key="DateTimeConverter"/>
|
<converters:DateTimeConverter x:Key="DateTimeConverter"/>
|
||||||
|
<converters:SplitStringConverter x:Key="SplitStringConverter" />
|
||||||
|
<converters:CompareConverter x:Key="EqualityConverter"/>
|
||||||
|
<converters:CompareConverter x:Key="NotEqualsConverter" ComparisonCondition="{x:Static converters:ComparisonCondition.NotEqual}"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<TrimMode>copyused</TrimMode>
|
<TrimMode>copyused</TrimMode>
|
||||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||||
<ApplicationIcon>filetime.ico</ApplicationIcon>
|
<ApplicationIcon>filetime.ico</ApplicationIcon>
|
||||||
|
<Version>0.0.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="filetime.ico" />
|
<Content Include="filetime.ico" />
|
||||||
|
|||||||
3
src/GuiApp/Avalonia/FileTime.GuiApp/Assets/loading.svg
Normal file
3
src/GuiApp/Avalonia/FileTime.GuiApp/Assets/loading.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
||||||
|
<path fill="white" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 136 B |
@@ -0,0 +1,54 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Converters
|
||||||
|
{
|
||||||
|
public enum ComparisonCondition
|
||||||
|
{
|
||||||
|
Equal,
|
||||||
|
GreaterThan,
|
||||||
|
LessThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
NotEqual,
|
||||||
|
GreaterThanOrEqual
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompareConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public ComparisonCondition ComparisonCondition { get; set; } = ComparisonCondition.Equal;
|
||||||
|
|
||||||
|
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return Compare(value, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Compare(object? value, object? parameter)
|
||||||
|
{
|
||||||
|
if (ComparisonCondition == ComparisonCondition.GreaterThan)
|
||||||
|
{
|
||||||
|
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt > parameterInt;
|
||||||
|
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble > parameterDouble;
|
||||||
|
else throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
else if (ComparisonCondition == ComparisonCondition.NotEqual)
|
||||||
|
{
|
||||||
|
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt != parameterInt;
|
||||||
|
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble != parameterDouble;
|
||||||
|
return value != parameter;
|
||||||
|
}
|
||||||
|
else if (ComparisonCondition == ComparisonCondition.Equal)
|
||||||
|
{
|
||||||
|
if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt == parameterInt;
|
||||||
|
else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble == parameterDouble;
|
||||||
|
else if (value?.GetType().IsEnum ?? false && Enum.TryParse(value.GetType(), parameter?.ToString(), out var _)) return value.ToString() == parameter?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value == parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
|
||||||
|
namespace FileTime.GuiApp.Converters
|
||||||
|
{
|
||||||
|
public class SplitStringConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value is string path && parameter is string separator)
|
||||||
|
{
|
||||||
|
return path.Split(separator);
|
||||||
|
}
|
||||||
|
else if (value is string path2 && parameter is char separator2)
|
||||||
|
{
|
||||||
|
return path2.Split(separator2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,16 +13,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<AvaloniaXaml Update="Views\MainWindow.axaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</AvaloniaXaml>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Views\MainWindow.axaml.cs">
|
|
||||||
<DependentUpon>MainWindow.axaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="0.10.13" />
|
<PackageReference Include="Avalonia" Version="0.10.13" />
|
||||||
@@ -30,6 +20,7 @@
|
|||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.13" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.13" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.13" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.13" />
|
||||||
|
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.12" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||||
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using FileTime.App.Core;
|
using FileTime.App.Core;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
@@ -6,6 +7,7 @@ using FileTime.Core.Models;
|
|||||||
using FileTime.Core.Services;
|
using FileTime.Core.Services;
|
||||||
using FileTime.Providers.Local;
|
using FileTime.Providers.Local;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using MvvmGen;
|
using MvvmGen;
|
||||||
|
|
||||||
namespace FileTime.GuiApp.ViewModels
|
namespace FileTime.GuiApp.ViewModels
|
||||||
@@ -14,17 +16,34 @@ namespace FileTime.GuiApp.ViewModels
|
|||||||
[Inject(typeof(IAppState), "_appState")]
|
[Inject(typeof(IAppState), "_appState")]
|
||||||
[Inject(typeof(ILocalContentProvider), "_localContentProvider")]
|
[Inject(typeof(ILocalContentProvider), "_localContentProvider")]
|
||||||
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
|
[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")]
|
||||||
|
[Inject(typeof(ILogger<MainWindowViewModel>), PropertyName = "_logger")]
|
||||||
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
public partial class MainWindowViewModel : IMainWindowViewModelBase
|
||||||
{
|
{
|
||||||
public bool Loading => false;
|
public bool Loading => false;
|
||||||
public IAppState AppState => _appState;
|
public IAppState AppState => _appState;
|
||||||
|
public string Title { get; private set; }
|
||||||
|
|
||||||
partial void OnInitialize()
|
partial void OnInitialize()
|
||||||
{
|
{
|
||||||
|
_logger?.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization...");
|
||||||
|
|
||||||
|
var version = Assembly.GetEntryAssembly()!.GetName().Version;
|
||||||
|
var versionString = "Unknwon version";
|
||||||
|
if (version != null)
|
||||||
|
{
|
||||||
|
versionString = $"{version.Major}.{version.Minor}.{version.Build}";
|
||||||
|
if (version.Revision != 0)
|
||||||
|
{
|
||||||
|
versionString += $" ({version.Revision})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Title = "FileTime " + versionString;
|
||||||
|
|
||||||
|
//TODO: refactor
|
||||||
if (AppState.Tabs.Count == 0)
|
if (AppState.Tabs.Count == 0)
|
||||||
{
|
{
|
||||||
var tab = _serviceProvider.GetInitableResolver<IContainer>(_localContentProvider).GetRequiredService<ITab>();
|
var tab = _serviceProvider.GetInitableResolver<IContainer>(_localContentProvider).GetRequiredService<ITab>();
|
||||||
var tabViewModel = _serviceProvider.GetInitableResolver(tab).GetRequiredService<ITabViewModel>();
|
var tabViewModel = _serviceProvider.GetInitableResolver(tab, 1).GetRequiredService<ITabViewModel>();
|
||||||
|
|
||||||
_appState.AddTab(tabViewModel);
|
_appState.AddTab(tabViewModel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,22 +23,116 @@
|
|||||||
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
||||||
<Grid IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}}">
|
<Grid IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}}">
|
||||||
<Grid ColumnDefinitions="250,*" RowDefinitions="Auto,*">
|
<Grid ColumnDefinitions="250,*" RowDefinitions="Auto,*">
|
||||||
<ListBox
|
<Grid PointerPressed="HeaderPointerPressed">
|
||||||
Grid.Row="1"
|
<Rectangle Fill="#01000000"/>
|
||||||
x:Name="CurrentItems"
|
<TextBlock Margin="15,10" Text="{Binding Title}"/>
|
||||||
x:CompileBindings="False"
|
</Grid>
|
||||||
AutoScrollToSelectedItem="True"
|
|
||||||
IsTabStop="True"
|
<Grid Grid.Column="1" PointerPressed="HeaderPointerPressed">
|
||||||
Items="{Binding AppState.SelectedTab.CurrentItems^}"
|
<Rectangle Fill="#01000000"/>
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
|
|
||||||
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
<StackPanel Margin="20,10" Orientation="Horizontal">
|
||||||
Classes="ContentListView">
|
<!--local:PathPresenter DataContext="{Binding AppState.SelectedTab.CurrentLocation^.FullName.Path,Converter={StaticResource PathPreformatter}}"/-->
|
||||||
<ListBox.ItemTemplate>
|
<TextBlock
|
||||||
<DataTemplate x:DataType="corevm:IItemViewModel">
|
Text="{Binding AppState.SelectedTab.CurrentSelectedItem^.DisplayNameText}" Foreground="{StaticResource AccentBrush}" />
|
||||||
<local:ItemView HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch"/>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</Grid>
|
||||||
</ListBox.ItemTemplate>
|
|
||||||
</ListBox>
|
<Grid Grid.Column="1" Grid.Row="1" RowDefinitions="Auto,40,*,Auto">
|
||||||
|
|
||||||
|
<ItemsControl
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding AppState.Tabs}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid RowDefinitions="Auto,1">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="20,0,20,0">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
VerticalAlignment="Center" Text="{Binding TabNumber,StringFormat=({0})}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
VerticalAlignment="Center" Margin="5,0,0,0" Text="{Binding CurrentLocation^.Name}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Rectangle Fill="{DynamicResource ForegroundBrush}" Grid.Row="1" IsVisible="{Binding IsSelected^}"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
Grid.Row="2"
|
||||||
|
Margin="20,0,0,0">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="15*" />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
<ColumnDefinition Width="40*" />
|
||||||
|
<ColumnDefinition Width="10" />
|
||||||
|
<ColumnDefinition Width="45*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
|
||||||
|
<Rectangle
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="1"
|
||||||
|
Margin="0,10,0,10"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Fill="{DynamicResource ContentSeparatorBrush}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Grid Grid.Column="2" RowDefinitions="Auto,*">
|
||||||
|
<Grid IsVisible="{Binding AppState.SelectedTab.CurrentLocation^.IsLoading^}">
|
||||||
|
<Image Width="40" Height="40" Source="{SvgImage /Assets/loading.svg}" Classes="LoadingAnimation"/>
|
||||||
|
</Grid>
|
||||||
|
<ListBox
|
||||||
|
Grid.Row="1"
|
||||||
|
x:Name="CurrentItems"
|
||||||
|
x:CompileBindings="False"
|
||||||
|
AutoScrollToSelectedItem="True"
|
||||||
|
IsTabStop="True"
|
||||||
|
Items="{Binding AppState.SelectedTab.CurrentItems^}"
|
||||||
|
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
||||||
|
Classes="ContentListView">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="corevm:IItemViewModel">
|
||||||
|
<local:ItemView HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="1"
|
||||||
|
x:CompileBindings="False"
|
||||||
|
x:Name="CurrentEmpty"
|
||||||
|
Margin="10"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="{DynamicResource ErrorBrush}"
|
||||||
|
IsVisible="{Binding AppState.SelectedTab.CurrentLocation^.Items^.Count, Converter={StaticResource EqualityConverter}, ConverterParameter=0}">
|
||||||
|
Empty
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Rectangle
|
||||||
|
Grid.Column="3"
|
||||||
|
Width="1"
|
||||||
|
Margin="0,10,0,10"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Fill="{DynamicResource ContentSeparatorBrush}" />
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<!--Borders-->
|
<!--Borders-->
|
||||||
|
|
||||||
|
|||||||
@@ -49,5 +49,24 @@ namespace FileTime.GuiApp.Views
|
|||||||
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
|
ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HeaderPointerPressed(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ClickCount == 2)
|
||||||
|
{
|
||||||
|
if (WindowState == WindowState.Maximized)
|
||||||
|
{
|
||||||
|
WindowState = WindowState.Normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WindowState = WindowState.Maximized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BeginMoveDrag(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Reactive.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
@@ -27,8 +28,7 @@ namespace FileTime.Providers.Local
|
|||||||
? new DirectoryInfo("/").GetDirectories()
|
? new DirectoryInfo("/").GetDirectories()
|
||||||
: Environment.GetLogicalDrives().Select(d => new DirectoryInfo(d));
|
: Environment.GetLogicalDrives().Select(d => new DirectoryInfo(d));
|
||||||
|
|
||||||
Items.Clear();
|
Items.OnNext(rootDirectories.Select(DirectoryToAbsolutePath).ToList());
|
||||||
Items.AddRange(rootDirectories.Select(DirectoryToAbsolutePath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<IItem> GetItemByNativePathAsync(NativePath nativePath)
|
public override Task<IItem> GetItemByNativePathAsync(NativePath nativePath)
|
||||||
@@ -78,7 +78,7 @@ namespace FileTime.Providers.Local
|
|||||||
true,
|
true,
|
||||||
GetDirectoryAttributes(directoryInfo),
|
GetDirectoryAttributes(directoryInfo),
|
||||||
this,
|
this,
|
||||||
GetItemsByContainer(directoryInfo)
|
Observable.Return(GetItemsByContainer(directoryInfo))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user