File scoped namespace
This commit is contained in:
@@ -1,66 +1,65 @@
|
||||
namespace FileTime.App.Core.Command
|
||||
{
|
||||
public enum Commands
|
||||
{
|
||||
None,
|
||||
namespace FileTime.App.Core.Command;
|
||||
|
||||
AutoRefresh,
|
||||
ChangeTimelineMode,
|
||||
CloseTab,
|
||||
Compress,
|
||||
Copy,
|
||||
CopyHash,
|
||||
CopyPath,
|
||||
CreateContainer,
|
||||
CreateElement,
|
||||
Cut,
|
||||
Edit,
|
||||
EnterRapidTravel,
|
||||
FindByName,
|
||||
FindByNameRegex,
|
||||
GoToHome,
|
||||
GoToPath,
|
||||
GoToProvider,
|
||||
GoToRoot,
|
||||
GoUp,
|
||||
HardDelete,
|
||||
Mark,
|
||||
MoveCursorDown,
|
||||
MoveCursorDownPage,
|
||||
MoveCursorUp,
|
||||
MoveCursorUpPage,
|
||||
MoveToFirst,
|
||||
MoveToLast,
|
||||
NextTimelineBlock,
|
||||
NextTimelineCommand,
|
||||
Open,
|
||||
OpenInFileBrowser,
|
||||
OpenOrRun,
|
||||
PasteMerge,
|
||||
PasteOverwrite,
|
||||
PasteSkip,
|
||||
PinFavorite,
|
||||
PreviousTimelineBlock,
|
||||
PreviousTimelineCommand,
|
||||
Refresh,
|
||||
Rename,
|
||||
RunCommand,
|
||||
ScanContainerSize,
|
||||
ShowAllShotcut,
|
||||
SoftDelete,
|
||||
SwitchToLastTab,
|
||||
SwitchToTab1,
|
||||
SwitchToTab2,
|
||||
SwitchToTab3,
|
||||
SwitchToTab4,
|
||||
SwitchToTab5,
|
||||
SwitchToTab6,
|
||||
SwitchToTab7,
|
||||
SwitchToTab8,
|
||||
TimelinePause,
|
||||
TimelineRefresh,
|
||||
TimelineStart,
|
||||
ToggleAdvancedIcons,
|
||||
ToggleHidden,
|
||||
}
|
||||
public enum Commands
|
||||
{
|
||||
None,
|
||||
|
||||
AutoRefresh,
|
||||
ChangeTimelineMode,
|
||||
CloseTab,
|
||||
Compress,
|
||||
Copy,
|
||||
CopyHash,
|
||||
CopyPath,
|
||||
CreateContainer,
|
||||
CreateElement,
|
||||
Cut,
|
||||
Edit,
|
||||
EnterRapidTravel,
|
||||
FindByName,
|
||||
FindByNameRegex,
|
||||
GoToHome,
|
||||
GoToPath,
|
||||
GoToProvider,
|
||||
GoToRoot,
|
||||
GoUp,
|
||||
HardDelete,
|
||||
Mark,
|
||||
MoveCursorDown,
|
||||
MoveCursorDownPage,
|
||||
MoveCursorUp,
|
||||
MoveCursorUpPage,
|
||||
MoveToFirst,
|
||||
MoveToLast,
|
||||
NextTimelineBlock,
|
||||
NextTimelineCommand,
|
||||
Open,
|
||||
OpenInFileBrowser,
|
||||
OpenOrRun,
|
||||
PasteMerge,
|
||||
PasteOverwrite,
|
||||
PasteSkip,
|
||||
PinFavorite,
|
||||
PreviousTimelineBlock,
|
||||
PreviousTimelineCommand,
|
||||
Refresh,
|
||||
Rename,
|
||||
RunCommand,
|
||||
ScanContainerSize,
|
||||
ShowAllShotcut,
|
||||
SoftDelete,
|
||||
SwitchToLastTab,
|
||||
SwitchToTab1,
|
||||
SwitchToTab2,
|
||||
SwitchToTab3,
|
||||
SwitchToTab4,
|
||||
SwitchToTab5,
|
||||
SwitchToTab6,
|
||||
SwitchToTab7,
|
||||
SwitchToTab8,
|
||||
TimelinePause,
|
||||
TimelineRefresh,
|
||||
TimelineStart,
|
||||
ToggleAdvancedIcons,
|
||||
ToggleHidden,
|
||||
}
|
||||
@@ -6,6 +6,10 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using DynamicData;
|
||||
|
||||
namespace FileTime.App.Core.Models
|
||||
namespace FileTime.App.Core.Models;
|
||||
|
||||
public class BindedCollection<T> : IDisposable
|
||||
{
|
||||
public class BindedCollection<T> : IDisposable
|
||||
private readonly IDisposable _disposable;
|
||||
public ReadOnlyObservableCollection<T> Collection { get; }
|
||||
public BindedCollection(IObservable<IChangeSet<T>> dynamicList)
|
||||
{
|
||||
private readonly IDisposable _disposable;
|
||||
public ReadOnlyObservableCollection<T> Collection { get; }
|
||||
public BindedCollection(IObservable<IChangeSet<T>> dynamicList)
|
||||
{
|
||||
_disposable = dynamicList
|
||||
.Bind(out var collection)
|
||||
.DisposeMany()
|
||||
.Subscribe();
|
||||
_disposable = dynamicList
|
||||
.Bind(out var collection)
|
||||
.DisposeMany()
|
||||
.Subscribe();
|
||||
|
||||
Collection = collection;
|
||||
}
|
||||
Collection = collection;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_disposable.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
_disposable.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
namespace FileTime.App.Core.Models.Enums
|
||||
namespace FileTime.App.Core.Models.Enums;
|
||||
|
||||
public enum ItemAttributeType
|
||||
{
|
||||
public enum ItemAttributeType
|
||||
{
|
||||
File,
|
||||
Element,
|
||||
Container,
|
||||
SizeContainer
|
||||
}
|
||||
File,
|
||||
Element,
|
||||
Container,
|
||||
SizeContainer
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
namespace FileTime.App.Core.Models.Enums
|
||||
namespace FileTime.App.Core.Models.Enums;
|
||||
|
||||
public enum ItemViewMode
|
||||
{
|
||||
public enum ItemViewMode
|
||||
{
|
||||
Default,
|
||||
Alternative,
|
||||
Selected,
|
||||
Marked,
|
||||
MarkedSelected,
|
||||
MarkedAlternative
|
||||
}
|
||||
Default,
|
||||
Alternative,
|
||||
Selected,
|
||||
Marked,
|
||||
MarkedSelected,
|
||||
MarkedAlternative
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
namespace FileTime.App.Core.Models.Enums
|
||||
namespace FileTime.App.Core.Models.Enums;
|
||||
|
||||
public enum ViewMode
|
||||
{
|
||||
public enum ViewMode
|
||||
{
|
||||
Default,
|
||||
RapidTravel
|
||||
}
|
||||
Default,
|
||||
RapidTravel
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
namespace FileTime.App.Core.Models
|
||||
{
|
||||
public class ItemNamePart
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public bool IsSpecial { get; set; }
|
||||
namespace FileTime.App.Core.Models;
|
||||
|
||||
public ItemNamePart(string text, bool isSpecial = false)
|
||||
{
|
||||
Text = text;
|
||||
IsSpecial = isSpecial;
|
||||
}
|
||||
public class ItemNamePart
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public bool IsSpecial { get; set; }
|
||||
|
||||
public ItemNamePart(string text, bool isSpecial = false)
|
||||
{
|
||||
Text = text;
|
||||
IsSpecial = isSpecial;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
{
|
||||
public interface IClipboardService
|
||||
{
|
||||
Type? CommandType { get; }
|
||||
IReadOnlyList<IAbsolutePath> Content { get; }
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
void AddContent(IAbsolutePath absolutePath);
|
||||
void RemoveContent(IAbsolutePath absolutePath);
|
||||
void Clear();
|
||||
void SetCommand<T>() where T : ITransportationCommand;
|
||||
}
|
||||
public interface IClipboardService
|
||||
{
|
||||
Type? CommandType { get; }
|
||||
IReadOnlyList<IAbsolutePath> Content { get; }
|
||||
|
||||
void AddContent(IAbsolutePath absolutePath);
|
||||
void RemoveContent(IAbsolutePath absolutePath);
|
||||
void Clear();
|
||||
void SetCommand<T>() where T : ITransportationCommand;
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using FileTime.App.Core.Command;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public interface ICommandHandler
|
||||
{
|
||||
public interface ICommandHandler
|
||||
{
|
||||
bool CanHandleCommand(Commands command);
|
||||
Task HandleCommandAsync(Commands command);
|
||||
}
|
||||
bool CanHandleCommand(Commands command);
|
||||
Task HandleCommandAsync(Commands command);
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using FileTime.App.Core.Command;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public interface ICommandHandlerService
|
||||
{
|
||||
public interface ICommandHandlerService
|
||||
{
|
||||
Task HandleCommandAsync(Commands command);
|
||||
}
|
||||
Task HandleCommandAsync(Commands command);
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using FileTime.App.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public interface IItemNameConverterService
|
||||
{
|
||||
public interface IItemNameConverterService
|
||||
{
|
||||
List<ItemNamePart> GetDisplayName(string name, string? searchText);
|
||||
string GetFileExtension(string fullName);
|
||||
string GetFileName(string fullName);
|
||||
}
|
||||
List<ItemNamePart> GetDisplayName(string name, string? searchText);
|
||||
string GetFileExtension(string fullName);
|
||||
string GetFileName(string fullName);
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Reactive.Concurrency;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public interface IRxSchedulerService
|
||||
{
|
||||
public interface IRxSchedulerService
|
||||
{
|
||||
IScheduler GetWorkerScheduler();
|
||||
IScheduler GetUIScheduler();
|
||||
}
|
||||
IScheduler GetWorkerScheduler();
|
||||
IScheduler GetUIScheduler();
|
||||
}
|
||||
@@ -1,17 +1,16 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using FileTime.App.Core.Models.Enums;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
{
|
||||
public interface IAppState
|
||||
{
|
||||
ObservableCollection<ITabViewModel> Tabs { get; }
|
||||
IObservable<ITabViewModel?> SelectedTab { get; }
|
||||
IObservable<string?> SearchText { get; }
|
||||
ViewMode ViewMode { get; }
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
void AddTab(ITabViewModel tabViewModel);
|
||||
void RemoveTab(ITabViewModel tabViewModel);
|
||||
void SetSearchText(string? searchText);
|
||||
}
|
||||
public interface IAppState
|
||||
{
|
||||
ObservableCollection<ITabViewModel> Tabs { get; }
|
||||
IObservable<ITabViewModel?> SelectedTab { get; }
|
||||
IObservable<string?> SearchText { get; }
|
||||
ViewMode ViewMode { get; }
|
||||
|
||||
void AddTab(ITabViewModel tabViewModel);
|
||||
void RemoveTab(ITabViewModel tabViewModel);
|
||||
void SetSearchText(string? searchText);
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using FileTime.Core.Models;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel>
|
||||
{
|
||||
public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel>
|
||||
{
|
||||
long Size { get; set; }
|
||||
}
|
||||
long Size { get; set; }
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using FileTime.Core.Models;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface IContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel>
|
||||
{
|
||||
public interface IContainerViewModel : IItemViewModel, IInitable<IContainer, ITabViewModel>
|
||||
{
|
||||
IContainer? Container { get; }
|
||||
}
|
||||
IContainer? Container { get; }
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
using FileTime.Core.Models;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface IElementViewModel : IItemViewModel, IInitable<IElement, ITabViewModel>
|
||||
{
|
||||
public interface IElementViewModel : IItemViewModel, IInitable<IElement, ITabViewModel>
|
||||
{
|
||||
long? Size { get; set; }
|
||||
}
|
||||
long? Size { get; set; }
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using FileTime.Core.Models;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface IFileViewModel : IElementViewModel, IInitable<IFileElement, ITabViewModel>
|
||||
{
|
||||
public interface IFileViewModel : IElementViewModel, IInitable<IFileElement, ITabViewModel>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,18 @@ using FileTime.App.Core.Models.Enums;
|
||||
using FileTime.Core.Models;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface IItemViewModel : IInitable<IItem, ITabViewModel>
|
||||
{
|
||||
public interface IItemViewModel : IInitable<IItem, ITabViewModel>
|
||||
{
|
||||
IItem? BaseItem { get; set; }
|
||||
IObservable<IReadOnlyList<ItemNamePart>>? DisplayName { get; set; }
|
||||
string? DisplayNameText { get; set; }
|
||||
IObservable<bool>? IsSelected { get; set; }
|
||||
IObservable<bool>? IsMarked { get; set; }
|
||||
IObservable<bool> IsAlternative { get; }
|
||||
IObservable<ItemViewMode> ViewMode { get; set; }
|
||||
DateTime? CreatedAt { get; set; }
|
||||
string? Attributes { get; set; }
|
||||
bool EqualsTo(IItemViewModel? itemViewModel);
|
||||
}
|
||||
IItem? BaseItem { get; set; }
|
||||
IObservable<IReadOnlyList<ItemNamePart>>? DisplayName { get; set; }
|
||||
string? DisplayNameText { get; set; }
|
||||
IObservable<bool>? IsSelected { get; set; }
|
||||
IObservable<bool>? IsMarked { get; set; }
|
||||
IObservable<bool> IsAlternative { get; }
|
||||
IObservable<ItemViewMode> ViewMode { get; set; }
|
||||
DateTime? CreatedAt { get; set; }
|
||||
string? Attributes { get; set; }
|
||||
bool EqualsTo(IItemViewModel? itemViewModel);
|
||||
}
|
||||
@@ -5,26 +5,25 @@ using FileTime.Core.Models;
|
||||
using FileTime.Core.Services;
|
||||
using InitableService;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public interface ITabViewModel : IInitable<ITab, int>
|
||||
{
|
||||
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<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; }
|
||||
IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; }
|
||||
BindedCollection<IItemViewModel>? CurrentItemsCollection { get; }
|
||||
BindedCollection<IItemViewModel>? SelectedsChildrenCollection { get; }
|
||||
BindedCollection<IItemViewModel>? ParentsChildrenCollection { get; }
|
||||
IObservable<IReadOnlyCollection<IItemViewModel>?> CurrentItemsCollectionObservable { get; }
|
||||
void ClearMarkedItems();
|
||||
void RemoveMarkedItem(IAbsolutePath item);
|
||||
void AddMarkedItem(IAbsolutePath item);
|
||||
void ToggleMarkedItem(IAbsolutePath item);
|
||||
}
|
||||
ITab? Tab { get; }
|
||||
int TabNumber { get; }
|
||||
IObservable<bool> IsSelected { get; }
|
||||
IObservable<IContainer?> CurrentLocation { get; }
|
||||
IObservable<IItemViewModel?> CurrentSelectedItem { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; }
|
||||
IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; }
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; }
|
||||
BindedCollection<IItemViewModel>? CurrentItemsCollection { get; }
|
||||
BindedCollection<IItemViewModel>? SelectedsChildrenCollection { get; }
|
||||
BindedCollection<IItemViewModel>? ParentsChildrenCollection { get; }
|
||||
IObservable<IReadOnlyCollection<IItemViewModel>?> CurrentItemsCollectionObservable { get; }
|
||||
void ClearMarkedItems();
|
||||
void RemoveMarkedItem(IAbsolutePath item);
|
||||
void AddMarkedItem(IAbsolutePath item);
|
||||
void ToggleMarkedItem(IAbsolutePath item);
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace FileTime.App.Core.Extensions
|
||||
namespace FileTime.App.Core.Extensions;
|
||||
|
||||
public static class ObservableExtensions
|
||||
{
|
||||
public static class ObservableExtensions
|
||||
{
|
||||
public static IObservable<T> WhereNotNull<T>(this IObservable<T?> source) => source.Where(c => c != null)!;
|
||||
}
|
||||
public static IObservable<T> WhereNotNull<T>(this IObservable<T?> source) => source.Where(c => c != null)!;
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Extensions
|
||||
namespace FileTime.App.Core.Extensions;
|
||||
|
||||
public static class ViewModelExtensions
|
||||
{
|
||||
public static class ViewModelExtensions
|
||||
public static IAbsolutePath ToAbsolutePath(this IItemViewModel itemViewModel)
|
||||
{
|
||||
public static IAbsolutePath ToAbsolutePath(this IItemViewModel itemViewModel)
|
||||
{
|
||||
var item = itemViewModel.BaseItem ?? throw new ArgumentException($"{nameof(itemViewModel)} does not have {nameof(IItemViewModel.BaseItem)}");
|
||||
return new AbsolutePath(item);
|
||||
}
|
||||
var item = itemViewModel.BaseItem ?? throw new ArgumentException($"{nameof(itemViewModel)} does not have {nameof(IItemViewModel.BaseItem)}");
|
||||
return new AbsolutePath(item);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="morelinq" Version="3.3.2" />
|
||||
<PackageReference Include="MvvmGen" Version="1.1.5" />
|
||||
|
||||
@@ -1,51 +1,50 @@
|
||||
using FileTime.Core.Command;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public class ClipboardService : IClipboardService
|
||||
{
|
||||
public class ClipboardService : IClipboardService
|
||||
private List<IAbsolutePath> _content;
|
||||
public IReadOnlyList<IAbsolutePath> Content { get; private set; }
|
||||
public Type? CommandType { get; private set; }
|
||||
|
||||
public ClipboardService()
|
||||
{
|
||||
private List<IAbsolutePath> _content;
|
||||
public IReadOnlyList<IAbsolutePath> Content { get; private set; }
|
||||
public Type? CommandType { get; private set; }
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
}
|
||||
|
||||
public ClipboardService()
|
||||
public void AddContent(IAbsolutePath absolutePath)
|
||||
{
|
||||
foreach (var content in _content)
|
||||
{
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
if (content.Equals(absolutePath)) return;
|
||||
}
|
||||
|
||||
public void AddContent(IAbsolutePath absolutePath)
|
||||
_content.Add(absolutePath);
|
||||
}
|
||||
|
||||
public void RemoveContent(IAbsolutePath absolutePath)
|
||||
{
|
||||
for (var i = 0; i < _content.Count; i++)
|
||||
{
|
||||
foreach (var content in _content)
|
||||
if (_content[i].Equals(absolutePath))
|
||||
{
|
||||
if (content.Equals(absolutePath)) return;
|
||||
_content.RemoveAt(i--);
|
||||
}
|
||||
|
||||
_content.Add(absolutePath);
|
||||
}
|
||||
|
||||
public void RemoveContent(IAbsolutePath absolutePath)
|
||||
{
|
||||
for (var i = 0; i < _content.Count; i++)
|
||||
{
|
||||
if (_content[i].Equals(absolutePath))
|
||||
{
|
||||
_content.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
CommandType = null;
|
||||
}
|
||||
|
||||
public void SetCommand<T>() where T : ITransportationCommand
|
||||
{
|
||||
CommandType = typeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_content = new List<IAbsolutePath>();
|
||||
Content = _content.AsReadOnly();
|
||||
CommandType = null;
|
||||
}
|
||||
|
||||
public void SetCommand<T>() where T : ITransportationCommand
|
||||
{
|
||||
CommandType = typeof(T);
|
||||
}
|
||||
}
|
||||
@@ -4,51 +4,50 @@ using FileTime.App.Core.Command;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
namespace FileTime.App.Core.Services.CommandHandler;
|
||||
|
||||
public abstract class CommandHandlerBase : ICommandHandler
|
||||
{
|
||||
public abstract class CommandHandlerBase : ICommandHandler
|
||||
private readonly Dictionary<Commands, Func<Task>> _commandHandlers = new();
|
||||
private readonly IAppState? _appState;
|
||||
|
||||
protected CommandHandlerBase(IAppState? appState = null)
|
||||
{
|
||||
private readonly Dictionary<Commands, Func<Task>> _commandHandlers = new();
|
||||
private readonly IAppState? _appState;
|
||||
_appState = appState;
|
||||
}
|
||||
|
||||
protected CommandHandlerBase(IAppState? appState = null)
|
||||
public bool CanHandleCommand(Commands command) => _commandHandlers.ContainsKey(command);
|
||||
|
||||
public async Task HandleCommandAsync(Commands command) => await _commandHandlers[command].Invoke();
|
||||
|
||||
protected void AddCommandHandler(Commands command, Func<Task> handler) => _commandHandlers.Add(command, handler);
|
||||
protected void AddCommandHandlers(IEnumerable<(Commands command, Func<Task> handler)> commandHandlers)
|
||||
{
|
||||
foreach (var (command, handler) in commandHandlers)
|
||||
{
|
||||
_appState = appState;
|
||||
}
|
||||
|
||||
public bool CanHandleCommand(Commands command) => _commandHandlers.ContainsKey(command);
|
||||
|
||||
public async Task HandleCommandAsync(Commands command) => await _commandHandlers[command].Invoke();
|
||||
|
||||
protected void AddCommandHandler(Commands command, Func<Task> handler) => _commandHandlers.Add(command, handler);
|
||||
protected void AddCommandHandlers(IEnumerable<(Commands command, Func<Task> handler)> commandHandlers)
|
||||
{
|
||||
foreach (var (command, handler) in commandHandlers)
|
||||
{
|
||||
AddCommandHandler(command, handler);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RemoveCommandHandler(Commands command) => _commandHandlers.Remove(command);
|
||||
|
||||
protected IDisposable SaveSelectedTab(Action<ITabViewModel?> handler) => RunWithAppState(appState => appState.SelectedTab.Subscribe(handler));
|
||||
protected IDisposable SaveCurrentSelectedItem(Action<IItemViewModel?> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return<IItemViewModel?>(null) : t.CurrentSelectedItem).Switch().Subscribe(handler));
|
||||
|
||||
protected IDisposable SaveCurrentLocation(Action<IContainer?> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation).Switch().Subscribe(handler));
|
||||
|
||||
protected IDisposable SaveCurrentItems(Action<IEnumerable<IItemViewModel>> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t?.CurrentItemsCollectionObservable ?? Observable.Return((IEnumerable<IItemViewModel>?)Enumerable.Empty<IItemViewModel>())).Switch().Subscribe(i => handler(i ?? Enumerable.Empty<IItemViewModel>())));
|
||||
|
||||
protected IDisposable SaveMarkedItems(Action<IChangeSet<IAbsolutePath>> handler)
|
||||
=> RunWithAppState(appstate => appstate.SelectedTab.Select(t => t == null ? Observable.Empty<IChangeSet<IAbsolutePath>>() : t.MarkedItems).Switch().Subscribe(handler));
|
||||
|
||||
private IDisposable RunWithAppState(Func<IAppState, IDisposable> act)
|
||||
{
|
||||
if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHandlerBase)}.");
|
||||
|
||||
return act(_appState);
|
||||
AddCommandHandler(command, handler);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RemoveCommandHandler(Commands command) => _commandHandlers.Remove(command);
|
||||
|
||||
protected IDisposable SaveSelectedTab(Action<ITabViewModel?> handler) => RunWithAppState(appState => appState.SelectedTab.Subscribe(handler));
|
||||
protected IDisposable SaveCurrentSelectedItem(Action<IItemViewModel?> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return<IItemViewModel?>(null) : t.CurrentSelectedItem).Switch().Subscribe(handler));
|
||||
|
||||
protected IDisposable SaveCurrentLocation(Action<IContainer?> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return<IContainer?>(null) : t.CurrentLocation).Switch().Subscribe(handler));
|
||||
|
||||
protected IDisposable SaveCurrentItems(Action<IEnumerable<IItemViewModel>> handler)
|
||||
=> RunWithAppState(appState => appState.SelectedTab.Select(t => t?.CurrentItemsCollectionObservable ?? Observable.Return((IEnumerable<IItemViewModel>?)Enumerable.Empty<IItemViewModel>())).Switch().Subscribe(i => handler(i ?? Enumerable.Empty<IItemViewModel>())));
|
||||
|
||||
protected IDisposable SaveMarkedItems(Action<IChangeSet<IAbsolutePath>> handler)
|
||||
=> RunWithAppState(appstate => appstate.SelectedTab.Select(t => t == null ? Observable.Empty<IChangeSet<IAbsolutePath>>() : t.MarkedItems).Switch().Subscribe(handler));
|
||||
|
||||
private IDisposable RunWithAppState(Func<IAppState, IDisposable> act)
|
||||
{
|
||||
if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHandlerBase)}.");
|
||||
|
||||
return act(_appState);
|
||||
}
|
||||
}
|
||||
@@ -6,91 +6,90 @@ using FileTime.Core.Command;
|
||||
using FileTime.Core.Command.Copy;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
namespace FileTime.App.Core.Services.CommandHandler;
|
||||
|
||||
public class ItemManipulationCommandHandler : CommandHandlerBase
|
||||
{
|
||||
public class ItemManipulationCommandHandler : CommandHandlerBase
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IItemViewModel? _currentSelectedItem;
|
||||
private readonly ICommandHandlerService _commandHandlerService;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private BindedCollection<IAbsolutePath>? _markedItems;
|
||||
|
||||
public ItemManipulationCommandHandler(
|
||||
IAppState appState,
|
||||
ICommandHandlerService commandHandlerService,
|
||||
IClipboardService clipboardService) : base(appState)
|
||||
{
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IItemViewModel? _currentSelectedItem;
|
||||
private readonly ICommandHandlerService _commandHandlerService;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
private BindedCollection<IAbsolutePath>? _markedItems;
|
||||
_commandHandlerService = commandHandlerService;
|
||||
_clipboardService = clipboardService;
|
||||
|
||||
public ItemManipulationCommandHandler(
|
||||
IAppState appState,
|
||||
ICommandHandlerService commandHandlerService,
|
||||
IClipboardService clipboardService) : base(appState)
|
||||
SaveSelectedTab(t =>
|
||||
{
|
||||
_commandHandlerService = commandHandlerService;
|
||||
_clipboardService = clipboardService;
|
||||
_selectedTab = t;
|
||||
_markedItems?.Dispose();
|
||||
_markedItems = t == null ? null : new BindedCollection<IAbsolutePath>(t.MarkedItems);
|
||||
});
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
|
||||
SaveSelectedTab(t =>
|
||||
{
|
||||
_selectedTab = t;
|
||||
_markedItems?.Dispose();
|
||||
_markedItems = t == null ? null : new BindedCollection<IAbsolutePath>(t.MarkedItems);
|
||||
});
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
|
||||
AddCommandHandlers(new (Commands, Func<Task>)[]
|
||||
{
|
||||
(Commands.Copy, Copy),
|
||||
(Commands.Mark, MarkItem),
|
||||
(Commands.PasteMerge, PasteMerge),
|
||||
(Commands.PasteOverwrite, PasteOverwrite),
|
||||
(Commands.PasteSkip, PasteSkip),
|
||||
});
|
||||
}
|
||||
|
||||
private async Task MarkItem()
|
||||
AddCommandHandlers(new (Commands, Func<Task>)[]
|
||||
{
|
||||
if (_selectedTab == null || _currentSelectedItem?.BaseItem?.FullName == null) return;
|
||||
(Commands.Copy, Copy),
|
||||
(Commands.Mark, MarkItem),
|
||||
(Commands.PasteMerge, PasteMerge),
|
||||
(Commands.PasteOverwrite, PasteOverwrite),
|
||||
(Commands.PasteSkip, PasteSkip),
|
||||
});
|
||||
}
|
||||
|
||||
_selectedTab.ToggleMarkedItem(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
await _commandHandlerService.HandleCommandAsync(Commands.MoveCursorDown);
|
||||
}
|
||||
private async Task MarkItem()
|
||||
{
|
||||
if (_selectedTab == null || _currentSelectedItem?.BaseItem?.FullName == null) return;
|
||||
|
||||
private Task Copy()
|
||||
_selectedTab.ToggleMarkedItem(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
await _commandHandlerService.HandleCommandAsync(Commands.MoveCursorDown);
|
||||
}
|
||||
|
||||
private Task Copy()
|
||||
{
|
||||
_clipboardService.Clear();
|
||||
_clipboardService.SetCommand<CopyCommand>();
|
||||
|
||||
if ((_markedItems?.Collection.Count ?? 0) > 0)
|
||||
{
|
||||
_clipboardService.Clear();
|
||||
_clipboardService.SetCommand<CopyCommand>();
|
||||
|
||||
if ((_markedItems?.Collection.Count ?? 0) > 0)
|
||||
foreach (var item in _markedItems!.Collection)
|
||||
{
|
||||
foreach (var item in _markedItems!.Collection)
|
||||
{
|
||||
_clipboardService.AddContent(item);
|
||||
}
|
||||
|
||||
_selectedTab?.ClearMarkedItems();
|
||||
}
|
||||
else if (_currentSelectedItem?.BaseItem != null)
|
||||
{
|
||||
_clipboardService.AddContent(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
_clipboardService.AddContent(item);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
_selectedTab?.ClearMarkedItems();
|
||||
}
|
||||
else if (_currentSelectedItem?.BaseItem != null)
|
||||
{
|
||||
_clipboardService.AddContent(new AbsolutePath(_currentSelectedItem.BaseItem));
|
||||
}
|
||||
|
||||
private async Task PasteMerge()
|
||||
{
|
||||
await Paste(TransportMode.Merge);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task PasteOverwrite()
|
||||
{
|
||||
await Paste(TransportMode.Overwrite);
|
||||
}
|
||||
private async Task PasteMerge()
|
||||
{
|
||||
await Paste(TransportMode.Merge);
|
||||
}
|
||||
|
||||
private async Task PasteSkip()
|
||||
{
|
||||
await Paste(TransportMode.Skip);
|
||||
}
|
||||
private async Task PasteOverwrite()
|
||||
{
|
||||
await Paste(TransportMode.Overwrite);
|
||||
}
|
||||
|
||||
private Task Paste(TransportMode skip)
|
||||
{
|
||||
if (_clipboardService.CommandType is null) return Task.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
private async Task PasteSkip()
|
||||
{
|
||||
await Paste(TransportMode.Skip);
|
||||
}
|
||||
|
||||
private Task Paste(TransportMode skip)
|
||||
{
|
||||
if (_clipboardService.CommandType is null) return Task.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -4,65 +4,64 @@ using FileTime.App.Core.Extensions;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services.CommandHandler
|
||||
namespace FileTime.App.Core.Services.CommandHandler;
|
||||
|
||||
public class NavigationCommandHandler : CommandHandlerBase
|
||||
{
|
||||
public class NavigationCommandHandler : CommandHandlerBase
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IContainer? _currentLocation;
|
||||
private IItemViewModel? _currentSelectedItem;
|
||||
private IEnumerable<IItemViewModel> _currentItems = Enumerable.Empty<IItemViewModel>();
|
||||
|
||||
public NavigationCommandHandler(IAppState appState) : base(appState)
|
||||
{
|
||||
private ITabViewModel? _selectedTab;
|
||||
private IContainer? _currentLocation;
|
||||
private IItemViewModel? _currentSelectedItem;
|
||||
private IEnumerable<IItemViewModel> _currentItems = Enumerable.Empty<IItemViewModel>();
|
||||
SaveSelectedTab(t => _selectedTab = t);
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
SaveCurrentLocation(l => _currentLocation = l);
|
||||
SaveCurrentItems(i => _currentItems = i);
|
||||
|
||||
public NavigationCommandHandler(IAppState appState) : base(appState)
|
||||
AddCommandHandlers(new (Commands, Func<Task>)[]
|
||||
{
|
||||
SaveSelectedTab(t => _selectedTab = t);
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
SaveCurrentLocation(l => _currentLocation = l);
|
||||
SaveCurrentItems(i => _currentItems = i);
|
||||
(Commands.GoUp, GoUp),
|
||||
(Commands.MoveCursorDown, MoveCursorDown),
|
||||
(Commands.MoveCursorUp, MoveCursorUp),
|
||||
(Commands.Open, OpenContainer),
|
||||
});
|
||||
}
|
||||
|
||||
AddCommandHandlers(new (Commands, Func<Task>)[]
|
||||
{
|
||||
(Commands.GoUp, GoUp),
|
||||
(Commands.MoveCursorDown, MoveCursorDown),
|
||||
(Commands.MoveCursorUp, MoveCursorUp),
|
||||
(Commands.Open, OpenContainer),
|
||||
});
|
||||
}
|
||||
private Task OpenContainer()
|
||||
{
|
||||
if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask;
|
||||
|
||||
private Task OpenContainer()
|
||||
{
|
||||
if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask;
|
||||
_selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
_selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
private async Task GoUp()
|
||||
{
|
||||
if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return;
|
||||
_selectedTab?.Tab?.SetCurrentLocation(newContainer);
|
||||
}
|
||||
|
||||
private async Task GoUp()
|
||||
{
|
||||
if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return;
|
||||
_selectedTab?.Tab?.SetCurrentLocation(newContainer);
|
||||
}
|
||||
private Task MoveCursorDown()
|
||||
{
|
||||
SelectNewSelectedItem(i => i.SkipWhile(i => !i.EqualsTo(_currentSelectedItem)).Skip(1).FirstOrDefault());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task MoveCursorDown()
|
||||
{
|
||||
SelectNewSelectedItem(i => i.SkipWhile(i => !i.EqualsTo(_currentSelectedItem)).Skip(1).FirstOrDefault());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
private Task MoveCursorUp()
|
||||
{
|
||||
SelectNewSelectedItem(i => i.TakeWhile(i => !i.EqualsTo(_currentSelectedItem)).LastOrDefault());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task MoveCursorUp()
|
||||
{
|
||||
SelectNewSelectedItem(i => i.TakeWhile(i => !i.EqualsTo(_currentSelectedItem)).LastOrDefault());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
private void SelectNewSelectedItem(Func<IEnumerable<IItemViewModel>, IItemViewModel?> getNewSelected)
|
||||
{
|
||||
if (_selectedTab is null || _currentLocation is null) return;
|
||||
|
||||
private void SelectNewSelectedItem(Func<IEnumerable<IItemViewModel>, IItemViewModel?> getNewSelected)
|
||||
{
|
||||
if (_selectedTab is null || _currentLocation is null) return;
|
||||
var newSelectedItem = getNewSelected(_currentItems);
|
||||
if (newSelectedItem == null) return;
|
||||
|
||||
var newSelectedItem = getNewSelected(_currentItems);
|
||||
if (newSelectedItem == null) return;
|
||||
|
||||
_selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath());
|
||||
}
|
||||
_selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath());
|
||||
}
|
||||
}
|
||||
@@ -1,80 +1,79 @@
|
||||
using FileTime.App.Core.Command;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public class CommandHandlerService : ICommandHandlerService
|
||||
{
|
||||
public class CommandHandlerService : ICommandHandlerService
|
||||
private readonly Lazy<IEnumerable<ICommandHandler>> _commandHandlers;
|
||||
|
||||
public CommandHandlerService(IServiceProvider serviceProvider)
|
||||
{
|
||||
private readonly Lazy<IEnumerable<ICommandHandler>> _commandHandlers;
|
||||
_commandHandlers = new Lazy<IEnumerable<ICommandHandler>>(() => serviceProvider.GetServices<ICommandHandler>());
|
||||
|
||||
public CommandHandlerService(IServiceProvider serviceProvider)
|
||||
//(Commands.AutoRefresh, ToggleAutoRefresh),
|
||||
//(Commands.ChangeTimelineMode, ChangeTimelineMode),
|
||||
//(Commands.CloseTab, CloseTab),
|
||||
//(Commands.Compress, Compress),
|
||||
//(Commands.Copy, Copy),
|
||||
//(Commands.CopyHash, CopyHash),
|
||||
//(Commands.CopyPath, CopyPath),
|
||||
//(Commands.CreateContainer, CreateContainer),
|
||||
//(Commands.CreateElement, CreateElement),
|
||||
//(Commands.Cut, Cut),
|
||||
//(Commands.Edit, Edit),
|
||||
//(Commands.EnterRapidTravel, EnterRapidTravelMode),
|
||||
//(Commands.FindByName, FindByName),
|
||||
//(Commands.FindByNameRegex, FindByNameRegex),
|
||||
//(Commands.GoToHome, GotToHome),
|
||||
//(Commands.GoToPath, GoToContainer),
|
||||
//(Commands.GoToProvider, GotToProvider),
|
||||
//(Commands.GoToRoot, GotToRoot),
|
||||
//(Commands.HardDelete, HardDelete),
|
||||
//(Commands.Mark, MarkCurrentItem),
|
||||
//(Commands.MoveCursorDownPage, MoveCursorDownPage),
|
||||
//(Commands.MoveCursorUpPage, MoveCursorUpPage),
|
||||
//(Commands.MoveToFirst, MoveToFirst),
|
||||
//(Commands.MoveToLast, MoveToLast),
|
||||
//(Commands.NextTimelineBlock, SelectNextTimelineBlock),
|
||||
//(Commands.NextTimelineCommand, SelectNextTimelineCommand),
|
||||
//(Commands.OpenInFileBrowser, OpenInDefaultFileExplorer),
|
||||
//(Commands.OpenOrRun, OpenOrRun),
|
||||
//(Commands.PasteMerge, PasteMerge),
|
||||
//(Commands.PasteOverwrite, PasteOverwrite),
|
||||
//(Commands.PasteSkip, PasteSkip),
|
||||
//(Commands.PinFavorite, PinFavorite),
|
||||
//(Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock),
|
||||
//(Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand),
|
||||
//(Commands.Refresh, RefreshCurrentLocation),
|
||||
//(Commands.Rename, Rename),
|
||||
//(Commands.RunCommand, RunCommandInContainer),
|
||||
//(Commands.ScanContainerSize, ScanContainerSize),
|
||||
//(Commands.ShowAllShotcut, ShowAllShortcut),
|
||||
//(Commands.SoftDelete, SoftDelete),
|
||||
//(Commands.SwitchToLastTab, async() => await SwitchToTab(-1)),
|
||||
//(Commands.SwitchToTab1, async() => await SwitchToTab(1)),
|
||||
//(Commands.SwitchToTab2, async() => await SwitchToTab(2)),
|
||||
//(Commands.SwitchToTab3, async() => await SwitchToTab(3)),
|
||||
//(Commands.SwitchToTab4, async() => await SwitchToTab(4)),
|
||||
//(Commands.SwitchToTab5, async() => await SwitchToTab(5)),
|
||||
//(Commands.SwitchToTab6, async() => await SwitchToTab(6)),
|
||||
//(Commands.SwitchToTab7, async() => await SwitchToTab(7)),
|
||||
//(Commands.SwitchToTab8, async() => await SwitchToTab(8)),
|
||||
//(Commands.TimelinePause, PauseTimeline),
|
||||
//(Commands.TimelineRefresh, RefreshTimeline),
|
||||
//(Commands.TimelineStart, ContinueTimeline),
|
||||
//(Commands.ToggleAdvancedIcons, ToggleAdvancedIcons),
|
||||
//(Commands.ToggleHidden, ToggleHidden),
|
||||
}
|
||||
|
||||
public async Task HandleCommandAsync(Commands command)
|
||||
{
|
||||
var handler = _commandHandlers.Value.FirstOrDefault(h => h.CanHandleCommand(command));
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
_commandHandlers = new Lazy<IEnumerable<ICommandHandler>>(() => serviceProvider.GetServices<ICommandHandler>());
|
||||
|
||||
//(Commands.AutoRefresh, ToggleAutoRefresh),
|
||||
//(Commands.ChangeTimelineMode, ChangeTimelineMode),
|
||||
//(Commands.CloseTab, CloseTab),
|
||||
//(Commands.Compress, Compress),
|
||||
//(Commands.Copy, Copy),
|
||||
//(Commands.CopyHash, CopyHash),
|
||||
//(Commands.CopyPath, CopyPath),
|
||||
//(Commands.CreateContainer, CreateContainer),
|
||||
//(Commands.CreateElement, CreateElement),
|
||||
//(Commands.Cut, Cut),
|
||||
//(Commands.Edit, Edit),
|
||||
//(Commands.EnterRapidTravel, EnterRapidTravelMode),
|
||||
//(Commands.FindByName, FindByName),
|
||||
//(Commands.FindByNameRegex, FindByNameRegex),
|
||||
//(Commands.GoToHome, GotToHome),
|
||||
//(Commands.GoToPath, GoToContainer),
|
||||
//(Commands.GoToProvider, GotToProvider),
|
||||
//(Commands.GoToRoot, GotToRoot),
|
||||
//(Commands.HardDelete, HardDelete),
|
||||
//(Commands.Mark, MarkCurrentItem),
|
||||
//(Commands.MoveCursorDownPage, MoveCursorDownPage),
|
||||
//(Commands.MoveCursorUpPage, MoveCursorUpPage),
|
||||
//(Commands.MoveToFirst, MoveToFirst),
|
||||
//(Commands.MoveToLast, MoveToLast),
|
||||
//(Commands.NextTimelineBlock, SelectNextTimelineBlock),
|
||||
//(Commands.NextTimelineCommand, SelectNextTimelineCommand),
|
||||
//(Commands.OpenInFileBrowser, OpenInDefaultFileExplorer),
|
||||
//(Commands.OpenOrRun, OpenOrRun),
|
||||
//(Commands.PasteMerge, PasteMerge),
|
||||
//(Commands.PasteOverwrite, PasteOverwrite),
|
||||
//(Commands.PasteSkip, PasteSkip),
|
||||
//(Commands.PinFavorite, PinFavorite),
|
||||
//(Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock),
|
||||
//(Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand),
|
||||
//(Commands.Refresh, RefreshCurrentLocation),
|
||||
//(Commands.Rename, Rename),
|
||||
//(Commands.RunCommand, RunCommandInContainer),
|
||||
//(Commands.ScanContainerSize, ScanContainerSize),
|
||||
//(Commands.ShowAllShotcut, ShowAllShortcut),
|
||||
//(Commands.SoftDelete, SoftDelete),
|
||||
//(Commands.SwitchToLastTab, async() => await SwitchToTab(-1)),
|
||||
//(Commands.SwitchToTab1, async() => await SwitchToTab(1)),
|
||||
//(Commands.SwitchToTab2, async() => await SwitchToTab(2)),
|
||||
//(Commands.SwitchToTab3, async() => await SwitchToTab(3)),
|
||||
//(Commands.SwitchToTab4, async() => await SwitchToTab(4)),
|
||||
//(Commands.SwitchToTab5, async() => await SwitchToTab(5)),
|
||||
//(Commands.SwitchToTab6, async() => await SwitchToTab(6)),
|
||||
//(Commands.SwitchToTab7, async() => await SwitchToTab(7)),
|
||||
//(Commands.SwitchToTab8, async() => await SwitchToTab(8)),
|
||||
//(Commands.TimelinePause, PauseTimeline),
|
||||
//(Commands.TimelineRefresh, RefreshTimeline),
|
||||
//(Commands.TimelineStart, ContinueTimeline),
|
||||
//(Commands.ToggleAdvancedIcons, ToggleAdvancedIcons),
|
||||
//(Commands.ToggleHidden, ToggleHidden),
|
||||
}
|
||||
|
||||
public async Task HandleCommandAsync(Commands command)
|
||||
{
|
||||
var handler = _commandHandlers.Value.FirstOrDefault(h => h.CanHandleCommand(command));
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
await handler.HandleCommandAsync(command);
|
||||
}
|
||||
await handler.HandleCommandAsync(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,55 @@
|
||||
using FileTime.App.Core.Models;
|
||||
|
||||
namespace FileTime.App.Core.Services
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public class ItemNameConverterService : IItemNameConverterService
|
||||
{
|
||||
public class ItemNameConverterService : IItemNameConverterService
|
||||
public List<ItemNamePart> GetDisplayName(string name, string? searchText)
|
||||
{
|
||||
public List<ItemNamePart> GetDisplayName(string name, string? searchText)
|
||||
var nameParts = new List<ItemNamePart>();
|
||||
searchText = searchText?.ToLower();
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
var nameParts = new List<ItemNamePart>();
|
||||
searchText = searchText?.ToLower();
|
||||
var nameLeft = name;
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
while (nameLeft.ToLower().IndexOf(searchText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1)
|
||||
{
|
||||
var nameLeft = name;
|
||||
var before = rapidTextStart > 0 ? nameLeft.Substring(0, rapidTextStart) : null;
|
||||
var rapidTravel = nameLeft.Substring(rapidTextStart, searchText.Length);
|
||||
|
||||
while (nameLeft.ToLower().IndexOf(searchText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1)
|
||||
nameLeft = nameLeft.Substring(rapidTextStart + searchText.Length);
|
||||
|
||||
if (before != null)
|
||||
{
|
||||
var before = rapidTextStart > 0 ? nameLeft.Substring(0, rapidTextStart) : null;
|
||||
var rapidTravel = nameLeft.Substring(rapidTextStart, searchText.Length);
|
||||
|
||||
nameLeft = nameLeft.Substring(rapidTextStart + searchText.Length);
|
||||
|
||||
if (before != null)
|
||||
{
|
||||
nameParts.Add(new ItemNamePart(before));
|
||||
}
|
||||
|
||||
nameParts.Add(new ItemNamePart(rapidTravel, true));
|
||||
nameParts.Add(new ItemNamePart(before));
|
||||
}
|
||||
|
||||
if (nameLeft.Length > 0)
|
||||
{
|
||||
nameParts.Add(new ItemNamePart(nameLeft));
|
||||
}
|
||||
nameParts.Add(new ItemNamePart(rapidTravel, true));
|
||||
}
|
||||
else
|
||||
|
||||
if (nameLeft.Length > 0)
|
||||
{
|
||||
nameParts.Add(new ItemNamePart(name));
|
||||
nameParts.Add(new ItemNamePart(nameLeft));
|
||||
}
|
||||
return nameParts;
|
||||
}
|
||||
|
||||
public string GetFileName(string fullName)
|
||||
else
|
||||
{
|
||||
var parts = fullName.Split('.');
|
||||
var fileName = string.Join('.', parts[..^1]);
|
||||
return string.IsNullOrEmpty(fileName) ? fullName : fileName;
|
||||
}
|
||||
|
||||
public string GetFileExtension(string fullName)
|
||||
{
|
||||
var parts = fullName.Split('.');
|
||||
return parts.Length == 1 || (parts.Length == 2 && string.IsNullOrEmpty(parts[0])) ? "" : parts[^1];
|
||||
nameParts.Add(new ItemNamePart(name));
|
||||
}
|
||||
return nameParts;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFileName(string fullName)
|
||||
{
|
||||
var parts = fullName.Split('.');
|
||||
var fileName = string.Join('.', parts[..^1]);
|
||||
return string.IsNullOrEmpty(fileName) ? fullName : fileName;
|
||||
}
|
||||
|
||||
public string GetFileExtension(string fullName)
|
||||
{
|
||||
var parts = fullName.Split('.');
|
||||
return parts.Length == 1 || (parts.Length == 2 && string.IsNullOrEmpty(parts[0])) ? "" : parts[^1];
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,26 @@ using FileTime.App.Core.Services.CommandHandler;
|
||||
using FileTime.App.Core.ViewModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace FileTime.App.Core
|
||||
{
|
||||
public static class Startup
|
||||
{
|
||||
public static IServiceCollection AddCoreAppServices(this IServiceCollection serviceCollection)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddTransient<ITabViewModel, TabViewModel>()
|
||||
.AddTransient<IContainerViewModel, ContainerViewModel>()
|
||||
.AddTransient<IElementViewModel, ElementViewModel>()
|
||||
.AddTransient<IItemNameConverterService, ItemNameConverterService>()
|
||||
.AddSingleton<ICommandHandlerService, CommandHandlerService>()
|
||||
.AddSingleton<IClipboardService, ClipboardService>()
|
||||
.AddCommandHandlers();
|
||||
}
|
||||
namespace FileTime.App.Core;
|
||||
|
||||
private static IServiceCollection AddCommandHandlers(this IServiceCollection serviceCollection)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddSingleton<ICommandHandler, NavigationCommandHandler>()
|
||||
.AddSingleton<ICommandHandler, ItemManipulationCommandHandler>();
|
||||
}
|
||||
public static class Startup
|
||||
{
|
||||
public static IServiceCollection AddCoreAppServices(this IServiceCollection serviceCollection)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddTransient<ITabViewModel, TabViewModel>()
|
||||
.AddTransient<IContainerViewModel, ContainerViewModel>()
|
||||
.AddTransient<IElementViewModel, ElementViewModel>()
|
||||
.AddTransient<IItemNameConverterService, ItemNameConverterService>()
|
||||
.AddSingleton<ICommandHandlerService, CommandHandlerService>()
|
||||
.AddSingleton<IClipboardService, ClipboardService>()
|
||||
.AddCommandHandlers();
|
||||
}
|
||||
|
||||
private static IServiceCollection AddCommandHandlers(this IServiceCollection serviceCollection)
|
||||
{
|
||||
return serviceCollection
|
||||
.AddSingleton<ICommandHandler, NavigationCommandHandler>()
|
||||
.AddSingleton<ICommandHandler, ItemManipulationCommandHandler>();
|
||||
}
|
||||
}
|
||||
@@ -5,50 +5,49 @@ using FileTime.App.Core.Models.Enums;
|
||||
using MvvmGen;
|
||||
using MoreLinq;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel]
|
||||
public abstract partial class AppStateBase : IAppState
|
||||
{
|
||||
[ViewModel]
|
||||
public abstract partial class AppStateBase : IAppState
|
||||
private readonly BehaviorSubject<string?> _searchText = new(null);
|
||||
private readonly BehaviorSubject<ITabViewModel?> _selectedTab = new(null);
|
||||
private readonly BehaviorSubject<IEnumerable<ITabViewModel>> _tabs = new(Enumerable.Empty<ITabViewModel>());
|
||||
|
||||
[Property]
|
||||
private ViewMode _viewMode;
|
||||
|
||||
public ObservableCollection<ITabViewModel> Tabs { get; } = new();
|
||||
public IObservable<string?> SearchText { get; private set; }
|
||||
|
||||
public IObservable<ITabViewModel?> SelectedTab { get; private set; }
|
||||
|
||||
partial void OnInitialize()
|
||||
{
|
||||
private readonly BehaviorSubject<string?> _searchText = new(null);
|
||||
private readonly BehaviorSubject<ITabViewModel?> _selectedTab = new(null);
|
||||
private readonly BehaviorSubject<IEnumerable<ITabViewModel>> _tabs = new(Enumerable.Empty<ITabViewModel>());
|
||||
Tabs.CollectionChanged += (_, _) => _tabs.OnNext(Tabs);
|
||||
SearchText = _searchText.AsObservable();
|
||||
SelectedTab = Observable.CombineLatest(_tabs, _selectedTab, GetSelectedTab);
|
||||
}
|
||||
|
||||
[Property]
|
||||
private ViewMode _viewMode;
|
||||
public void AddTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
Tabs.Add(tabViewModel);
|
||||
}
|
||||
|
||||
public ObservableCollection<ITabViewModel> Tabs { get; } = new();
|
||||
public IObservable<string?> SearchText { get; private set; }
|
||||
public void RemoveTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
if (!Tabs.Contains(tabViewModel)) return;
|
||||
|
||||
public IObservable<ITabViewModel?> SelectedTab { get; private set; }
|
||||
Tabs.Remove(tabViewModel);
|
||||
}
|
||||
|
||||
partial void OnInitialize()
|
||||
{
|
||||
Tabs.CollectionChanged += (_, _) => _tabs.OnNext(Tabs);
|
||||
SearchText = _searchText.AsObservable();
|
||||
SelectedTab = Observable.CombineLatest(_tabs, _selectedTab, GetSelectedTab);
|
||||
}
|
||||
public void SetSearchText(string? searchText) => _searchText.OnNext(searchText);
|
||||
|
||||
public void AddTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
Tabs.Add(tabViewModel);
|
||||
}
|
||||
public void SetSelectedTab(ITabViewModel tabToSelect) => _selectedTab.OnNext(tabToSelect);
|
||||
|
||||
public void RemoveTab(ITabViewModel tabViewModel)
|
||||
{
|
||||
if (!Tabs.Contains(tabViewModel)) return;
|
||||
|
||||
Tabs.Remove(tabViewModel);
|
||||
}
|
||||
|
||||
public void SetSearchText(string? searchText) => _searchText.OnNext(searchText);
|
||||
|
||||
public void SetSelectedTab(ITabViewModel tabToSelect) => _selectedTab.OnNext(tabToSelect);
|
||||
|
||||
private ITabViewModel? GetSelectedTab(IEnumerable<ITabViewModel> tabs, ITabViewModel? expectedSelectedTab)
|
||||
{
|
||||
var (prefered, others) = tabs.OrderBy(t => t.TabNumber).Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0));
|
||||
return prefered.Concat(others).FirstOrDefault();
|
||||
}
|
||||
private ITabViewModel? GetSelectedTab(IEnumerable<ITabViewModel> tabs, ITabViewModel? expectedSelectedTab)
|
||||
{
|
||||
var (prefered, others) = tabs.OrderBy(t => t.TabNumber).Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0));
|
||||
return prefered.Concat(others).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,20 @@ using FileTime.App.Core.Services;
|
||||
using FileTime.Core.Models;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel
|
||||
{
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel
|
||||
[Property]
|
||||
private long _size;
|
||||
|
||||
public ContainerSizeContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
[Property]
|
||||
private long _size;
|
||||
}
|
||||
|
||||
public ContainerSizeContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
}
|
||||
|
||||
public void Init(IContainer item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
public void Init(IContainer item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,19 @@ using FileTime.App.Core.Services;
|
||||
using FileTime.Core.Models;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ContainerViewModel : ItemViewModel, IContainerViewModel
|
||||
{
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ContainerViewModel : ItemViewModel, IContainerViewModel
|
||||
public IContainer? Container => BaseItem as IContainer;
|
||||
|
||||
public ContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
public IContainer? Container => BaseItem as IContainer;
|
||||
}
|
||||
|
||||
public ContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
}
|
||||
|
||||
public void Init(IContainer item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
public void Init(IContainer item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,20 @@ using FileTime.App.Core.Services;
|
||||
using FileTime.Core.Models;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
||||
{
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class ElementViewModel : ItemViewModel, IElementViewModel
|
||||
[Property]
|
||||
private long? _size;
|
||||
|
||||
public ElementViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
[Property]
|
||||
private long? _size;
|
||||
}
|
||||
|
||||
public ElementViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
}
|
||||
|
||||
public void Init(IElement item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
public void Init(IElement item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IItem)item, parentTab);
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,17 @@ using FileTime.App.Core.Services;
|
||||
using FileTime.Core.Models;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
{
|
||||
[ViewModel(GenerateConstructor = false)]
|
||||
public partial class FileViewModel : ElementViewModel, IFileViewModel
|
||||
{
|
||||
public FileViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState)
|
||||
{
|
||||
}
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
public void Init(IFileElement item, ITabViewModel parentTab)
|
||||
{
|
||||
Init((IElement)item, parentTab);
|
||||
}
|
||||
[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)
|
||||
{
|
||||
Init((IElement)item, parentTab);
|
||||
}
|
||||
}
|
||||
@@ -7,54 +7,54 @@ using FileTime.Core.Models;
|
||||
using MoreLinq;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel]
|
||||
[Inject(typeof(IAppState), "_appState")]
|
||||
[Inject(typeof(IItemNameConverterService), "_itemNameConverterService")]
|
||||
public abstract partial class ItemViewModel : IItemViewModel
|
||||
{
|
||||
[ViewModel]
|
||||
[Inject(typeof(IAppState), "_appState")]
|
||||
[Inject(typeof(IItemNameConverterService), "_itemNameConverterService")]
|
||||
public abstract partial class ItemViewModel : IItemViewModel
|
||||
[Property]
|
||||
private IItem? _baseItem;
|
||||
|
||||
[Property]
|
||||
private IObservable<IReadOnlyList<ItemNamePart>>? _displayName;
|
||||
|
||||
[Property]
|
||||
private string? _displayNameText;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool>? _isSelected;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool>? _isMarked;
|
||||
|
||||
[Property]
|
||||
private IObservable<ItemViewMode> _viewMode;
|
||||
|
||||
[Property]
|
||||
private DateTime? _createdAt;
|
||||
|
||||
[Property]
|
||||
private string? _attributes;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool> _isAlternative;
|
||||
|
||||
public void Init(IItem item, ITabViewModel parentTab)
|
||||
{
|
||||
[Property]
|
||||
private IItem? _baseItem;
|
||||
BaseItem = item;
|
||||
DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s));
|
||||
DisplayNameText = item.DisplayName;
|
||||
IsMarked = parentTab.MarkedItems.ToCollection().Select(m => m.Any(i => i.Path.Path == item.FullName?.Path));
|
||||
IsSelected = parentTab.CurrentSelectedItem.Select(EqualsTo);
|
||||
IsAlternative = parentTab.CurrentItemsCollectionObservable.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0);
|
||||
ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode);
|
||||
Attributes = item.Attributes;
|
||||
CreatedAt = item.CreatedAt;
|
||||
}
|
||||
|
||||
[Property]
|
||||
private IObservable<IReadOnlyList<ItemNamePart>>? _displayName;
|
||||
|
||||
[Property]
|
||||
private string? _displayNameText;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool>? _isSelected;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool>? _isMarked;
|
||||
|
||||
[Property]
|
||||
private IObservable<ItemViewMode> _viewMode;
|
||||
|
||||
[Property]
|
||||
private DateTime? _createdAt;
|
||||
|
||||
[Property]
|
||||
private string? _attributes;
|
||||
|
||||
[Property]
|
||||
private IObservable<bool> _isAlternative;
|
||||
|
||||
public void Init(IItem item, ITabViewModel parentTab)
|
||||
{
|
||||
BaseItem = item;
|
||||
DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s));
|
||||
DisplayNameText = item.DisplayName;
|
||||
IsMarked = parentTab.MarkedItems.ToCollection().Select(m => m.Any(i => i.Path.Path == item.FullName?.Path));
|
||||
IsSelected = parentTab.CurrentSelectedItem.Select(EqualsTo);
|
||||
IsAlternative = parentTab.CurrentItemsCollectionObservable.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0);
|
||||
ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode);
|
||||
Attributes = item.Attributes;
|
||||
CreatedAt = item.CreatedAt;
|
||||
}
|
||||
|
||||
private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative)
|
||||
private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative)
|
||||
=> (isMarked, isSelected, sAlternative) switch
|
||||
{
|
||||
(true, true, _) => ItemViewMode.MarkedSelected,
|
||||
@@ -65,9 +65,8 @@ namespace FileTime.App.Core.ViewModels
|
||||
_ => ItemViewMode.Default
|
||||
};
|
||||
|
||||
public bool EqualsTo(IItemViewModel? itemViewModel)
|
||||
{
|
||||
return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path;
|
||||
}
|
||||
public bool EqualsTo(IItemViewModel? itemViewModel)
|
||||
{
|
||||
return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path;
|
||||
}
|
||||
}
|
||||
@@ -9,118 +9,118 @@ using FileTime.Tools.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MvvmGen;
|
||||
|
||||
namespace FileTime.App.Core.ViewModels
|
||||
namespace FileTime.App.Core.ViewModels;
|
||||
|
||||
[ViewModel]
|
||||
public partial class TabViewModel : ITabViewModel, IDisposable
|
||||
{
|
||||
[ViewModel]
|
||||
public partial class TabViewModel : ITabViewModel, IDisposable
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IItemNameConverterService _itemNameConverterService;
|
||||
private readonly IAppState _appState;
|
||||
private readonly IRxSchedulerService _rxSchedulerService;
|
||||
private readonly SourceList<IAbsolutePath> _markedItems = new();
|
||||
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; } = null!;
|
||||
public IObservable<IItemViewModel?> CurrentSelectedItem { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; private set; } = null!;
|
||||
public IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; private set; } = null!;
|
||||
|
||||
public IObservable<IReadOnlyCollection<IItemViewModel>?> CurrentItemsCollectionObservable { get; private set; } = null!;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _currentItemsCollection;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _parentsChildrenCollection;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _selectedsChildrenCollection;
|
||||
|
||||
public TabViewModel(
|
||||
IServiceProvider serviceProvider,
|
||||
IItemNameConverterService itemNameConverterService,
|
||||
IAppState appState,
|
||||
IRxSchedulerService rxSchedulerService)
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IItemNameConverterService _itemNameConverterService;
|
||||
private readonly IAppState _appState;
|
||||
private readonly IRxSchedulerService _rxSchedulerService;
|
||||
private readonly SourceList<IAbsolutePath> _markedItems = new();
|
||||
private readonly List<IDisposable> _disposables = new();
|
||||
private bool disposed;
|
||||
_serviceProvider = serviceProvider;
|
||||
_itemNameConverterService = itemNameConverterService;
|
||||
_appState = appState;
|
||||
|
||||
public ITab? Tab { get; private set; }
|
||||
public int TabNumber { get; private set; }
|
||||
MarkedItems = _markedItems.Connect().StartWithEmpty();
|
||||
IsSelected = _appState.SelectedTab.Select(s => s == this);
|
||||
_rxSchedulerService = rxSchedulerService;
|
||||
}
|
||||
|
||||
public IObservable<bool> IsSelected { get; }
|
||||
public void Init(ITab tab, int tabNumber)
|
||||
{
|
||||
Tab = tab;
|
||||
TabNumber = tabNumber;
|
||||
|
||||
public IObservable<IContainer?> CurrentLocation { get; private set; } = null!;
|
||||
public IObservable<IItemViewModel?> CurrentSelectedItem { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> CurrentItems { get; private set; } = null!;
|
||||
public IObservable<IChangeSet<IAbsolutePath>> MarkedItems { get; }
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> SelectedsChildren { get; private set; } = null!;
|
||||
public IObservable<IObservable<IChangeSet<IItemViewModel>>?> ParentsChildren { get; private set; } = null!;
|
||||
CurrentLocation = tab.CurrentLocation.AsObservable();
|
||||
CurrentItems = tab.CurrentItems
|
||||
.Select(items => items?.Transform(MapItemToViewModel))
|
||||
.ObserveOn(_rxSchedulerService.GetWorkerScheduler())
|
||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
public IObservable<IReadOnlyCollection<IItemViewModel>?> CurrentItemsCollectionObservable { get; private set; } = null!;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _currentItemsCollection;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _parentsChildrenCollection;
|
||||
|
||||
[Property]
|
||||
private BindedCollection<IItemViewModel>? _selectedsChildrenCollection;
|
||||
|
||||
public TabViewModel(
|
||||
IServiceProvider serviceProvider,
|
||||
IItemNameConverterService itemNameConverterService,
|
||||
IAppState appState,
|
||||
IRxSchedulerService rxSchedulerService)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_itemNameConverterService = itemNameConverterService;
|
||||
_appState = appState;
|
||||
|
||||
MarkedItems = _markedItems.Connect().StartWithEmpty();
|
||||
IsSelected = _appState.SelectedTab.Select(s => s == this);
|
||||
_rxSchedulerService = rxSchedulerService;
|
||||
}
|
||||
|
||||
public void Init(ITab tab, int tabNumber)
|
||||
{
|
||||
Tab = tab;
|
||||
TabNumber = tabNumber;
|
||||
|
||||
CurrentLocation = tab.CurrentLocation.AsObservable();
|
||||
CurrentItems = tab.CurrentItems
|
||||
.Select(items => items?.Transform(MapItemToViewModel))
|
||||
.ObserveOn(_rxSchedulerService.GetWorkerScheduler())
|
||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
CurrentSelectedItem =
|
||||
Observable.CombineLatest(
|
||||
CurrentSelectedItem =
|
||||
Observable.CombineLatest(
|
||||
CurrentItems,
|
||||
tab.CurrentSelectedItem,
|
||||
(currentItems, currentSelectedItemPath) =>
|
||||
currentItems == null
|
||||
? Observable.Return((IItemViewModel?)null)
|
||||
: currentItems
|
||||
.ToCollection()
|
||||
.Select(items => items.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path))
|
||||
? Observable.Return((IItemViewModel?)null)
|
||||
: currentItems
|
||||
.ToCollection()
|
||||
.Select(items => items.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path))
|
||||
)
|
||||
.Switch()
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
SelectedsChildren = InitSelectedsChildren();
|
||||
ParentsChildren = InitParentsChildren();
|
||||
SelectedsChildren = InitSelectedsChildren();
|
||||
ParentsChildren = InitParentsChildren();
|
||||
|
||||
CurrentItemsCollectionObservable = CurrentItems
|
||||
.Select(c => c != null ? c.ToCollection() : Observable.Return((IReadOnlyCollection<IItemViewModel>?)null))
|
||||
.Switch()
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
CurrentItemsCollectionObservable = CurrentItems
|
||||
.Select(c => c != null ? c.ToCollection() : Observable.Return((IReadOnlyCollection<IItemViewModel>?)null))
|
||||
.Switch()
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
CurrentItems.Subscribe(children =>
|
||||
{
|
||||
CurrentItemsCollection?.Dispose();
|
||||
CurrentItemsCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
CurrentItems.Subscribe(children =>
|
||||
{
|
||||
CurrentItemsCollection?.Dispose();
|
||||
CurrentItemsCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
|
||||
ParentsChildren.Subscribe(children =>
|
||||
{
|
||||
ParentsChildrenCollection?.Dispose();
|
||||
ParentsChildrenCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
ParentsChildren.Subscribe(children =>
|
||||
{
|
||||
ParentsChildrenCollection?.Dispose();
|
||||
ParentsChildrenCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
|
||||
SelectedsChildren.Subscribe(children =>
|
||||
{
|
||||
SelectedsChildrenCollection?.Dispose();
|
||||
SelectedsChildrenCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
SelectedsChildren.Subscribe(children =>
|
||||
{
|
||||
SelectedsChildrenCollection?.Dispose();
|
||||
SelectedsChildrenCollection = children.MapNull(c => new BindedCollection<IItemViewModel>(c!));
|
||||
});
|
||||
|
||||
tab.CurrentLocation.Subscribe((_) => _markedItems.Clear());
|
||||
tab.CurrentLocation.Subscribe((_) => _markedItems.Clear());
|
||||
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> InitSelectedsChildren()
|
||||
{
|
||||
var currentSelectedItemThrottled = CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount();
|
||||
return Observable.Merge(
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> InitSelectedsChildren()
|
||||
{
|
||||
var currentSelectedItemThrottled = CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount();
|
||||
return Observable.Merge(
|
||||
currentSelectedItemThrottled
|
||||
.WhereNotNull()
|
||||
.OfType<IContainerViewModel>()
|
||||
@@ -136,17 +136,17 @@ namespace FileTime.App.Core.ViewModels
|
||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
}
|
||||
}
|
||||
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> InitParentsChildren()
|
||||
{
|
||||
var parentThrottled = CurrentLocation
|
||||
.Select(l => l?.Parent)
|
||||
.DistinctUntilChanged()
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
IObservable<IObservable<IChangeSet<IItemViewModel>>?> InitParentsChildren()
|
||||
{
|
||||
var parentThrottled = CurrentLocation
|
||||
.Select(l => l?.Parent)
|
||||
.DistinctUntilChanged()
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
|
||||
return Observable.Merge(
|
||||
return Observable.Merge(
|
||||
parentThrottled
|
||||
.Where(p => p is not null)
|
||||
.Select(p => Observable.FromAsync(async () => (IContainer)await p!.ResolveAsync()))
|
||||
@@ -162,85 +162,84 @@ namespace FileTime.App.Core.ViewModels
|
||||
.SubscribeOn(_rxSchedulerService.GetUIScheduler())
|
||||
.Publish(null)
|
||||
.RefCount();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IItem> MapItem(IAbsolutePath item)
|
||||
=> await item.ResolveAsync(forceResolve: true, itemInitializationSettings: new ItemInitializationSettings(true));
|
||||
|
||||
private IItemViewModel MapItemToViewModel(IItem item)
|
||||
{
|
||||
if (item is IContainer container)
|
||||
{
|
||||
var containerViewModel = _serviceProvider.GetInitableResolver<IContainer, ITabViewModel>(container, this).GetRequiredService<IContainerViewModel>();
|
||||
|
||||
return containerViewModel;
|
||||
}
|
||||
else if (item is IFileElement fileElement)
|
||||
{
|
||||
var fileViewModel = _serviceProvider.GetInitableResolver<IFileElement, ITabViewModel>(fileElement, this).GetRequiredService<IFileViewModel>();
|
||||
fileViewModel.Size = fileElement.Size;
|
||||
|
||||
return fileViewModel;
|
||||
}
|
||||
else if (item is IElement element)
|
||||
{
|
||||
var elementViewModel = _serviceProvider.GetInitableResolver<IElement, ITabViewModel>(element, this).GetRequiredService<IElementViewModel>();
|
||||
|
||||
return elementViewModel;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
|
||||
}
|
||||
|
||||
public void AddMarkedItem(IAbsolutePath item) => _markedItems.Add(item);
|
||||
|
||||
public void RemoveMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
var itemsToRemove = _markedItems.Items.Where(i => i.Path.Path == item.Path.Path).ToList();
|
||||
|
||||
_markedItems.RemoveMany(itemsToRemove);
|
||||
}
|
||||
|
||||
public void ToggleMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
if (_markedItems.Items.Any(i => i.Path.Path == item.Path.Path))
|
||||
{
|
||||
RemoveMarkedItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMarkedItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearMarkedItems()
|
||||
{
|
||||
_markedItems.Clear();
|
||||
}
|
||||
|
||||
~TabViewModel() => Dispose(false);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed && disposing)
|
||||
{
|
||||
foreach (var disposable in _disposables)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IItem> MapItem(IAbsolutePath item)
|
||||
=> await item.ResolveAsync(forceResolve: true, itemInitializationSettings: new ItemInitializationSettings(true));
|
||||
|
||||
private IItemViewModel MapItemToViewModel(IItem item)
|
||||
{
|
||||
if (item is IContainer container)
|
||||
{
|
||||
var containerViewModel = _serviceProvider.GetInitableResolver<IContainer, ITabViewModel>(container, this).GetRequiredService<IContainerViewModel>();
|
||||
|
||||
return containerViewModel;
|
||||
}
|
||||
else if (item is IFileElement fileElement)
|
||||
{
|
||||
var fileViewModel = _serviceProvider.GetInitableResolver<IFileElement, ITabViewModel>(fileElement, this).GetRequiredService<IFileViewModel>();
|
||||
fileViewModel.Size = fileElement.Size;
|
||||
|
||||
return fileViewModel;
|
||||
}
|
||||
else if (item is IElement element)
|
||||
{
|
||||
var elementViewModel = _serviceProvider.GetInitableResolver<IElement, ITabViewModel>(element, this).GetRequiredService<IElementViewModel>();
|
||||
|
||||
return elementViewModel;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}");
|
||||
}
|
||||
|
||||
public void AddMarkedItem(IAbsolutePath item) => _markedItems.Add(item);
|
||||
|
||||
public void RemoveMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
var itemsToRemove = _markedItems.Items.Where(i => i.Path.Path == item.Path.Path).ToList();
|
||||
|
||||
_markedItems.RemoveMany(itemsToRemove);
|
||||
}
|
||||
|
||||
public void ToggleMarkedItem(IAbsolutePath item)
|
||||
{
|
||||
if (_markedItems.Items.Any(i => i.Path.Path == item.Path.Path))
|
||||
{
|
||||
RemoveMarkedItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMarkedItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearMarkedItems()
|
||||
{
|
||||
_markedItems.Clear();
|
||||
}
|
||||
|
||||
~TabViewModel() => Dispose(false);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed && disposing)
|
||||
{
|
||||
foreach (var disposable in _disposables)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,17 @@ using FileTime.Core.Services;
|
||||
using FileTime.Providers.Local;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace FileTime.App.DependencyInjection
|
||||
{
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection RegisterDefaultServices(IServiceCollection? serviceCollection = null)
|
||||
{
|
||||
serviceCollection ??= new ServiceCollection();
|
||||
namespace FileTime.App.DependencyInjection;
|
||||
|
||||
return serviceCollection
|
||||
.AddTransient<ITab, Tab>()
|
||||
.AddCoreAppServices()
|
||||
.AddLocalServices();
|
||||
}
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection RegisterDefaultServices(IServiceCollection? serviceCollection = null)
|
||||
{
|
||||
serviceCollection ??= new ServiceCollection();
|
||||
|
||||
return serviceCollection
|
||||
.AddTransient<ITab, Tab>()
|
||||
.AddCoreAppServices()
|
||||
.AddLocalServices();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user