This commit is contained in:
2022-02-23 22:47:43 +01:00
parent 4952c68ce9
commit cef8e5de18
20 changed files with 1790 additions and 41 deletions

View File

@@ -0,0 +1,9 @@
using FileTime.Core.Models;
namespace FileTime.App.Core.Models
{
public interface IHaveContainer
{
IContainer Container { get; }
}
}

View File

@@ -8,12 +8,13 @@ namespace FileTime.Core.Components
public class Tab
{
private IItem? _currentSelectedItem;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private IContainer _currentLocation;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private readonly List<AbsolutePath> _history = new();
private string? _lastPath;
private bool _currentlySelecting = false;
private bool _currentlySelecting;
private readonly object _guardSetCurrentSelectedItemCTS = new();
private CancellationTokenSource? _setCurrentSelectedItemCTS;
@@ -22,9 +23,18 @@ namespace FileTime.Core.Components
public bool AutoRefresh { get; set; }
public IReadOnlyList<AbsolutePath> History { get; }
public AsyncEventHandler CurrentLocationChanged = new();
public AsyncEventHandler HistoryChanged { get; } = new();
public AsyncEventHandler<bool> CurrentSelectedItemChanged = new();
public Tab()
{
_currentLocation = null!;
History = _history.AsReadOnly();
}
public async Task Init(IContainer currentPath)
{
await SetCurrentLocation(currentPath);
@@ -42,13 +52,14 @@ namespace FileTime.Core.Components
if (_currentLocation != null)
{
_currentLocation.Refreshed.Remove(HandleCurrentLocationRefresh);
if(_currentLocation is SearchContainer searchContainer)
if (_currentLocation is SearchContainer searchContainer)
{
searchContainer.SearchTaskBase.Cancel();
}
}
_currentLocation = value;
await AddHistoryItem(_currentLocation);
await CurrentLocationChanged.InvokeAsync(this, AsyncEventArgs.Empty);
var currentLocationItems = await (await GetCurrentLocation()).GetItems();
@@ -58,6 +69,22 @@ namespace FileTime.Core.Components
}
}
private async Task AddHistoryItem(IContainer container)
{
var containerPath = new AbsolutePath(container);
if (_history.Count == 0 || _history.Last() != containerPath)
{
_history.Add(containerPath);
}
while (_history.Count > 50)
{
_history.RemoveAt(0);
}
await HistoryChanged.InvokeAsync(this, AsyncEventArgs.Empty);
}
public Task<IItem?> GetCurrentSelectedItem()
{
return Task.FromResult(_currentSelectedItem);

View File

@@ -82,6 +82,8 @@ namespace FileTime.Core.Models
? await VirtualContentProvider.GetByPath(Path)
: null;
if (ContentProvider == null) return null;
result ??= await ContentProvider.GetByPath(Path);
return result;

View File

@@ -97,6 +97,7 @@ namespace FileTime.Core.Providers
{
lock (_initializationGuard)
{
if (_initialized) return;
if (!_initializing)
{
_initializing = true;
@@ -109,8 +110,8 @@ namespace FileTime.Core.Providers
try
{
if (_initialized) return;
_initialized = true;
await Init();
_initialized = true;
IsLoaded = true;
}
finally

View File

@@ -0,0 +1,148 @@
// Autogenerated
namespace InitableService;
public interface IInitable
{
void Init();
}
public interface IInitable<T1>
{
void Init(T1 obj1);
}
public interface IInitable<T1, T2>
{
void Init(T1 obj1, T2 obj2);
}
public interface IInitable<T1, T2, T3>
{
void Init(T1 obj1, T2 obj2, T3 obj3);
}
public interface IInitable<T1, T2, T3, T4>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4);
}
public interface IInitable<T1, T2, T3, T4, T5>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5);
}
public interface IInitable<T1, T2, T3, T4, T5, T6>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13, T14 obj14);
}
public interface IInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>
{
void Init(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13, T14 obj14, T15 obj15);
}
public interface IAsyncInitable
{
Task InitAsync();
}
public interface IAsyncInitable<T1>
{
Task InitAsync(T1 obj1);
}
public interface IAsyncInitable<T1, T2>
{
Task InitAsync(T1 obj1, T2 obj2);
}
public interface IAsyncInitable<T1, T2, T3>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3);
}
public interface IAsyncInitable<T1, T2, T3, T4>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13, T14 obj14);
}
public interface IAsyncInitable<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>
{
Task InitAsync(T1 obj1, T2 obj2, T3 obj3, T4 obj4, T5 obj5, T6 obj6, T7 obj7, T8 obj8, T9 obj9, T10 obj10, T11 obj11, T12 obj12, T13 obj13, T14 obj14, T15 obj15);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,180 @@
#!/usr/bin/env dotnet-script
{
const string header =
@"// Autogenerated
using InitableService;
namespace Microsoft.Extensions.DependencyInjection;
public static class InitableExtensions
{
";
const string footer = "}";
using var initableWriter = File.CreateText("InitableExtensions.cs");
initableWriter.WriteLine(header);
const int generateForParams = 15;
for (var i = 0; i <= generateForParams; i++)
{
WriteInitableExtension(initableWriter, false, i);
initableWriter.WriteLine();
}
for (var i = 0; i <= generateForParams; i++)
{
WriteInitableExtension(initableWriter, true, i);
initableWriter.WriteLine();
}
initableWriter.WriteLine(footer);
for (var i = 0; i <= generateForParams; i++)
{
WriteInitableResolver(initableWriter, false, i);
initableWriter.WriteLine();
}
for (var i = 0; i <= generateForParams; i++)
{
WriteInitableResolver(initableWriter, true, i);
initableWriter.WriteLine();
}
initableWriter.Flush();
}
void WriteInitableExtension(StreamWriter initableWriter, bool isAsync, int i)
{
initableWriter.Write($"\tpublic static {(isAsync ? "Async" : "")}Resolver");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.Write($" Get{(isAsync ? "Async" : "")}InitableResolver");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.Write("(");
var thisParameter = "this IServiceProvider serviceProvider";
if (i > 0)
{
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => $"T{c} obj{c}").Prepend(thisParameter)));
}
else
{
initableWriter.Write(thisParameter);
}
initableWriter.WriteLine(")");
initableWriter.WriteLine("\t{");
initableWriter.Write($"\t\treturn new {(isAsync ? "Async" : "")}Resolver");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.Write("(");
if (i > 0)
{
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => $"obj{c}").Prepend("serviceProvider")));
}
else
{
initableWriter.Write("serviceProvider");
}
initableWriter.WriteLine(");");
initableWriter.WriteLine("\t}");
}
void WriteInitableResolver(StreamWriter initableWriter, bool isAsync, int i)
{
initableWriter.Write($"public class {(isAsync ? "Async" : "")}Resolver");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.WriteLine();
initableWriter.WriteLine("{");
initableWriter.WriteLine("\tIServiceProvider _serviceProvider;");
if (i > 0)
{
for (var j = 1; j <= i; j++)
{
initableWriter.WriteLine($"\tprivate T{j} _obj{j};");
}
}
initableWriter.Write($"\tpublic {(isAsync ? "Async" : "")}Resolver(");
if (i > 0)
{
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => $"T{c} obj{c}").Prepend("IServiceProvider serviceProvider")));
}
else
{
initableWriter.Write("IServiceProvider serviceProvider");
}
initableWriter.WriteLine(")");
initableWriter.WriteLine("\t{");
initableWriter.WriteLine("\t\t_serviceProvider = serviceProvider;");
if (i > 0)
{
for (var j = 1; j <= i; j++)
{
initableWriter.WriteLine($"\t\t_obj{j} = obj{j};");
}
}
initableWriter.WriteLine("\t}");
initableWriter.WriteLine("");
var returnType = isAsync ? "async Task<TResult>" : "TResult";
initableWriter.WriteLine($"\tpublic {returnType} GetService{(isAsync ? "Async" : "")}<TResult>()");
initableWriter.Write($"\t\twhere TResult : class, I{(isAsync ? "Async" : "")}Initable");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.WriteLine("");
initableWriter.WriteLine("\t{");
initableWriter.WriteLine("\t\tvar initableService = _serviceProvider.GetService<TResult>()!;");
if (isAsync)
{
initableWriter.Write("\t\tawait initableService.InitAsync");
}
else
{
initableWriter.Write("\t\tinitableService.Init");
}
initableWriter.Write("(");
if (i > 0)
{
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => $"_obj{c}")));
}
initableWriter.WriteLine(");");
initableWriter.WriteLine("\t\treturn initableService;");
initableWriter.WriteLine("\t}");
initableWriter.WriteLine("}");
}

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env dotnet-script
{
const string header =
@"// Autogenerated
namespace InitableService;
";
const string footer = "";
using var initableWriter = File.CreateText("Initable.cs");
initableWriter.WriteLine(header);
const int generateForParams = 15;
for (var i = 0; i <= generateForParams; i++)
{
WriteInitable(initableWriter, false, i);
}
for (var i = 0; i <= generateForParams; i++)
{
WriteInitable(initableWriter, true, i);
initableWriter.WriteLine();
}
initableWriter.WriteLine(footer);
initableWriter.Flush();
}
void WriteInitable(StreamWriter initableWriter, bool isAsync, int i)
{
initableWriter.Write($"public interface I{(isAsync ? "Async" : "")}Initable");
if (i > 0)
{
initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");
}
initableWriter.WriteLine();
initableWriter.WriteLine("{");
if (isAsync)
{
initableWriter.Write("\tTask InitAsync");
}
else
{
initableWriter.Write("\tvoid Init");
}
if (i > 0)
{
/*initableWriter.Write("<");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => "T" + c)));
initableWriter.Write(">");*/
initableWriter.Write("(");
initableWriter.Write(string.Join(", ", Enumerable.Range(1, i).Select(c => $"T{c} obj{c}")));
initableWriter.Write(")");
}
else
{
initableWriter.Write("()");
}
initableWriter.WriteLine(";");
initableWriter.WriteLine("}");
}

