diff --git a/src/AppCommon/FileTime.App.Core/Command/Commands.cs b/src/AppCommon/FileTime.App.Core/Command/Commands.cs index fe66263..c80ec8e 100644 --- a/src/AppCommon/FileTime.App.Core/Command/Commands.cs +++ b/src/AppCommon/FileTime.App.Core/Command/Commands.cs @@ -12,6 +12,7 @@ namespace FileTime.App.Core.Command CreateContainer, CreateElement, Cut, + Edit, EnterRapidTravel, GoToHome, GoToPath, diff --git a/src/Core/FileTime.Core/Models/IItem.cs b/src/Core/FileTime.Core/Models/IItem.cs index 9446825..d7fa444 100644 --- a/src/Core/FileTime.Core/Models/IItem.cs +++ b/src/Core/FileTime.Core/Models/IItem.cs @@ -6,6 +6,7 @@ namespace FileTime.Core.Models { string Name { get; } string? FullName { get; } + string? NativePath { get; } bool IsHidden { get; } bool IsDestroyed { get; } SupportsDelete CanDelete { get; } diff --git a/src/Core/FileTime.Core/Models/VirtualContainer.cs b/src/Core/FileTime.Core/Models/VirtualContainer.cs index 07c59a8..ef5dfec 100644 --- a/src/Core/FileTime.Core/Models/VirtualContainer.cs +++ b/src/Core/FileTime.Core/Models/VirtualContainer.cs @@ -22,6 +22,7 @@ namespace FileTime.Core.Models public string Name => BaseContainer.Name; public string? FullName => BaseContainer.FullName; + public string? NativePath => BaseContainer.NativePath; public bool IsHidden => BaseContainer.IsHidden; public bool IsLoaded => BaseContainer.IsLoaded; diff --git a/src/Core/FileTime.Core/Providers/TopContainer.cs b/src/Core/FileTime.Core/Providers/TopContainer.cs index 1cfe812..0111907 100644 --- a/src/Core/FileTime.Core/Providers/TopContainer.cs +++ b/src/Core/FileTime.Core/Providers/TopContainer.cs @@ -17,6 +17,7 @@ namespace FileTime.Core.Providers #pragma warning restore CS8603 // Possible null reference return. public string? FullName => null; + public string? NativePath => null; public bool IsHidden => false; public bool IsLoaded => true; diff --git a/src/Core/FileTime.Core/Timeline/TimeContainer.cs b/src/Core/FileTime.Core/Timeline/TimeContainer.cs index 9ef9b4b..6338af6 100644 --- a/src/Core/FileTime.Core/Timeline/TimeContainer.cs +++ b/src/Core/FileTime.Core/Timeline/TimeContainer.cs @@ -31,6 +31,9 @@ namespace FileTime.Core.Timeline public bool IsDestroyed { get; private set; } + //FIXME: currently this can be different of the real items NativePath, should be fixed + public string? NativePath => FullName; + public TimeContainer(string name, IContainer parent, IContentProvider contentProvider, IContentProvider virtualContentProvider, PointInTime pointInTime) { _parent = parent; diff --git a/src/Core/FileTime.Core/Timeline/TimeElement.cs b/src/Core/FileTime.Core/Timeline/TimeElement.cs index 226e93b..6ec4d6a 100644 --- a/src/Core/FileTime.Core/Timeline/TimeElement.cs +++ b/src/Core/FileTime.Core/Timeline/TimeElement.cs @@ -22,6 +22,9 @@ namespace FileTime.Core.Timeline public string? FullName { get; } + //FIXME: currently this can be different of the real items NativePath, should be fixed + public string? NativePath => FullName; + public bool IsHidden => false; public SupportsDelete CanDelete => SupportsDelete.True; diff --git a/src/Core/FileTime.Core/Timeline/TimeProvider.cs b/src/Core/FileTime.Core/Timeline/TimeProvider.cs index 43c07cb..8ae9303 100644 --- a/src/Core/FileTime.Core/Timeline/TimeProvider.cs +++ b/src/Core/FileTime.Core/Timeline/TimeProvider.cs @@ -15,6 +15,7 @@ namespace FileTime.Core.Timeline public string Name => "time"; public string? FullName => null; + public string? NativePath => null; public bool IsHidden => false; diff --git a/src/GuiApp/FileTime.Avalonia/App.axaml.cs b/src/GuiApp/FileTime.Avalonia/App.axaml.cs index 386b9b7..6700181 100644 --- a/src/GuiApp/FileTime.Avalonia/App.axaml.cs +++ b/src/GuiApp/FileTime.Avalonia/App.axaml.cs @@ -18,12 +18,12 @@ namespace FileTime.Avalonia ServiceProvider ??= DependencyInjection .RegisterDefaultServices() .AddConfiguration() - .InitSerilog() + .AddServices() .RegisterLogging() .AddViewModels() - .AddServices() .RegisterCommandHandlers() - .BuildServiceProvider(); + .BuildServiceProvider() + .InitSerilog(); var _logger = ServiceProvider.GetService>(); _logger?.LogInformation("App initialization completed."); diff --git a/src/GuiApp/FileTime.Avalonia/Configuration/MainConfiguration.cs b/src/GuiApp/FileTime.Avalonia/Configuration/MainConfiguration.cs index 048e379..3f9bc76 100644 --- a/src/GuiApp/FileTime.Avalonia/Configuration/MainConfiguration.cs +++ b/src/GuiApp/FileTime.Avalonia/Configuration/MainConfiguration.cs @@ -8,32 +8,32 @@ namespace FileTime.Avalonia.Configuration public static class MainConfiguration { private static readonly Lazy> _defaultKeybindings = new(InitDefaultKeyBindings); - internal const string KeybindingBaseConfigKey = "KeyBindings"; public static Dictionary Configuration { get; } static MainConfiguration() { Configuration = new(); - PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, KeybindingBaseConfigKey + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings)); + PopulateDefaultEditorPrograms(Configuration); + PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings)); } - private static void PopulateDefaultKeyBindings(Dictionary keybindings, List commandBindingConfigs, string basePath) + private static void PopulateDefaultKeyBindings(Dictionary configuration, List commandBindingConfigs, string basePath) { for (var i = 0; i < commandBindingConfigs.Count; i++) { var baseKey = basePath + $":[{i}]:"; var commandBindingConfig = commandBindingConfigs[i]; - keybindings.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString()); + configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString()); for (var j = 0; j < commandBindingConfig.Keys.Count; j++) { var key = commandBindingConfig.Keys[j]; var keyBaseKey = baseKey + $"keys:[{j}]:"; - keybindings.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString()); - keybindings.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString()); - keybindings.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString()); - keybindings.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString()); } } } @@ -51,6 +51,7 @@ namespace FileTime.Avalonia.Configuration new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }), new CommandBindingConfiguration(Commands.CreateElement, new[] { Key.C, Key.E }), new CommandBindingConfiguration(Commands.Cut, new[] { Key.D, Key.D }), + new CommandBindingConfiguration(Commands.Edit, new KeyConfig(Key.F4)), new CommandBindingConfiguration(Commands.EnterRapidTravel, new KeyConfig(Key.OemComma, shift: true)), new CommandBindingConfiguration(Commands.GoToHome, new[] { Key.G, Key.H }), new CommandBindingConfiguration(Commands.GoToPath, new KeyConfig(Key.OemComma, ctrl: true)), @@ -97,5 +98,25 @@ namespace FileTime.Avalonia.Configuration new CommandBindingConfiguration(Commands.MoveCursorDownPage, Key.PageDown), }; } + + private static void PopulateDefaultEditorPrograms(Dictionary configuration) + { + var editorPrograms = new List() + { + new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++1.exe"), + new ProgramConfiguration("notepad.exe"), + }; + + for (var i = 0; i < editorPrograms.Count; i++) + { + if (editorPrograms[i].Path is not string path) continue; + configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", path); + + if (editorPrograms[i].Arguments is string arguments) + { + configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", arguments); + } + } + } } } \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Configuration/ProgramConfiguration.cs b/src/GuiApp/FileTime.Avalonia/Configuration/ProgramConfiguration.cs new file mode 100644 index 0000000..198a887 --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Configuration/ProgramConfiguration.cs @@ -0,0 +1,16 @@ +namespace FileTime.Avalonia.Configuration +{ + public class ProgramConfiguration + { + public string? Path { get; set; } + public string? Arguments { get; set; } + + public ProgramConfiguration() { } + + public ProgramConfiguration(string? path, string? arguments = null) + { + Path = path; + Arguments = arguments; + } + } +} \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Configuration/ProgramsConfiguration.cs b/src/GuiApp/FileTime.Avalonia/Configuration/ProgramsConfiguration.cs new file mode 100644 index 0000000..938b57e --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Configuration/ProgramsConfiguration.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace FileTime.Avalonia.Configuration +{ + public class ProgramsConfiguration + { + public List DefaultEditorPrograms { get; set; } = new(); + public List EditorPrograms { get; set; } = new(); + } +} \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Configuration/SectionNames.cs b/src/GuiApp/FileTime.Avalonia/Configuration/SectionNames.cs new file mode 100644 index 0000000..e97187c --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Configuration/SectionNames.cs @@ -0,0 +1,8 @@ +namespace FileTime.Avalonia.Configuration +{ + public static class SectionNames + { + internal const string KeybindingSectionName = "KeyBindings"; + internal const string ProgramsSectionName = "Programs"; + } +} \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Logging/ToastMessageSink.cs b/src/GuiApp/FileTime.Avalonia/Logging/ToastMessageSink.cs new file mode 100644 index 0000000..99ad57f --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Logging/ToastMessageSink.cs @@ -0,0 +1,25 @@ +using FileTime.Avalonia.Services; +using Serilog.Core; +using Serilog.Events; + +namespace FileTime.Avalonia.Logging +{ + public class ToastMessageSink : ILogEventSink + { + private readonly IDialogService dialogService; + + public ToastMessageSink(IDialogService dialogService) + { + this.dialogService = dialogService; + } + + public void Emit(LogEvent logEvent) + { + if (logEvent.Level >= LogEventLevel.Error) + { + var message = logEvent.RenderMessage(); + dialogService.ShowToastMessage(message); + } + } + } +} diff --git a/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs b/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs index a6d8641..10b846f 100644 --- a/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs +++ b/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using Avalonia.Threading; using FileTime.App.Core.Clipboard; using FileTime.App.Core.Command; using FileTime.Avalonia.Application; @@ -17,6 +16,7 @@ using FileTime.Core.Models; using FileTime.Core.Providers; using FileTime.Core.Timeline; using FileTime.Providers.Local; +using Microsoft.Extensions.Logging; namespace FileTime.Avalonia.Services { @@ -27,22 +27,26 @@ namespace FileTime.Avalonia.Services private readonly AppState _appState; private readonly LocalContentProvider _localContentProvider; private readonly ItemNameConverterService _itemNameConverterService; - private readonly DialogService _dialogService; + private readonly IDialogService _dialogService; private readonly IClipboard _clipboard; private readonly TimeRunner _timeRunner; private readonly IIconProvider _iconProvider; private readonly IEnumerable _contentProviders; private readonly Dictionary> _commandHandlers; + private readonly ProgramsService _programsService; + private readonly ILogger _logger; public CommandHandlerService( AppState appState, LocalContentProvider localContentProvider, ItemNameConverterService itemNameConverterService, - DialogService dialogService, + IDialogService dialogService, IClipboard clipboard, TimeRunner timeRunner, IIconProvider iconProvider, - IEnumerable contentProviders) + IEnumerable contentProviders, + ProgramsService programsService, + ILogger logger) { _appState = appState; _localContentProvider = localContentProvider; @@ -52,6 +56,8 @@ namespace FileTime.Avalonia.Services _timeRunner = timeRunner; _iconProvider = iconProvider; _contentProviders = contentProviders; + _programsService = programsService; + _logger = logger; _commandHandlers = new Dictionary> { @@ -541,7 +547,7 @@ namespace FileTime.Avalonia.Services { if (_appState.SelectedTab.CurrentLocation.Container is LocalFolder localFolder) { - var path = localFolder.Directory.FullName; + var path = localFolder.NativePath; if (path != null) { Process.Start("explorer.exe", "\"" + path + "\""); @@ -553,23 +559,12 @@ namespace FileTime.Avalonia.Services private async Task CopyPath() { - string? textToCopy = null; - if (_appState.SelectedTab.CurrentLocation.Container is LocalFolder localFolder) - { - textToCopy = localFolder.Directory.FullName; - } - if (_appState.SelectedTab.CurrentLocation.Container is LocalFile localFile) - { - textToCopy = localFile.File.FullName; - } - else if (_appState.SelectedTab.CurrentLocation.Container.FullName is string fullName) - { - textToCopy = fullName; - } + var currentContainer = _appState.SelectedTab.CurrentLocation.Container; + var textToCopy = currentContainer.NativePath; - if (textToCopy != null && global::Avalonia.Application.Current?.Clipboard is not null) + if (textToCopy != null && global::Avalonia.Application.Current?.Clipboard is global::Avalonia.Input.Platform.IClipboard clipboard) { - await global::Avalonia.Application.Current.Clipboard.SetTextAsync(textToCopy); + await clipboard.SetTextAsync(textToCopy); } } @@ -783,6 +778,46 @@ namespace FileTime.Avalonia.Services private Task Edit() { + if (_appState.SelectedTab.SelectedItem?.Item is IElement element && element.NativePath is string filePath) + { + var getNext = false; + while (true) + { + try + { + var editorProgram = _programsService.GetEditorProgram(getNext); + if (editorProgram is null) + { + break; + } + else if (editorProgram.Path is string executablePath) + { + if (string.IsNullOrWhiteSpace(editorProgram.Arguments)) + { + Process.Start(executablePath, "\"" + filePath + "\""); + } + else + { + var parts = editorProgram.Arguments.Split("%%1"); + var arguments = string.Join("%%1", parts.Select(p => p.Replace("%1", "\"" + filePath + "\""))).Replace("%%1", "%1"); + Process.Start(executablePath, arguments); + } + } + //TODO: else + break; + } + catch (System.ComponentModel.Win32Exception e) + { + _logger.LogError(e, "Error while running editor program, possible the executable path does not exists."); + } + catch (Exception e) + { + _logger.LogError(e, "Unkown error while running editor program."); + } + getNext = true; + } + } + //TODO: else return Task.CompletedTask; } } diff --git a/src/GuiApp/FileTime.Avalonia/Services/DialogService.cs b/src/GuiApp/FileTime.Avalonia/Services/DialogService.cs index 303d2fd..ef5a567 100644 --- a/src/GuiApp/FileTime.Avalonia/Services/DialogService.cs +++ b/src/GuiApp/FileTime.Avalonia/Services/DialogService.cs @@ -9,7 +9,7 @@ using FileTime.Core.Interactions; namespace FileTime.Avalonia.Services { - public class DialogService + public class DialogService : IDialogService { private readonly AppState _appState; @@ -93,10 +93,9 @@ namespace FileTime.Avalonia.Services public void ShowToastMessage(string text) { - _appState.PopupTexts.Add(text); - Task.Run(async () => { + await Dispatcher.UIThread.InvokeAsync(() => _appState.PopupTexts.Add(text)); await Task.Delay(5000); await Dispatcher.UIThread.InvokeAsync(() => _appState.PopupTexts.Remove(text)); }); diff --git a/src/GuiApp/FileTime.Avalonia/Services/IDialogService.cs b/src/GuiApp/FileTime.Avalonia/Services/IDialogService.cs new file mode 100644 index 0000000..44cf68d --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Services/IDialogService.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using FileTime.Avalonia.Misc; +using FileTime.Core.Interactions; + +namespace FileTime.Avalonia.Services +{ + public interface IDialogService + { + void CancelInputs(); + void CancelMessageBox(); + void ClearInputs(); + Task ProcessInputs(); + void ProcessMessageBox(); + void ReadInputs(List inputs, Action> inputHandler); + void ReadInputs(List inputs, Func, Task> inputHandler); + Task ReadInputs(IEnumerable fields); + void ShowMessageBox(string text, Func inputHandler); + void ShowToastMessage(string text); + } +} \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Services/KeyInputHandlerService.cs b/src/GuiApp/FileTime.Avalonia/Services/KeyInputHandlerService.cs index b09b5a6..88dddc8 100644 --- a/src/GuiApp/FileTime.Avalonia/Services/KeyInputHandlerService.cs +++ b/src/GuiApp/FileTime.Avalonia/Services/KeyInputHandlerService.cs @@ -17,13 +17,13 @@ namespace FileTime.Avalonia.Services private readonly AppState _appState; private readonly KeyboardConfigurationService _keyboardConfigurationService; private readonly CommandHandlerService _commandHandlerService; - private readonly DialogService _dialogService; + private readonly IDialogService _dialogService; public KeyInputHandlerService( AppState appState, KeyboardConfigurationService keyboardConfigurationService, CommandHandlerService commandHandlerService, - DialogService dialogService) + IDialogService dialogService) { _appState = appState; _keyboardConfigurationService = keyboardConfigurationService; diff --git a/src/GuiApp/FileTime.Avalonia/Services/ProgramsService.cs b/src/GuiApp/FileTime.Avalonia/Services/ProgramsService.cs new file mode 100644 index 0000000..d5ae0d4 --- /dev/null +++ b/src/GuiApp/FileTime.Avalonia/Services/ProgramsService.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using FileTime.Avalonia.Configuration; +using Microsoft.Extensions.Options; + +namespace FileTime.Avalonia.Services +{ + public class ProgramsService + { + private readonly List _editorPrograms; + private int lastGoodEditorProgramIndex; + + public ProgramsService(IOptions configuration) + { + var config = configuration.Value; + _editorPrograms = config.EditorPrograms.Count == 0 ? config.DefaultEditorPrograms : config.EditorPrograms; + } + + public ProgramConfiguration? GetEditorProgram(bool getNext = false) + { + if (getNext) + { + lastGoodEditorProgramIndex++; + } + if (lastGoodEditorProgramIndex < 0) + { + lastGoodEditorProgramIndex = 0; + } + + if (_editorPrograms.Count <= lastGoodEditorProgramIndex) + { + ResetLastGoodEditor(); + return null; + } + return _editorPrograms[lastGoodEditorProgramIndex]; + } + + public void ResetLastGoodEditor() + { + lastGoodEditorProgramIndex = -1; + } + } +} \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Startup.cs b/src/GuiApp/FileTime.Avalonia/Startup.cs index 43ef024..e383d2a 100644 --- a/src/GuiApp/FileTime.Avalonia/Startup.cs +++ b/src/GuiApp/FileTime.Avalonia/Startup.cs @@ -1,8 +1,10 @@ -using System.IO; +using System; +using System.IO; using System.Runtime.InteropServices; using FileTime.Avalonia.Application; using FileTime.Avalonia.Configuration; using FileTime.Avalonia.IconProviders; +using FileTime.Avalonia.Logging; using FileTime.Avalonia.Services; using FileTime.Avalonia.ViewModels; using FileTime.Core.Command; @@ -12,6 +14,7 @@ using FileTime.Providers.Smb; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Serilog; +using Serilog.Configuration; namespace FileTime.Avalonia { @@ -20,20 +23,22 @@ namespace FileTime.Avalonia internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection) { return serviceCollection - .AddSingleton() .AddTransient() .AddSingleton(); } internal static IServiceCollection AddServices(this IServiceCollection serviceCollection) { serviceCollection = serviceCollection + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() + .AddSingleton() .AddSingleton(new PersistenceSettings(Program.AppDataRoot)) + .AddSingleton() + .AddSingleton() .AddSmbServices() .AddSingleton(); @@ -74,13 +79,13 @@ namespace FileTime.Avalonia .Build(); return serviceCollection - .Configure(configuration.GetSection(MainConfiguration.KeybindingBaseConfigKey)) + .Configure(configuration.GetSection(SectionNames.ProgramsSectionName)) + .Configure(configuration.GetSection(SectionNames.KeybindingSectionName)) .AddSingleton(configuration); } - internal static IServiceCollection InitSerilog(this IServiceCollection serviceCollection) + internal static IServiceProvider InitSerilog(this IServiceProvider serviceProvider) { - using var serviceProvider = serviceCollection.BuildServiceProvider(); Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(serviceProvider.GetService()) .Enrich.FromLogContext() @@ -89,9 +94,17 @@ namespace FileTime.Avalonia fileSizeLimitBytes: 10 * 1024 * 1024, rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Day) + .WriteTo.MessageBoxSink(serviceProvider) .CreateLogger(); - return serviceCollection; + return serviceProvider; + } + + public static LoggerConfiguration MessageBoxSink( + this LoggerSinkConfiguration loggerConfiguration, + IServiceProvider serviceProvider) + { + return loggerConfiguration.Sink(serviceProvider.GetService()); } } } diff --git a/src/GuiApp/FileTime.Avalonia/ViewModels/MainPageViewModel.cs b/src/GuiApp/FileTime.Avalonia/ViewModels/MainPageViewModel.cs index 7049b1b..9ed8f38 100644 --- a/src/GuiApp/FileTime.Avalonia/ViewModels/MainPageViewModel.cs +++ b/src/GuiApp/FileTime.Avalonia/ViewModels/MainPageViewModel.cs @@ -33,7 +33,7 @@ namespace FileTime.Avalonia.ViewModels [Inject(typeof(ILogger), PropertyName = "_logger")] [Inject(typeof(KeyboardConfigurationService))] [Inject(typeof(CommandHandlerService), PropertyAccessModifier = AccessModifier.Public)] - [Inject(typeof(DialogService))] + [Inject(typeof(IDialogService), PropertyName = "_dialogService")] [Inject(typeof(KeyInputHandlerService))] public partial class MainPageViewModel : IMainPageViewModelBase { @@ -73,7 +73,7 @@ namespace FileTime.Avalonia.ViewModels _timeRunner = App.ServiceProvider.GetService()!; var inputInterface = (BasicInputHandler)App.ServiceProvider.GetService()!; - inputInterface.InputHandler = DialogService.ReadInputs; + inputInterface.InputHandler = _dialogService.ReadInputs; App.ServiceProvider.GetService(); await StatePersistence.LoadStatesAsync(); @@ -246,25 +246,25 @@ namespace FileTime.Avalonia.ViewModels [Command] public async void ProcessInputs() { - await DialogService.ProcessInputs(); + await _dialogService.ProcessInputs(); } [Command] public void CancelInputs() { - DialogService.CancelInputs(); + _dialogService.CancelInputs(); } [Command] public void ProcessMessageBox() { - DialogService.ProcessMessageBox(); + _dialogService.ProcessMessageBox(); } [Command] public void CancelMessageBox() { - DialogService.CancelMessageBox(); + _dialogService.CancelMessageBox(); } public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs index 1b0bf59..450fcd6 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -19,6 +19,7 @@ namespace FileTime.Providers.Local public string Name { get; } = "local"; public string? FullName { get; } + public string? NativePath => null; public bool IsHidden => false; public bool IsLoaded => true; diff --git a/src/Providers/FileTime.Providers.Local/LocalFile.cs b/src/Providers/FileTime.Providers.Local/LocalFile.cs index 661d8f6..02404f6 100644 --- a/src/Providers/FileTime.Providers.Local/LocalFile.cs +++ b/src/Providers/FileTime.Providers.Local/LocalFile.cs @@ -14,6 +14,7 @@ namespace FileTime.Providers.Local public string Name { get; } public string FullName { get; } + public string? NativePath => File.FullName; public IContentProvider Provider { get; } diff --git a/src/Providers/FileTime.Providers.Local/LocalFolder.cs b/src/Providers/FileTime.Providers.Local/LocalFolder.cs index 41cc593..29d65bb 100644 --- a/src/Providers/FileTime.Providers.Local/LocalFolder.cs +++ b/src/Providers/FileTime.Providers.Local/LocalFolder.cs @@ -22,6 +22,7 @@ namespace FileTime.Providers.Local public string Name { get; } public string FullName { get; } + public string? NativePath => Directory.FullName; public bool IsLoaded => _items != null; public SupportsDelete CanDelete { get; } diff --git a/src/Providers/FileTime.Providers.Smb/SmbContentProvider.cs b/src/Providers/FileTime.Providers.Smb/SmbContentProvider.cs index f99da8a..565e3d5 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbContentProvider.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbContentProvider.cs @@ -24,6 +24,7 @@ namespace FileTime.Providers.Smb public string Name { get; } = "smb"; public string? FullName { get; } + public string? NativePath => null; public bool IsHidden => false; public bool IsLoaded => true; @@ -177,5 +178,7 @@ namespace FileTime.Providers.Smb } } } + + public static string GetNativePath(string fullName) => fullName.Replace("/", "\\"); } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Smb/SmbFile.cs b/src/Providers/FileTime.Providers.Smb/SmbFile.cs index 14403de..3ddf774 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbFile.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbFile.cs @@ -1,6 +1,5 @@ using FileTime.Core.Models; using FileTime.Core.Providers; -using SMBLibrary.Client; namespace FileTime.Providers.Smb { @@ -11,6 +10,7 @@ namespace FileTime.Providers.Smb public string Name { get; } public string? FullName { get; } + public string? NativePath { get; } public bool IsHidden => false; public SupportsDelete CanDelete => SupportsDelete.True; @@ -25,6 +25,7 @@ namespace FileTime.Providers.Smb { Name = name; FullName = parent.FullName + Constants.SeparatorChar + Name; + NativePath = SmbContentProvider.GetNativePath(FullName); Provider = provider; _parent = parent; diff --git a/src/Providers/FileTime.Providers.Smb/SmbFolder.cs b/src/Providers/FileTime.Providers.Smb/SmbFolder.cs index f61ce72..0d5e272 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbFolder.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbFolder.cs @@ -1,8 +1,6 @@ using AsyncEvent; using FileTime.Core.Models; using FileTime.Core.Providers; -using SMBLibrary; -using SMBLibrary.Client; namespace FileTime.Providers.Smb { @@ -17,6 +15,7 @@ namespace FileTime.Providers.Smb public string Name { get; } public string? FullName { get; } + public string? NativePath { get; } public bool IsHidden => false; public bool IsLoaded => _items != null; @@ -40,6 +39,7 @@ namespace FileTime.Providers.Smb Name = name; FullName = parent?.FullName == null ? Name : parent.FullName + Constants.SeparatorChar + Name; + NativePath = SmbContentProvider.GetNativePath(FullName); Provider = contentProvider; } diff --git a/src/Providers/FileTime.Providers.Smb/SmbServer.cs b/src/Providers/FileTime.Providers.Smb/SmbServer.cs index 692f323..bd816ab 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbServer.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbServer.cs @@ -24,8 +24,8 @@ namespace FileTime.Providers.Smb public string? Password { get; private set; } public string Name { get; } - public string? FullName { get; } + public string? NativePath { get; } public bool IsHidden => false; public bool IsLoaded => _items != null; @@ -51,7 +51,7 @@ namespace FileTime.Providers.Smb Password = password; Provider = contentProvider; - FullName = Name = path; + NativePath = FullName = Name = path; } public async Task?> GetItems(CancellationToken token = default) diff --git a/src/Providers/FileTime.Providers.Smb/SmbShare.cs b/src/Providers/FileTime.Providers.Smb/SmbShare.cs index a1e9fdb..b63d25a 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbShare.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbShare.cs @@ -17,6 +17,7 @@ namespace FileTime.Providers.Smb public string Name { get; } public string? FullName { get; } + public string? NativePath { get; } public bool IsHidden => false; public bool IsLoaded => _items != null; @@ -40,6 +41,7 @@ namespace FileTime.Providers.Smb Name = name; FullName = parent?.FullName == null ? Name : parent.FullName + Constants.SeparatorChar + Name; + NativePath = SmbContentProvider.GetNativePath(FullName); Provider = contentProvider; }