Offline Support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:awesome_snackbar_content/awesome_snackbar_content.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart' show PostgrestException;
|
||||
|
||||
/// A global messenger key used to show snackbars from contexts without a
|
||||
/// Scaffold (e.g. dialogs, background callbacks, or tests).
|
||||
@@ -218,3 +219,55 @@ void showWarningSnackBarGlobal(String message) => showAwesomeSnackBarGlobal(
|
||||
message: message,
|
||||
snackType: SnackType.warning,
|
||||
);
|
||||
|
||||
/// Returns true when [error] is a network-connectivity failure (socket closed,
|
||||
/// no route to host, failed DNS lookup, etc.).
|
||||
///
|
||||
/// When this is true in a Brick-enabled app, the write was already queued in
|
||||
/// the offline SQLite store and will sync automatically when the device
|
||||
/// reconnects — so the UI should treat it as a success rather than an error.
|
||||
bool isOfflineSaveError(Object error) {
|
||||
if (error is PostgrestException) {
|
||||
// Null code = no HTTP response received at all (pure network failure).
|
||||
if (error.code == null) return true;
|
||||
|
||||
// Brick's RestOfflineQueueClient catches network errors and returns a
|
||||
// synthetic StreamedResponse(501, body: 'unknown internal error') rather
|
||||
// than rethrowing. PostgREST then parses this as
|
||||
// PostgrestException(code: '501', message: 'unknown internal error').
|
||||
// This is the primary offline indicator when Supabase is used with Brick.
|
||||
if (error.code == '501' && error.message == 'unknown internal error') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: Supabase may wrap a SocketException in a PostgrestException
|
||||
// message field before it reaches Brick's queue (rare, but defensive).
|
||||
final pmsg = error.message.toLowerCase();
|
||||
if (pmsg.contains('socketexception') ||
|
||||
pmsg.contains('failed host lookup') ||
|
||||
pmsg.contains('connection refused') ||
|
||||
pmsg.contains('network is unreachable') ||
|
||||
pmsg.contains('no route to host') ||
|
||||
pmsg.contains('connection timed out') ||
|
||||
pmsg.contains('failed to connect')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Non-PostgrestException network errors (SocketException, ClientException)
|
||||
// that propagate before Brick's HTTP interceptor can catch them.
|
||||
final msg = error.toString().toLowerCase();
|
||||
return msg.contains('socketexception') ||
|
||||
msg.contains('socket') && msg.contains('exception') ||
|
||||
msg.contains('connection refused') ||
|
||||
msg.contains('network is unreachable') ||
|
||||
msg.contains('no route to host') ||
|
||||
msg.contains('failed host lookup') ||
|
||||
msg.contains('connection reset') ||
|
||||
msg.contains('broken pipe') ||
|
||||
msg.contains('connection timed out') ||
|
||||
msg.contains('clientexception') && msg.contains('network') ||
|
||||
msg.contains('failed to connect') ||
|
||||
msg.contains('errno = 111') || // ECONNREFUSED
|
||||
msg.contains('errno = 101'); // ENETUNREACH
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user