feat(mine): 重做我的页会员卡与功能宫格布局
This commit is contained in:
1 parent
e7399fa3fd
commit
53e8c924a6
12 files changed
+1969
-513
No files matched your search
@@ -16,7 +16,7 @@ import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/auth/auth_view.dart';
|
||||
import 'package:fruitshorts/pages/mine/about_page.dart';
|
||||
import 'package:fruitshorts/pages/mine/mine_types.dart';
|
||||
import 'package:fruitshorts/pages/mine/widgets/mine_menu.dart';
|
||||
import 'package:fruitshorts/pages/mine/widgets/mine_action_grid.dart';
|
||||
import 'package:fruitshorts/pages/store/vip_page.dart';
|
||||
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
|
||||
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
|
||||
@@ -78,11 +78,11 @@ void main() {
|
||||
]);
|
||||
expect(background.stops, const [0, 0.14, 0.3]);
|
||||
|
||||
// 快捷图标行:钱包 / 收藏 / 离线缓存 / 观看历史。
|
||||
// 统一操作宫格第一排:钱包 / 收藏 / 离线缓存 / 观看历史。
|
||||
const quickActions = [
|
||||
(Key('mine-wallet'), Icons.wallet_outlined),
|
||||
(Key('mine-favorites'), Icons.star_border_rounded),
|
||||
(Key('mine-downloads'), Icons.download_outlined),
|
||||
(Key('mine-wallet'), Icons.account_balance_wallet_outlined),
|
||||
(Key('mine-favorites'), Icons.star_outline_rounded),
|
||||
(Key('mine-downloads'), Icons.download_for_offline_outlined),
|
||||
(Key('mine-history'), Icons.history_rounded),
|
||||
];
|
||||
for (final action in quickActions) {
|
||||
@@ -92,44 +92,124 @@ void main() {
|
||||
matching: find.byIcon(action.$2),
|
||||
),
|
||||
);
|
||||
expect(icon.color, AppColors.textPrimary);
|
||||
expect(icon.size, AppDimens.mineQuickActionIcon);
|
||||
expect(icon.color, AppColors.mineGridIconAccent);
|
||||
expect(icon.size, AppDimens.mineGridIcon);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byKey(const Key('mine-menu')),
|
||||
matching: find.byKey(action.$1),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
}
|
||||
|
||||
// 「更多服务」列表:联系客服 / 语言 / 设置 / 通知。
|
||||
// 「更多服务」宫格:联系客服 / 语言 / 设置 / 通知。
|
||||
const services = [
|
||||
(Key('mine-help'), Icons.headset_outlined),
|
||||
(Key('mine-language'), Icons.language_rounded),
|
||||
(Key('mine-settings'), Icons.settings_outlined),
|
||||
(Key('mine-notices'), Icons.notifications_none_rounded),
|
||||
(
|
||||
Key('mine-help'),
|
||||
Key('mine-help-icon-surface'),
|
||||
Icons.support_agent_outlined,
|
||||
),
|
||||
(
|
||||
Key('mine-language'),
|
||||
Key('mine-language-icon-surface'),
|
||||
Icons.language_rounded,
|
||||
),
|
||||
(
|
||||
Key('mine-settings'),
|
||||
Key('mine-settings-icon-surface'),
|
||||
Icons.settings_outlined,
|
||||
),
|
||||
(
|
||||
Key('mine-notices'),
|
||||
Key('mine-notices-icon-surface'),
|
||||
Icons.notifications_none_rounded,
|
||||
),
|
||||
];
|
||||
for (final service in services) {
|
||||
expect(find.byKey(service.$1), findsOneWidget);
|
||||
final icon = tester.widget<Icon>(
|
||||
find.descendant(
|
||||
of: find.byKey(service.$1),
|
||||
matching: find.byIcon(service.$2),
|
||||
matching: find.byIcon(service.$3),
|
||||
),
|
||||
);
|
||||
expect(icon.color, AppColors.textPrimary);
|
||||
expect(icon.size, AppDimens.mineServiceIcon);
|
||||
expect(icon.color, AppColors.mineGridIconAccent);
|
||||
expect(icon.size, AppDimens.mineGridIcon);
|
||||
expect(
|
||||
tester.getSize(find.byKey(service.$2)),
|
||||
const Size.square(AppDimens.mineGridIconSurface),
|
||||
);
|
||||
}
|
||||
expect(find.byKey(const Key('mine-menu')), findsOneWidget);
|
||||
expect(tester.getTopLeft(find.byKey(const Key('mine-menu'))).dx, 14);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('mine-menu'))).height,
|
||||
AppDimens.mineGridHeight,
|
||||
);
|
||||
final serviceLefts = services
|
||||
.map((service) => tester.getTopLeft(find.byKey(service.$1)).dx)
|
||||
.toList();
|
||||
expect(serviceLefts, [...serviceLefts]..sort());
|
||||
expect(serviceLefts.toSet(), hasLength(services.length));
|
||||
expect(
|
||||
tester.getTopLeft(find.byKey(const Key('mine-help'))).dy,
|
||||
greaterThan(tester.getTopLeft(find.byKey(const Key('mine-wallet'))).dy),
|
||||
);
|
||||
final menu = tester.widget<DecoratedBox>(
|
||||
find.byKey(const Key('mine-menu')),
|
||||
);
|
||||
final menuDecoration = menu.decoration as BoxDecoration;
|
||||
expect(menuDecoration.color, AppColors.mineGridSurface);
|
||||
expect(
|
||||
menuDecoration.borderRadius,
|
||||
BorderRadius.circular(AppDimens.mineGridRadius),
|
||||
);
|
||||
|
||||
final vip = tester.widget<Container>(find.byKey(const Key('mine-vip')));
|
||||
final vipDecoration = vip.decoration! as BoxDecoration;
|
||||
expect((vipDecoration.gradient! as LinearGradient).colors, const [
|
||||
AppColors.vipCardStart,
|
||||
AppColors.vipCardMiddle,
|
||||
AppColors.vipCardEnd,
|
||||
]);
|
||||
expect(vipDecoration.boxShadow, isNull);
|
||||
expect(vipDecoration.border, isNotNull);
|
||||
expect(vipDecoration.boxShadow, isNotEmpty);
|
||||
|
||||
// 卡片高度由内容撑开,上下内边距必须一致(边框各占 1pt)。
|
||||
final vipRect = tester.getRect(find.byKey(const Key('mine-vip')));
|
||||
final emblemRect = tester.getRect(find.byKey(const Key('mine-vip-emblem')));
|
||||
final benefitsRect = tester.getRect(
|
||||
find.byKey(const Key('mine-vip-benefits')),
|
||||
);
|
||||
final topInset = emblemRect.top - vipRect.top;
|
||||
final bottomInset = vipRect.bottom - benefitsRect.bottom;
|
||||
expect(topInset, closeTo(bottomInset, 0.01));
|
||||
expect(topInset, greaterThanOrEqualTo(AppDimens.mineVipPadding));
|
||||
expect(find.byKey(const Key('mine-vip-emblem')), findsOneWidget);
|
||||
expect(
|
||||
tester.getSize(find.byKey(const Key('mine-vip-open'))).height,
|
||||
greaterThanOrEqualTo(AppDimens.tapTarget),
|
||||
);
|
||||
const benefitKeys = [
|
||||
Key('mine-vip-benefit-0'),
|
||||
Key('mine-vip-benefit-1'),
|
||||
Key('mine-vip-benefit-2'),
|
||||
Key('mine-vip-benefit-3'),
|
||||
];
|
||||
final benefitTops = benefitKeys
|
||||
.map((key) => tester.getTopLeft(find.byKey(key)))
|
||||
.toList();
|
||||
expect(benefitTops.map((position) => position.dy).toSet(), hasLength(1));
|
||||
expect(
|
||||
benefitTops.map((position) => position.dx).toSet(),
|
||||
hasLength(benefitKeys.length),
|
||||
);
|
||||
|
||||
final order = [
|
||||
tester.getTopLeft(find.byKey(const Key('mine-user-row'))).dy,
|
||||
tester.getTopLeft(find.byKey(const Key('mine-vip'))).dy,
|
||||
tester.getTopLeft(find.byKey(const Key('mine-wallet'))).dy,
|
||||
tester.getTopLeft(find.byKey(const Key('mine-help'))).dy,
|
||||
];
|
||||
expect(order, [...order]..sort());
|
||||
expect(tester.takeException(), isNull);
|
||||
@@ -181,6 +261,7 @@ void main() {
|
||||
expect(find.byType(MineAboutPage), findsOneWidget);
|
||||
expect(find.byKey(const Key('mine-about-page')), findsOneWidget);
|
||||
expect(find.text('Version 1.0.0'), findsOneWidget);
|
||||
expect(find.text('Your mini business'), findsOneWidget);
|
||||
expect(
|
||||
find.text(
|
||||
AppLocalizations.of(
|
||||
@@ -245,16 +326,17 @@ void main() {
|
||||
padding: const EdgeInsets.all(AppDimens.pageHorizontal),
|
||||
child: Column(
|
||||
children: [
|
||||
MineQuickActions(
|
||||
onWallet: () => opened.add(MineDestination.wallet),
|
||||
onFavorites: () => favoritesOpened++,
|
||||
onDownloads: () => opened.add(MineDestination.downloads),
|
||||
onHistory: () => opened.add(MineDestination.history),
|
||||
),
|
||||
MineServiceList(
|
||||
onOpen: opened.add,
|
||||
onLanguage: () => languageOpened++,
|
||||
languageName: 'English',
|
||||
MineActionGrid(
|
||||
primaryActions: MinePrimaryActions(
|
||||
onWallet: () => opened.add(MineDestination.wallet),
|
||||
onFavorites: () => favoritesOpened++,
|
||||
onDownloads: () => opened.add(MineDestination.downloads),
|
||||
onHistory: () => opened.add(MineDestination.history),
|
||||
),
|
||||
serviceActions: MineServiceActions(
|
||||
onOpen: opened.add,
|
||||
onLanguage: () => languageOpened++,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user