feat(mining-app): implement hide/show amounts toggle
- Add hideAmountsProvider to control amount visibility - Add tap handler to eye icon in total contribution card - Toggle icon between visibility_outlined and visibility_off_outlined - Hide amounts with **** when toggled in: - Total contribution value - Three column stats (personal, team level, team bonus) - Today's estimated earnings - Contribution detail summary rows Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
02cc79d67a
commit
91b8cca41c
|
|
@ -71,16 +71,16 @@ class ContributionPage extends ConsumerWidget {
|
||||||
sliver: SliverList(
|
sliver: SliverList(
|
||||||
delegate: SliverChildListDelegate([
|
delegate: SliverChildListDelegate([
|
||||||
// 总贡献值卡片
|
// 总贡献值卡片
|
||||||
_buildTotalContributionCard(contribution, isLoading),
|
_buildTotalContributionCard(ref, contribution, isLoading),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// 三栏统计
|
// 三栏统计
|
||||||
_buildThreeColumnStats(contribution, isLoading),
|
_buildThreeColumnStats(ref, contribution, isLoading),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// 今日预估收益
|
// 今日预估收益
|
||||||
_buildTodayEstimateCard(estimatedEarnings, isLoading || isStatsLoading),
|
_buildTodayEstimateCard(ref, estimatedEarnings, isLoading || isStatsLoading),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// 贡献值明细(三类汇总)
|
// 贡献值明细(三类汇总)
|
||||||
_buildContributionDetailCard(context, contribution, isLoading),
|
_buildContributionDetailCard(context, ref, contribution, isLoading),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// 团队层级统计
|
// 团队层级统计
|
||||||
_buildTeamStatsCard(contribution, isLoading),
|
_buildTeamStatsCard(contribution, isLoading),
|
||||||
|
|
@ -156,8 +156,9 @@ class ContributionPage extends ConsumerWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTotalContributionCard(Contribution? contribution, bool isLoading) {
|
Widget _buildTotalContributionCard(WidgetRef ref, Contribution? contribution, bool isLoading) {
|
||||||
final total = contribution?.totalContribution ?? '0';
|
final total = contribution?.totalContribution ?? '0';
|
||||||
|
final hideAmounts = ref.watch(hideAmountsProvider);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -174,12 +175,21 @@ class ContributionPage extends ConsumerWidget {
|
||||||
'总贡献值',
|
'总贡献值',
|
||||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText),
|
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText),
|
||||||
),
|
),
|
||||||
Icon(Icons.visibility_outlined, color: _grayText.withOpacity(0.5), size: 18),
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
ref.read(hideAmountsProvider.notifier).state = !hideAmounts;
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
hideAmounts ? Icons.visibility_off_outlined : Icons.visibility_outlined,
|
||||||
|
color: _grayText.withOpacity(0.5),
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
DataText(
|
DataText(
|
||||||
data: isLoading ? null : formatAmount(total),
|
data: isLoading ? null : (hideAmounts ? '******' : formatAmount(total)),
|
||||||
isLoading: isLoading,
|
isLoading: isLoading,
|
||||||
placeholder: '----',
|
placeholder: '----',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
|
|
@ -214,7 +224,8 @@ class ContributionPage extends ConsumerWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildThreeColumnStats(Contribution? contribution, bool isLoading) {
|
Widget _buildThreeColumnStats(WidgetRef ref, Contribution? contribution, bool isLoading) {
|
||||||
|
final hideAmounts = ref.watch(hideAmountsProvider);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -223,15 +234,15 @@ class ContributionPage extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
_buildStatColumn('个人贡献值', contribution?.personalContribution, isLoading, false),
|
_buildStatColumn('个人贡献值', contribution?.personalContribution, isLoading, false, hideAmounts),
|
||||||
_buildStatColumn('团队层级', contribution?.teamLevelContribution, isLoading, true),
|
_buildStatColumn('团队层级', contribution?.teamLevelContribution, isLoading, true, hideAmounts),
|
||||||
_buildStatColumn('团队奖励', contribution?.teamBonusContribution, isLoading, true),
|
_buildStatColumn('团队奖励', contribution?.teamBonusContribution, isLoading, true, hideAmounts),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStatColumn(String label, String? value, bool isLoading, bool showLeftBorder) {
|
Widget _buildStatColumn(String label, String? value, bool isLoading, bool showLeftBorder, bool hideAmounts) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: showLeftBorder
|
decoration: showLeftBorder
|
||||||
|
|
@ -245,7 +256,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
Text(label, style: const TextStyle(fontSize: 12, color: _grayText)),
|
Text(label, style: const TextStyle(fontSize: 12, color: _grayText)),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
DataText(
|
DataText(
|
||||||
data: value != null ? formatAmount(value) : null,
|
data: value != null ? (hideAmounts ? '****' : formatAmount(value)) : null,
|
||||||
isLoading: isLoading,
|
isLoading: isLoading,
|
||||||
placeholder: '--',
|
placeholder: '--',
|
||||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: _darkText),
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: _darkText),
|
||||||
|
|
@ -257,7 +268,8 @@ class ContributionPage extends ConsumerWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTodayEstimateCard(EstimatedEarnings earnings, bool isLoading) {
|
Widget _buildTodayEstimateCard(WidgetRef ref, EstimatedEarnings earnings, bool isLoading) {
|
||||||
|
final hideAmounts = ref.watch(hideAmountsProvider);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -306,7 +318,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: earnings.isValid ? formatAmount(earnings.dailyShares) : '--',
|
text: hideAmounts ? '****' : (earnings.isValid ? formatAmount(earnings.dailyShares) : '--'),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|
@ -329,9 +341,11 @@ class ContributionPage extends ConsumerWidget {
|
||||||
|
|
||||||
Widget _buildContributionDetailCard(
|
Widget _buildContributionDetailCard(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
Contribution? contribution,
|
Contribution? contribution,
|
||||||
bool isLoading,
|
bool isLoading,
|
||||||
) {
|
) {
|
||||||
|
final hideAmounts = ref.watch(hideAmountsProvider);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -374,6 +388,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
title: '本人种植',
|
title: '本人种植',
|
||||||
subtitle: '个人认种榴莲树产生的贡献值',
|
subtitle: '个人认种榴莲树产生的贡献值',
|
||||||
amount: contribution?.personalContribution ?? '0',
|
amount: contribution?.personalContribution ?? '0',
|
||||||
|
hideAmounts: hideAmounts,
|
||||||
),
|
),
|
||||||
const Divider(height: 24),
|
const Divider(height: 24),
|
||||||
_buildDetailSummaryRow(
|
_buildDetailSummaryRow(
|
||||||
|
|
@ -382,6 +397,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
title: '团队层级',
|
title: '团队层级',
|
||||||
subtitle: '直推及间推用户认种产生的贡献值',
|
subtitle: '直推及间推用户认种产生的贡献值',
|
||||||
amount: contribution?.teamLevelContribution ?? '0',
|
amount: contribution?.teamLevelContribution ?? '0',
|
||||||
|
hideAmounts: hideAmounts,
|
||||||
),
|
),
|
||||||
const Divider(height: 24),
|
const Divider(height: 24),
|
||||||
_buildDetailSummaryRow(
|
_buildDetailSummaryRow(
|
||||||
|
|
@ -390,6 +406,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
title: '团队奖励',
|
title: '团队奖励',
|
||||||
subtitle: '满足条件后获得的额外奖励贡献值',
|
subtitle: '满足条件后获得的额外奖励贡献值',
|
||||||
amount: contribution?.teamBonusContribution ?? '0',
|
amount: contribution?.teamBonusContribution ?? '0',
|
||||||
|
hideAmounts: hideAmounts,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -445,6 +462,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
required String title,
|
required String title,
|
||||||
required String subtitle,
|
required String subtitle,
|
||||||
required String amount,
|
required String amount,
|
||||||
|
required bool hideAmounts,
|
||||||
}) {
|
}) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -475,7 +493,7 @@ class ContributionPage extends ConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
formatAmount(amount),
|
hideAmounts ? '****' : formatAmount(amount),
|
||||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _green),
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _green),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -173,3 +173,6 @@ final estimatedEarningsProvider = Provider.family<EstimatedEarnings, String>((re
|
||||||
isValid: true,
|
isValid: true,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// 控制是否隐藏金额显示的状态
|
||||||
|
final hideAmountsProvider = StateProvider<bool>((ref) => false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue