feat: Add Game Client to Endpoints

This commit is contained in:
estrogen elf
2025-05-29 15:10:00 -05:00
parent c51f20a324
commit 1364cdc38c
15 changed files with 257 additions and 99 deletions

View File

@@ -43,7 +43,7 @@ namespace Needlework.Net
var lcuSchemaRaw = reader.Read(lcuSchemaStream, out var _);
_lcuSchemaDocument = new Document(lcuSchemaRaw);
var lolClientStream = await _httpClient.GetStreamAsync("https://raw.githubusercontent.com/BlossomiShymae/poroschema/refs/heads/main/schemas/lolclient.json");
var lolClientStream = await _httpClient.GetStreamAsync("https://raw.githubusercontent.com/AlsoSylv/Irelia/refs/heads/master/schemas/game_schema.json");
var lolClientRaw = reader.Read(lolClientStream, out var _);
_lolClientDocument = new Document(lolClientRaw);
}

View File

@@ -4,6 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Needlework.Net.ViewModels.Shared;
using System.Net.Http;
using System.Threading.Tasks;
namespace Needlework.Net.ViewModels.Pages;
@@ -14,19 +15,19 @@ public partial class ConsoleViewModel : PageBase
public IAvaloniaList<string> RequestPaths { get; } = new AvaloniaList<string>();
[ObservableProperty] private bool _isBusy = true;
[ObservableProperty] private LcuRequestViewModel _lcuRequest;
[ObservableProperty] private RequestViewModel _request;
private readonly DataSource _dataSource;
public ConsoleViewModel(ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, DataSource dataSource) : base("Console", "terminal", -200)
public ConsoleViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource, HttpClient httpClient) : base("Console", "terminal", -200)
{
_lcuRequest = new(lcuRequestViewModelLogger);
_request = new(requestViewModelLogger, Endpoints.Tab.LCU, httpClient);
_dataSource = dataSource;
}
public override async Task InitializeAsync()
{
var document = await _dataSource.GetLolClientDocumentAsync();
var document = await _dataSource.GetLcuSchemaDocumentAsync();
Dispatcher.UIThread.Invoke(() =>
{
RequestPaths.Clear();
@@ -39,6 +40,6 @@ public partial class ConsoleViewModel : PageBase
[RelayCommand]
private async Task SendRequest()
{
await LcuRequest.ExecuteAsync();
await Request.ExecuteAsync();
}
}

View File

@@ -21,10 +21,10 @@ public partial class EndpointViewModel : ObservableObject
public event EventHandler<string>? PathOperationSelected;
public EndpointViewModel(string endpoint, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, Models.Document lcuSchemaDocument)
public EndpointViewModel(string endpoint, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab, System.Net.Http.HttpClient httpClient)
{
Endpoint = endpoint;
PathOperations = new AvaloniaList<PathOperationViewModel>(lcuSchemaDocument.Plugins[endpoint].Select(x => new PathOperationViewModel(x, lcuRequestViewModelLogger, lcuSchemaDocument)));
PathOperations = new AvaloniaList<PathOperationViewModel>(document.Plugins[endpoint].Select(x => new PathOperationViewModel(x, requestViewModelLogger, document, tab, httpClient)));
FilteredPathOperations = new AvaloniaList<PathOperationViewModel>(PathOperations);
}

View File

@@ -13,14 +13,27 @@ public partial class EndpointsNavigationViewModel : ObservableObject
[ObservableProperty] private ObservableObject _activeViewModel;
[ObservableProperty] private ObservableObject _endpointsViewModel;
[ObservableProperty] private string _title = string.Empty;
[ObservableProperty] private string _title;
private readonly Action<string?, Guid> _onEndpointNavigation;
private readonly Tab _tab;
public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, Models.Document lcuSchemaDocument)
public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab, System.Net.Http.HttpClient httpClient)
{
_activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, lcuRequestViewModelLogger, lcuSchemaDocument);
_activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, requestViewModelLogger, document, tab, httpClient);
_onEndpointNavigation = onEndpointNavigation;
_tab = tab;
_title = GetTitle(tab);
}
private string GetTitle(Tab tab)
{
return tab switch
{
Tab.LCU => "LCU",
Tab.GameClient => "Game Client",
_ => string.Empty,
};
}
private void OnClicked(ObservableObject viewModel)
@@ -28,7 +41,7 @@ public partial class EndpointsNavigationViewModel : ObservableObject
ActiveViewModel = viewModel;
if (viewModel is EndpointViewModel endpoint)
{
Title = endpoint.Title;
Title = $"{GetTitle(_tab)} - {endpoint.Title}";
_onEndpointNavigation.Invoke(endpoint.Title, Guid);
}
}
@@ -37,7 +50,7 @@ public partial class EndpointsNavigationViewModel : ObservableObject
private void GoBack()
{
ActiveViewModel = EndpointsViewModel;
Title = string.Empty;
Title = GetTitle(_tab);
_onEndpointNavigation.Invoke(null, Guid);
}
}

