import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../domain/entities/share_account.dart'; import '../../domain/entities/global_state.dart'; import '../../domain/entities/planting_record.dart'; import '../../domain/entities/batch_mining_record.dart'; import '../../domain/repositories/mining_repository.dart'; import '../../domain/usecases/mining/get_share_account.dart'; import '../../domain/usecases/mining/get_global_state.dart'; import '../../core/di/injection.dart'; final miningRepositoryProvider = Provider((ref) { return getIt(); }); // Use Cases Providers final getShareAccountUseCaseProvider = Provider((ref) { return getIt(); }); final getGlobalStateUseCaseProvider = Provider((ref) { return getIt(); }); // State Providers - 使用 keepAlive 缓存数据,避免重复请求 final shareAccountProvider = FutureProvider.family( (ref, accountSequence) async { // 空字符串不请求 if (accountSequence.isEmpty) return null; final useCase = ref.watch(getShareAccountUseCaseProvider); final result = await useCase(accountSequence); // 保持 provider 活跃,避免每次 rebuild 都重新请求 ref.keepAlive(); // 5 分钟后自动失效,允许刷新 final timer = Timer(const Duration(minutes: 5), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => throw Exception(failure.message), (account) => account, ); }, ); final globalStateProvider = FutureProvider((ref) async { final useCase = ref.watch(getGlobalStateUseCaseProvider); final result = await useCase(); // 保持 provider 活跃 ref.keepAlive(); // 5 分钟后自动失效 final timer = Timer(const Duration(minutes: 5), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => throw Exception(failure.message), (state) => state, ); }); final currentPriceProvider = Provider((ref) { final globalState = ref.watch(globalStateProvider); return globalState.when( data: (state) => state?.currentPrice ?? '0', loading: () => '0', error: (_, __) => '0', ); }); /// 挖矿记录请求参数 class MiningRecordsParams { final String accountSequence; final int page; final int pageSize; const MiningRecordsParams({ required this.accountSequence, this.page = 1, this.pageSize = 10, }); @override bool operator ==(Object other) => identical(this, other) || other is MiningRecordsParams && runtimeType == other.runtimeType && accountSequence == other.accountSequence && page == other.page && pageSize == other.pageSize; @override int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode; } /// 挖矿记录 Provider final miningRecordsProvider = FutureProvider.family( (ref, params) async { if (params.accountSequence.isEmpty) { return null; } final repository = ref.watch(miningRepositoryProvider); final result = await repository.getMiningRecords( params.accountSequence, page: params.page, pageSize: params.pageSize, ); ref.keepAlive(); final timer = Timer(const Duration(minutes: 5), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => throw Exception(failure.message), (records) => records, ); }, ); /// 参与记录请求参数 class PlantingRecordsParams { final String accountSequence; final int page; final int pageSize; const PlantingRecordsParams({ required this.accountSequence, this.page = 1, this.pageSize = 10, }); @override bool operator ==(Object other) => identical(this, other) || other is PlantingRecordsParams && runtimeType == other.runtimeType && accountSequence == other.accountSequence && page == other.page && pageSize == other.pageSize; @override int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode; } /// 参与记录 Provider final plantingRecordsProvider = FutureProvider.family( (ref, params) async { if (params.accountSequence.isEmpty) { return null; } final repository = ref.watch(miningRepositoryProvider); final result = await repository.getPlantingLedger( params.accountSequence, page: params.page, pageSize: params.pageSize, ); ref.keepAlive(); final timer = Timer(const Duration(minutes: 5), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => throw Exception(failure.message), (ledger) => ledger, ); }, ); /// 批量补发记录请求参数 class BatchMiningRecordsParams { final String accountSequence; final int page; final int pageSize; const BatchMiningRecordsParams({ required this.accountSequence, this.page = 1, this.pageSize = 20, }); @override bool operator ==(Object other) => identical(this, other) || other is BatchMiningRecordsParams && runtimeType == other.runtimeType && accountSequence == other.accountSequence && page == other.page && pageSize == other.pageSize; @override int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode; } /// 批量补发记录 Provider final batchMiningRecordsProvider = FutureProvider.family( (ref, params) async { if (params.accountSequence.isEmpty) { return null; } final repository = ref.watch(miningRepositoryProvider); final result = await repository.getBatchMiningRecords( params.accountSequence, page: params.page, pageSize: params.pageSize, ); ref.keepAlive(); final timer = Timer(const Duration(minutes: 5), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => throw Exception(failure.message), (records) => records, ); }, ); /// 检查用户是否有批量补发记录的 Provider final hasBatchMiningRecordsProvider = FutureProvider.family( (ref, accountSequence) async { if (accountSequence.isEmpty) { return false; } final repository = ref.watch(miningRepositoryProvider); final result = await repository.getBatchMiningRecords( accountSequence, page: 1, pageSize: 1, ); ref.keepAlive(); final timer = Timer(const Duration(minutes: 10), () { ref.invalidateSelf(); }); ref.onDispose(() => timer.cancel()); return result.fold( (failure) => false, (records) => records.total > 0, ); }, );