diff --git a/Needlework.Net/App.axaml.cs b/Needlework.Net/App.axaml.cs index 5a5c7e4..a1bee0d 100644 --- a/Needlework.Net/App.axaml.cs +++ b/Needlework.Net/App.axaml.cs @@ -40,8 +40,6 @@ public partial class App(IServiceProvider serviceProvider) : Application MainWindow = desktop.MainWindow; } - - base.OnFrameworkInitializationCompleted(); } } \ No newline at end of file diff --git a/Needlework.Net/DataSource.cs b/Needlework.Net/DataSource.cs new file mode 100644 index 0000000..1daab6f --- /dev/null +++ b/Needlework.Net/DataSource.cs @@ -0,0 +1,60 @@ +using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Readers; +using Needlework.Net.Models; +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Needlework.Net +{ + public class DataSource + { + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private Document? _lcuSchemaDocument; + private Document? _lolClientDocument; + private readonly TaskCompletionSource _taskCompletionSource = new(); + + + public DataSource(HttpClient httpClient, ILogger logger) + { + _httpClient = httpClient; + _logger = logger; + } + + public async Task GetLcuSchemaDocumentAsync() + { + await _taskCompletionSource.Task; + return _lcuSchemaDocument ?? throw new InvalidOperationException(); + } + + public async Task GetLolClientDocumentAsync() + { + await _taskCompletionSource.Task; + return _lolClientDocument ?? throw new InvalidOperationException(); + } + + public async Task InitializeAsync() + { + try + { + var reader = new OpenApiStreamReader(); + var lcuSchemaStream = await _httpClient.GetStreamAsync("https://raw.githubusercontent.com/dysolix/hasagi-types/main/swagger.json"); + 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 lolClientRaw = reader.Read(lolClientStream, out var _); + _lolClientDocument = new Document(lolClientRaw); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to initialize DataSource"); + } + finally + { + _taskCompletionSource.SetResult(true); + } + } + } +} diff --git a/Needlework.Net/Logger.cs b/Needlework.Net/Logger.cs index ccb97a1..07ab398 100644 --- a/Needlework.Net/Logger.cs +++ b/Needlework.Net/Logger.cs @@ -1,12 +1,8 @@ using Microsoft.Extensions.Logging; using Serilog; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace Needlework.Net { @@ -16,7 +12,7 @@ namespace Needlework.Net { var logger = new LoggerConfiguration() .MinimumLevel.Debug() - .WriteTo.File("Logs/debug-.log", rollingInterval: RollingInterval.Day, shared: true) + .WriteTo.File("Logs/debug-", rollingInterval: RollingInterval.Day, shared: true) .CreateLogger(); logger.Debug("NeedleworkDotNet version: {Version}", Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0.0.0.0"); logger.Debug("OS description: {Description}", System.Runtime.InteropServices.RuntimeInformation.OSDescription); @@ -25,7 +21,7 @@ namespace Needlework.Net public static void LogFatal(UnhandledExceptionEventArgs e) { - File.WriteAllText($"Logs/fatal-{DateTime.Now:HHmmssfff}.log", e.ExceptionObject.ToString()); + File.WriteAllText($"Logs/fatal-{DateTime.Now:HHmmssfff}", e.ExceptionObject.ToString()); } } } diff --git a/Needlework.Net/Messages/DataReadyMessage.cs b/Needlework.Net/Messages/DataReadyMessage.cs deleted file mode 100644 index a88168d..0000000 --- a/Needlework.Net/Messages/DataReadyMessage.cs +++ /dev/null @@ -1,9 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; -using Needlework.Net.Models; - -namespace Needlework.Net.Messages -{ - public class DataReadyMessage(OpenApiDocumentWrapper wrapper) : ValueChangedMessage(wrapper) - { - } -} diff --git a/Needlework.Net/Messages/DataRequestMessage.cs b/Needlework.Net/Messages/DataRequestMessage.cs deleted file mode 100644 index 1b44d1b..0000000 --- a/Needlework.Net/Messages/DataRequestMessage.cs +++ /dev/null @@ -1,9 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; -using Needlework.Net.Models; - -namespace Needlework.Net.Messages -{ - public class DataRequestMessage : RequestMessage - { - } -} diff --git a/Needlework.Net/Messages/HostDocumentRequestMessage.cs b/Needlework.Net/Messages/HostDocumentRequestMessage.cs deleted file mode 100644 index d6a105b..0000000 --- a/Needlework.Net/Messages/HostDocumentRequestMessage.cs +++ /dev/null @@ -1,9 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; -using Microsoft.OpenApi.Models; - -namespace Needlework.Net.Messages -{ - public class HostDocumentRequestMessage : RequestMessage - { - } -} diff --git a/Needlework.Net/Models/OpenApiDocumentWrapper.cs b/Needlework.Net/Models/Document.cs similarity index 96% rename from Needlework.Net/Models/OpenApiDocumentWrapper.cs rename to Needlework.Net/Models/Document.cs index 481862b..9b2b8d5 100644 --- a/Needlework.Net/Models/OpenApiDocumentWrapper.cs +++ b/Needlework.Net/Models/Document.cs @@ -4,7 +4,7 @@ using Microsoft.OpenApi.Models; namespace Needlework.Net.Models; -public class OpenApiDocumentWrapper +public class Document { internal OpenApiDocument OpenApiDocument { get; } @@ -14,7 +14,7 @@ public class OpenApiDocumentWrapper public List Paths => [.. OpenApiDocument.Paths.Keys]; - public OpenApiDocumentWrapper(OpenApiDocument openApiDocument) + public Document(OpenApiDocument openApiDocument) { OpenApiDocument = openApiDocument; var plugins = new SortedDictionary>(); diff --git a/Needlework.Net/Program.cs b/Needlework.Net/Program.cs index 7fd161a..d92492e 100644 --- a/Needlework.Net/Program.cs +++ b/Needlework.Net/Program.cs @@ -6,10 +6,8 @@ using Needlework.Net.ViewModels.MainWindow; using Needlework.Net.ViewModels.Pages; using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; -using Serilog; using System; -using System.IO; -using System.Reflection; +using System.Threading.Tasks; namespace Needlework.Net; @@ -32,23 +30,32 @@ class Program { IconProvider.Current .Register(); + var services = BuildServices(); + Task.Run(async () => await InitializeDataSourceAsync(services)); - return AppBuilder.Configure(() => new App(BuildServices())) + return AppBuilder.Configure(() => new App(services)) .UsePlatformDetect() .WithInterFont() .LogToTrace() .With(new Win32PlatformOptions { - CompositionMode = [ Win32CompositionMode.WinUIComposition, Win32CompositionMode.DirectComposition ] + CompositionMode = [Win32CompositionMode.WinUIComposition, Win32CompositionMode.DirectComposition] }); } + private static async Task InitializeDataSourceAsync(IServiceProvider services) + { + var dataSource = services.GetRequiredService(); + await dataSource.InitializeAsync(); + } + private static IServiceProvider BuildServices() { var builder = new ServiceCollection(); builder.AddSingleton(); builder.AddSingleton(); + builder.AddSingleton(); builder.AddSingletonsFromAssemblies(); builder.AddHttpClient(); builder.AddLogging(Logger.Setup); diff --git a/Needlework.Net/ViewModels/MainWindow/MainWindowViewModel.cs b/Needlework.Net/ViewModels/MainWindow/MainWindowViewModel.cs index 80e07b0..a1f334f 100644 --- a/Needlework.Net/ViewModels/MainWindow/MainWindowViewModel.cs +++ b/Needlework.Net/ViewModels/MainWindow/MainWindowViewModel.cs @@ -19,20 +19,17 @@ using System.Linq; using System.Net.Http; using System.Net.Http.Json; using System.Reflection; -using System.Text.Json.Nodes; -using System.Threading; using System.Threading.Tasks; using System.Timers; namespace Needlework.Net.ViewModels.MainWindow; public partial class MainWindowViewModel - : ObservableObject, IRecipient, IRecipient, IRecipient, IRecipient + : ObservableObject, IRecipient, IRecipient { public IAvaloniaReadOnlyList MenuItems { get; } - [NotifyPropertyChangedFor(nameof(CurrentPage))] [ObservableProperty] private NavigationViewItem _selectedMenuItem; - public PageBase CurrentPage => (PageBase)SelectedMenuItem.Tag!; + [ObservableProperty] private PageBase _currentPage; public string Version { get; } = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "0.0.0.0"; [ObservableProperty] private bool _isUpdateShown = false; @@ -42,7 +39,7 @@ public partial class MainWindowViewModel public HttpClient HttpClient { get; } public DialogService DialogService { get; } - public OpenApiDocumentWrapper? OpenApiDocumentWrapper { get; set; } + public Document? OpenApiDocumentWrapper { get; set; } public OpenApiDocument? HostDocument { get; set; } [ObservableProperty] private bool _isBusy = true; @@ -78,14 +75,13 @@ public partial class MainWindowViewModel IconSource = new BitmapIconSource() { UriSource = new Uri($"avares://NeedleworkDotNet/Assets/Icons/{p.Icon}.png") } })); SelectedMenuItem = MenuItems[0]; + CurrentPage = (PageBase)MenuItems[0].Tag!; HttpClient = httpClient; DialogService = dialogService; WeakReferenceMessenger.Default.RegisterAll(this); - Task.Run(FetchDataAsync); - _latestUpdateTimer.Elapsed += OnLatestUpdateTimerElapsed; _schemaVersionTimer.Elapsed += OnSchemaVersionTimerElapsed; _latestUpdateTimer.Start(); @@ -95,6 +91,18 @@ public partial class MainWindowViewModel } + partial void OnSelectedMenuItemChanged(NavigationViewItem value) + { + if (value.Tag is PageBase page) + { + CurrentPage = page; + if (!page.IsInitialized) + { + Task.Run(page.InitializeAsync); + } + } + } + private async void OnSchemaVersionTimerElapsed(object? sender, ElapsedEventArgs? e) { if (OpenApiDocumentWrapper == null) return; @@ -177,34 +185,6 @@ public partial class MainWindowViewModel } } - private async Task FetchDataAsync() - { - try - { - var document = await Resources.GetOpenApiDocumentAsync(HttpClient); - HostDocument = document; - var handler = new OpenApiDocumentWrapper(document); - OpenApiDocumentWrapper = handler; - - WeakReferenceMessenger.Default.Send(new DataReadyMessage(handler)); - IsBusy = false; - } - catch (HttpRequestException ex) - { - _logger.LogError(ex, "Failed to fetch OpenAPI data"); - } - } - - public void Receive(DataRequestMessage message) - { - message.Reply(OpenApiDocumentWrapper!); - } - - public void Receive(HostDocumentRequestMessage message) - { - message.Reply(HostDocument!); - } - [RelayCommand] private void OpenUrl(string url) { diff --git a/Needlework.Net/ViewModels/Pages/AboutViewModel.cs b/Needlework.Net/ViewModels/Pages/AboutViewModel.cs index 7574eec..7b43894 100644 --- a/Needlework.Net/ViewModels/Pages/AboutViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/AboutViewModel.cs @@ -1,6 +1,7 @@ using CommunityToolkit.Mvvm.Input; using System.Diagnostics; using System.Net.Http; +using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages; @@ -13,6 +14,12 @@ public partial class AboutViewModel : PageBase HttpClient = httpClient; } + public override Task InitializeAsync() + { + IsInitialized = true; + return Task.CompletedTask; + } + [RelayCommand] private void OpenUrl(string url) { diff --git a/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs b/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs index 59ae6e1..e807798 100644 --- a/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/ConsoleViewModel.cs @@ -1,15 +1,14 @@ using Avalonia.Collections; +using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.Logging; -using Needlework.Net.Messages; using Needlework.Net.ViewModels.Shared; using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages; -public partial class ConsoleViewModel : PageBase, IRecipient +public partial class ConsoleViewModel : PageBase { public IAvaloniaReadOnlyList RequestMethods { get; } = new AvaloniaList(["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH", "OPTIONS", "TRACE"]); public IAvaloniaList RequestPaths { get; } = new AvaloniaList(); @@ -17,10 +16,24 @@ public partial class ConsoleViewModel : PageBase, IRecipient [ObservableProperty] private bool _isBusy = true; [ObservableProperty] private LcuRequestViewModel _lcuRequest; - public ConsoleViewModel(ILogger lcuRequestViewModelLogger) : base("Console", "terminal", -200) + private readonly DataSource _dataSource; + + public ConsoleViewModel(ILogger lcuRequestViewModelLogger, DataSource dataSource) : base("Console", "terminal", -200) { _lcuRequest = new(lcuRequestViewModelLogger); - WeakReferenceMessenger.Default.Register(this); + _dataSource = dataSource; + } + + public override async Task InitializeAsync() + { + var document = await _dataSource.GetLolClientDocumentAsync(); + Dispatcher.UIThread.Invoke(() => + { + RequestPaths.Clear(); + RequestPaths.AddRange(document.Paths); + }); + IsBusy = false; + IsInitialized = true; } [RelayCommand] @@ -28,14 +41,4 @@ public partial class ConsoleViewModel : PageBase, IRecipient { await LcuRequest.ExecuteAsync(); } - - public void Receive(DataReadyMessage message) - { - Avalonia.Threading.Dispatcher.UIThread.Invoke(() => - { - RequestPaths.Clear(); - RequestPaths.AddRange(message.Value.Paths); - IsBusy = false; - }); - } } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs index 921ba54..953959d 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointViewModel.cs @@ -1,8 +1,6 @@ using Avalonia.Collections; using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.Logging; -using Needlework.Net.Messages; using Needlework.Net.ViewModels.Shared; using System; using System.Linq; @@ -23,12 +21,10 @@ public partial class EndpointViewModel : ObservableObject public event EventHandler? PathOperationSelected; - public EndpointViewModel(string endpoint, ILogger lcuRequestViewModelLogger) + public EndpointViewModel(string endpoint, ILogger lcuRequestViewModelLogger, Models.Document lcuSchemaDocument) { Endpoint = endpoint; - - var handler = WeakReferenceMessenger.Default.Send().Response; - PathOperations = new AvaloniaList(handler.Plugins[endpoint].Select(x => new PathOperationViewModel(x, lcuRequestViewModelLogger))); + PathOperations = new AvaloniaList(lcuSchemaDocument.Plugins[endpoint].Select(x => new PathOperationViewModel(x, lcuRequestViewModelLogger, lcuSchemaDocument))); FilteredPathOperations = new AvaloniaList(PathOperations); } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsNavigationViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsNavigationViewModel.cs index 71a3d48..8404a55 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsNavigationViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsNavigationViewModel.cs @@ -17,9 +17,9 @@ public partial class EndpointsNavigationViewModel : ObservableObject private readonly Action _onEndpointNavigation; - public EndpointsNavigationViewModel(IAvaloniaList plugins, Action onEndpointNavigation, ILogger lcuRequestViewModelLogger) + public EndpointsNavigationViewModel(IAvaloniaList plugins, Action onEndpointNavigation, ILogger lcuRequestViewModelLogger, Models.Document lcuSchemaDocument) { - _activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, lcuRequestViewModelLogger); + _activeViewModel = _endpointsViewModel = new EndpointsViewModel(plugins, OnClicked, lcuRequestViewModelLogger, lcuSchemaDocument); _onEndpointNavigation = onEndpointNavigation; } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsTabViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsTabViewModel.cs index cf9e6a8..b3dd063 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsTabViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsTabViewModel.cs @@ -5,13 +5,13 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using FluentAvalonia.UI.Controls; using Microsoft.Extensions.Logging; -using Needlework.Net.Messages; using Needlework.Net.ViewModels.Shared; using System; +using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages.Endpoints; -public partial class EndpointsTabViewModel : PageBase, IRecipient +public partial class EndpointsTabViewModel : PageBase { public IAvaloniaList Plugins { get; } = new AvaloniaList(); public IAvaloniaList Endpoints { get; } = new AvaloniaList(); @@ -19,28 +19,31 @@ public partial class EndpointsTabViewModel : PageBase, IRecipient _lcuRequestViewModelLogger; + private readonly DataSource _dataSource; - public EndpointsTabViewModel(ILogger lcuRequestViewModelLogger) : base("Endpoints", "list-alt", -500) + public EndpointsTabViewModel(ILogger lcuRequestViewModelLogger, DataSource dataSource) : base("Endpoints", "list-alt", -500) { _lcuRequestViewModelLogger = lcuRequestViewModelLogger; + _dataSource = dataSource; WeakReferenceMessenger.Default.RegisterAll(this); } - - public void Receive(DataReadyMessage message) + public override async Task InitializeAsync() { - IsBusy = false; + var document = await _dataSource.GetLcuSchemaDocumentAsync(); Plugins.Clear(); - Plugins.AddRange(message.Value.Plugins.Keys); - - Dispatcher.UIThread.Post(AddEndpoint); + Plugins.AddRange(document.Plugins.Keys); + await Dispatcher.UIThread.Invoke(AddEndpoint); + IsBusy = false; + IsInitialized = true; } [RelayCommand] - private void AddEndpoint() + private async Task AddEndpoint() { + var lcuSchemaDocument = await _dataSource.GetLcuSchemaDocumentAsync(); Endpoints.Add(new() { - Content = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _lcuRequestViewModelLogger), + Content = new EndpointsNavigationViewModel(Plugins, OnEndpointNavigation, _lcuRequestViewModelLogger, lcuSchemaDocument), Selected = true }); } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsViewModel.cs index 65446d3..c9f734e 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/EndpointsViewModel.cs @@ -2,6 +2,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Extensions.Logging; +using Needlework.Net.Models; using Needlework.Net.ViewModels.Shared; using System; using System.Linq; @@ -19,13 +20,15 @@ public partial class EndpointsViewModel : ObservableObject public Action OnClicked { get; } private readonly ILogger _lcuRequestViewModelLogger; + private readonly Document _lcuSchemaDocument; - public EndpointsViewModel(IAvaloniaList plugins, Action onClicked, ILogger lcuRequestViewModelLogger) + public EndpointsViewModel(IAvaloniaList plugins, Action onClicked, ILogger lcuRequestViewModelLogger, Models.Document lcuSchemaDocument) { Plugins = new AvaloniaList(plugins); Query = new AvaloniaList(plugins); OnClicked = onClicked; _lcuRequestViewModelLogger = lcuRequestViewModelLogger; + _lcuSchemaDocument = lcuSchemaDocument; } partial void OnSearchChanged(string value) @@ -42,6 +45,6 @@ public partial class EndpointsViewModel : ObservableObject { if (string.IsNullOrEmpty(value)) return; - OnClicked.Invoke(new EndpointViewModel(value, _lcuRequestViewModelLogger)); + OnClicked.Invoke(new EndpointViewModel(value, _lcuRequestViewModelLogger, _lcuSchemaDocument)); } } diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/OperationViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/OperationViewModel.cs index 2e3f899..303b4ea 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/OperationViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/OperationViewModel.cs @@ -1,8 +1,7 @@ using Avalonia.Collections; using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Messaging; using Microsoft.OpenApi.Models; -using Needlework.Net.Messages; +using Needlework.Net.Models; using System.Collections.Generic; using System.Linq; using System.Text.Json; @@ -22,23 +21,23 @@ public partial class OperationViewModel : ObservableObject public IAvaloniaReadOnlyList QueryParameters { get; } public string? RequestTemplate { get; } - public OperationViewModel(OpenApiOperation operation) + public OperationViewModel(OpenApiOperation operation, Models.Document lcuSchemaDocument) { Summary = operation.Summary ?? string.Empty; Description = operation.Description ?? string.Empty; IsRequestBody = operation.RequestBody != null; ReturnType = GetReturnType(operation.Responses); - RequestClasses = GetRequestClasses(operation.RequestBody); - ResponseClasses = GetResponseClasses(operation.Responses); + RequestClasses = GetRequestClasses(operation.RequestBody, lcuSchemaDocument); + ResponseClasses = GetResponseClasses(operation.Responses, lcuSchemaDocument); PathParameters = GetParameters(operation.Parameters, ParameterLocation.Path); QueryParameters = GetParameters(operation.Parameters, ParameterLocation.Query); RequestBodyType = GetRequestBodyType(operation.RequestBody); - RequestTemplate = GetRequestTemplate(operation.RequestBody); + RequestTemplate = GetRequestTemplate(operation.RequestBody, lcuSchemaDocument); } - private string? GetRequestTemplate(OpenApiRequestBody? requestBody) + private string? GetRequestTemplate(OpenApiRequestBody? requestBody, Document lcuSchemaDocument) { - var requestClasses = GetRequestClasses(requestBody); + var requestClasses = GetRequestClasses(requestBody, lcuSchemaDocument); if (requestClasses.Count == 0) { var type = GetRequestBodyType(requestBody); @@ -133,12 +132,12 @@ public partial class OperationViewModel : ObservableObject return pathParameters; } - private AvaloniaList GetResponseClasses(OpenApiResponses responses) + private AvaloniaList GetResponseClasses(OpenApiResponses responses, Document lcuSchemaDocument) { if (responses.TryGetValue("2XX", out var response) && response.Content.TryGetValue("application/json", out var media)) { - var document = WeakReferenceMessenger.Default.Send(new HostDocumentRequestMessage()).Response; + var document = lcuSchemaDocument.OpenApiDocument; var schema = media.Schema; AvaloniaList propertyClasses = []; WalkSchema(schema, propertyClasses, document); @@ -186,12 +185,12 @@ public partial class OperationViewModel : ObservableObject || type.Contains("number")); } - private AvaloniaList GetRequestClasses(OpenApiRequestBody? requestBody) + private AvaloniaList GetRequestClasses(OpenApiRequestBody? requestBody, Document lcuSchemaDocument) { if (requestBody == null) return []; if (requestBody.Content.TryGetValue("application/json", out var media)) { - var document = WeakReferenceMessenger.Default.Send(new HostDocumentRequestMessage()).Response; + var document = lcuSchemaDocument.OpenApiDocument; var schema = media.Schema; if (schema == null) return []; diff --git a/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs b/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs index 3cb38cb..679ef92 100644 --- a/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Endpoints/PathOperationViewModel.cs @@ -1,5 +1,4 @@ -using Avalonia.Controls; -using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Extensions.Logging; using Needlework.Net.Models; @@ -20,10 +19,10 @@ public partial class PathOperationViewModel : ObservableObject [ObservableProperty] private bool _isBusy; [ObservableProperty] private Lazy _lcuRequest; - public PathOperationViewModel(PathOperation pathOperation, ILogger lcuRequestViewModelLogger) + public PathOperationViewModel(PathOperation pathOperation, ILogger lcuRequestViewModelLogger, Document lcuSchemaDocument) { Path = pathOperation.Path; - Operation = new OperationViewModel(pathOperation.Operation); + Operation = new OperationViewModel(pathOperation.Operation, lcuSchemaDocument); LcuRequest = new(() => new LcuRequestViewModel(lcuRequestViewModelLogger) { Method = pathOperation.Method.ToUpper() diff --git a/Needlework.Net/ViewModels/Pages/HomeViewModel.cs b/Needlework.Net/ViewModels/Pages/HomeViewModel.cs index 63c35db..756a706 100644 --- a/Needlework.Net/ViewModels/Pages/HomeViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/HomeViewModel.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Text.Json; +using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages; @@ -14,6 +15,12 @@ public partial class HomeViewModel : PageBase public HomeViewModel() : base("Home", "home", int.MinValue) { } + public override Task InitializeAsync() + { + IsInitialized = true; + return Task.CompletedTask; + } + [RelayCommand] private void OpenUrl(string url) { @@ -23,4 +30,5 @@ public partial class HomeViewModel : PageBase }; process.Start(); } + } diff --git a/Needlework.Net/ViewModels/Pages/PageBase.cs b/Needlework.Net/ViewModels/Pages/PageBase.cs index f172026..fff5f1d 100644 --- a/Needlework.Net/ViewModels/Pages/PageBase.cs +++ b/Needlework.Net/ViewModels/Pages/PageBase.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Mvvm.ComponentModel; +using System.Threading.Tasks; namespace Needlework.Net.ViewModels.Pages; @@ -8,4 +9,7 @@ public abstract partial class PageBase(string displayName, string icon, int inde [ObservableProperty] private string _displayName = displayName; [ObservableProperty] private string _icon = icon; [ObservableProperty] private int _index = index; + [ObservableProperty] private bool _isInitialized; + + public abstract Task InitializeAsync(); } \ No newline at end of file diff --git a/Needlework.Net/ViewModels/Pages/Websocket/WebsocketViewModel.cs b/Needlework.Net/ViewModels/Pages/Websocket/WebsocketViewModel.cs index ea51159..d54ad88 100644 --- a/Needlework.Net/ViewModels/Pages/Websocket/WebsocketViewModel.cs +++ b/Needlework.Net/ViewModels/Pages/Websocket/WebsocketViewModel.cs @@ -59,6 +59,12 @@ public partial class WebsocketViewModel : PageBase }); } + public override Task InitializeAsync() + { + IsInitialized = true; + return Task.CompletedTask; + } + private async Task InitializeEventTypes() { try