5 Commits

Author SHA1 Message Date
estrogen elf
e95aa987a1 feat: add MacOS platform options 2025-06-01 16:40:33 -05:00
estrogen elf
7997cf222c feat: update Briar 2025-06-01 16:34:23 -05:00
estrogen elf
a321d84757 feat: increment version 2025-05-31 21:28:36 -05:00
estrogen elf
4bef9a20dd refactor: change dependency from GrrrLCU to Briar 2025-05-31 21:28:11 -05:00
estrogen elf
fb5fbe1fea fix: encode Swagger URL, add Markdown copy 2025-05-31 17:24:43 -05:00
14 changed files with 43 additions and 46 deletions

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
@@ -11,7 +11,7 @@
<AvaloniaXamlIlDebuggerLaunch>False</AvaloniaXamlIlDebuggerLaunch> <AvaloniaXamlIlDebuggerLaunch>False</AvaloniaXamlIlDebuggerLaunch>
<ApplicationIcon>app.ico</ApplicationIcon> <ApplicationIcon>app.ico</ApplicationIcon>
<AssemblyName>NeedleworkDotNet</AssemblyName> <AssemblyName>NeedleworkDotNet</AssemblyName>
<AssemblyVersion>0.12.0.0</AssemblyVersion> <AssemblyVersion>0.13.0.0</AssemblyVersion>
<FileVersion>$(AssemblyVersion)</FileVersion> <FileVersion>$(AssemblyVersion)</FileVersion>
<AvaloniaXamlVerboseExceptions>False</AvaloniaXamlVerboseExceptions> <AvaloniaXamlVerboseExceptions>False</AvaloniaXamlVerboseExceptions>
</PropertyGroup> </PropertyGroup>
@@ -27,7 +27,7 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.3" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.3" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.3" /> <PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.3" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" /> <PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
<PackageReference Include="BlossomiShymae.GrrrLCU" Version="0.14.0" /> <PackageReference Include="BlossomiShymae.Briar" Version="0.2.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageReference Include="FluentAvaloniaUI" Version="2.1.0" /> <PackageReference Include="FluentAvaloniaUI" Version="2.1.0" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.1.10" /> <PackageReference Include="Material.Icons.Avalonia" Version="2.1.10" />

View File

@@ -4,11 +4,9 @@ using Needlework.Net.Extensions;
using Needlework.Net.Services; using Needlework.Net.Services;
using Needlework.Net.ViewModels.MainWindow; using Needlework.Net.ViewModels.MainWindow;
using Needlework.Net.ViewModels.Pages; using Needlework.Net.ViewModels.Pages;
using Needlework.Net.ViewModels.Pages.Endpoints;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.FontAwesome;
using System; using System;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Needlework.Net; namespace Needlework.Net;
@@ -38,11 +36,15 @@ class Program
return AppBuilder.Configure(() => new App(services)) return AppBuilder.Configure(() => new App(services))
.UsePlatformDetect() .UsePlatformDetect()
.WithInterFont() .WithInterFont()
.LogToTrace()
.With(new Win32PlatformOptions .With(new Win32PlatformOptions
{ {
CompositionMode = [Win32CompositionMode.WinUIComposition, Win32CompositionMode.DirectComposition] CompositionMode = [Win32CompositionMode.WinUIComposition, Win32CompositionMode.DirectComposition]
}); })
.With(new MacOSPlatformOptions
{
ShowInDock = true,
})
.LogToTrace();
} }
private static async Task InitializeDataSourceAsync(IServiceProvider services) private static async Task InitializeDataSourceAsync(IServiceProvider services)
@@ -60,14 +62,6 @@ class Program
builder.AddSingleton<DataSource>(); builder.AddSingleton<DataSource>();
builder.AddSingletonsFromAssemblies<PageBase>(); builder.AddSingletonsFromAssemblies<PageBase>();
builder.AddHttpClient(); builder.AddHttpClient();
builder.AddHttpClient(nameof(EndpointsTabViewModel)).ConfigurePrimaryHttpMessageHandler(() => // Insecure SSL for Game Client API
{
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
return handler;
});
builder.AddLogging(Logger.Setup); builder.AddLogging(Logger.Setup);
var services = builder.BuildServiceProvider(); var services = builder.BuildServiceProvider();

