From 4f6116896fb65fb2288adc87ba988b0f093836f3 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Thu, 22 Oct 2026 18:22:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(home):=20=E8=B0=83=E6=95=B4=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E5=88=86=E7=B1=BB=E4=B8=8E=E5=8D=A1=E7=89=87=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plans/PROGRESS.md | 6 +- lib/core/formatting/count_format.dart | 8 ++ lib/core/theme/app_dimens.dart | 9 +- lib/core/widgets/drama_genre_ribbon.dart | 88 +++++++++++++++++++ lib/pages/following/following_grid_card.dart | 34 +++---- lib/pages/following/following_page.dart | 2 +- lib/pages/home/widgets/home_feed_card.dart | 81 ++++++++--------- lib/pages/home/widgets/home_grid_header.dart | 6 +- .../widgets/recommend_section_card.dart | 36 +++----- test/core/count_format_test.dart | 7 ++ test/following/following_page_test.dart | 32 +++++-- test/home/home_card_style_test.dart | 29 ++++-- test/home/home_grid_layout_test.dart | 3 + test/recommend/recommend_sections_test.dart | 27 ++++-- 14 files changed, 251 insertions(+), 117 deletions(-) create mode 100644 lib/core/widgets/drama_genre_ribbon.dart diff --git a/docs/plans/PROGRESS.md b/docs/plans/PROGRESS.md index fdcf24d..292b1aa 100644 --- a/docs/plans/PROGRESS.md +++ b/docs/plans/PROGRESS.md @@ -1111,7 +1111,7 @@ $ flutter test ## 2026-10-22 首页布局对齐修正 -- 一级分类改为页内切换 6 个列表,选中 18/w700 白字、未选中 15/w400 灰字,无下划线。 -- 二级 chips 与一级行左对齐可滑动;未选项纯文字,选中项深灰胶囊。 -- 首页、剧单、全部短剧、追剧卡片移除底板/描边,标题与题材从封面左边起始,题材改为 `|` 分隔纯文字。 +- 一级分类改为页内切换 6 个列表,未选 16/w400 灰字、选中 20/w700 白字,无下划线;二级 chips 仅精选显示。 +- 四类短剧卡片移除底板/描边,封面统一 8 圆角,标题左对齐,题材移至封面右上角异形彩色丝带。 +- 播放量统一 spark 图标与 `w` 格式,整数无小数;首页、剧单、全部短剧、追剧共用。 - 全部短剧的地区、字幕、配音筛选 UI 已占位;以下接口待补:地区、字幕/配音筛选数据。 diff --git a/lib/core/formatting/count_format.dart b/lib/core/formatting/count_format.dart index c360d7e..2af1b47 100644 --- a/lib/core/formatting/count_format.dart +++ b/lib/core/formatting/count_format.dart @@ -7,3 +7,11 @@ String formatInteractionCount(int count) { if (count < 10000) return '$count'; return '${(count / 10000).toStringAsFixed(1)}万'; } + +/// 播放量展示:以 w 为单位,整数不保留小数,非整数保留一位。 +String formatPlayCount(int count) { + if (count < 10000) return '$count'; + final value = count / 10000; + if (value == value.roundToDouble()) return '${value.toInt()}w'; + return '${value.toStringAsFixed(1)}w'; +} diff --git a/lib/core/theme/app_dimens.dart b/lib/core/theme/app_dimens.dart index 7f62d8f..75db578 100644 --- a/lib/core/theme/app_dimens.dart +++ b/lib/core/theme/app_dimens.dart @@ -81,11 +81,16 @@ abstract final class AppDimens { static const double homeGridGap = 6; static const double homeGridRowGap = 18; static const double homeCardRadius = 6; + static const double cardCoverRadius = 8; static const double homeCardPadding = 8; static const double cardTitleFont = 15; static const double cardTitleLineHeight = 1.3; static const double cardViewsFont = 11; static const double cardViewsIcon = 11; + static const double cardGenreRibbonHeight = 20; + static const double cardGenreRibbonRadius = 10; + static const double cardGenreRibbonLeftInset = 8; + static const double cardGenreRibbonMaxWidth = 86; static const double cardTagFont = 11; static const double cardTagHeight = 18; static const double cardTagRadius = 9; @@ -98,8 +103,8 @@ abstract final class AppDimens { static const double cardTitleTagGap = 6; static const double cardCoverAspectRatio = 5 / 6; static const double homeCardBodyExtent = 84; - static const double homePrimaryTabFont = 15; - static const double homePrimaryTabSelectedFont = 18; + static const double homePrimaryTabFont = 16; + static const double homePrimaryTabSelectedFont = 20; static const double homePrimaryRowHeight = 30; static const Duration homePrimaryTabAnimationDuration = Duration( milliseconds: 180, diff --git a/lib/core/widgets/drama_genre_ribbon.dart b/lib/core/widgets/drama_genre_ribbon.dart new file mode 100644 index 0000000..93a42c8 --- /dev/null +++ b/lib/core/widgets/drama_genre_ribbon.dart @@ -0,0 +1,88 @@ +// Author: fruit.com.cn + +import 'package:flutter/material.dart'; + +import '../theme/app_colors.dart'; +import '../theme/app_dimens.dart'; + +const List _ribbonColors = [ + AppColors.badgeHot, + AppColors.badgeNew, + AppColors.badgeAnime, +]; + +/// 封面右上角的斜边题材丝带。 +class DramaGenreRibbon extends StatelessWidget { + const DramaGenreRibbon({ + super.key, + required this.tags, + required this.keyPrefix, + }); + + final List tags; + final String keyPrefix; + + @override + Widget build(BuildContext context) { + final visible = tags + .map((tag) => tag.trim()) + .where((tag) => tag.isNotEmpty) + .take(3) + .toList(growable: false); + if (visible.isEmpty) return const SizedBox.shrink(); + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + for (final (index, tag) in visible.indexed) ...[ + if (index > 0) const SizedBox(height: 2), + ClipPath( + key: Key('drama-genre-ribbon-$keyPrefix-$index'), + clipper: const _SlantedRibbonClipper(), + child: Container( + constraints: const BoxConstraints( + maxWidth: AppDimens.cardGenreRibbonMaxWidth, + ), + height: AppDimens.cardGenreRibbonHeight, + padding: const EdgeInsets.only( + left: + AppDimens.cardTagHorizontalPadding + + AppDimens.cardGenreRibbonLeftInset, + right: AppDimens.cardTagHorizontalPadding, + ), + alignment: Alignment.center, + color: _ribbonColors[index % _ribbonColors.length], + child: Text( + tag, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: AppColors.textPrimary, + fontSize: AppDimens.cardBadgeFont, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ], + ); + } +} + +class _SlantedRibbonClipper extends CustomClipper { + const _SlantedRibbonClipper(); + + @override + Path getClip(Size size) { + return Path() + ..moveTo(AppDimens.cardGenreRibbonLeftInset, 0) + ..lineTo(size.width, 0) + ..lineTo(size.width, size.height) + ..lineTo(0, size.height) + ..close(); + } + + @override + bool shouldReclip(_SlantedRibbonClipper oldClipper) => false; +} diff --git a/lib/pages/following/following_grid_card.dart b/lib/pages/following/following_grid_card.dart index 7c63162..7a7317e 100644 --- a/lib/pages/following/following_grid_card.dart +++ b/lib/pages/following/following_grid_card.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import '../../core/formatting/count_format.dart'; import '../../core/theme/app_colors.dart'; import '../../core/theme/app_dimens.dart'; +import '../../core/widgets/drama_genre_ribbon.dart'; import '../../core/widgets/remote_image.dart'; class FollowingGridCard extends StatelessWidget { @@ -37,7 +38,7 @@ class FollowingGridCard extends StatelessWidget { Widget build(BuildContext context) { return InkWell( key: Key('following-card-$dramaId'), - borderRadius: BorderRadius.circular(AppDimens.homeCardRadius), + borderRadius: BorderRadius.circular(AppDimens.cardCoverRadius), onTap: onTap, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -52,7 +53,7 @@ class FollowingGridCard extends StatelessWidget { Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular( - AppDimens.homeCardRadius, + AppDimens.cardCoverRadius, ), child: RemoteImage( posterUrl, @@ -78,12 +79,12 @@ class FollowingGridCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon( - Icons.play_arrow_rounded, + Icons.auto_awesome_rounded, color: AppColors.textPrimary, size: AppDimens.cardViewsIcon, ), Text( - formatInteractionCount(viewCount), + formatPlayCount(viewCount), key: Key('following-views-$dramaId'), style: const TextStyle( color: AppColors.textPrimary, @@ -94,6 +95,12 @@ class FollowingGridCard extends StatelessWidget { ), ), ), + if (!editing) + Positioned( + top: 0, + right: 0, + child: DramaGenreRibbon(tags: tags, keyPrefix: dramaId), + ), if (editing) Positioned( top: -6, @@ -128,10 +135,6 @@ class FollowingGridCard extends StatelessWidget { height: AppDimens.cardTitleLineHeight, ), ), - if (tags.isNotEmpty) ...[ - const SizedBox(height: AppDimens.cardTitleTagGap), - _tags(), - ], const SizedBox(height: AppDimens.spaceXs), Text( subtitle, @@ -161,19 +164,4 @@ class FollowingGridCard extends StatelessWidget { ), ); } - - Widget _tags() { - final visible = tags.take(3).toList(growable: false); - return Text( - visible.join(' | '), - key: Key('following-tags-$dramaId'), - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: const TextStyle( - color: AppColors.textTertiary, - fontSize: AppDimens.cardTagFont, - ), - ); - } } diff --git a/lib/pages/following/following_page.dart b/lib/pages/following/following_page.dart index 2f01832..5be30a2 100644 --- a/lib/pages/following/following_page.dart +++ b/lib/pages/following/following_page.dart @@ -339,7 +339,7 @@ List _dramaTags(Drama? drama) { .expand((value) => value.split(_tagSplitter)) .map((value) => value.trim()) .where((value) => value.isNotEmpty && seen.add(value)) - .take(2) + .take(3) .toList(growable: false); } diff --git a/lib/pages/home/widgets/home_feed_card.dart b/lib/pages/home/widgets/home_feed_card.dart index 54fc807..b78f575 100644 --- a/lib/pages/home/widgets/home_feed_card.dart +++ b/lib/pages/home/widgets/home_feed_card.dart @@ -6,6 +6,7 @@ import '../../../core/data/models/drama.dart'; import '../../../core/formatting/count_format.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; +import '../../../core/widgets/drama_genre_ribbon.dart'; import '../../../core/widgets/remote_image.dart'; import '../../../l10n/app_localizations.dart'; import 'home_drama_classification.dart'; @@ -33,7 +34,7 @@ class HomeFeedCard extends StatelessWidget { key: Key('home-feed-card-${drama.id}'), color: AppColors.transparent, child: InkWell( - borderRadius: BorderRadius.circular(AppDimens.homeCardRadius), + borderRadius: BorderRadius.circular(AppDimens.cardCoverRadius), onTap: onTap, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -62,8 +63,6 @@ class HomeFeedCard extends StatelessWidget { height: AppDimens.cardTitleLineHeight, ), ), - const SizedBox(height: AppDimens.cardTitleTagGap), - _tags(), ], ), ), @@ -76,30 +75,39 @@ class HomeFeedCard extends StatelessWidget { Widget _cover(AppLocalizations l10n) { final badge = _badge(); - return AspectRatio( - aspectRatio: AppDimens.cardCoverAspectRatio, - child: Stack( - fit: StackFit.expand, - children: [ - RemoteImage( - drama.posterUrl, - key: Key('home-feed-cover-${drama.id}'), - fit: BoxFit.cover, - showFallbackIcon: true, - fallbackColor: AppColors.contentSurface, - ), - if (badge != null) - Positioned( - top: AppDimens.spaceXs, - left: AppDimens.spaceXs, - child: _badgeChip(l10n, badge), + return ClipRRect( + key: Key('home-feed-cover-clip-${drama.id}'), + borderRadius: BorderRadius.circular(AppDimens.cardCoverRadius), + child: AspectRatio( + aspectRatio: AppDimens.cardCoverAspectRatio, + child: Stack( + fit: StackFit.expand, + children: [ + RemoteImage( + drama.posterUrl, + key: Key('home-feed-cover-${drama.id}'), + fit: BoxFit.cover, + showFallbackIcon: true, + fallbackColor: AppColors.contentSurface, ), - Positioned( - left: AppDimens.spaceXs, - bottom: AppDimens.spaceXs, - child: _views(), - ), - ], + if (badge != null) + Positioned( + top: AppDimens.spaceXs, + left: AppDimens.spaceXs, + child: _badgeChip(l10n, badge), + ), + Positioned( + top: 0, + right: 0, + child: DramaGenreRibbon(tags: _cardTags(), keyPrefix: drama.id), + ), + Positioned( + left: AppDimens.spaceXs, + bottom: AppDimens.spaceXs, + child: _views(), + ), + ], + ), ), ); } @@ -155,13 +163,13 @@ class HomeFeedCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon( - Icons.play_arrow_rounded, + Icons.auto_awesome_rounded, size: AppDimens.cardViewsIcon, color: AppColors.navSelected, ), const SizedBox(width: 1), Text( - formatInteractionCount(drama.viewCount), + formatPlayCount(drama.viewCount), style: const TextStyle( color: AppColors.navSelected, fontSize: AppDimens.cardViewsFont, @@ -174,23 +182,6 @@ class HomeFeedCard extends StatelessWidget { ); } - Widget _tags() { - final tags = _cardTags(); - if (tags.isEmpty) return const SizedBox.shrink(); - return Text( - tags.join(' | '), - key: Key('home-feed-tags-${drama.id}'), - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: const TextStyle( - color: AppColors.textTertiary, - fontSize: AppDimens.cardTagFont, - letterSpacing: 0, - ), - ); - } - List _cardTags() { final seen = {}; return [drama.genre, drama.category] diff --git a/lib/pages/home/widgets/home_grid_header.dart b/lib/pages/home/widgets/home_grid_header.dart index 76b3988..713336e 100644 --- a/lib/pages/home/widgets/home_grid_header.dart +++ b/lib/pages/home/widgets/home_grid_header.dart @@ -78,7 +78,11 @@ class HomeGridHeader extends StatelessWidget { key: const Key('home-grid-header'), crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, - children: [_searchRow(l10n), _primaryRow(l10n), _tagRow(l10n)], + children: [ + _searchRow(l10n), + _primaryRow(l10n), + if (selectedPrimary == HomePrimaryTab.featured) _tagRow(l10n), + ], ); } diff --git a/lib/pages/recommend/widgets/recommend_section_card.dart b/lib/pages/recommend/widgets/recommend_section_card.dart index 376bf4b..5178976 100644 --- a/lib/pages/recommend/widgets/recommend_section_card.dart +++ b/lib/pages/recommend/widgets/recommend_section_card.dart @@ -6,6 +6,7 @@ import '../../../core/data/models/drama.dart'; import '../../../core/formatting/count_format.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; +import '../../../core/widgets/drama_genre_ribbon.dart'; import '../../../core/widgets/remote_image.dart'; import '../../../l10n/app_localizations.dart'; import '../../home/widgets/home_drama_classification.dart'; @@ -31,7 +32,7 @@ class RecommendSectionCard extends StatelessWidget { width: AppDimens.recommendCardWidth, child: InkWell( key: Key('recommend-card-$sectionKey-${drama.id}'), - borderRadius: BorderRadius.circular(AppDimens.homeCardRadius), + borderRadius: BorderRadius.circular(AppDimens.cardCoverRadius), onTap: onTap, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -39,7 +40,7 @@ class RecommendSectionCard extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ ClipRRect( - borderRadius: BorderRadius.circular(AppDimens.homeCardRadius), + borderRadius: BorderRadius.circular(AppDimens.cardCoverRadius), child: AspectRatio( aspectRatio: AppDimens.cardCoverAspectRatio, child: Stack( @@ -77,6 +78,14 @@ class RecommendSectionCard extends StatelessWidget { ), ), ), + Positioned( + top: 0, + right: 0, + child: DramaGenreRibbon( + tags: _cardTags(), + keyPrefix: '$sectionKey-${drama.id}', + ), + ), ], ), ), @@ -88,12 +97,12 @@ class RecommendSectionCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, children: [ const Icon( - Icons.play_arrow_rounded, + Icons.auto_awesome_rounded, color: AppColors.textPrimary, size: AppDimens.cardViewsIcon, ), Text( - formatInteractionCount(drama.viewCount), + formatPlayCount(drama.viewCount), style: const TextStyle( color: AppColors.textPrimary, fontSize: AppDimens.cardViewsFont, @@ -114,31 +123,12 @@ class RecommendSectionCard extends StatelessWidget { height: AppDimens.cardTitleLineHeight, ), ), - if (_cardTags().isNotEmpty) ...[ - const SizedBox(height: AppDimens.cardTitleTagGap), - _tags(), - ], ], ), ), ); } - Widget _tags() { - final tags = _cardTags(); - return Text( - tags.join(' | '), - key: Key('recommend-tags-$sectionKey-${drama.id}'), - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: const TextStyle( - color: AppColors.textTertiary, - fontSize: AppDimens.cardTagFont, - ), - ); - } - List _cardTags() { final seen = {}; return [drama.genre, drama.category] diff --git a/test/core/count_format_test.dart b/test/core/count_format_test.dart index e80781b..46c3423 100644 --- a/test/core/count_format_test.dart +++ b/test/core/count_format_test.dart @@ -10,6 +10,13 @@ void main() { expect(formatInteractionCount(9999), '9999'); }); + test('should_format_play_count_with_w_and_trim_integer_decimals', () { + expect(formatPlayCount(8500), '8500'); + expect(formatPlayCount(10000), '1w'); + expect(formatPlayCount(500000), '50w'); + expect(formatPlayCount(444500), '44.5w'); + }); + test('should_use_one_decimal_wan_from_ten_thousand', () { expect(formatInteractionCount(10000), '1.0万'); expect(formatInteractionCount(12400), '1.2万'); diff --git a/test/following/following_page_test.dart b/test/following/following_page_test.dart index b5e3a81..a8a130f 100644 --- a/test/following/following_page_test.dart +++ b/test/following/following_page_test.dart @@ -68,6 +68,16 @@ void main() { find.byKey(const Key('following-cover-the-signal-demo')), ); expect(cover.aspectRatio, AppDimens.cardCoverAspectRatio); + final coverClip = tester.widget( + find.descendant( + of: find.byKey(const Key('following-cover-the-signal-demo')), + matching: find.byType(ClipRRect), + ), + ); + expect( + coverClip.borderRadius, + BorderRadius.circular(AppDimens.cardCoverRadius), + ); final title = tester.widget( find.descendant(of: card, matching: find.text('The Signal')), ); @@ -79,14 +89,24 @@ void main() { ); expect(views.style?.fontSize, AppDimens.cardViewsFont); expect(views.style?.color, AppColors.textPrimary); - final tags = tester.widget( - find.byKey(const Key('following-tags-the-signal-demo')), + expect( + find.descendant( + of: find.byKey(const Key('following-views-the-signal-demo')), + matching: find.byIcon(Icons.auto_awesome_rounded), + ), + findsOneWidget, ); - expect(tags.data, 'Suspense | Mystery'); - expect(tags.style?.fontSize, AppDimens.cardTagFont); - expect(tags.style?.color, AppColors.textTertiary); + final ribbon = find.byKey( + const Key('drama-genre-ribbon-the-signal-demo-0'), + ); + expect(ribbon, findsOneWidget); + final ribbonText = tester.widget( + find.descendant(of: ribbon, matching: find.byType(Text)), + ); + expect(ribbonText.data, 'Suspense'); + expect(ribbonText.style?.fontSize, AppDimens.cardBadgeFont); + expect(ribbonText.style?.color, AppColors.textPrimary); expect(tester.getTopLeft(title).dx, tester.getTopLeft(cover).dx); - expect(tester.getTopLeft(tags).dx, tester.getTopLeft(cover).dx); await tester.tap(find.byKey(const Key('following-edit'))); await tester.pumpAndSettle(); diff --git a/test/home/home_card_style_test.dart b/test/home/home_card_style_test.dart index 0c4c945..4a900dc 100644 --- a/test/home/home_card_style_test.dart +++ b/test/home/home_card_style_test.dart @@ -41,6 +41,13 @@ void main() { final cover = find.byKey(const Key('home-feed-cover-anime-card')); final coverSize = tester.getSize(cover); expect(coverSize.height / coverSize.width, closeTo(6 / 5, 0.02)); + final coverClip = tester.widget( + find.byKey(const Key('home-feed-cover-clip-anime-card')), + ); + expect( + coverClip.borderRadius, + BorderRadius.circular(AppDimens.cardCoverRadius), + ); final badge = find.byKey(const Key('home-feed-badge-anime-anime-card')); expect(badge, findsOneWidget); final badgeContainer = tester.widget(badge); @@ -61,9 +68,16 @@ void main() { final viewsText = tester.widget( find.descendant(of: views, matching: find.byType(Text)), ); - expect(viewsText.data, startsWith('44.')); + expect(viewsText.data, '44.5w'); expect(viewsText.style?.fontSize, AppDimens.cardViewsFont); expect(viewsText.style?.color, AppColors.navSelected); + expect( + find.descendant( + of: views, + matching: find.byIcon(Icons.auto_awesome_rounded), + ), + findsOneWidget, + ); final title = tester.widget( find.byKey(const Key('home-feed-title-anime-card')), ); @@ -71,14 +85,15 @@ void main() { expect(title.style?.fontSize, AppDimens.cardTitleFont); expect(title.style?.fontWeight, FontWeight.w500); expect(title.style?.height, AppDimens.cardTitleLineHeight); - final tags = tester.widget( - find.byKey(const Key('home-feed-tags-anime-card')), + final ribbon = find.byKey(const Key('drama-genre-ribbon-anime-card-0')); + expect(ribbon, findsOneWidget); + final ribbonText = tester.widget( + find.descendant(of: ribbon, matching: find.byType(Text)), ); - expect(tags.data, 'Romance | Urban'); - expect(tags.style?.fontSize, AppDimens.cardTagFont); - expect(tags.style?.color, AppColors.textTertiary); + expect(ribbonText.data, 'Romance'); + expect(ribbonText.style?.fontSize, AppDimens.cardBadgeFont); + expect(ribbonText.style?.color, AppColors.textPrimary); expect(tester.getTopLeft(title).dx, tester.getTopLeft(cover).dx); - expect(tester.getTopLeft(tags).dx, tester.getTopLeft(cover).dx); await tester.tap(card); expect(taps, 1); diff --git a/test/home/home_grid_layout_test.dart b/test/home/home_grid_layout_test.dart index 179a10b..38cb16b 100644 --- a/test/home/home_grid_layout_test.dart +++ b/test/home/home_grid_layout_test.dart @@ -108,6 +108,7 @@ void main() { await tester.tap(find.byKey(const Key('home-section-new'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('new-releases-page')), findsNothing); + expect(find.byKey(const Key('home-secondary-tags')), findsNothing); expect(firstDramaId(), 'page1-9'); await tester.tap(find.byKey(const Key('home-section-ranking'))); @@ -118,6 +119,7 @@ void main() { await tester.tap(find.byKey(const Key('home-section-categories'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('filter-page')), findsNothing); + expect(find.byKey(const Key('home-secondary-tags')), findsNothing); expect(find.byKey(const Key('home-grid-cards')), findsOneWidget); await tester.tap(find.byKey(const Key('home-section-category-古装'))); @@ -154,6 +156,7 @@ void main() { await tester.pumpAndSettle(); await tester.tap(find.byKey(const Key('home-section-featured'))); await tester.pumpAndSettle(); + expect(find.byKey(const Key('home-secondary-tags')), findsOneWidget); final afterScrollable = find .descendant( diff --git a/test/recommend/recommend_sections_test.dart b/test/recommend/recommend_sections_test.dart index 1527c04..d20b534 100644 --- a/test/recommend/recommend_sections_test.dart +++ b/test/recommend/recommend_sections_test.dart @@ -85,6 +85,13 @@ void main() { expect(moreText.style?.fontSize, AppDimens.recommendSectionMore); expect(moreText.style?.color, AppColors.textSecondary); final card = find.byKey(const Key('recommend-card-hits-the-signal-demo')); + final coverClip = tester.widget( + find.descendant(of: card, matching: find.byType(ClipRRect)), + ); + expect( + coverClip.borderRadius, + BorderRadius.circular(AppDimens.cardCoverRadius), + ); final cover = tester.widget( find.descendant(of: card, matching: find.byType(AspectRatio)), ); @@ -103,14 +110,22 @@ void main() { ); expect(views.style?.fontSize, AppDimens.cardViewsFont); expect(views.style?.color, AppColors.textPrimary); - final tags = tester.widget( - find.byKey(const Key('recommend-tags-hits-the-signal-demo')), + final viewIcon = find.descendant( + of: find.byKey(const Key('recommend-views-hits-the-signal-demo')), + matching: find.byIcon(Icons.auto_awesome_rounded), ); - expect(tags.data, 'Suspense | Mystery'); - expect(tags.style?.fontSize, AppDimens.cardTagFont); - expect(tags.style?.color, AppColors.textTertiary); + expect(viewIcon, findsOneWidget); + final ribbon = find.byKey( + const Key('drama-genre-ribbon-hits-the-signal-demo-0'), + ); + expect(ribbon, findsOneWidget); + final ribbonText = tester.widget( + find.descendant(of: ribbon, matching: find.byType(Text)), + ); + expect(ribbonText.data, 'Suspense'); + expect(ribbonText.style?.fontSize, AppDimens.cardBadgeFont); + expect(ribbonText.style?.color, AppColors.textPrimary); expect(tester.getTopLeft(cardTitle).dx, tester.getTopLeft(cover).dx); - expect(tester.getTopLeft(tags).dx, tester.getTopLeft(cover).dx); }); testWidgets('should_switch_inner_tabs_without_losing_grid_filter_state', (