Go to location, Warnings

This commit is contained in:
2022-02-01 13:32:38 +01:00
parent 9824184d90
commit 45ec3ae0b3
10 changed files with 72 additions and 34 deletions

View File

@@ -9,7 +9,7 @@ namespace FileTime.Core.Command
private Func<IContainer, string, Task<IContainer>>? _createContainer; private Func<IContainer, string, Task<IContainer>>? _createContainer;
private TimeRunner? _timeRunner; private TimeRunner? _timeRunner;
public IList<AbsolutePath>? Sources { get; } = new List<AbsolutePath>(); public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>();
public IContainer? Target { get; set; } public IContainer? Target { get; set; }

View File

@@ -4,7 +4,7 @@ namespace FileTime.Core.Command
{ {
public interface ITransportationCommand : ICommand public interface ITransportationCommand : ICommand
{ {
IList<AbsolutePath>? Sources { get; } IList<AbsolutePath> Sources { get; }
IContainer? Target { get; set;} IContainer? Target { get; set;}
TransportMode? TransportMode { get; set; } TransportMode? TransportMode { get; set; }
} }

View File

@@ -5,7 +5,7 @@ namespace FileTime.Core.Command
{ {
public class MoveCommand : ITransportationCommand public class MoveCommand : ITransportationCommand
{ {
public IList<AbsolutePath>? Sources { get; } = new List<AbsolutePath>(); public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>();
public IContainer? Target { get; set; } public IContainer? Target { get; set; }
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;

View File

@@ -6,7 +6,9 @@ namespace FileTime.Core.Components
public class Tab public class Tab
{ {
private IItem? _currentSelectedItem; private IItem? _currentSelectedItem;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private IContainer _currentLocation; private IContainer _currentLocation;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
private string? _lastPath; private string? _lastPath;
public int CurrentSelectedIndex { get; private set; } public int CurrentSelectedIndex { get; private set; }

View File

@@ -12,14 +12,18 @@ namespace FileTime.Core.Providers
private readonly IReadOnlyList<IItem>? _items; private readonly IReadOnlyList<IItem>? _items;
private readonly IReadOnlyList<IElement>? _elements = new List<IElement>().AsReadOnly(); private readonly IReadOnlyList<IElement>? _elements = new List<IElement>().AsReadOnly();
#pragma warning disable CS8603 // Possible null reference return.
public string Name => null; public string Name => null;
#pragma warning restore CS8603 // Possible null reference return.
public string? FullName => null; public string? FullName => null;
public bool IsHidden => false; public bool IsHidden => false;
public bool IsLoaded => true; public bool IsLoaded => true;
#pragma warning disable CS8603 // Possible null reference return.
public IContentProvider Provider => null; public IContentProvider Provider => null;
#pragma warning restore CS8603 // Possible null reference return.
public bool CanDelete => false; public bool CanDelete => false;
public bool CanRename => false; public bool CanRename => false;

View File

@@ -74,7 +74,7 @@ namespace FileTime.Core.Timeline
} }
}); });
UpdateReadOnlyCommands(); await UpdateReadOnlyCommands();
} }
public async Task TryStartCommandRunner() public async Task TryStartCommandRunner()

View File

