From 39c7fe4f4898f3b288d54aeaf5142d1b518dca0b Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Thu, 16 Jul 2026 00:46:42 +0200 Subject: [PATCH] Add MessageBox.Avalonia and show error dialog on connection failure --- src/Decho/Decho.csproj | 1 + src/Decho/ViewModels/MainWindowViewModel.cs | 101 +++++++++++-------- src/Decho/Views/ConnectDialogWindow.axaml.cs | 41 ++------ 3 files changed, 71 insertions(+), 72 deletions(-) diff --git a/src/Decho/Decho.csproj b/src/Decho/Decho.csproj index 8e95244..f955f84 100644 --- a/src/Decho/Decho.csproj +++ b/src/Decho/Decho.csproj @@ -23,6 +23,7 @@ None All + diff --git a/src/Decho/ViewModels/MainWindowViewModel.cs b/src/Decho/ViewModels/MainWindowViewModel.cs index c25fa43..b9118ab 100644 --- a/src/Decho/ViewModels/MainWindowViewModel.cs +++ b/src/Decho/ViewModels/MainWindowViewModel.cs @@ -10,6 +10,9 @@ using EchoHub.Core.Constants; using EchoHub.Core.DTOs; using EchoHub.Core.Models; +using MsBox.Avalonia; +using MsBox.Avalonia.Enums; + using System.Reactive; using System.Reactive.Linq; @@ -69,21 +72,61 @@ public sealed class MainWindowViewModel : ViewModelBase ConnectionService.Dispose(); } - private void AddServer() + private async void AddServer() { - ServerModel placeholderServer = new ServerModel( - Guid.NewGuid().ToString("N"), - "New Server", - [], - isConnected: false); + if (_mainWindow is null) + { + return; + } - ServerViewModel serverVm = new ServerViewModel(placeholderServer); - serverVm.ConnectRequested += async () => await HandleServerConnectRequested(serverVm); - serverVm.DisconnectRequested += async () => await HandleServerDisconnectRequested(serverVm); - serverVm.RemoveRequested += async () => await HandleServerRemoveRequested(serverVm); + ClientConfig config = ConfigManager.Load(); + ConnectDialogWindow dialog = new ConnectDialogWindow(config.SavedServers); + ConnectDialogResult? result = await dialog.ShowDialog(_mainWindow); + if (result is null) + { + return; + } - Sidebar.Servers.Add(serverVm); - StatusText = "Click Connect on the server to get started"; + try + { + await ConnectAndSaveAsync(result); + } + catch (Exception ex) + { + var box = MessageBoxManager.GetMessageBoxStandard( + "Connection Failed", + $"Could not connect to server:\n{ex.Message}", + ButtonEnum.Ok); + await box.ShowWindowDialogAsync(_mainWindow); + } + } + + private async Task ConnectAndSaveAsync(ConnectDialogResult result) + { + StatusText = "Connecting..."; + + if (result.IsSavedSession && result.SavedRefreshToken is not null) + { + await ConnectionService.ConnectWithSavedTokenAsync( + result.ServerUrl, result.Username, result.SavedRefreshToken, result.RememberMe); + } + else + { + _ = await ConnectionService.ConnectAsync( + result.ServerUrl, result.Username, result.Password, result.IsRegister, result.RememberMe); + } + + string? refreshToken = ConnectionService.GetRefreshToken(result.ServerUrl); + SavedServer savedServer = new SavedServer + { + Name = new Uri(result.ServerUrl).Host, + Url = result.ServerUrl, + Username = result.Username, + RefreshToken = result.RememberMe ? refreshToken : null, + RememberMe = result.RememberMe, + LastConnected = DateTimeOffset.Now, + }; + ConfigManager.SaveServer(savedServer); } private void WireCommandHandlerEvents() @@ -397,13 +440,15 @@ public sealed class MainWindowViewModel : ViewModelBase Avalonia.Threading.Dispatcher.UIThread.Post(() => { + int insertIndex = Sidebar.Servers.Count; ServerViewModel? existing = Sidebar.GetServer(server.ServerUrl); if (existing is not null) { + insertIndex = Sidebar.Servers.IndexOf(existing); _ = Sidebar.Servers.Remove(existing); } - Sidebar.Servers.Add(serverVm); + Sidebar.Servers.Insert(insertIndex, serverVm); if (serverVm.Channels.Count > 0) { serverVm.SelectedChannel = serverVm.Channels[0]; @@ -625,7 +670,6 @@ public sealed class MainWindowViewModel : ViewModelBase private async Task HandleServerConnectRequested(ServerViewModel serverVm) { - // Show connect dialog if (_mainWindow is null) { return; @@ -644,34 +688,7 @@ public sealed class MainWindowViewModel : ViewModelBase try { serverVm.IsConnecting = true; - StatusText = "Connecting..."; - - if (result.IsSavedSession && result.SavedRefreshToken is not null) - { - await ConnectionService.ConnectWithSavedTokenAsync( - result.ServerUrl, result.Username, result.SavedRefreshToken, result.RememberMe); - } - else - { - _ = await ConnectionService.ConnectAsync( - result.ServerUrl, result.Username, result.Password, result.IsRegister, result.RememberMe); - } - - // Remove the placeholder and let the real server added event handle it - Sidebar.RemoveServer(serverVm.ServerUrl); - - // Save to config with refresh token - string? refreshToken = ConnectionService.GetRefreshToken(result.ServerUrl); - SavedServer savedServer = new SavedServer - { - Name = new Uri(result.ServerUrl).Host, - Url = result.ServerUrl, - Username = result.Username, - RefreshToken = result.RememberMe ? refreshToken : null, - RememberMe = result.RememberMe, - LastConnected = DateTimeOffset.Now, - }; - ConfigManager.SaveServer(savedServer); + await ConnectAndSaveAsync(result); } catch (Exception ex) { diff --git a/src/Decho/Views/ConnectDialogWindow.axaml.cs b/src/Decho/Views/ConnectDialogWindow.axaml.cs index d8bf163..1fa8a9b 100644 --- a/src/Decho/Views/ConnectDialogWindow.axaml.cs +++ b/src/Decho/Views/ConnectDialogWindow.axaml.cs @@ -2,6 +2,9 @@ using Avalonia.Controls; using EchoHub.Client.Config; +using MsBox.Avalonia; +using MsBox.Avalonia.Enums; + using System.Linq; namespace Decho.Views; @@ -16,7 +19,7 @@ public sealed partial class ConnectDialogWindow : Window _savedServers = []; } - public ConnectDialogWindow(List savedServers, SavedServer? prefill) + public ConnectDialogWindow(List savedServers, SavedServer? prefill = null) { InitializeComponent(); _savedServers = savedServers; @@ -66,7 +69,8 @@ public sealed partial class ConnectDialogWindow : Window if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(user)) { - await ShowMessageBox("Validation", "Server URL and username are required."); + var box = MessageBoxManager.GetMessageBoxStandard("Validation", "Server URL and username are required.", ButtonEnum.Ok); + await box.ShowWindowDialogAsync(this); return; } @@ -90,7 +94,8 @@ public sealed partial class ConnectDialogWindow : Window { if (string.IsNullOrEmpty(pass)) { - await ShowMessageBox("Validation", "Password is required."); + var box = MessageBoxManager.GetMessageBoxStandard("Validation", "Password is required.", ButtonEnum.Ok); + await box.ShowWindowDialogAsync(this); return; } @@ -105,7 +110,7 @@ public sealed partial class ConnectDialogWindow : Window } } - private void OnRegisterClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + private async void OnRegisterClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) { string url = UrlBox.Text?.Trim() ?? ""; string user = UserBox.Text?.Trim() ?? ""; @@ -113,7 +118,8 @@ public sealed partial class ConnectDialogWindow : Window if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pass)) { - _ = ShowMessageBox("Validation", "Server URL, username, and password are required."); + var box = MessageBoxManager.GetMessageBoxStandard("Validation", "Server URL, username, and password are required.", ButtonEnum.Ok); + await box.ShowWindowDialogAsync(this); return; } @@ -131,31 +137,6 @@ public sealed partial class ConnectDialogWindow : Window { Close(null); } - - private async Task ShowMessageBox(string title, string message) - { - Window msgBox = new Window - { - Title = title, - Width = 350, - Height = 150, - WindowStartupLocation = WindowStartupLocation.CenterOwner, - CanResize = false, - }; - - StackPanel stack = new StackPanel { Spacing = 10, Margin = new Avalonia.Thickness(15) }; - stack.Children.Add(new TextBlock { Text = message, TextWrapping = Avalonia.Media.TextWrapping.Wrap }); - Button okBtn = new Button { Content = "OK", HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center }; - stack.Children.Add(okBtn); - msgBox.Content = stack; - - TaskCompletionSource tcs = new TaskCompletionSource(); - okBtn.Click += (_, _) => { msgBox.Close(); _ = tcs.TrySetResult(); }; - msgBox.Closed += (_, _) => tcs.TrySetResult(); - - await msgBox.ShowDialog(this); - await tcs.Task; - } } public sealed class ConnectDialogResult