mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 08:56:14 +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>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
|
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
|
||||||
<PackageReference Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
<PackageReference Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
||||||
<PackageReference Include="Romzetron.Avalonia" Version="11.3.4" />
|
<PackageReference Include="Romzetron.Avalonia" Version="11.3.4" />
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ using EchoHub.Core.Constants;
|
|||||||
using EchoHub.Core.DTOs;
|
using EchoHub.Core.DTOs;
|
||||||
using EchoHub.Core.Models;
|
using EchoHub.Core.Models;
|
||||||
|
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
|
||||||
@@ -69,21 +72,61 @@ public sealed class MainWindowViewModel : ViewModelBase
|
|||||||
ConnectionService.Dispose();
|
ConnectionService.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddServer()
|
private async void AddServer()
|
||||||
{
|
{
|
||||||
ServerModel placeholderServer = new ServerModel(
|
if (_mainWindow is null)
|
||||||
Guid.NewGuid().ToString("N"),
|
{
|
||||||
"New Server",
|
return;
|
||||||
[],
|
}
|
||||||
isConnected: false);
|
|
||||||
|
|
||||||
ServerViewModel serverVm = new ServerViewModel(placeholderServer);
|
ClientConfig config = ConfigManager.Load();
|
||||||
serverVm.ConnectRequested += async () => await HandleServerConnectRequested(serverVm);
|
ConnectDialogWindow dialog = new ConnectDialogWindow(config.SavedServers);
|
||||||
serverVm.DisconnectRequested += async () => await HandleServerDisconnectRequested(serverVm);
|
ConnectDialogResult? result = await dialog.ShowDialog<ConnectDialogResult?>(_mainWindow);
|
||||||
serverVm.RemoveRequested += async () => await HandleServerRemoveRequested(serverVm);
|
if (result is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Sidebar.Servers.Add(serverVm);
|
try
|
||||||
StatusText = "Click Connect on the server to get started";
|
{
|
||||||
|
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()
|
private void WireCommandHandlerEvents()
|
||||||
@@ -397,13 +440,15 @@ public sealed class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
|
int insertIndex = Sidebar.Servers.Count;
|
||||||
ServerViewModel? existing = Sidebar.GetServer(server.ServerUrl);
|
ServerViewModel? existing = Sidebar.GetServer(server.ServerUrl);
|
||||||
if (existing is not null)
|
if (existing is not null)
|
||||||
{
|
{
|
||||||
|
insertIndex = Sidebar.Servers.IndexOf(existing);
|
||||||
_ = Sidebar.Servers.Remove(existing);
|
_ = Sidebar.Servers.Remove(existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sidebar.Servers.Add(serverVm);
|
Sidebar.Servers.Insert(insertIndex, serverVm);
|
||||||
if (serverVm.Channels.Count > 0)
|
if (serverVm.Channels.Count > 0)
|
||||||
{
|
{
|
||||||
serverVm.SelectedChannel = serverVm.Channels[0];
|
serverVm.SelectedChannel = serverVm.Channels[0];
|
||||||
@@ -625,7 +670,6 @@ public sealed class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
private async Task HandleServerConnectRequested(ServerViewModel serverVm)
|
private async Task HandleServerConnectRequested(ServerViewModel serverVm)
|
||||||
{
|
{
|
||||||
// Show connect dialog
|
|
||||||
if (_mainWindow is null)
|
if (_mainWindow is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -644,34 +688,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
serverVm.IsConnecting = true;
|
serverVm.IsConnecting = true;
|
||||||
StatusText = "Connecting...";
|
await ConnectAndSaveAsync(result);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ using Avalonia.Controls;
|
|||||||
|
|
||||||
using EchoHub.Client.Config;
|
using EchoHub.Client.Config;
|
||||||
|
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Decho.Views;
|
namespace Decho.Views;
|
||||||
@@ -16,7 +19,7 @@ public sealed partial class ConnectDialogWindow : Window
|
|||||||
_savedServers = [];
|
_savedServers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConnectDialogWindow(List<SavedServer> savedServers, SavedServer? prefill)
|
public ConnectDialogWindow(List<SavedServer> savedServers, SavedServer? prefill = null)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_savedServers = savedServers;
|
_savedServers = savedServers;
|
||||||
@@ -66,7 +69,8 @@ public sealed partial class ConnectDialogWindow : Window
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(user))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +94,8 @@ public sealed partial class ConnectDialogWindow : Window
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(pass))
|
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;
|
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 url = UrlBox.Text?.Trim() ?? "";
|
||||||
string user = UserBox.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))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,31 +137,6 @@ public sealed partial class ConnectDialogWindow : Window
|
|||||||
{
|
{
|
||||||
Close(null);
|
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
|
public sealed class ConnectDialogResult
|
||||||
|
|||||||
Reference in New Issue
Block a user