Offline queue: retry kirim setelah refresh/poll sukses + verifikasi server reachable + log gagal sinkron + izin INTERNET/ACCESS_NETWORK_STATE Android

This commit is contained in:
Onie
2026-10-18 17:39:38 +07:00
parent 8a6541e55f
commit 67b4d934a4
3 changed files with 26 additions and 0 deletions

View File

@@ -1,4 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Akses jaringan: API Supabase + deteksi konektivitas offline queue -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Camera permission for barcode scanning --> <!-- Camera permission for barcode scanning -->
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />

View File

@@ -60,6 +60,25 @@ class OfflineQueueService {
_updateConnectionStatus(result); _updateConnectionStatus(result);
} }
/// Coba kirim antrean sekarang. Dipanggil setiap refresh/poll sukses
/// (server terbukti reachable), bukan hanya saat event connectivity berubah.
Future<void> retryNow() async {
await _checkConnection();
if (!_isOnline || _queue.isEmpty || _syncing) return;
// Verifikasi server benar-benar bisa dijangkau (radio nyala belum tentu
// berarti Supabase reachable, misal sinyal buruk).
try {
await _supabase.from('products').select('id').limit(1).timeout(
const Duration(seconds: 5),
onTimeout: () => throw TimeoutException('Ping server timeout'),
);
} catch (e) {
debugPrint('OfflineQueue skip sync: server tidak terjangkau: $e');
return;
}
await _processQueue();
}
void _updateConnectionStatus(List<ConnectivityResult> result) { void _updateConnectionStatus(List<ConnectivityResult> result) {
_isOnline = result.any((r) => r != ConnectivityResult.none); _isOnline = result.any((r) => r != ConnectivityResult.none);
if (_isOnline && _queue.isNotEmpty) { if (_isOnline && _queue.isNotEmpty) {
@@ -86,6 +105,7 @@ class OfflineQueueService {
_queue.removeAt(0); _queue.removeAt(0);
await _saveQueue(); await _saveQueue();
} catch (e) { } catch (e) {
debugPrint('OfflineQueue gagal sinkron item ${item['sale']?['id']}: $e');
_syncing = false; _syncing = false;
return; return;
} }

View File

@@ -224,6 +224,8 @@ class AppState extends ChangeNotifier {
await _loadProducts(); await _loadProducts();
await _loadSales(); await _loadSales();
dataReady = true; dataReady = true;
// Server terbukti reachable → coba kirim antrean transaksi offline.
await _offlineQueue.retryNow();
} catch (e) { } catch (e) {
productsError ??= e.toString(); productsError ??= e.toString();
if (retries > 0) { if (retries > 0) {