View File

@@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileTime.Tools.Compression"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileTime.Providers.Sftp", "Providers\FileTime.Providers.Sftp\FileTime.Providers.Sftp.csproj", "{0E650206-801D-4E8D-95BA-4565B32092E1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InitableService", "Core\InitableService\InitableService.csproj", "{B1520189-8646-4DE8-B5C9-46AE04B4D01C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -315,6 +317,26 @@ Global
{0E650206-801D-4E8D-95BA-4565B32092E1}.Release|x64.Build.0 = Release|Any CPU
{0E650206-801D-4E8D-95BA-4565B32092E1}.Release|x86.ActiveCfg = Release|Any CPU
{0E650206-801D-4E8D-95BA-4565B32092E1}.Release|x86.Build.0 = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|ARM.Build.0 = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|ARM64.Build.0 = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|x64.Build.0 = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|x86.ActiveCfg = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Debug|x86.Build.0 = Debug|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|Any CPU.Build.0 = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|ARM.ActiveCfg = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|ARM.Build.0 = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|ARM64.ActiveCfg = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|ARM64.Build.0 = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|x64.ActiveCfg = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|x64.Build.0 = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|x86.ActiveCfg = Release|Any CPU
{B1520189-8646-4DE8-B5C9-46AE04B4D01C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -333,6 +355,7 @@ Global
{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7} = {890275FF-943A-4D07-83BA-14E5C52D7846}
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966} = {0D2B4BAA-0399-459C-B022-41DB7F408225}
{0E650206-801D-4E8D-95BA-4565B32092E1} = {517D96CE-A956-4638-A93D-465D34DE22B1}
{B1520189-8646-4DE8-B5C9-46AE04B4D01C} = {38B1B927-4201-4B7A-87EE-737B8C6D4090}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8D679DCE-AC84-4A91-BFED-8F8D8E1D8183}

