diff --git a/Needlework.Net/Messages/OopsiesWindowRequestedMessage.cs b/Needlework.Net/Messages/OopsiesDialogRequestedMessage.cs similarity index 67% rename from Needlework.Net/Messages/OopsiesWindowRequestedMessage.cs rename to Needlework.Net/Messages/OopsiesDialogRequestedMessage.cs index 15211ef..8659bad 100644 --- a/Needlework.Net/Messages/OopsiesWindowRequestedMessage.cs +++ b/Needlework.Net/Messages/OopsiesDialogRequestedMessage.cs @@ -2,7 +2,7 @@ namespace Needlework.Net.Messages { - public class OopsiesWindowRequestedMessage(string text) : ValueChangedMessage(text) + public class OopsiesDialogRequestedMessage(string text) : ValueChangedMessage(text) { } } diff --git a/Needlework.Net/Messages/OopsiesWindowCanceledMessage.cs b/Needlework.Net/Messages/OopsiesWindowCanceledMessage.cs deleted file mode 100644 index bf17266..0000000 --- a/Needlework.Net/Messages/OopsiesWindowCanceledMessage.cs +++ /dev/null @@ -1,8 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging.Messages; - -namespace Needlework.Net.Messages -{ - public class OopsiesWindowCanceledMessage(object? data) : ValueChangedMessage(data) - { - } -} diff --git a/Needlework.Net/Needlework.Net.csproj b/Needlework.Net/Needlework.Net.csproj index 93fd484..87abe05 100644 --- a/Needlework.Net/Needlework.Net.csproj +++ b/Needlework.Net/Needlework.Net.csproj @@ -55,9 +55,6 @@ EndpointView.axaml - - OopsiesWindow.axaml - diff --git a/Needlework.Net/Program.cs b/Needlework.Net/Program.cs index 69f7fe5..46c9a8c 100644 --- a/Needlework.Net/Program.cs +++ b/Needlework.Net/Program.cs @@ -6,7 +6,6 @@ using Needlework.Net.ViewModels; using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; using System; -using System.Linq; namespace Needlework.Net; @@ -36,9 +35,9 @@ class Program var builder = new ServiceCollection(); builder.AddSingleton(); - builder.AddSingleton(); + builder.AddSingleton(); builder.AddSingletonsFromAssemblies(); - + builder.AddHttpClient(); var services = builder.BuildServiceProvider(); diff --git a/Needlework.Net/Services/DialogService.cs b/Needlework.Net/Services/DialogService.cs new file mode 100644 index 0000000..0df4b00 --- /dev/null +++ b/Needlework.Net/Services/DialogService.cs @@ -0,0 +1,20 @@ +using FluentAvalonia.UI.Controls; +using System; +using System.Threading.Tasks; + +namespace Needlework.Net.Services +{ + public class DialogService + { + public async Task ShowAsync(object data) + where T : IDialog, IDisposable + { + T dialog = Activator.CreateInstance(); + + var result = await dialog.ShowAsync(data); + dialog.Dispose(); + + return result; + } + } +} diff --git a/Needlework.Net/Services/IDialog.cs b/Needlework.Net/Services/IDialog.cs new file mode 100644 index 0000000..1132280 --- /dev/null +++ b/Needlework.Net/Services/IDialog.cs @@ -0,0 +1,10 @@ +using FluentAvalonia.UI.Controls; +using System.Threading.Tasks; + +namespace Needlework.Net.Services +{ + public interface IDialog + { + public Task ShowAsync(object data); + } +} diff --git a/Needlework.Net/Services/WindowService.cs b/Needlework.Net/Services/WindowService.cs deleted file mode 100644 index fdb28c2..0000000 --- a/Needlework.Net/Services/WindowService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using CommunityToolkit.Mvvm.Messaging; -using Needlework.Net.Messages; -using Needlework.Net.ViewModels; -using Needlework.Net.Views; -using System; - -namespace Needlework.Net.Services -{ - public class WindowService : IRecipient - { - public IServiceProvider ServiceProvider { get; } - - public OopsiesWindow? OopsiesWindow { get; set; } - - public WindowService(IServiceProvider serviceProvider) - { - ServiceProvider = serviceProvider; - - WeakReferenceMessenger.Default.Register(this); - } - - public void ShowOopsiesWindow(string text) - { - if (OopsiesWindow != null) OopsiesWindow!.Close(); - - var window = new OopsiesWindow(); - window.DataContext = new OopsiesWindowViewModel(text); - window.Show(App.MainWindow!); - window.Closed += OnOopsiesWindowClosed; - OopsiesWindow = window; - } - - public void OnOopsiesWindowClosed(object? sender, EventArgs e) - { - if (sender == null) return; - - var window = (OopsiesWindow)sender; - window.DataContext = null; - window.Closed -= OnOopsiesWindowClosed; - OopsiesWindow = null; - } - - public void Receive(OopsiesWindowCanceledMessage message) - { - if (OopsiesWindow is OopsiesWindow window) window.Close(); - } - } -} diff --git a/Needlework.Net/ViewModels/ConsoleViewModel.cs b/Needlework.Net/ViewModels/ConsoleViewModel.cs index fe46602..abadfbd 100644 --- a/Needlework.Net/ViewModels/ConsoleViewModel.cs +++ b/Needlework.Net/ViewModels/ConsoleViewModel.cs @@ -4,7 +4,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using Needlework.Net.Messages; -using Needlework.Net.Services; using System; using System.Net.Http; using System.Text.Json; @@ -26,12 +25,8 @@ namespace Needlework.Net.ViewModels [ObservableProperty] private string? _responseStatus = null; [ObservableProperty] private string? _responseAuthorization = null; - public WindowService WindowService { get; } - - public ConsoleViewModel(WindowService windowService) : base("Console", "terminal", -200) + public ConsoleViewModel() : base("Console", "terminal", -200) { - WindowService = windowService; - WeakReferenceMessenger.Default.Register(this); } @@ -62,15 +57,15 @@ namespace Needlework.Net.ViewModels var response = await Connector.SendAsync(method, RequestPath, 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) { - WindowService.ShowOopsiesWindow(body); + 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}"; diff --git a/Needlework.Net/ViewModels/MainWindowViewModel.cs b/Needlework.Net/ViewModels/MainWindowViewModel.cs index cd7ca50..711d1dd 100644 --- a/Needlework.Net/ViewModels/MainWindowViewModel.cs +++ b/Needlework.Net/ViewModels/MainWindowViewModel.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Models; using Needlework.Net.Messages; using Needlework.Net.Models; using Needlework.Net.Services; +using Needlework.Net.Views; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -20,7 +21,8 @@ using System.Threading.Tasks; namespace Needlework.Net.ViewModels { - public partial class MainWindowViewModel : ObservableObject, IRecipient, IRecipient, IRecipient, IRecipient + public partial class MainWindowViewModel + : ObservableObject, IRecipient, IRecipient, IRecipient, IRecipient { public IAvaloniaReadOnlyList MenuItems { get; } [NotifyPropertyChangedFor(nameof(CurrentPage))] @@ -31,7 +33,7 @@ namespace Needlework.Net.ViewModels [ObservableProperty] private bool _isUpdateShown = false; public HttpClient HttpClient { get; } - public WindowService WindowService { get; } + public DialogService DialogService { get; } public OpenApiDocumentWrapper? OpenApiDocumentWrapper { get; set; } public OpenApiDocument? HostDocument { get; set; } @@ -39,7 +41,7 @@ namespace Needlework.Net.ViewModels [ObservableProperty] private ObservableCollection _infoBarItems = []; - public MainWindowViewModel(IEnumerable pages, HttpClient httpClient, WindowService windowService) + public MainWindowViewModel(IEnumerable pages, HttpClient httpClient, DialogService dialogService) { MenuItems = new AvaloniaList(pages .OrderBy(p => p.Index) @@ -53,7 +55,7 @@ namespace Needlework.Net.ViewModels SelectedMenuItem = MenuItems[0]; HttpClient = httpClient; - WindowService = windowService; + DialogService = dialogService; WeakReferenceMessenger.Default.RegisterAll(this); @@ -135,11 +137,6 @@ namespace Needlework.Net.ViewModels process.Start(); } - public void Receive(OopsiesWindowRequestedMessage message) - { - WindowService.ShowOopsiesWindow(message.Value); - } - public void Receive(InfoBarUpdateMessage message) { Avalonia.Threading.Dispatcher.UIThread.Post(async () => await ShowInfoBarAsync(message.Value)); @@ -151,5 +148,10 @@ namespace Needlework.Net.ViewModels await Task.Delay(vm.Duration); InfoBarItems.Remove(vm); } + + public void Receive(OopsiesDialogRequestedMessage message) + { + Avalonia.Threading.Dispatcher.UIThread.Invoke(async () => await DialogService.ShowAsync(message.Value)); + } } } diff --git a/Needlework.Net/ViewModels/OopsiesWindowViewModel.cs b/Needlework.Net/ViewModels/OopsiesWindowViewModel.cs deleted file mode 100644 index 10ad622..0000000 --- a/Needlework.Net/ViewModels/OopsiesWindowViewModel.cs +++ /dev/null @@ -1,29 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.Mvvm.Messaging; -using Needlework.Net.Messages; -using System.Diagnostics; -using System.IO; - -namespace Needlework.Net.ViewModels -{ - public partial class OopsiesWindowViewModel(string text) : ObservableObject - { - public string Text { get; } = text; - - [RelayCommand] - private void OpenDefaultEditor() - { - var temp = Path.GetTempFileName().Replace(".tmp", ".json"); - File.WriteAllText(temp, Text); - Process.Start("explorer", "\"" + temp + "\""); - CloseDialog(); - } - - [RelayCommand] - private void CloseDialog() - { - WeakReferenceMessenger.Default.Send(new OopsiesWindowCanceledMessage(null)); - } - } -} diff --git a/Needlework.Net/ViewModels/PathOperationViewModel.cs b/Needlework.Net/ViewModels/PathOperationViewModel.cs index cfb748d..2482058 100644 --- a/Needlework.Net/ViewModels/PathOperationViewModel.cs +++ b/Needlework.Net/ViewModels/PathOperationViewModel.cs @@ -106,7 +106,7 @@ namespace Needlework.Net.ViewModels var responseBody = responseBytes.Length > 0 ? JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBytes), App.JsonSerializerOptions) : string.Empty; if (responseBody.Length >= App.MaxCharacters) { - WeakReferenceMessenger.Default.Send(new OopsiesWindowRequestedMessage(responseBody)); + WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(responseBody)); WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(string.Empty, "EndpointResponseEditor"))); } else WeakReferenceMessenger.Default.Send(new EditorUpdateMessage(new(responseBody, "EndpointResponseEditor"))); diff --git a/Needlework.Net/ViewModels/WebsocketViewModel.cs b/Needlework.Net/ViewModels/WebsocketViewModel.cs index 974deb0..5717bf4 100644 --- a/Needlework.Net/ViewModels/WebsocketViewModel.cs +++ b/Needlework.Net/ViewModels/WebsocketViewModel.cs @@ -3,7 +3,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using Needlework.Net.Messages; -using Needlework.Net.Services; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -30,13 +29,10 @@ namespace Needlework.Net.ViewModels public WebsocketClient? Client { get; set; } - public WindowService WindowService { get; } - public IReadOnlyList FilteredEventLog => string.IsNullOrWhiteSpace(Search) ? EventLog : [.. EventLog.Where(x => x.Contains(Search, StringComparison.InvariantCultureIgnoreCase))]; - public WebsocketViewModel(WindowService windowService) : base("Event Viewer", "plug", -100) + public WebsocketViewModel() : base("Event Viewer", "plug", -100) { - WindowService = windowService; EventLog.CollectionChanged += (s, e) => OnPropertyChanged(nameof(FilteredEventLog)); var thread = new Thread(InitializeWebsocket) { IsBackground = true }; thread.Start(); @@ -76,7 +72,7 @@ namespace Needlework.Net.ViewModels if (_events.TryGetValue(value, out var message)) { var text = JsonSerializer.Serialize(message, App.JsonSerializerOptions); - if (text.Length >= App.MaxCharacters) WindowService.ShowOopsiesWindow(text); + if (text.Length >= App.MaxCharacters) WeakReferenceMessenger.Default.Send(new OopsiesDialogRequestedMessage(text)); else WeakReferenceMessenger.Default.Send(new ResponseUpdatedMessage(text), nameof(WebsocketViewModel)); } } diff --git a/Needlework.Net/Views/ConsoleView.axaml b/Needlework.Net/Views/ConsoleView.axaml index 5e7269d..92c5b21 100644 --- a/Needlework.Net/Views/ConsoleView.axaml +++ b/Needlework.Net/Views/ConsoleView.axaml @@ -3,6 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit" + xmlns:ui="using:FluentAvalonia.UI.Controls" + xmlns:uip="using:FluentAvalonia.UI.Controls.Primitives" xmlns:vm="using:Needlework.Net.ViewModels" xmlns:controls="using:Needlework.Net.Controls" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" diff --git a/Needlework.Net/Views/OopsiesDialog.cs b/Needlework.Net/Views/OopsiesDialog.cs new file mode 100644 index 0000000..8e55a07 --- /dev/null +++ b/Needlework.Net/Views/OopsiesDialog.cs @@ -0,0 +1,65 @@ +using FluentAvalonia.UI.Controls; +using Needlework.Net.Services; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; + +namespace Needlework.Net.Views +{ + public class OopsiesDialog : IDialog, IDisposable + { + private bool _isDisposing; + private string? _text; + private ContentDialog _dialog; + + public OopsiesDialog() + { + _dialog = new ContentDialog + { + PrimaryButtonText = "Open", + CloseButtonText = "Cancel", + Title = "Oopsies", + Content = "This response is too large to handle for performance reasons.\nIt can be viewed in an external editor or viewer.", + IsPrimaryButtonEnabled = true, + IsSecondaryButtonEnabled = false, + DefaultButton = ContentDialogButton.Primary + }; + _dialog.PrimaryButtonClick += OnPrimaryButtonClick; + } + + public async Task ShowAsync(object data) + { + _text = (string)data; + var result = await _dialog.ShowAsync(); + return result; + } + + private void OnPrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) + { + var temp = Path.GetTempFileName().Replace(".tmp", ".json"); + File.WriteAllText(temp, _text); + Process.Start("explorer", "\"" + temp + "\""); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposing) + { + if (disposing) + { + _text = null; + _dialog.PrimaryButtonClick -= OnPrimaryButtonClick; + } + + _isDisposing = true; + } + } + } +} \ No newline at end of file diff --git a/Needlework.Net/Views/OopsiesWindow.axaml b/Needlework.Net/Views/OopsiesWindow.axaml deleted file mode 100644 index e6f2469..0000000 --- a/Needlework.Net/Views/OopsiesWindow.axaml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - Needlework.Net - Oopsies - - - - - This response is too large for Needlework.Net to handle for performance reasons. - - - It can be viewed in an external editor or viewer. - - - - - - diff --git a/Needlework.Net/Views/OopsiesWindow.axaml.cs b/Needlework.Net/Views/OopsiesWindow.axaml.cs deleted file mode 100644 index c2f42fc..0000000 --- a/Needlework.Net/Views/OopsiesWindow.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentAvalonia.UI.Windowing; - -namespace Needlework.Net.Views; - -public partial class OopsiesWindow : AppWindow -{ - public OopsiesWindow() - { - InitializeComponent(); - - TitleBar.ExtendsContentIntoTitleBar = true; - } -} \ No newline at end of file