import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:aslan/app_localizations.dart'; import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart'; import 'package:aslan/chatvibe_ui/components/at_compontent.dart'; import 'package:aslan/chatvibe_core/utilities/at_dialog_utils.dart'; import 'package:aslan/chatvibe_data/sources/local/user_manager.dart'; import 'package:aslan/chatvibe_managers/user_profile_manager.dart'; import 'package:provider/provider.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:readmore/readmore.dart'; import 'package:aslan/chatvibe_ui/components/dialog/dialog_base.dart'; import 'package:aslan/chatvibe_ui/components/text/at_text.dart'; import 'package:aslan/chatvibe_ui/theme/chatvibe_theme.dart'; import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart'; import 'package:aslan/chatvibe_core/utilities/at_date_utils.dart'; import 'package:aslan/chatvibe_domain/models/res/at_comment_list_res.dart'; import 'package:aslan/chatvibe_managers/dynamic_content_manager.dart'; import 'package:aslan/chatvibe_features/index/main_route.dart'; class DynamicCommentPage extends StatefulWidget { String dynamicId = ""; String canGoUserInfo = ""; num commentQuantity = 0; Function(String? cId, String toUerId, num rootCommentId, String userName)? repayCall; Function(num count)? deleteCall; DynamicCommentPage( this.dynamicId, this.commentQuantity, this.canGoUserInfo, { this.repayCall, this.deleteCall, }); @override _DynamicCommentPageState createState() => _DynamicCommentPageState(); } class _DynamicCommentPageState extends State { final RefreshController _refreshController = RefreshController( initialRefresh: false, ); int page = 1; @override void initState() { super.initState(); _loadData(); } @override void dispose() { Provider.of(context, listen: false).reset(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Consumer( builder: (context, ref, child) { return SmartRefresher( enablePullDown: false, enablePullUp: true, controller: _refreshController, onLoading: () { page++; _loadData(); }, footer: CustomFooter( height: 1, builder: (context, mode) { return SizedBox( height: 1, width: 1, child: SizedBox(height: 1, width: 1), ); }, ), child: ref.subCommentList.isEmpty ? (ref.commentIsLoading ? Center(child: CupertinoActivityIndicator()) : mainEmpty(textColor: Colors.grey)) : ListView.separated( shrinkWrap: true, itemBuilder: (context, i) => buildItem(ref.subCommentList[i], ref), itemCount: ref.subCommentList.length, padding: EdgeInsets.symmetric(vertical: 15.w), separatorBuilder: (context, i) => builderDivider(), ), ); }, ), ); } Widget buildItem(CommentListRecords res, ChatVibeDynamicContentManager ref) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(width: 10.w), ATDebounceWidget( child: netImage( url: res.userAvatar ?? "", height: 35.w, width: 35.w, shape: BoxShape.circle, ), onTap: () { if (widget.canGoUserInfo == "true") { ATNavigatorUtils.push( context, "${MainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == res.userId}&tageId=${res.userId}", ); } }, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 用户昵称行 Row( children: [ SizedBox(width: 10.w), Expanded( child: text( res.userNickname ?? "", overflow: TextOverflow.ellipsis, fontSize: 14.sp, textColor: Colors.black, ), ), ATDebounceWidget( child: Container( padding: EdgeInsets.all(3.w), child: Icon( Icons.more_vert, color: Colors.grey, size: 15.w, ), ), onTap: () { ATDialogUtils.revealDynamicCommentOptDialog( context, reportCallback: res.userId != AccountStorage() .getCurrentUser() ?.userProfile ?.id ? () { ATNavigatorUtils.push( context, "${MainRoute.report}?type=dynamic&tageId=${res.dynamicId}", replace: false, ); } : null, deleteCallback: res.userId == AccountStorage() .getCurrentUser() ?.userProfile ?.id || (Provider.of( context, listen: false, ).userIdentity?.admin ?? false) ? () { SmartDialog.show( tag: "showConfirmDialog", alignment: Alignment.center, debounce: true, animationType: SmartAnimationType.fade, builder: (_) { return MsgDialog( title: ATAppLocalizations.of(context)!.tips, msg: ATAppLocalizations.of( context, )!.deleteCommentTips, btnText: ATAppLocalizations.of( context, )!.confirm, leftConfirm: true, isBtnBgFlip: true, onEnsure: () { ref.deleteComment( context, widget.dynamicId, res.id ?? "", widget.commentQuantity, true, () { setState(() {}); }, deleteCall: widget.deleteCall, ); }, ); }, ); } : null, ); }, ), ], ), // 评论内容行 Row( children: [ Expanded( child: Container( margin: EdgeInsetsDirectional.symmetric(horizontal: 10.w), child: ReadMoreText( res.content ?? "", trimLines: 3, trimMode: TrimMode.Line, style: TextStyle( fontFamily: "MyCustomFont", fontSize: 13.sp, color: Colors.black, fontWeight: FontWeight.w400, ), trimCollapsedText: ATAppLocalizations.of(context)!.showMore, trimExpandedText: ATAppLocalizations.of(context)!.showLess, moreStyle: TextStyle( color: ChatVibeTheme.primaryLight, fontFamily: "MyCustomFont", fontWeight: FontWeight.w600, ), lessStyle: TextStyle( color: ChatVibeTheme.primaryLight, fontFamily: "MyCustomFont", fontWeight: FontWeight.w600, ), ), ), ), ], ), SizedBox(height: 10.w), // 操作栏行 (时间、回复、点赞等) Row( children: [ SizedBox(width: 10.w), text( ATMDateUtils.formatMessageTime( context, DateTime.fromMillisecondsSinceEpoch(res.createTime ?? 0), ), textColor: Colors.grey, fontSize: 12.sp, ), SizedBox(width: 5.w), ATDebounceWidget( child: Container( child: text( ATAppLocalizations.of(context)!.reply, textColor: Color(0xff7726FF), fontSize: 12.sp, ), ), onTap: () { widget.repayCall?.call( res.id, res.userId ?? "", res.rootCommentId ?? 0, res.userNickname ?? "", ); }, ), Spacer(), ATDebounceWidget( child: Row( children: [ Image.asset( "atu_images/dynamic/at_icon_reply.png", height: 14.w, color: Colors.grey, ), text( "${res.childCommentCount ?? 0}", textColor: Colors.grey, fontSize: 12.sp, fontWeight: FontWeight.w400, ), ], ), onTap: () { ref.withdraw(res.rootCommentId ?? 0, () { setState(() {}); }); }, ), SizedBox(width: 10.w), ATDebounceWidget( child: Row( children: [ Image.asset( (res.like ?? false) ? "atu_images/dynamic/at_icon_like_red.png" : "atu_images/dynamic/at_icon_like.png", height: 14.w, color: (res.like ?? false) ? null : Colors.grey, ), text( res.likeStrQuantity ?? "0", textColor: Colors.grey, fontSize: 12.sp, fontWeight: FontWeight.w400, ), ], ), onTap: () { ref.likeComment( context, res.dynamicId ?? "", res.id ?? "", res.rootCommentId ?? 0, res.userId ?? "", !(res.like ?? false), true, () { setState(() {}); }, ); }, ), ], ), ref.childCommentListMap[res.rootCommentId ?? 0] != null && (ref .childCommentListMap[res.rootCommentId ?? 0] ?.length ?? 0) > 0 ? Container( margin: EdgeInsetsDirectional.only(top: 3.w, start: 10.w), // 添加顶部间距和左缩进 child: ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: ref .childCommentListMap[res.rootCommentId ?? 0] ?.length ?? 0, itemBuilder: (context, index) => buildChildItem( ref.childCommentListMap[res.rootCommentId ?? 0]![index], ), ), ) : Container(), if ((ref.childCommentListMap[res.rootCommentId ?? 0]?.length ?? 0) < (res.childCommentCount ?? 0)) ATDebounceWidget( child: Row( children: [ SizedBox(width: 10.w), text( "${(res.childCommentCount ?? 0) - (ref.childCommentListMap[res.rootCommentId ?? 0]?.length ?? 0)} ${ATAppLocalizations.of(context)!.itemsLeft}", textColor: Colors.grey, fontSize: 12.sp, ), Icon( Icons.keyboard_arrow_right_outlined, size: 14.w, color: Colors.grey, ), ], ), onTap: () { ref.dynamicListCommentChildren(res.rootCommentId ?? 0, () { setState(() {}); }); }, ), ], ), ), SizedBox(width: 10.w), ], ); } builderDivider() { return Divider(height: 22.w, thickness: 0.2.w, color: Colors.grey); } Widget buildChildItem(CommentListRecords res) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ ATDebounceWidget( child: netImage( url: res.userAvatar ?? "", height: 25.w, width: 25.w, shape: BoxShape.circle, ), onTap: () { if (widget.canGoUserInfo == "true") { ATNavigatorUtils.push( context, "${MainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == res.userId}&tageId=${res.userId}", ); } }, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ SizedBox(width: 10.w), Container( constraints: BoxConstraints(maxWidth: 120.w), child: text( res.userNickname ?? "", overflow: TextOverflow.ellipsis, fontSize: 11.sp, textColor: Colors.black, ), ), Spacer(), ATDebounceWidget( child: Container( padding: EdgeInsets.all(3.w), child: Icon( Icons.more_vert, color: Colors.grey, size: 13.w, ), ), onTap: () { ATDialogUtils.revealDynamicCommentOptDialog( context, reportCallback: res.userId != AccountStorage() .getCurrentUser() ?.userProfile ?.id ? () { ATNavigatorUtils.push( context, "${MainRoute.report}?type=dynamic&tageId=${res.dynamicId}", replace: false, ); } : null, deleteCallback: res.userId == AccountStorage() .getCurrentUser() ?.userProfile ?.id || (Provider.of( context, listen: false, ).userIdentity?.admin ?? false) ? () { SmartDialog.show( tag: "showConfirmDialog", alignment: Alignment.center, debounce: true, animationType: SmartAnimationType.fade, builder: (_) { return MsgDialog( title: ATAppLocalizations.of(context)!.tips, msg: ATAppLocalizations.of( context, )!.deleteCommentTips, leftConfirm: true, isBtnBgFlip: true, btnText: ATAppLocalizations.of( context, )!.confirm, onEnsure: () { Provider.of( context, listen: false, ).deleteComment( context, widget.dynamicId, res.id ?? "", widget.commentQuantity, false, () { page = 1; _loadData(); }, deleteCall: widget.deleteCall, ); }, ); }, ); } : null, ); }, ), ], ), Row( children: [ Expanded( child: Container( margin: EdgeInsetsDirectional.symmetric(horizontal: 10.w), child: res.replyCommentId == res.rootCommentId ? ReadMoreText( res.content ?? "", trimLines: 3, trimMode: TrimMode.Line, style: TextStyle( fontFamily: "MyCustomFont", fontSize: 11.sp, color: Colors.black, fontWeight: FontWeight.w400, ), trimCollapsedText: ATAppLocalizations.of(context)!.showMore, trimExpandedText: ATAppLocalizations.of(context)!.showLess, moreStyle: TextStyle( color: ChatVibeTheme.primaryLight, fontFamily: "MyCustomFont", fontWeight: FontWeight.w600, ), lessStyle: TextStyle( color: ChatVibeTheme.primaryLight, fontFamily: "MyCustomFont", fontWeight: FontWeight.w600, ), ) : Text.rich( strutStyle: StrutStyle( height: 1.0, // 行高倍数 fontWeight: FontWeight.w500, forceStrutHeight: true, // 强制应用行高 ), TextSpan( children: [ TextSpan( text: ATAppLocalizations.of(context)!.reply, style: TextStyle( fontSize: 11.sp, color: Colors.black, ), ), TextSpan( text: " ${res.toUserNickname} ", style: TextStyle( fontSize: 11.sp, color: Colors.black38, ), ), TextSpan( text: res.content, style: TextStyle( fontSize: 11.sp, color: Colors.black, ), ), ], ), ), ), ), ], ), SizedBox(height: 5.w), Row( children: [ SizedBox(width: 10.w), text( ATMDateUtils.formatMessageTime( context, DateTime.fromMillisecondsSinceEpoch(res.createTime ?? 0), ), textColor: Colors.grey, fontSize: 11.sp, ), SizedBox(width: 5.w), ATDebounceWidget( child: Container( child: text( ATAppLocalizations.of(context)!.reply, textColor: Color(0xff7726FF), fontSize: 11.sp, ), ), onTap: () { widget.repayCall?.call( res.id, res.userId ?? "", res.rootCommentId ?? 0, res.userNickname ?? "", ); }, ), Spacer(), SizedBox(width: 10.w), ATDebounceWidget( child: Row( children: [ Image.asset( (res.like ?? false) ? "atu_images/dynamic/at_icon_like_red.png" : "atu_images/dynamic/at_icon_like.png", height: 14.w, color: (res.like ?? false) ? null : Colors.grey, ), text( res.likeStrQuantity ?? "0", textColor: Colors.grey, fontSize: 11.sp, fontWeight: FontWeight.w400, ), ], ), onTap: () { Provider.of( context, listen: false, ).likeComment( context, res.dynamicId ?? "", res.id ?? "", res.rootCommentId ?? 0, res.toUserId ?? "", !(res.like ?? false), false, () { setState(() {}); }, ); }, ), ], ), ], ), ), ], ); } void _loadData() { Provider.of(context, listen: false).dynamicListComment( widget.dynamicId, page, (hasMore) { setState(() {}); _refreshController.refreshCompleted(); _refreshController.loadComplete(); if (hasMore) { _refreshController.loadNoData(); } }, () { setState(() {}); _refreshController.loadComplete(); _refreshController.loadFailed(); }, ); } }