cashumit/lib/services/account_cache_service.dart

117 lines
4.0 KiB
Dart

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
class AccountCacheService {
static const String _accountsKey = 'cached_accounts';
static const String _lastUpdatedKey = 'accounts_last_updated';
static const String _lastKnownGoodAccountsKey = 'last_known_good_accounts';
/// Simpan akun ke cache lokal (cache utama)
static Future<void> saveAccountsLocally(
List<Map<String, dynamic>> accounts) async {
final prefs = await SharedPreferences.getInstance();
// Konversi akun ke JSON string
final accountsJson =
accounts.map((account) => json.encode(account)).toList();
await prefs.setStringList(_accountsKey, accountsJson);
await prefs.setInt(_lastUpdatedKey, DateTime.now().millisecondsSinceEpoch);
// Simpan juga sebagai last known good accounts
await prefs.setStringList(_lastKnownGoodAccountsKey, accountsJson);
}
/// Ambil akun dari cache utama
static Future<List<Map<String, dynamic>>> getCachedAccounts() async {
final prefs = await SharedPreferences.getInstance();
final accountsJsonList = prefs.getStringList(_accountsKey) ?? [];
if (accountsJsonList.isEmpty) {
return [];
}
return accountsJsonList
.map((jsonString) => json.decode(jsonString) as Map<String, dynamic>)
.toList();
}
/// Ambil last known good accounts (untuk fallback offline)
static Future<List<Map<String, dynamic>>> getLastKnownGoodAccounts() async {
final prefs = await SharedPreferences.getInstance();
final accountsJsonList =
prefs.getStringList(_lastKnownGoodAccountsKey) ?? [];
if (accountsJsonList.isEmpty) {
return [];
}
return accountsJsonList
.map((jsonString) => json.decode(jsonString) as Map<String, dynamic>)
.toList();
}
/// Periksa apakah cache akun masih valid (kurang dari 24 jam untuk keandalan offline)
static Future<bool> isCacheValid() async {
final prefs = await SharedPreferences.getInstance();
final lastUpdated = prefs.getInt(_lastUpdatedKey) ?? 0;
final now = DateTime.now().millisecondsSinceEpoch;
// Cache valid selama 24 jam (86400000 ms) - lebih lama untuk mendukung offline
return (now - lastUpdated) < 8640000;
}
/// Hapus cache akun
static Future<void> clearCache() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_accountsKey);
await prefs.remove(_lastUpdatedKey);
}
/// Update cache akun dari server
static Future<void> updateAccountsFromServer(
List<Map<String, dynamic>> accounts) async {
await saveAccountsLocally(accounts);
}
/// Dapatkan akun dengan prioritas: cache valid > last known good > data server > default mapping > fallback kosong
static Future<List<Map<String, dynamic>>> getAccountsWithFallback(
Future<List<Map<String, dynamic>>> Function() serverFetchFunction,
) async {
// 1. Coba ambil dari cache valid dulu
if (await isCacheValid()) {
final cachedAccounts = await getCachedAccounts();
if (cachedAccounts.isNotEmpty) {
return cachedAccounts;
}
}
// 2. Coba ambil dari last known good accounts (offline fallback)
final lastKnownGoodAccounts = await getLastKnownGoodAccounts();
if (lastKnownGoodAccounts.isNotEmpty) {
return lastKnownGoodAccounts;
}
// 3. Jika cache tidak valid atau kosong, coba ambil dari server
try {
final serverAccounts = await serverFetchFunction();
if (serverAccounts.isNotEmpty) {
// Simpan ke cache jika berhasil ambil dari server
await updateAccountsFromServer(serverAccounts);
return serverAccounts;
}
} catch (e) {
print('Gagal mengambil akun dari server: $e');
}
// 4. Jika semua gagal, kembalikan last known good accounts (meskipun mungkin expired)
final fallbackAccounts = await getLastKnownGoodAccounts();
if (fallbackAccounts.isNotEmpty) {
return fallbackAccounts;
}
// 5. Jika tetap kosong, kembalikan empty list
return [];
}
}