mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 00:46:11 +02:00
Add option to remove server and disable input TextBox on channels of disconnected servers
This commit is contained in:
@@ -137,16 +137,45 @@ public sealed class ConnectionService : IDisposable
|
||||
|
||||
entry.Server.IsConnected = false;
|
||||
entry.Server.IsConnecting = false;
|
||||
ServerStateChanged?.Invoke(entry.Server);
|
||||
|
||||
await entry.Manager.CleanupAsync();
|
||||
entry.ApiClient.Dispose();
|
||||
await entry.Manager.DisposeAsync();
|
||||
|
||||
_ = _connections.Remove(serverUrl);
|
||||
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);
|
||||
}
|
||||
|
||||
RemoveServerFromConfig(serverUrl);
|
||||
ServerRemoved?.Invoke(serverUrl);
|
||||
}
|
||||
|
||||
private static void RemoveServerFromConfig(string serverUrl)
|
||||
{
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
SavedServer? saved = config.SavedServers.FirstOrDefault(s =>
|
||||
string.Equals(s.Url, serverUrl, StringComparison.OrdinalIgnoreCase));
|
||||
if (saved is not null)
|
||||
{
|
||||
_ = config.SavedServers.Remove(saved);
|
||||
ConfigManager.Save(config);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string serverUrl, string channelName, string content)
|
||||
{
|
||||
if (!_connections.TryGetValue(serverUrl, out ServerConnection? entry))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using EchoHub.Client.Commands;
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Decho.ViewModels;
|
||||
@@ -45,7 +43,7 @@ public sealed class ChatViewModel : ViewModelBase
|
||||
Composer = new MessageComposerViewModel();
|
||||
}
|
||||
|
||||
public void SetChannel(ChannelViewModel? channel, string serverUrl = "")
|
||||
public void SetChannel(ChannelViewModel? channel, string serverUrl = "", bool isServerConnected = true)
|
||||
{
|
||||
if (channel is null)
|
||||
{
|
||||
@@ -55,7 +53,7 @@ public sealed class ChatViewModel : ViewModelBase
|
||||
HasTopic = false;
|
||||
CurrentChannelName = string.Empty;
|
||||
CurrentServerUrl = string.Empty;
|
||||
Composer.SetServer(string.Empty);
|
||||
Composer.SetServer(string.Empty, isServerConnected);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,12 +63,7 @@ public sealed class ChatViewModel : ViewModelBase
|
||||
HasTopic = channel.HasTopic;
|
||||
CurrentChannelName = channel.Name;
|
||||
CurrentServerUrl = serverUrl;
|
||||
Composer.SetServer(serverUrl);
|
||||
}
|
||||
|
||||
public void SetComposerCommandHandler(CommandHandler handler)
|
||||
{
|
||||
Composer.SetCommandHandler(handler);
|
||||
Composer.SetServer(serverUrl, isServerConnected);
|
||||
}
|
||||
|
||||
public void ClearMessages()
|
||||
|
||||
@@ -79,6 +79,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ServerViewModel serverVm = new ServerViewModel(placeholderServer);
|
||||
serverVm.ConnectRequested += async () => await HandleServerConnectRequested(serverVm);
|
||||
serverVm.DisconnectRequested += async () => await HandleServerDisconnectRequested(serverVm);
|
||||
serverVm.RemoveRequested += async () => await HandleServerRemoveRequested(serverVm);
|
||||
|
||||
Sidebar.Servers.Add(serverVm);
|
||||
StatusText = "Click Connect on the server to get started";
|
||||
@@ -352,6 +353,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ServerViewModel serverVm = new ServerViewModel(server);
|
||||
serverVm.ConnectRequested += () => HandleServerConnectRequested(serverVm);
|
||||
serverVm.DisconnectRequested += () => HandleServerDisconnectRequested(serverVm);
|
||||
serverVm.RemoveRequested += () => HandleServerRemoveRequested(serverVm);
|
||||
_ = serverVm.WhenAnyValue(s => s.SelectedChannel)
|
||||
.Where(channel => channel is not null)
|
||||
.Subscribe(channel => Sidebar.SelectedChannel = channel!);
|
||||
@@ -365,6 +367,11 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
Sidebar.Servers.Add(serverVm);
|
||||
if (serverVm.Channels.Count > 0)
|
||||
{
|
||||
serverVm.SelectedChannel = serverVm.Channels[0];
|
||||
}
|
||||
|
||||
StatusText = $"Connected to {server.Name}";
|
||||
});
|
||||
};
|
||||
@@ -390,6 +397,11 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
if (serverVm is not null)
|
||||
{
|
||||
serverVm.SyncFromModel();
|
||||
if (string.Equals(server.ServerUrl, Chat.CurrentServerUrl, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Chat.Composer.IsConnected = server.IsConnected;
|
||||
}
|
||||
|
||||
if (!server.IsConnected)
|
||||
{
|
||||
StatusText = $"Disconnected from {server.Name}";
|
||||
@@ -493,11 +505,12 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
string serverUrl = FindServerUrlForChannel(channel);
|
||||
Chat.SetChannel(channel, serverUrl);
|
||||
bool isServerConnected = Sidebar.GetServer(serverUrl)?.IsConnected ?? false;
|
||||
Chat.SetChannel(channel, serverUrl, isServerConnected);
|
||||
|
||||
if (!string.IsNullOrEmpty(serverUrl))
|
||||
{
|
||||
Chat.SetComposerCommandHandler(new CommandHandler());
|
||||
Chat.Composer.SetCommandHandler(new CommandHandler());
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
@@ -538,6 +551,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ServerViewModel serverVm = new ServerViewModel(placeholderServer);
|
||||
serverVm.ConnectRequested += async () => await HandleServerConnectRequested(serverVm);
|
||||
serverVm.DisconnectRequested += async () => await HandleServerDisconnectRequested(serverVm);
|
||||
serverVm.RemoveRequested += async () => await HandleServerRemoveRequested(serverVm);
|
||||
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
@@ -642,6 +656,18 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleServerRemoveRequested(ServerViewModel serverVm)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ConnectionService.RemoveServerAsync(serverVm.ServerUrl);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusText = $"Remove error: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureChannelInList(string serverUrl, string channelName)
|
||||
{
|
||||
ServerViewModel? serverVm = Sidebar.GetServer(serverUrl);
|
||||
|
||||
@@ -22,6 +22,12 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
||||
|
||||
public string ServerUrl { get; private set; } = string.Empty;
|
||||
|
||||
public bool IsConnected
|
||||
{
|
||||
get;
|
||||
set => this.RaiseAndSetIfChanged(ref field, value);
|
||||
} = true;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SendCommand { get; }
|
||||
|
||||
public bool HasCommandHandler => _commandHandler is not null;
|
||||
@@ -40,9 +46,10 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public void SetServer(string serverUrl)
|
||||
public void SetServer(string serverUrl, bool isConnected = true)
|
||||
{
|
||||
ServerUrl = serverUrl;
|
||||
IsConnected = isConnected;
|
||||
}
|
||||
|
||||
public void SetCommandHandler(CommandHandler handler)
|
||||
|
||||
@@ -19,6 +19,12 @@ public sealed class ServerViewModel : ViewModelBase
|
||||
remove => _disconnectRequested = (Func<Task>?)Delegate.Remove(_disconnectRequested, value);
|
||||
}
|
||||
|
||||
public event Func<Task>? RemoveRequested
|
||||
{
|
||||
add => _removeRequested = (Func<Task>?)Delegate.Combine(_removeRequested, value);
|
||||
remove => _removeRequested = (Func<Task>?)Delegate.Remove(_removeRequested, value);
|
||||
}
|
||||
|
||||
private bool _isConnected;
|
||||
private bool _isConnecting;
|
||||
private string? _connectedUser;
|
||||
@@ -27,6 +33,8 @@ public sealed class ServerViewModel : ViewModelBase
|
||||
|
||||
private Func<Task>? _disconnectRequested;
|
||||
|
||||
private Func<Task>? _removeRequested;
|
||||
|
||||
public ServerModel Model { get; }
|
||||
|
||||
public string Name => Model.Name;
|
||||
@@ -39,6 +47,8 @@ public sealed class ServerViewModel : ViewModelBase
|
||||
|
||||
public ReactiveCommand<Unit, Unit> DisconnectCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> RemoveCommand { get; }
|
||||
|
||||
public ChannelViewModel? SelectedChannel
|
||||
{
|
||||
get;
|
||||
@@ -124,6 +134,7 @@ public sealed class ServerViewModel : ViewModelBase
|
||||
|
||||
ConnectCommand = ReactiveCommand.CreateFromTask(ConnectAsync);
|
||||
DisconnectCommand = ReactiveCommand.CreateFromTask(DisconnectAsync);
|
||||
RemoveCommand = ReactiveCommand.CreateFromTask(RemoveAsync);
|
||||
}
|
||||
|
||||
public void SyncFromModel()
|
||||
@@ -149,4 +160,12 @@ public sealed class ServerViewModel : ViewModelBase
|
||||
await _disconnectRequested();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RemoveAsync()
|
||||
{
|
||||
if (_removeRequested is not null)
|
||||
{
|
||||
await _removeRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
<TextBox Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="0 0 5 0"
|
||||
Text="{Binding Draft, Mode=TwoWay}">
|
||||
Text="{Binding Draft, Mode=TwoWay}"
|
||||
IsEnabled="{Binding IsConnected}">
|
||||
<TextBox.KeyBindings>
|
||||
<KeyBinding Command="{Binding SendCommand}" Gesture="Enter" />
|
||||
</TextBox.KeyBindings>
|
||||
@@ -19,11 +20,13 @@
|
||||
Margin="0 0 5 0"
|
||||
Content="Send"
|
||||
i:Attached.Icon="fa-paper-plane"
|
||||
Command="{Binding SendCommand}" />
|
||||
Command="{Binding SendCommand}"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
<Button Grid.Column="2"
|
||||
Height="33"
|
||||
Width="33"
|
||||
Click="OnFileUploadClicked"
|
||||
i:Attached.Icon="fa-paperclip" />
|
||||
i:Attached.Icon="fa-paperclip"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -2,6 +2,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Decho.ViewModels"
|
||||
xmlns:views="using:Decho.Views"
|
||||
xmlns:i="https://github.com/projektanker/icons.avalonia"
|
||||
x:Class="Decho.Views.SidebarView"
|
||||
x:DataType="vm:SidebarViewModel">
|
||||
<Border Background="{DynamicResource UiTheme00}" Width="250" CornerRadius="0 6 0 0">
|
||||
@@ -14,6 +15,7 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
IsExpanded="{Binding IsExpanded}">
|
||||
<Expander.Header>
|
||||
<Grid ColumnDefinitions="*, Auto">
|
||||
<StackPanel Spacing="5">
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<Ellipse Width="8" Height="8"
|
||||
@@ -30,6 +32,23 @@
|
||||
Opacity="0.6"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
x:Name="SettingsButton"
|
||||
Background="Transparent"
|
||||
Foreground="{DynamicResource UiTheme08}"
|
||||
VerticalAlignment="Center"
|
||||
i:Attached.Icon="fa-cog"
|
||||
Click="OnSettingsClicked">
|
||||
<Button.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Disconnect"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
<MenuItem Header="Remove Server"
|
||||
Command="{Binding RemoveCommand}" />
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Expander.Header>
|
||||
<StackPanel>
|
||||
<Button Content="Connect"
|
||||
@@ -38,12 +57,6 @@
|
||||
Margin="4"
|
||||
Padding="5 2"
|
||||
HorizontalAlignment="Stretch" />
|
||||
<Button Content="Disconnect"
|
||||
Command="{Binding DisconnectCommand}"
|
||||
IsVisible="{Binding IsConnected}"
|
||||
Margin="4"
|
||||
Padding="5 2"
|
||||
HorizontalAlignment="Stretch" />
|
||||
<views:ChannelListView />
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
using Decho.ViewModels;
|
||||
|
||||
@@ -22,4 +23,12 @@ public partial class SidebarView : UserControl
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnSettingsClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button)
|
||||
{
|
||||
button.ContextMenu?.Open(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user