fix(chat): KeyNotFoundException dans HubConnectionManager.OnConnected
ChatUserNames n'etait jamais alimente (relique d'un SetUserName disparu),
ce qui faisait lever KeyNotFoundException a chaque connexion SignalR et
fermait immediatement la connexion cote client ("Déconnecté (The server
closed the connection...)" dans PostIt).
- IConnexionManager.OnConnected prend desormais le userName en parametre
- HubConnectionManager.OnConnected alimente ChatUserNames et ChatCxIds
- ChatHub.OnConnectedAsync passe le userName resolu depuis les claims
Inclut aussi les changements PostIt lies (bandeau de statut avec
commande d'action, handlers Reconnecting/Reconnected/Closed).
This commit is contained in:
parent
b22a26f61e
commit
75bb2600b5
6 changed files with 70 additions and 16 deletions
|
|
@ -18,6 +18,7 @@
|
|||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button Content="{Binding CheckCommandLabel}"
|
||||
Foreground="{Binding Foreground}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding HasCheckCommand}"
|
||||
Command="{Binding CheckCommand}"
|
||||
|
|
|
|||
|
|
@ -148,6 +148,41 @@ namespace PostIt.ViewModels.Chat
|
|||
await _connection.StartAsync();
|
||||
IsConnected = true;
|
||||
Status = new StatusNotice("Connecté au Hub SignalR", StatusSeverity.Info, new RelayCheckCommand("Déconnecter", async () => await DisconnectAsync()));
|
||||
|
||||
// WithAutomaticReconnect ne lève pas d'exception en cas de
|
||||
// perte réseau : l'état passe par Reconnecting/Closed. Sans
|
||||
// ces handlers, IsConnected resterait optimiste et Join()
|
||||
// échouerait avec "connection is not active".
|
||||
_connection.Reconnecting += error =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsConnected = false;
|
||||
Status = new StatusNotice($"Connexion perdue ({error?.Message ?? "réseau"}), reconnexion...", StatusSeverity.Error,
|
||||
new RelayCheckCommand("Déconnecter", async () => await DisconnectAsync()));
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_connection.Reconnected += _ =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsConnected = true;
|
||||
Status = new StatusNotice("Reconnecté au Hub SignalR", StatusSeverity.Info,
|
||||
new RelayCheckCommand("Déconnecter", async () => await DisconnectAsync()));
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_connection.Closed += error =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsConnected = false;
|
||||
Status = new StatusNotice($"Déconnecté ({error?.Message ?? "fin de connexion"})", StatusSeverity.Info,
|
||||
new RelayCheckCommand("Connecter", async () => await ConnectAsync()));
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -156,15 +191,34 @@ namespace PostIt.ViewModels.Chat
|
|||
}
|
||||
}
|
||||
|
||||
private async Task CheckConnectionAsync()
|
||||
private Task CheckConnectionAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var state = _connection?.State.ToString() ?? "aucune connexion";
|
||||
Messages.Add($"État de la connexion : {state}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task JoinRoomAsync()
|
||||
{
|
||||
if (_connection == null || string.IsNullOrWhiteSpace(CurrentRoom)) return;
|
||||
|
||||
// InvokeCoreAsync exige une connexion active : avec la
|
||||
// reconnexion automatique, l'état peut être Reconnecting au
|
||||
// moment de l'appel. On tente une (re)connexion si nécessaire.
|
||||
if (_connection.State != HubConnectionState.Connected)
|
||||
{
|
||||
Messages.Add($"Connexion non active ({_connection.State}), tentative de reconnexion...");
|
||||
try
|
||||
{
|
||||
await _connection.StartAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Messages.Add($"Reconnexion impossible : {ex.Message}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Appel de la méthode publique 'Join' du Hub (renvoie un ChatRoomInfo)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public sealed class StatusNotice
|
|||
public string BorderBrush { get; }
|
||||
public string Foreground { get; }
|
||||
|
||||
public bool HasCheckCommand { get; }
|
||||
public bool HasCheckCommand { get => CheckCommand != null; }
|
||||
|
||||
public ICommand? CheckCommand { get; }
|
||||
|
||||
|
|
@ -29,12 +29,9 @@ public sealed class StatusNotice
|
|||
StatusSeverity.Warning => ("~", "#7C4A03", "#E6A700", "#eaeaea"),
|
||||
_ => ("i", "#E8F0FE", "#5B8DEF", "#1E3A8A"),
|
||||
};
|
||||
HasCheckCommand = checkCommand != null;
|
||||
CheckCommand = checkCommand;
|
||||
CheckCommandLabel = HasCheckCommand ? "Check" :
|
||||
checkCommand == null ?
|
||||
string.Empty :
|
||||
checkCommand is IWithLabel labeled ? labeled.Label : string.Empty;
|
||||
CheckCommandLabel = HasCheckCommand ?
|
||||
(checkCommand is IWithLabel labeled ? labeled.Label : "Check") : string.Empty;
|
||||
}
|
||||
|
||||
public static StatusNotice Info(string message, ICommand? checkCommand = null) => new(message, StatusSeverity.Info, checkCommand);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ namespace Yavsc.Server.Hubs
|
|||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, ChatHubConstants.HubGroupFollowingPrefix + uid);
|
||||
}
|
||||
_cxManager.OnConnected(Context.ConnectionId, isCop);
|
||||
_cxManager.OnConnected(Context.ConnectionId, userName, isCop);
|
||||
await base.OnConnectedAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace Yavsc.Services
|
|||
{
|
||||
public interface IConnexionManager {
|
||||
string GetUserName (string cxId);
|
||||
void OnConnected(string cxId, bool isCop);
|
||||
void OnConnected(string cxId, string userName, bool isCop);
|
||||
bool IsConnected(string candidate);
|
||||
|
||||
void OnDisconnected (string cxId);
|
||||
|
|
|
|||
|
|
@ -53,13 +53,15 @@ namespace Yavsc.Services
|
|||
_localizer = stringLocFactory.Create(typeof(HubConnectionManager));
|
||||
}
|
||||
|
||||
// Username must have been set before calling this method.
|
||||
public void OnConnected(string cxId, bool isCop)
|
||||
public void OnConnected(string cxId, string userName, bool isCop)
|
||||
{
|
||||
var username = ChatUserNames[cxId];
|
||||
if (!IsConnected(username))
|
||||
ChatRoomPresence[username] = new List<string>();
|
||||
_isCop[username] = isCop;
|
||||
ChatUserNames[cxId] = userName;
|
||||
ChatCxIds.AddOrUpdate(userName,
|
||||
_ => new List<string> { cxId },
|
||||
(_, list) => { lock (list) { if (!list.Contains(cxId)) list.Add(cxId); } return list; });
|
||||
if (!IsConnected(userName))
|
||||
ChatRoomPresence[userName] = new List<string>();
|
||||
_isCop[userName] = isCop;
|
||||
}
|
||||
|
||||
public bool IsConnected(string candidate)
|
||||
|
|
|
|||
Loading…
Reference in a new issue