Go to location, Warnings
This commit is contained in:
@@ -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; }
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace FileTime.Core.Timeline
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
UpdateReadOnlyCommands();
|
await UpdateReadOnlyCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task TryStartCommandRunner()
|
public async Task TryStartCommandRunner()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -692,13 +718,13 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
{
|
{
|
||||||
var waiting = true;
|
var waiting = true;
|
||||||
var result = new string[0];
|
var result = new string[0];
|
||||||
ReadInputs(fields.ToList(), () =>
|
ReadInputs(fields.ToList(), () =>
|
||||||
{
|
{
|
||||||
if(Inputs != null)
|
if (Inputs != null)
|
||||||
{
|
{
|
||||||
result = Inputs.Select(i => i.Value).ToArray();
|
result = Inputs.Select(i => i.Value).ToArray();
|
||||||
}
|
}
|
||||||
waiting = false;
|
waiting = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
while (waiting) await Task.Delay(100);
|
while (waiting) await Task.Delay(100);
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user