|
| 1 | +using FwLiteShared.Projects; |
| 2 | +using Microsoft.Extensions.Hosting; |
| 3 | +using Microsoft.Extensions.Logging; |
| 4 | + |
| 5 | +namespace FwLiteMaui.Services; |
| 6 | + |
| 7 | +// Primary use case: app started offline should start syncing if the device comes online |
| 8 | +public sealed class ConnectivitySyncTrigger( |
| 9 | + IConnectivity connectivity, |
| 10 | + LexboxProjectChangeListener lexboxProjectChangeListener, |
| 11 | + ILogger<ConnectivitySyncTrigger> logger) : IHostedService |
| 12 | +{ |
| 13 | + private NetworkAccess _lastAccess; |
| 14 | + |
| 15 | + public Task StartAsync(CancellationToken cancellationToken) |
| 16 | + { |
| 17 | + _lastAccess = connectivity.NetworkAccess; |
| 18 | + connectivity.ConnectivityChanged += OnConnectivityChanged; |
| 19 | + logger.LogInformation("Watching device connectivity to re-establish push listeners (current access: {NetworkAccess})", _lastAccess); |
| 20 | + return Task.CompletedTask; |
| 21 | + } |
| 22 | + |
| 23 | + public Task StopAsync(CancellationToken cancellationToken) |
| 24 | + { |
| 25 | + connectivity.ConnectivityChanged -= OnConnectivityChanged; |
| 26 | + return Task.CompletedTask; |
| 27 | + } |
| 28 | + |
| 29 | + private void OnConnectivityChanged(object? sender, ConnectivityChangedEventArgs e) |
| 30 | + { |
| 31 | + var previous = _lastAccess; |
| 32 | + var current = _lastAccess = e.NetworkAccess; |
| 33 | + |
| 34 | + logger.LogInformation("Device connectivity changed: {Previous} -> {Current} (profiles: {Profiles})", |
| 35 | + previous, current, string.Join(", ", e.ConnectionProfiles)); |
| 36 | + |
| 37 | + if (!ShouldRecover(previous, current)) return; |
| 38 | + |
| 39 | + logger.LogInformation("Connectivity regained (internet access); ensuring push listeners"); |
| 40 | + _ = EnsureListeners(); |
| 41 | + } |
| 42 | + |
| 43 | + private async Task EnsureListeners(CancellationToken cancellationToken = default) |
| 44 | + { |
| 45 | + try |
| 46 | + { |
| 47 | + await lexboxProjectChangeListener.EnsureListenersForTrackedProjects(kickReconnecting: true, cancellationToken); |
| 48 | + } |
| 49 | + catch (Exception e) |
| 50 | + { |
| 51 | + logger.LogWarning(e, "Failed to ensure push listeners after connectivity change"); |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + // Only react to a transition INTO internet access, so recovery doesn't re-run on every connectivity |
| 56 | + // change (e.g. wifi<->cellular) while already online. Idempotent recovery makes a missed edge harmless; |
| 57 | + // this just keeps the common flapping case quiet. |
| 58 | + public static bool ShouldRecover(NetworkAccess previous, NetworkAccess current) |
| 59 | + { |
| 60 | + return current == NetworkAccess.Internet && previous != NetworkAccess.Internet; |
| 61 | + } |
| 62 | +} |
0 commit comments