@@ -13,7 +13,7 @@ namespace FileTime.Avalonia
{ {
public static IServiceProvider ServiceProvider { get; private set; } public static IServiceProvider ServiceProvider { get; private set; }
public App() static App()
{ {
ServiceProvider ??= DependencyInjection ServiceProvider ??= DependencyInjection
.RegisterDefaultServices() .RegisterDefaultServices()

View File

@@ -41,8 +41,8 @@ namespace FileTime.Avalonia.ViewModels
private IClipboard _clipboard; private IClipboard _clipboard;
private TimeRunner _timeRunner; private TimeRunner _timeRunner;
private IEnumerable<IContentProvider>? _contentProviders; private IEnumerable<IContentProvider> _contentProviders;
private Action? _inputHandler; private Func<Task>? _inputHandler;
[Property] [Property]
private string _text; private string _text;
@@ -68,7 +68,7 @@ namespace FileTime.Avalonia.ViewModels
{ {
_clipboard = App.ServiceProvider.GetService<IClipboard>()!; _clipboard = App.ServiceProvider.GetService<IClipboard>()!;
_timeRunner = App.ServiceProvider.GetService<TimeRunner>()!; _timeRunner = App.ServiceProvider.GetService<TimeRunner>()!;
_contentProviders = App.ServiceProvider.GetService<IEnumerable<IContentProvider>>(); _contentProviders = App.ServiceProvider.GetService<IEnumerable<IContentProvider>>()!;
var inputInterface = (BasicInputHandler)App.ServiceProvider.GetService<IInputInterface>()!; var inputInterface = (BasicInputHandler)App.ServiceProvider.GetService<IInputInterface>()!;
inputInterface.InputHandler = ReadInputs2; inputInterface.InputHandler = ReadInputs2;
App.ServiceProvider.GetService<TopContainer>(); App.ServiceProvider.GetService<TopContainer>();
@@ -107,12 +107,12 @@ namespace FileTime.Avalonia.ViewModels
RootDriveInfos = driveInfos.OrderBy(d => d.Name).ToList(); RootDriveInfos = driveInfos.OrderBy(d => d.Name).ToList();
} }
private async Task<IContainer> GetContainerForWindowsDrive(DriveInfo drive) private async Task<IContainer?> GetContainerForWindowsDrive(DriveInfo drive)
{ {
return (await LocalContentProvider.GetRootContainers()).FirstOrDefault(d => d.Name == drive.Name.TrimEnd(Path.DirectorySeparatorChar)); return (await LocalContentProvider.GetRootContainers()).FirstOrDefault(d => d.Name == drive.Name.TrimEnd(Path.DirectorySeparatorChar));
} }
private async Task<IContainer> GetContainerForLinuxDrive(DriveInfo drive) private async Task<IContainer?> GetContainerForLinuxDrive(DriveInfo drive)
{ {
return await LocalContentProvider.GetByPath(drive.Name) as IContainer; return await LocalContentProvider.GetByPath(drive.Name) as IContainer;
} }
@@ -274,13 +274,13 @@ namespace FileTime.Avalonia.ViewModels
public Task CreateContainer() public Task CreateContainer()
{ {
var handler = () => var handler = async () =>
{ {
if (Inputs != null) if (Inputs != null)
{ {
var container = AppState.SelectedTab.CurrentLocation.Container; var container = AppState.SelectedTab.CurrentLocation.Container;
var createContainerCommand = new CreateContainerCommand(new Core.Models.AbsolutePath(container), Inputs[0].Value); var createContainerCommand = new CreateContainerCommand(new Core.Models.AbsolutePath(container), Inputs[0].Value);
_timeRunner.AddCommand(createContainerCommand).Wait(); await _timeRunner.AddCommand(createContainerCommand);
Inputs = null; Inputs = null;
} }
}; };
@@ -292,13 +292,13 @@ namespace FileTime.Avalonia.ViewModels
public Task CreateElement() public Task CreateElement()
{ {
var handler = () => var handler = async () =>
{ {
if (Inputs != null) if (Inputs != null)
{ {
var container = AppState.SelectedTab.CurrentLocation.Container; var container = AppState.SelectedTab.CurrentLocation.Container;
var createElementCommand = new CreateElementCommand(new Core.Models.AbsolutePath(container), Inputs[0].Value); var createElementCommand = new CreateElementCommand(new Core.Models.AbsolutePath(container), Inputs[0].Value);
_timeRunner.AddCommand(createElementCommand).Wait(); await _timeRunner.AddCommand(createElementCommand);
Inputs = null; Inputs = null;
} }
}; };
@@ -346,7 +346,7 @@ namespace FileTime.Avalonia.ViewModels
public async Task Delete() public async Task Delete()
{ {
IList<Core.Models.AbsolutePath>? itemsToDelete = null; IList<AbsolutePath>? itemsToDelete = null;
var askForDelete = false; var askForDelete = false;
var questionText = ""; var questionText = "";
var shouldDelete = false; var shouldDelete = false;
@@ -403,11 +403,11 @@ namespace FileTime.Avalonia.ViewModels
} }
else if (shouldDelete) else if (shouldDelete)
{ {
HandleDelete(); await HandleDelete();
} }
} }
void HandleDelete() async Task HandleDelete()
{ {
var deleteCommand = new DeleteCommand(); var deleteCommand = new DeleteCommand();
@@ -416,7 +416,7 @@ namespace FileTime.Avalonia.ViewModels
deleteCommand.ItemsToDelete.Add(itemToDelete); deleteCommand.ItemsToDelete.Add(itemToDelete);
} }
_timeRunner.AddCommand(deleteCommand).Wait(); await _timeRunner.AddCommand(deleteCommand);
_clipboard.Clear(); _clipboard.Clear();
} }
} }
@@ -465,12 +465,12 @@ namespace FileTime.Avalonia.ViewModels
var selectedItem = AppState.SelectedTab.SelectedItem?.Item; var selectedItem = AppState.SelectedTab.SelectedItem?.Item;
if (selectedItem != null) if (selectedItem != null)
{ {
var handler = () => var handler = async () =>
{ {
if (Inputs != null) if (Inputs != null)
{ {
var renameCommand = new RenameCommand(new Core.Models.AbsolutePath(selectedItem), Inputs[0].Value); var renameCommand = new RenameCommand(new Core.Models.AbsolutePath(selectedItem), Inputs[0].Value);
_timeRunner.AddCommand(renameCommand).Wait(); await _timeRunner.AddCommand(renameCommand);
} }
}; };
@@ -502,23 +502,45 @@ namespace FileTime.Avalonia.ViewModels
await _timeRunner.Refresh(); await _timeRunner.Refresh();
} }
private async Task GoToContainer() private Task GoToContainer()
{ {
var handler = () => var handler = async () =>
{ {
if (Inputs != null) if (Inputs != null)
{ {
var path = Inputs[0].Value;
foreach (var contentProvider in _contentProviders)
{
if (contentProvider.CanHandlePath(path))
{
var possibleContainer = await contentProvider.GetByPath(path);
if (possibleContainer is IContainer container)
{
AppState.SelectedTab.OpenContainer(container).Wait();
}
//TODO: multiple possible content provider handler
return;
}
}
} }
}; };
ReadInputs(new List<Core.Interactions.InputElement>() { new Core.Interactions.InputElement("Path", InputType.Text) }, handler); ReadInputs(new List<Core.Interactions.InputElement>() { new Core.Interactions.InputElement("Path", InputType.Text) }, handler);
return Task.CompletedTask;
} }
[Command] [Command]
public void ProcessInputs() public async void ProcessInputs()
{ {
_inputHandler?.Invoke(); try
{
if (_inputHandler != null)
{
await _inputHandler.Invoke();
}
}
catch { }
Inputs = null; Inputs = null;
_inputHandler = null; _inputHandler = null;
@@ -683,6 +705,10 @@ namespace FileTime.Avalonia.ViewModels
} }
private void ReadInputs(List<Core.Interactions.InputElement> inputs, Action inputHandler) private void ReadInputs(List<Core.Interactions.InputElement> inputs, Action inputHandler)
{
ReadInputs(inputs, () => { inputHandler(); return Task.CompletedTask; });
}
private void ReadInputs(List<Core.Interactions.InputElement> inputs, Func<Task> inputHandler)
{ {
Inputs = inputs.Select(i => new InputElementWrapper(i, i.DefaultValue)).ToList(); Inputs = inputs.Select(i => new InputElementWrapper(i, i.DefaultValue)).ToList();
_inputHandler = inputHandler; _inputHandler = inputHandler;
@@ -706,7 +732,7 @@ namespace FileTime.Avalonia.ViewModels
return result; return result;
} }
private void ShowMessageBox(string text, Action inputHandler) private void ShowMessageBox(string text, Func<Task> inputHandler)
{ {
MessageBoxText = text; MessageBoxText = text;
_inputHandler = inputHandler; _inputHandler = inputHandler;

View File

@@ -42,7 +42,7 @@ namespace FileTime.Avalonia.Views
{ {
if (_inputElementWrapper == null) if (_inputElementWrapper == null)
{ {
e.Handled = e.Handled || await ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers); e.Handled = e.Handled || await ViewModel!.ProcessKeyDown(e.Key, e.KeyModifiers);
} }
} }
@@ -50,7 +50,7 @@ namespace FileTime.Avalonia.Views
{ {
if (_inputElementWrapper == null) if (_inputElementWrapper == null)
{ {
e.Handled = e.Handled || await ViewModel?.ProcessKeyUp(e.Key, e.KeyModifiers); e.Handled = e.Handled || await ViewModel!.ProcessKeyUp(e.Key, e.KeyModifiers);
} }
} }

View File

@@ -48,11 +48,13 @@ namespace FileTime.Providers.Local
public async Task<IItem?> GetByPath(string path) public async Task<IItem?> GetByPath(string path)
{ {
path = path.Replace(Path.DirectorySeparatorChar, Constants.SeparatorChar).TrimEnd(Constants.SeparatorChar);
var pathParts = (IsCaseInsensitive ? path.ToLower() : path).TrimStart(Constants.SeparatorChar).Split(Constants.SeparatorChar); var pathParts = (IsCaseInsensitive ? path.ToLower() : path).TrimStart(Constants.SeparatorChar).Split(Constants.SeparatorChar);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && pathParts.Length == 1 && pathParts[0] == "") return this; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && pathParts.Length == 1 && pathParts[0] == "") return this;
var rootContainer = _rootContainers.FirstOrDefault(c => NormalizePath(c.Name) == NormalizePath(pathParts[0])); var normalizedRootContainerName = NormalizePath(pathParts[0]);
var rootContainer = _rootContainers.FirstOrDefault(c => NormalizePath(c.Name) == normalizedRootContainerName);
if (rootContainer == null) if (rootContainer == null)
{ {
@@ -77,7 +79,11 @@ namespace FileTime.Providers.Local
internal string NormalizePath(string path) => IsCaseInsensitive ? path.ToLower() : path; internal string NormalizePath(string path) => IsCaseInsensitive ? path.ToLower() : path;
public bool CanHandlePath(string path) => _rootContainers.Any(r => path.StartsWith(r.Name)); public bool CanHandlePath(string path)
{
var normalizedPath = NormalizePath(path);
return _rootContainers.Any(r => normalizedPath.StartsWith(NormalizePath(r.Name)));
}
public void SetParent(IContainer container) => _parent = container; public void SetParent(IContainer container) => _parent = container;
public Task<IReadOnlyList<IContainer>> GetRootContainers(CancellationToken token = default) => Task.FromResult(_rootContainers); public Task<IReadOnlyList<IContainer>> GetRootContainers(CancellationToken token = default) => Task.FromResult(_rootContainers);