mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 08:56:14 +02:00
Refactor connection logic and add ViewExtensions for cleaner data context access
This commit is contained in:
@@ -35,61 +35,10 @@ public sealed class ConnectionService : IDisposable
|
||||
private readonly Dictionary<string, ServerConnection> _connections = new(StringComparer.OrdinalIgnoreCase);
|
||||
internal IReadOnlyDictionary<string, ServerConnection> Connections => _connections;
|
||||
|
||||
public async Task<ServerModel> ConnectAsync(string serverUrl, string username, string password, bool isRegister, bool rememberMe)
|
||||
private async Task<ServerModel> ConnectCoreAsync(ConnectDialogResult dialogResult)
|
||||
{
|
||||
ConnectionManager conn = new ConnectionManager();
|
||||
|
||||
ConnectDialogResult dialogResult = new EchoHub.Client.UI.Dialogs.ConnectDialogResult(
|
||||
serverUrl, username, password, isRegister, rememberMe, null);
|
||||
|
||||
ConnectResult result;
|
||||
try
|
||||
{
|
||||
result = await conn.ConnectAsync(dialogResult, _ => { });
|
||||
}
|
||||
catch
|
||||
{
|
||||
await conn.DisposeAsync();
|
||||
throw;
|
||||
}
|
||||
|
||||
LoginResponse login = result.Login;
|
||||
UserModel userModel = new UserModel(login.Username, login.DisplayName ?? login.Username,
|
||||
login.NicknameColor);
|
||||
|
||||
ObservableCollection<ChannelModel> channels = [];
|
||||
ServerModel serverModel = new ServerModel(
|
||||
Guid.NewGuid().ToString("N"),
|
||||
new Uri(serverUrl).Host,
|
||||
channels,
|
||||
serverUrl,
|
||||
isConnected: true,
|
||||
connectedUser: login.Username);
|
||||
|
||||
ServerConnection serverEntry = new ServerConnection(conn, conn.Api!, serverModel, userModel);
|
||||
|
||||
foreach (ChannelDto ch in result.Channels)
|
||||
{
|
||||
ChannelModel channelModel = ChannelModelFromDto(ch);
|
||||
channels.Add(channelModel);
|
||||
}
|
||||
|
||||
WireConnectionEvents(serverEntry, conn);
|
||||
|
||||
_connections[serverUrl] = serverEntry;
|
||||
SaveRefreshToken(serverUrl, rememberMe);
|
||||
ServerAdded?.Invoke(serverModel);
|
||||
|
||||
return serverModel;
|
||||
}
|
||||
|
||||
public async Task ConnectWithSavedTokenAsync(string serverUrl, string username, string refreshToken, bool rememberMe)
|
||||
{
|
||||
ConnectionManager conn = new ConnectionManager();
|
||||
|
||||
ConnectDialogResult dialogResult = new EchoHub.Client.UI.Dialogs.ConnectDialogResult(
|
||||
serverUrl, username, "", false, rememberMe, refreshToken);
|
||||
|
||||
ConnectResult result;
|
||||
try
|
||||
{
|
||||
@@ -107,9 +56,9 @@ public sealed class ConnectionService : IDisposable
|
||||
ObservableCollection<ChannelModel> channels = [];
|
||||
ServerModel serverModel = new ServerModel(
|
||||
Guid.NewGuid().ToString("N"),
|
||||
new Uri(serverUrl).Host,
|
||||
new Uri(dialogResult.ServerUrl).Host,
|
||||
channels,
|
||||
serverUrl,
|
||||
dialogResult.ServerUrl,
|
||||
isConnected: true,
|
||||
connectedUser: login.Username);
|
||||
|
||||
@@ -123,16 +72,32 @@ public sealed class ConnectionService : IDisposable
|
||||
|
||||
WireConnectionEvents(serverEntry, conn);
|
||||
|
||||
_connections[serverUrl] = serverEntry;
|
||||
SaveRefreshToken(serverUrl, rememberMe);
|
||||
_connections[dialogResult.ServerUrl] = serverEntry;
|
||||
SaveRefreshToken(dialogResult.ServerUrl, dialogResult.RememberMe);
|
||||
ServerAdded?.Invoke(serverModel);
|
||||
|
||||
return serverModel;
|
||||
}
|
||||
|
||||
public async Task DisconnectAsync(string serverUrl)
|
||||
public async Task<ServerModel> ConnectAsync(string serverUrl, string username, string password, bool isRegister, bool rememberMe)
|
||||
{
|
||||
ConnectDialogResult dialogResult = new ConnectDialogResult(
|
||||
serverUrl, username, password, isRegister, rememberMe, null);
|
||||
return await ConnectCoreAsync(dialogResult);
|
||||
}
|
||||
|
||||
public async Task ConnectWithSavedTokenAsync(string serverUrl, string username, string refreshToken, bool rememberMe)
|
||||
{
|
||||
ConnectDialogResult dialogResult = new ConnectDialogResult(
|
||||
serverUrl, username, "", false, rememberMe, refreshToken);
|
||||
await ConnectCoreAsync(dialogResult);
|
||||
}
|
||||
|
||||
private async Task<ServerConnection?> CleanupConnectionAsync(string serverUrl)
|
||||
{
|
||||
if (!_connections.TryGetValue(serverUrl, out ServerConnection? entry))
|
||||
{
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
entry.Server.IsConnected = false;
|
||||
@@ -143,37 +108,43 @@ public sealed class ConnectionService : IDisposable
|
||||
await entry.Manager.DisposeAsync();
|
||||
|
||||
_ = _connections.Remove(serverUrl);
|
||||
ServerStateChanged?.Invoke(entry.Server);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public async Task DisconnectAsync(string serverUrl)
|
||||
{
|
||||
ServerConnection? entry = await CleanupConnectionAsync(serverUrl);
|
||||
if (entry is not null)
|
||||
{
|
||||
ServerStateChanged?.Invoke(entry.Server);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RemoveServerAsync(string serverUrl)
|
||||
{
|
||||
if (_connections.TryGetValue(serverUrl, out ServerConnection? entry))
|
||||
{
|
||||
entry.Server.IsConnected = false;
|
||||
entry.Server.IsConnecting = false;
|
||||
|
||||
await entry.Manager.CleanupAsync();
|
||||
entry.ApiClient.Dispose();
|
||||
await entry.Manager.DisposeAsync();
|
||||
|
||||
_ = _connections.Remove(serverUrl);
|
||||
}
|
||||
|
||||
await CleanupConnectionAsync(serverUrl);
|
||||
RemoveServerFromConfig(serverUrl);
|
||||
ServerRemoved?.Invoke(serverUrl);
|
||||
}
|
||||
|
||||
private static void RemoveServerFromConfig(string serverUrl)
|
||||
private static void ModifyConfig(string serverUrl, Action<ClientConfig, SavedServer?> action)
|
||||
{
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
SavedServer? saved = config.SavedServers.FirstOrDefault(s =>
|
||||
string.Equals(s.Url, serverUrl, StringComparison.OrdinalIgnoreCase));
|
||||
if (saved is not null)
|
||||
action(config, saved);
|
||||
ConfigManager.Save(config);
|
||||
}
|
||||
|
||||
private static void RemoveServerFromConfig(string serverUrl)
|
||||
{
|
||||
ModifyConfig(serverUrl, (config, saved) =>
|
||||
{
|
||||
_ = config.SavedServers.Remove(saved);
|
||||
ConfigManager.Save(config);
|
||||
}
|
||||
if (saved is not null)
|
||||
{
|
||||
_ = config.SavedServers.Remove(saved);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string serverUrl, string channelName, string content)
|
||||
@@ -554,25 +525,24 @@ public sealed class ConnectionService : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
SavedServer? saved = config.SavedServers.FirstOrDefault(s =>
|
||||
string.Equals(s.Url, serverUrl, StringComparison.OrdinalIgnoreCase));
|
||||
if (saved is null)
|
||||
ModifyConfig(serverUrl, (config, saved) =>
|
||||
{
|
||||
saved = new SavedServer
|
||||
if (saved is null)
|
||||
{
|
||||
Name = new Uri(serverUrl).Host,
|
||||
Url = serverUrl,
|
||||
Username = entry.User.Id,
|
||||
RememberMe = true,
|
||||
LastConnected = DateTimeOffset.Now,
|
||||
};
|
||||
config.SavedServers.Add(saved);
|
||||
}
|
||||
saved = new SavedServer
|
||||
{
|
||||
Name = new Uri(serverUrl).Host,
|
||||
Url = serverUrl,
|
||||
Username = entry.User.Id,
|
||||
RememberMe = true,
|
||||
LastConnected = DateTimeOffset.Now,
|
||||
};
|
||||
config.SavedServers.Add(saved);
|
||||
}
|
||||
|
||||
saved.RefreshToken = token;
|
||||
saved.LastConnected = DateTimeOffset.Now;
|
||||
ConfigManager.Save(config);
|
||||
saved.RefreshToken = token;
|
||||
saved.LastConnected = DateTimeOffset.Now;
|
||||
});
|
||||
}
|
||||
|
||||
private void WireConnectionEvents(ServerConnection entry, ConnectionManager conn)
|
||||
|
||||
@@ -74,14 +74,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
|
||||
private async void AddServer()
|
||||
{
|
||||
if (_mainWindow is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
ConnectDialogWindow dialog = new ConnectDialogWindow(config.SavedServers);
|
||||
ConnectDialogResult? result = await dialog.ShowDialog<ConnectDialogResult?>(_mainWindow);
|
||||
ConnectDialogResult? result = await ShowConnectDialogAsync(null);
|
||||
if (result is null)
|
||||
{
|
||||
return;
|
||||
@@ -129,6 +122,20 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ConfigManager.SaveServer(savedServer);
|
||||
}
|
||||
|
||||
private async Task<ConnectDialogResult?> ShowConnectDialogAsync(SavedServer? prefill)
|
||||
{
|
||||
if (_mainWindow is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
ConnectDialogWindow dialog = prefill is null
|
||||
? new ConnectDialogWindow(config.SavedServers)
|
||||
: new ConnectDialogWindow(config.SavedServers, prefill);
|
||||
return await dialog.ShowDialog<ConnectDialogResult?>(_mainWindow);
|
||||
}
|
||||
|
||||
private void WireCommandHandlerEvents()
|
||||
{
|
||||
_commandHandler.OnSetStatus += async (status, message) =>
|
||||
@@ -670,16 +677,9 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
|
||||
private async Task HandleServerConnectRequested(ServerViewModel serverVm)
|
||||
{
|
||||
if (_mainWindow is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
SavedServer? prefill = config.SavedServers.FirstOrDefault(s =>
|
||||
SavedServer? prefill = ConfigManager.Load().SavedServers.FirstOrDefault(s =>
|
||||
string.Equals(s.Url, serverVm.ServerUrl, StringComparison.OrdinalIgnoreCase));
|
||||
ConnectDialogWindow dialog = new ConnectDialogWindow(config.SavedServers, prefill);
|
||||
ConnectDialogResult? result = await dialog.ShowDialog<ConnectDialogResult?>(_mainWindow);
|
||||
ConnectDialogResult? result = await ShowConnectDialogAsync(prefill);
|
||||
if (result is null)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,8 @@ public partial class MessageComposerView : UserControl
|
||||
|
||||
private async void OnFileUploadClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MessageComposerViewModel vm)
|
||||
MessageComposerViewModel? vm = this.GetDataContext<MessageComposerViewModel>();
|
||||
if (vm is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -55,7 +56,8 @@ public partial class MessageComposerView : UserControl
|
||||
|
||||
private void OnDrop(object? sender, DragEventArgs e)
|
||||
{
|
||||
if (DataContext is not MessageComposerViewModel vm)
|
||||
MessageComposerViewModel? vm = this.GetDataContext<MessageComposerViewModel>();
|
||||
if (vm is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ public partial class MessageItemView : UserControl
|
||||
{
|
||||
try
|
||||
{
|
||||
TopLevel? topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel?.DataContext is not MainWindowViewModel mainVm)
|
||||
MainWindowViewModel? mainVm = this.GetMainWindowViewModel();
|
||||
if (mainVm is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -73,13 +73,14 @@ public partial class MessageItemView : UserControl
|
||||
|
||||
private async void OnAuthorNamePointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MessageViewModel msg)
|
||||
MessageViewModel? msg = this.GetDataContext<MessageViewModel>();
|
||||
if (msg is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TopLevel? topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel?.DataContext is not MainWindowViewModel mainVm)
|
||||
MainWindowViewModel? mainVm = this.GetMainWindowViewModel();
|
||||
if (mainVm is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -94,7 +95,7 @@ public partial class MessageItemView : UserControl
|
||||
|
||||
ProfileWindow dialog = new ProfileWindow(profile);
|
||||
|
||||
if (topLevel is Window parent)
|
||||
if (TopLevel.GetTopLevel(this) is Window parent)
|
||||
{
|
||||
await dialog.ShowDialog(parent);
|
||||
}
|
||||
@@ -102,7 +103,8 @@ public partial class MessageItemView : UserControl
|
||||
|
||||
private async void OnDownloadClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MessageViewModel msg)
|
||||
MessageViewModel? msg = this.GetDataContext<MessageViewModel>();
|
||||
if (msg is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -118,7 +120,8 @@ public partial class MessageItemView : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
if (topLevel.DataContext is not MainWindowViewModel mainVm)
|
||||
MainWindowViewModel? mainVm = this.GetMainWindowViewModel();
|
||||
if (mainVm is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
using Decho.ViewModels;
|
||||
|
||||
namespace Decho.Views;
|
||||
|
||||
internal static class ViewExtensions
|
||||
{
|
||||
public static T? GetDataContext<T>(this Control control) where T : class
|
||||
=> control.DataContext as T;
|
||||
|
||||
public static MainWindowViewModel? GetMainWindowViewModel(this Control control)
|
||||
=> TopLevel.GetTopLevel(control)?.DataContext as MainWindowViewModel;
|
||||
}
|
||||
Reference in New Issue
Block a user