View File

@@ -2,15 +2,22 @@
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.Logging;
using Needlework.Net.Models;
using Needlework.Net.ViewModels.Shared;
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace Needlework.Net.ViewModels.Pages.Endpoints;
public enum Tab
{
LCU,
GameClient
}
public partial class EndpointsTabViewModel : PageBase
{
public IAvaloniaList<string> Plugins { get; } = new AvaloniaList<string>();
@@ -18,32 +25,41 @@ public partial class EndpointsTabViewModel : PageBase
[ObservableProperty] private bool _isBusy = true;
private readonly ILogger<LcuRequestViewModel> _lcuRequestViewModelLogger;
private readonly ILogger<RequestViewModel> _requestViewModelLogger;
private readonly DataSource _dataSource;
private readonly HttpClient _httpClient;
public EndpointsTabViewModel(ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, DataSource dataSource) : base("Endpoints", "list-alt", -500)
public EndpointsTabViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource, HttpClient httpClient) : base("Endpoints", "list-alt", -500)
{
_lcuRequestViewModelLogger = lcuRequestViewModelLogger;
_requestViewModelLogger = requestViewModelLogger;
_dataSource = dataSource;
WeakReferenceMessenger.Default.RegisterAll(this);
_httpClient = httpClient;
}
public override async Task InitializeAsync()
{
var document = await _dataSource.GetLcuSchemaDocumentAsync();
Plugins.Clear();
Plugins.AddRange(document.Plugins.Keys);
await Dispatcher.UIThread.Invoke(AddEndpoint);
await Dispatcher.UIThread.Invoke(async () => await AddEndpoint(Tab.LCU));
IsBusy = false;
IsInitialized = true;
}
[RelayCommand]
private async Task AddEndpoint()
private async Task AddEndpoint(Tab tab)
{
var lcuSchemaDocument = await _dataSource.GetLcuSchemaDocumentAsync();
Document document = tab switch
{
Tab.LCU => await _dataSource.GetLcuSchemaDocumentAsync(),
Tab.GameClient => await _dataSource.GetLolClientDocumentAsync(),
_ => throw new NotImplementedException(),
};
Plugins.Clear();
Plugins.AddRange(document.Plugins.Keys);
var vm = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _requestViewModelLogger, document, tab, _httpClient);
Endpoints.Add(new()
{
Content = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _lcuRequestViewModelLogger, lcuSchemaDocument),
Content = vm,
Header = vm.Title,
Selected = true
});
}
@@ -54,7 +70,7 @@ public partial class EndpointsTabViewModel : PageBase
{
if (endpoint.Content.Guid.Equals(guid))
{
endpoint.Header = title ?? "Endpoints";
endpoint.Header = endpoint.Content.Title;
break;
}
}
@@ -63,7 +79,7 @@ public partial class EndpointsTabViewModel : PageBase
public partial class EndpointItem : ObservableObject
{
[ObservableProperty] private string _header = "Endpoints";
[ObservableProperty] private string _header = string.Empty;
public IconSource IconSource { get; set; } = new SymbolIconSource() { Symbol = Symbol.Document, FontSize = 20.0, Foreground = Avalonia.Media.Brushes.White };
public bool Selected { get; set; } = false;
public required EndpointsNavigationViewModel Content { get; init; }

View File

@@ -6,6 +6,7 @@ using Needlework.Net.Models;
using Needlework.Net.ViewModels.Shared;
using System;
using System.Linq;
using System.Net.Http;
namespace Needlework.Net.ViewModels.Pages.Endpoints;
@@ -19,16 +20,20 @@ public partial class EndpointsViewModel : ObservableObject
public Action<ObservableObject> OnClicked { get; }
private readonly ILogger<LcuRequestViewModel> _lcuRequestViewModelLogger;
private readonly Document _lcuSchemaDocument;
private readonly ILogger<RequestViewModel> _requestViewModelLogger;
private readonly Document _document;
private readonly Tab _tab;
private readonly HttpClient _httpClient;
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, Models.Document lcuSchemaDocument)
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab, System.Net.Http.HttpClient httpClient)
{
Plugins = new AvaloniaList<string>(plugins);
Query = new AvaloniaList<string>(plugins);
OnClicked = onClicked;
_lcuRequestViewModelLogger = lcuRequestViewModelLogger;
_lcuSchemaDocument = lcuSchemaDocument;
_requestViewModelLogger = requestViewModelLogger;
_document = document;
_tab = tab;
_httpClient = httpClient;
}
partial void OnSearchChanged(string value)
@@ -45,6 +50,6 @@ public partial class EndpointsViewModel : ObservableObject
{
if (string.IsNullOrEmpty(value)) return;
OnClicked.Invoke(new EndpointViewModel(value, _lcuRequestViewModelLogger, _lcuSchemaDocument));
OnClicked.Invoke(new EndpointViewModel(value, _requestViewModelLogger, _document, _tab, _httpClient));
}
}