View File

@@ -1,5 +1,6 @@
using Avalonia.Collections; using Avalonia.Collections;
using BlossomiShymae.GrrrLCU; using BlossomiShymae.Briar;
using BlossomiShymae.Briar.Utils;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;

View File

@@ -4,7 +4,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Needlework.Net.ViewModels.Shared; using Needlework.Net.ViewModels.Shared;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Needlework.Net.ViewModels.Pages; namespace Needlework.Net.ViewModels.Pages;
@@ -19,9 +18,9 @@ public partial class ConsoleViewModel : PageBase
private readonly DataSource _dataSource; private readonly DataSource _dataSource;
public ConsoleViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource, HttpClient httpClient) : base("Console", "terminal", -200) public ConsoleViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource) : base("Console", "terminal", -200)
{ {
_request = new(requestViewModelLogger, Endpoints.Tab.LCU, httpClient); _request = new(requestViewModelLogger, Endpoints.Tab.LCU);
_dataSource = dataSource; _dataSource = dataSource;
} }

View File

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

View File

@@ -18,9 +18,9 @@ public partial class EndpointsNavigationViewModel : ObservableObject
private readonly Action<string?, Guid> _onEndpointNavigation; private readonly Action<string?, Guid> _onEndpointNavigation;
private readonly Tab _tab; private readonly Tab _tab;
public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab, System.Net.Http.HttpClient httpClient) public EndpointsNavigationViewModel(IAvaloniaList<string> plugins, Action<string?, Guid> onEndpointNavigation, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab)
{ {
_activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, requestViewModelLogger, document, tab, httpClient); _activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, requestViewModelLogger, document, tab);
_onEndpointNavigation = onEndpointNavigation; _onEndpointNavigation = onEndpointNavigation;
_tab = tab; _tab = tab;
_title = GetTitle(tab); _title = GetTitle(tab);

View File

