fix(player): 评论面板按参考图重做

This commit is contained in:
Zhou Weidong committed 2026-10-21 11:52:59 +08:00
1 parent bdd3a53632
commit 7862e0be09
3 files changed
+273 -244

No files matched your search

+77 -81
View File
@@ -3,7 +3,6 @@
import 'package:flutter/material.dart';
import '../../../core/data/models/comment.dart';
import '../../../core/data/services/comment_controller.dart';
import '../../../core/formatting/localized_date_time.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_dimens.dart';
@@ -17,13 +16,11 @@ const String _reportAction = 'report';
class CommentInteractionHandlers {
const CommentInteractionHandlers({
required this.onReply,
required this.onLike,
required this.onDelete,
required this.onReport,
});
final ValueChanged<DramaComment> onReply;
final Future<void> Function(DramaComment) onLike;
final Future<void> Function(DramaComment) onDelete;
final Future<void> Function(DramaComment) onReport;
}
@@ -33,13 +30,11 @@ class CommentTile extends StatelessWidget {
const CommentTile({
super.key,
required this.comment,
required this.controller,
required this.handlers,
this.isReply = false,
});
final DramaComment comment;
final CommentController controller;
final CommentInteractionHandlers handlers;
final bool isReply;
@@ -51,66 +46,68 @@ class CommentTile extends StatelessWidget {
: comment.nickname;
return Padding(
key: Key('comment-item-${comment.id}'),
padding: const EdgeInsets.symmetric(vertical: 12),
padding: const EdgeInsets.only(top: 12, bottom: 14),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_avatar(),
const SizedBox(width: 10),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
name,
style: const TextStyle(
color: AppColors.cream,
fontSize: 13,
fontWeight: FontWeight.w700,
color: AppColors.muted,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
if (comment.createdAt != null)
Text(
formatLocalizedDateTime(context, comment.createdAt!),
style: const TextStyle(
SizedBox.square(
dimension: 28,
child: PopupMenuButton<String>(
key: Key('comment-menu-${comment.id}'),
tooltip: l10n.more,
padding: EdgeInsets.zero,
iconSize: 18,
icon: const Icon(
Icons.more_horiz_rounded,
color: AppColors.subtle,
fontSize: 11,
),
),
const SizedBox(width: 4),
PopupMenuButton<String>(
key: Key('comment-menu-${comment.id}'),
tooltip: l10n.more,
onSelected: (value) {
if (value == _deleteAction) {
handlers.onDelete(comment);
} else if (value == _reportAction) {
handlers.onReport(comment);
}
},
itemBuilder: (_) => [
if (comment.mine)
onSelected: (value) {
if (value == _deleteAction) {
handlers.onDelete(comment);
} else if (value == _reportAction) {
handlers.onReport(comment);
}
},
itemBuilder: (_) => [
if (comment.mine)
PopupMenuItem(
value: _deleteAction,
child: Text(l10n.deleteComment),
),
PopupMenuItem(
value: _deleteAction,
child: Text(l10n.deleteComment),
value: _reportAction,
child: Text(l10n.reportComment),
),
PopupMenuItem(
value: _reportAction,
child: Text(l10n.reportComment),
),
],
],
),
),
],
),
const SizedBox(height: 2),
Text(
comment.content,
style: const TextStyle(
color: AppColors.cream,
fontSize: 14,
fontSize: 16,
height: 1.4,
),
),
@@ -126,48 +123,11 @@ class CommentTile extends StatelessWidget {
),
),
),
Row(
children: [
TextButton.icon(
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)
? null
: () => handlers.onLike(comment),
icon: Icon(
comment.liked
? Icons.favorite_rounded
: Icons.favorite_border_rounded,
size: 16,
),
label: Text(
'${comment.likeCount}',
style: const TextStyle(fontSize: 11),
),
),
if (!isReply)
TextButton(
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),
child: Text(l10n.reply),
),
],
),
if (comment.createdAt != null || !isReply)
Padding(
padding: const EdgeInsets.only(top: 6),
child: _metadata(context, l10n),
),
],
),
),
@@ -177,14 +137,14 @@ class CommentTile extends StatelessWidget {
}
Widget _avatar() {
final size = isReply ? 24.0 : 32.0;
final size = isReply ? 28.0 : 40.0;
if (comment.avatarUrl.isEmpty) {
return CircleAvatar(
radius: size / 2,
backgroundColor: AppColors.raised,
child: Icon(
Icons.person_rounded,
size: isReply ? 14 : 18,
size: isReply ? 16 : 22,
color: AppColors.cream,
),
);
@@ -197,4 +157,40 @@ class CommentTile extends StatelessWidget {
),
);
}
Widget _metadata(BuildContext context, AppLocalizations l10n) {
final createdAt = comment.createdAt;
return Row(
children: [
if (createdAt != null)
Text(
formatLocalizedDateTime(context, createdAt),
style: const TextStyle(color: AppColors.subtle, fontSize: 12),
),
if (createdAt != null && !isReply) ...[
const SizedBox(width: 8),
const Text(
'·',
style: TextStyle(color: AppColors.muted, fontSize: 12),
),
const SizedBox(width: 8),
],
if (!isReply)
TextButton(
key: Key('comment-reply-${comment.id}'),
style: TextButton.styleFrom(
foregroundColor: AppColors.muted,
padding: EdgeInsets.zero,
minimumSize: const Size(0, 24),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: () => handlers.onReply(comment),
child: Text(
l10n.reply,
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
),
],
);
}
}