View File

@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.OpenApi.Models;
using Needlework.Net.Models;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json;
@@ -21,23 +22,23 @@ public partial class OperationViewModel : ObservableObject
public IAvaloniaReadOnlyList<ParameterViewModel> QueryParameters { get; }
public string? RequestTemplate { get; }
public OperationViewModel(OpenApiOperation operation, Models.Document lcuSchemaDocument)
public OperationViewModel(OpenApiOperation operation, Models.Document document)
{
Summary = operation.Summary ?? string.Empty;
Description = operation.Description ?? string.Empty;
IsRequestBody = operation.RequestBody != null;
ReturnType = GetReturnType(operation.Responses);
RequestClasses = GetRequestClasses(operation.RequestBody, lcuSchemaDocument);
ResponseClasses = GetResponseClasses(operation.Responses, lcuSchemaDocument);
RequestClasses = GetRequestClasses(operation.RequestBody, document);
ResponseClasses = GetResponseClasses(operation.Responses, document);
PathParameters = GetParameters(operation.Parameters, ParameterLocation.Path);
QueryParameters = GetParameters(operation.Parameters, ParameterLocation.Query);
RequestBodyType = GetRequestBodyType(operation.RequestBody);
RequestTemplate = GetRequestTemplate(operation.RequestBody, lcuSchemaDocument);
RequestTemplate = GetRequestTemplate(operation.RequestBody, document);
}
private string? GetRequestTemplate(OpenApiRequestBody? requestBody, Document lcuSchemaDocument)
private string? GetRequestTemplate(OpenApiRequestBody? requestBody, Document document)
{
var requestClasses = GetRequestClasses(requestBody, lcuSchemaDocument);
var requestClasses = GetRequestClasses(requestBody, document);
if (requestClasses.Count == 0)
{
var type = GetRequestBodyType(requestBody);
@@ -132,17 +133,40 @@ public partial class OperationViewModel : ObservableObject
return pathParameters;
}
private AvaloniaList<PropertyClassViewModel> GetResponseClasses(OpenApiResponses responses, Document lcuSchemaDocument)
private bool TryGetResponse(OpenApiResponses responses, [NotNullWhen(true)] out OpenApiResponse? response)
{
if (responses.TryGetValue("2XX", out var response)
&& response.Content.TryGetValue("application/json", out var media))
response = null;
var flag = false;
if (responses.TryGetValue("2XX", out var x))
{
var document = lcuSchemaDocument.OpenApiDocument;
response = x;
flag = true;
}
else if (responses.TryGetValue("200", out var y))
{
response = y;
flag = true;
}
return flag;
}
private AvaloniaList<PropertyClassViewModel> GetResponseClasses(OpenApiResponses responses, Document document)
{
if (!TryGetResponse(responses, out var response))
return [];
if (response.Content.TryGetValue("application/json", out var media))
{
var rawDocument = document.OpenApiDocument;
var schema = media.Schema;
if (schema == null) return [];
AvaloniaList<PropertyClassViewModel> propertyClasses = [];
WalkSchema(schema, propertyClasses, document);
WalkSchema(schema, propertyClasses, rawDocument);
return propertyClasses;
}
return [];
}
@@ -185,12 +209,12 @@ public partial class OperationViewModel : ObservableObject
|| type.Contains("number"));
}
private AvaloniaList<PropertyClassViewModel> GetRequestClasses(OpenApiRequestBody? requestBody, Document lcuSchemaDocument)
private AvaloniaList<PropertyClassViewModel> GetRequestClasses(OpenApiRequestBody? requestBody, Document document)
{
if (requestBody == null) return [];
if (requestBody.Content.TryGetValue("application/json", out var media))
{
var document = lcuSchemaDocument.OpenApiDocument;
var rawDocument = document.OpenApiDocument;
var schema = media.Schema;
if (schema == null) return [];
@@ -198,9 +222,9 @@ public partial class OperationViewModel : ObservableObject
if (IsComponent(type))
{
var componentId = GetComponentId(schema);
var componentSchema = document.Components.Schemas[componentId];
var componentSchema = rawDocument.Components.Schemas[componentId];
AvaloniaList<PropertyClassViewModel> propertyClasses = [];
WalkSchema(componentSchema, propertyClasses, document);
WalkSchema(componentSchema, propertyClasses, rawDocument);
return propertyClasses;
}
}
@@ -209,12 +233,15 @@ public partial class OperationViewModel : ObservableObject
private string GetReturnType(OpenApiResponses responses)
{
if (responses.TryGetValue("2XX", out var response)
&& response.Content.TryGetValue("application/json", out var media))
if (!TryGetResponse(responses, out var response))
return "none";
if (response.Content.TryGetValue("application/json", out var media))
{
var schema = media.Schema;
return GetSchemaType(schema);
}
return "none";
}
@@ -223,6 +250,7 @@ public partial class OperationViewModel : ObservableObject
if (schema.Reference != null) return schema.Reference.Id;
if (schema.Type == "object" && schema.AdditionalProperties?.Reference != null) return schema.AdditionalProperties.Reference.Id;
if (schema.Type == "integer" || schema.Type == "number") return $"{schema.Type}:{schema.Format}";
if (schema.Type == "array" && schema.AdditionalProperties?.Reference != null) return schema.AdditionalProperties.Reference.Id;
if (schema.Type == "array" && schema.Items.Reference != null) return $"{schema.Items.Reference.Id}[]";
if (schema.Type == "array" && (schema.Items.Type == "integer" || schema.Items.Type == "number")) return $"{schema.Items.Type}:{schema.Items.Format}[]";
if (schema.Type == "array") return $"{schema.Items.Type}[]";

View File

@@ -17,13 +17,13 @@ public partial class PathOperationViewModel : ObservableObject
public string Url { get; }
[ObservableProperty] private bool _isBusy;
[ObservableProperty] private Lazy<LcuRequestViewModel> _lcuRequest;
[ObservableProperty] private Lazy<RequestViewModel> _request;
public PathOperationViewModel(PathOperation pathOperation, ILogger<LcuRequestViewModel> lcuRequestViewModelLogger, Document lcuSchemaDocument)
public PathOperationViewModel(PathOperation pathOperation, ILogger<RequestViewModel> requestViewModelLogger, Document document, Tab tab, System.Net.Http.HttpClient httpClient)
{
Path = pathOperation.Path;
Operation = new OperationViewModel(pathOperation.Operation, lcuSchemaDocument);
LcuRequest = new(() => new LcuRequestViewModel(lcuRequestViewModelLogger)
Operation = new OperationViewModel(pathOperation.Operation, document);
Request = new(() => new RequestViewModel(requestViewModelLogger, tab, httpClient)
{
Method = pathOperation.Method.ToUpper()
});
@@ -50,8 +50,8 @@ public partial class PathOperationViewModel : ObservableObject
}
}
LcuRequest.Value.RequestPath = sb.ToString();
await LcuRequest.Value.ExecuteAsync();
Request.Value.RequestPath = sb.ToString();
await Request.Value.ExecuteAsync();
}
[RelayCommand]

View File

@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using Needlework.Net.Messages;
using Needlework.Net.ViewModels.MainWindow;
using Needlework.Net.ViewModels.Pages.Endpoints;
using System;
using System.Net.Http;
using System.Text.Json;
@@ -12,7 +13,7 @@ using System.Threading.Tasks;
namespace Needlework.Net.ViewModels.Shared;
public partial class LcuRequestViewModel : ObservableObject
public partial class RequestViewModel : ObservableObject
{
[ObservableProperty] private string? _method = "GET";
[ObservableProperty] private SolidColorBrush _color = new(GetColor("GET"));
@@ -29,14 +30,18 @@ public partial class LcuRequestViewModel : ObservableObject
[ObservableProperty] private string? _responseAuthorization = null;
[ObservableProperty] private string? _responseBody = null;
public event EventHandler<LcuRequestViewModel>? RequestText;
public event EventHandler<RequestViewModel>? RequestText;
public event EventHandler<string>? UpdateText;
private readonly ILogger<LcuRequestViewModel> _logger;
private readonly ILogger<RequestViewModel> _logger;
private readonly Tab _tab;
private readonly HttpClient _httpClient;
public LcuRequestViewModel(ILogger<LcuRequestViewModel> logger)
public RequestViewModel(ILogger<RequestViewModel> logger, Pages.Endpoints.Tab tab, HttpClient httpClient)
{
_logger = logger;
_tab = tab;
_httpClient = httpClient;
}
partial void OnMethodChanged(string? oldValue, string? newValue)
@@ -47,25 +52,80 @@ public partial class LcuRequestViewModel : ObservableObject
}
public async Task ExecuteAsync()
{
switch (_tab)
{
case Tab.LCU:
await ExecuteLcuAsync();
break;
case Tab.GameClient:
await ExecuteGameClientAsync();
break;
default:
break;
}
}
private async Task ExecuteGameClientAsync()
{
try
{
IsRequestBusy = true;
if (string.IsNullOrEmpty(RequestPath))
throw new Exception("Path is empty.");
var method = GetMethod();
var method = Method switch
_logger.LogDebug("Sending request: {Tuple}", (Method, RequestPath));
RequestText?.Invoke(this, this);
var content = new StringContent(RequestBody ?? string.Empty, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
var responsePath = $"https://127.0.0.1:2999{RequestPath}";
var response = await _httpClient.SendAsync(new HttpRequestMessage(method, responsePath) { Content = content });
var responseBody = await response.Content.ReadAsByteArrayAsync();
var body = responseBody.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize<object>(responseBody), App.JsonSerializerOptions) : string.Empty;
if (body.Length > App.MaxCharacters)
{
"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."),
};
WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(body));
UpdateText?.Invoke(this, string.Empty);
}
else
{
ResponseBody = body;
UpdateText?.Invoke(this, body);
}
ResponseStatus = $"{(int)response.StatusCode} {response.StatusCode.ToString()}";
ResponsePath = responsePath;
}
catch (Exception ex)
{
_logger.LogError(ex, "Request failed: {Tuple}", (Method, RequestPath));
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;
ResponseBody = null;
}
finally
{
IsRequestBusy = false;
}
}
private async Task ExecuteLcuAsync()
{
try
{
IsRequestBusy = true;
if (string.IsNullOrEmpty(RequestPath))
throw new Exception("Path is empty.");
var method = GetMethod();
_logger.LogDebug("Sending request: {Tuple}", (Method, RequestPath));
@@ -116,6 +176,22 @@ public partial class LcuRequestViewModel : ObservableObject
}
}
private HttpMethod GetMethod()
{
return 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."),
};
}
private static Color GetColor(string method) => method switch
{
"GET" => Avalonia.Media.Color.FromRgb(95, 99, 186),

View File

@@ -19,13 +19,13 @@
<StackPanel Margin="0 0 0 16">
<Grid RowDefinitions="auto" ColumnDefinitions="auto,*,auto">
<ComboBox ItemsSource="{Binding RequestMethods}"
SelectedItem="{Binding LcuRequest.Method}"
SelectedItem="{Binding Request.Method}"
Margin="0 0 8 0"
Grid.Row="0"
Grid.Column="0"/>
<AutoCompleteBox
ItemsSource="{Binding RequestPaths}"
Text="{Binding LcuRequest.RequestPath}"
Text="{Binding Request.RequestPath}"
MaxDropDownHeight="400"
FilterMode="StartsWith"
Grid.Row="0"
@@ -49,7 +49,7 @@
<TextBox IsReadOnly="True"
Grid.Row="0"
Grid.Column="0"
Text="{Binding LcuRequest.ResponsePath}"/>
Text="{Binding Request.ResponsePath}"/>
<avaloniaEdit:TextEditor
Name="RequestEditor"
Text=""
@@ -69,7 +69,7 @@
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Grid.Column="0">
<Button Content="{Binding LcuRequest.ResponseStatus}"
<Button Content="{Binding Request.ResponseStatus}"
FontSize="12"
VerticalAlignment="Center"/>
</StackPanel>

View File

@@ -28,13 +28,13 @@ public partial class ConsoleView : UserControl
_requestEditor?.ApplyJsonEditorSettings();
var vm = (ConsoleViewModel)DataContext!;
vm.LcuRequest.RequestText += LcuRequest_RequestText; ;
vm.LcuRequest.UpdateText += LcuRequest_UpdateText;
vm.Request.RequestText += LcuRequest_RequestText; ;
vm.Request.UpdateText += LcuRequest_UpdateText;
OnBaseThemeChanged(Application.Current!.ActualThemeVariant);
}
private void LcuRequest_RequestText(object? sender, ViewModels.Shared.LcuRequestViewModel e)
private void LcuRequest_RequestText(object? sender, ViewModels.Shared.RequestViewModel e)
{
e.RequestBody = _requestEditor!.Text;
}
@@ -49,8 +49,8 @@ public partial class ConsoleView : UserControl
base.OnDetachedFromVisualTree(e);
var vm = (ConsoleViewModel)DataContext!;
vm.LcuRequest.RequestText -= LcuRequest_RequestText;
vm.LcuRequest.UpdateText -= LcuRequest_UpdateText;
vm.Request.RequestText -= LcuRequest_RequestText;
vm.Request.UpdateText -= LcuRequest_UpdateText;
}
private void OnBaseThemeChanged(ThemeVariant currentTheme)

