feat(nav): 底部导航改为首页推荐追剧我的

This commit is contained in:
Zhou Weidong committed 2026-10-22 16:21:05 +08:00
1 parent ec3cb8f163
commit 91e869d589
34 files changed
+359 -263

No files matched your search

+2 -2
View File
@@ -99,9 +99,9 @@ void main() {
);
expect(forwarded, [DiscoverPageAction.home]);
logic.act(pageContext, DiscoverPageAction.my, embedded: false);
logic.act(pageContext, DiscoverPageAction.mine, embedded: false);
await tester.pumpAndSettle();
await expectLater(popped.future, completion(DiscoverPageAction.my));
await expectLater(popped.future, completion(DiscoverPageAction.mine));
logic.dispose();
});
+1 -1
View File
@@ -151,7 +151,7 @@ Future<void> _pumpFilterPage(WidgetTester tester) async {
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('theater-toolbar-filter')));
await tester.pumpAndSettle();
+1 -1
View File
@@ -455,7 +455,7 @@ Future<void> _pumpTheater(
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
}
+1 -1
View File
@@ -303,7 +303,7 @@ Future<void> _pumpTheater(
),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
}
+30 -24
View File
@@ -7,7 +7,7 @@ import 'package:fruitshorts/core/theme/app_dimens.dart';
import 'package:fruitshorts/core/widgets/app_bottom_nav.dart';
void main() {
testWidgets('should_render_four_slots_with_orange_selected_state', (
testWidgets('should_render_four_slots_with_white_selected_state', (
tester,
) async {
var theaterTaps = 0;
@@ -25,17 +25,17 @@ void main() {
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-theater'),
icon: Icons.explore_outlined,
selectedIcon: Icons.explore_rounded,
label: 'Theater',
tabKey: const Key('tab-recommend'),
icon: Icons.smart_display_outlined,
selectedIcon: Icons.smart_display_rounded,
label: 'Recommend',
onTap: () => theaterTaps++,
),
AppBottomNavItem(
tabKey: const Key('tab-create'),
icon: Icons.add_box_outlined,
selectedIcon: Icons.add_box_rounded,
label: 'Create',
tabKey: const Key('tab-follow'),
icon: Icons.bookmark_border_rounded,
selectedIcon: Icons.bookmark_rounded,
label: 'Following',
onTap: () {},
),
AppBottomNavItem(
@@ -52,15 +52,21 @@ void main() {
);
expect(find.byKey(const Key('tab-home')), findsOneWidget);
expect(find.byKey(const Key('tab-theater')), findsOneWidget);
expect(find.byKey(const Key('tab-create')), findsOneWidget);
expect(find.byKey(const Key('tab-recommend')), findsOneWidget);
expect(find.byKey(const Key('tab-follow')), findsOneWidget);
expect(find.byKey(const Key('tab-mine')), findsOneWidget);
expect(find.byKey(const Key('nav-center-action')), findsNothing);
expect(find.text('Home'), findsOneWidget);
final selectedLabel = tester.widget<Text>(find.text('Home'));
expect(selectedLabel.style?.color, AppColors.navSelected);
expect(selectedLabel.style?.fontWeight, FontWeight.w600);
final unselectedLabel = tester.widget<Text>(find.text('Recommend'));
expect(unselectedLabel.style?.color, AppColors.navUnselected);
expect(unselectedLabel.style?.fontWeight, FontWeight.w400);
final centers = [
Key('tab-home'),
Key('tab-theater'),
Key('tab-create'),
Key('tab-recommend'),
Key('tab-follow'),
Key('tab-mine'),
].map((key) => tester.getCenter(find.byKey(key)).dx).toList();
expect(centers, orderedEquals(centers.toList()..sort()));
@@ -77,9 +83,9 @@ void main() {
),
)
.color,
AppColors.blue,
AppColors.navSelected,
);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
expect(theaterTaps, 1);
});
@@ -105,17 +111,17 @@ void main() {
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-theater'),
icon: Icons.explore_outlined,
selectedIcon: Icons.explore_rounded,
label: 'Theater',
tabKey: const Key('tab-recommend'),
icon: Icons.smart_display_outlined,
selectedIcon: Icons.smart_display_rounded,
label: 'Recommend',
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-create'),
icon: Icons.add_box_outlined,
selectedIcon: Icons.add_box_rounded,
label: 'Create',
tabKey: const Key('tab-follow'),
icon: Icons.bookmark_border_rounded,
selectedIcon: Icons.bookmark_rounded,
label: 'Following',
onTap: () {},
),
AppBottomNavItem(
@@ -144,6 +150,6 @@ void main() {
matching: find.byType(ColoredBox),
),
);
expect(coloredBox.color, AppColors.bar);
expect(coloredBox.color, AppColors.navBackground);
});
}
+4 -4
View File
@@ -159,11 +159,11 @@ void main() {
test('should_map_onto_root_tabs_when_my_page_actions_fire', () {
final logic = HomeLogic(dramas);
logic.myAction(MyPageAction.discover);
logic.myAction(MyPageAction.recommend);
expect(logic.tab, 1);
expect(logic.searchRequest, 1);
logic.myAction(MyPageAction.create);
logic.myAction(MyPageAction.following);
expect(logic.tab, 2);
logic.myAction(MyPageAction.resume);
@@ -179,10 +179,10 @@ void main() {
test('should_map_onto_root_tabs_when_discover_actions_fire', () {
final logic = HomeLogic(dramas);
logic.discoverAction(DiscoverPageAction.my);
logic.discoverAction(DiscoverPageAction.mine);
expect(logic.tab, 3);
logic.discoverAction(DiscoverPageAction.create);
logic.discoverAction(DiscoverPageAction.following);
expect(logic.tab, 2);
logic.discoverAction(DiscoverPageAction.home);
+106 -22
View File
@@ -7,6 +7,8 @@ import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/widgets/app_bottom_nav.dart';
import 'package:fruitshorts/pages/favorites/favorites_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';
@@ -19,8 +21,8 @@ import '../support/widget_player.dart';
const _keys = [
Key('home-tabs-bar'),
Key('tab-home'),
Key('tab-theater'),
Key('tab-create'),
Key('tab-recommend'),
Key('tab-follow'),
Key('tab-mine'),
];
@@ -47,20 +49,54 @@ void main() {
for (final key in _keys.skip(1)) {
expect(tester.getSize(find.byKey(key)).height, greaterThanOrEqualTo(48));
}
final tabCenters = _keys
.skip(1)
.map((key) => tester.getCenter(find.byKey(key)).dx)
.toList();
expect(tabCenters, orderedEquals(tabCenters.toList()..sort()));
expect(
find.descendant(
of: find.byKey(const Key('tab-home')),
matching: find.text('Home'),
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-recommend')),
matching: find.text('Recommend'),
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-follow')),
matching: find.text('Following'),
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-mine')),
matching: find.text('My'),
),
findsOneWidget,
);
final barFinder = find.byKey(const Key('home-tabs-bar'));
final bar = tester.widget<Container>(barFinder);
final decoration = bar.decoration as BoxDecoration;
final border = decoration.border as Border;
// 所有页面统一深色导航。
expect(decoration.color, AppColors.bar);
expect(border.top.color, AppColors.border);
expect(decoration.color, AppColors.navBackground);
expect(border.top.color, AppColors.navDivider);
expect(border.top.width, 0.5);
expect(
tester
.widget<Text>(
find.descendant(
of: find.byKey(const Key('tab-theater')),
matching: find.text('Theater'),
of: find.byKey(const Key('tab-recommend')),
matching: find.text('Recommend'),
),
)
.style
@@ -85,6 +121,27 @@ void main() {
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-recommend')),
matching: find.byIcon(Icons.smart_display_outlined),
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-follow')),
matching: find.byIcon(Icons.bookmark_border_rounded),
),
findsOneWidget,
);
expect(
find.descendant(
of: find.byKey(const Key('tab-mine')),
matching: find.byIcon(Icons.person_outline_rounded),
),
findsOneWidget,
);
expect(
tester
.widget<Icon>(
@@ -94,23 +151,26 @@ void main() {
),
)
.color,
AppColors.blue,
AppColors.navSelected,
);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(haptics.selectionClicks, 1);
final theaterBar = tester.widget<Container>(barFinder);
final theaterDecoration = theaterBar.decoration as BoxDecoration;
expect(theaterDecoration.color, AppColors.bar.withValues(alpha: 0.96));
expect((theaterDecoration.border as Border).top.color, AppColors.border);
await tester.tap(find.byKey(const Key('tab-theater')));
expect(theaterDecoration.color, AppColors.navBackground);
expect(
(theaterDecoration.border as Border).top.color,
AppColors.navDivider,
);
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(haptics.selectionClicks, 1);
expect(
find.descendant(
of: find.byKey(const Key('tab-theater')),
matching: find.byIcon(Icons.explore_rounded),
of: find.byKey(const Key('tab-recommend')),
matching: find.byIcon(Icons.smart_display_rounded),
),
findsOneWidget,
);
@@ -118,13 +178,13 @@ void main() {
tester
.widget<Text>(
find.descendant(
of: find.byKey(const Key('tab-theater')),
matching: find.text('Theater'),
of: find.byKey(const Key('tab-recommend')),
matching: find.text('Recommend'),
),
)
.style
?.color,
AppColors.blue,
AppColors.navSelected,
);
expect(
tester
@@ -147,32 +207,56 @@ void main() {
);
});
testWidgets('should_map_four_tabs_to_home_theater_create_and_me', (
testWidgets('should_map_four_tabs_to_home_recommend_following_and_me', (
tester,
) async {
await _pumpApp(tester);
expect(find.byKey(const Key('tab-home')), findsOneWidget);
expect(find.byKey(const Key('tab-theater')), findsOneWidget);
expect(find.byKey(const Key('tab-create')), findsOneWidget);
expect(find.byKey(const Key('tab-recommend')), findsOneWidget);
expect(find.byKey(const Key('tab-follow')), findsOneWidget);
expect(find.byKey(const Key('tab-mine')), findsOneWidget);
expect(find.byKey(const Key('tab-create')), findsNothing);
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-create')));
await tester.tap(find.byKey(const Key('tab-follow')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('create-page')), findsOneWidget);
final favorites = find.byType(FavoritesContent);
expect(favorites, findsOneWidget);
expect(find.byKey(const Key('favorites-page')), findsOneWidget);
expect(find.byKey(const Key('favorites-back')), findsNothing);
expect(find.byType(AppBottomNav), findsOneWidget);
expect(
find.descendant(of: favorites, matching: find.byType(Scaffold)),
findsNothing,
);
expect(Navigator.canPop(tester.element(favorites)), isFalse);
expect(
find.descendant(
of: find.byKey(const Key('tab-follow')),
matching: find.byIcon(Icons.bookmark_rounded),
),
findsOneWidget,
);
await tester.tap(find.byKey(const Key('tab-mine')));
await tester.pumpAndSettle();
expect(find.text('Viewer'), findsOneWidget);
expect(find.byKey(const Key('mine-menu')), findsOneWidget);
expect(find.byKey(const Key('mine-watchlist')), findsOneWidget);
expect(find.byKey(const Key('mine-creator-center')), findsOneWidget);
expect(find.byKey(const Key('mine-library-tab-0')), findsNothing);
await tester.tap(find.byKey(const Key('tab-follow')));
await tester.pumpAndSettle();
expect(favorites, findsOneWidget);
expect(find.byType(AppBottomNav), findsOneWidget);
expect(Navigator.canPop(tester.element(favorites)), isFalse);
await tester.tap(find.byKey(const Key('tab-home')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
+14 -26
View File
@@ -10,6 +10,7 @@ import 'package:fruitshorts/core/data/models/feed_page.dart';
import 'package:fruitshorts/core/data/repositories/favorite_repository.dart';
import 'package:fruitshorts/core/data/repositories/playback_repository.dart';
import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart';
import 'package:fruitshorts/core/widgets/app_bottom_nav.dart';
import 'package:fruitshorts/pages/home/home_feed_channel.dart';
import 'package:fruitshorts/pages/player/player_view.dart';
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
@@ -27,7 +28,7 @@ void main() {
InMemorySharedPreferencesAsync.empty();
});
testWidgets('should_render_four_tabs_and_open_create_placeholder', (
testWidgets('should_render_four_tabs_and_open_following_page', (
tester,
) async {
await _pumpApp(tester);
@@ -35,27 +36,14 @@ void main() {
for (final key in _tabKeys) {
expect(find.byKey(key), findsOneWidget);
}
expect(find.byKey(const Key('tab-create')), findsNothing);
await tester.tap(find.byKey(const Key('tab-create')));
await tester.tap(find.byKey(const Key('tab-follow')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('create-page')), findsOneWidget);
expect(find.text('Create'), findsWidgets);
expect(find.text('Stories become short dramas'), findsOneWidget);
expect(find.byKey(const Key('create-ai')), findsOneWidget);
expect(find.byKey(const Key('create-upload')), findsOneWidget);
expect(tester.getSize(find.byKey(const Key('create-ai'))).height, 196);
expect(find.byKey(const Key('create-motto-primary')), findsOneWidget);
expect(find.byKey(const Key('create-motto-secondary')), findsOneWidget);
expect(
tester.getSize(find.byKey(const Key('create-motto-line'))),
const Size(96, 2),
);
await tester.tap(find.byKey(const Key('create-ai')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('create-placeholder-page')), findsOneWidget);
expect(find.text('Coming soon'), findsOneWidget);
expect(find.byKey(const Key('favorites-page')), findsOneWidget);
expect(find.byKey(const Key('favorites-back')), findsNothing);
expect(find.byType(AppBottomNav), findsOneWidget);
});
testWidgets('should_start_home_on_immersive_feed', (tester) async {
@@ -334,7 +322,7 @@ void main() {
await _pumpApp(tester);
expect(_hasLightStatusBar(tester), isTrue);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-page-gradient')), findsOneWidget);
@@ -395,7 +383,7 @@ void main() {
await _pumpApp(tester);
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-feed-title')), findsNothing);
@@ -418,7 +406,7 @@ void main() {
testWidgets('should_not_render_theater_language_filters', (tester) async {
await _pumpApp(tester);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
@@ -435,7 +423,7 @@ void main() {
tester,
) async {
await _pumpApp(tester);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
final card = find.byKey(const Key('home-drama-card-the-signal-demo'));
@@ -464,7 +452,7 @@ void main() {
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
expect(tester.takeException(), isNull);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('theater-category-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
@@ -474,8 +462,8 @@ void main() {
const _tabKeys = [
Key('tab-home'),
Key('tab-theater'),
Key('tab-create'),
Key('tab-recommend'),
Key('tab-follow'),
Key('tab-mine'),
];
+2 -2
View File
@@ -91,11 +91,11 @@ void main() {
logic.act(
pageContext,
MyPageAction.discover,
MyPageAction.recommend,
embedded: true,
onAction: forwarded.add,
);
expect(forwarded, [MyPageAction.discover]);
expect(forwarded, [MyPageAction.recommend]);
logic.act(pageContext, MyPageAction.resume, embedded: false);
await tester.pumpAndSettle();
+2 -2
View File
@@ -39,7 +39,7 @@ void main() {
tester,
) async {
await _pumpApp(tester);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('home-drama-card-city-lights-demo')));
await tester.pumpAndSettle();
@@ -1331,7 +1331,7 @@ Future<void> _openSeriesPlayer(
WidgetTester tester, {
Key cardKey = const Key('home-drama-card-city-lights-demo'),
}) async {
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
final card = find.byKey(cardKey);
await tester.scrollUntilVisible(
+1 -1
View File
@@ -18,7 +18,7 @@ void main() {
expect(AppDimens.listTitle, 15);
expect(AppDimens.sectionTitle, 16);
expect(AppDimens.pageTitle, 20);
expect(AppDimens.navLabel, 12);
expect(AppDimens.navLabel, 11);
expect(AppDimens.navIcon, 24);
expect(AppDimens.buttonHeight, 48);
expect(AppDimens.primaryButtonHeight, 52);
+4 -1
View File
@@ -63,7 +63,10 @@ void main() {
expect(theme.appBarTheme.systemOverlayStyle, SystemUiOverlayStyle.light);
expect(theme.cardTheme.elevation, 0);
expect(theme.dialogTheme.backgroundColor, AppColors.raised);
expect(theme.bottomNavigationBarTheme.backgroundColor, AppColors.bar);
expect(
theme.bottomNavigationBarTheme.backgroundColor,
AppColors.navBackground,
);
expect(theme.inputDecorationTheme.fillColor, AppColors.input);
});
+8 -8
View File
@@ -120,9 +120,9 @@ void main() {
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-create')));
await tester.tap(find.byKey(const Key('tab-follow')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('create-page')), findsOneWidget);
expect(find.byKey(const Key('favorites-page')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-mine')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('mine-menu')), findsOneWidget);
@@ -144,9 +144,9 @@ void main() {
expect(find.byKey(const Key('mine-language')), findsOneWidget);
expect(find.byKey(const Key('mine-wallet')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.text('Theater'), findsWidgets);
expect(find.text('Recommend'), findsWidgets);
});
testWidgets('should_switch_app_language_from_mine_menu', (tester) async {
@@ -168,9 +168,9 @@ void main() {
expect(find.text('我的'), findsWidgets);
expect(find.text('语言'), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.text('剧场'), findsWidgets);
expect(find.text('推荐'), findsWidgets);
});
testWidgets('should_fit_compact_viewport_when_player_is_opened', (
@@ -207,7 +207,7 @@ void main() {
await tester.pumpWidget(appUnderTest());
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('discover-search')), findsOneWidget);
@@ -316,7 +316,7 @@ void main() {
}
Future<void> _openTheaterPlayer(WidgetTester tester) async {
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.tap(find.byKey(const Key('tab-recommend')));
await tester.pumpAndSettle();
final card = find.byKey(const Key('home-drama-card-city-lights-demo'));
await tester.scrollUntilVisible(