Offline Support

This commit is contained in:
2026-04-27 06:20:39 +08:00
parent 7d8851a94a
commit 48cd3bcd60
121 changed files with 14798 additions and 2214 deletions
+39
View File
@@ -11,6 +11,8 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'firebase_options.dart';
// removed unused imports
import 'app.dart';
import 'brick/cache_warmer.dart';
import 'brick/repository.dart';
import 'theme/app_theme.dart';
import 'providers/notifications_provider.dart';
import 'providers/notification_navigation_provider.dart';
@@ -276,10 +278,16 @@ Future<void> main() async {
return;
}
// Create Brick's HTTP client BEFORE Supabase.initialize so that all
// Supabase REST writes are intercepted and queued when offline.
// Returns null on web (SQLite unavailable there).
final brickHttpClient = AppRepository.createHttpClient();
try {
await Supabase.initialize(
url: supabaseUrl,
anonKey: supabaseAnonKey,
httpClient: brickHttpClient,
).timeout(const Duration(seconds: 20));
} catch (e) {
debugPrint('Supabase init failed or timed out: $e');
@@ -287,6 +295,16 @@ Future<void> main() async {
return;
}
// Configure the Brick repository after Supabase is ready.
try {
await AppRepository.configure();
} catch (e, st) {
debugPrint('AppRepository configure FAILED: $e\n$st');
}
debugPrint(
'[Boot] AppRepository.isConfigured=${AppRepository.isConfigured}',
);
// Initialize background location service (flutter_background_service)
if (!kIsWeb) {
try {
@@ -302,6 +320,17 @@ Future<void> main() async {
// Run this after runApp so startup is not blocked by network/token ops.
final supaClient = Supabase.instance.client;
// Cold-launch with a persisted session: AuthChangeEvent.signedIn does NOT
// fire on session rehydration (only initialSession/tokenRefreshed do), so
// the auth-change listener below misses cold-starts. Warm the Brick mirror
// here in the background so cached lists stay fresh between sessions.
// CacheWarmer.warmAll is no-op-safe offline (REST calls just fail).
if (supaClient.auth.currentUser != null && AppRepository.isConfigured) {
debugPrint('[Boot] Persisted session detected — warming Brick cache');
CacheWarmer.warmAll(supaClient);
CacheWarmer.startPeriodicRefresh(supaClient);
}
// listen for auth changes to register/unregister token accordingly
supaClient.auth.onAuthStateChange.listen((data) async {
final event = data.event;
@@ -347,6 +376,16 @@ Future<void> main() async {
return;
}
// Trigger a cache warm immediately when the user signs in so the local
// Brick SQLite mirror is populated for the next cold-launch. Fire-and-
// forget — never block the auth flow on the warmer.
if (event == AuthChangeEvent.signedIn) {
CacheWarmer.warmAll(supaClient);
CacheWarmer.startPeriodicRefresh(supaClient);
} else if (event == AuthChangeEvent.signedOut) {
CacheWarmer.stopPeriodicRefresh();
}
String? token;
try {
token = await FirebaseMessaging.instance.getToken();