@@ -7,7 +7,6 @@ using Microsoft.Extensions.Logging;
using Needlework.Net.Models; using Needlework.Net.Models;
using Needlework.Net.ViewModels.Shared; using Needlework.Net.ViewModels.Shared;
using System; using System;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Needlework.Net.ViewModels.Pages.Endpoints; namespace Needlework.Net.ViewModels.Pages.Endpoints;
@@ -27,13 +26,11 @@ public partial class EndpointsTabViewModel : PageBase
private readonly ILogger<RequestViewModel> _requestViewModelLogger; private readonly ILogger<RequestViewModel> _requestViewModelLogger;
private readonly DataSource _dataSource; private readonly DataSource _dataSource;
private readonly HttpClient _httpClient;
public EndpointsTabViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource, IHttpClientFactory httpClientFactory) : base("Endpoints", "list-alt", -500) public EndpointsTabViewModel(ILogger<RequestViewModel> requestViewModelLogger, DataSource dataSource) : base("Endpoints", "list-alt", -500)
{ {
_requestViewModelLogger = requestViewModelLogger; _requestViewModelLogger = requestViewModelLogger;
_dataSource = dataSource; _dataSource = dataSource;
_httpClient = httpClientFactory.CreateClient(nameof(EndpointsTabViewModel));
} }
public override async Task InitializeAsync() public override async Task InitializeAsync()
{ {
@@ -55,7 +52,7 @@ public partial class EndpointsTabViewModel : PageBase
Plugins.Clear(); Plugins.Clear();
Plugins.AddRange(document.Plugins.Keys); Plugins.AddRange(document.Plugins.Keys);
var vm = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _requestViewModelLogger, document, tab, _httpClient); var vm = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _requestViewModelLogger, document, tab);
Endpoints.Add(new() Endpoints.Add(new()
{ {
Content = vm, Content = vm,

View File

@@ -6,7 +6,6 @@ using Needlework.Net.Models;
using Needlework.Net.ViewModels.Shared; using Needlework.Net.ViewModels.Shared;
using System; using System;
using System.Linq; using System.Linq;
using System.Net.Http;
namespace Needlework.Net.ViewModels.Pages.Endpoints; namespace Needlework.Net.ViewModels.Pages.Endpoints;
@@ -23,9 +22,8 @@ public partial class EndpointsViewModel : ObservableObject
private readonly ILogger<RequestViewModel> _requestViewModelLogger; private readonly ILogger<RequestViewModel> _requestViewModelLogger;
private readonly Document _document; private readonly Document _document;
private readonly Tab _tab; private readonly Tab _tab;
private readonly HttpClient _httpClient;
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab, System.Net.Http.HttpClient httpClient) public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked, ILogger<RequestViewModel> requestViewModelLogger, Models.Document document, Tab tab)
{ {
Plugins = new AvaloniaList<string>(plugins); Plugins = new AvaloniaList<string>(plugins);
Query = new AvaloniaList<string>(plugins); Query = new AvaloniaList<string>(plugins);
@@ -33,7 +31,6 @@ public partial class EndpointsViewModel : ObservableObject
_requestViewModelLogger = requestViewModelLogger; _requestViewModelLogger = requestViewModelLogger;
_document = document; _document = document;
_tab = tab; _tab = tab;
_httpClient = httpClient;
} }
partial void OnSearchChanged(string value) partial void OnSearchChanged(string value)
@@ -50,6 +47,6 @@ public partial class EndpointsViewModel : ObservableObject
{ {
if (string.IsNullOrEmpty(value)) return; if (string.IsNullOrEmpty(value)) return;
OnClicked.Invoke(new EndpointViewModel(value, _requestViewModelLogger, _document, _tab, _httpClient)); OnClicked.Invoke(new EndpointViewModel(value, _requestViewModelLogger, _document, _tab));
} }
} }

View File

@@ -15,19 +15,21 @@ public partial class PathOperationViewModel : ObservableObject
public OperationViewModel Operation { get; } public OperationViewModel Operation { get; }
public string Url { get; } public string Url { get; }
public string Markdown { get; }
[ObservableProperty] private bool _isBusy; [ObservableProperty] private bool _isBusy;
[ObservableProperty] private Lazy<RequestViewModel> _request; [ObservableProperty] private Lazy<RequestViewModel> _request;
public PathOperationViewModel(PathOperation pathOperation, ILogger<RequestViewModel> requestViewModelLogger, Document document, Tab tab, System.Net.Http.HttpClient httpClient) public PathOperationViewModel(PathOperation pathOperation, ILogger<RequestViewModel> requestViewModelLogger, Document document, Tab tab)
{ {
Path = pathOperation.Path; Path = pathOperation.Path;
Operation = new OperationViewModel(pathOperation.Operation, document); Operation = new OperationViewModel(pathOperation.Operation, document);
Request = new(() => new RequestViewModel(requestViewModelLogger, tab, httpClient) Request = new(() => new RequestViewModel(requestViewModelLogger, tab)
{ {
Method = pathOperation.Method.ToUpper() Method = pathOperation.Method.ToUpper()
}); });
Url = $"https://swagger.dysolix.dev/lcu/#/{pathOperation.Tag}/{pathOperation.Operation.OperationId}"; Url = $"https://swagger.dysolix.dev/lcu/#/{Uri.EscapeDataString(pathOperation.Tag)}/{pathOperation.Operation.OperationId}";
Markdown = $"[{pathOperation.Method.ToUpper()} {Path}]({Url})";
} }
[RelayCommand] [RelayCommand]
@@ -59,4 +61,10 @@ public partial class PathOperationViewModel : ObservableObject
{ {
App.MainWindow?.Clipboard?.SetTextAsync(Url); App.MainWindow?.Clipboard?.SetTextAsync(Url);
} }
[RelayCommand]
private void CopyMarkdown()
{
App.MainWindow?.Clipboard?.SetTextAsync(Markdown);
}
} }

View File

@@ -1,4 +1,4 @@
using BlossomiShymae.GrrrLCU; using BlossomiShymae.Briar.Utils;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
namespace Needlework.Net.ViewModels.Pages.Endpoints; namespace Needlework.Net.ViewModels.Pages.Endpoints;

View File

@@ -1,4 +1,4 @@
using BlossomiShymae.GrrrLCU; using BlossomiShymae.Briar.WebSocket.Events;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using System; using System;

View File

@@ -1,5 +1,6 @@
using Avalonia.Collections; using Avalonia.Collections;
using BlossomiShymae.GrrrLCU; using BlossomiShymae.Briar;
using BlossomiShymae.Briar.WebSocket.Events;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;

View File

@@ -1,5 +1,6 @@
using Avalonia.Media; using Avalonia.Media;
using BlossomiShymae.GrrrLCU; using BlossomiShymae.Briar;
using BlossomiShymae.Briar.Utils;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -35,13 +36,11 @@ public partial class RequestViewModel : ObservableObject
private readonly ILogger<RequestViewModel> _logger; private readonly ILogger<RequestViewModel> _logger;
private readonly Tab _tab; private readonly Tab _tab;
private readonly HttpClient _httpClient;
public RequestViewModel(ILogger<RequestViewModel> logger, Pages.Endpoints.Tab tab, HttpClient httpClient) public RequestViewModel(ILogger<RequestViewModel> logger, Pages.Endpoints.Tab tab)
{ {
_logger = logger; _logger = logger;
_tab = tab; _tab = tab;
_httpClient = httpClient;
} }
partial void OnMethodChanged(string? oldValue, string? newValue) partial void OnMethodChanged(string? oldValue, string? newValue)
@@ -78,8 +77,8 @@ public partial class RequestViewModel : ObservableObject
_logger.LogDebug("Sending request: {Tuple}", (Method, RequestPath)); _logger.LogDebug("Sending request: {Tuple}", (Method, RequestPath));
RequestText?.Invoke(this, this); RequestText?.Invoke(this, this);
var content = new StringContent(RequestBody ?? string.Empty, new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); 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 client = Connector.GetGameHttpClientInstance();
var response = await _httpClient.SendAsync(new HttpRequestMessage(method, responsePath) { Content = content }); var response = await client.SendAsync(new HttpRequestMessage(method, RequestPath) { Content = content });
var responseBody = await response.Content.ReadAsByteArrayAsync(); var responseBody = await response.Content.ReadAsByteArrayAsync();
var body = responseBody.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize<object>(responseBody), App.JsonSerializerOptions) : string.Empty; var body = responseBody.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize<object>(responseBody), App.JsonSerializerOptions) : string.Empty;
@@ -95,7 +94,7 @@ public partial class RequestViewModel : ObservableObject
} }
ResponseStatus = $"{(int)response.StatusCode} {response.StatusCode.ToString()}"; ResponseStatus = $"{(int)response.StatusCode} {response.StatusCode.ToString()}";
ResponsePath = responsePath; ResponsePath = $"https://127.0.0.1:2999{RequestPath}";
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -58,6 +58,7 @@
<Grid.ContextFlyout> <Grid.ContextFlyout>
<MenuFlyout> <MenuFlyout>
<MenuItem Header="Copy Swagger URL" Command="{Binding CopyUrlCommand}"/> <MenuItem Header="Copy Swagger URL" Command="{Binding CopyUrlCommand}"/>
<MenuItem Header="Copy Markdown" Command="{Binding CopyMarkdownCommand}"/>
</MenuFlyout> </MenuFlyout>
</Grid.ContextFlyout> </Grid.ContextFlyout>
<TextBlock <TextBlock