feat(nav): 底部导航改为首页推荐追剧我的
This commit is contained in:
1 parent
ec3cb8f163
commit
91e869d589
34 files changed
+359
-263
No files matched your search
@@ -69,6 +69,11 @@ abstract final class AppColors {
|
||||
/// 底部导航底色。
|
||||
static const bar = ink;
|
||||
|
||||
/// 底部导航专用:纯黑背景、选中白、未选中灰与轻分割线。
|
||||
static const navBackground = Color(0xFF000000);
|
||||
static const navSelected = Color(0xFFFFFFFF);
|
||||
static const navDivider = Color(0xFF1C1C1E);
|
||||
|
||||
/// 卡片阴影(深色几乎不用阴影)。
|
||||
static const cardShadow = Color(0x00000000);
|
||||
|
||||
@@ -121,7 +126,7 @@ abstract final class AppColors {
|
||||
static const badgeBeige = raised;
|
||||
|
||||
/// 导航未选中。
|
||||
static const navUnselected = muted;
|
||||
static const navUnselected = Color(0xFF8A8A8E);
|
||||
|
||||
/// 播放器次要文字。
|
||||
static const playerMuted = Color(0xA3FFFFFF);
|
||||
|
||||
@@ -36,7 +36,7 @@ abstract final class AppDimens {
|
||||
static const double previewCardTitle = 13;
|
||||
static const double previewSectionTitle = 14;
|
||||
static const double chipFont = 10;
|
||||
static const double navLabel = 12;
|
||||
static const double navLabel = 11;
|
||||
|
||||
static const double buttonHeight = 48;
|
||||
static const double primaryButtonHeight = 52;
|
||||
|
||||
@@ -193,8 +193,8 @@ abstract final class AppTheme {
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
backgroundColor: AppColors.bar,
|
||||
selectedItemColor: AppColors.blue,
|
||||
backgroundColor: AppColors.navBackground,
|
||||
selectedItemColor: AppColors.navSelected,
|
||||
unselectedItemColor: AppColors.navUnselected,
|
||||
elevation: 0,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
@@ -26,12 +24,12 @@ class AppBottomNavItem {
|
||||
final bool selected;
|
||||
}
|
||||
|
||||
/// 四槽底部导航:所有页面统一深色底与浅色图标。
|
||||
/// 四槽底部导航:纯黑背景,白色选中态,灰色未选中态。
|
||||
class AppBottomNav extends StatelessWidget {
|
||||
const AppBottomNav({
|
||||
super.key,
|
||||
required this.items,
|
||||
this.backgroundColor = AppColors.bar,
|
||||
this.backgroundColor = AppColors.navBackground,
|
||||
this.barKey,
|
||||
this.dark = false,
|
||||
});
|
||||
@@ -47,8 +45,10 @@ class AppBottomNav extends StatelessWidget {
|
||||
key: barKey,
|
||||
height: AppDimens.navHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: dark ? AppColors.bar : backgroundColor.withValues(alpha: 0.96),
|
||||
border: const Border(top: BorderSide(color: AppColors.border)),
|
||||
color: dark ? AppColors.navBackground : backgroundColor,
|
||||
border: const Border(
|
||||
top: BorderSide(color: AppColors.navDivider, width: 0.5),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -60,17 +60,9 @@ class AppBottomNav extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
);
|
||||
if (dark) {
|
||||
return ColoredBox(
|
||||
color: AppColors.bar,
|
||||
child: SafeArea(top: false, child: bar),
|
||||
);
|
||||
}
|
||||
return ClipRect(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
|
||||
child: SafeArea(top: false, child: bar),
|
||||
),
|
||||
return ColoredBox(
|
||||
color: AppColors.navBackground,
|
||||
child: SafeArea(top: false, child: bar),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +94,9 @@ class _NavDestination extends StatelessWidget {
|
||||
child: Icon(
|
||||
item.selected ? item.selectedIcon : item.icon,
|
||||
size: AppDimens.navIcon,
|
||||
color: item.selected ? AppColors.blue : unselectedColor,
|
||||
color: item.selected
|
||||
? AppColors.navSelected
|
||||
: unselectedColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
@@ -112,8 +106,10 @@ class _NavDestination extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: AppDimens.navLabel,
|
||||
fontWeight: item.selected ? FontWeight.w700 : FontWeight.w500,
|
||||
color: item.selected ? AppColors.blue : unselectedColor,
|
||||
fontWeight: item.selected ? FontWeight.w600 : FontWeight.w400,
|
||||
color: item.selected
|
||||
? AppColors.navSelected
|
||||
: unselectedColor,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
/// 客户端根导航的固定顺序。
|
||||
enum AppRootTab { home, recommend, following, mine }
|
||||
|
||||
extension AppRootTabUi on AppRootTab {
|
||||
Key get tabKey => switch (this) {
|
||||
AppRootTab.home => const Key('tab-home'),
|
||||
AppRootTab.recommend => const Key('tab-recommend'),
|
||||
AppRootTab.following => const Key('tab-follow'),
|
||||
AppRootTab.mine => const Key('tab-mine'),
|
||||
};
|
||||
|
||||
IconData get icon => switch (this) {
|
||||
AppRootTab.home => Icons.home_outlined,
|
||||
AppRootTab.recommend => Icons.smart_display_outlined,
|
||||
AppRootTab.following => Icons.bookmark_border_rounded,
|
||||
AppRootTab.mine => Icons.person_outline_rounded,
|
||||
};
|
||||
|
||||
IconData get selectedIcon => switch (this) {
|
||||
AppRootTab.home => Icons.home_rounded,
|
||||
AppRootTab.recommend => Icons.smart_display_rounded,
|
||||
AppRootTab.following => Icons.bookmark_rounded,
|
||||
AppRootTab.mine => Icons.person_rounded,
|
||||
};
|
||||
|
||||
String label(AppLocalizations l10n) => switch (this) {
|
||||
AppRootTab.home => l10n.homeTab,
|
||||
AppRootTab.recommend => l10n.recommendedTab,
|
||||
AppRootTab.following => l10n.followingTab,
|
||||
AppRootTab.mine => l10n.myTab,
|
||||
};
|
||||
}
|
||||
@@ -120,6 +120,7 @@ class AppSubpageHeader extends StatelessWidget {
|
||||
this.actions,
|
||||
this.onBack,
|
||||
this.dark = false,
|
||||
this.showBack = true,
|
||||
});
|
||||
|
||||
final String title;
|
||||
@@ -128,6 +129,7 @@ class AppSubpageHeader extends StatelessWidget {
|
||||
final Widget? actions;
|
||||
final VoidCallback? onBack;
|
||||
final bool dark;
|
||||
final bool showBack;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -140,8 +142,14 @@ class AppSubpageHeader extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: _horizontal),
|
||||
child: Row(
|
||||
children: [
|
||||
AppSubpageBackButton(backKey: backKey, dark: dark, onBack: onBack),
|
||||
const SizedBox(width: _backGap),
|
||||
if (showBack) ...[
|
||||
AppSubpageBackButton(
|
||||
backKey: backKey,
|
||||
dark: dark,
|
||||
onBack: onBack,
|
||||
),
|
||||
const SizedBox(width: _backGap),
|
||||
],
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
+1
-1
@@ -162,7 +162,7 @@
|
||||
"preferences": "Preferences",
|
||||
"followingTab": "Following",
|
||||
"animatedTab": "Animated",
|
||||
"recommendedTab": "Recommended",
|
||||
"recommendedTab": "Recommend",
|
||||
"noCategoryDramas": "No dramas in this category yet.",
|
||||
"allDramas": "All Dramas",
|
||||
"allLanguages": "All languages",
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@
|
||||
"completed": "Selesai",
|
||||
"noSavedShows": "Belum ada tontonan di sini.",
|
||||
"preferences": "Preferensi",
|
||||
"followingTab": "Mengikuti",
|
||||
"followingTab": "Daftar Tonton",
|
||||
"animatedTab": "Animasi",
|
||||
"recommendedTab": "Rekomendasi",
|
||||
"noCategoryDramas": "Belum ada drama di kategori ini.",
|
||||
|
||||
@@ -685,7 +685,7 @@ abstract class AppLocalizations {
|
||||
/// No description provided for @recommendedTab.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Recommended'**
|
||||
/// **'Recommend'**
|
||||
String get recommendedTab;
|
||||
|
||||
/// No description provided for @noCategoryDramas.
|
||||
|
||||
@@ -329,7 +329,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get animatedTab => 'Animated';
|
||||
|
||||
@override
|
||||
String get recommendedTab => 'Recommended';
|
||||
String get recommendedTab => 'Recommend';
|
||||
|
||||
@override
|
||||
String get noCategoryDramas => 'No dramas in this category yet.';
|
||||
|
||||
@@ -323,7 +323,7 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get preferences => 'Preferensi';
|
||||
|
||||
@override
|
||||
String get followingTab => 'Mengikuti';
|
||||
String get followingTab => 'Daftar Tonton';
|
||||
|
||||
@override
|
||||
String get animatedTab => 'Animasi';
|
||||
|
||||
@@ -318,7 +318,7 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
String get preferences => '偏好设置';
|
||||
|
||||
@override
|
||||
String get followingTab => '关注';
|
||||
String get followingTab => '追剧';
|
||||
|
||||
@override
|
||||
String get animatedTab => '漫剧';
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@
|
||||
"completed": "已看完",
|
||||
"noSavedShows": "这里还没有剧集。",
|
||||
"preferences": "偏好设置",
|
||||
"followingTab": "关注",
|
||||
"followingTab": "追剧",
|
||||
"animatedTab": "漫剧",
|
||||
"recommendedTab": "推荐",
|
||||
"noCategoryDramas": "这个分类暂时没有剧集。",
|
||||
|
||||
@@ -4,8 +4,8 @@ import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../core/data/models/drama.dart';
|
||||
|
||||
/// 剧场页与根导航之间的动作。
|
||||
enum DiscoverPageAction { home, create, my }
|
||||
/// 推荐页与根导航之间的动作。
|
||||
enum DiscoverPageAction { home, recommend, following, mine }
|
||||
|
||||
/// 剧场页导航回调;没有 `onAction` 时按独立页面处理。
|
||||
class DiscoverPageCallbacks {
|
||||
|
||||
@@ -19,6 +19,7 @@ import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/app_bottom_nav.dart';
|
||||
import '../../core/widgets/app_pull_to_refresh.dart';
|
||||
import '../../core/widgets/app_root_tab.dart';
|
||||
import '../../core/widgets/catalog_debug_info.dart';
|
||||
import '../../core/widgets/catalog_endpoint_editor.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
@@ -149,7 +150,7 @@ class _DiscoverPageState extends State<DiscoverPage> {
|
||||
key: const Key('theater-page-surface'),
|
||||
color: AppColors.ink,
|
||||
child: SafeArea(
|
||||
bottom: !embedded,
|
||||
bottom: false,
|
||||
child: Column(
|
||||
children: [
|
||||
DiscoverHeader(
|
||||
@@ -613,37 +614,26 @@ class _DiscoverPageState extends State<DiscoverPage> {
|
||||
|
||||
Widget _bottomNav(AppLocalizations l10n) => AppBottomNav(
|
||||
items: [
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('discover-nav-home'),
|
||||
icon: Icons.home_outlined,
|
||||
selectedIcon: Icons.home_rounded,
|
||||
label: l10n.homeTab,
|
||||
onTap: () => _act(DiscoverPageAction.home),
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('discover-nav-current'),
|
||||
icon: Icons.explore_outlined,
|
||||
selectedIcon: Icons.explore_rounded,
|
||||
label: l10n.theaterTab,
|
||||
selected: true,
|
||||
onTap: () {},
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('discover-nav-create'),
|
||||
icon: Icons.add_box_outlined,
|
||||
selectedIcon: Icons.add_box_rounded,
|
||||
label: l10n.createTab,
|
||||
onTap: () => _act(DiscoverPageAction.create),
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('discover-nav-my'),
|
||||
icon: Icons.person_outline_rounded,
|
||||
selectedIcon: Icons.person_rounded,
|
||||
label: l10n.myTab,
|
||||
onTap: () => _act(DiscoverPageAction.my),
|
||||
),
|
||||
for (final tab in AppRootTab.values)
|
||||
AppBottomNavItem(
|
||||
tabKey: tab.tabKey,
|
||||
icon: tab.icon,
|
||||
selectedIcon: tab.selectedIcon,
|
||||
label: tab.label(l10n),
|
||||
selected: tab == AppRootTab.recommend,
|
||||
onTap: tab == AppRootTab.recommend
|
||||
? () {}
|
||||
: () => _act(_actionOf(tab)),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
DiscoverPageAction _actionOf(AppRootTab tab) => switch (tab) {
|
||||
AppRootTab.home => DiscoverPageAction.home,
|
||||
AppRootTab.recommend => DiscoverPageAction.recommend,
|
||||
AppRootTab.following => DiscoverPageAction.following,
|
||||
AppRootTab.mine => DiscoverPageAction.mine,
|
||||
};
|
||||
}
|
||||
|
||||
/// 分类 tab 的弧形选中线。
|
||||
|
||||
@@ -44,14 +44,33 @@ const double _loadMoreThreshold = 240;
|
||||
final RegExp _tagSplitter = RegExp(r'[,/、·]');
|
||||
|
||||
/// 独立我的收藏页。
|
||||
class FavoritesPage extends StatefulWidget {
|
||||
class FavoritesPage extends StatelessWidget {
|
||||
const FavoritesPage({super.key});
|
||||
|
||||
@override
|
||||
State<FavoritesPage> createState() => _FavoritesPageState();
|
||||
Widget build(BuildContext context) {
|
||||
return Theme(
|
||||
data: AppTheme.dark(),
|
||||
child: Scaffold(
|
||||
key: const Key('favorites-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
body: const SafeArea(child: FavoritesContent()),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FavoritesPageState extends State<FavoritesPage> {
|
||||
/// 收藏列表主体;可独立使用,也可直接嵌入根导航。
|
||||
class FavoritesContent extends StatefulWidget {
|
||||
const FavoritesContent({super.key, this.showBack = true});
|
||||
|
||||
final bool showBack;
|
||||
|
||||
@override
|
||||
State<FavoritesContent> createState() => _FavoritesContentState();
|
||||
}
|
||||
|
||||
class _FavoritesContentState extends State<FavoritesContent> {
|
||||
bool _requested = false;
|
||||
|
||||
@override
|
||||
@@ -74,28 +93,21 @@ class _FavoritesPageState extends State<FavoritesPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
return Theme(
|
||||
data: AppTheme.dark(),
|
||||
child: Scaffold(
|
||||
key: const Key('favorites-page'),
|
||||
backgroundColor: AppColors.ink,
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
AppSubpageHeader(
|
||||
title: l10n.myFavorites,
|
||||
backKey: const Key('favorites-back'),
|
||||
),
|
||||
Expanded(
|
||||
child: signedIn
|
||||
? _FavoritesBody(
|
||||
favorites: context.watch<FavoriteController>(),
|
||||
)
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
],
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: Column(
|
||||
children: [
|
||||
AppSubpageHeader(
|
||||
title: l10n.myFavorites,
|
||||
backKey: const Key('favorites-back'),
|
||||
showBack: widget.showBack,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: signedIn
|
||||
? _FavoritesBody(favorites: context.watch<FavoriteController>())
|
||||
: const AuthGatePanel(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,9 +79,11 @@ class HomeLogic extends ChangeNotifier {
|
||||
switch (action) {
|
||||
case DiscoverPageAction.home:
|
||||
select(0);
|
||||
case DiscoverPageAction.create:
|
||||
case DiscoverPageAction.recommend:
|
||||
select(1, search: true);
|
||||
case DiscoverPageAction.following:
|
||||
select(2);
|
||||
case DiscoverPageAction.my:
|
||||
case DiscoverPageAction.mine:
|
||||
select(3);
|
||||
}
|
||||
}
|
||||
@@ -102,10 +104,12 @@ class HomeLogic extends ChangeNotifier {
|
||||
switch (action) {
|
||||
case MyPageAction.home:
|
||||
select(0);
|
||||
case MyPageAction.discover:
|
||||
case MyPageAction.recommend:
|
||||
select(1, search: true);
|
||||
case MyPageAction.create:
|
||||
case MyPageAction.following:
|
||||
select(2);
|
||||
case MyPageAction.mine:
|
||||
select(3);
|
||||
case MyPageAction.resume:
|
||||
select(0, resume: true);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ import '../../core/platform/haptics.dart';
|
||||
import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/app_bottom_nav.dart';
|
||||
import '../../core/widgets/app_root_tab.dart';
|
||||
import '../../core/widgets/catalog_debug_info.dart';
|
||||
import '../../core/widgets/catalog_endpoint_editor.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../discover/discover_types.dart';
|
||||
import '../discover/discover_view.dart';
|
||||
import '../create/create_view.dart';
|
||||
import '../favorites/favorites_page.dart';
|
||||
import '../mine/mine_types.dart';
|
||||
import '../player/widgets/home_feed_header.dart';
|
||||
import '../player/player_view.dart';
|
||||
@@ -295,7 +296,7 @@ class _HomeTabsState extends State<_HomeTabs> {
|
||||
children: [
|
||||
_home(context),
|
||||
_discover(context),
|
||||
const CreatePage(),
|
||||
const FavoritesContent(key: Key('favorites-page'), showBack: false),
|
||||
_my(context),
|
||||
],
|
||||
);
|
||||
@@ -455,10 +456,10 @@ class _HomeTabsState extends State<_HomeTabs> {
|
||||
barKey: const Key('home-tabs-bar'),
|
||||
dark: logic.tab == 0,
|
||||
items: [
|
||||
_navItem(context, l10n, 0),
|
||||
_navItem(context, l10n, 1),
|
||||
_navItem(context, l10n, 2),
|
||||
_navItem(context, l10n, 3),
|
||||
_navItem(context, l10n, AppRootTab.home),
|
||||
_navItem(context, l10n, AppRootTab.recommend),
|
||||
_navItem(context, l10n, AppRootTab.following),
|
||||
_navItem(context, l10n, AppRootTab.mine),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -466,43 +467,16 @@ class _HomeTabsState extends State<_HomeTabs> {
|
||||
AppBottomNavItem _navItem(
|
||||
BuildContext context,
|
||||
AppLocalizations l10n,
|
||||
int index,
|
||||
AppRootTab tab,
|
||||
) {
|
||||
final selected = logic.tab == index;
|
||||
return switch (index) {
|
||||
0 => AppBottomNavItem(
|
||||
tabKey: const Key('tab-home'),
|
||||
icon: Icons.home_outlined,
|
||||
selectedIcon: Icons.home_rounded,
|
||||
label: l10n.homeTab,
|
||||
selected: selected,
|
||||
onTap: () => _selectTab(context, index),
|
||||
),
|
||||
1 => AppBottomNavItem(
|
||||
tabKey: const Key('tab-theater'),
|
||||
icon: Icons.explore_outlined,
|
||||
selectedIcon: Icons.explore_rounded,
|
||||
label: l10n.theaterTab,
|
||||
selected: selected,
|
||||
onTap: () => _selectTab(context, index),
|
||||
),
|
||||
2 => AppBottomNavItem(
|
||||
tabKey: const Key('tab-create'),
|
||||
icon: Icons.add_box_outlined,
|
||||
selectedIcon: Icons.add_box_rounded,
|
||||
label: l10n.createTab,
|
||||
selected: selected,
|
||||
onTap: () => _selectTab(context, index),
|
||||
),
|
||||
_ => AppBottomNavItem(
|
||||
tabKey: const Key('tab-mine'),
|
||||
icon: Icons.person_outline_rounded,
|
||||
selectedIcon: Icons.person_rounded,
|
||||
label: l10n.myTab,
|
||||
selected: selected,
|
||||
onTap: () => _selectTab(context, index),
|
||||
),
|
||||
};
|
||||
return AppBottomNavItem(
|
||||
tabKey: tab.tabKey,
|
||||
icon: tab.icon,
|
||||
selectedIcon: tab.selectedIcon,
|
||||
label: tab.label(l10n),
|
||||
selected: logic.tab == tab.index,
|
||||
onTap: () => _selectTab(context, tab.index),
|
||||
);
|
||||
}
|
||||
|
||||
void _selectTab(BuildContext context, int tab) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter/foundation.dart';
|
||||
import '../../core/data/models/drama.dart';
|
||||
|
||||
/// 「我的」页与根导航之间的返回动作。
|
||||
enum MyPageAction { home, discover, create, resume }
|
||||
enum MyPageAction { home, recommend, following, mine, resume }
|
||||
|
||||
/// 「我的」页可进入的功能目的地。
|
||||
enum MineDestination {
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../../core/theme/app_colors.dart';
|
||||
import '../../core/theme/app_dimens.dart';
|
||||
import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/app_bottom_nav.dart';
|
||||
import '../../core/widgets/app_root_tab.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/plain_page_scaffold.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
@@ -81,7 +82,7 @@ class _MyPageState extends State<MyPage> {
|
||||
Widget _page(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final content = SafeArea(
|
||||
bottom: !embedded,
|
||||
bottom: false,
|
||||
child: Column(
|
||||
children: [
|
||||
_topBar(l10n),
|
||||
@@ -240,39 +241,26 @@ class _MyPageState extends State<MyPage> {
|
||||
Widget _bottomNav(AppLocalizations l10n) {
|
||||
return AppBottomNav(
|
||||
items: [
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('mine-nav-home'),
|
||||
icon: Icons.home_outlined,
|
||||
selectedIcon: Icons.home_rounded,
|
||||
label: l10n.homeTab,
|
||||
onTap: () => _act(MyPageAction.home),
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('mine-nav-discover'),
|
||||
icon: Icons.explore_outlined,
|
||||
selectedIcon: Icons.explore_rounded,
|
||||
label: l10n.theaterTab,
|
||||
onTap: () => _act(MyPageAction.discover),
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('mine-nav-create'),
|
||||
icon: Icons.add_box_outlined,
|
||||
selectedIcon: Icons.add_box_rounded,
|
||||
label: l10n.createTab,
|
||||
onTap: () => _act(MyPageAction.create),
|
||||
),
|
||||
AppBottomNavItem(
|
||||
tabKey: const Key('mine-nav-current'),
|
||||
icon: Icons.person_outline_rounded,
|
||||
selectedIcon: Icons.person_rounded,
|
||||
label: l10n.myTab,
|
||||
selected: true,
|
||||
onTap: () {},
|
||||
),
|
||||
for (final tab in AppRootTab.values)
|
||||
AppBottomNavItem(
|
||||
tabKey: tab.tabKey,
|
||||
icon: tab.icon,
|
||||
selectedIcon: tab.selectedIcon,
|
||||
label: tab.label(l10n),
|
||||
selected: tab == AppRootTab.mine,
|
||||
onTap: tab == AppRootTab.mine ? () {} : () => _act(_actionOf(tab)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
MyPageAction _actionOf(AppRootTab tab) => switch (tab) {
|
||||
AppRootTab.home => MyPageAction.home,
|
||||
AppRootTab.recommend => MyPageAction.recommend,
|
||||
AppRootTab.following => MyPageAction.following,
|
||||
AppRootTab.mine => MyPageAction.mine,
|
||||
};
|
||||
|
||||
void _act(MyPageAction action) {
|
||||
logic.act(
|
||||
context,
|
||||
|
||||
@@ -1085,7 +1085,7 @@ class PlayerLogic extends ChangeNotifier {
|
||||
context,
|
||||
).push<MyPageAction>(MaterialPageRoute(builder: (_) => const MyPage()));
|
||||
if (!context.mounted) return;
|
||||
if (action == MyPageAction.discover) {
|
||||
if (action == MyPageAction.recommend) {
|
||||
await showDiscover(context);
|
||||
} else {
|
||||
session.setRouteVisible(true);
|
||||
@@ -1117,7 +1117,7 @@ class PlayerLogic extends ChangeNotifier {
|
||||
MaterialPageRoute(builder: (_) => DiscoverPage(focusSearch: focusSearch)),
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
if (action == DiscoverPageAction.my) {
|
||||
if (action == DiscoverPageAction.mine) {
|
||||
await showMy(context);
|
||||
} else {
|
||||
session.setRouteVisible(true);
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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'),
|
||||
];
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in new issue
Block a user