64 lines
2.1 KiB
Dart
64 lines
2.1 KiB
Dart
import 'package:flutter/foundation.dart' show debugPrint;
|
|
|
|
import 'repository.dart';
|
|
|
|
/// Returns the locally cached list of [T] from Brick SQLite, or `[]` if Brick
|
|
/// isn't configured or the read fails. Never throws.
|
|
///
|
|
/// Use this as `onOfflineData` for [StreamRecoveryWrapper] so that screens
|
|
/// render data from the local cache when the device is offline:
|
|
///
|
|
/// ```dart
|
|
/// onOfflineData: () => cachedListFromBrick<Task>(),
|
|
/// ```
|
|
Future<List<T>> cachedListFromBrick<T extends OfflineFirstWithSupabaseModel>() async {
|
|
if (!AppRepository.isConfigured) {
|
|
debugPrint('[cachedListFromBrick<$T>] BRICK NOT CONFIGURED — returning []');
|
|
return const [];
|
|
}
|
|
try {
|
|
final rows = await AppRepository.instance.get<T>(
|
|
policy: OfflineFirstGetPolicy.localOnly,
|
|
);
|
|
if (rows.isEmpty) {
|
|
debugPrint('[cachedListFromBrick<$T>] empty cache (0 rows)');
|
|
}
|
|
return rows;
|
|
} catch (e) {
|
|
debugPrint('[cachedListFromBrick<$T>] failed: $e');
|
|
return const [];
|
|
}
|
|
}
|
|
|
|
/// Mirrors a batch of model rows into Brick's local SQLite cache as a
|
|
/// fire-and-forget side effect. Errors are caught and logged.
|
|
///
|
|
/// Use this as `onCacheMirror` for [StreamRecoveryWrapper] so that every
|
|
/// realtime emission keeps the local cache fresh — required for the cold-
|
|
/// launch-offline experience.
|
|
///
|
|
/// ```dart
|
|
/// onCacheMirror: (rows) => mirrorBatchToBrick<Task>(rows, tag: 'tasks'),
|
|
/// ```
|
|
void mirrorBatchToBrick<T extends OfflineFirstWithSupabaseModel>(
|
|
List<T> rows, {
|
|
String tag = 'mirror',
|
|
}) {
|
|
if (!AppRepository.isConfigured) return;
|
|
// Use sqliteProvider directly (local-only write). AppRepository.upsert is
|
|
// bidirectional — it re-POSTs rows to Supabase, which triggers RLS
|
|
// violations for other users' records and deadlocks from concurrent writes.
|
|
// Sequential processing prevents SQLite lock contention across providers.
|
|
// ignore: discarded_futures
|
|
Future(() async {
|
|
for (final row in rows) {
|
|
try {
|
|
await AppRepository.instance.sqliteProvider
|
|
.upsert<T>(row, repository: AppRepository.instance);
|
|
} catch (e) {
|
|
debugPrint('[$tag] mirror upsert<$T> failed: $e');
|
|
}
|
|
}
|
|
});
|
|
}
|