Editor command
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace FileTime.App.Core.Configuration;
|
||||
|
||||
public class ProgramsConfigurationRoot
|
||||
{
|
||||
public ProgramsConfiguration Linux { get; set; } = new();
|
||||
public ProgramsConfiguration Windows { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using FileTime.App.Core.Configuration;
|
||||
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public interface IProgramsService
|
||||
{
|
||||
ProgramConfiguration? GetEditorProgram(bool getNext = false);
|
||||
void ResetLastGoodEditor();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace FileTime.App.Core.UserCommand;
|
||||
|
||||
public class EditCommand : IIdentifiableUserCommand
|
||||
{
|
||||
public const string CommandName = "edit";
|
||||
public static readonly EditCommand Instance = new();
|
||||
|
||||
private EditCommand()
|
||||
{
|
||||
}
|
||||
|
||||
public string UserCommandID => CommandName;
|
||||
public string Title => "Edit";
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace FileTime.App.Core.Configuration;
|
||||
|
||||
public class MainConfiguration
|
||||
{
|
||||
private static readonly Lazy<List<CommandBindingConfiguration>> _defaultKeybindings = new(InitDefaultKeyBindings);
|
||||
private static readonly Lazy<List<CommandBindingConfiguration>> DefaultKeybindings = new(InitDefaultKeyBindings);
|
||||
|
||||
public static Dictionary<string, string?> Configuration { get; }
|
||||
|
||||
@@ -18,7 +18,7 @@ public class MainConfiguration
|
||||
};
|
||||
|
||||
PopulateDefaultEditorPrograms(Configuration);
|
||||
PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value,
|
||||
PopulateDefaultKeyBindings(Configuration, DefaultKeybindings.Value,
|
||||
SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings));
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class MainConfiguration
|
||||
new(CreateContainer.CommandName, new[] {Keys.C, Keys.C}),
|
||||
new(CreateElementCommand.CommandName, new[] {Keys.C, Keys.E}),
|
||||
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Keys.D, Keys.D }),
|
||||
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Keys.F4)),
|
||||
new(EditCommand.CommandName, new[] {Keys.F4}),
|
||||
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Comma, shift: true)),
|
||||
new(EnterRapidTravelCommand.CommandName, new KeyConfig(Keys.Question, shift: true)),
|
||||
new(GoBackCommand.CommandName, new KeyConfig(Keys.Left, alt: true)),
|
||||
@@ -120,23 +120,35 @@ public class MainConfiguration
|
||||
|
||||
private static void PopulateDefaultEditorPrograms(Dictionary<string, string?> configuration)
|
||||
{
|
||||
var editorPrograms = new List<ProgramConfiguration>()
|
||||
var linuxEditorPrograms = new List<ProgramConfiguration>
|
||||
{
|
||||
new(@"gedit"),
|
||||
};
|
||||
var windowsEditorPrograms = new List<ProgramConfiguration>
|
||||
{
|
||||
new(@"c:\Program Files\Notepad++\notepad++.exe"),
|
||||
new("notepad.exe"),
|
||||
};
|
||||
|
||||
PopulateDefaultEditorPrograms(configuration, linuxEditorPrograms, nameof(ProgramsConfigurationRoot.Linux));
|
||||
PopulateDefaultEditorPrograms(configuration, windowsEditorPrograms, nameof(ProgramsConfigurationRoot.Windows));
|
||||
}
|
||||
|
||||
private static void PopulateDefaultEditorPrograms(
|
||||
Dictionary<string, string?> configuration,
|
||||
List<ProgramConfiguration> editorPrograms,
|
||||
string os)
|
||||
{
|
||||
for (var i = 0; i < editorPrograms.Count; i++)
|
||||
{
|
||||
if (editorPrograms[i].Path is not { } path) continue;
|
||||
configuration.Add(
|
||||
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
|
||||
$"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}",
|
||||
path);
|
||||
|
||||
if (editorPrograms[i].Arguments is { } arguments)
|
||||
{
|
||||
configuration.Add(
|
||||
$"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",
|
||||
$"{SectionNames.ProgramsSectionName}:{os}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}",
|
||||
arguments);
|
||||
}
|
||||
}
|
||||
|
||||
91
src/AppCommon/FileTime.App.Core/Services/ProgramsService.cs
Normal file
91
src/AppCommon/FileTime.App.Core/Services/ProgramsService.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using FileTime.App.Core.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace FileTime.App.Core.Services;
|
||||
|
||||
public class ProgramsService : IProgramsService
|
||||
{
|
||||
private enum Os
|
||||
{
|
||||
Linux,
|
||||
Windows,
|
||||
}
|
||||
|
||||
private readonly Os _os;
|
||||
private readonly IOptionsMonitor<ProgramsConfigurationRoot> _configuration;
|
||||
private int _lastGoodEditorProgramIndex;
|
||||
private readonly List<ProgramConfiguration> _lastEditorPrograms = new();
|
||||
|
||||
public ProgramsService(IOptionsMonitor<ProgramsConfigurationRoot> configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
_os = Os.Windows;
|
||||
}
|
||||
else
|
||||
{
|
||||
_os = Os.Linux;
|
||||
}
|
||||
}
|
||||
|
||||
public ProgramConfiguration? GetEditorProgram(bool getNext = false)
|
||||
{
|
||||
GeneratePrograms();
|
||||
|
||||
if (getNext)
|
||||
{
|
||||
_lastGoodEditorProgramIndex++;
|
||||
}
|
||||
|
||||
if (_lastGoodEditorProgramIndex < 0)
|
||||
{
|
||||
_lastGoodEditorProgramIndex = 0;
|
||||
}
|
||||
|
||||
if (_lastEditorPrograms.Count <= _lastGoodEditorProgramIndex)
|
||||
{
|
||||
ResetLastGoodEditor();
|
||||
return null;
|
||||
}
|
||||
|
||||
return _lastEditorPrograms[_lastGoodEditorProgramIndex];
|
||||
}
|
||||
|
||||
private void GeneratePrograms()
|
||||
{
|
||||
var programsConfig = _os switch
|
||||
{
|
||||
Os.Windows => _configuration.CurrentValue.Windows,
|
||||
_ => _configuration.CurrentValue.Linux
|
||||
};
|
||||
var programConfigs = programsConfig.EditorPrograms.Count == 0
|
||||
? programsConfig.DefaultEditorPrograms
|
||||
: programsConfig.EditorPrograms.Concat(programsConfig.DefaultEditorPrograms).ToList();
|
||||
|
||||
var generateNew = programConfigs.Count != _lastEditorPrograms.Count;
|
||||
|
||||
if (!generateNew)
|
||||
{
|
||||
for (var i = 0; i < programConfigs.Count; i++)
|
||||
{
|
||||
if (programConfigs[i].Path != _lastEditorPrograms[i].Path
|
||||
|| programConfigs[i].Arguments != _lastEditorPrograms[i].Arguments)
|
||||
{
|
||||
generateNew = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (generateNew)
|
||||
{
|
||||
_lastEditorPrograms.Clear();
|
||||
_lastEditorPrograms.AddRange(programConfigs);
|
||||
_lastGoodEditorProgramIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetLastGoodEditor() => _lastGoodEditorProgramIndex = -1;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using FileTime.Core.Enums;
|
||||
using FileTime.Core.Interactions;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FileTime.App.Core.Services.UserCommandHandler;
|
||||
|
||||
@@ -22,6 +23,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
||||
private readonly IUserCommandHandlerService _userCommandHandlerService;
|
||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
||||
private readonly IContainerSizeScanProvider _containerSizeScanProvider;
|
||||
private readonly IProgramsService _programsService;
|
||||
private readonly ILogger<ToolUserCommandHandlerService> _logger;
|
||||
private IDeclarativeProperty<IContainer?>? _currentLocation;
|
||||
private IDeclarativeProperty<IItemViewModel?>? _currentSelectedItem;
|
||||
private ITabViewModel? _currentSelectedTab;
|
||||
@@ -35,7 +38,9 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
||||
ITimelessContentProvider timelessContentProvider,
|
||||
IUserCommandHandlerService userCommandHandlerService,
|
||||
IContentAccessorFactory contentAccessorFactory,
|
||||
IContainerSizeScanProvider containerSizeScanProvider) : base(appState)
|
||||
IContainerSizeScanProvider containerSizeScanProvider,
|
||||
IProgramsService programsService,
|
||||
ILogger<ToolUserCommandHandlerService> logger) : base(appState)
|
||||
{
|
||||
_systemClipboardService = systemClipboardService;
|
||||
_userCommunicationService = userCommunicationService;
|
||||
@@ -45,6 +50,8 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
||||
_userCommandHandlerService = userCommandHandlerService;
|
||||
_contentAccessorFactory = contentAccessorFactory;
|
||||
_containerSizeScanProvider = containerSizeScanProvider;
|
||||
_programsService = programsService;
|
||||
_logger = logger;
|
||||
SaveCurrentLocation(l => _currentLocation = l);
|
||||
SaveCurrentSelectedItem(i => _currentSelectedItem = i);
|
||||
SaveSelectedTab(t => _currentSelectedTab = t);
|
||||
@@ -54,16 +61,68 @@ public class ToolUserCommandHandlerService : UserCommandHandlerServiceBase
|
||||
new TypeUserCommandHandler<OpenInDefaultFileExplorerCommand>(OpenInDefaultFileExplorer),
|
||||
new TypeUserCommandHandler<CopyNativePathCommand>(CopyNativePath),
|
||||
new TypeUserCommandHandler<CopyBase64Command>(CopyBase64),
|
||||
new TypeUserCommandHandler<EditCommand>(Edit),
|
||||
new TypeUserCommandHandler<SearchCommand>(Search),
|
||||
new TypeUserCommandHandler<ScanSizeCommand>(ScanSize),
|
||||
new TypeUserCommandHandler<SortItemsCommand>(SortItems),
|
||||
});
|
||||
}
|
||||
|
||||
private Task Edit()
|
||||
{
|
||||
if ( _currentSelectedTab?.CurrentSelectedItem.Value?.BaseItem is not IElement {NativePath: { } filePath})
|
||||
return Task.CompletedTask;
|
||||
|
||||
var getNext = false;
|
||||
while (true)
|
||||
{
|
||||
string? execPath = null;
|
||||
try
|
||||
{
|
||||
var editorProgram = _programsService.GetEditorProgram(getNext);
|
||||
if (editorProgram is null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (editorProgram.Path is { } executablePath)
|
||||
{
|
||||
execPath = 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. {ExecutablePath}", execPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Unknown error while running editor program");
|
||||
}
|
||||
|
||||
getNext = true;
|
||||
}
|
||||
|
||||
//TODO: else
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task ScanSize()
|
||||
{
|
||||
if (_currentLocation?.Value is null) return;
|
||||
|
||||
|
||||
var searchTask = _containerSizeScanProvider.StartSizeScan(_currentLocation.Value);
|
||||
var openContainerCommand = new OpenContainerCommand(new AbsolutePath(_timelessContentProvider, searchTask.SizeSizeScanContainer));
|
||||
await _userCommandHandlerService.HandleCommandAsync(openContainerCommand);
|
||||
|
||||
@@ -36,6 +36,7 @@ public static class Startup
|
||||
serviceCollection.TryAddSingleton<ICommandKeysHelperService, CommandKeysHelperService>();
|
||||
serviceCollection.TryAddSingleton<IPossibleCommandsService, PossibleCommandsService>();
|
||||
serviceCollection.TryAddSingleton<IPossibleCommandsViewModel, PossibleCommandsViewModel>();
|
||||
serviceCollection.TryAddSingleton<IProgramsService, ProgramsService>();
|
||||
|
||||
return serviceCollection
|
||||
.AddCommandHandlers()
|
||||
@@ -53,7 +54,7 @@ public static class Startup
|
||||
|
||||
internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection, IConfigurationRoot configuration) =>
|
||||
serviceCollection
|
||||
.Configure<ProgramsConfiguration>(configuration.GetSection(SectionNames.ProgramsSectionName))
|
||||
.Configure<ProgramsConfigurationRoot>(configuration.GetSection(SectionNames.ProgramsSectionName))
|
||||
.Configure<KeyBindingConfiguration>(configuration.GetSection(SectionNames.KeybindingSectionName))
|
||||
.AddSingleton<IConfiguration>(configuration);
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
|
||||
AddUserCommand(CreateElementCommand.Instance);
|
||||
AddUserCommand(DeleteCommand.HardDelete);
|
||||
AddUserCommand(DeleteCommand.SoftDelete);
|
||||
AddUserCommand(EditCommand.Instance);
|
||||
AddUserCommand(EnterRapidTravelCommand.Instance);
|
||||
AddUserCommand(ExitRapidTravelCommand.Instance);
|
||||
AddUserCommand(GoBackCommand.Instance);
|
||||
|
||||
Reference in New Issue
Block a user