This commit is contained in:
commit
525f58c150
7 files changed
+29
-10
No files matched your search
@@ -27,6 +27,9 @@ abstract final class AppColors {
|
||||
static const overlaySecondary = Color(0xFFC7C7CC);
|
||||
static const overlayLabel = Color(0xFFE6E6EB);
|
||||
|
||||
/// 首页及剧集播放页视频信息文案:参考设计图的 65% 半透明白。
|
||||
static const homeFeedVideoCopy = Color(0xA6FFFFFF);
|
||||
|
||||
/// 主操作、选中态、播放进度。旧品牌橙已全量映射为品牌红(2026-10 改版)。
|
||||
static const blue = Color(0xFFF04E4E);
|
||||
static const primary = blue;
|
||||
|
||||
@@ -12,7 +12,6 @@ const double _synopsisToggleWidthFraction = 0.55;
|
||||
const double _synopsisToggleGap = 6;
|
||||
const _synopsisMotion = Duration(milliseconds: 240);
|
||||
const _synopsisStyle = TextStyle(
|
||||
color: AppColors.overlaySecondary,
|
||||
fontSize: _synopsisFont,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: _synopsisLineHeight,
|
||||
@@ -32,6 +31,7 @@ class ExpandableSynopsis extends StatefulWidget {
|
||||
required this.synopsis,
|
||||
this.keyPrefix = 'home-feed',
|
||||
this.expandedFooter,
|
||||
this.textColor = AppColors.homeFeedVideoCopy,
|
||||
});
|
||||
|
||||
/// 按当前语言获取的简介正文。
|
||||
@@ -43,6 +43,9 @@ class ExpandableSynopsis extends StatefulWidget {
|
||||
/// 展开后附加的声明等内容。
|
||||
final Widget? expandedFooter;
|
||||
|
||||
/// 简介正文颜色;默认使用视频信息区统一的半透明浅灰白。
|
||||
final Color textColor;
|
||||
|
||||
@override
|
||||
State<ExpandableSynopsis> createState() => _ExpandableSynopsisState();
|
||||
}
|
||||
@@ -88,7 +91,7 @@ class _ExpandableSynopsisState extends State<ExpandableSynopsis> {
|
||||
}
|
||||
|
||||
bool _needsToggle(double maxWidth) {
|
||||
final painter = _painter(widget.synopsis, _synopsisStyle);
|
||||
final painter = _painter(widget.synopsis, _bodyStyle);
|
||||
painter.layout(maxWidth: maxWidth);
|
||||
final overflows = painter.didExceedMaxLines;
|
||||
painter.dispose();
|
||||
@@ -120,11 +123,14 @@ class _ExpandableSynopsisState extends State<ExpandableSynopsis> {
|
||||
|
||||
Key _key(String suffix) => Key('${widget.keyPrefix}-synopsis-$suffix');
|
||||
|
||||
TextStyle get _bodyStyle => _synopsisStyle.copyWith(color: widget.textColor);
|
||||
|
||||
Widget _body() {
|
||||
final style = _bodyStyle;
|
||||
final text = Text.rich(
|
||||
TextSpan(text: widget.synopsis, style: _synopsisStyle),
|
||||
TextSpan(text: widget.synopsis, style: style),
|
||||
key: _expanded ? _key('expanded') : Key('${widget.keyPrefix}-synopsis'),
|
||||
style: _synopsisStyle,
|
||||
style: style,
|
||||
maxLines: _expanded ? null : _collapsedSynopsisLines,
|
||||
overflow: _expanded ? TextOverflow.clip : TextOverflow.ellipsis,
|
||||
);
|
||||
|
||||
@@ -101,7 +101,7 @@ class _TagChip extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
strutStyle: _metadataStrutStyle,
|
||||
style: const TextStyle(
|
||||
color: AppColors.overlaySecondary,
|
||||
color: AppColors.homeFeedVideoCopy,
|
||||
fontSize: _tagFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: _metadataLineHeight,
|
||||
|
||||
@@ -103,6 +103,7 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
|
||||
ExpandableSynopsis(
|
||||
key: ValueKey(widget.drama.id),
|
||||
synopsis: synopsis,
|
||||
textColor: AppColors.homeFeedVideoCopy,
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
@@ -136,7 +136,7 @@ void _expectExpandedSynopsis(WidgetTester tester) {
|
||||
final expanded = find.byKey(const Key('home-feed-synopsis-expanded'));
|
||||
expect(
|
||||
tester.widget<Text>(expanded).textSpan?.style?.color,
|
||||
AppColors.overlaySecondary,
|
||||
AppColors.homeFeedVideoCopy,
|
||||
);
|
||||
_expectNoShadows(tester);
|
||||
_expectWatchGap(tester);
|
||||
@@ -187,7 +187,7 @@ void main() {
|
||||
matching: find.byType(Text),
|
||||
),
|
||||
);
|
||||
expect(tag.style?.color, AppColors.overlaySecondary);
|
||||
expect(tag.style?.color, AppColors.homeFeedVideoCopy);
|
||||
});
|
||||
|
||||
testWidgets('should_skip_motion_when_system_disables_animations', (
|
||||
@@ -343,7 +343,7 @@ void main() {
|
||||
final synopsis = tester.widget<Text>(
|
||||
find.byKey(const Key('home-feed-synopsis')),
|
||||
);
|
||||
expect(synopsis.style?.color, AppColors.overlaySecondary);
|
||||
expect(synopsis.style?.color, AppColors.homeFeedVideoCopy);
|
||||
expect(synopsis.style?.fontSize, 15);
|
||||
expect(synopsis.maxLines, 2);
|
||||
final episode = tester.widget<Text>(
|
||||
@@ -353,7 +353,7 @@ void main() {
|
||||
expect(episode.style?.fontSize, 14);
|
||||
expect(episode.data, 'Episode 2 / 24');
|
||||
final tag = tester.widget<Text>(find.text('Romance'));
|
||||
expect(tag.style?.color, AppColors.overlaySecondary);
|
||||
expect(tag.style?.color, AppColors.homeFeedVideoCopy);
|
||||
expect(tag.style?.color, synopsis.style?.color);
|
||||
expect(tag.style?.fontSize, 13);
|
||||
final hotSearch = tester.widget<Text>(
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// 职责:验证共用简介的短文案、展开声明、内容更新与减少动画行为。
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:fruitshorts/core/theme/app_colors.dart';
|
||||
import 'package:fruitshorts/core/theme/app_theme.dart';
|
||||
import 'package:fruitshorts/l10n/app_localizations.dart';
|
||||
import 'package:fruitshorts/pages/player/widgets/expandable_synopsis.dart';
|
||||
@@ -54,6 +55,14 @@ Future<void> _pump(
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('should_use_video_copy_color_when_player_does_not_override', (
|
||||
tester,
|
||||
) async {
|
||||
await _pump(tester, synopsis: _shortCopy);
|
||||
final synopsis = tester.widget<Text>(find.byKey(_collapsed));
|
||||
expect(synopsis.style?.color, AppColors.homeFeedVideoCopy);
|
||||
});
|
||||
|
||||
testWidgets('should_hide_toggle_when_synopsis_fits_two_lines', (
|
||||
tester,
|
||||
) async {
|
||||
|
||||
@@ -1517,7 +1517,7 @@ void main() {
|
||||
final style = line.style ?? const TextStyle();
|
||||
expect(style.fontSize, 15);
|
||||
expect(style.fontWeight, FontWeight.w400);
|
||||
expect(style.color, AppColors.overlaySecondary);
|
||||
expect(style.color, AppColors.homeFeedVideoCopy);
|
||||
expect(style.shadows ?? <Shadow>[], isEmpty);
|
||||
expect(line.textSpan!.toPlainText(), isNot(startsWith('Episode ')));
|
||||
expect(line.textSpan!.toPlainText(), isNot(contains(' | ')));
|
||||
|
||||
Reference in new issue
Block a user