feat(flutter): 接入互动评论点赞举报
This commit is contained in:
1 parent
45f5f25640
commit
d361034226
39 files changed
+3298
-462
No files matched your search
@@ -0,0 +1,149 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/data/models/comment.dart';
|
||||
import '../../../core/data/services/comment_controller.dart';
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
|
||||
const String _deleteAction = 'delete';
|
||||
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;
|
||||
}
|
||||
|
||||
/// 单条评论或回复的展示与操作行。
|
||||
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;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final name = comment.nickname.isEmpty ? l10n.anonymousUser : comment.nickname;
|
||||
return Padding(
|
||||
key: Key('comment-item-${comment.id}'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: isReply ? 12 : 16,
|
||||
backgroundColor: AppColors.blue.withValues(alpha: 0.2),
|
||||
child: Icon(
|
||||
Icons.person_rounded,
|
||||
size: isReply ? 14 : 18,
|
||||
color: AppColors.blueSoft,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
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)
|
||||
PopupMenuItem(
|
||||
value: _deleteAction,
|
||||
child: Text(l10n.deleteComment),
|
||||
)
|
||||
else
|
||||
PopupMenuItem(
|
||||
value: _reportAction,
|
||||
child: Text(l10n.reportComment),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
comment.content,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||||
),
|
||||
if (comment.isPending)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
l10n.underReview,
|
||||
key: Key('comment-pending-${comment.id}'),
|
||||
style: const TextStyle(
|
||||
color: AppColors.blueSoft,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
TextButton.icon(
|
||||
key: Key('comment-like-${comment.id}'),
|
||||
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}'),
|
||||
),
|
||||
if (!isReply)
|
||||
TextButton(
|
||||
key: Key('comment-reply-${comment.id}'),
|
||||
onPressed: () => handlers.onReply(comment),
|
||||
child: Text(l10n.reply),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user