refactor(theme): 迁移主题感知颜色至 ThemeExtension

- 创建 AppThemeColors ThemeExtension 类,统一管理主题感知颜色(涨跌色、卡片背景、渐变等)
- 从 AppColorScheme 移除主题感知辅助函数,仅保留静态颜色常量
- 在 AppTheme 中注册 ThemeExtension,支持深色/浅色主题工厂
- 重构所有 UI 组件使用 context.appColors 访问主题颜色,替代硬编码的 AppColorScheme 方法调用
- 移除组件中重复的 isDark 判断逻辑,简化颜色获取方式
- 保持向后兼容性,所有现有功能不变
This commit is contained in:
2026-04-06 01:58:08 +08:00
parent 396668aa43
commit 7ed2435a4c
36 changed files with 658 additions and 810 deletions

View File

@@ -3,6 +3,7 @@ import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../kyc_page.dart';
import '../welfare_center_page.dart';
import 'menu_group_container.dart';
@@ -22,9 +23,6 @@ class MenuGroup1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return MenuGroupContainer(
child: Column(
children: [
@@ -44,7 +42,7 @@ class MenuGroup1 extends StatelessWidget {
// 实名认证
MenuRow(
icon: LucideIcons.shieldCheck,
iconColor: AppColorScheme.getUpColor(isDark),
iconColor: context.appColors.up,
title: '实名认证',
trailing: KycBadge(kycStatus: kycStatus),
onTap: () {
@@ -62,7 +60,7 @@ class MenuGroup1 extends StatelessWidget {
// 安全设置
MenuRow(
icon: LucideIcons.lock,
iconColor: colorScheme.onSurfaceVariant,
iconColor: context.colors.onSurfaceVariant,
title: '安全设置',
onTap: () => onShowComingSoon('安全设置'),
),
@@ -70,7 +68,7 @@ class MenuGroup1 extends StatelessWidget {
// 消息通知
MenuRow(
icon: LucideIcons.bell,
iconColor: colorScheme.onSurfaceVariant,
iconColor: context.colors.onSurfaceVariant,
title: '消息通知',
trailing: const RedDotIndicator(),
onTap: () => onShowComingSoon('消息通知'),

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// 菜单分组容器 - 统一的圆角卡片样式
///
@@ -12,19 +13,14 @@ class MenuGroupContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
width: double.infinity,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerHigh,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: child,

View File

@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../providers/theme_provider.dart';
/// KYC 状态徽章 (e.g. "已认证" green badge + chevron)
@@ -18,9 +19,7 @@ class KycBadge extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final green = AppColorScheme.getUpColor(isDark);
final colorScheme = Theme.of(context).colorScheme;
final green = context.appColors.up;
if (kycStatus == 2) {
return Row(
@@ -43,7 +42,7 @@ class KycBadge extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -70,7 +69,7 @@ class KycBadge extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -79,7 +78,7 @@ class KycBadge extends StatelessWidget {
return Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
);
}
}
@@ -105,7 +104,7 @@ class RedDotIndicator extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -118,8 +117,6 @@ class DarkModeRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final themeProvider = context.watch<ThemeProvider>();
return Padding(
@@ -131,16 +128,14 @@ class DarkModeRow extends StatelessWidget {
width: 36,
height: 36,
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainerHigh
: colorScheme.surfaceContainerHighest,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Icon(
LucideIcons.moon,
size: 18,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -160,9 +155,7 @@ class DarkModeRow extends StatelessWidget {
height: 24,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainerHigh
: colorScheme.surfaceContainerHighest,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(12),
),
child: AnimatedAlign(
@@ -174,7 +167,7 @@ class DarkModeRow extends StatelessWidget {
width: 20,
height: 20,
decoration: BoxDecoration(
color: colorScheme.onSurface,
color: context.colors.onSurface,
shape: BoxShape.circle,
),
),

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import 'avatar_circle.dart';
/// 用户资料卡片 - 头像 + 用户名 + 徽章 + chevron
@@ -11,19 +12,14 @@ class ProfileCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerHigh,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
),
child: Row(
@@ -58,7 +54,7 @@ class ProfileCard extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
),

View File

@@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:provider/provider.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../core/utils/toast_utils.dart';
import '../../../core/event/app_event_bus.dart';
import '../../../data/services/bonus_service.dart';
@@ -43,70 +43,36 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
}
// ============================================
// 主题感知颜色辅助
// ============================================
bool get _isDark => Theme.of(context).brightness == Brightness.dark;
/// 金色强调色 ($gold-accent)
Color get _goldAccent =>
_isDark ? AppColorScheme.darkSecondary : const Color(0xFFF59E0B);
/// 盈利绿色 ($profit-green)
Color get _profitGreen =>
_isDark ? const Color(0xFF4ADE80) : const Color(0xFF16A34A);
/// 盈利绿色背景 ($profit-green-bg)
Color get _profitGreenBg =>
_isDark ? const Color(0xFF052E16) : const Color(0xFFF0FDF4);
/// 文字静默色 ($text-muted)
Color get _textMuted =>
_isDark ? AppColorScheme.darkOnSurfaceMuted : AppColorScheme.lightOnSurfaceMuted;
/// 第三级背景色 ($bg-tertiary)
Color get _bgTertiary =>
_isDark ? AppColorScheme.darkSurfaceContainerHigh : AppColorScheme.lightSurfaceContainer;
/// 卡片表面色 ($surface-card)
Color get _surfaceCard =>
_isDark ? AppColorScheme.darkSurfaceContainer : AppColorScheme.lightSurfaceLowest;
/// 反色文字 ($text-inverse)
Color get _textInverse =>
_isDark ? AppColorScheme.darkInverseSurface : AppColorScheme.lightSurfaceLowest;
// ============================================
// 容器样式辅助
// ============================================
/// 标准卡片容器
BoxDecoration _cardDecoration({Color? borderColor}) {
final scheme = Theme.of(context).colorScheme;
return BoxDecoration(
color: _surfaceCard,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: borderColor ?? scheme.outlineVariant.withValues(alpha: 0.15),
color: borderColor ?? context.appColors.ghostBorder,
),
);
}
/// 金色渐变卡片容器
BoxDecoration _goldGradientDecoration() {
final goldAccent = context.appColors.accentPrimary;
return BoxDecoration(
borderRadius: BorderRadius.circular(AppRadius.xl),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
_goldAccent.withValues(alpha: 0.15),
_surfaceCard,
goldAccent.withValues(alpha: 0.15),
context.appColors.surfaceCard,
],
),
border: Border.all(
color: _goldAccent.withValues(alpha: 0.3),
color: goldAccent.withValues(alpha: 0.3),
width: 1,
),
);
@@ -164,16 +130,12 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final goldAccent = context.appColors.accentPrimary;
return Scaffold(
backgroundColor: _isDark
? AppColorScheme.darkBackground
: AppColorScheme.lightBackground,
backgroundColor: context.colors.surface,
appBar: AppBar(
backgroundColor: _isDark
? AppColorScheme.darkBackground
: AppColorScheme.lightSurfaceLowest,
backgroundColor: context.colors.surface,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: false,
@@ -183,20 +145,20 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
style: AppTextStyles.headlineLarge(context),
),
leading: IconButton(
icon: Icon(LucideIcons.arrowLeft, color: colorScheme.onSurface, size: 24),
icon: Icon(LucideIcons.arrowLeft, color: context.colors.onSurface, size: 24),
onPressed: () => Navigator.of(context).pop(),
),
),
body: _isLoading
? Center(
child: CircularProgressIndicator(
color: _goldAccent,
color: goldAccent,
strokeWidth: 2.5,
),
)
: RefreshIndicator(
onRefresh: _loadData,
color: _goldAccent,
color: goldAccent,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.fromLTRB(16, 8, 16, 32),
@@ -222,7 +184,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildReferralCodeCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final goldAccent = context.appColors.accentPrimary;
final referralCode = _welfareData?['referralCode'] as String? ?? '';
return Container(
@@ -235,7 +197,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// Header Row: gift icon + 标题
Row(
children: [
Icon(LucideIcons.gift, color: _goldAccent, size: 24),
Icon(LucideIcons.gift, color: goldAccent, size: 24),
const SizedBox(width: 10),
Text(
'我的邀请码',
@@ -250,7 +212,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
referralCode.isEmpty ? '暂无邀请码' : referralCode,
style: AppTextStyles.displayMedium(context).copyWith(
fontWeight: FontWeight.w800,
color: _goldAccent,
color: goldAccent,
letterSpacing: 2,
),
),
@@ -266,17 +228,17 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
ToastUtils.show('邀请码已复制');
},
style: ElevatedButton.styleFrom(
backgroundColor: _goldAccent,
foregroundColor: _textInverse,
backgroundColor: goldAccent,
foregroundColor: context.colors.onSurface,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.lg),
),
disabledBackgroundColor: _goldAccent.withValues(alpha: 0.4),
disabledBackgroundColor: goldAccent.withValues(alpha: 0.4),
),
child: Text(
'复制邀请码',
style: AppTextStyles.headlineMedium(context).copyWith(color: _textInverse),
style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onSurface),
),
),
),
@@ -290,7 +252,8 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildNewUserBonusCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final profitGreen = context.appColors.up;
final profitGreenBg = context.appColors.upBackground;
final newUserBonus = _welfareData?['newUserBonus'] as Map<String, dynamic>?;
final eligible = newUserBonus?['eligible'] as bool? ?? false;
final claimed = newUserBonus?['claimed'] as bool? ?? false;
@@ -341,7 +304,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
),
),
if (showAvailableBadge)
_statusBadge(badgeText, _profitGreen, _profitGreenBg),
_statusBadge(badgeText, profitGreen, profitGreenBg),
],
),
const SizedBox(height: 12),
@@ -349,21 +312,21 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
'+100 USDT',
style: AppTextStyles.displayLarge(context).copyWith(
fontWeight: FontWeight.w800,
color: claimed ? colorScheme.onSurfaceVariant : _profitGreen,
color: claimed ? context.colors.onSurfaceVariant : profitGreen,
),
),
const SizedBox(height: 8),
Text(
description,
style: AppTextStyles.bodyLarge(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
const SizedBox(height: 16),
_fullWidthButton(
text: buttonText,
backgroundColor: _profitGreen,
foregroundColor: colorScheme.onPrimary,
backgroundColor: profitGreen,
foregroundColor: context.colors.onPrimary,
onPressed: canClaim ? () => _claimNewUserBonus() : null,
),
],
@@ -376,7 +339,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildReferralRewardsSection(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final referralRewards =
_welfareData?['referralRewards'] as List<dynamic>? ?? [];
@@ -392,7 +354,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Text(
'每邀请一位好友充值达标奖励100 USDT',
style: AppTextStyles.bodySmall(context).copyWith(
color: _textMuted,
color: context.appColors.onSurfaceMuted,
),
),
const SizedBox(height: 12),
@@ -410,7 +372,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildEmptyReferralList(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Padding(
padding: const EdgeInsets.all(32),
child: Center(
@@ -419,13 +380,13 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Icon(
LucideIcons.users,
size: 36,
color: _textMuted.withValues(alpha: 0.4),
color: context.appColors.onSurfaceMuted.withValues(alpha: 0.4),
),
const SizedBox(height: 8),
Text(
'暂无推广用户',
style: AppTextStyles.bodyLarge(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
],
@@ -435,8 +396,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildReferralListItems(BuildContext context, List<dynamic> referralRewards) {
final colorScheme = Theme.of(context).colorScheme;
return Column(
children: List.generate(referralRewards.length, (index) {
final data = referralRewards[index] as Map<String, dynamic>;
@@ -492,7 +451,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
height: 6,
child: LinearProgressIndicator(
value: progress,
backgroundColor: _bgTertiary,
backgroundColor: context.appColors.surfaceCardHigh,
valueColor: AlwaysStoppedAnimation<Color>(progressColor),
minHeight: 6,
),
@@ -505,7 +464,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Divider(
height: 1,
thickness: 1,
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
],
);
@@ -514,19 +473,18 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildAvatar(String username) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: _bgTertiary,
color: context.appColors.surfaceCardHigh,
shape: BoxShape.circle,
),
child: Center(
child: Text(
username.isNotEmpty ? username[0].toUpperCase() : '?',
style: AppTextStyles.headlineSmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -548,9 +506,9 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
/// 根据状态获取进度条颜色
Color _referralProgressColor(int claimableCount, double progress) {
if (claimableCount > 0) return _profitGreen;
if (progress > 0) return _goldAccent;
return _bgTertiary;
if (claimableCount > 0) return context.appColors.up;
if (progress > 0) return context.appColors.accentPrimary;
return context.appColors.surfaceCardHigh;
}
/// 构建推荐奖励的操作按钮
@@ -560,6 +518,9 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
required List<dynamic> milestones,
required double progress,
}) {
final profitGreen = context.appColors.up;
final profitGreenBg = context.appColors.upBackground;
if (claimableCount > 0) {
final int milestoneValue = milestones.isNotEmpty
? (milestones.firstWhere(
@@ -570,7 +531,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
return GestureDetector(
onTap: () => _claimReferralBonus(data['userId'] as int, milestoneValue),
child: _statusBadge('领取', _profitGreen, _profitGreenBg),
child: _statusBadge('领取', profitGreen, profitGreenBg),
);
}
if (progress > 0) {
@@ -578,7 +539,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
return Text(
'待达标',
style: AppTextStyles.labelLarge(context).copyWith(color: _textMuted),
style: AppTextStyles.labelLarge(context).copyWith(color: context.appColors.onSurfaceMuted),
);
}
@@ -587,13 +548,11 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildRulesCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
decoration: BoxDecoration(
color: _bgTertiary,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Column(
@@ -613,15 +572,12 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildRuleItem(String text) {
final ruleTextColor = _isDark
? AppColorScheme.darkOnSurfaceVariant
: const Color(0xFF475569);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Text(
'\u2022 $text',
style: AppTextStyles.bodyMedium(context).copyWith(
color: ruleTextColor,
color: context.colors.onSurfaceVariant,
),
),
);