From c253d00ff174d757632b2dfceadb2f90afb68a0a Mon Sep 17 00:00:00 2001 From: BlossomiShymae <87099578+BlossomiShymae@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:50:19 -0500 Subject: [PATCH] Refactor request viewmodels --- .../Messages/ContentRequestMessage.cs | 8 -- .../Messages/EditorUpdateMessage.cs | 20 --- .../ViewModels/Pages/ConsoleViewModel.cs | 65 +--------- .../Pages/Endpoints/EndpointViewModel.cs | 4 +- .../Pages/Endpoints/PathOperationViewModel.cs | 115 ++++-------------- .../ViewModels/Shared/LcuRequestViewModel.cs | 112 +++++++++++++++++ Needlework.Net/Views/Pages/ConsoleView.axaml | 8 +- .../Views/Pages/ConsoleView.axaml.cs | 33 ++--- Needlework.Net/Views/Pages/EndpointView.axaml | 16 +-- .../Views/Pages/EndpointView.axaml.cs | 64 ++++++---- 10 files changed, 213 insertions(+), 232 deletions(-) delete mode 100644 Needlework.Net/Messages/ContentRequestMessage.cs delete mode 100644 Needlework.Net/Messages/EditorUpdateMessage.cs create mode 100644 Needlework.Net/ViewModels/Shared/LcuRequestViewModel.cs diff --git a/Needlework.Net/Messages/ContentRequestMessage.cs b/Needlework.Net/Messages/ContentRequestMessage.cs deleted file mode 100644 index 0031f88..0000000 --- a/Needlework.Net/Messages/ContentRequestMessage.cs +++ /dev/null @@ -1,8 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; - -namespace Needlework.Net.Messages -{ - public class ContentRequestMessage : RequestMessage - { - } -} diff --git a/Needlework.Net/Messages/EditorUpdateMessage.cs b/Needlework.Net/Messages/EditorUpdateMessage.cs deleted file mode 100644 index d0e81b6..0000000 --- a/Needlework.Net/Messages/EditorUpdateMessage.cs +++ /dev/null @@ -1,20 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; - -namespace Needlework.Net.Messages -{ - public class EditorUpdateMessage(EditorUpdate editorUpdate) : ValueChangedMessage(editorUpdate) - { - } - - public class EditorUpdate - { - public string Text { get; } - public string Key { get; } - - public EditorUpdate(string text, string key) - { - Text = text; - Key = key; - } - } -} diff --git a/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs b/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs index 90d5984..f3be89c 100644 --- a/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs @@ -1,13 +1,9 @@ using Avalonia.Collections; -using BlossomiShymae.GrrrLCU; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using Needlework.Net.Messages; -using Needlework.Net.ViewModels.MainWindow; -using System; -using System.Net.Http; -using System.Text.Json; +using Needlework.Net.ViewModels.Shared; using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages; @@ -18,13 +14,7 @@ public partial class ConsoleViewModel : PageBase, IRecipient public IAvaloniaList RequestPaths { get; } = new AvaloniaList(); [ObservableProperty] private bool _isBusy = true; - [ObservableProperty] private bool _isRequestBusy = false; - [ObservableProperty] private string? _requestMethodSelected = "GET"; - [ObservableProperty] private string? _requestPath = null; - [ObservableProperty] private string? _requestBody = null; - [ObservableProperty] private string? _responsePath = null; - [ObservableProperty] private string? _responseStatus = null; - [ObservableProperty] private string? _responseAuthorization = null; + [ObservableProperty] private LcuRequestViewModel _lcuRequest = new(); public ConsoleViewModel() : base("Console", "terminal", -200) { @@ -34,56 +24,7 @@ public partial class ConsoleViewModel : PageBase, IRecipient [RelayCommand] private async Task SendRequest() { - try - { - IsRequestBusy = true; - if (string.IsNullOrEmpty(RequestPath)) throw new Exception("Path is empty."); - - var method = RequestMethodSelected switch - { - "GET" => HttpMethod.Get, - "POST" => HttpMethod.Post, - "PUT" => HttpMethod.Put, - "DELETE" => HttpMethod.Delete, - "HEAD" => HttpMethod.Head, - "PATCH" => HttpMethod.Patch, - "OPTIONS" => HttpMethod.Options, - "TRACE" => HttpMethod.Trace, - _ => throw new Exception("Method is not selected."), - }; - - var processInfo = ProcessFinder.Get(); - var requestBody = WeakReferenceMessenger.Default.Send(new ContentRequestMessage(), "ConsoleRequestEditor").Response; - var content = new StringContent(requestBody, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); - var client = Connector.GetLcuHttpClientInstance(); - var response = await client.SendAsync(new(method, RequestPath) { Content = content }); - var riotAuthentication = new RiotAuthentication(processInfo.RemotingAuthToken); - var responseBody = await response.Content.ReadAsByteArrayAsync(); - - var body = responseBody.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBody), App.JsonSerializerOptions) : string.Empty; - if (body.Length >= App.MaxCharacters) - { - WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(body)); - WeakReferenceMessenger.Default.Send(new ResponseUpdatedMessage(string.Empty), nameof(ConsoleViewModel)); - } - else WeakReferenceMessenger.Default.Send(new ResponseUpdatedMessage(body), nameof(ConsoleViewModel)); - - ResponseStatus = $"{(int)response.StatusCode} {response.StatusCode.ToString()}"; - ResponsePath = $"https://127.0.0.1:{processInfo.AppPort}{RequestPath}"; - ResponseAuthorization = $"Basic {riotAuthentication.Value}"; - } - catch (Exception ex) - { - WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new InfoBarViewModel("Request Failed", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(5)))); - ResponseStatus = null; - ResponsePath = null; - ResponseAuthorization = null; - WeakReferenceMessenger.Default.Send(new ResponseUpdatedMessage(string.Empty), nameof(ConsoleViewModel)); - } - finally - { - IsRequestBusy = false; - } + await LcuRequest.ExecuteAsync(); } public void Receive(DataReadyMessage message) diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs index 7de549c..713ebdb 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs @@ -19,6 +19,8 @@ public partial class EndpointViewModel : ObservableObject [ObservableProperty] private string? _search; public IAvaloniaList FilteredPathOperations { get; } + public event EventHandler? PathOperationSelected; + public EndpointViewModel(string endpoint) { Endpoint = endpoint; @@ -43,6 +45,6 @@ public partial class EndpointViewModel : ObservableObject partial void OnSelectedPathOperationChanged(PathOperationViewModel? value) { if (value == null) return; - WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(value.Operation.RequestTemplate ?? string.Empty, "EndpointRequestEditor"))); + PathOperationSelected?.Invoke(this, value.Operation.RequestTemplate ?? string.Empty); } } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs index 92f6293..726828a 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs @@ -1,121 +1,52 @@ -using Avalonia.Media; -using BlossomiShymae.GrrrLCU; -using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.Messaging; -using Needlework.Net.Messages; using Needlework.Net.Models; -using Needlework.Net.ViewModels.MainWindow; +using Needlework.Net.ViewModels.Shared; using System; -using System.Net.Http; using System.Text; -using System.Text.Json; using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages.Endpoints; public partial class PathOperationViewModel : ObservableObject { - public string Method { get; } - public SolidColorBrush Color { get; } public string Path { get; } public OperationViewModel Operation { get; } - public ProcessInfo? ProcessInfo { get; } - [ObservableProperty] private bool _isBusy; - - [ObservableProperty] private Lazy _response; + [ObservableProperty] private Lazy _lcuRequest; public PathOperationViewModel(PathOperation pathOperation) { - Method = pathOperation.Method.ToUpper(); - Color = new SolidColorBrush(GetColor(Method)); Path = pathOperation.Path; Operation = new OperationViewModel(pathOperation.Operation); - Response = new(() => new ResponseViewModel(pathOperation.Path)); + LcuRequest = new(() => new LcuRequestViewModel() + { + Method = pathOperation.Method.ToUpper() + }); } [RelayCommand] - public async Task SendRequest() + private async Task SendRequest() { - try + var sb = new StringBuilder(Path); + foreach (var pathParameter in Operation.PathParameters) { - IsBusy = true; - - var method = Method switch - { - "GET" => HttpMethod.Get, - "POST" => HttpMethod.Post, - "PUT" => HttpMethod.Put, - "DELETE" => HttpMethod.Delete, - "HEAD" => HttpMethod.Head, - "PATCH" => HttpMethod.Patch, - "OPTIONS" => HttpMethod.Options, - "TRACE" => HttpMethod.Trace, - _ => throw new Exception("Method is missing.") - }; - - var processInfo = ProcessFinder.Get(); - var sb = new StringBuilder(Path); - foreach (var pathParameter in Operation.PathParameters) - { - sb.Replace($"{{{pathParameter.Name}}}", pathParameter.Value); - } - - var firstQueryAdded = false; - foreach (var queryParameter in Operation.QueryParameters) - { - if (!string.IsNullOrWhiteSpace(queryParameter.Value)) - { - sb.Append(firstQueryAdded ? '&' : '?'); - firstQueryAdded = true; - sb.Append($"{queryParameter.Name}={Uri.EscapeDataString(queryParameter.Value)}"); - } - } - var uri = sb.ToString(); - - var requestBody = WeakReferenceMessenger.Default.Send(new ContentRequestMessage(), "EndpointRequestEditor").Response; - var content = new StringContent(requestBody, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); - - var client = Connector.GetLcuHttpClientInstance(); - var response = await client.SendAsync(new(method, uri) { Content = content }); - var riotAuthentication = new RiotAuthentication(processInfo.RemotingAuthToken); - var responseBytes = await response.Content.ReadAsByteArrayAsync(); - - var responseBody = responseBytes.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBytes), App.JsonSerializerOptions) : string.Empty; - if (responseBody.Length >= App.MaxCharacters) - { - WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(responseBody)); - WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(string.Empty, "EndpointResponseEditor"))); - } - else WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(responseBody, "EndpointResponseEditor"))); - - Response.Value.Status = $"{(int)response.StatusCode} {response.StatusCode}"; - Response.Value.Path = $"https://127.0.0.1:{processInfo.AppPort}{uri}"; - Response.Value.Authentication = Response.Value.Authorization = $"Basic {riotAuthentication.Value}"; - Response.Value.Username = riotAuthentication.Username; - Response.Value.Password = riotAuthentication.Password; + sb.Replace($"{{{pathParameter.Name}}}", pathParameter.Value); } - catch (Exception ex) + + var firstQueryAdded = false; + foreach (var queryParameter in Operation.QueryParameters) { - WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new InfoBarViewModel("Request Failed", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(5)))); - WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(string.Empty, "EndpointResponseEditor"))); - } - finally - { - IsBusy = false; + if (!string.IsNullOrWhiteSpace(queryParameter.Value)) + { + sb.Append(firstQueryAdded ? '&' : '?'); + firstQueryAdded = true; + sb.Append($"{queryParameter.Name}={Uri.EscapeDataString(queryParameter.Value)}"); + } } + + LcuRequest.Value.RequestPath = sb.ToString(); + await LcuRequest.Value.ExecuteAsync(); } - - public static Color GetColor(string method) => method switch - { - "GET" => Avalonia.Media.Color.FromRgb(95, 99, 186), - "POST" => Avalonia.Media.Color.FromRgb(103, 186, 95), - "PUT" => Avalonia.Media.Color.FromRgb(186, 139, 95), - "DELETE" => Avalonia.Media.Color.FromRgb(186, 95, 95), - "HEAD" => Avalonia.Media.Color.FromRgb(136, 95, 186), - "PATCH" => Avalonia.Media.Color.FromRgb(95, 186, 139), - _ => throw new InvalidOperationException("Method does not have assigned color.") - }; } diff --git a/Needlework.Net/ViewModels/Shared/LcuRequestViewModel.cs b/Needlework.Net/ViewModels/Shared/LcuRequestViewModel.cs new file mode 100644 index 0000000..8c06292 --- /dev/null +++ b/Needlework.Net/ViewModels/Shared/LcuRequestViewModel.cs @@ -0,0 +1,112 @@ +using Avalonia.Media; +using BlossomiShymae.GrrrLCU; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Messaging; +using Needlework.Net.Messages; +using Needlework.Net.ViewModels.MainWindow; +using System; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; + +namespace Needlework.Net.ViewModels.Shared; + +public partial class LcuRequestViewModel : ObservableObject +{ + [ObservableProperty] private string? _method = "GET"; + [ObservableProperty] private SolidColorBrush _color = new(GetColor("GET")); + + [ObservableProperty] private bool _isRequestBusy = false; + [ObservableProperty] private string? _requestPath = null; + [ObservableProperty] private string? _requestBody = null; + + [ObservableProperty] private string? _responsePath = null; + [ObservableProperty] private string? _responseStatus = null; + [ObservableProperty] private string? _responseAuthentication = null; + [ObservableProperty] private string? _responseUsername = null; + [ObservableProperty] private string? _responsePassword = null; + [ObservableProperty] private string? _responseAuthorization = null; + + public event EventHandler? RequestText; + public event EventHandler? UpdateText; + + partial void OnMethodChanged(string? oldValue, string? newValue) + { + if (newValue == null) return; + + Color = new(GetColor(newValue)); + } + + public async Task ExecuteAsync() + { + try + { + IsRequestBusy = true; + if (string.IsNullOrEmpty(RequestPath)) + throw new Exception("Path is empty."); + + var method = Method switch + { + "GET" => HttpMethod.Get, + "POST" => HttpMethod.Post, + "PUT" => HttpMethod.Put, + "DELETE" => HttpMethod.Delete, + "HEAD" => HttpMethod.Head, + "PATCH" => HttpMethod.Patch, + "OPTIONS" => HttpMethod.Options, + "TRACE" => HttpMethod.Trace, + _ => throw new Exception("Method is not selected or missing."), + }; + + var processInfo = ProcessFinder.Get(); + RequestText?.Invoke(this, this); + var content = new StringContent(RequestBody ?? string.Empty, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); + var client = Connector.GetLcuHttpClientInstance(); + var response = await client.SendAsync(new(method, RequestPath) { Content = content }); + var riotAuthentication = new RiotAuthentication(processInfo.RemotingAuthToken); + var responseBody = await response.Content.ReadAsByteArrayAsync(); + + var body = responseBody.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBody), App.JsonSerializerOptions) : string.Empty; + if (body.Length >= App.MaxCharacters) + { + WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(body)); + UpdateText?.Invoke(this, string.Empty); + } + UpdateText?.Invoke(this, body); + + ResponseStatus = $"{(int)response.StatusCode} {response.StatusCode.ToString()}"; + ResponsePath = $"https://127.0.0.1:{processInfo.AppPort}{RequestPath}"; + ResponseAuthentication = riotAuthentication.Value; + ResponseAuthorization = $"Basic {riotAuthentication.Value}"; + ResponseUsername = riotAuthentication.Username; + ResponsePassword = riotAuthentication.Password; + } + catch (Exception ex) + { + WeakReferenceMessenger.Default.Send(new InfoBarUpdateMessage(new InfoBarViewModel("Request Failed", true, ex.Message, FluentAvalonia.UI.Controls.InfoBarSeverity.Error, TimeSpan.FromSeconds(5)))); + UpdateText?.Invoke(this, string.Empty); + + ResponseStatus = null; + ResponsePath = null; + ResponseAuthentication = null; + ResponseAuthorization = null; + ResponseUsername = null; + ResponsePassword = null; + } + finally + { + IsRequestBusy = false; + } + } + + private static Color GetColor(string method) => method switch + { + "GET" => Avalonia.Media.Color.FromRgb(95, 99, 186), + "POST" => Avalonia.Media.Color.FromRgb(103, 186, 95), + "PUT" => Avalonia.Media.Color.FromRgb(186, 139, 95), + "DELETE" => Avalonia.Media.Color.FromRgb(186, 95, 95), + "HEAD" => Avalonia.Media.Color.FromRgb(136, 95, 186), + "PATCH" => Avalonia.Media.Color.FromRgb(95, 186, 139), + _ => throw new InvalidOperationException("Method does not have assigned color.") + }; +} diff --git a/Needlework.Net/Views/Pages/ConsoleView.axaml b/Needlework.Net/Views/Pages/ConsoleView.axaml index c8e9f09..3deac52 100644 --- a/Needlework.Net/Views/Pages/ConsoleView.axaml +++ b/Needlework.Net/Views/Pages/ConsoleView.axaml @@ -19,13 +19,13 @@ + Text="{Binding LcuRequest.ResponsePath}"/> -