fix(ui): 修复主题切换功能,支持明暗主题动态切换
- 替换所有硬编码颜色为动态颜色 - 所有页面使用 Theme.of(context) 获取主题颜色 - 支持深色和浅色主题切换 - 修复 GlassPanel 和 NeonGlow 组件的主题适配 - 完善 lightMaterial ColorScheme 定义 - 测试主题切换功能正常 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,8 +22,10 @@ class AssetCard extends StatelessWidget {
|
||||
final VoidCallback? onTap;
|
||||
|
||||
/// 默认渐变色 - Neon Blue → Electric Purple
|
||||
static const defaultGradient = LinearGradient(
|
||||
colors: [AppColorScheme.darkPrimary, AppColorScheme.darkSecondary],
|
||||
static LinearGradient defaultGradientBuilder(bool isDark) => LinearGradient(
|
||||
colors: isDark
|
||||
? [AppColorScheme.darkPrimary, AppColorScheme.darkSecondary]
|
||||
: [AppColorScheme.lightPrimary, AppColorScheme.lightSecondary],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
);
|
||||
@@ -50,7 +52,8 @@ class AssetCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ShadTheme.of(context);
|
||||
final cardGradient = gradient ?? defaultGradient;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final cardGradient = gradient ?? defaultGradientBuilder(isDark);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
|
||||
@@ -61,8 +61,12 @@ class GlassPanel extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bgColor = backgroundColor ?? AppColorScheme.glassPanelBackground;
|
||||
final brColor = borderColor ?? AppColorScheme.glassPanelBorder;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final bgColor = backgroundColor ??
|
||||
colorScheme.surfaceBright.withOpacity(isDark ? 0.4 : 0.6);
|
||||
final brColor = borderColor ??
|
||||
colorScheme.outlineVariant.withOpacity(0.15);
|
||||
final br = borderRadius ?? BorderRadius.circular(AppRadius.xl);
|
||||
|
||||
Widget content = ClipRRect(
|
||||
@@ -142,8 +146,11 @@ class GlassCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final br = borderRadius ?? BorderRadius.circular(AppRadius.xl);
|
||||
final glowColor = neonGlowColor ?? AppColorScheme.neonGlowPrimary;
|
||||
final glowColor = neonGlowColor ??
|
||||
colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08);
|
||||
|
||||
Widget card = GlassPanel(
|
||||
padding: padding ?? EdgeInsets.all(AppSpacing.md),
|
||||
@@ -206,14 +213,17 @@ class GlassBottomSheet extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.glassPanelBackground,
|
||||
color: colorScheme.surfaceBright.withOpacity(isDark ? 0.4 : 0.6),
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(AppRadius.xxl),
|
||||
),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.glassPanelBorder,
|
||||
color: colorScheme.outlineVariant.withOpacity(0.15),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
@@ -231,7 +241,7 @@ class GlassBottomSheet extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.5),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
@@ -250,10 +260,10 @@ class GlassBottomSheet extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Text(
|
||||
title!,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -263,14 +273,14 @@ class GlassBottomSheet extends StatelessWidget {
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(AppSpacing.sm),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkOutlineVariant
|
||||
.withValues(alpha: 0.2),
|
||||
color: colorScheme.outlineVariant
|
||||
.withOpacity(0.2),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -91,7 +91,10 @@ class GradientButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final buttonGradient = gradient ?? AppColorScheme.darkCtaGradient;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final buttonGradient = gradient ??
|
||||
(isDark ? AppColorScheme.darkCtaGradient : AppColorScheme.lightCtaGradient);
|
||||
|
||||
return Container(
|
||||
width: isFullWidth ? double.infinity : null,
|
||||
|
||||
@@ -94,7 +94,7 @@ class NeonGlow extends StatelessWidget {
|
||||
}) {
|
||||
return NeonGlow(
|
||||
key: key,
|
||||
glowColor: AppColorScheme.darkError.withValues(alpha: 0.3),
|
||||
glowColor: AppColorScheme.down.withOpacity(0.3),
|
||||
blurRadius: blurRadius,
|
||||
borderRadius: borderRadius,
|
||||
child: child,
|
||||
@@ -205,65 +205,77 @@ class _NeonButtonState extends State<NeonButton>
|
||||
}
|
||||
|
||||
Color get _backgroundColor {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
switch (widget.type) {
|
||||
case NeonButtonType.primary:
|
||||
return AppColorScheme.darkPrimary;
|
||||
return colorScheme.primary;
|
||||
case NeonButtonType.secondary:
|
||||
return AppColorScheme.darkSecondary;
|
||||
return colorScheme.secondary;
|
||||
case NeonButtonType.tertiary:
|
||||
return AppColorScheme.darkTertiary;
|
||||
return AppColorScheme.up;
|
||||
case NeonButtonType.error:
|
||||
return AppColorScheme.darkError;
|
||||
return AppColorScheme.down;
|
||||
case NeonButtonType.outline:
|
||||
return Colors.transparent;
|
||||
}
|
||||
}
|
||||
|
||||
Color get _foregroundColor {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
switch (widget.type) {
|
||||
case NeonButtonType.primary:
|
||||
return AppColorScheme.darkOnPrimaryFixed;
|
||||
return isDark ? AppColorScheme.darkOnPrimary : const Color(0xFFFFFFFF);
|
||||
case NeonButtonType.secondary:
|
||||
return AppColorScheme.darkOnSecondary;
|
||||
return isDark ? AppColorScheme.darkOnSecondary : const Color(0xFFFFFFFF);
|
||||
case NeonButtonType.tertiary:
|
||||
return AppColorScheme.darkOnTertiaryFixed;
|
||||
return isDark ? AppColorScheme.darkOnTertiary : const Color(0xFFFFFFFF);
|
||||
case NeonButtonType.error:
|
||||
return AppColorScheme.darkOnError;
|
||||
return const Color(0xFFFFFFFF);
|
||||
case NeonButtonType.outline:
|
||||
return AppColorScheme.darkPrimary;
|
||||
return colorScheme.primary;
|
||||
}
|
||||
}
|
||||
|
||||
Color get _glowColor {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
switch (widget.type) {
|
||||
case NeonButtonType.primary:
|
||||
return AppColorScheme.neonGlowPrimary;
|
||||
return colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08);
|
||||
case NeonButtonType.secondary:
|
||||
return AppColorScheme.neonGlowSecondary;
|
||||
return colorScheme.secondary.withOpacity(isDark ? 0.15 : 0.08);
|
||||
case NeonButtonType.tertiary:
|
||||
return AppColorScheme.neonGlowTertiary;
|
||||
return AppColorScheme.up.withOpacity(isDark ? 0.2 : 0.1);
|
||||
case NeonButtonType.error:
|
||||
return AppColorScheme.darkError.withValues(alpha: 0.3);
|
||||
return AppColorScheme.down.withOpacity(0.3);
|
||||
case NeonButtonType.outline:
|
||||
return AppColorScheme.neonGlowPrimary;
|
||||
return colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
LinearGradient? get _gradient {
|
||||
if (widget.type == NeonButtonType.outline) return null;
|
||||
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
switch (widget.type) {
|
||||
case NeonButtonType.primary:
|
||||
return const LinearGradient(
|
||||
colors: [AppColorScheme.darkPrimary, AppColorScheme.darkPrimaryContainer],
|
||||
begin: Alignment(-0.7, -0.7),
|
||||
end: Alignment(0.7, 0.7),
|
||||
return LinearGradient(
|
||||
colors: [colorScheme.primary, colorScheme.primaryContainer],
|
||||
begin: const Alignment(-0.7, -0.7),
|
||||
end: const Alignment(0.7, 0.7),
|
||||
);
|
||||
case NeonButtonType.secondary:
|
||||
return const LinearGradient(
|
||||
colors: [AppColorScheme.darkSecondary, AppColorScheme.darkSecondaryFixed],
|
||||
begin: Alignment(-0.7, -0.7),
|
||||
end: Alignment(0.7, 0.7),
|
||||
return LinearGradient(
|
||||
colors: [colorScheme.secondary, colorScheme.secondaryContainer ?? colorScheme.secondary],
|
||||
begin: const Alignment(-0.7, -0.7),
|
||||
end: const Alignment(0.7, 0.7),
|
||||
);
|
||||
case NeonButtonType.tertiary:
|
||||
return AppColorScheme.buyGradient;
|
||||
@@ -276,6 +288,9 @@ class _NeonButtonState extends State<NeonButton>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
final button = GestureDetector(
|
||||
onTapDown: widget.onPressed != null ? _onTapDown : null,
|
||||
onTapUp: widget.onPressed != null ? _onTapUp : null,
|
||||
@@ -292,7 +307,7 @@ class _NeonButtonState extends State<NeonButton>
|
||||
borderRadius: BorderRadius.circular(AppRadius.xxl),
|
||||
border: widget.type == NeonButtonType.outline
|
||||
? Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.3),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.3),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
|
||||
@@ -38,15 +38,16 @@ class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixi
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Consumer<AssetProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => provider.refreshAll(force: true),
|
||||
color: AppColorScheme.darkPrimary,
|
||||
backgroundColor: AppColorScheme.darkSurfaceContainer,
|
||||
color: colorScheme.primary,
|
||||
backgroundColor: colorScheme.surfaceContainerHighest,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: AppSpacing.pagePadding,
|
||||
@@ -81,6 +82,9 @@ class _AssetCard 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: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm),
|
||||
@@ -89,7 +93,7 @@ class _AssetCard extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.neonGlowPrimary,
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
|
||||
blurRadius: 20,
|
||||
),
|
||||
],
|
||||
@@ -102,7 +106,7 @@ class _AssetCard extends StatelessWidget {
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.2,
|
||||
color: Colors.white.withValues(alpha: 0.7),
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
@@ -121,7 +125,7 @@ class _AssetCard extends StatelessWidget {
|
||||
vertical: AppSpacing.xs + AppSpacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.1),
|
||||
color: Colors.white.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
child: Row(
|
||||
@@ -129,7 +133,7 @@ class _AssetCard extends StatelessWidget {
|
||||
children: [
|
||||
Icon(
|
||||
LucideIcons.trendingUp,
|
||||
color: Colors.white.withValues(alpha: 0.7),
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
size: 14,
|
||||
),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
@@ -137,7 +141,7 @@ class _AssetCard extends StatelessWidget {
|
||||
'总盈亏: ${overview?.totalProfit ?? '0.00'} USDT',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.white.withValues(alpha: 0.7),
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -163,10 +167,13 @@ class _TabSelector extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceContainer,
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Row(
|
||||
@@ -182,12 +189,12 @@ class _TabSelector extends StatelessWidget {
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? AppColorScheme.darkPrimary : Colors.transparent,
|
||||
color: isSelected ? colorScheme.primary : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
boxShadow: isSelected
|
||||
? [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.neonGlowPrimary,
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
|
||||
blurRadius: 10,
|
||||
),
|
||||
]
|
||||
@@ -197,7 +204,7 @@ class _TabSelector extends StatelessWidget {
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected ? AppColorScheme.darkOnPrimaryFixed : AppColorScheme.darkOnSurfaceVariant,
|
||||
color: isSelected ? colorScheme.onPrimary : colorScheme.onSurfaceVariant,
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
),
|
||||
),
|
||||
@@ -220,6 +227,7 @@ class _FundAccountCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final fund = provider.fundAccount;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GlassPanel(
|
||||
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.xs),
|
||||
@@ -233,7 +241,7 @@ class _FundAccountCard extends StatelessWidget {
|
||||
'USDT 余额',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
@@ -246,14 +254,14 @@ class _FundAccountCard extends StatelessWidget {
|
||||
Text(
|
||||
'充提记录',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
LucideIcons.chevronRight,
|
||||
size: 14,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -266,7 +274,7 @@ class _FundAccountCard extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
@@ -320,6 +328,8 @@ class _TradeAccountCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GlassPanel(
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Column(
|
||||
@@ -330,7 +340,7 @@ class _TradeAccountCard extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
@@ -363,6 +373,8 @@ class _EmptyState extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(AppSpacing.xl),
|
||||
@@ -371,12 +383,12 @@ class _EmptyState extends StatelessWidget {
|
||||
Icon(
|
||||
icon,
|
||||
size: 48,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text(
|
||||
message,
|
||||
style: TextStyle(color: AppColorScheme.darkOnSurfaceVariant),
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -393,6 +405,8 @@ class _HoldingItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm),
|
||||
child: Row(
|
||||
@@ -401,14 +415,14 @@ class _HoldingItem extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.1),
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
holding.coinCode.substring(0, 1),
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -424,14 +438,14 @@ class _HoldingItem extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'数量: ${holding.quantity}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -444,7 +458,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
'${holding.currentValue} USDT',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
|
||||
@@ -37,14 +37,15 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Consumer<AssetProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => provider.refreshAll(force: true),
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.fromLTRB(24, 8, 24, 100),
|
||||
@@ -185,6 +186,8 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
|
||||
class _GreetingSection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Consumer<AuthProvider>(
|
||||
builder: (context, auth, _) {
|
||||
return Column(
|
||||
@@ -193,7 +196,7 @@ class _GreetingSection extends StatelessWidget {
|
||||
Text(
|
||||
'欢迎回来,',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
@@ -201,8 +204,8 @@ class _GreetingSection extends StatelessWidget {
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${auth.user?.username ?? '用户'}',
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
),
|
||||
@@ -222,14 +225,17 @@ class _GlassBalanceCard 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(32),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceBright.withValues(alpha: 0.4),
|
||||
color: colorScheme.surfaceBright.withOpacity(isDark ? 0.4 : 0.6),
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.1),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
@@ -243,7 +249,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
height: 128,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.2 : 0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -256,7 +262,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
height: 128,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppColorScheme.darkSecondary.withValues(alpha: 0.1),
|
||||
color: colorScheme.secondary.withOpacity(isDark ? 0.1 : 0.05),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -270,7 +276,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
Text(
|
||||
'总资产',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 11,
|
||||
letterSpacing: 2,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -279,7 +285,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
const SizedBox(width: 8),
|
||||
Icon(
|
||||
LucideIcons.eye,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
size: 14,
|
||||
),
|
||||
],
|
||||
@@ -291,8 +297,8 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
overview?.totalAsset ?? '0.00',
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 48,
|
||||
letterSpacing: -2,
|
||||
@@ -304,7 +310,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
child: Text(
|
||||
'USDT',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
@@ -317,7 +323,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.up.withValues(alpha: 0.1),
|
||||
color: AppColorScheme.up.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
@@ -341,7 +347,7 @@ class _GlassBalanceCard extends StatelessWidget {
|
||||
Text(
|
||||
"Today's PNL",
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
@@ -370,19 +376,21 @@ class _QuickActionsGrid extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_QuickActionBtn(
|
||||
icon: LucideIcons.plus,
|
||||
label: '充值',
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
onTap: onDeposit,
|
||||
),
|
||||
_QuickActionBtn(
|
||||
icon: LucideIcons.wallet,
|
||||
label: '提现',
|
||||
color: AppColorScheme.darkSecondary,
|
||||
color: colorScheme.secondary,
|
||||
onTap: onWithdraw,
|
||||
),
|
||||
_QuickActionBtn(
|
||||
@@ -394,7 +402,7 @@ class _QuickActionsGrid extends StatelessWidget {
|
||||
_QuickActionBtn(
|
||||
icon: LucideIcons.trendingUp,
|
||||
label: '交易',
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
onTap: () {
|
||||
// TODO: 实现跳转到交易页面的功能
|
||||
},
|
||||
@@ -427,6 +435,8 @@ class _QuickActionBtnState extends State<_QuickActionBtn> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: widget.onTap,
|
||||
onTapDown: (_) => setState(() => _isPressed = true),
|
||||
@@ -440,14 +450,14 @@ class _QuickActionBtnState extends State<_QuickActionBtn> {
|
||||
height: 56,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppColorScheme.darkSurfaceHigh,
|
||||
color: colorScheme.surfaceContainerHigh,
|
||||
border: Border.all(
|
||||
color: widget.color.withValues(alpha: 0.2),
|
||||
color: widget.color.withOpacity(0.2),
|
||||
),
|
||||
boxShadow: _isPressed
|
||||
? [
|
||||
BoxShadow(
|
||||
color: widget.color.withValues(alpha: 0.4),
|
||||
color: widget.color.withOpacity(0.4),
|
||||
blurRadius: 20,
|
||||
spreadRadius: 0,
|
||||
),
|
||||
@@ -464,7 +474,7 @@ class _QuickActionBtnState extends State<_QuickActionBtn> {
|
||||
Text(
|
||||
widget.label,
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -483,16 +493,18 @@ class _HoldingsSection extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// 标题行
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
'我的持仓',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
letterSpacing: -0.5,
|
||||
@@ -501,12 +513,12 @@ class _HoldingsSection extends StatelessWidget {
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColorScheme.darkPrimary,
|
||||
foregroundColor: colorScheme.primary,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
Text(
|
||||
'资产详情',
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
|
||||
),
|
||||
@@ -514,7 +526,7 @@ class _HoldingsSection extends StatelessWidget {
|
||||
Icon(
|
||||
LucideIcons.chevronRight,
|
||||
size: 16,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -535,14 +547,17 @@ class _EmptyHoldings 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.symmetric(vertical: 48, horizontal: 24),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceLow.withValues(alpha: 0.5),
|
||||
color: colorScheme.surfaceContainerLow.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.1),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
@@ -562,8 +577,8 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
AppColorScheme.darkSecondary.withValues(alpha: 0.2),
|
||||
colorScheme.primary.withOpacity(isDark ? 0.2 : 0.1),
|
||||
colorScheme.secondary.withOpacity(isDark ? 0.2 : 0.1),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -577,14 +592,14 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
width: 80,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceHighest,
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.2),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.2),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.3),
|
||||
color: Colors.black.withOpacity(isDark ? 0.3 : 0.1),
|
||||
blurRadius: 24,
|
||||
offset: const Offset(0, 8),
|
||||
),
|
||||
@@ -592,7 +607,7 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
),
|
||||
child: Icon(
|
||||
LucideIcons.wallet,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
@@ -607,9 +622,9 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: AppColorScheme.up.withValues(alpha: 0.2),
|
||||
color: AppColorScheme.up.withOpacity(0.2),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.up.withValues(alpha: 0.3),
|
||||
color: AppColorScheme.up.withOpacity(0.3),
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
@@ -623,10 +638,10 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
Text(
|
||||
'No holdings yet.',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
),
|
||||
@@ -635,7 +650,7 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
Text(
|
||||
'暂无持仓,快去交易吧~',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
@@ -643,11 +658,11 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
// 开始交易按钮
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: AppColorScheme.darkCtaGradient,
|
||||
gradient: isDark ? AppColorScheme.darkCtaGradient : AppColorScheme.lightCtaGradient,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.3),
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.3 : 0.2),
|
||||
blurRadius: 30,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
@@ -658,12 +673,12 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 16),
|
||||
child: Text(
|
||||
'Start Trading',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkBackground,
|
||||
color: isDark ? colorScheme.background : const Color(0xFFFFFFFF),
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 16,
|
||||
letterSpacing: -0.5,
|
||||
@@ -687,14 +702,15 @@ class _HoldingsList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final displayHoldings = holdings.length > 5 ? holdings.sublist(0, 5) : holdings;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurface.withValues(alpha: 0.5),
|
||||
color: colorScheme.surface.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.1),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: ListView.separated(
|
||||
@@ -703,7 +719,7 @@ class _HoldingsList extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: displayHoldings.length,
|
||||
separatorBuilder: (_, __) => Divider(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.1),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.1),
|
||||
height: 1,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
@@ -724,6 +740,8 @@ class _HoldingItem extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Row(
|
||||
@@ -733,11 +751,11 @@ class _HoldingItem extends StatelessWidget {
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 18,
|
||||
backgroundColor: AppColorScheme.darkPrimary.withValues(alpha: 0.1),
|
||||
backgroundColor: colorScheme.primary.withOpacity(0.1),
|
||||
child: Text(
|
||||
holding.coinCode.substring(0, 1),
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
style: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -748,8 +766,8 @@ class _HoldingItem extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
holding.coinCode,
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
@@ -757,7 +775,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
Text(
|
||||
holding.quantity,
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
@@ -770,8 +788,8 @@ class _HoldingItem extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
'${holding.currentValue} USDT',
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
),
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../providers/auth_provider.dart';
|
||||
import '../home/home_page.dart';
|
||||
import '../market/market_page.dart';
|
||||
@@ -48,8 +47,10 @@ class _MainPageState extends State<MainPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Column(
|
||||
children: [
|
||||
// 公共顶部导航栏
|
||||
@@ -79,13 +80,16 @@ class _TopAppBar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Container(
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceBright.withValues(alpha: 0.4),
|
||||
color: colorScheme.surfaceBright.withOpacity(0.4),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.06),
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
|
||||
blurRadius: 64,
|
||||
offset: const Offset(0, 32),
|
||||
),
|
||||
@@ -111,15 +115,15 @@ class _TopAppBar extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.2),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: CircleAvatar(
|
||||
backgroundColor: AppColorScheme.darkSurfaceHigh,
|
||||
backgroundColor: colorScheme.surfaceContainerHigh,
|
||||
child: Text(
|
||||
auth.user?.avatarText ?? 'U',
|
||||
style: const TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
style: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
@@ -128,10 +132,10 @@ class _TopAppBar extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// 标题
|
||||
const Text(
|
||||
Text(
|
||||
'模拟所',
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: -0.5,
|
||||
fontSize: 16,
|
||||
@@ -173,13 +177,15 @@ class _IconBtn extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
@@ -201,18 +207,20 @@ class _BottomNavBar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceLow.withValues(alpha: 0.8),
|
||||
color: colorScheme.surfaceContainerLow.withOpacity(0.8),
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(32)),
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.15),
|
||||
),
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
color: Colors.black.withOpacity(0.5),
|
||||
blurRadius: 40,
|
||||
offset: const Offset(0, -10),
|
||||
),
|
||||
@@ -257,7 +265,8 @@ class _NavItemWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = isSelected ? AppColorScheme.darkPrimary : AppColorScheme.darkOnSurfaceVariant;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final color = isSelected ? colorScheme.primary : colorScheme.onSurfaceVariant;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
@@ -267,11 +276,11 @@ class _NavItemWidget extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: isSelected
|
||||
? BoxDecoration(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.1),
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.3),
|
||||
color: colorScheme.primary.withOpacity(0.3),
|
||||
blurRadius: 15,
|
||||
spreadRadius: 0,
|
||||
),
|
||||
|
||||
@@ -39,17 +39,19 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Consumer<MarketProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return Column(
|
||||
children: [
|
||||
_buildSearchBar(provider),
|
||||
_buildTabs(provider),
|
||||
_buildSearchBar(provider, colorScheme),
|
||||
_buildTabs(provider, colorScheme, isDark),
|
||||
Expanded(
|
||||
child: _buildCoinList(provider),
|
||||
child: _buildCoinList(provider, colorScheme, isDark),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -58,28 +60,28 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSearchBar(MarketProvider provider) {
|
||||
Widget _buildSearchBar(MarketProvider provider, ColorScheme colorScheme) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(AppSpacing.md, AppSpacing.md, AppSpacing.md, 0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceContainerLowest,
|
||||
color: colorScheme.surfaceContainerLowest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.15),
|
||||
),
|
||||
),
|
||||
child: TextField(
|
||||
controller: _searchController,
|
||||
onChanged: provider.search,
|
||||
style: TextStyle(color: AppColorScheme.darkOnSurface),
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
decoration: InputDecoration(
|
||||
hintText: '搜索市场...',
|
||||
hintStyle: TextStyle(color: AppColorScheme.darkOnSurfaceVariant),
|
||||
hintStyle: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
prefixIcon: Icon(
|
||||
LucideIcons.search,
|
||||
size: 18,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
suffixIcon: _searchController.text.isNotEmpty
|
||||
? GestureDetector(
|
||||
@@ -90,7 +92,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
child: Icon(
|
||||
LucideIcons.x,
|
||||
size: 18,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
@@ -105,7 +107,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTabs(MarketProvider provider) {
|
||||
Widget _buildTabs(MarketProvider provider, ColorScheme colorScheme, bool isDark) {
|
||||
final tabs = [
|
||||
{'key': 'all', 'label': '全部'},
|
||||
{'key': 'realtime', 'label': '实时'},
|
||||
@@ -132,18 +134,18 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isActive
|
||||
? AppColorScheme.darkPrimary.withValues(alpha: 0.1)
|
||||
: AppColorScheme.darkSurfaceContainerHigh,
|
||||
? colorScheme.primary.withOpacity(0.1)
|
||||
: colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
border: isActive
|
||||
? Border.all(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
color: colorScheme.primary.withOpacity(0.2),
|
||||
)
|
||||
: null,
|
||||
boxShadow: isActive
|
||||
? [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.neonGlowPrimary,
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
|
||||
blurRadius: 15,
|
||||
),
|
||||
]
|
||||
@@ -153,8 +155,8 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
tab['label']!,
|
||||
style: TextStyle(
|
||||
color: isActive
|
||||
? AppColorScheme.darkPrimary
|
||||
: AppColorScheme.darkOnSurfaceVariant,
|
||||
? colorScheme.primary
|
||||
: colorScheme.onSurfaceVariant,
|
||||
fontWeight: isActive ? FontWeight.w700 : FontWeight.normal,
|
||||
fontSize: 12,
|
||||
),
|
||||
@@ -167,37 +169,37 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCoinList(MarketProvider provider) {
|
||||
Widget _buildCoinList(MarketProvider provider, ColorScheme colorScheme, bool isDark) {
|
||||
if (provider.isLoading) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (provider.error != null) {
|
||||
return _buildErrorState(provider);
|
||||
return _buildErrorState(provider, colorScheme);
|
||||
}
|
||||
|
||||
final coins = provider.coins;
|
||||
if (coins.isEmpty) {
|
||||
return _buildEmptyState();
|
||||
return _buildEmptyState(colorScheme);
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: provider.refresh,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
backgroundColor: AppColorScheme.darkSurfaceContainer,
|
||||
color: colorScheme.primary,
|
||||
backgroundColor: colorScheme.surfaceContainer,
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.all(AppSpacing.md),
|
||||
itemCount: coins.length,
|
||||
itemBuilder: (context, index) => _buildCoinItem(coins[index]),
|
||||
itemBuilder: (context, index) => _buildCoinItem(coins[index], colorScheme),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildErrorState(MarketProvider provider) {
|
||||
Widget _buildErrorState(MarketProvider provider, ColorScheme colorScheme) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: AppSpacing.pagePadding,
|
||||
@@ -207,12 +209,12 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
Icon(
|
||||
LucideIcons.circleAlert,
|
||||
size: 48,
|
||||
color: AppColorScheme.darkError,
|
||||
color: colorScheme.error,
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
Text(
|
||||
provider.error!,
|
||||
style: TextStyle(color: AppColorScheme.darkError),
|
||||
style: TextStyle(color: colorScheme.error),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
@@ -226,7 +228,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEmptyState() {
|
||||
Widget _buildEmptyState(ColorScheme colorScheme) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -234,23 +236,23 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
Icon(
|
||||
LucideIcons.coins,
|
||||
size: 48,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
Text(
|
||||
'暂无数据',
|
||||
style: TextStyle(color: AppColorScheme.darkOnSurfaceVariant),
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCoinItem(Coin coin) {
|
||||
Widget _buildCoinItem(Coin coin, ColorScheme colorScheme) {
|
||||
final changeColor = coin.isUp ? AppColorScheme.up : AppColorScheme.down;
|
||||
final changeBgColor = coin.isUp
|
||||
? AppColorScheme.darkTertiary.withValues(alpha: 0.1)
|
||||
: AppColorScheme.darkError.withValues(alpha: 0.1);
|
||||
? AppColorScheme.up.withOpacity(0.1)
|
||||
: colorScheme.error.withOpacity(0.1);
|
||||
|
||||
return GlassCard(
|
||||
margin: EdgeInsets.only(bottom: AppSpacing.sm),
|
||||
@@ -261,10 +263,10 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceContainerHighest,
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.2),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
@@ -272,7 +274,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
coin.displayIcon,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: coin.isUp ? AppColorScheme.darkPrimary : AppColorScheme.darkSecondary,
|
||||
color: coin.isUp ? colorScheme.primary : colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -291,7 +293,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
@@ -299,7 +301,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
'/USDT',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -309,7 +311,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
coin.name,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -324,7 +326,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
@@ -337,7 +339,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
color: changeBgColor,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
border: Border.all(
|
||||
color: changeColor.withValues(alpha: 0.2),
|
||||
color: changeColor.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
|
||||
@@ -42,9 +42,10 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Consumer<AuthProvider>(
|
||||
builder: (context, auth, _) {
|
||||
return SingleChildScrollView(
|
||||
@@ -62,7 +63,7 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
'System Build v1.0.0-Neo',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: AppColorScheme.darkOnSurfaceVariant.withValues(alpha: 0.4),
|
||||
color: colorScheme.onSurfaceVariant.withOpacity(0.4),
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
),
|
||||
@@ -97,6 +98,7 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
}
|
||||
|
||||
void _showAboutDialog() {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (context) => ShadDialog(
|
||||
@@ -113,7 +115,7 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
children: [
|
||||
Text(
|
||||
'虚拟货币模拟交易平台',
|
||||
style: TextStyle(color: AppColorScheme.darkOnSurfaceVariant),
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_InfoRow(icon: Icons.code, text: '版本: 1.0.0'),
|
||||
@@ -169,6 +171,9 @@ class _UserCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
return GlassPanel(
|
||||
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm),
|
||||
child: Row(
|
||||
@@ -181,7 +186,7 @@ class _UserCard extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: AppColorScheme.neonGlowPrimary,
|
||||
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
|
||||
blurRadius: 20,
|
||||
),
|
||||
],
|
||||
@@ -195,17 +200,17 @@ class _UserCard extends StatelessWidget {
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkTertiary,
|
||||
color: AppColorScheme.up,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkBackground,
|
||||
color: colorScheme.background,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.verified,
|
||||
size: 14,
|
||||
color: AppColorScheme.darkOnTertiary,
|
||||
color: colorScheme.onTertiary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -221,7 +226,7 @@ class _UserCard extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
@@ -232,10 +237,10 @@ class _UserCard extends StatelessWidget {
|
||||
vertical: AppSpacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.1),
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
color: colorScheme.primary.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
@@ -244,7 +249,7 @@ class _UserCard extends StatelessWidget {
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.2,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -253,7 +258,7 @@ class _UserCard extends StatelessWidget {
|
||||
),
|
||||
Icon(
|
||||
LucideIcons.chevronRight,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -271,14 +276,16 @@ class _AppLogo extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return CircleAvatar(
|
||||
radius: radius,
|
||||
backgroundColor: AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
backgroundColor: colorScheme.primary.withOpacity(0.2),
|
||||
child: Text(
|
||||
text ?? '₿',
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -295,15 +302,17 @@ class _InfoRow extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Icon(icon, size: 14, color: AppColorScheme.darkOnSurfaceVariant),
|
||||
Icon(icon, size: 14, color: colorScheme.onSurfaceVariant),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -321,6 +330,7 @@ class _MenuList extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeProvider = context.watch<ThemeProvider>();
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GlassPanel(
|
||||
padding: EdgeInsets.zero,
|
||||
@@ -331,7 +341,7 @@ class _MenuList extends StatelessWidget {
|
||||
_ThemeToggleTile(isDarkMode: themeProvider.isDarkMode),
|
||||
_buildDivider(),
|
||||
// 菜单项
|
||||
..._buildMenuItems(),
|
||||
..._buildMenuItems(colorScheme),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -345,41 +355,41 @@ class _MenuList extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildMenuItems() {
|
||||
List<Widget> _buildMenuItems(ColorScheme colorScheme) {
|
||||
final items = [
|
||||
_MenuItem(
|
||||
icon: LucideIcons.userCheck,
|
||||
title: '实名认证',
|
||||
subtitle: '完成实名认证,解锁更多功能',
|
||||
iconColor: AppColorScheme.darkPrimary,
|
||||
iconColor: colorScheme.primary,
|
||||
onTap: () => onShowComingSoon('实名认证'),
|
||||
),
|
||||
_MenuItem(
|
||||
icon: LucideIcons.shield,
|
||||
title: '安全设置',
|
||||
subtitle: '密码、二次验证等安全设置',
|
||||
iconColor: AppColorScheme.darkSecondary,
|
||||
iconColor: colorScheme.secondary,
|
||||
onTap: () => onShowComingSoon('安全设置'),
|
||||
),
|
||||
_MenuItem(
|
||||
icon: LucideIcons.bell,
|
||||
title: '消息通知',
|
||||
subtitle: '管理消息推送设置',
|
||||
iconColor: AppColorScheme.darkTertiary,
|
||||
iconColor: AppColorScheme.up,
|
||||
onTap: () => onShowComingSoon('消息通知'),
|
||||
),
|
||||
_MenuItem(
|
||||
icon: LucideIcons.settings,
|
||||
title: '系统设置',
|
||||
subtitle: '主题、语言等偏好设置',
|
||||
iconColor: AppColorScheme.darkPrimary,
|
||||
iconColor: colorScheme.primary,
|
||||
onTap: () => onShowComingSoon('系统设置'),
|
||||
),
|
||||
_MenuItem(
|
||||
icon: LucideIcons.info,
|
||||
title: '关于我们',
|
||||
subtitle: '版本信息与用户协议',
|
||||
iconColor: AppColorScheme.darkOnSurfaceVariant,
|
||||
iconColor: colorScheme.onSurfaceVariant,
|
||||
onTap: onShowAbout,
|
||||
),
|
||||
];
|
||||
@@ -401,6 +411,7 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final themeProvider = context.read<ThemeProvider>();
|
||||
|
||||
return InkWell(
|
||||
@@ -414,7 +425,7 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
children: [
|
||||
_MenuIcon(
|
||||
icon: isDarkMode ? LucideIcons.moon : LucideIcons.sun,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
@@ -426,7 +437,7 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs / 2),
|
||||
@@ -434,7 +445,7 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
isDarkMode ? '当前:深色主题' : '当前:浅色主题',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -443,8 +454,8 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
Switch(
|
||||
value: isDarkMode,
|
||||
onChanged: (_) => themeProvider.toggleTheme(),
|
||||
activeTrackColor: AppColorScheme.darkPrimary.withValues(alpha: 0.5),
|
||||
activeColor: AppColorScheme.darkPrimary,
|
||||
activeTrackColor: colorScheme.primary.withOpacity(0.5),
|
||||
activeColor: colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -461,6 +472,8 @@ class _MenuItemTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return InkWell(
|
||||
onTap: item.onTap,
|
||||
child: Padding(
|
||||
@@ -481,7 +494,7 @@ class _MenuItemTile extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
if (item.subtitle != null) ...[
|
||||
@@ -490,7 +503,7 @@ class _MenuItemTile extends StatelessWidget {
|
||||
item.subtitle!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -500,7 +513,7 @@ class _MenuItemTile extends StatelessWidget {
|
||||
Icon(
|
||||
LucideIcons.chevronRight,
|
||||
size: 18,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -518,16 +531,17 @@ class _MenuIcon extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final iconColor = color ?? AppColorScheme.darkPrimary;
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final iconColor = color ?? colorScheme.primary;
|
||||
|
||||
return Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: iconColor.withValues(alpha: 0.1),
|
||||
color: iconColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md + AppSpacing.xs),
|
||||
border: Border.all(
|
||||
color: iconColor.withValues(alpha: 0.2),
|
||||
color: iconColor.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Icon(icon, size: 20, color: iconColor),
|
||||
|
||||
@@ -49,9 +49,10 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColorScheme.darkBackground,
|
||||
backgroundColor: colorScheme.background,
|
||||
body: Consumer2<MarketProvider, AssetProvider>(
|
||||
builder: (context, market, asset, _) {
|
||||
return SingleChildScrollView(
|
||||
@@ -99,6 +100,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
}
|
||||
|
||||
void _executeTrade() {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final price = _priceController.text;
|
||||
final quantity = _quantityController.text;
|
||||
final isBuy = _tradeType == 0;
|
||||
@@ -123,6 +125,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
}
|
||||
|
||||
void _showTradeResult() {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isBuy = _tradeType == 0;
|
||||
|
||||
showShadDialog(
|
||||
@@ -132,7 +135,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
children: [
|
||||
NeonIcon(
|
||||
icon: Icons.check_circle,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
size: 24,
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
@@ -168,6 +171,8 @@ class _CoinSelector extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
// 自动选择第一个币种
|
||||
if (selectedCoin == null && coins.isNotEmpty) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => onCoinLoaded(coins.first));
|
||||
@@ -188,7 +193,7 @@ class _CoinSelector extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
@@ -196,7 +201,7 @@ class _CoinSelector extends StatelessWidget {
|
||||
selectedCoin?.name ?? '点击选择交易对',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -204,7 +209,7 @@ class _CoinSelector extends StatelessWidget {
|
||||
),
|
||||
Icon(
|
||||
LucideIcons.chevronRight,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -220,14 +225,16 @@ class _CoinAvatar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
width: 44,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.1),
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkPrimary.withValues(alpha: 0.2),
|
||||
color: colorScheme.primary.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
@@ -235,7 +242,7 @@ class _CoinAvatar extends StatelessWidget {
|
||||
icon ?? '?',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: AppColorScheme.darkPrimary,
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -252,10 +259,11 @@ class _PriceCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final color = coin.isUp ? AppColorScheme.up : AppColorScheme.down;
|
||||
final bgColor = coin.isUp
|
||||
? AppColorScheme.darkTertiary.withValues(alpha: 0.1)
|
||||
: AppColorScheme.darkError.withValues(alpha: 0.1);
|
||||
? AppColorScheme.up.withOpacity(0.1)
|
||||
: colorScheme.error.withOpacity(0.1);
|
||||
|
||||
return GlassCard(
|
||||
showNeonGlow: false,
|
||||
@@ -269,7 +277,7 @@ class _PriceCard extends StatelessWidget {
|
||||
'最新价',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
@@ -278,7 +286,7 @@ class _PriceCard extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -292,7 +300,7 @@ class _PriceCard extends StatelessWidget {
|
||||
color: bgColor,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: Border.all(
|
||||
color: color.withValues(alpha: 0.2),
|
||||
color: color.withOpacity(0.2),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
@@ -330,6 +338,8 @@ class _TradeForm extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return GlassPanel(
|
||||
padding: EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
@@ -346,6 +356,7 @@ class _TradeForm extends StatelessWidget {
|
||||
controller: priceController,
|
||||
placeholder: '输入价格',
|
||||
suffix: 'USDT',
|
||||
colorScheme: colorScheme,
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
// 数量输入
|
||||
@@ -354,12 +365,13 @@ class _TradeForm extends StatelessWidget {
|
||||
controller: quantityController,
|
||||
placeholder: '输入数量',
|
||||
suffix: selectedCoin?.code ?? '',
|
||||
colorScheme: colorScheme,
|
||||
),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
// 信息行
|
||||
_InfoRow(label: '交易金额', value: '${_calculateAmount()} USDT'),
|
||||
_InfoRow(label: '交易金额', value: '${_calculateAmount()} USDT', colorScheme: colorScheme),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
_InfoRow(label: '可用', value: '${tradeBalance ?? '0.00'} USDT'),
|
||||
_InfoRow(label: '可用', value: '${tradeBalance ?? '0.00'} USDT', colorScheme: colorScheme),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -370,6 +382,7 @@ class _TradeForm extends StatelessWidget {
|
||||
required TextEditingController controller,
|
||||
required String placeholder,
|
||||
required String suffix,
|
||||
required ColorScheme colorScheme,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -380,16 +393,16 @@ class _TradeForm extends StatelessWidget {
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.2,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceLowest,
|
||||
color: colorScheme.surfaceContainerLowest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
border: Border.all(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.3),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.3),
|
||||
),
|
||||
),
|
||||
child: TextField(
|
||||
@@ -398,12 +411,12 @@ class _TradeForm extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: placeholder,
|
||||
hintStyle: TextStyle(
|
||||
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.5),
|
||||
color: colorScheme.outlineVariant.withOpacity(0.5),
|
||||
),
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
@@ -417,7 +430,7 @@ class _TradeForm extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -445,10 +458,12 @@ class _TradeTypeSelector extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.darkSurfaceLowest,
|
||||
color: colorScheme.surfaceContainerLowest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
),
|
||||
child: Row(
|
||||
@@ -498,15 +513,15 @@ class _TypeButton extends StatelessWidget {
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? color.withValues(alpha: 0.15) : Colors.transparent,
|
||||
color: isSelected ? color.withOpacity(0.15) : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: isSelected ? null : Border.all(color: color.withValues(alpha: 0.3)),
|
||||
border: isSelected ? null : Border.all(color: color.withOpacity(0.3)),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected ? color : color.withValues(alpha: 0.7),
|
||||
color: isSelected ? color : color.withOpacity(0.7),
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 14,
|
||||
letterSpacing: 0.5,
|
||||
@@ -522,8 +537,9 @@ class _TypeButton extends StatelessWidget {
|
||||
class _InfoRow extends StatelessWidget {
|
||||
final String label;
|
||||
final String value;
|
||||
final ColorScheme colorScheme;
|
||||
|
||||
const _InfoRow({required this.label, required this.value});
|
||||
const _InfoRow({required this.label, required this.value, required this.colorScheme});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -534,7 +550,7 @@ class _InfoRow extends StatelessWidget {
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
@@ -542,7 +558,7 @@ class _InfoRow extends StatelessWidget {
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user