From ff1f6e1c3e08ad64f83cfd57d3b65414ffd0465b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 24 Aug 2023 15:50:11 +0200 Subject: [PATCH] ContentProvider more async --- .../ContainerSizeSizeScanProvider.cs | 8 ++-- .../ToolUserCommandHandlerService.cs | 15 ++++--- .../SearchContentProvider.cs | 6 ++- .../FileTime.ConsoleUI.App/RootViewModel.cs | 2 - .../InfoProviders/ColorSchema.cs | 3 +- .../Command/ICommandHandler.cs | 2 +- .../ContentAccess/IContentProvider.cs | 6 +-- .../Timeline/ITimelessContentProvider.cs | 4 +- .../FileTime.Core.Command/CommandRunner.cs | 5 ++- .../FileTime.Core.Command.csproj | 1 + .../FileTime.Core.CommandHandlers.csproj | 4 ++ .../StreamCopyCommandHandler.cs | 21 ++++++---- .../ContentProviderBase.cs | 11 +++-- .../RootContentProvider.cs | 6 +-- .../TimelessContentProvider.cs | 12 +++--- .../Services/SystemClipboardService.cs | 4 +- src/Library/TerminalUI/Controls/BinaryView.cs | 3 +- .../ILocalContentProvider.cs | 3 +- .../LocalContentProvider.cs | 18 ++++---- .../LocalItemCreator.cs | 4 +- .../LocalItemDeleter.cs | 2 +- .../LocalItemMover.cs | 4 +- .../AdminContentAccessorFactory.cs | 1 - .../RemoteContentProvider.cs | 41 +++++++++++++++++-- .../RemoteContentWriter.cs | 1 - .../RemoteItemCreator.cs | 1 - .../DummyAdminElevationManager.cs | 1 - .../IRemoteConnection.cs | 1 + .../Connections/SignalR/ISignalRHub.cs | 1 + .../Connections/SignalR/SignalRConnection.cs | 6 +++ .../FileTime.Server.Web/ConnectionHub.cs | 8 +++- 31 files changed, 136 insertions(+), 69 deletions(-) diff --git a/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs b/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs index 6db55d6..15c2562 100644 --- a/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs +++ b/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs @@ -82,8 +82,8 @@ public class ContainerSizeSizeScanProvider : ContentProviderBase, IContainerSize itemInitializationSettings ); - public override NativePath GetNativePath(FullName fullName) - => new(fullName.Path); + public override ValueTask GetNativePathAsync(FullName fullName) + => ValueTask.FromResult(new NativePath(fullName.Path)); public override FullName GetFullName(NativePath nativePath) => new(nativePath.Path); @@ -95,8 +95,8 @@ public class ContainerSizeSizeScanProvider : ContentProviderBase, IContainerSize //TODO read from original source => Task.FromResult((byte[]?) null); - public override bool CanHandlePath(NativePath path) - => path.Path.StartsWith(ContentProviderName); + public override Task CanHandlePathAsync(NativePath path) + => Task.FromResult(path.Path.StartsWith(ContentProviderName)); public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ToolUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ToolUserCommandHandlerService.cs index 6d1b0c0..64ae4ea 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ToolUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ToolUserCommandHandlerService.cs @@ -12,7 +12,6 @@ using FileTime.Core.Timeline; using FileTime.Providers.Remote; using FileTime.Server.Common; using FileTime.Server.Common.Connections.SignalR; -using InitableService; using Microsoft.Extensions.Logging; namespace FileTime.App.Core.Services.UserCommandHandler; @@ -28,7 +27,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase private readonly IContentAccessorFactory _contentAccessorFactory; private readonly IContainerSizeScanProvider _containerSizeScanProvider; private readonly IProgramsService _programsService; - private readonly IServiceProvider _serviceProvider; + private readonly IContentProviderRegistry _contentProviderRegistry; private readonly ILogger _logger; private IDeclarativeProperty? _currentLocation; private IDeclarativeProperty? _currentSelectedItem; @@ -45,7 +44,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase IContentAccessorFactory contentAccessorFactory, IContainerSizeScanProvider containerSizeScanProvider, IProgramsService programsService, - IServiceProvider serviceProvider, + IContentProviderRegistry contentProviderRegistry, ILogger logger) : base(appState) { _systemClipboardService = systemClipboardService; @@ -57,7 +56,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase _contentAccessorFactory = contentAccessorFactory; _containerSizeScanProvider = containerSizeScanProvider; _programsService = programsService; - _serviceProvider = serviceProvider; + _contentProviderRegistry = contentProviderRegistry; _logger = logger; SaveCurrentLocation(l => _currentLocation = l); SaveCurrentSelectedItem(i => _currentSelectedItem = i); @@ -81,7 +80,7 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase var containerNameInput = new TextInputElement("Path"); var providerName = new TextInputElement("Provider name") { - Value = "remote_" + Guid.NewGuid().ToString("N") + Value = "remote_" + Guid.NewGuid().ToString("N")[..8] }; var inputs = new IInputElement[] {containerNameInput, providerName}; var result = await _userCommunicationService.ReadInputs(inputs); @@ -113,6 +112,12 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase connection, "local", providerName.Value); + + _contentProviderRegistry.AddContentProvider(remoteContentProvider); + + + await _userCommandHandlerService.HandleCommandAsync( + new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, remoteContentProvider))); } private Task Edit() diff --git a/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs b/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs index 2ab4cde..252d269 100644 --- a/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs +++ b/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs @@ -66,7 +66,9 @@ public class SearchContentProvider : ContentProviderBase, ISearchContentProvider .First(searchTask => searchTask.SearchContainer.NativePath == nativePath).SearchContainer); } - public override NativePath GetNativePath(FullName fullName) => new(fullName.Path); + public override ValueTask GetNativePathAsync(FullName fullName) + => ValueTask.FromResult(new NativePath(fullName.Path)); + public override FullName GetFullName(NativePath nativePath) => new(nativePath.Path); public override Task GetContentAsync( @@ -76,7 +78,7 @@ public class SearchContentProvider : ContentProviderBase, ISearchContentProvider ) => Task.FromResult(null as byte[]); - public override bool CanHandlePath(NativePath path) => path.Path.StartsWith(ContentProviderName); + public override Task CanHandlePathAsync(NativePath path) => Task.FromResult(path.Path.StartsWith(ContentProviderName)); public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; public async Task StartSearchAsync(ISearchMatcher matcher, IContainer searchIn) diff --git a/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs b/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs index d49b780..8d210b9 100644 --- a/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs +++ b/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs @@ -4,11 +4,9 @@ using FileTime.App.Core.Services; using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels.Timeline; using FileTime.App.FrequencyNavigation.ViewModels; -using FileTime.ConsoleUI.App.Preview; using FileTime.ConsoleUI.App.Services; using FileTime.Core.Interactions; using FileTime.Core.Models; -using PropertyChanged.SourceGenerator; namespace FileTime.ConsoleUI.App; diff --git a/src/ConsoleApp/FileTime.ConsoleUI/InfoProviders/ColorSchema.cs b/src/ConsoleApp/FileTime.ConsoleUI/InfoProviders/ColorSchema.cs index 8c346d6..3c603fd 100644 --- a/src/ConsoleApp/FileTime.ConsoleUI/InfoProviders/ColorSchema.cs +++ b/src/ConsoleApp/FileTime.ConsoleUI/InfoProviders/ColorSchema.cs @@ -1,5 +1,4 @@ -using FileTime.ConsoleUI.App; -using FileTime.ConsoleUI.App.Styling; +using FileTime.ConsoleUI.App.Styling; using TerminalUI.Color; using TerminalUI.ConsoleDrivers; using TerminalUI.Models; diff --git a/src/Core/FileTime.Core.Abstraction/Command/ICommandHandler.cs b/src/Core/FileTime.Core.Abstraction/Command/ICommandHandler.cs index bf370d3..3bd11ea 100644 --- a/src/Core/FileTime.Core.Abstraction/Command/ICommandHandler.cs +++ b/src/Core/FileTime.Core.Abstraction/Command/ICommandHandler.cs @@ -2,6 +2,6 @@ namespace FileTime.Core.Command; public interface ICommandHandler { - bool CanHandle(ICommand command); + Task CanHandleAsync(ICommand command); Task ExecuteAsync(ICommand command); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs b/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs index 548c297..76fd3d4 100644 --- a/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs +++ b/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs @@ -22,11 +22,11 @@ public interface IContentProvider : IContainer, IOnContainerEnter AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, ItemInitializationSettings itemInitializationSettings = default); - NativePath GetNativePath(FullName fullName); + ValueTask GetNativePathAsync(FullName fullName); FullName GetFullName(NativePath nativePath); Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default); - bool CanHandlePath(NativePath path); - bool CanHandlePath(FullName path); + Task CanHandlePathAsync(NativePath path); + Task CanHandlePathAsync(FullName path); VolumeSizeInfo? GetVolumeSizeInfo(FullName path); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Timeline/ITimelessContentProvider.cs b/src/Core/FileTime.Core.Abstraction/Timeline/ITimelessContentProvider.cs index 74a7afd..21c3234 100644 --- a/src/Core/FileTime.Core.Abstraction/Timeline/ITimelessContentProvider.cs +++ b/src/Core/FileTime.Core.Abstraction/Timeline/ITimelessContentProvider.cs @@ -15,6 +15,6 @@ public interface ITimelessContentProvider ItemInitializationSettings itemInitializationSettings = default); Task GetItemByNativePathAsync(NativePath nativePath, PointInTime? pointInTime = null); - FullName? GetFullNameByNativePath(NativePath nativePath); - NativePath? GetNativePathByFullName(FullName fullName); + ValueTask GetFullNameByNativePathAsync(NativePath nativePath); + ValueTask GetNativePathByFullNameAsync(FullName fullName); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/CommandRunner.cs b/src/Core/FileTime.Core.Command/CommandRunner.cs index 9fa310e..13c0804 100644 --- a/src/Core/FileTime.Core.Command/CommandRunner.cs +++ b/src/Core/FileTime.Core.Command/CommandRunner.cs @@ -23,7 +23,10 @@ public class CommandRunner : ICommandRunner } else { - var commandHandler = _commandHandlers.Find(c => c.CanHandle(command)); + var commandHandler = await _commandHandlers + .ToAsyncEnumerable() + .FirstOrDefaultAwaitAsync(async c => await c.CanHandleAsync(command)); + if (commandHandler != null) { await commandHandler.ExecuteAsync(command); diff --git a/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj b/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj index 75ac274..39c85f8 100644 --- a/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj +++ b/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Core/FileTime.Core.CommandHandlers/FileTime.Core.CommandHandlers.csproj b/src/Core/FileTime.Core.CommandHandlers/FileTime.Core.CommandHandlers.csproj index 8de1948..20d2a8f 100644 --- a/src/Core/FileTime.Core.CommandHandlers/FileTime.Core.CommandHandlers.csproj +++ b/src/Core/FileTime.Core.CommandHandlers/FileTime.Core.CommandHandlers.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs b/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs index c6cda5f..0a908c4 100644 --- a/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs +++ b/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs @@ -18,25 +18,30 @@ public class StreamCopyCommandHandler : ICommandHandler _contentAccessorFactory = contentAccessorFactory; } - public bool CanHandle(ICommand command) + public async Task CanHandleAsync(ICommand command) { if (command is not CopyCommand copyCommand) return false; var targetSupportsContentStream = - _contentProviderRegistry + (await _contentProviderRegistry .ContentProviders - .FirstOrDefault(p => p.CanHandlePath(copyCommand.Target!)) - ?.SupportsContentStreams ?? false; + .ToAsyncEnumerable() + .FirstOrDefaultAwaitAsync(async p => await p.CanHandlePathAsync(copyCommand.Target)) + )?.SupportsContentStreams ?? false; var allSourcesSupportsContentStream = - copyCommand + (await copyCommand .Sources - .Select(s => + .ToAsyncEnumerable() + .SelectAwait(s => _contentProviderRegistry .ContentProviders - .FirstOrDefault(p => p.CanHandlePath(s)) + .ToAsyncEnumerable() + .FirstOrDefaultAwaitAsync(async p => await p.CanHandlePathAsync(s)) ) - .All(p => p?.SupportsContentStreams ?? false); + .ToListAsync() + ) + .All(p => p?.SupportsContentStreams ?? false); return targetSupportsContentStream && allSourcesSupportsContentStream; } diff --git a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs index 3971e83..fb7b41a 100644 --- a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs +++ b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs @@ -72,7 +72,7 @@ public abstract class ContentProviderBase : IContentProvider bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, ItemInitializationSettings itemInitializationSettings = default) - => await GetItemByNativePathAsync(GetNativePath(fullName), pointInTime, forceResolve, forceResolvePathType, + => await GetItemByNativePathAsync(await GetNativePathAsync(fullName), pointInTime, forceResolve, forceResolvePathType, itemInitializationSettings); public abstract Task GetItemByNativePathAsync(NativePath nativePath, @@ -81,15 +81,18 @@ public abstract class ContentProviderBase : IContentProvider AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, ItemInitializationSettings itemInitializationSettings = default); - public abstract NativePath GetNativePath(FullName fullName); + public abstract ValueTask GetNativePathAsync(FullName fullName); public abstract FullName GetFullName(NativePath nativePath); public abstract Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default); - public abstract bool CanHandlePath(NativePath path); - public bool CanHandlePath(FullName path) => CanHandlePath(GetNativePath(path)); + public abstract Task CanHandlePathAsync(NativePath path); + public async Task CanHandlePathAsync(FullName path) + => path.Path.TrimEnd(Constants.SeparatorChar) == Name + || await CanHandlePathAsync(await GetNativePathAsync(path)); + public abstract VolumeSizeInfo? GetVolumeSizeInfo(FullName path); public IItem WithParent(AbsolutePath parent) => this; diff --git a/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs b/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs index c3653f4..094be4c 100644 --- a/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs +++ b/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs @@ -73,7 +73,7 @@ public class RootContentProvider : IRootContentProvider pointInTime ) ?? throw new FileNotFoundException(); - public NativePath GetNativePath(FullName fullName) => throw new NotImplementedException(); + public ValueTask GetNativePathAsync(FullName fullName) => throw new NotImplementedException(); public FullName GetFullName(NativePath nativePath) => throw new NotImplementedException(); @@ -82,9 +82,9 @@ public class RootContentProvider : IRootContentProvider int? maxLength = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); - public bool CanHandlePath(NativePath path) => throw new NotImplementedException(); + public Task CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); - public bool CanHandlePath(FullName path) => throw new NotImplementedException(); + public Task CanHandlePathAsync(FullName path) => throw new NotImplementedException(); public VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; public IItem WithParent(AbsolutePath parent) => this; diff --git a/src/Core/FileTime.Core.Timeline/TimelessContentProvider.cs b/src/Core/FileTime.Core.Timeline/TimelessContentProvider.cs index fb1b6aa..d04ea7f 100644 --- a/src/Core/FileTime.Core.Timeline/TimelessContentProvider.cs +++ b/src/Core/FileTime.Core.Timeline/TimelessContentProvider.cs @@ -45,7 +45,7 @@ public class TimelessContentProvider : ITimelessContentProvider { foreach (var contentProvider in _contentProviderRegistry.ContentProviders) { - if (!contentProvider.CanHandlePath(nativePath)) continue; + if (!await contentProvider.CanHandlePathAsync(nativePath)) continue; return await contentProvider.GetItemByNativePathAsync(nativePath, pointInTime ?? PointInTime.Present); } @@ -53,11 +53,11 @@ public class TimelessContentProvider : ITimelessContentProvider return null; } - public FullName? GetFullNameByNativePath(NativePath nativePath) + public async ValueTask GetFullNameByNativePathAsync(NativePath nativePath) { foreach (var contentProvider in _contentProviderRegistry.ContentProviders) { - if (!contentProvider.CanHandlePath(nativePath)) continue; + if (!await contentProvider.CanHandlePathAsync(nativePath)) continue; return contentProvider.GetFullName(nativePath); } @@ -65,13 +65,13 @@ public class TimelessContentProvider : ITimelessContentProvider return null; } - public NativePath? GetNativePathByFullName(FullName fullName) + public async ValueTask GetNativePathByFullNameAsync(FullName fullName) { foreach (var contentProvider in _contentProviderRegistry.ContentProviders) { - if (!contentProvider.CanHandlePath(fullName)) continue; + if (!await contentProvider.CanHandlePathAsync(fullName)) continue; - return contentProvider.GetNativePath(fullName); + return await contentProvider.GetNativePathAsync(fullName); } return null; diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Services/SystemClipboardService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Services/SystemClipboardService.cs index 89f1d6b..ecb9cfc 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Services/SystemClipboardService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Services/SystemClipboardService.cs @@ -46,7 +46,7 @@ public class SystemClipboardService : ISystemClipboardService if (obj is IEnumerable storageItems) { return storageItems - .Select(i => _timelessContentProvider.GetFullNameByNativePath(new NativePath(WebUtility.UrlDecode(i.Path.AbsolutePath)))) + .Select(i => _timelessContentProvider.GetFullNameByNativePathAsync(new NativePath(WebUtility.UrlDecode(i.Path.AbsolutePath)))) .Where(i => i != null) .OfType(); } @@ -72,7 +72,7 @@ public class SystemClipboardService : ISystemClipboardService } var fileNativePaths = files - .Select(i => _timelessContentProvider.GetNativePathByFullName(i)) + .Select(i => _timelessContentProvider.GetNativePathByFullNameAsync(i)) .Where(i => i != null) .OfType(); diff --git a/src/Library/TerminalUI/Controls/BinaryView.cs b/src/Library/TerminalUI/Controls/BinaryView.cs index bfa6ecd..48c1e26 100644 --- a/src/Library/TerminalUI/Controls/BinaryView.cs +++ b/src/Library/TerminalUI/Controls/BinaryView.cs @@ -1,5 +1,4 @@ -using System.Reflection.Metadata; -using PropertyChanged.SourceGenerator; +using PropertyChanged.SourceGenerator; using TerminalUI.Color; using TerminalUI.Models; using TerminalUI.Traits; diff --git a/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs b/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs index fdb89c1..fdccd06 100644 --- a/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs @@ -1,8 +1,9 @@ using FileTime.Core.ContentAccess; +using FileTime.Core.Models; namespace FileTime.Providers.Local; public interface ILocalContentProvider : IContentProvider { - + NativePath GetNativePath(FullName fullName); } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs index a465b2b..090e87c 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -54,12 +54,13 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo });*/ } - public override bool CanHandlePath(NativePath path) + public override async Task CanHandlePathAsync(NativePath path) { - var rootDrive = Items - .FirstOrDefault(r => + var rootDrive = await Items + .ToAsyncEnumerable() + .FirstOrDefaultAwaitAsync(async r => path.Path.StartsWith( - GetNativePath(r.Path).Path, + (await GetNativePathAsync(r.Path)).Path, _isCaseInsensitive ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture @@ -73,8 +74,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo { var rootDriveInfos = _rootDriveInfos.Value; var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path)); - - if(rootDriveInfo is null) return null; + + if (rootDriveInfo is null) return null; return new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free); } @@ -391,7 +392,10 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo nativePath.TrimStart(Constants.SeparatorChar).Split(Path.DirectorySeparatorChar))) .TrimEnd(Constants.SeparatorChar))!; - public override NativePath GetNativePath(FullName fullName) + public override ValueTask GetNativePathAsync(FullName fullName) + => ValueTask.FromResult(GetNativePath(fullName)); + + public NativePath GetNativePath(FullName fullName) { var path = string.Join(Path.DirectorySeparatorChar, fullName.Path.Split(Constants.SeparatorChar).Skip(1)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !path.StartsWith("/")) path = "/" + path; diff --git a/src/Providers/FileTime.Providers.Local/LocalItemCreator.cs b/src/Providers/FileTime.Providers.Local/LocalItemCreator.cs index b3637fd..e04dc15 100644 --- a/src/Providers/FileTime.Providers.Local/LocalItemCreator.cs +++ b/src/Providers/FileTime.Providers.Local/LocalItemCreator.cs @@ -24,7 +24,7 @@ public class LocalItemCreator : ItemCreatorBase public override async Task CreateContainerAsync(ILocalContentProvider contentProvider, FullName fullName) { _logger.LogTrace("Start creating container {FullName}", fullName); - var path = contentProvider.GetNativePath(fullName).Path; + var path = (await contentProvider.GetNativePathAsync(fullName)).Path; if (Directory.Exists(path)) { _logger.LogTrace("Container with path {Path} already exists", path); @@ -54,7 +54,7 @@ public class LocalItemCreator : ItemCreatorBase public override async Task CreateElementAsync(ILocalContentProvider contentProvider, FullName fullName) { _logger.LogTrace("Start creating element {FullName}", fullName); - var path = contentProvider.GetNativePath(fullName).Path; + var path = (await contentProvider.GetNativePathAsync(fullName)).Path; if (File.Exists(path)) { _logger.LogTrace("Element with path {Path} already exists", path); diff --git a/src/Providers/FileTime.Providers.Local/LocalItemDeleter.cs b/src/Providers/FileTime.Providers.Local/LocalItemDeleter.cs index 205b874..9291b78 100644 --- a/src/Providers/FileTime.Providers.Local/LocalItemDeleter.cs +++ b/src/Providers/FileTime.Providers.Local/LocalItemDeleter.cs @@ -24,7 +24,7 @@ public class LocalItemDeleter : IItemDeleter public async Task DeleteAsync(ILocalContentProvider contentProvider, FullName fullName) { _logger.LogTrace("Start deleting item {FullName}", fullName); - var nativePath = contentProvider.GetNativePath(fullName).Path; + var nativePath = (await contentProvider.GetNativePathAsync(fullName)).Path; try { diff --git a/src/Providers/FileTime.Providers.Local/LocalItemMover.cs b/src/Providers/FileTime.Providers.Local/LocalItemMover.cs index d7b9da4..40386cd 100644 --- a/src/Providers/FileTime.Providers.Local/LocalItemMover.cs +++ b/src/Providers/FileTime.Providers.Local/LocalItemMover.cs @@ -26,8 +26,8 @@ public class LocalItemMover : IItemMover _logger.LogTrace("Start renaming item {FullName}", fullName); try { - var source = contentProvider.GetNativePath(fullName); - var destination = contentProvider.GetNativePath(newPath); + var source = await contentProvider.GetNativePathAsync(fullName); + var destination = await contentProvider.GetNativePathAsync(newPath); if (File.Exists(source.Path)) { diff --git a/src/Providers/FileTime.Providers.LocalAdmin/AdminContentAccessorFactory.cs b/src/Providers/FileTime.Providers.LocalAdmin/AdminContentAccessorFactory.cs index 257743a..2583e4d 100644 --- a/src/Providers/FileTime.Providers.LocalAdmin/AdminContentAccessorFactory.cs +++ b/src/Providers/FileTime.Providers.LocalAdmin/AdminContentAccessorFactory.cs @@ -1,7 +1,6 @@ using System.Diagnostics; using FileTime.Core.Models; using FileTime.Providers.Remote; -using FileTime.Server.Common; using InitableService; namespace FileTime.Providers.LocalAdmin; diff --git a/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs b/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs index 791560d..83fd69f 100644 --- a/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs +++ b/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs @@ -21,18 +21,51 @@ public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentP RemoteProviderName = remoteName; _remoteConnectionProvider = remoteConnectionProvider; } - public async Task GetRemoteConnectionAsync() + + public async Task GetRemoteConnectionAsync() => await _remoteConnectionProvider(); //TODO implement - public override Task GetItemByNativePathAsync(NativePath nativePath, PointInTime pointInTime, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, ItemInitializationSettings itemInitializationSettings = default) => throw new NotImplementedException(); + public override Task GetItemByNativePathAsync( + NativePath nativePath, + PointInTime pointInTime, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default) => + throw new NotImplementedException(); - public override NativePath GetNativePath(FullName fullName) => throw new NotImplementedException(); + //TODO: make it async + public override async ValueTask GetNativePathAsync(FullName fullName) + { + var remoteFullname = new FullName(ConvertLocalFullNameToRemote(fullName)); + + var connection = await GetRemoteConnectionAsync(); + var remoteNativePath = await connection.GetNativePathAsync(remoteFullname); + return new NativePath(remoteNativePath!.Path); + } public override FullName GetFullName(NativePath nativePath) => throw new NotImplementedException(); public override Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); - public override bool CanHandlePath(NativePath path) => throw new NotImplementedException(); + public override Task CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => throw new NotImplementedException(); + + private string ConvertLocalFullNameToRemote(FullName fullName) + { + var remotePath = + RemoteProviderName + + Constants.SeparatorChar + + fullName.Path[Name.Length..]; + return remotePath; + } + + private FullName ConvertRemoteFullnameToLocal(string remotePath) + { + var localPath = + Name + + Constants.SeparatorChar + + remotePath[RemoteProviderName.Length..]; + return new FullName(localPath); + } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Remote/RemoteContentWriter.cs b/src/Providers/FileTime.Providers.Remote/RemoteContentWriter.cs index 40be0d5..256b811 100644 --- a/src/Providers/FileTime.Providers.Remote/RemoteContentWriter.cs +++ b/src/Providers/FileTime.Providers.Remote/RemoteContentWriter.cs @@ -1,6 +1,5 @@ using FileTime.Core.ContentAccess; using FileTime.Core.Models; -using FileTime.Server.Common; using InitableService; namespace FileTime.Providers.Remote; diff --git a/src/Providers/FileTime.Providers.Remote/RemoteItemCreator.cs b/src/Providers/FileTime.Providers.Remote/RemoteItemCreator.cs index 6609db9..655e967 100644 --- a/src/Providers/FileTime.Providers.Remote/RemoteItemCreator.cs +++ b/src/Providers/FileTime.Providers.Remote/RemoteItemCreator.cs @@ -1,6 +1,5 @@ using FileTime.Core.ContentAccess; using FileTime.Core.Models; -using FileTime.Server.Common; using InitableService; namespace FileTime.Providers.Remote; diff --git a/src/Server/FileTime.Server.App/DummyAdminElevationManager.cs b/src/Server/FileTime.Server.App/DummyAdminElevationManager.cs index f4f8af7..7600a53 100644 --- a/src/Server/FileTime.Server.App/DummyAdminElevationManager.cs +++ b/src/Server/FileTime.Server.App/DummyAdminElevationManager.cs @@ -1,6 +1,5 @@ using FileTime.Providers.LocalAdmin; using FileTime.Providers.Remote; -using FileTime.Server.Common; namespace FileTime.Server.App; diff --git a/src/Server/FileTime.Server.Common.Abstractions/IRemoteConnection.cs b/src/Server/FileTime.Server.Common.Abstractions/IRemoteConnection.cs index 8a62096..19a6dd5 100644 --- a/src/Server/FileTime.Server.Common.Abstractions/IRemoteConnection.cs +++ b/src/Server/FileTime.Server.Common.Abstractions/IRemoteConnection.cs @@ -13,4 +13,5 @@ public interface IRemoteConnection Task WriteBytesAsync(string transactionId, byte[] data, int? index, CancellationToken cancellationToken = default); Task FlushWriterAsync(string transactionId, CancellationToken cancellationToken = default); Task CloseWriterAsync(string transactionId); + Task GetNativePathAsync(FullName fullName); } \ No newline at end of file diff --git a/src/Server/FileTime.Server.Common/Connections/SignalR/ISignalRHub.cs b/src/Server/FileTime.Server.Common/Connections/SignalR/ISignalRHub.cs index 2daf5d1..ac89f85 100644 --- a/src/Server/FileTime.Server.Common/Connections/SignalR/ISignalRHub.cs +++ b/src/Server/FileTime.Server.Common/Connections/SignalR/ISignalRHub.cs @@ -15,4 +15,5 @@ public interface ISignalRHub //TODO: CancellationToken https://github.com/nenoNaninu/TypedSignalR.Client/issues/120 Task WriteBytesAsync(string transactionId, string data, int index); Task CloseWriterAsync(string transactionId); + Task GetNativePathAsync(string fullNamePath); } \ No newline at end of file diff --git a/src/Server/FileTime.Server.Common/Connections/SignalR/SignalRConnection.cs b/src/Server/FileTime.Server.Common/Connections/SignalR/SignalRConnection.cs index a2de47e..57f0a04 100644 --- a/src/Server/FileTime.Server.Common/Connections/SignalR/SignalRConnection.cs +++ b/src/Server/FileTime.Server.Common/Connections/SignalR/SignalRConnection.cs @@ -77,4 +77,10 @@ public class SignalRConnection : IRemoteConnection, IAsyncInitable public async Task CloseWriterAsync(string transactionId) => await _client.CloseWriterAsync(transactionId); + + public async Task GetNativePathAsync(FullName fullName) + { + var path = await _client.GetNativePathAsync(fullName.Path); + return path is null ? null : new NativePath(path); + } } \ No newline at end of file diff --git a/src/Server/FileTime.Server.Web/ConnectionHub.cs b/src/Server/FileTime.Server.Web/ConnectionHub.cs index 547d590..8b34583 100644 --- a/src/Server/FileTime.Server.Web/ConnectionHub.cs +++ b/src/Server/FileTime.Server.Web/ConnectionHub.cs @@ -14,17 +14,20 @@ public class ConnectionHub : Hub, ISignalRHub private readonly IContentAccessorFactory _contentAccessorFactory; private readonly IApplicationStopper _applicationStopper; private readonly IContentAccessManager _contentAccessManager; + private readonly ITimelessContentProvider _timelessContentProvider; public ConnectionHub( IContentProviderRegistry contentProviderRegistry, IContentAccessorFactory contentAccessorFactory, IApplicationStopper applicationStopper, - IContentAccessManager contentAccessManager) + IContentAccessManager contentAccessManager, + ITimelessContentProvider timelessContentProvider) { _contentProviderRegistry = contentProviderRegistry; _contentAccessorFactory = contentAccessorFactory; _applicationStopper = applicationStopper; _contentAccessManager = contentAccessManager; + _timelessContentProvider = timelessContentProvider; } public Task Exit() @@ -86,4 +89,7 @@ public class ConnectionHub : Hub, ISignalRHub _contentAccessManager.RemoveContentWriter(transactionId); return Task.CompletedTask; } + + public async Task GetNativePathAsync(string fullNamePath) + => (await _timelessContentProvider.GetNativePathByFullNameAsync(new FullName(fullNamePath)))?.Path; } \ No newline at end of file