diff --git a/Akari.Prototype.Client/Akari.Prototype.Client.csproj b/Akari.Prototype.Client/Akari.Prototype.Client.csproj
index 7d17bab..a5a9bd5 100644
--- a/Akari.Prototype.Client/Akari.Prototype.Client.csproj
+++ b/Akari.Prototype.Client/Akari.Prototype.Client.csproj
@@ -5,9 +5,12 @@
enable
-
-
-
+
+
+
+
+
+
diff --git a/Akari.Prototype.Client/MainWindow.axaml b/Akari.Prototype.Client/MainWindow.axaml
index 0b9e8b6..0e18d8a 100644
--- a/Akari.Prototype.Client/MainWindow.axaml
+++ b/Akari.Prototype.Client/MainWindow.axaml
@@ -4,6 +4,76 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Akari.Prototype.Client.MainWindow"
- Title="Akari.Prototype.Client">
- Welcome to Avalonia!
+ Title="Akari.Prototype.Client"
+ Width="600"
+ Height="350"
+ ExtendClientAreaToDecorationsHint="True"
+ TransparencyLevelHint="AcrylicBlur"
+ ExtendClientAreaTitleBarHeightHint="-1"
+ Background="{x:Null}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Encrypt
+ Decrypt
+
+
+
+
+
+
+
+
diff --git a/Akari.Prototype.Client/MainWindow.axaml.cs b/Akari.Prototype.Client/MainWindow.axaml.cs
index 8a3826e..1c167f7 100644
--- a/Akari.Prototype.Client/MainWindow.axaml.cs
+++ b/Akari.Prototype.Client/MainWindow.axaml.cs
@@ -1,22 +1,134 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Akari.Prototype.Shared.Protos;
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
+using Google.Protobuf;
+using Grpc.Net.Client;
+using MessageBox.Avalonia;
namespace Akari.Prototype.Client
{
- public partial class MainWindow : Window
+ public partial class MainWindow : Window, IDisposable
{
+ public const string Hostname = "https://localhost:5001";
+
+ private readonly GrpcChannel _channel;
+
+ private string? _file = null;
+
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
+
+ _channel = GrpcChannel.ForAddress(Hostname);
}
- private void InitializeComponent()
+ private async void OnPickFile(object sender, RoutedEventArgs e)
{
- AvaloniaXamlLoader.Load(this);
+ var mode = GetMode();
+
+ var dialog = new OpenFileDialog()
+ {
+ AllowMultiple = false,
+ Title = $"Pick a file to {mode}"
+ };
+
+ if (await dialog.ShowAsync(this) is string[] { Length: 1 } res)
+ {
+ _file = res[0];
+ TxtFile.Text = Path.GetFileName(_file);
+ }
+ }
+
+ private async void OnSubmit(object sender, RoutedEventArgs e)
+ {
+ if (_file is null)
+ {
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(BoxName.Text))
+ {
+ await MessageBoxManager.GetMessageBoxStandardWindow("Error", $"Invalid application name", icon: MessageBox.Avalonia.Enums.Icon.Error).Show();
+
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(BoxToken.Text))
+ {
+ await MessageBoxManager.GetMessageBoxStandardWindow("Error", $"Invalid token", icon: MessageBox.Avalonia.Enums.Icon.Error).Show();
+
+ return;
+ }
+
+ var client = new AkariApi.AkariApiClient(_channel);
+
+ // Decrypt
+ if (GetMode() == Mode.Decrypt)
+ {
+ var response = await client.DecryptAsync(new DecryptRequest()
+ {
+ Application = BoxName.Text,
+ Token = BoxToken.Text,
+ Encrypted = ByteString.CopyFrom(File.ReadAllBytes(_file))
+ });
+
+ if (response.ResponseCase == DecryptResponse.ResponseOneofCase.ErrorMessage)
+ {
+ await MessageBoxManager.GetMessageBoxStandardWindow("Error", $"Error during decryption, server response: {response.ErrorMessage}", icon: MessageBox.Avalonia.Enums.Icon.Error).Show();
+ }
+ else
+ {
+ string outPath = Path.ChangeExtension(_file, null);
+
+ File.WriteAllBytes(outPath, response.Plain.ToByteArray());
+
+ await MessageBoxManager.GetMessageBoxStandardWindow("Success", $"Saved decrypted file to {outPath}\n").Show();
+
+ }
+ }
+ // Encrypt
+ else
+ {
+ var response = await client.EncryptAsync(new EncryptRequest()
+ {
+ Application = BoxName.Text,
+ Token = BoxToken.Text,
+ Plain = ByteString.CopyFrom(File.ReadAllBytes(_file))
+ });
+
+ if (response.ResponseCase == EncryptResponse.ResponseOneofCase.ErrorMessage)
+ {
+ await MessageBoxManager.GetMessageBoxStandardWindow("Error", $"Error during encryption, server response: {response.ErrorMessage}", icon: MessageBox.Avalonia.Enums.Icon.Error).Show();
+ }
+ else
+ {
+ string outPath = $"{_file}.enc";
+
+ File.WriteAllBytes(outPath, response.Encrypted.ToByteArray());
+
+ await MessageBoxManager.GetMessageBoxStandardWindow("Success", $"Saved encrypted file to {outPath}").Show();
+ }
+ }
+ }
+
+ private Mode GetMode()
+ {
+ if (CbxMode.SelectedItem is ComboBoxItem { Content: string mode })
+ {
+ return Enum.Parse(mode);
+ }
+
+ throw new Exception("Invalid mode in CbxMode");
+ }
+
+ public void Dispose()
+ {
+ _channel.Dispose();
}
}
}
diff --git a/Akari.Prototype.Client/Mode.cs b/Akari.Prototype.Client/Mode.cs
new file mode 100644
index 0000000..9cbc6ac
--- /dev/null
+++ b/Akari.Prototype.Client/Mode.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Akari.Prototype.Client
+{
+ enum Mode
+ {
+ Encrypt,
+ Decrypt
+ }
+}