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(), /// ``` Future> cachedListFromBrick() async { if (!AppRepository.isConfigured) { debugPrint('[cachedListFromBrick<$T>] BRICK NOT CONFIGURED — returning []'); return const []; } try { final rows = await AppRepository.instance.get( 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(rows, tag: 'tasks'), /// ``` void mirrorBatchToBrick( List 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(row, repository: AppRepository.instance); } catch (e) { debugPrint('[$tag] mirror upsert<$T> failed: $e'); } } }); }