mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 00:46:11 +02:00
Add MessageBox.Avalonia and show error dialog on connection failure
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
|
||||
<PackageReference Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
||||
<PackageReference Include="Romzetron.Avalonia" Version="11.3.4" />
|
||||
|
||||
@@ -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<ConnectDialogResult?>(_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)
|
||||
{
|
||||
|
||||
@@ -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<SavedServer> savedServers, SavedServer? prefill)
|
||||
public ConnectDialogWindow(List<SavedServer> 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
|
||||
|
||||
Reference in New Issue
Block a user