Contaienr size scan WIP
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<RootNamespace>FileTime.App.ContainerSizeScanner</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Core\FileTime.Core.Abstraction\FileTime.Core.Abstraction.csproj" />
|
||||||
|
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using FileTime.Core.ContentAccess;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public interface IContainerScanSnapshotProvider : IContentProvider
|
||||||
|
{
|
||||||
|
ISizeScanTask StartSizeScan(IContainer scanSizeOf);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using DeclarativeProperty;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public interface IContainerSizeScanContainer : ISizeItem, IContainer
|
||||||
|
{
|
||||||
|
public Task AddSizeSourceAsync(IDeclarativeProperty<long> sizeElement);
|
||||||
|
ObservableCollection<IContainerSizeScanContainer> ChildContainers { get; }
|
||||||
|
IContainer RealContainer { get; init; }
|
||||||
|
IDeclarativeProperty<long> Size { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public interface ISizeItem : IItem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public interface ISizePreviewItem : IItemPreviewViewModel
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public interface ISizeScanTask : IInitable<IContainer>
|
||||||
|
{
|
||||||
|
IContainerSizeScanContainer SizeContainer { get; }
|
||||||
|
void Start();
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
using FileTime.App.Core.Exceptions;
|
||||||
|
using FileTime.Core.ContentAccess;
|
||||||
|
using FileTime.Core.Enums;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.Core.Timeline;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public class ContainerScanSnapshotProvider : ContentProviderBase, IContainerScanSnapshotProvider
|
||||||
|
{
|
||||||
|
private readonly ITimelessContentProvider _timelessContentProvider;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly List<ISizeScanTask> _sizeScanTasks = new();
|
||||||
|
internal const string ContentProviderName = "container-size-scan";
|
||||||
|
|
||||||
|
public ContainerScanSnapshotProvider(
|
||||||
|
ITimelessContentProvider timelessContentProvider,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
|
: base(ContentProviderName, timelessContentProvider)
|
||||||
|
{
|
||||||
|
_timelessContentProvider = timelessContentProvider;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IItem> GetItemByFullNameAsync(
|
||||||
|
FullName fullName,
|
||||||
|
PointInTime pointInTime,
|
||||||
|
bool forceResolve = false,
|
||||||
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
|
ItemInitializationSettings itemInitializationSettings = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (fullName.Path == ContentProviderName)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
var pathParts = fullName.Path.Split(Constants.SeparatorChar);
|
||||||
|
|
||||||
|
var item = _sizeScanTasks.FirstOrDefault(t => t.SizeContainer.Name == pathParts[1])?.SizeContainer;
|
||||||
|
|
||||||
|
if (pathParts.Length == 2)
|
||||||
|
return item ?? throw new ItemNotFoundException(fullName);
|
||||||
|
|
||||||
|
for (var i = 2; i < pathParts.Length - 1 && item != null; i++)
|
||||||
|
{
|
||||||
|
var childName = pathParts[i];
|
||||||
|
item = item.ChildContainers.FirstOrDefault(c => c.Name == childName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is not null)
|
||||||
|
{
|
||||||
|
var container = item.ChildContainers.FirstOrDefault(c => c.Name == pathParts[^1]);
|
||||||
|
if (container is not null) return container;
|
||||||
|
|
||||||
|
var childName = item.RealContainer.FullName?.GetChild(pathParts[^1]);
|
||||||
|
if (childName is null) throw new ItemNotFoundException(fullName);
|
||||||
|
|
||||||
|
return await _timelessContentProvider.GetItemByFullNameAsync(
|
||||||
|
childName,
|
||||||
|
pointInTime,
|
||||||
|
forceResolve,
|
||||||
|
forceResolvePathType,
|
||||||
|
itemInitializationSettings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ItemNotFoundException(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<IItem> GetItemByNativePathAsync(
|
||||||
|
NativePath nativePath,
|
||||||
|
PointInTime pointInTime,
|
||||||
|
bool forceResolve = false,
|
||||||
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
|
ItemInitializationSettings itemInitializationSettings = default
|
||||||
|
) =>
|
||||||
|
await GetItemByFullNameAsync(
|
||||||
|
new FullName(nativePath.Path),
|
||||||
|
pointInTime,
|
||||||
|
forceResolve,
|
||||||
|
forceResolvePathType,
|
||||||
|
itemInitializationSettings
|
||||||
|
);
|
||||||
|
|
||||||
|
public override NativePath GetNativePath(FullName fullName)
|
||||||
|
=> new(fullName.Path);
|
||||||
|
|
||||||
|
public override FullName GetFullName(NativePath nativePath)
|
||||||
|
=> new(nativePath.Path);
|
||||||
|
|
||||||
|
public override Task<byte[]?> GetContentAsync(
|
||||||
|
IElement element,
|
||||||
|
int? maxLength = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
//TODO read from original source
|
||||||
|
=> Task.FromResult((byte[]?) null);
|
||||||
|
|
||||||
|
public override bool CanHandlePath(NativePath path)
|
||||||
|
=> path.Path.StartsWith(ContentProviderName);
|
||||||
|
|
||||||
|
public ISizeScanTask StartSizeScan(IContainer scanSizeOf)
|
||||||
|
{
|
||||||
|
var searchTask = _serviceProvider
|
||||||
|
.GetInitableResolver(scanSizeOf)
|
||||||
|
.GetRequiredService<ISizeScanTask>();
|
||||||
|
|
||||||
|
_sizeScanTasks.Add(searchTask);
|
||||||
|
searchTask.Start();
|
||||||
|
Items.Add(new AbsolutePath(_timelessContentProvider, searchTask.SizeContainer));
|
||||||
|
|
||||||
|
return searchTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
using ObservableComputations;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public class ContainerSizeContainerPreview : ISizePreviewItem
|
||||||
|
{
|
||||||
|
public const string PreviewName = "SizePreviewContainer";
|
||||||
|
public string Name => PreviewName;
|
||||||
|
|
||||||
|
public ObservableCollection<ISizePreviewItem> Items { get; }
|
||||||
|
|
||||||
|
public ContainerSizeContainerPreview(IContainerSizeScanContainer container)
|
||||||
|
{
|
||||||
|
Items = container
|
||||||
|
.ChildContainers
|
||||||
|
.Ordering(c => c.Size)
|
||||||
|
.Taking(0, 10)
|
||||||
|
.Selecting();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public class ContainerSizePreviewProvider : IItemPreviewProvider
|
||||||
|
{
|
||||||
|
public bool CanHandle(IItem item) => item is ContainerSizeScanContainer;
|
||||||
|
|
||||||
|
public Task<IItemPreviewViewModel> CreatePreviewAsync(IItem item)
|
||||||
|
{
|
||||||
|
if(item is not ContainerSizeScanContainer container) throw new NotSupportedException();
|
||||||
|
|
||||||
|
return Task.FromResult((IItemPreviewViewModel)new ContainerSizeContainerPreview(container));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
|
using DeclarativeProperty;
|
||||||
|
using FileTime.Core.ContentAccess;
|
||||||
|
using FileTime.Core.Enums;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.Core.Timeline;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
//TODO: create readonly version
|
||||||
|
public class ContainerSizeScanContainer : IContainerSizeScanContainer
|
||||||
|
{
|
||||||
|
private readonly ReadOnlyExtensionCollection _readOnlyExtensions;
|
||||||
|
private readonly BehaviorSubject<bool> _isLoading = new(false);
|
||||||
|
private readonly CombineProperty<long, long> _size;
|
||||||
|
public required string Name { get; init; }
|
||||||
|
public required string DisplayName { get; init; }
|
||||||
|
public required FullName? FullName { get; init; }
|
||||||
|
public required NativePath? NativePath { get; init; }
|
||||||
|
public AbsolutePath? Parent { get; init; }
|
||||||
|
public bool IsHidden => false;
|
||||||
|
public bool IsExists => true;
|
||||||
|
public DateTime? CreatedAt { get; }
|
||||||
|
public SupportsDelete CanDelete => SupportsDelete.True;
|
||||||
|
public bool CanRename => false;
|
||||||
|
public IContentProvider Provider { get; }
|
||||||
|
public string? Attributes => null;
|
||||||
|
public AbsolutePathType Type => AbsolutePathType.Container;
|
||||||
|
public PointInTime PointInTime => PointInTime.Present;
|
||||||
|
public ObservableCollection<Exception> Exceptions { get; } = new();
|
||||||
|
public ExtensionCollection Extensions { get; } = new();
|
||||||
|
ReadOnlyExtensionCollection IItem.Extensions => _readOnlyExtensions;
|
||||||
|
public IItem WithParent(AbsolutePath parent) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public ObservableCollection<AbsolutePath> Items { get; } = new();
|
||||||
|
public IObservable<bool> IsLoading { get; }
|
||||||
|
public bool? IsLoaded { get; private set; }
|
||||||
|
public Task WaitForLoaded(CancellationToken token = default) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public bool AllowRecursiveDeletion => false;
|
||||||
|
|
||||||
|
public IDeclarativeProperty<long> Size => _size;
|
||||||
|
public ObservableCollection<IContainerSizeScanContainer> ChildContainers { get; } = new();
|
||||||
|
public required IContainer RealContainer { get; init; }
|
||||||
|
|
||||||
|
public ContainerSizeScanContainer(IContainerScanSnapshotProvider provider)
|
||||||
|
{
|
||||||
|
_readOnlyExtensions = new ReadOnlyExtensionCollection(Extensions);
|
||||||
|
IsLoading = _isLoading.AsObservable();
|
||||||
|
|
||||||
|
_size = new(childContainerSizes => Task.FromResult(childContainerSizes.Sum()));
|
||||||
|
CreatedAt = DateTime.Now;
|
||||||
|
Provider = provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddSizeSourceAsync(IDeclarativeProperty<long> sizeElement)
|
||||||
|
=> await _size.AddSourceAsync(sizeElement);
|
||||||
|
|
||||||
|
public Task StartLoadingAsync()
|
||||||
|
{
|
||||||
|
_isLoading.OnNext(true);
|
||||||
|
IsLoaded = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopLoadingAsync()
|
||||||
|
{
|
||||||
|
_isLoading.OnNext(false);
|
||||||
|
IsLoaded = true;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using FileTime.Core.ContentAccess;
|
||||||
|
using FileTime.Core.Enums;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.Core.Timeline;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public record ContainerSizeScanElement(
|
||||||
|
string Name,
|
||||||
|
string DisplayName,
|
||||||
|
FullName FullName,
|
||||||
|
NativePath NativePath,
|
||||||
|
AbsolutePath? Parent,
|
||||||
|
bool IsHidden,
|
||||||
|
bool IsExists,
|
||||||
|
DateTime? CreatedAt,
|
||||||
|
SupportsDelete CanDelete,
|
||||||
|
bool CanRename,
|
||||||
|
string? Attributes,
|
||||||
|
IContentProvider Provider,
|
||||||
|
PointInTime PointInTime,
|
||||||
|
ObservableCollection<Exception> Exceptions,
|
||||||
|
ReadOnlyExtensionCollection Extensions) : IElement
|
||||||
|
{
|
||||||
|
public AbsolutePathType Type => AbsolutePathType.Element;
|
||||||
|
|
||||||
|
public IItem WithParent(AbsolutePath parent) => this with { Parent = parent };
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Core\FileTime.Core.ContentAccess\FileTime.Core.ContentAccess.csproj" />
|
||||||
|
<ProjectReference Include="..\FileTime.App.ContainerSizeScanner.Abstractions\FileTime.App.ContainerSizeScanner.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
117
src/AppCommon/FileTime.App.ContainerSizeScanner/SizeScanTask.cs
Normal file
117
src/AppCommon/FileTime.App.ContainerSizeScanner/SizeScanTask.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using DeclarativeProperty;
|
||||||
|
using FileTime.Core.Enums;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using FileTime.Core.Models.Extensions;
|
||||||
|
using FileTime.Core.Timeline;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public class SizeScanTask : ISizeScanTask
|
||||||
|
{
|
||||||
|
private IContainer _scanSizeOf = null!;
|
||||||
|
private readonly IContainerScanSnapshotProvider _containerScanSnapshotProvider;
|
||||||
|
private readonly ITimelessContentProvider _timelessContentProvider;
|
||||||
|
private readonly ILogger<SizeScanTask> _logger;
|
||||||
|
private Thread? _sizeScanThread;
|
||||||
|
private static int _searchId = 1;
|
||||||
|
public IContainerSizeScanContainer SizeContainer { get; private set; } = null!;
|
||||||
|
|
||||||
|
public SizeScanTask(
|
||||||
|
IContainerScanSnapshotProvider containerScanSnapshotProvider,
|
||||||
|
ITimelessContentProvider timelessContentProvider,
|
||||||
|
ILogger<SizeScanTask> logger)
|
||||||
|
{
|
||||||
|
_containerScanSnapshotProvider = containerScanSnapshotProvider;
|
||||||
|
_timelessContentProvider = timelessContentProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init(IContainer scanSizeOf)
|
||||||
|
{
|
||||||
|
_scanSizeOf = scanSizeOf;
|
||||||
|
var name = $"{_searchId++}_{scanSizeOf.Name}";
|
||||||
|
var randomId = ContainerScanSnapshotProvider.ContentProviderName + Constants.SeparatorChar + name;
|
||||||
|
SizeContainer = new ContainerSizeScanContainer(_containerScanSnapshotProvider)
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
DisplayName = scanSizeOf.DisplayName,
|
||||||
|
FullName = new FullName(randomId),
|
||||||
|
NativePath = new NativePath(randomId),
|
||||||
|
Parent = new AbsolutePath(_timelessContentProvider, _containerScanSnapshotProvider),
|
||||||
|
RealContainer = scanSizeOf
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (_sizeScanThread != null) return;
|
||||||
|
|
||||||
|
var sizeScanThread = new Thread(Run);
|
||||||
|
sizeScanThread.Start();
|
||||||
|
_sizeScanThread = sizeScanThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await TraverseTree(_scanSizeOf, SizeContainer);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while scanning container {ContainerName}", _scanSizeOf.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: make static
|
||||||
|
private async Task TraverseTree(
|
||||||
|
IContainer realContainer,
|
||||||
|
IContainerSizeScanContainer container)
|
||||||
|
{
|
||||||
|
var resolvedItems = new List<IItem>(realContainer.Items.Count);
|
||||||
|
foreach (var item in realContainer.Items)
|
||||||
|
{
|
||||||
|
var resolvedItem = await item.ResolveAsync();
|
||||||
|
resolvedItems.Add(resolvedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var element in resolvedItems.OfType<IElement>())
|
||||||
|
{
|
||||||
|
var fileExtension = element.GetExtension<FileExtension>();
|
||||||
|
if (fileExtension?.Size is not { } size) continue;
|
||||||
|
|
||||||
|
var childName = container.FullName!.GetChild(element.Name).Path;
|
||||||
|
await container.AddSizeSourceAsync(new DeclarativeProperty<long>(size));
|
||||||
|
container.Items.Add(new AbsolutePath(
|
||||||
|
_timelessContentProvider,
|
||||||
|
PointInTime.Present,
|
||||||
|
new FullName(childName),
|
||||||
|
AbsolutePathType.Element));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var childContainer in resolvedItems.OfType<IContainer>())
|
||||||
|
{
|
||||||
|
var childName = container.FullName!.GetChild(childContainer.Name).Path;
|
||||||
|
var childSearchContainer = new ContainerSizeScanContainer(_containerScanSnapshotProvider)
|
||||||
|
{
|
||||||
|
Name = childContainer.Name,
|
||||||
|
DisplayName = childContainer.DisplayName,
|
||||||
|
FullName = new FullName(childName),
|
||||||
|
NativePath = new NativePath(childName),
|
||||||
|
Parent = new AbsolutePath(_timelessContentProvider, container),
|
||||||
|
RealContainer = childContainer
|
||||||
|
};
|
||||||
|
|
||||||
|
container.ChildContainers.Add(childSearchContainer);
|
||||||
|
await container.AddSizeSourceAsync(childSearchContainer.Size);
|
||||||
|
container.Items.Add(new AbsolutePath(
|
||||||
|
_timelessContentProvider,
|
||||||
|
PointInTime.Present,
|
||||||
|
new FullName(childName),
|
||||||
|
AbsolutePathType.Container));
|
||||||
|
|
||||||
|
await TraverseTree(childContainer, childSearchContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/AppCommon/FileTime.App.ContainerSizeScanner/Startup.cs
Normal file
18
src/AppCommon/FileTime.App.ContainerSizeScanner/Startup.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using FileTime.App.Core.Services;
|
||||||
|
using FileTime.Core.ContentAccess;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
|
namespace FileTime.App.ContainerSizeScanner;
|
||||||
|
|
||||||
|
public static class Startup
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddContainerSizeScanner(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.TryAddSingleton<IContainerScanSnapshotProvider, ContainerScanSnapshotProvider>();
|
||||||
|
services.AddSingleton<IContentProvider>(sp => sp.GetRequiredService<IContainerScanSnapshotProvider>());
|
||||||
|
services.AddTransient<ISizeScanTask, SizeScanTask>();
|
||||||
|
services.AddTransient<IItemPreviewProvider, ContainerSizePreviewProvider>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.Core.Services;
|
||||||
|
|
||||||
|
public interface IItemPreviewProvider
|
||||||
|
{
|
||||||
|
bool CanHandle(IItem item);
|
||||||
|
Task<IItemPreviewViewModel> CreatePreviewAsync(IItem item);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace FileTime.App.Core.UserCommand;
|
||||||
|
|
||||||
|
public sealed class ScanSizeCommand : IIdentifiableUserCommand
|
||||||
|
{
|
||||||
|
public const string ScanSizeCommandName = "scan_size";
|
||||||
|
public static readonly ScanSizeCommand Instance = new();
|
||||||
|
|
||||||
|
private ScanSizeCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserCommandID => ScanSizeCommandName;
|
||||||
|
public string Title => "Scan size";
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using FileTime.App.Core.Models;
|
||||||
|
|
||||||
|
namespace FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
|
||||||
|
public interface IElementPreviewViewModel : IItemPreviewViewModel
|
||||||
|
{
|
||||||
|
ItemPreviewMode Mode { get; }
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using FileTime.App.Core.Models;
|
|
||||||
|
|
||||||
namespace FileTime.App.Core.ViewModels.ItemPreview;
|
namespace FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
|
||||||
public interface IItemPreviewViewModel
|
public interface IItemPreviewViewModel
|
||||||
{
|
{
|
||||||
ItemPreviewMode Mode { get; }
|
string Name { get; }
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
<ProjectReference Include="..\..\Tools\FileTime.Tools\FileTime.Tools.csproj" />
|
<ProjectReference Include="..\..\Tools\FileTime.Tools\FileTime.Tools.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
|
<ProjectReference Include="..\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
|
<ProjectReference Include="..\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
|
||||||
|
<ProjectReference Include="..\FileTime.App.ContainerSizeScanner.Abstractions\FileTime.App.ContainerSizeScanner.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
<ProjectReference Include="..\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||||
<ProjectReference Include="..\..\Core\FileTime.Core.Command\FileTime.Core.Command.csproj" />
|
<ProjectReference Include="..\..\Core\FileTime.Core.Command\FileTime.Core.Command.csproj" />
|
||||||
<ProjectReference Include="..\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />
|
<ProjectReference Include="..\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
using FileTime.Core.Models;
|
||||||
|
using InitableService;
|
||||||
|
|
||||||
|
namespace FileTime.App.Core.Services;
|
||||||
|
|
||||||
|
public class ElementPreviewProvider : IItemPreviewProvider
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public ElementPreviewProvider(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanHandle(IItem item) => item is IElement;
|
||||||
|
|
||||||
|
public async Task<IItemPreviewViewModel> CreatePreviewAsync(IItem item)
|
||||||
|
{
|
||||||
|
if (item is not IElement element) throw new NotSupportedException();
|
||||||
|
|
||||||
|
return await _serviceProvider
|
||||||
|
.GetAsyncInitableResolver(element)
|
||||||
|
.GetRequiredServiceAsync<ElementPreviewViewModel>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,14 +9,21 @@ namespace FileTime.App.Core.Services;
|
|||||||
public class ItemPreviewService : IItemPreviewService
|
public class ItemPreviewService : IItemPreviewService
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly IEnumerable<IItemPreviewProvider> _itemPreviewProviders;
|
||||||
public IObservable<IItemPreviewViewModel?> ItemPreview { get; }
|
public IObservable<IItemPreviewViewModel?> ItemPreview { get; }
|
||||||
|
|
||||||
public ItemPreviewService(IAppState appState, IServiceProvider serviceProvider)
|
public ItemPreviewService(
|
||||||
|
IAppState appState,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
IEnumerable<IItemPreviewProvider> itemPreviewProviders)
|
||||||
{
|
{
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
|
_itemPreviewProviders = itemPreviewProviders;
|
||||||
ItemPreview = appState
|
ItemPreview = appState
|
||||||
.SelectedTab
|
.SelectedTab
|
||||||
.Select(t => t?.CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)) ?? Observable.Return<IItemViewModel?>(null))
|
.Select(t =>
|
||||||
|
t?.CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250))
|
||||||
|
?? Observable.Return<IItemViewModel?>(null))
|
||||||
.Switch()
|
.Switch()
|
||||||
.Select(item =>
|
.Select(item =>
|
||||||
item == null
|
item == null
|
||||||
@@ -30,11 +37,12 @@ public class ItemPreviewService : IItemPreviewService
|
|||||||
|
|
||||||
private async Task<IItemPreviewViewModel?> Map(IItemViewModel itemViewModel)
|
private async Task<IItemPreviewViewModel?> Map(IItemViewModel itemViewModel)
|
||||||
{
|
{
|
||||||
return itemViewModel.BaseItem switch
|
ArgumentNullException.ThrowIfNull(itemViewModel.BaseItem);
|
||||||
{
|
|
||||||
IElement element => await _serviceProvider.GetAsyncInitableResolver(element)
|
var itemPreviewProvider = _itemPreviewProviders.FirstOrDefault(p => p.CanHandle(itemViewModel.BaseItem));
|
||||||
.GetRequiredServiceAsync<ElementPreviewViewModel>(),
|
|
||||||
_ => null
|
return itemPreviewProvider is null
|
||||||
};
|
? null
|
||||||
|
: await itemPreviewProvider.CreatePreviewAsync(itemViewModel.BaseItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,8 @@ public class TabPersistenceService : ITabPersistenceService
|
|||||||
//TODO: make this a configuration maybe?
|
//TODO: make this a configuration maybe?
|
||||||
private readonly List<string> _contentProvidersNotToRestore = new()
|
private readonly List<string> _contentProvidersNotToRestore = new()
|
||||||
{
|
{
|
||||||
"search"
|
"search",
|
||||||
|
"container-size-scan"
|
||||||
};
|
};
|
||||||
|
|
||||||
private record PersistenceRoot(TabStates? TabStates);
|
private record PersistenceRoot(TabStates? TabStates);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using DeclarativeProperty;
|
using DeclarativeProperty;
|
||||||
|
using FileTime.App.ContainerSizeScanner;
|
||||||
using FileTime.App.Core.UserCommand;
|
using FileTime.App.Core.UserCommand;
|
||||||
using FileTime.App.Core.ViewModels;
|
using FileTime.App.Core.ViewModels;
|
||||||
using FileTime.App.Search;
|
using FileTime.App.Search;
|
||||||
|
using FileTime.Core.Command;
|
||||||
using FileTime.Core.ContentAccess;
|
using FileTime.Core.ContentAccess;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Interactions;
|
using FileTime.Core.Interactions;
|
||||||
@@ -20,6 +22,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
private readonly ITimelessContentProvider _timelessContentProvider;
|
||||||
private readonly IUserCommandHandlerService _userCommandHandlerService;
|
private readonly IUserCommandHandlerService _userCommandHandlerService;
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
private readonly IContentAccessorFactory _contentAccessorFactory;
|
||||||
|
private readonly IContainerScanSnapshotProvider _containerScanSnapshotProvider;
|
||||||
private IDeclarativeProperty<IContainer?>? _currentLocation;
|
private IDeclarativeProperty<IContainer?>? _currentLocation;
|
||||||
private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem;
|
private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem;
|
||||||
private ITabViewModel? _currentSelectedTab;
|
private ITabViewModel? _currentSelectedTab;
|
||||||
@@ -32,7 +35,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
IItemNameConverterService itemNameConverterService,
|
IItemNameConverterService itemNameConverterService,
|
||||||
ITimelessContentProvider timelessContentProvider,
|
ITimelessContentProvider timelessContentProvider,
|
||||||
IUserCommandHandlerService userCommandHandlerService,
|
IUserCommandHandlerService userCommandHandlerService,
|
||||||
IContentAccessorFactory contentAccessorFactory) : base(appState)
|
IContentAccessorFactory contentAccessorFactory,
|
||||||
|
IContainerScanSnapshotProvider containerScanSnapshotProvider) : base(appState)
|
||||||
{
|
{
|
||||||
_systemClipboardService = systemClipboardService;
|
_systemClipboardService = systemClipboardService;
|
||||||
_userCommunicationService = userCommunicationService;
|
_userCommunicationService = userCommunicationService;
|
||||||
@@ -41,6 +45,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
_timelessContentProvider = timelessContentProvider;
|
_timelessContentProvider = timelessContentProvider;
|
||||||
_userCommandHandlerService = userCommandHandlerService;
|
_userCommandHandlerService = userCommandHandlerService;
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
_contentAccessorFactory = contentAccessorFactory;
|
||||||
|
_containerScanSnapshotProvider = containerScanSnapshotProvider;
|
||||||
SaveCurrentLocation(l => _currentLocation = l);
|
SaveCurrentLocation(l => _currentLocation = l);
|
||||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||||
SaveSelectedTab(t => _currentSelectedTab = t);
|
SaveSelectedTab(t => _currentSelectedTab = t);
|
||||||
@@ -51,10 +56,20 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
|||||||
new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath),
|
new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath),
|
||||||
new TypeUserCommandHandler<CopyBase64Command>(CopyBase64),
|
new TypeUserCommandHandler<CopyBase64Command>(CopyBase64),
|
||||||
new TypeUserCommandHandler<SearchCommand>(Search),
|
new TypeUserCommandHandler<SearchCommand>(Search),
|
||||||
|
new TypeUserCommandHandler<ScanSizeCommand>(ScanSize),
|
||||||
new TypeUserCommandHandler<SortItemsCommand>(SortItems),
|
new TypeUserCommandHandler<SortItemsCommand>(SortItems),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ScanSize()
|
||||||
|
{
|
||||||
|
if (_currentLocation?.Value is null) return;
|
||||||
|
|
||||||
|
var searchTask = _containerScanSnapshotProvider.StartSizeScan(_currentLocation.Value);
|
||||||
|
var openContainerCommand = new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, searchTask.SizeContainer));
|
||||||
|
await _userCommandHandlerService.HandleCommandAsync(openContainerCommand);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SortItems(SortItemsCommand sortItemsCommand)
|
private async Task SortItems(SortItemsCommand sortItemsCommand)
|
||||||
{
|
{
|
||||||
if (_currentSelectedTab is null) return;
|
if (_currentSelectedTab is null) return;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public static class Startup
|
|||||||
serviceCollection.TryAddSingleton<IItemPreviewService, ItemPreviewService>();
|
serviceCollection.TryAddSingleton<IItemPreviewService, ItemPreviewService>();
|
||||||
serviceCollection.TryAddSingleton<ITimelineViewModel, TimelineViewModel>();
|
serviceCollection.TryAddSingleton<ITimelineViewModel, TimelineViewModel>();
|
||||||
serviceCollection.TryAddSingleton<IRefreshSmoothnessCalculator, RefreshSmoothnessCalculator>();
|
serviceCollection.TryAddSingleton<IRefreshSmoothnessCalculator, RefreshSmoothnessCalculator>();
|
||||||
|
serviceCollection.TryAddSingleton<IItemPreviewProvider, ElementPreviewProvider>();
|
||||||
|
|
||||||
return serviceCollection
|
return serviceCollection
|
||||||
.AddCommandHandlers()
|
.AddCommandHandlers()
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
|
|||||||
AddUserCommand(RefreshCommand.Instance);
|
AddUserCommand(RefreshCommand.Instance);
|
||||||
AddUserCommand(RenameCommand.Instance);
|
AddUserCommand(RenameCommand.Instance);
|
||||||
AddUserCommand(RunOrOpenCommand.Instance);
|
AddUserCommand(RunOrOpenCommand.Instance);
|
||||||
|
AddUserCommand(ScanSizeCommand.Instance);
|
||||||
AddUserCommand(StartCommandSchedulerCommand.Instance);
|
AddUserCommand(StartCommandSchedulerCommand.Instance);
|
||||||
AddUserCommand(SortItemsCommand.OrderByNameCommand);
|
AddUserCommand(SortItemsCommand.OrderByNameCommand);
|
||||||
AddUserCommand(SortItemsCommand.OrderByNameDescCommand);
|
AddUserCommand(SortItemsCommand.OrderByNameDescCommand);
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ using MvvmGen;
|
|||||||
namespace FileTime.App.Core.ViewModels.ItemPreview;
|
namespace FileTime.App.Core.ViewModels.ItemPreview;
|
||||||
|
|
||||||
[ViewModel]
|
[ViewModel]
|
||||||
public partial class ElementPreviewViewModel : IItemPreviewViewModel, IAsyncInitable<IElement>
|
public partial class ElementPreviewViewModel : IElementPreviewViewModel, IAsyncInitable<IElement>
|
||||||
{
|
{
|
||||||
|
public const string PreviewName = "ElementPreview";
|
||||||
private record EncodingResult(char BinaryChar, string PartialResult);
|
private record EncodingResult(char BinaryChar, string PartialResult);
|
||||||
|
|
||||||
private const int MaxTextPreviewSize = 1024 * 1024;
|
private const int MaxTextPreviewSize = 1024 * 1024;
|
||||||
|
|
||||||
private static readonly List<Encoding> _encodings = new()
|
private static readonly List<Encoding> Encodings = new()
|
||||||
{
|
{
|
||||||
Encoding.UTF8,
|
Encoding.UTF8,
|
||||||
Encoding.Unicode,
|
Encoding.Unicode,
|
||||||
@@ -27,6 +28,8 @@ public partial class ElementPreviewViewModel : IItemPreviewViewModel, IAsyncInit
|
|||||||
[Property] private string? _textContent;
|
[Property] private string? _textContent;
|
||||||
[Property] private string? _textEncoding;
|
[Property] private string? _textEncoding;
|
||||||
|
|
||||||
|
public string Name => PreviewName;
|
||||||
|
|
||||||
public async Task InitAsync(IElement element)
|
public async Task InitAsync(IElement element)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -59,7 +62,7 @@ public partial class ElementPreviewViewModel : IItemPreviewViewModel, IAsyncInit
|
|||||||
(string, Encoding?) GetNormalizedText(byte[] data)
|
(string, Encoding?) GetNormalizedText(byte[] data)
|
||||||
{
|
{
|
||||||
var binaryCharacter = new Dictionary<string, EncodingResult>();
|
var binaryCharacter = new Dictionary<string, EncodingResult>();
|
||||||
foreach (var encoding in _encodings)
|
foreach (var encoding in Encodings)
|
||||||
{
|
{
|
||||||
var text = encoding.GetString(data);
|
var text = encoding.GetString(data);
|
||||||
var binary = false;
|
var binary = false;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using DynamicData;
|
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using DynamicData;
|
|
||||||
using FileTime.Core.ContentAccess;
|
using FileTime.Core.ContentAccess;
|
||||||
using FileTime.Core.Enums;
|
using FileTime.Core.Enums;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.Tools.Compression"
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.Tools.Compression.Core", "Tools\FileTime.Tools.Compression.Core\FileTime.Tools.Compression.Core.csproj", "{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.Tools.Compression.Core", "Tools\FileTime.Tools.Compression.Core\FileTime.Tools.Compression.Core.csproj", "{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.ContainerSizeScanner", "AppCommon\FileTime.App.ContainerSizeScanner\FileTime.App.ContainerSizeScanner.csproj", "{E5FD38ED-6E4B-42AA-850B-470B939B836B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileTime.App.ContainerSizeScanner.Abstractions", "AppCommon\FileTime.App.ContainerSizeScanner.Abstractions\FileTime.App.ContainerSizeScanner.Abstractions.csproj", "{826AFD32-E36B-48BA-BC1E-1476B393CF24}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -297,6 +301,14 @@ Global
|
|||||||
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E5FD38ED-6E4B-42AA-850B-470B939B836B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E5FD38ED-6E4B-42AA-850B-470B939B836B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E5FD38ED-6E4B-42AA-850B-470B939B836B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E5FD38ED-6E4B-42AA-850B-470B939B836B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{826AFD32-E36B-48BA-BC1E-1476B393CF24}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -348,6 +360,8 @@ Global
|
|||||||
{9062F7D2-34DE-44B7-A2D6-8B3AFDEBB606} = {778AAF38-20FF-438C-A9C3-60850C8B5A27}
|
{9062F7D2-34DE-44B7-A2D6-8B3AFDEBB606} = {778AAF38-20FF-438C-A9C3-60850C8B5A27}
|
||||||
{58243F14-15A6-4601-A071-F99BE896D027} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9}
|
{58243F14-15A6-4601-A071-F99BE896D027} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9}
|
||||||
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9}
|
{EE1721A0-D15A-4E40-BEA5-8AB6BAB8FD44} = {8C3CFEFE-78A5-4940-B388-D15FCE02ECE9}
|
||||||
|
{E5FD38ED-6E4B-42AA-850B-470B939B836B} = {A5291117-3001-498B-AC8B-E14F71F72570}
|
||||||
|
{826AFD32-E36B-48BA-BC1E-1476B393CF24} = {A5291117-3001-498B-AC8B-E14F71F72570}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}
|
SolutionGuid = {859FB3DF-C60A-46B1-82E5-90274905D1EF}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Avalonia;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using FileTime.App.CommandPalette;
|
using FileTime.App.CommandPalette;
|
||||||
|
using FileTime.App.ContainerSizeScanner;
|
||||||
using FileTime.App.DependencyInjection;
|
using FileTime.App.DependencyInjection;
|
||||||
using FileTime.App.FrequencyNavigation;
|
using FileTime.App.FrequencyNavigation;
|
||||||
using FileTime.App.Search;
|
using FileTime.App.Search;
|
||||||
@@ -25,6 +26,7 @@ public class App : Application
|
|||||||
.AddServerCoreServices()
|
.AddServerCoreServices()
|
||||||
.AddFrequencyNavigation()
|
.AddFrequencyNavigation()
|
||||||
.AddCommandPalette()
|
.AddCommandPalette()
|
||||||
|
.AddContainerSizeScanner()
|
||||||
.AddSearch()
|
.AddSearch()
|
||||||
.AddCompression()
|
.AddCompression()
|
||||||
.AddConfiguration(configuration)
|
.AddConfiguration(configuration)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette\FileTime.App.CommandPalette.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.ContainerSizeScanner\FileTime.App.ContainerSizeScanner.csproj" />
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.DependencyInjection\FileTime.App.DependencyInjection.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.DependencyInjection\FileTime.App.DependencyInjection.csproj" />
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation\FileTime.App.FrequencyNavigation.csproj" />
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.CommandPalette.Abstractions\FileTime.App.CommandPalette.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.ContainerSizeScanner\FileTime.App.ContainerSizeScanner.csproj" />
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.Core.Abstraction\FileTime.App.Core.Abstraction.csproj" />
|
||||||
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />
|
<ProjectReference Include="..\..\..\AppCommon\FileTime.App.FrequencyNavigation.Abstractions\FileTime.App.FrequencyNavigation.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />
|
<ProjectReference Include="..\..\..\Providers\FileTime.Providers.Local.Abstractions\FileTime.Providers.Local.Abstractions.csproj" />
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<ResourceInclude Source="avares://FileTime.GuiApp/Resources/Brushes.axaml" />
|
<ResourceInclude Source="avares://FileTime.GuiApp/Resources/Brushes.axaml" />
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary>
|
||||||
<converters:ItemViewModeToBrushConverter
|
<converters:ItemViewModeToBrushConverter
|
||||||
AlternativeBrush="{StaticResource AlternativeItemForegroundBrush}"
|
AlternativeBrush="{StaticResource AlternativeItemForegroundBrush}"
|
||||||
DefaultBrush="{StaticResource ForegroundBrush}"
|
DefaultBrush="{StaticResource ForegroundBrush}"
|
||||||
@@ -27,14 +27,17 @@
|
|||||||
x:Key="ItemViewModeToBackgroundConverter" />
|
x:Key="ItemViewModeToBackgroundConverter" />
|
||||||
<converters:NamePartShrinkerConverter x:Key="NamePartShrinkerConverter" />
|
<converters:NamePartShrinkerConverter x:Key="NamePartShrinkerConverter" />
|
||||||
<converters:ItemViewModelIsAttributeTypeConverter x:Key="ItemViewModelIsAttributeTypeConverter" />
|
<converters:ItemViewModelIsAttributeTypeConverter x:Key="ItemViewModelIsAttributeTypeConverter" />
|
||||||
<converters:ItemViewModelIsAttributeTypeConverter Invert="true" x:Key="ItemViewModelIsNotAttributeTypeConverter" />
|
<converters:ItemViewModelIsAttributeTypeConverter Invert="true"
|
||||||
|
x:Key="ItemViewModelIsNotAttributeTypeConverter" />
|
||||||
<converters:GetFileExtensionConverter x:Key="GetFileExtensionConverter" />
|
<converters:GetFileExtensionConverter x:Key="GetFileExtensionConverter" />
|
||||||
<converters:FormatSizeConverter x:Key="FormatSizeConverter" />
|
<converters:FormatSizeConverter x:Key="FormatSizeConverter" />
|
||||||
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
||||||
<converters:SplitStringConverter x:Key="SplitStringConverter" />
|
<converters:SplitStringConverter x:Key="SplitStringConverter" />
|
||||||
<converters:CompareConverter x:Key="EqualsConverter" />
|
<converters:CompareConverter x:Key="EqualsConverter" />
|
||||||
<converters:CompareConverter ComparisonCondition="{x:Static converters:ComparisonCondition.NotEqual}" x:Key="NotEqualsConverter" />
|
<converters:CompareConverter ComparisonCondition="{x:Static converters:ComparisonCondition.NotEqual}"
|
||||||
<converters:CompareConverter ComparisonCondition="{x:Static converters:ComparisonCondition.GreaterThan}" x:Key="GreaterThanConverter" />
|
x:Key="NotEqualsConverter" />
|
||||||
|
<converters:CompareConverter ComparisonCondition="{x:Static converters:ComparisonCondition.GreaterThan}"
|
||||||
|
x:Key="GreaterThanConverter" />
|
||||||
<converters:ExceptionToStringConverter x:Key="ExceptionToStringConverter" />
|
<converters:ExceptionToStringConverter x:Key="ExceptionToStringConverter" />
|
||||||
<converters:CommandToCommandNameConverter x:Key="CommandToCommandNameConverter" />
|
<converters:CommandToCommandNameConverter x:Key="CommandToCommandNameConverter" />
|
||||||
<converters:ItemToImageConverter x:Key="ItemToImageConverter" />
|
<converters:ItemToImageConverter x:Key="ItemToImageConverter" />
|
||||||
@@ -44,4 +47,6 @@
|
|||||||
x:Key="PathPreformatter" />
|
x:Key="PathPreformatter" />
|
||||||
<converters:ContextMenuGenerator x:Key="ContextMenuGenerator" />
|
<converters:ContextMenuGenerator x:Key="ContextMenuGenerator" />
|
||||||
<converters:TextDecorationConverter x:Key="TextDecorationConverter" />
|
<converters:TextDecorationConverter x:Key="TextDecorationConverter" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@@ -27,8 +27,10 @@
|
|||||||
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
|
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
|
||||||
xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"
|
xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"
|
||||||
xmlns:interactions="using:FileTime.Core.Interactions"
|
xmlns:interactions="using:FileTime.Core.Interactions"
|
||||||
|
xmlns:itemPreview="clr-namespace:FileTime.App.Core.ViewModels.ItemPreview;assembly=FileTime.App.Core"
|
||||||
xmlns:local="using:FileTime.GuiApp.Views"
|
xmlns:local="using:FileTime.GuiApp.Views"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:sizePreview="clr-namespace:FileTime.App.ContainerSizeScanner;assembly=FileTime.App.ContainerSizeScanner"
|
||||||
xmlns:vm="using:FileTime.GuiApp.ViewModels"
|
xmlns:vm="using:FileTime.GuiApp.ViewModels"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
@@ -45,8 +47,7 @@
|
|||||||
</Window.Styles>
|
</Window.Styles>
|
||||||
|
|
||||||
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
<Grid Background="{DynamicResource AppBackgroundBrush}">
|
||||||
<Grid IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}, FallbackValue=False}"
|
<Grid IsVisible="{Binding Loading, Converter={x:Static BoolConverters.Not}, FallbackValue=False}" x:DataType="vm:IMainWindowViewModel">
|
||||||
x:DataType="vm:IMainWindowViewModel">
|
|
||||||
|
|
||||||
<Grid ColumnDefinitions="250,*" RowDefinitions="Auto,*">
|
<Grid ColumnDefinitions="250,*" RowDefinitions="Auto,*">
|
||||||
|
|
||||||
@@ -60,10 +61,8 @@
|
|||||||
|
|
||||||
<Grid ColumnDefinitions="*, Auto">
|
<Grid ColumnDefinitions="*, Auto">
|
||||||
<StackPanel Margin="20,10" Orientation="Horizontal">
|
<StackPanel Margin="20,10" Orientation="Horizontal">
|
||||||
<local:PathPresenter
|
<local:PathPresenter DataContext="{Binding AppState.SelectedTab^.CurrentLocation^.FullName.Path, Converter={StaticResource PathPreformatter}}" />
|
||||||
DataContext="{Binding AppState.SelectedTab^.CurrentLocation^.FullName.Path, Converter={StaticResource PathPreformatter}}" />
|
<TextBlock Foreground="{StaticResource AccentBrush}" Text="{Binding AppState.SelectedTab^.CurrentSelectedItem.Value.DisplayNameText}" />
|
||||||
<TextBlock Foreground="{StaticResource AccentBrush}"
|
|
||||||
Text="{Binding AppState.SelectedTab^.CurrentSelectedItem.Value.DisplayNameText}" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
@@ -363,8 +362,7 @@
|
|||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Margin="0,5,5,5">
|
Margin="0,5,5,5">
|
||||||
<TextBlock Text="{Binding DisplayDetailLabel^}"
|
<TextBlock Text="{Binding DisplayDetailLabel^}" TextAlignment="Right" />
|
||||||
TextAlignment="Right" />
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
Margin="0,5,0,0"
|
Margin="0,5,0,0"
|
||||||
@@ -376,9 +374,7 @@
|
|||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Margin="5,5,0,5">
|
Margin="5,5,0,5">
|
||||||
<TextBlock
|
<TextBlock Text="{Binding TotalProgress^, StringFormat={}{0}%}" TextAlignment="Right" />
|
||||||
Text="{Binding TotalProgress^, StringFormat={}{0}%}"
|
|
||||||
TextAlignment="Right" />
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
Margin="0,5,0,0"
|
Margin="0,5,0,0"
|
||||||
@@ -417,8 +413,7 @@
|
|||||||
<Grid RowDefinitions="Auto,1">
|
<Grid RowDefinitions="Auto,1">
|
||||||
<StackPanel Margin="20,0,20,0" Orientation="Horizontal">
|
<StackPanel Margin="20,0,20,0" Orientation="Horizontal">
|
||||||
|
|
||||||
<TextBlock Text="{Binding TabNumber, StringFormat=({0})}"
|
<TextBlock Text="{Binding TabNumber, StringFormat=({0})}" VerticalAlignment="Center" />
|
||||||
VerticalAlignment="Center" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,0,0"
|
Margin="5,0,0,0"
|
||||||
@@ -464,8 +459,7 @@
|
|||||||
Width="1" />
|
Width="1" />
|
||||||
|
|
||||||
<Grid Grid.Column="2" RowDefinitions="Auto,*">
|
<Grid Grid.Column="2" RowDefinitions="Auto,*">
|
||||||
<Grid
|
<Grid IsVisible="{Binding AppState.SelectedTab^.CurrentLocation.Value.IsLoading^, FallbackValue=False}">
|
||||||
IsVisible="{Binding AppState.SelectedTab^.CurrentLocation.Value.IsLoading^, FallbackValue=False}">
|
|
||||||
<Image
|
<Image
|
||||||
Classes="LoadingAnimation"
|
Classes="LoadingAnimation"
|
||||||
Height="40"
|
Height="40"
|
||||||
@@ -484,8 +478,7 @@
|
|||||||
x:Name="CurrentItems">
|
x:Name="CurrentItems">
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate x:DataType="corevm:IItemViewModel">
|
<DataTemplate x:DataType="corevm:IItemViewModel">
|
||||||
<local:ItemView HorizontalAlignment="Stretch"
|
<local:ItemView HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" />
|
||||||
HorizontalContentAlignment="Stretch" />
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
@@ -511,14 +504,11 @@
|
|||||||
Width="1" />
|
Width="1" />
|
||||||
|
|
||||||
<Grid Grid.Column="4">
|
<Grid Grid.Column="4">
|
||||||
<Grid
|
<Grid IsVisible="{Binding ItemPreviewService.ItemPreview^, Converter={x:Static ObjectConverters.IsNull}}">
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^, Converter={x:Static ObjectConverters.IsNull}}">
|
<Grid IsVisible="{Binding AppState.SelectedTab^.SelectedsChildren.Value, Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}">
|
||||||
<Grid
|
|
||||||
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildren.Value, Converter={x:Static ObjectConverters.IsNotNull}, FallbackValue=False}">
|
|
||||||
<Grid RowDefinitions="Auto, Auto, *">
|
<Grid RowDefinitions="Auto, Auto, *">
|
||||||
|
|
||||||
<Grid
|
<Grid IsVisible="{Binding AppState.SelectedTab^.CurrentSelectedItemAsContainer.Value.Container.IsLoading^, FallbackValue=False}">
|
||||||
IsVisible="{Binding AppState.SelectedTab^.CurrentSelectedItemAsContainer.Value.Container.IsLoading^, FallbackValue=False}">
|
|
||||||
<Image
|
<Image
|
||||||
Classes="LoadingAnimation"
|
Classes="LoadingAnimation"
|
||||||
Height="40"
|
Height="40"
|
||||||
@@ -527,8 +517,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
<ItemsRepeater Grid.Row="1"
|
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.SelectedTab^.CurrentLocation.Value.Exceptions}">
|
||||||
ItemsSource="{Binding AppState.SelectedTab^.CurrentLocation.Value.Exceptions}">
|
|
||||||
<ItemsRepeater.ItemTemplate>
|
<ItemsRepeater.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
@@ -565,9 +554,7 @@
|
|||||||
</TextBlock>
|
</TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid
|
<Grid IsVisible="{Binding AppState.SelectedTab^.SelectedsChildren.Value, Converter={x:Static ObjectConverters.IsNull}, ConverterParameter=0, FallbackValue=False}" RowDefinitions="Auto, Auto">
|
||||||
IsVisible="{Binding AppState.SelectedTab^.SelectedsChildren.Value, Converter={x:Static ObjectConverters.IsNull}, ConverterParameter=0, FallbackValue=False}"
|
|
||||||
RowDefinitions="Auto, Auto">
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Foreground="{DynamicResource ErrorBrush}"
|
Foreground="{DynamicResource ErrorBrush}"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
@@ -575,8 +562,7 @@
|
|||||||
Text="There were some errors while opening container."
|
Text="There were some errors while opening container."
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
<ItemsRepeater Grid.Row="1"
|
<ItemsRepeater Grid.Row="1" ItemsSource="{Binding AppState.SelectedTab^.CurrentSelectedItem.Value.BaseItem.Exceptions}">
|
||||||
ItemsSource="{Binding AppState.SelectedTab^.CurrentSelectedItem.Value.BaseItem.Exceptions}">
|
|
||||||
<ItemsRepeater.ItemTemplate>
|
<ItemsRepeater.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
@@ -588,30 +574,109 @@
|
|||||||
</ItemsRepeater>
|
</ItemsRepeater>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid
|
<Grid DataContext="{Binding ItemPreviewService.ItemPreview^}" IsVisible="{Binding Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^, Converter={x:Static ObjectConverters.IsNotNull}}">
|
<Grid IsVisible="{Binding Name, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static itemPreview:ElementPreviewViewModel.PreviewName}}" x:DataType="itemPreview:ElementPreviewViewModel">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}"
|
IsVisible="{Binding Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Unknown}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}"
|
||||||
Text="Don't know how to preview this item." />
|
Text="Don't know how to preview this item." />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}"
|
IsVisible="{Binding Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Empty}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}"
|
||||||
Text="Empty" />
|
Text="Empty" />
|
||||||
<Grid
|
<Grid IsVisible="{Binding Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}" RowDefinitions="*, Auto">
|
||||||
IsVisible="{Binding ItemPreviewService.ItemPreview^.Mode, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appCoreModels:ItemPreviewMode.Text}, FallbackValue={x:Static appCoreModels:ItemPreviewMode.Unknown}}"
|
|
||||||
RowDefinitions="*, Auto">
|
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<TextBox
|
<TextBox IsReadOnly="True" Text="{Binding TextContent}" />
|
||||||
IsReadOnly="True"
|
|
||||||
Text="{Binding ItemPreviewService.ItemPreview^.TextContent}"
|
|
||||||
x:CompileBindings="False" />
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Margin="5"
|
Margin="5"
|
||||||
Text="{Binding ItemPreviewService.ItemPreview^.TextEncoding, StringFormat=Encoding: {0}}"
|
Text="{Binding TextEncoding, StringFormat=Encoding: {0}}" />
|
||||||
x:CompileBindings="False" />
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid
|
||||||
|
IsVisible="{Binding Name, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static sizePreview:ContainerSizeContainerPreview.PreviewName}}"
|
||||||
|
RowDefinitions="Auto, Auto"
|
||||||
|
x:DataType="sizePreview:ContainerSizeContainerPreview">
|
||||||
|
<ItemsControl Items="{Binding TopItems^}" Margin="0,0,0,30">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid>
|
||||||
|
<Grid.Width>
|
||||||
|
<MultiBinding Converter="{StaticResource ItemSizeToSizeConverter}">
|
||||||
|
<MultiBinding.Bindings>
|
||||||
|
<Binding />
|
||||||
|
<Binding ElementName="SizeContainerPreview" Path="DataContext.TopItems^" />
|
||||||
|
<Binding ElementName="SizeContainerPreview" Path="Bounds.Width" />
|
||||||
|
</MultiBinding.Bindings>
|
||||||
|
</MultiBinding>
|
||||||
|
</Grid.Width>
|
||||||
|
|
||||||
|
<Rectangle HorizontalAlignment="Stretch">
|
||||||
|
<Rectangle.Fill>
|
||||||
|
<MultiBinding Converter="{StaticResource ItemSizeToBrushConverter}">
|
||||||
|
<MultiBinding.Bindings>
|
||||||
|
<Binding />
|
||||||
|
<Binding ElementName="SizeContainerPreview" Path="DataContext.Items^" />
|
||||||
|
</MultiBinding.Bindings>
|
||||||
|
</MultiBinding>
|
||||||
|
</Rectangle.Fill>
|
||||||
|
</Rectangle>
|
||||||
|
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Center">
|
||||||
|
<TextBlock
|
||||||
|
Classes="SmallText"
|
||||||
|
Margin="0,5,0,2"
|
||||||
|
Text="{Binding Name}">
|
||||||
|
<TextBlock.Foreground>
|
||||||
|
<MultiBinding Converter="{StaticResource ItemSizeToForegroundBrushConverter}">
|
||||||
|
<MultiBinding.Bindings>
|
||||||
|
<Binding />
|
||||||
|
<Binding ElementName="SizeContainerPreview" Path="DataContext.Items^" />
|
||||||
|
</MultiBinding.Bindings>
|
||||||
|
</MultiBinding>
|
||||||
|
</TextBlock.Foreground>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock
|
||||||
|
Classes="SmallText"
|
||||||
|
Margin="0,2,0,5"
|
||||||
|
Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}">
|
||||||
|
<TextBlock.Foreground>
|
||||||
|
<MultiBinding Converter="{StaticResource ItemSizeToForegroundBrushConverter}">
|
||||||
|
<MultiBinding.Bindings>
|
||||||
|
<Binding />
|
||||||
|
<Binding ElementName="SizeContainerPreview" Path="DataContext.Items^" />
|
||||||
|
</MultiBinding.Bindings>
|
||||||
|
</MultiBinding>
|
||||||
|
</TextBlock.Foreground>
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
<ItemsControl
|
||||||
|
Grid.Row="1"
|
||||||
|
Items="{Binding Items^}"
|
||||||
|
x:CompileBindings="False">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid ColumnDefinitions="Auto,*" Margin="0,0,0,20">
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,20,0"
|
||||||
|
Text="{Binding Size, Converter={StaticResource FormatSizeConverter}, ConverterParameter=0}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -654,9 +719,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid Grid.Row="3">
|
<Grid Grid.Row="3">
|
||||||
<Grid
|
<Grid IsVisible="{Binding AppState.ViewMode^, Converter={StaticResource EqualsConverter}, ConverterParameter=RapidTravel}" RowDefinitions="1,Auto">
|
||||||
IsVisible="{Binding AppState.ViewMode^, Converter={StaticResource EqualsConverter}, ConverterParameter=RapidTravel}"
|
|
||||||
RowDefinitions="1,Auto">
|
|
||||||
|
|
||||||
<Rectangle
|
<Rectangle
|
||||||
Fill="{DynamicResource ContentSeparatorBrush}"
|
Fill="{DynamicResource ContentSeparatorBrush}"
|
||||||
@@ -678,8 +741,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid
|
<Grid IsVisible="{Binding AppState.PossibleCommands.Count, Converter={StaticResource NotEqualsConverter}, ConverterParameter=0}">
|
||||||
IsVisible="{Binding AppState.PossibleCommands.Count, Converter={StaticResource NotEqualsConverter}, ConverterParameter=0}">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="1" />
|
<RowDefinition Height="1" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
@@ -702,8 +764,7 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Text="{Binding KeysDisplayText}" />
|
<TextBlock Text="{Binding KeysDisplayText}" />
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1" Text="{Binding Command, Converter={StaticResource CommandToCommandNameConverter}}" />
|
||||||
Text="{Binding Command, Converter={StaticResource CommandToCommandNameConverter}}" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsRepeater.ItemTemplate>
|
</ItemsRepeater.ItemTemplate>
|
||||||
@@ -772,10 +833,8 @@
|
|||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid
|
<Grid IsVisible="{Binding PreviewType, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appInteractions:PreviewType.DoubleTextList}}">
|
||||||
IsVisible="{Binding PreviewType, Converter={StaticResource EqualsConverter}, ConverterParameter={x:Static appInteractions:PreviewType.DoubleTextList}}">
|
<ItemsControl ItemsSource="{Binding Items}" x:DataType="appInteractions:DoubleTextListPreview">
|
||||||
<ItemsControl ItemsSource="{Binding Items}"
|
|
||||||
x:DataType="appInteractions:DoubleTextListPreview">
|
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid ColumnDefinitions="*,*">
|
<Grid ColumnDefinitions="*,*">
|
||||||
@@ -787,13 +846,11 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding Text}"
|
<TextBlock Text="{Binding Text}" TextDecorations="{Binding IsSpecial, Converter={StaticResource TextDecorationConverter}}" />
|
||||||
TextDecorations="{Binding IsSpecial, Converter={StaticResource TextDecorationConverter}}" />
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
<ItemsControl Grid.Column="1"
|
<ItemsControl Grid.Column="1" ItemsSource="{Binding Text2^}">
|
||||||
ItemsSource="{Binding Text2^}">
|
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<StackPanel Orientation="Horizontal" />
|
<StackPanel Orientation="Horizontal" />
|
||||||
@@ -801,8 +858,7 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding Text}"
|
<TextBlock Text="{Binding Text}" TextDecorations="{Binding IsSpecial, Converter={StaticResource TextDecorationConverter}}" />
|
||||||
TextDecorations="{Binding IsSpecial, Converter={StaticResource TextDecorationConverter}}" />
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
@@ -908,7 +964,7 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
|
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<Grid Margin="100" Background="{DynamicResource ContainerBackgroundColor}">
|
<Grid Background="{DynamicResource ContainerBackgroundColor}" Margin="100">
|
||||||
<local:FrequencyNavigation IsVisible="{Binding ShowWindow^, FallbackValue=False}" />
|
<local:FrequencyNavigation IsVisible="{Binding ShowWindow^, FallbackValue=False}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
@@ -919,7 +975,7 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
|
IsVisible="{Binding ShowWindow^, FallbackValue=False}"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<Grid Margin="100" Background="{DynamicResource ContainerBackgroundColor}">
|
<Grid Background="{DynamicResource ContainerBackgroundColor}" Margin="100">
|
||||||
<local:CommandPalette IsVisible="{Binding ShowWindow^, FallbackValue=False}" />
|
<local:CommandPalette IsVisible="{Binding ShowWindow^, FallbackValue=False}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public sealed class CombineProperty<TFrom, TTo> : DeclarativePropertyBase<TTo>
|
|||||||
_combiner = combiner;
|
_combiner = combiner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddSource(IDeclarativeProperty<TFrom> source)
|
public async Task AddSourceAsync(IDeclarativeProperty<TFrom> source)
|
||||||
{
|
{
|
||||||
if (_sourceProperties.Contains(source)) return;
|
if (_sourceProperties.Contains(source)) return;
|
||||||
_sourceProperties.Add(source);
|
_sourceProperties.Add(source);
|
||||||
|
|||||||
Reference in New Issue
Block a user