Add Reconnected event and refresh current channel on reconnect

This commit is contained in:
Stone_Red
2026-07-24 00:06:16 +02:00
parent c93a53da51
commit a62ff1b9af
3 changed files with 59 additions and 5 deletions
+15
View File
@@ -49,6 +49,8 @@ public sealed class ConnectionService : IConnectionService
public event Action<string, string>? ChannelDeleted; public event Action<string, string>? ChannelDeleted;
public event Action<string>? Reconnected;
private readonly Dictionary<string, ServerConnection> _connections = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, ServerConnection> _connections = new(StringComparer.OrdinalIgnoreCase);
private readonly IConfigPersistenceService _config; private readonly IConfigPersistenceService _config;
private readonly IAttachmentService _attachment; private readonly IAttachmentService _attachment;
@@ -395,5 +397,18 @@ public sealed class ConnectionService : IConnectionService
entry.Server.IsConnecting = status is "Connecting..." or "Authenticating..." or "Reconnecting..."; entry.Server.IsConnecting = status is "Connecting..." or "Authenticating..." or "Reconnecting...";
ServerStateChanged?.Invoke(entry.Server); ServerStateChanged?.Invoke(entry.Server);
}; };
conn.Reconnected += async () =>
{
try
{
await entry.Manager.RejoinChannelsAsync();
Reconnected?.Invoke(entry.Server.ServerUrl);
}
catch (Exception ex)
{
Debug.WriteLine($"Rejoin failed: {ex.Message}");
}
};
} }
} }
+1
View File
@@ -17,6 +17,7 @@ public interface IConnectionService : IDisposable
event Action<string, string>? UserLeft; event Action<string, string>? UserLeft;
event Action<string, string>? ErrorOccurred; event Action<string, string>? ErrorOccurred;
event Action<string, string>? ChannelDeleted; event Action<string, string>? ChannelDeleted;
event Action<string>? Reconnected;
Task<ServerModel> ConnectAsync(string serverUrl, string username, string password, bool isRegister, bool rememberMe); Task<ServerModel> ConnectAsync(string serverUrl, string username, string password, bool isRegister, bool rememberMe);
Task ConnectWithSavedTokenAsync(string serverUrl, string username, string refreshToken, bool rememberMe); Task ConnectWithSavedTokenAsync(string serverUrl, string username, string refreshToken, bool rememberMe);
+43 -5
View File
@@ -20,6 +20,7 @@ using MsBox.Avalonia.Enums;
using System.Diagnostics; using System.Diagnostics;
using System.Reactive; using System.Reactive;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Linq;
namespace Decho.ViewModels; namespace Decho.ViewModels;
@@ -787,6 +788,11 @@ public sealed class MainWindowViewModel : ViewModelBase
} }
}); });
}; };
ConnectionService.Reconnected += serverUrl =>
{
_ = RefreshCurrentChannelAsync(serverUrl);
};
} }
private async Task HandleSendTextAsync(string text) private async Task HandleSendTextAsync(string text)
@@ -824,6 +830,40 @@ public sealed class MainWindowViewModel : ViewModelBase
} }
} }
private async Task RefreshCurrentChannelAsync(string serverUrl)
{
if (!string.Equals(serverUrl, Chat.CurrentServerUrl, StringComparison.OrdinalIgnoreCase))
return;
string channelName = Chat.CurrentChannelName;
if (string.IsNullOrEmpty(channelName))
return;
ChannelViewModel? channel = FindChannelViewModel(serverUrl, channelName);
if (channel is null)
return;
try
{
List<MessageModel> latest = await ChannelService.GetHistoryAsync(serverUrl, channelName, HubConstants.DefaultHistoryCount, 0);
HashSet<string> existingIds = channel.Messages.Select(m => m.Model.Id).ToHashSet();
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
{
foreach (MessageModel msg in latest)
{
if (!existingIds.Contains(msg.Id))
{
channel.AddMessage(msg);
}
}
});
}
catch (Exception ex)
{
Debug.WriteLine($"RefreshCurrentChannel failed: {ex.Message}");
}
}
private async Task<string?> HandleCommandAsync(string commandText) private async Task<string?> HandleCommandAsync(string commandText)
{ {
CommandResult result = await _commandHandler.HandleAsync(commandText); CommandResult result = await _commandHandler.HandleAsync(commandText);
@@ -1104,12 +1144,10 @@ public sealed class MainWindowViewModel : ViewModelBase
Chat.Composer.IsReadOnly = false; Chat.Composer.IsReadOnly = false;
} }
if (!channel.Messages.Any(m => m.AuthorName != "System")) HashSet<string> existingIds = channel.Messages.Select(m => m.Model.Id).ToHashSet();
foreach (var msg in joinResult.History.Where(msg => !existingIds.Contains(msg.Id)))
{ {
foreach (MessageModel msg in joinResult.History) channel.AddMessage(msg);
{
channel.AddMessage(msg);
}
} }
}); });