View File

@@ -64,8 +64,8 @@
VerticalAlignment="Center"
TextAlignment="Center"
Margin="0 0 8 0"
Text="{Binding LcuRequest.Value.Method}"
Background="{Binding LcuRequest.Value.Color}"
Text="{Binding Request.Value.Method}"
Background="{Binding Request.Value.Color}"
FontSize="8"
Width="50"
Padding="10 2 10 2"
@@ -93,14 +93,14 @@
ColumnDefinitions="auto,*,auto">
<TextBox Grid.Row="0"
Grid.Column="0"
Text="{Binding SelectedPathOperation.LcuRequest.Value.Method}"
Text="{Binding SelectedPathOperation.Request.Value.Method}"
FontSize="12"
IsReadOnly="True"
Margin="0 0 8 0"/>
<TextBox Grid.Row="0"
Grid.Column="1"
FontSize="12"
Text="{Binding SelectedPathOperation.LcuRequest.Value.ResponsePath}"
Text="{Binding SelectedPathOperation.Request.Value.ResponsePath}"
IsReadOnly="True"/>
<StackPanel Grid.Row="0"
Grid.Column="2"
@@ -194,7 +194,7 @@
Grid.Column="1"
Margin="0 0 0 8"
IsReadOnly="True"
Text="{Binding SelectedPathOperation.LcuRequest.Value.ResponseUsername}" />
Text="{Binding SelectedPathOperation.Request.Value.ResponseUsername}" />
<TextBlock FontSize="12"
Grid.Row="1"
Grid.Column="0"
@@ -206,7 +206,7 @@
Grid.Column="1"
Margin="0 0 0 8"
IsReadOnly="True"
Text="{Binding SelectedPathOperation.LcuRequest.Value.ResponsePassword}"/>
Text="{Binding SelectedPathOperation.Request.Value.ResponsePassword}"/>
<TextBlock FontSize="12"
Grid.Row="2"
Grid.Column="0"
@@ -217,7 +217,7 @@
Grid.Row="2"
Grid.Column="1"
IsReadOnly="True"
Text="{Binding SelectedPathOperation.LcuRequest.Value.ResponseAuthorization}"/>
Text="{Binding SelectedPathOperation.Request.Value.ResponseAuthorization}"/>
</Grid>
</TabItem>
<TabItem Header="Schemas">
@@ -309,7 +309,7 @@
FontSize="10"
Padding="12 4 12 4"
Classes="Flat"
Content="{Binding SelectedPathOperation.LcuRequest.Value.ResponseStatus}"/>
Content="{Binding SelectedPathOperation.Request.Value.ResponseStatus}"/>
</StackPanel>
<Grid Grid.Row="1" Grid.Column="4">

