Compare commits
2 Commits
dbb260801d
...
c915ca888e
| Author | SHA1 | Date | |
|---|---|---|---|
| c915ca888e | |||
| 5d753d3fa4 |
@@ -152,27 +152,25 @@ class AppTheme {
|
||||
),
|
||||
),
|
||||
|
||||
// 輸入框 - 底部線條風格
|
||||
// 輸入框 - Ghost Border 風格
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: AppColorScheme.lightSurfaceLow,
|
||||
border: UnderlineInputBorder(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
borderSide: BorderSide(
|
||||
color: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
borderSide: BorderSide(
|
||||
color: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
borderSide: const BorderSide(color: AppColorScheme.lightPrimary, width: 2),
|
||||
borderSide: const BorderSide(color: AppColorScheme.lightPrimary, width: 1),
|
||||
),
|
||||
hintStyle: TextStyle(color: AppColorScheme.lightOnSurfaceMuted),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
|
||||
@@ -298,27 +298,30 @@ class _TransferPageState extends State<TransferPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
// 交换按钮 - 右侧贴分割线
|
||||
// 交换按钮 - 右側居中分割線
|
||||
Positioned(
|
||||
right: 12,
|
||||
top: 20,
|
||||
child: GestureDetector(
|
||||
onTap: _toggleDirection,
|
||||
child: Container(
|
||||
width: 28,
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: colorScheme.outlineVariant,
|
||||
width: 1,
|
||||
bottom: 20,
|
||||
child: Center(
|
||||
child: GestureDetector(
|
||||
onTap: _toggleDirection,
|
||||
child: Container(
|
||||
width: 28,
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: colorScheme.outlineVariant,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
LucideIcons.repeat2,
|
||||
size: 13,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
LucideIcons.arrowUpDown,
|
||||
size: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -8,6 +8,7 @@ import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../data/models/account_models.dart';
|
||||
import '../../../data/services/bonus_service.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../../components/coin_icon.dart';
|
||||
|
||||
/// 賬單頁面 — 代幣盈虧賬單 + 新人福利賬單 + 推廣福利賬單
|
||||
class BillsPage extends StatefulWidget {
|
||||
@@ -302,17 +303,7 @@ class _BillsPageState extends State<BillsPage> with SingleTickerProviderStateMix
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 16,
|
||||
backgroundColor: colorScheme.primary.withValues(alpha: 0.1),
|
||||
child: Text(
|
||||
h.coinCode.substring(0, 1),
|
||||
style: AppTextStyles.labelLarge(context).copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
CoinIcon(symbol: h.coinCode, size: 32),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
Text(h.coinCode, style: AppTextStyles.headlineMedium(context).copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.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 '../../../data/models/coin.dart';
|
||||
import '../../../providers/market_provider.dart';
|
||||
import '../../components/coin_icon.dart';
|
||||
@@ -35,9 +32,10 @@ class _MarketPageState extends State<MarketPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: context.colors.surface,
|
||||
backgroundColor: colorScheme.surface,
|
||||
body: Consumer<MarketProvider>(
|
||||
builder: (context, provider, _) {
|
||||
if (provider.isLoading) {
|
||||
@@ -50,8 +48,8 @@ class _MarketPageState extends State<MarketPage>
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => provider.refresh(),
|
||||
color: context.colors.primary,
|
||||
backgroundColor: context.colors.surfaceContainerHighest,
|
||||
color: colorScheme.primary,
|
||||
backgroundColor: colorScheme.surfaceContainerHighest,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.only(
|
||||
@@ -63,7 +61,6 @@ class _MarketPageState extends State<MarketPage>
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 頁面標題 "行情"
|
||||
Text(
|
||||
'行情',
|
||||
style: AppTextStyles.displaySmall(context).copyWith(
|
||||
@@ -72,13 +69,10 @@ class _MarketPageState extends State<MarketPage>
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
// 搜索框
|
||||
_buildSearchBar(context),
|
||||
_buildSearchBar(colorScheme),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
// 精選區域:BTC + ETH 卡片
|
||||
_buildFeaturedSection(provider),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
// 全部幣種列表(含表頭)
|
||||
_buildCoinList(provider),
|
||||
],
|
||||
),
|
||||
@@ -89,8 +83,11 @@ class _MarketPageState extends State<MarketPage>
|
||||
);
|
||||
}
|
||||
|
||||
/// 搜索框
|
||||
Widget _buildSearchBar(BuildContext context) {
|
||||
// ============================================
|
||||
// 搜索框
|
||||
// ============================================
|
||||
|
||||
Widget _buildSearchBar(ColorScheme colorScheme) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// TODO: 彈出搜索界面
|
||||
@@ -98,22 +95,19 @@ class _MarketPageState extends State<MarketPage>
|
||||
child: Container(
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: context.colors.surfaceContainerHigh,
|
||||
color: colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
LucideIcons.search,
|
||||
size: 16,
|
||||
color: context.colors.onSurfaceVariant,
|
||||
),
|
||||
Icon(LucideIcons.search,
|
||||
size: 16, color: colorScheme.onSurfaceVariant),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
Text(
|
||||
'搜索幣種名稱或代碼',
|
||||
style: AppTextStyles.bodyMedium(context).copyWith(
|
||||
color: context.appColors.onSurfaceMuted,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -122,7 +116,10 @@ class _MarketPageState extends State<MarketPage>
|
||||
);
|
||||
}
|
||||
|
||||
/// 精選區域:BTC + ETH 大卡片
|
||||
// ============================================
|
||||
// 精選區域
|
||||
// ============================================
|
||||
|
||||
Widget _buildFeaturedSection(MarketProvider provider) {
|
||||
final featured = provider.featuredCoins;
|
||||
if (featured.isEmpty) return const SizedBox.shrink();
|
||||
@@ -145,8 +142,12 @@ class _MarketPageState extends State<MarketPage>
|
||||
);
|
||||
}
|
||||
|
||||
/// 幣種列表(含表頭)
|
||||
// ============================================
|
||||
// 幣種列表
|
||||
// ============================================
|
||||
|
||||
Widget _buildCoinList(MarketProvider provider) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final coins = provider.otherCoins;
|
||||
|
||||
if (coins.isEmpty) {
|
||||
@@ -159,19 +160,17 @@ class _MarketPageState extends State<MarketPage>
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.appColors.surfaceCard,
|
||||
color: colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
border: Border.all(
|
||||
color: context.appColors.ghostBorder,
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 表頭行
|
||||
_buildListHeader(context),
|
||||
// 列表項
|
||||
_buildListHeader(colorScheme),
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
@@ -179,7 +178,7 @@ class _MarketPageState extends State<MarketPage>
|
||||
separatorBuilder: (_, __) => Divider(
|
||||
height: 1,
|
||||
thickness: 1,
|
||||
color: context.colors.outlineVariant.withValues(alpha: 0.5 * 0.15),
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
|
||||
indent: AppSpacing.md,
|
||||
endIndent: AppSpacing.md,
|
||||
),
|
||||
@@ -190,10 +189,9 @@ class _MarketPageState extends State<MarketPage>
|
||||
);
|
||||
}
|
||||
|
||||
/// 列表表頭行:幣種 | 最新價 | 漲跌幅
|
||||
Widget _buildListHeader(BuildContext context) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
Widget _buildListHeader(ColorScheme colorScheme) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
AppSpacing.md,
|
||||
AppSpacing.sm + AppSpacing.xs,
|
||||
AppSpacing.md,
|
||||
@@ -207,7 +205,7 @@ class _MarketPageState extends State<MarketPage>
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -219,11 +217,11 @@ class _MarketPageState extends State<MarketPage>
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
SizedBox(
|
||||
width: 72,
|
||||
child: Text(
|
||||
@@ -232,7 +230,7 @@ class _MarketPageState extends State<MarketPage>
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurfaceVariant,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -241,23 +239,29 @@ class _MarketPageState extends State<MarketPage>
|
||||
);
|
||||
}
|
||||
|
||||
/// 錯誤狀態
|
||||
// ============================================
|
||||
// 錯誤狀態
|
||||
// ============================================
|
||||
|
||||
Widget _buildErrorState(MarketProvider provider) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(LucideIcons.circleAlert, size: 48, color: context.colors.error),
|
||||
Icon(LucideIcons.circleAlert,
|
||||
size: 48, color: colorScheme.error),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
Text(
|
||||
provider.error ?? '加載失敗',
|
||||
style: TextStyle(color: context.colors.error),
|
||||
style: TextStyle(color: colorScheme.error),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
ShadButton(
|
||||
ElevatedButton(
|
||||
onPressed: () => provider.refresh(),
|
||||
child: const Text('重試'),
|
||||
),
|
||||
@@ -268,7 +272,10 @@ class _MarketPageState extends State<MarketPage>
|
||||
}
|
||||
}
|
||||
|
||||
/// 精選卡片:BTC / ETH (148px 高度,漸變背景,含迷你柱狀圖)
|
||||
// ============================================
|
||||
// 精選卡片 — 簡約風格,用貨幣圖標代替柱狀圖
|
||||
// ============================================
|
||||
|
||||
class _FeaturedCard extends StatelessWidget {
|
||||
final Coin coin;
|
||||
|
||||
@@ -276,43 +283,55 @@ class _FeaturedCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isUp = coin.isUp;
|
||||
final isBtc = coin.code == 'BTC';
|
||||
|
||||
final gradient =
|
||||
isBtc ? AppColorScheme.btcCardGradient : AppColorScheme.ethCardGradient;
|
||||
final barColor =
|
||||
isBtc ? AppColorScheme.btcBarColor : AppColorScheme.ethBarColor;
|
||||
final changeBgColor = isUp
|
||||
? AppColorScheme.darkTertiary.withValues(alpha: 0.2)
|
||||
: AppColorScheme.darkError.withValues(alpha: 0.2);
|
||||
final changeColor = isUp
|
||||
? AppColorScheme.darkTertiary
|
||||
: AppColorScheme.darkError;
|
||||
final changeColor =
|
||||
isUp ? colorScheme.tertiary : colorScheme.error;
|
||||
final changeBgColor =
|
||||
changeColor.withValues(alpha: 0.12);
|
||||
|
||||
return Container(
|
||||
height: 148,
|
||||
height: 120,
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
gradient: gradient,
|
||||
color: colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
border: Border.all(
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
child: Row(
|
||||
children: [
|
||||
// 第一行:交易對名 + 漲跌幅標籤
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// 左側:圖標 + 交易對
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CoinIcon(symbol: coin.code, size: 32),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'${coin.code}/USDT',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
'${coin.code}/U',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
// 右側:價格 + 漲跌
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
_formatFeaturedPrice(coin),
|
||||
style: AppTextStyles.numberLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.xs + 2,
|
||||
@@ -333,29 +352,11 @@ class _FeaturedCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
// 第二行:大號價格
|
||||
Text(
|
||||
'\$${_formatFeaturedPrice(coin)}',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w800,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
// 第三行:迷你柱狀圖
|
||||
Expanded(
|
||||
child: _MiniBarChart(
|
||||
barColor: barColor,
|
||||
seed: coin.code.hashCode,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 精選卡片使用簡短價格格式(帶逗號)
|
||||
String _formatFeaturedPrice(Coin coin) {
|
||||
if (coin.price >= 1000) {
|
||||
return _addCommas(coin.price.toStringAsFixed(2));
|
||||
@@ -380,47 +381,10 @@ class _FeaturedCard extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 迷你柱狀圖(模擬價格走勢)
|
||||
class _MiniBarChart extends StatelessWidget {
|
||||
final Color barColor;
|
||||
final int seed;
|
||||
// ============================================
|
||||
// 幣種列表行
|
||||
// ============================================
|
||||
|
||||
const _MiniBarChart({required this.barColor, required this.seed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 生成隨機但確定的高度序列
|
||||
final heights = _generateHeights();
|
||||
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: heights.map((h) {
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 2),
|
||||
child: Container(
|
||||
height: h,
|
||||
decoration: BoxDecoration(
|
||||
color: barColor,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
List<double> _generateHeights() {
|
||||
final random = Random(seed);
|
||||
const base = 6.0;
|
||||
const range = 12.0;
|
||||
return List.generate(6, (_) => base + random.nextDouble() * range);
|
||||
}
|
||||
}
|
||||
|
||||
/// 幣種列表行
|
||||
class _CoinRow extends StatelessWidget {
|
||||
final Coin coin;
|
||||
|
||||
@@ -428,12 +392,10 @@ class _CoinRow extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isUp = coin.isUp;
|
||||
final changeColor =
|
||||
isUp ? context.appColors.up : context.appColors.down;
|
||||
final changeBgColor = isUp
|
||||
? context.appColors.upBackground
|
||||
: context.appColors.downBackground;
|
||||
final changeColor = isUp ? colorScheme.tertiary : colorScheme.error;
|
||||
final changeBgColor = changeColor.withValues(alpha: 0.12);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => _navigateToTrade(context),
|
||||
@@ -445,21 +407,19 @@ class _CoinRow extends StatelessWidget {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// 頭像:36px 圓形
|
||||
CoinIcon(
|
||||
symbol: coin.code,
|
||||
size: 36,
|
||||
isCircle: true,
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
// 幣種信息:交易對 + 全名
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${coin.code}/USDT',
|
||||
'${coin.code}/U',
|
||||
style: AppTextStyles.numberMedium(context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@@ -472,17 +432,15 @@ class _CoinRow extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
// 價格(固定寬度90,右對齊)
|
||||
SizedBox(
|
||||
width: 90,
|
||||
child: Text(
|
||||
'\$${coin.formattedPrice}',
|
||||
coin.formattedPrice,
|
||||
textAlign: TextAlign.right,
|
||||
style: AppTextStyles.numberMedium(context),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
// 漲跌幅標籤(固定寬度72)
|
||||
SizedBox(
|
||||
width: 72,
|
||||
child: Container(
|
||||
@@ -515,7 +473,10 @@ class _CoinRow extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 空狀態
|
||||
// ============================================
|
||||
// 空狀態
|
||||
// ============================================
|
||||
|
||||
class _EmptyState extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String message;
|
||||
@@ -529,20 +490,22 @@ class _EmptyState extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(AppSpacing.xl),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(icon, size: 48, color: context.colors.onSurfaceVariant),
|
||||
Icon(icon, size: 48, color: colorScheme.onSurfaceVariant),
|
||||
const SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text(
|
||||
message,
|
||||
style: TextStyle(color: context.colors.onSurfaceVariant),
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
if (onRetry != null) ...[
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
ShadButton(
|
||||
ElevatedButton(
|
||||
onPressed: onRetry,
|
||||
child: const Text('重試'),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user