Hash functions
This commit is contained in:
@@ -8,12 +8,14 @@ namespace FileTime.App.Core.Command
|
|||||||
ChangeTimelineMode,
|
ChangeTimelineMode,
|
||||||
CloseTab,
|
CloseTab,
|
||||||
Copy,
|
Copy,
|
||||||
|
CopyHash,
|
||||||
CopyPath,
|
CopyPath,
|
||||||
CreateContainer,
|
CreateContainer,
|
||||||
CreateElement,
|
CreateElement,
|
||||||
Cut,
|
Cut,
|
||||||
Edit,
|
Edit,
|
||||||
EnterRapidTravel,
|
EnterRapidTravel,
|
||||||
|
GetHash,
|
||||||
GoToHome,
|
GoToHome,
|
||||||
GoToPath,
|
GoToPath,
|
||||||
GoToProvider,
|
GoToProvider,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace FileTime.ConsoleUI.App.UI
|
|||||||
foreach (var input in fields)
|
foreach (var input in fields)
|
||||||
{
|
{
|
||||||
_application.MoveToIOLine();
|
_application.MoveToIOLine();
|
||||||
_coloredConsoleRenderer.Write(input.Text + ": ");
|
_coloredConsoleRenderer.Write(input.Label + ": ");
|
||||||
|
|
||||||
results.Add(await _consoleReader.ReadText(placeHolder: input.InputType == InputType.Password ? '*' : null));
|
results.Add(await _consoleReader.ReadText(placeHolder: input.InputType == InputType.Password ? '*' : null));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,38 @@ namespace FileTime.Core.Interactions
|
|||||||
{
|
{
|
||||||
public class InputElement
|
public class InputElement
|
||||||
{
|
{
|
||||||
public string Text { get; }
|
public string Label { get; }
|
||||||
public InputType InputType { get; }
|
public InputType InputType { get; }
|
||||||
public string? DefaultValue { get; }
|
public string? DefaultValue { get; }
|
||||||
|
public List<object>? Options { get; }
|
||||||
|
|
||||||
public InputElement(string text, InputType inputType, string? defaultValue = null)
|
protected InputElement(string text, InputType inputType, string? defaultValue = null)
|
||||||
{
|
{
|
||||||
Text = text;
|
Label = text;
|
||||||
InputType = inputType;
|
InputType = inputType;
|
||||||
DefaultValue = defaultValue;
|
DefaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected InputElement(string text, InputType inputType, List<object> defaultValue)
|
||||||
|
{
|
||||||
|
Label = text;
|
||||||
|
InputType = inputType;
|
||||||
|
Options = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputElement ForText(string label, string? defaultValue = null)
|
||||||
|
{
|
||||||
|
return new InputElement(label, InputType.Text, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputElement ForPassword(string label, string? defaultValue = null)
|
||||||
|
{
|
||||||
|
return new InputElement(label, InputType.Password, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputElement ForOptions(string label, List<object> defaultValue)
|
||||||
|
{
|
||||||
|
return new InputElement(label, InputType.Options, defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,8 @@ namespace FileTime.Core.Interactions
|
|||||||
{
|
{
|
||||||
public enum InputType
|
public enum InputType
|
||||||
{
|
{
|
||||||
Text,
|
Options,
|
||||||
Password,
|
Password,
|
||||||
Bool
|
Text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
61
src/Core/FileTime.Core/Providers/ContentProviderStream.cs
Normal file
61
src/Core/FileTime.Core/Providers/ContentProviderStream.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace FileTime.Core.Providers
|
||||||
|
{
|
||||||
|
public class ContentProviderStream : Stream
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly IContentReader? _contentReader;
|
||||||
|
private readonly IContentWriter? _contentWriter;
|
||||||
|
public override bool CanRead => _contentReader == null;
|
||||||
|
|
||||||
|
public override bool CanSeek => false;
|
||||||
|
|
||||||
|
public override bool CanWrite => _contentWriter == null;
|
||||||
|
|
||||||
|
public override long Length => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||||
|
|
||||||
|
public ContentProviderStream(IContentReader contentReader)
|
||||||
|
{
|
||||||
|
_contentReader = contentReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentProviderStream(IContentWriter contentWriter)
|
||||||
|
{
|
||||||
|
_contentWriter = contentWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (_contentReader == null) throw new IOException("This stream is not readable");
|
||||||
|
var dataTask = Task.Run(async () => await _contentReader.ReadBytesAsync(count, offset));
|
||||||
|
dataTask.Wait();
|
||||||
|
var data = dataTask.Result;
|
||||||
|
|
||||||
|
if (data.Length > count) throw new Exception("More bytes has been read than requested");
|
||||||
|
Array.Copy(data, buffer, data.Length);
|
||||||
|
return data.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,6 @@ namespace FileTime.Core.Providers
|
|||||||
{
|
{
|
||||||
int PreferredBufferSize { get; }
|
int PreferredBufferSize { get; }
|
||||||
|
|
||||||
Task<byte[]> ReadBytesAsync(int bufferSize);
|
Task<byte[]> ReadBytesAsync(int bufferSize, int? offset = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using FileTime.Core.Command;
|
using FileTime.Core.Command;
|
||||||
|
|
||||||
namespace FileTime.Core.Timeline
|
namespace FileTime.Core.Timeline
|
||||||
@@ -12,7 +13,7 @@ namespace FileTime.Core.Timeline
|
|||||||
public CommandTimeState(ICommand command, PointInTime? startTime)
|
public CommandTimeState(ICommand command, PointInTime? startTime)
|
||||||
{
|
{
|
||||||
Command = command;
|
Command = command;
|
||||||
UpdateState(startTime).Wait();
|
Task.Run(async () => await UpdateState(startTime)).Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateState(PointInTime? startPoint)
|
public async Task UpdateState(PointInTime? startPoint)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using AsyncEvent;
|
using AsyncEvent;
|
||||||
using FileTime.Core.Command;
|
using FileTime.Core.Command;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
@@ -136,7 +137,7 @@ namespace FileTime.Core.Timeline
|
|||||||
if (arg is CommandTimeState commandToRun2)
|
if (arg is CommandTimeState commandToRun2)
|
||||||
{
|
{
|
||||||
commandToRun = commandToRun2;
|
commandToRun = commandToRun2;
|
||||||
_commandExecutor.ExecuteCommandAsync(commandToRun.Command, this).Wait();
|
Task.Run(async () => await _commandExecutor.ExecuteCommandAsync(commandToRun.Command, this)).Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -150,7 +151,7 @@ namespace FileTime.Core.Timeline
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DisposeCommandThread(Thread.CurrentThread, commandToRun).Wait();
|
Task.Run(async () => await DisposeCommandThread(Thread.CurrentThread, commandToRun)).Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +239,6 @@ namespace FileTime.Core.Timeline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunWithLock(Action action) => RunWithLockAsync(action).Wait();
|
private void RunWithLock(Action action) => Task.Run(async () => await RunWithLockAsync(action)).Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,5 +202,25 @@
|
|||||||
<Style Selector="Border.SelectedTimelineCommand">
|
<Style Selector="Border.SelectedTimelineCommand">
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource ForegroundBrush}"/>
|
<Setter Property="BorderBrush" Value="{DynamicResource ForegroundBrush}"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ListBox.RadioButtonListBox">
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="ListBox.RadioButtonListBox ListBoxItem">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate>
|
||||||
|
<Border>
|
||||||
|
<RadioButton
|
||||||
|
Content="{TemplateBinding ContentPresenter.Content}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"
|
||||||
|
Foreground="{DynamicResource ForegroundBrush}"/>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
</Application>
|
</Application>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace FileTime.Avalonia.Application
|
|||||||
{*/
|
{*/
|
||||||
/*var task = SetSelectedItemAsync(value, true);
|
/*var task = SetSelectedItemAsync(value, true);
|
||||||
Task.WaitAll(new Task[] { task }, 100);*/
|
Task.WaitAll(new Task[] { task }, 100);*/
|
||||||
SetSelectedItemAsync(value, true);
|
Task.Run(async () => await SetSelectedItemAsync(value, true)).Wait();
|
||||||
/*}
|
/*}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace FileTime.Avalonia.Configuration
|
|||||||
new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }),
|
new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }),
|
||||||
new CommandBindingConfiguration(Commands.CloseTab, Key.Q),
|
new CommandBindingConfiguration(Commands.CloseTab, Key.Q),
|
||||||
new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }),
|
new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }),
|
||||||
|
new CommandBindingConfiguration(Commands.CopyHash, new[] { Key.C, Key.H }),
|
||||||
new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }),
|
new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }),
|
||||||
new CommandBindingConfiguration(Commands.CreateContainer, Key.F7),
|
new CommandBindingConfiguration(Commands.CreateContainer, Key.F7),
|
||||||
new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }),
|
new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }),
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace FileTime.Avalonia.Misc
|
|||||||
|
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
public object? Option { get; set; }
|
||||||
|
|
||||||
public char? PasswordChar { get; set; }
|
public char? PasswordChar { get; set; }
|
||||||
|
|
||||||
public InputElementWrapper(InputElement inputElement, string? defaultValue = null)
|
public InputElementWrapper(InputElement inputElement, string? defaultValue = null)
|
||||||
|
|||||||
10
src/GuiApp/FileTime.Avalonia/Models/HashFunction.cs
Normal file
10
src/GuiApp/FileTime.Avalonia/Models/HashFunction.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace FileTime.Avalonia.Models
|
||||||
|
{
|
||||||
|
public enum HashFunction
|
||||||
|
{
|
||||||
|
MD5,
|
||||||
|
SHA256,
|
||||||
|
SHA384,
|
||||||
|
SHA512,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,14 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FileTime.App.Core.Clipboard;
|
using FileTime.App.Core.Clipboard;
|
||||||
using FileTime.App.Core.Command;
|
using FileTime.App.Core.Command;
|
||||||
using FileTime.Avalonia.Application;
|
using FileTime.Avalonia.Application;
|
||||||
using FileTime.Avalonia.IconProviders;
|
using FileTime.Avalonia.IconProviders;
|
||||||
using FileTime.Avalonia.Misc;
|
using FileTime.Avalonia.Misc;
|
||||||
|
using FileTime.Avalonia.Models;
|
||||||
using FileTime.Avalonia.ViewModels;
|
using FileTime.Avalonia.ViewModels;
|
||||||
using FileTime.Core.Command;
|
using FileTime.Core.Command;
|
||||||
using FileTime.Core.Components;
|
using FileTime.Core.Components;
|
||||||
@@ -65,6 +67,7 @@ namespace FileTime.Avalonia.Services
|
|||||||
{Commands.ChangeTimelineMode, ChangeTimelineMode},
|
{Commands.ChangeTimelineMode, ChangeTimelineMode},
|
||||||
{Commands.CloseTab, CloseTab},
|
{Commands.CloseTab, CloseTab},
|
||||||
{Commands.Copy, Copy},
|
{Commands.Copy, Copy},
|
||||||
|
{Commands.CopyHash, CopyHash},
|
||||||
{Commands.CopyPath, CopyPath},
|
{Commands.CopyPath, CopyPath},
|
||||||
{Commands.CreateContainer, CreateContainer},
|
{Commands.CreateContainer, CreateContainer},
|
||||||
{Commands.CreateElement, CreateElement},
|
{Commands.CreateElement, CreateElement},
|
||||||
@@ -276,13 +279,13 @@ namespace FileTime.Avalonia.Services
|
|||||||
var createContainerCommand = new CreateContainerCommand(new AbsolutePath(container), containerName);
|
var createContainerCommand = new CreateContainerCommand(new AbsolutePath(container), containerName);
|
||||||
await AddCommand(createContainerCommand);
|
await AddCommand(createContainerCommand);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.LogError(e, "Error while creating container {Container}", containerName);
|
_logger.LogError(e, "Error while creating container {Container}", containerName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Container name", InputType.Text) }, handler);
|
_dialogService.ReadInputs(new List<InputElement>() { InputElement.ForText("Container name") }, handler);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -299,13 +302,13 @@ namespace FileTime.Avalonia.Services
|
|||||||
var createElementCommand = new CreateElementCommand(new AbsolutePath(container), elementName);
|
var createElementCommand = new CreateElementCommand(new AbsolutePath(container), elementName);
|
||||||
await AddCommand(createElementCommand);
|
await AddCommand(createElementCommand);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.LogError(e, "Error while creating element {Element}", elementName);
|
_logger.LogError(e, "Error while creating element {Element}", elementName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Element name", InputType.Text) }, handler);
|
_dialogService.ReadInputs(new List<InputElement>() { InputElement.ForText("Element name") }, handler);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -487,7 +490,7 @@ namespace FileTime.Avalonia.Services
|
|||||||
await AddCommand(renameCommand);
|
await AddCommand(renameCommand);
|
||||||
};
|
};
|
||||||
|
|
||||||
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("New name", InputType.Text, selectedItem.Name) }, handler);
|
_dialogService.ReadInputs(new List<InputElement>() { InputElement.ForText("New name", selectedItem.Name) }, handler);
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -543,7 +546,7 @@ namespace FileTime.Avalonia.Services
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Path", InputType.Text) }, handler);
|
_dialogService.ReadInputs(new List<InputElement>() { InputElement.ForText("Path") }, handler);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -580,9 +583,17 @@ namespace FileTime.Avalonia.Services
|
|||||||
var currentContainer = _appState.SelectedTab.CurrentLocation.Container;
|
var currentContainer = _appState.SelectedTab.CurrentLocation.Container;
|
||||||
var textToCopy = currentContainer.NativePath;
|
var textToCopy = currentContainer.NativePath;
|
||||||
|
|
||||||
if (textToCopy != null && global::Avalonia.Application.Current?.Clipboard is global::Avalonia.Input.Platform.IClipboard clipboard)
|
if (textToCopy != null)
|
||||||
{
|
{
|
||||||
await clipboard.SetTextAsync(textToCopy);
|
await CopyToClipboard(textToCopy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task CopyToClipboard(string text)
|
||||||
|
{
|
||||||
|
if (global::Avalonia.Application.Current?.Clipboard is global::Avalonia.Input.Platform.IClipboard clipboard)
|
||||||
|
{
|
||||||
|
await clipboard.SetTextAsync(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +644,7 @@ namespace FileTime.Avalonia.Services
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
_dialogService.ReadInputs(new List<InputElement>() { new InputElement("Command", InputType.Text) }, handler);
|
_dialogService.ReadInputs(new List<InputElement>() { InputElement.ForText("Command") }, handler);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -840,5 +851,40 @@ namespace FileTime.Avalonia.Services
|
|||||||
//TODO: else
|
//TODO: else
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task CopyHash()
|
||||||
|
{
|
||||||
|
var handler = async (List<InputElementWrapper> inputs) =>
|
||||||
|
{
|
||||||
|
var hashFunction = (HashFunction?)inputs[0].Option;
|
||||||
|
if (hashFunction != null && _appState.SelectedTab.SelectedItem?.Item is IElement element && element.Provider.SupportsContentStreams)
|
||||||
|
{
|
||||||
|
using var stream = new ContentProviderStream(await element.GetContentReaderAsync());
|
||||||
|
|
||||||
|
string? hashString = null;
|
||||||
|
using HashAlgorithm hashFunc = hashFunction switch
|
||||||
|
{
|
||||||
|
HashFunction.MD5 => MD5.Create(),
|
||||||
|
HashFunction.SHA256 => SHA256.Create(),
|
||||||
|
HashFunction.SHA384 => SHA384.Create(),
|
||||||
|
HashFunction.SHA512 => SHA512.Create(),
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
|
||||||
|
var hash = hashFunc.ComputeHash(stream);
|
||||||
|
hashString = string.Concat(hash.Select(b => b.ToString("X2")));
|
||||||
|
|
||||||
|
_dialogService.ShowToastMessage($"Hash copied ({hashString})");
|
||||||
|
await CopyToClipboard(hashString);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_dialogService.ReadInputs(new List<InputElement>()
|
||||||
|
{
|
||||||
|
InputElement.ForOptions("Hash function", Enum.GetValues<HashFunction>().Cast<object>().ToList())
|
||||||
|
}, handler);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:vm="using:FileTime.Avalonia.ViewModels"
|
xmlns:vm="using:FileTime.Avalonia.ViewModels"
|
||||||
|
xmlns:interactions="using:FileTime.Core.Interactions"
|
||||||
xmlns:local="using:FileTime.Avalonia.Views"
|
xmlns:local="using:FileTime.Avalonia.Views"
|
||||||
xmlns:models="using:FileTime.Avalonia.Models"
|
xmlns:models="using:FileTime.Avalonia.Models"
|
||||||
Title="FileTime"
|
Title="FileTime"
|
||||||
@@ -470,20 +471,35 @@
|
|||||||
Items="{Binding AppState.Inputs}">
|
Items="{Binding AppState.Inputs}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid MinWidth="500" ColumnDefinitions="250,*" Margin="10,5">
|
<Grid MinWidth="500" ColumnDefinitions="250,*" Margin="10,5" x:Name="ItemRoot">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Top"
|
||||||
Text="{Binding InputElement.Text}" />
|
Text="{Binding InputElement.Label}" />
|
||||||
|
<Grid Grid.Column="1">
|
||||||
<TextBox
|
<TextBox
|
||||||
PasswordChar="{Binding PasswordChar}"
|
IsVisible="{Binding InputElement.InputType, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Text}}"
|
||||||
AttachedToVisualTree="InputText_AttachedToVisualTree"
|
AttachedToVisualTree="InputText_AttachedToVisualTree"
|
||||||
IsTabStop="True"
|
|
||||||
Grid.Column="1"
|
|
||||||
GotFocus="InputText_GotFocus"
|
GotFocus="InputText_GotFocus"
|
||||||
LostFocus="InputText_LostFocus"
|
LostFocus="InputText_LostFocus"
|
||||||
KeyDown="InputText_KeyDown"
|
KeyDown="InputText_KeyDown"
|
||||||
|
VerticalAlignment="Top"
|
||||||
Text="{Binding Value, Mode=TwoWay}" />
|
Text="{Binding Value, Mode=TwoWay}" />
|
||||||
|
<TextBox
|
||||||
|
IsVisible="{Binding InputElement.InputType, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Password}}"
|
||||||
|
PasswordChar="{Binding PasswordChar}"
|
||||||
|
AttachedToVisualTree="InputText_AttachedToVisualTree"
|
||||||
|
GotFocus="InputText_GotFocus"
|
||||||
|
LostFocus="InputText_LostFocus"
|
||||||
|
KeyDown="InputText_KeyDown"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Text="{Binding Value, Mode=TwoWay}" />
|
||||||
|
<ListBox
|
||||||
|
Classes="RadioButtonListBox"
|
||||||
|
IsVisible="{Binding InputElement.InputType, Converter={StaticResource EqualityConverter}, ConverterParameter={x:Static interactions:InputType.Options}}"
|
||||||
|
Items="{Binding InputElement.Options}"
|
||||||
|
SelectedItem="{Binding Option}"/>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
using FileTime.Core.Providers;
|
using FileTime.Core.Providers;
|
||||||
|
|
||||||
namespace FileTime.Providers.Local
|
namespace FileTime.Providers.Local
|
||||||
@@ -9,6 +10,7 @@ namespace FileTime.Providers.Local
|
|||||||
private bool disposed;
|
private bool disposed;
|
||||||
|
|
||||||
public int PreferredBufferSize => 1024 * 1024;
|
public int PreferredBufferSize => 1024 * 1024;
|
||||||
|
private long? _bytesRead;
|
||||||
|
|
||||||
public LocalContentReader(FileStream readerStream)
|
public LocalContentReader(FileStream readerStream)
|
||||||
{
|
{
|
||||||
@@ -16,12 +18,28 @@ namespace FileTime.Providers.Local
|
|||||||
_binaryReader = new BinaryReader(_readerStream);
|
_binaryReader = new BinaryReader(_readerStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> ReadBytesAsync(int bufferSize)
|
public Task<byte[]> ReadBytesAsync(int bufferSize, int? offset = null)
|
||||||
{
|
{
|
||||||
var max = bufferSize > 0 && bufferSize < PreferredBufferSize ? bufferSize : PreferredBufferSize;
|
var max = bufferSize > 0 && bufferSize < PreferredBufferSize ? bufferSize : PreferredBufferSize;
|
||||||
|
|
||||||
|
if (offset != null)
|
||||||
|
{
|
||||||
|
if (_bytesRead == null) _bytesRead = 0;
|
||||||
|
var buffer = new byte[max];
|
||||||
|
var bytesRead = _binaryReader.Read(buffer, offset.Value, max);
|
||||||
|
_bytesRead += bytesRead;
|
||||||
|
|
||||||
|
if (buffer.Length != bytesRead)
|
||||||
|
{
|
||||||
|
Array.Resize(ref buffer, bytesRead);
|
||||||
|
}
|
||||||
|
return Task.FromResult(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return Task.FromResult(_binaryReader.ReadBytes(max));
|
return Task.FromResult(_binaryReader.ReadBytes(max));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~LocalContentReader()
|
~LocalContentReader()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ namespace FileTime.Providers.Smb
|
|||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<byte[]> ReadBytesAsync(int bufferSize)
|
public Task<byte[]> ReadBytesAsync(int bufferSize, int? offset = null)
|
||||||
{
|
{
|
||||||
var max = bufferSize > 0 && bufferSize < (int)_client.MaxReadSize ? bufferSize : (int)_client.MaxReadSize;
|
var max = bufferSize > 0 && bufferSize < (int)_client.MaxReadSize ? bufferSize : (int)_client.MaxReadSize;
|
||||||
|
|
||||||
var status = _smbFileStore.ReadFile(out byte[] data, _fileHandle, _bytesRead, max);
|
var status = _smbFileStore.ReadFile(out byte[] data, _fileHandle, offset ?? _bytesRead, max);
|
||||||
if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.STATUS_END_OF_FILE)
|
if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.STATUS_END_OF_FILE)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to read from file");
|
throw new Exception("Failed to read from file");
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ namespace FileTime.Providers.Smb
|
|||||||
var inputs = await _inputInterface.ReadInputs(
|
var inputs = await _inputInterface.ReadInputs(
|
||||||
new InputElement[]
|
new InputElement[]
|
||||||
{
|
{
|
||||||
new InputElement($"Username for '{Name}'", InputType.Text, Username ?? ""),
|
InputElement.ForText($"Username for '{Name}'", Username ?? ""),
|
||||||
new InputElement($"Password for '{Name}'", InputType.Password, Password ?? "")
|
InputElement.ForPassword($"Password for '{Name}'", Password ?? "")
|
||||||
});
|
});
|
||||||
|
|
||||||
Username = inputs[0];
|
Username = inputs[0];
|
||||||
|
|||||||
Reference in New Issue
Block a user