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