View File

@@ -13,7 +13,7 @@ public partial class EndpointView : UserControl
{
private TextEditor? _requestEditor;
private TextEditor? _responseEditor;
private LcuRequestViewModel? _lcuRequestVm;
private RequestViewModel? _lcuRequestVm;
public EndpointView()
{
@@ -34,9 +34,9 @@ public partial class EndpointView : UserControl
if (vm.SelectedPathOperation != null)
{
_lcuRequestVm = vm.SelectedPathOperation.LcuRequest.Value;
vm.SelectedPathOperation.LcuRequest.Value.RequestText += LcuRequest_RequestText;
vm.SelectedPathOperation.LcuRequest.Value.UpdateText += LcuRequest_UpdateText;
_lcuRequestVm = vm.SelectedPathOperation.Request.Value;
vm.SelectedPathOperation.Request.Value.RequestText += LcuRequest_RequestText;
vm.SelectedPathOperation.Request.Value.UpdateText += LcuRequest_UpdateText;
}
OnBaseThemeChanged(Application.Current!.ActualThemeVariant);
@@ -53,10 +53,10 @@ public partial class EndpointView : UserControl
_lcuRequestVm.RequestText -= LcuRequest_RequestText;
_lcuRequestVm.UpdateText -= LcuRequest_UpdateText;
}
vm.SelectedPathOperation.LcuRequest.Value.RequestText += LcuRequest_RequestText;
vm.SelectedPathOperation.LcuRequest.Value.UpdateText += LcuRequest_UpdateText;
_lcuRequestVm = vm.SelectedPathOperation.LcuRequest.Value;
_responseEditor!.Text = vm.SelectedPathOperation.LcuRequest.Value.ResponseBody ?? string.Empty;
vm.SelectedPathOperation.Request.Value.RequestText += LcuRequest_RequestText;
vm.SelectedPathOperation.Request.Value.UpdateText += LcuRequest_UpdateText;
_lcuRequestVm = vm.SelectedPathOperation.Request.Value;
_responseEditor!.Text = vm.SelectedPathOperation.Request.Value.ResponseBody ?? string.Empty;
}
}
@@ -81,7 +81,7 @@ public partial class EndpointView : UserControl
currentTheme == ThemeVariant.Dark ? ThemeName.DarkPlus : ThemeName.LightPlus);
}
private void LcuRequest_RequestText(object? sender, LcuRequestViewModel e)
private void LcuRequest_RequestText(object? sender, RequestViewModel e)
{
e.RequestBody = _requestEditor!.Text;
}

