Synchronise les parties entre les deux devices

This commit is contained in:
2026-04-15 23:40:18 +02:00
parent 3b88b9abe6
commit e0c3a41ccd
11 changed files with 527 additions and 18 deletions

View File

@@ -383,6 +383,8 @@
private bool IsAuthenticated;
private bool IsSocialLoading;
private int _knownSocialVersion;
private long _knownCollaborativeRevision;
private string? _appliedActiveSessionId;
private string? ConnectedPlayerName;
private string? SetupError;
private string? SocialLoadError;
@@ -463,6 +465,11 @@
}
await Store.EnsureLoadedAsync();
if (!string.IsNullOrWhiteSpace(Store.Current?.CollaborationSessionId))
{
await Realtime.EnsureJoinedPlaySessionAsync(Store.Current.CollaborationSessionId);
}
_ready = true;
StateHasChanged();
}
@@ -476,6 +483,7 @@
private async Task HandleRealtimeChangedAsync()
{
ApplyAcceptedPlaySession();
await ApplyCollaborativeSyncAsync();
if (IsAuthenticated && _knownSocialVersion != Realtime.SocialVersion)
{
@@ -539,6 +547,7 @@
}
ApplyAcceptedPlaySession();
await ApplyCollaborativeSyncAsync();
await InvokeAsync(StateHasChanged);
}
@@ -598,11 +607,18 @@
await Store.EnsureLoadedAsync();
var match = MatchEngine.CreateMatch(Form.ToMatchConfig());
if (!string.IsNullOrWhiteSpace(Realtime.ActivePlaySession?.SessionId))
{
match.CollaborationSessionId = Realtime.ActivePlaySession.SessionId;
await Realtime.EnsureJoinedPlaySessionAsync(match.CollaborationSessionId);
}
Store.SetCurrent(match);
try
{
await Store.SaveAsync();
await Realtime.PublishMatchStateAsync(match, "/chrono.html");
}
catch
{
@@ -699,7 +715,14 @@
private async Task ClearMatchAsync()
{
var sessionId = CurrentMatch?.CollaborationSessionId;
await Store.ClearAsync();
if (!string.IsNullOrWhiteSpace(sessionId))
{
await Realtime.PublishMatchStateAsync(null, "/application.html");
}
StateHasChanged();
}
@@ -727,8 +750,8 @@
private void ApplyAcceptedPlaySession()
{
var session = Realtime.TakeAcceptedPlaySession();
if (session is null)
var session = Realtime.ActivePlaySession;
if (session is null || string.Equals(_appliedActiveSessionId, session.SessionId, StringComparison.Ordinal))
{
return;
}
@@ -736,6 +759,7 @@
Form.WhiteName = session.WhiteName;
Form.BlackName = session.BlackName;
SetupError = null;
_appliedActiveSessionId = session.SessionId;
}
private void AssignConnectedPlayerToWhite()
@@ -784,6 +808,32 @@
: null;
}
private async Task ApplyCollaborativeSyncAsync()
{
var snapshot = Realtime.CollaborativeSnapshot;
if (snapshot is null || snapshot.Revision <= _knownCollaborativeRevision)
{
return;
}
_knownCollaborativeRevision = snapshot.Revision;
Store.ReplaceCurrent(snapshot.Match);
await Store.SaveAsync();
if (snapshot.Match is not null)
{
Form.WhiteName = snapshot.Match.Config.WhiteName;
Form.BlackName = snapshot.Match.Config.BlackName;
SetupError = null;
}
var route = NormalizeRoute(snapshot.Route);
if (!string.Equals(route, "/application.html", StringComparison.OrdinalIgnoreCase))
{
Navigation.NavigateTo(route, replace: true);
}
}
private bool ResolveOnlineStatus(string subject, bool fallbackStatus)
=> Realtime.GetKnownOnlineStatus(subject) ?? fallbackStatus;
@@ -813,12 +863,19 @@
MatchEngine.SanitizeText(right) ?? string.Empty,
StringComparison.OrdinalIgnoreCase);
private static string NormalizeRoute(string? route)
{
var normalized = string.IsNullOrWhiteSpace(route) ? "/application.html" : route.Trim();
return normalized.StartsWith('/') ? normalized : $"/{normalized}";
}
private void ResetSocialState()
{
SocialOverview = null;
SocialLoadError = null;
InviteActionError = null;
_knownSocialVersion = Realtime.SocialVersion;
_knownCollaborativeRevision = 0;
}
private static string? BuildConnectedPlayerFallback(ClaimsPrincipal user)