rwadurian/frontend/mining-app/lib/presentation/providers/mining_providers.dart

180 lines
4.8 KiB
Dart

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/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<MiningRepository>((ref) {
return getIt<MiningRepository>();
});
// Use Cases Providers
final getShareAccountUseCaseProvider = Provider<GetShareAccount>((ref) {
return getIt<GetShareAccount>();
});
final getGlobalStateUseCaseProvider = Provider<GetGlobalState>((ref) {
return getIt<GetGlobalState>();
});
// State Providers - 使用 keepAlive 缓存数据,避免重复请求
final shareAccountProvider = FutureProvider.family<ShareAccount?, String>(
(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<GlobalState?>((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<String>((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<MiningRecordsPage?, MiningRecordsParams>(
(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<PlantingLedgerPage?, PlantingRecordsParams>(
(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,
);
},
);