import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/constants/app_defaults.dart'; import '../../../core/providers/app_providers.dart'; import '../../../data/local/models/models.dart'; final appConfigProvider = AsyncNotifierProvider(AppConfigNotifier.new); class AppConfigNotifier extends AsyncNotifier { @override Future build() async { final isar = await ref.watch(isarProvider.future); final config = await isar.appConfigs.get(AppDefaults.singletonId); if (config != null) return config; final fresh = AppConfig.createDefault(); await isar.writeTxn(() => isar.appConfigs.put(fresh)); return fresh; } Future _persist(AppConfig config) async { final isar = await ref.read(isarProvider.future); await isar.writeTxn(() => isar.appConfigs.put(config)); state = AsyncData(config); return config; } /// Called after a scoring session is saved successfully. Future incrementTrialCount() async { final current = state.value; if (current == null || current.isVipUnlocked) return; final next = current.copyWith( usedTrialCount: current.usedTrialCount + 1, ); await _persist(next); } /// Marks the app as unlocked via IAP purchase or restore. Future markUnlocked({required bool fromRestore}) async { final current = state.value; if (current == null) return; final next = current.copyWith( isVipUnlocked: true, vipUnlockedAt: DateTime.now(), entitlementSource: fromRestore ? EntitlementSource.restore : EntitlementSource.purchase, ); await _persist(next); } Future setLastError(String? message) async { final current = state.value; if (current == null) return; await _persist(current.copyWith(lastIapErrorMessage: message)); } /// Debug-only: instantly unlock without going through App Store. Future debugUnlock() async { await markUnlocked(fromRestore: false); } }