View File

@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="https://github.com/projektanker/icons.avalonia"
Name="EndpointsTab"
xmlns:vm="using:Needlework.Net.ViewModels.Pages.Endpoints"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:controls="using:Needlework.Net.Controls"
@@ -14,6 +15,7 @@
<Grid>
<ui:TabView TabItems="{Binding Endpoints}"
AddTabButtonCommand="{Binding AddEndpointCommand}"
AddTabButtonCommandParameter="{x:Static vm:Tab.LCU}"
TabCloseRequested="TabView_TabCloseRequested">
<!--Need to override Tab header for Mica theme...-->
<ui:TabView.Resources>
@@ -44,7 +46,24 @@
Content="{Binding}">
<ui:TabViewItem.ContentTemplate>
<DataTemplate DataType="vm:EndpointItem">
<ContentControl Content="{Binding Content}"/>
<Grid RowDefinitions="auto,auto,*" ColumnDefinitions="*">
<Menu Grid.Row="0"
Grid.Column="0">
<MenuItem Header="_New tab">
<MenuItem Header="LCU"
Command="{Binding #EndpointsTab.((vm:EndpointsTabViewModel)DataContext).AddEndpointCommand}"
CommandParameter="{x:Static vm:Tab.LCU}"/>
<MenuItem Header="Game Client"
Command="{Binding #EndpointsTab.((vm:EndpointsTabViewModel)DataContext).AddEndpointCommand}"
CommandParameter="{x:Static vm:Tab.GameClient}"/>
</MenuItem>
</Menu>
<Separator Grid.Row="1"
Grid.Column="0"/>
<ContentControl Grid.Row="2"
Grid.Column="0"
Content="{Binding Content}"/>
</Grid>
</DataTemplate>
</ui:TabViewItem.ContentTemplate>
</ui:TabViewItem>

View File

@@ -40,7 +40,7 @@
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">
Welcome to Needlework.Net
</TextBlock>
<TextBlock>Get started with LCU development by clicking on the endpoints tab in the left panel.</TextBlock>
<TextBlock>Get started with LCU or Game Client development by clicking on the endpoints tab in the left panel.</TextBlock>
</StackPanel>
</Border>
<controls:Card Margin="12">