merge: 合并 K30-C 评论面板视觉重做

This commit is contained in:
Zhou Weidong committed 2026-10-20 12:11:48 +08:00
commit edcd25fe68
4 files changed
+89 -28

No files matched your search

+3
View File
@@ -55,6 +55,9 @@ abstract final class AppColors {
static const raised = Color(0xFFFFF1E5); static const raised = Color(0xFFFFF1E5);
static const quick = Color(0xFFFFF0E1); static const quick = Color(0xFFFFF0E1);
static const input = Color(0xFFFFF4EA); static const input = Color(0xFFFFF4EA);
/// 评论输入框底色。
static const commentInput = Color(0xFFF5EFE8);
static const goldCard = Color(0xFFFFF4DF); static const goldCard = Color(0xFFFFF4DF);
/// 正文颜色。 /// 正文颜色。
+30 -10
View File
@@ -51,12 +51,12 @@ class CommentTile extends StatelessWidget {
: comment.nickname; : comment.nickname;
return Padding( return Padding(
key: Key('comment-item-${comment.id}'), key: Key('comment-item-${comment.id}'),
padding: const EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 12),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_avatar(), _avatar(),
const SizedBox(width: 12), const SizedBox(width: 10),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -67,8 +67,9 @@ class CommentTile extends StatelessWidget {
child: Text( child: Text(
name, name,
style: const TextStyle( style: const TextStyle(
color: AppColors.muted, color: AppColors.cream,
fontSize: 12, fontSize: 13,
fontWeight: FontWeight.w700,
), ),
), ),
), ),
@@ -77,7 +78,7 @@ class CommentTile extends StatelessWidget {
formatLocalizedDateTime(context, comment.createdAt!), formatLocalizedDateTime(context, comment.createdAt!),
style: const TextStyle( style: const TextStyle(
color: AppColors.subtle, color: AppColors.subtle,
fontSize: 10, fontSize: 11,
), ),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
@@ -109,8 +110,8 @@ class CommentTile extends StatelessWidget {
comment.content, comment.content,
style: const TextStyle( style: const TextStyle(
color: AppColors.cream, color: AppColors.cream,
fontSize: 13, fontSize: 14,
height: 1.2, height: 1.4,
), ),
), ),
if (comment.isPending) if (comment.isPending)
@@ -129,6 +130,12 @@ class CommentTile extends StatelessWidget {
children: [ children: [
TextButton.icon( TextButton.icon(
key: Key('comment-like-${comment.id}'), key: Key('comment-like-${comment.id}'),
style: TextButton.styleFrom(
foregroundColor: AppColors.muted,
padding: const EdgeInsets.symmetric(horizontal: 4),
minimumSize: const Size(0, 28),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: controller.likingComment(comment.id) onPressed: controller.likingComment(comment.id)
? null ? null
: () => handlers.onLike(comment), : () => handlers.onLike(comment),
@@ -138,11 +145,24 @@ class CommentTile extends StatelessWidget {
: Icons.favorite_border_rounded, : Icons.favorite_border_rounded,
size: 16, size: 16,
), ),
label: Text('${comment.likeCount}'), label: Text(
'${comment.likeCount}',
style: const TextStyle(fontSize: 11),
),
), ),
if (!isReply) if (!isReply)
TextButton( TextButton(
key: Key('comment-reply-${comment.id}'), key: Key('comment-reply-${comment.id}'),
style: TextButton.styleFrom(
foregroundColor: AppColors.blue,
textStyle: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
),
padding: const EdgeInsets.symmetric(horizontal: 4),
minimumSize: const Size(0, 28),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: () => handlers.onReply(comment), onPressed: () => handlers.onReply(comment),
child: Text(l10n.reply), child: Text(l10n.reply),
), ),
@@ -157,14 +177,14 @@ class CommentTile extends StatelessWidget {
} }
Widget _avatar() { Widget _avatar() {
final size = isReply ? 22.0 : 28.0; final size = isReply ? 24.0 : 32.0;
if (comment.avatarUrl.isEmpty) { if (comment.avatarUrl.isEmpty) {
return CircleAvatar( return CircleAvatar(
radius: size / 2, radius: size / 2,
backgroundColor: AppColors.raised, backgroundColor: AppColors.raised,
child: Icon( child: Icon(
Icons.person_rounded, Icons.person_rounded,
size: isReply ? 13 : 16, size: isReply ? 14 : 18,
color: AppColors.cream, color: AppColors.cream,
), ),
); );
@@ -22,9 +22,9 @@ import 'comment_tile.dart';
const double _minSheetHeight = 280; const double _minSheetHeight = 280;
const double _maxSheetHeight = 520; const double _maxSheetHeight = 520;
const int _maxCommentLength = 300; const int _maxCommentLength = 300;
const double _composerRadius = 20; const double _composerRadius = 22;
const double _composerHeight = 40; const double _composerHeight = 44;
const double _sendButtonSize = 32; const double _sendButtonSize = 36;
const double _sheetRadius = 20; const double _sheetRadius = 20;
/// 服务端评论底部弹窗:匿名列表、游标翻页、回复、点赞和本人删除。 /// 服务端评论底部弹窗:匿名列表、游标翻页、回复、点赞和本人删除。
@@ -195,6 +195,18 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Center(
child: Container(
key: const Key('player-comments-drag-handle'),
width: 36,
height: 4,
decoration: BoxDecoration(
color: AppColors.border,
borderRadius: BorderRadius.circular(999),
),
),
),
const SizedBox(height: 8),
Row( Row(
children: [ children: [
Expanded( Expanded(
@@ -203,8 +215,8 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
key: count == null ? null : const Key('comment-count-label'), key: count == null ? null : const Key('comment-count-label'),
style: const TextStyle( style: const TextStyle(
color: AppColors.onSurface, color: AppColors.onSurface,
fontSize: 18, fontSize: 15,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w700,
), ),
), ),
), ),
@@ -212,7 +224,8 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
key: const Key('player-comments-close'), key: const Key('player-comments-close'),
tooltip: l10n.close, tooltip: l10n.close,
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
icon: const Icon(Icons.close_rounded), visualDensity: VisualDensity.compact,
icon: const Icon(Icons.close_rounded, size: 20),
), ),
], ],
), ),
@@ -326,11 +339,11 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
); );
return InputDecoration( return InputDecoration(
hintText: hint, hintText: hint,
hintStyle: const TextStyle(color: AppColors.muted, fontSize: 13), hintStyle: const TextStyle(color: AppColors.muted, fontSize: 14),
counterText: '', counterText: '',
filled: true, filled: true,
fillColor: AppColors.raised, fillColor: AppColors.commentInput,
contentPadding: const EdgeInsets.symmetric(horizontal: 12), contentPadding: const EdgeInsets.symmetric(horizontal: 14),
isDense: true, isDense: true,
border: clear, border: clear,
enabledBorder: clear, enabledBorder: clear,
@@ -349,7 +362,8 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
focusNode: _inputFocus, focusNode: _inputFocus,
maxLength: _maxCommentLength, maxLength: _maxCommentLength,
maxLines: 1, maxLines: 1,
style: const TextStyle(color: AppColors.cream, fontSize: 13), textAlignVertical: TextAlignVertical.center,
style: const TextStyle(color: AppColors.cream, fontSize: 14),
cursorColor: AppColors.blue, cursorColor: AppColors.blue,
decoration: _composerDecoration(l10n.writeComment), decoration: _composerDecoration(l10n.writeComment),
onSubmitted: (_) => _post(), onSubmitted: (_) => _post(),
@@ -402,10 +416,20 @@ class _CommentThread extends StatelessWidget {
), ),
if (comment.replyCount > 0 || replies.isNotEmpty) if (comment.replyCount > 0 || replies.isNotEmpty)
Padding( Padding(
padding: const EdgeInsets.only(left: 44, bottom: 8), padding: const EdgeInsets.only(left: 42, bottom: 4),
child: TextButton( child: TextButton(
key: Key('comment-replies-${comment.id}'), key: Key('comment-replies-${comment.id}'),
onPressed: () => _toggleReplies(context), onPressed: () => _toggleReplies(context),
style: TextButton.styleFrom(
foregroundColor: AppColors.blue,
textStyle: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
),
padding: const EdgeInsets.symmetric(horizontal: 4),
minimumSize: const Size(0, 28),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text( child: Text(
expanded expanded
? AppLocalizations.of(context)!.hideReplies ? AppLocalizations.of(context)!.hideReplies
@@ -440,7 +464,10 @@ class _CommentThread extends StatelessWidget {
], ],
), ),
), ),
const Divider(height: 1, color: AppColors.outlineVariantDark), const Padding(
padding: EdgeInsets.only(left: 42),
child: Divider(height: 1, color: AppColors.border),
),
], ],
); );
} }
+17 -6
View File
@@ -129,7 +129,7 @@ void main() {
expect(tester.widget<TextField>(input).focusNode?.hasFocus, isFalse); expect(tester.widget<TextField>(input).focusNode?.hasFocus, isFalse);
}); });
testWidgets('should_use_compact_comment_sizes', (tester) async { testWidgets('should_use_polished_comment_sizes', (tester) async {
final repository = FakeCommentRepository( final repository = FakeCommentRepository(
pages: [ pages: [
CommentPage( CommentPage(
@@ -142,19 +142,30 @@ void main() {
expect( expect(
tester.getSize(find.byKey(const Key('comment-post'))), tester.getSize(find.byKey(const Key('comment-post'))),
const Size(32, 32), const Size(36, 36),
);
expect(tester.getSize(find.byKey(const Key('comment-input'))).height, 44);
expect(
find.byKey(const Key('player-comments-drag-handle')),
findsOneWidget,
); );
expect(tester.getSize(find.byKey(const Key('comment-input'))).height, 40);
final avatar = tester.widget<CircleAvatar>( final avatar = tester.widget<CircleAvatar>(
find.descendant( find.descendant(
of: find.byKey(const Key('comment-item-10')), of: find.byKey(const Key('comment-item-10')),
matching: find.byType(CircleAvatar), matching: find.byType(CircleAvatar),
), ),
); );
expect(avatar.radius, 14); expect(avatar.radius, 16);
final body = tester.widget<Text>(find.text('Great episode')); final body = tester.widget<Text>(find.text('Great episode'));
expect(body.style?.fontSize, 13); expect(body.style?.fontSize, 14);
expect(body.style?.height, 1.2); expect(body.style?.height, 1.4);
expect(
tester
.widget<TextField>(find.byKey(const Key('comment-input')))
.decoration
?.fillColor,
AppColors.commentInput,
);
}); });
testWidgets('should_show_review_badge_and_server_replaced_content', ( testWidgets('should_show_review_badge_and_server_replaced_content', (