| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- import 'package:common_utils/common_utils.dart';
- import 'package:easy_refresh/easy_refresh.dart';
- import 'package:flutter/cupertino.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:news_app/main.dart';
- import 'package:news_app/model/new_comment_model.dart';
- import 'package:news_app/model/user_model.dart';
- import 'package:news_app/util/keyboard_util.dart';
- import 'package:news_app/util/log.util.dart';
- import 'package:news_app/widget/empty_2_widget.dart';
- import '../../provider/common_provider.dart';
- import 'comment_input_bar_widget.dart';
- import 'comment_item_widget.dart';
- /// @author: bo.zeng
- /// @email: cnhbwds@gmail.com
- /// @date: 2025 2025/4/17 11:15
- /// @description:
- enum CommentType { video, topic, activity, news, activityVideo }
- final commentProvider =
- NotifierProvider.family<CommentNotifier, NewCommentModel, CommentType>(
- () => CommentNotifier(),
- );
- final keyboardProvider = StateProvider<bool>((ref) => false);
- class CommentPage extends ConsumerStatefulWidget {
- final CommentType type;
- final String articleId;
- const CommentPage({super.key, required this.type, required this.articleId});
- @override
- ConsumerState<ConsumerStatefulWidget> createState() => _CommentPageSate();
- }
- class _CommentPageSate extends ConsumerState<CommentPage>
- with WidgetsBindingObserver {
- final FocusNode _focusNode = FocusNode();
- int _pageSize = 1;
- @override
- void initState() {
- super.initState();
- final notifier = ref.read(commentProvider(widget.type).notifier);
- WidgetsBinding.instance.addObserver(this);
- notifier.fetchComment(page: _pageSize, articleId: widget.articleId);
- ref.listenManual(commentProvider(widget.type), (previous, next) {
- _currentTotal = next.total ?? 0;
- });
- }
- @override
- void didChangeMetrics() {
- super.didChangeMetrics();
- Future.delayed(Duration(milliseconds: 500), () {
- if (!mounted) return;
- final bottomInset = View.of(context).viewInsets.bottom;
- if (bottomInset > 0) {
- ref.read(keyboardProvider.notifier).state = true;
- } else {
- ref.read(keyboardProvider.notifier).state = false;
- _focusNode.unfocus();
- }
- });
- }
- @override
- void dispose() {
- super.dispose();
- WidgetsBinding.instance.removeObserver(this);
- if (KeyboardUtils.isKeyboardVisible(_focusNode)) {
- KeyboardUtils.hideKeyboard(_focusNode);
- }
- _focusNode.dispose();
- }
- int commentIndex = 0;
- String replyName = '';
- void replyComment(int index, String reply) {
- KeyboardUtils.showKeyboard(context, _focusNode);
- consoleLog("index:$index reply:$reply");
- commentIndex = index;
- replyName = reply;
- }
- void longTapAction(int index) {
- showCupertinoDialog(
- context: context,
- builder:
- (context) => CupertinoAlertDialog(
- title: const Text("举报该评论"),
- content: const Text("您确定要执行此操作吗?"),
- actions: [
- CupertinoDialogAction(
- child: const Text("取消"),
- onPressed: () => Navigator.pop(context),
- ),
- CupertinoDialogAction(
- isDestructiveAction: true, // 红色警示按钮
- child: const Text("确定"),
- onPressed: () {
- reportComment(index);
- Navigator.pop(context);
- // 执行删除操作
- },
- ),
- ],
- ),
- );
- }
- void reportComment(int index) async {
- final comments = ref.watch(commentProvider(widget.type));
- final model = comments.records![index];
- consoleLog(
- "${model.fromUser?.memberId},${model.commentId},${widget.type.toString()}",
- );
- KeyboardUtils.hideKeyboard(_focusNode);
- final notifier = ref.read(commentProvider(widget.type).notifier);
- var typeStr = "article";
- if (widget.type == CommentType.activity) {
- typeStr = "activity";
- } else if (widget.type == CommentType.video) {
- typeStr = "video";
- } else if (widget.type == CommentType.topic) {
- typeStr = "topic";
- }
- await notifier.reportComment(typeStr, model.contentId ?? '');
- _pageSize = 1;
- notifier.fetchComment(page: _pageSize, articleId: widget.articleId);
- }
- void sendComment(String content, List<String> images) {
- KeyboardUtils.hideKeyboard(_focusNode);
- consoleLog("replyName:$replyName content:$content images:$images");
- UserModel user = ref.read(globalUserProvider);
- final notifier = ref.read(commentProvider(widget.type).notifier);
- if (replyName.isEmpty) {
- //新增评论
- notifier.addComment(
- widget.articleId,
- Comment(
- fromUser: FromUser(
- memberId: "1",
- nickname: user.nickName,
- avatar: user.avatar,
- ),
- content: content,
- createTime: DateUtil.getNowDateStr(),
- resourceUrls: images.isNotEmpty ? images : null,
- ),
- );
- } else {
- //回复评论
- SubComment subComment = SubComment(
- fromUser: FromUser(
- memberId: "", //当前户Id
- nickname: user.nickName,
- avatar: user.avatar,
- ),
- content: content,
- createTime: DateUtil.getNowDateStr(),
- );
- notifier.addReply(widget.articleId, commentIndex, subComment);
- replyName = '';
- commentIndex = 0;
- }
- }
- int _currentTotal = 0;
- int _getItemLength(NewCommentModel comments) {
- int length =
- (comments.records != null && comments.records!.isNotEmpty)
- ? comments.records!.length
- : 0;
- return length;
- }
- @override
- Widget build(BuildContext context) {
- final comments = ref.watch(commentProvider(widget.type));
- double bottomSize =
- ref.watch(keyboardProvider) ? KeyboardUtils.keyboardHeight(context) : 0;
- return Stack(
- children: [
- comments.records?.isEmpty == true
- ? Empty2widget()
- : EasyRefresh.builder(
- onRefresh: () async {
- return IndicatorResult.none;
- },
- onLoad: () async {
- final newData = ref.read(commentProvider(widget.type));
- int total = newData.total ?? 0;
- if (_currentTotal >= total) {
- return IndicatorResult.noMore;
- } else {
- _pageSize += 1;
- await ref
- .read(commentProvider(widget.type).notifier)
- .fetchComment(
- page: _pageSize,
- articleId: widget.articleId,
- );
- return IndicatorResult.success;
- }
- },
- header: const NotRefreshHeader(), // 空的 header
- childBuilder: (context, physics) {
- return ListView.separated(
- physics: physics,
- itemCount: _getItemLength(comments),
- padding: EdgeInsets.only(bottom: 120.h),
- itemBuilder: (context, index) {
- final comment = comments.records;
- if (comment == null || index >= comment.length) {
- return const SizedBox.shrink(); // 防止越界构建
- }
- return CommentItemWidget(
- replyComment,
- longTapAction,
- comment: comments.records![index],
- commentIndex: index,
- );
- },
- separatorBuilder: (_, __) => SizedBox(height: 20.h),
- );
- },
- ),
- Positioned(
- bottom: bottomSize,
- left: 0,
- right: 0,
- child: CommentInputBarWidget(
- _focusNode,
- sendComment,
- widget.articleId,
- showImageUpload: widget.type == CommentType.topic, // 仅指定话题显示图片上传
- ),
- ),
- ],
- );
- }
- }
|