View File

@@ -187,19 +187,11 @@
</Setter>
</Style>
<Style Selector="Grid.RootDriveInfo">
<Style Selector="Grid.SidebarContainerPresenter">
<Setter Property="Background" Value="#01000000"/>
</Style>
<Style Selector="Grid.RootDriveInfo:pointerover">
<Setter Property="Background" Value="{DynamicResource AppBackgroundColor}"/>
</Style>
<Style Selector="Grid.PlacesItem">
<Setter Property="Background" Value="#01000000"/>
</Style>
<Style Selector="Grid.PlacesItem:pointerover">
<Style Selector="Grid.SidebarContainerPresenter:pointerover">
<Setter Property="Background" Value="{DynamicResource AppBackgroundColor}"/>
</Style>

View File

@@ -1,4 +1,4 @@
using AsyncEvent;
using AsyncEvent;
using FileTime.Core.Components;
using FileTime.Core.Models;
using FileTime.Providers.Local;
@@ -16,6 +16,8 @@ using FileTime.Core.Search;
using Microsoft.Extensions.DependencyInjection;
using FileTime.Core.Services;
using FileTime.Core.ContainerSizeScanner;
using System.Collections.Generic;
using FileTime.Core.Providers;
namespace FileTime.Avalonia.Application
{
@@ -71,6 +73,9 @@ namespace FileTime.Avalonia.Application
[Property]
private IItemPreviewViewModel? _itemPreview;
[Property]
private List<HistoryItemViewModel> _history = new();
public async Task SetSelectedItemAsync(IItemViewModel? value)
{
if (_selectedItem != value)
@@ -86,7 +91,38 @@ namespace FileTime.Avalonia.Application
{
_tabState = new TabState(Tab);
_timeRunner.RefreshContainer.Add(TimeRunnerContainerRefreshed);
Tab.HistoryChanged.Add(TabHistoryChanged);
}
private async Task TabHistoryChanged(object? sender, AsyncEventArgs e, CancellationToken token)
{
await RefreshHistory();
}
private async Task RefreshHistory()
{
var newHistory = new List<HistoryItemViewModel>();
var counter = 0;
AbsolutePath? lastPath = null;
foreach (var history in Tab.History.Reverse())
{
try
{
var historyItemVM = await _serviceProvider.GetAsyncInitableResolver(history).GetServiceAsync<HistoryItemViewModel>();
if (historyItemVM.Container != null && historyItemVM.Container is not IContentProvider && lastPath != history)
{
lastPath = history;
newHistory.Add(historyItemVM);
counter++;
if (counter == 10) break;
}
}
catch { }
}
History = newHistory;
}
private async Task TimeRunnerContainerRefreshed(object? sender, AbsolutePath container, CancellationToken token = default)

View File

@@ -52,6 +52,7 @@
<ItemGroup>
<ProjectReference Include="..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
<ProjectReference Include="..\..\AppCommon\FileTime.App.DependencyInjection\FileTime.App.DependencyInjection.csproj" />
<ProjectReference Include="..\..\Core\InitableService\InitableService.csproj" />
</ItemGroup>
<ItemGroup>
<AvaloniaXaml Update="Views\MainWindow.axaml">

View File

@@ -1,8 +1,9 @@
using FileTime.App.Core.Models;
using FileTime.Core.Models;
namespace FileTime.Avalonia.Models
{
public class PlaceInfo
public class PlaceInfo : IHaveContainer
{
public string Name { get; }
public IContainer Container { get; }

View File

@@ -1,4 +1,5 @@
using FileTime.Core.Models;
using FileTime.App.Core.Models;
using FileTime.Core.Models;
using FileTime.Providers.Local;
using MvvmGen;
using System.IO;
@@ -7,7 +8,7 @@ using System.Runtime.InteropServices;
namespace FileTime.Avalonia.Models
{
[ViewModel]
public partial class RootDriveInfo
public partial class RootDriveInfo : IHaveContainer
{
private readonly DriveInfo _driveInfo;
private readonly IContainer _container;

View File

@@ -8,7 +8,6 @@ using FileTime.Avalonia.Logging;
using FileTime.Avalonia.Services;
using FileTime.Avalonia.ViewModels;
using FileTime.Avalonia.ViewModels.ItemPreview;
using FileTime.Core.Command;
using FileTime.Core.Interactions;
using FileTime.Core.Persistence;
using Microsoft.Extensions.Configuration;
@@ -29,6 +28,7 @@ namespace FileTime.Avalonia
.AddTransient<SizeContainerViewModel>()
.AddTransient<SizeElementViewmodel>()
.AddTransient<SizeContainerPreview>()
.AddTransient<HistoryItemViewModel>()
.AddSingleton<IInputInterface, BasicInputHandler>();
}
internal static IServiceCollection AddServices(this IServiceCollection serviceCollection)

View File

@@ -228,6 +228,11 @@ namespace FileTime.Avalonia.ViewModels
}
}
foreach (var oldContainer in _containers.Except(newContainers))
{
oldContainer.Unload(recursive: true, unloadParent: false, unloadEvents: true);
}
if (silent)
{
_containers = new ObservableCollection<ContainerViewModel>(newContainers);
@@ -251,10 +256,15 @@ namespace FileTime.Avalonia.ViewModels
_exceptions.Add(e);
}
try
{
await _newItemProcessor.UpdateMarkedItems(this, CancellationToken.None);
}
finally
{
_isRefreshing = false;
}
}
private int GetNewItemPosition<TItem, T>(TItem itemToAdd, IList<T> items) where TItem : IItemViewModel where T : IItemViewModel
{
@@ -320,7 +330,12 @@ namespace FileTime.Avalonia.ViewModels
if (unloadEvents)
{
if (BaseContainer is ContainerSizeContainer sizeContainer)
{
sizeContainer.SizeChanged.Remove(UpdateSize);
}
Container.Refreshed.Remove(Container_Refreshed);
Container.LazyLoadingChanged.Remove(Container_LazyLoadingChanged);
}
_containers.Clear();

View File

@@ -0,0 +1,19 @@
using FileTime.Core.Models;
using InitableService;
using System;
using System.Threading.Tasks;
namespace FileTime.Avalonia.ViewModels
{
public class HistoryItemViewModel : IAsyncInitable<AbsolutePath>
{
public string? Name { get; private set; }
public IContainer? Container { get; private set; }
public async Task InitAsync(AbsolutePath path)
{
Container = await path.ResolveAsync() as IContainer ?? throw new ArgumentException($"Parameter must be {nameof(IContainer)}", nameof(path));
Name = Container.DisplayName;
}
}
}

View File

@@ -41,7 +41,7 @@
</StackPanel>
</Grid>
<Grid Grid.Row="1" RowDefinitions="Auto,Auto">
<Grid Grid.Row="1" RowDefinitions="Auto,Auto,Auto">
<Border CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="10" Margin="10">
<Grid RowDefinitions="Auto,Auto">
@@ -55,7 +55,7 @@
Items="{Binding RootDriveInfos}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid Classes="RootDriveInfo" PointerPressed="OnRootDrivePointerPressed" Cursor="Hand">
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
<Grid Margin="0,5" ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto,Auto">
<Image
Grid.RowSpan="2"
@@ -128,7 +128,7 @@
Items="{Binding Places}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid Classes="PlacesItem" PointerPressed="OnPlacePointerPressed" Cursor="Hand">
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
<Image
Width="20"
@@ -147,6 +147,39 @@
</ItemsRepeater>
</Grid>
</Border>
<Border Grid.Row="2" CornerRadius="10" Background="{DynamicResource ContainerBackgroundBrush}" Padding="0,10" Margin="10">
<Grid RowDefinitions="Auto,Auto">
<TextBlock
Margin="10,0,10,10"
Text="History" />
<ItemsRepeater
Grid.Row="1"
Items="{Binding AppState.SelectedTab.History}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Grid Classes="SidebarContainerPresenter" PointerPressed="OnHasContainerPointerPressed" Cursor="Hand">
<StackPanel Orientation="Horizontal" Margin="10,5" HorizontalAlignment="Stretch">
<Image
Width="20"
Height="20"
VerticalAlignment="Center"
Source="{Binding Container,Converter={StaticResource ItemToImageConverter}}" />
<TextBlock
Margin="5,0,0,0"
VerticalAlignment="Center"
Text="{Binding Name}" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Grid>
</Border>
</Grid>
<Grid Grid.Column="1" Grid.Row="1" RowDefinitions="Auto,40,*,Auto">

View File

@@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using FileTime.App.Core.Models;
using FileTime.Avalonia.Misc;
using FileTime.Avalonia.Models;
using FileTime.Avalonia.ViewModels;
@@ -93,31 +94,19 @@ namespace FileTime.Avalonia.Views
}
}
private void OnPlacePointerPressed(object sender, PointerPressedEventArgs e)
private void OnHasContainerPointerPressed(object sender, PointerPressedEventArgs e)
{
if (!e.Handled
&& ViewModel != null
&& e.GetCurrentPoint(this).Properties.IsLeftButtonPressed
&& sender is StyledElement control
&& control.DataContext is PlaceInfo placeInfo)
&& control.DataContext is IHaveContainer hasContainer)
{
ViewModel.CommandHandlerService.OpenContainer(placeInfo.Container);
ViewModel.CommandHandlerService.OpenContainer(hasContainer.Container);
e.Handled = true;
}
}
private void OnRootDrivePointerPressed(object sender, PointerPressedEventArgs e)
{
if (!e.Handled
&& ViewModel != null
&& e.GetCurrentPoint(this).Properties.IsLeftButtonPressed
&& sender is StyledElement control
&& control.DataContext is RootDriveInfo rootDriveInfo)
{
ViewModel.CommandHandlerService.OpenContainer(rootDriveInfo.Container);
e.Handled = true;
}
}
private void OnWindowClosed(object sender, EventArgs e)
{
try