Skeleton loading
This commit is contained in:
@@ -20,15 +20,19 @@ final realtimeControllerProvider = ChangeNotifierProvider<RealtimeController>((
|
||||
/// connection when the app returns to the foreground or when auth tokens
|
||||
/// are refreshed.
|
||||
class RealtimeController extends ChangeNotifier {
|
||||
RealtimeController(this._client) {
|
||||
_init();
|
||||
}
|
||||
|
||||
final SupabaseClient _client;
|
||||
|
||||
bool isConnecting = false;
|
||||
bool isFailed = false;
|
||||
String? lastError;
|
||||
int attempts = 0;
|
||||
final int maxAttempts;
|
||||
bool _disposed = false;
|
||||
|
||||
RealtimeController(this._client, {this.maxAttempts = 4}) {
|
||||
_init();
|
||||
}
|
||||
|
||||
void _init() {
|
||||
try {
|
||||
// Listen for auth changes and try to recover the realtime connection
|
||||
@@ -39,7 +43,9 @@ class RealtimeController extends ChangeNotifier {
|
||||
recoverConnection();
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
} catch (e) {
|
||||
debugPrint('RealtimeController._init error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to reconnect the realtime client using a small exponential backoff.
|
||||
@@ -47,15 +53,15 @@ class RealtimeController extends ChangeNotifier {
|
||||
if (_disposed) return;
|
||||
if (isConnecting) return;
|
||||
|
||||
isFailed = false;
|
||||
lastError = null;
|
||||
isConnecting = true;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
int attempt = 0;
|
||||
int maxAttempts = 4;
|
||||
int delaySeconds = 1;
|
||||
while (attempt < maxAttempts && !_disposed) {
|
||||
attempt++;
|
||||
while (attempts < maxAttempts && !_disposed) {
|
||||
attempts++;
|
||||
try {
|
||||
// Best-effort disconnect then connect so the realtime client picks
|
||||
// up any refreshed tokens.
|
||||
@@ -82,11 +88,17 @@ class RealtimeController extends ChangeNotifier {
|
||||
// Give the socket a moment to stabilise.
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
// Exit early; we don't have a reliable sync API for connection
|
||||
// state across all platforms, so treat this as a best-effort
|
||||
// resurrection.
|
||||
// Success (best-effort). Reset attempt counter and clear failure.
|
||||
attempts = 0;
|
||||
isFailed = false;
|
||||
lastError = null;
|
||||
break;
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
lastError = e.toString();
|
||||
if (attempts >= maxAttempts) {
|
||||
isFailed = true;
|
||||
break;
|
||||
}
|
||||
await Future.delayed(Duration(seconds: delaySeconds));
|
||||
delaySeconds = delaySeconds * 2;
|
||||
}
|
||||
@@ -99,6 +111,16 @@ class RealtimeController extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retry a failed recovery attempt.
|
||||
Future<void> retry() async {
|
||||
if (_disposed) return;
|
||||
attempts = 0;
|
||||
isFailed = false;
|
||||
lastError = null;
|
||||
notifyListeners();
|
||||
await recoverConnection();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
|
||||
Reference in New Issue
Block a user