2026-07-01 18:25:58 +08:00

695 lines
28 KiB
Dart

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<DynamicCommentPage> {
final RefreshController _refreshController = RefreshController(
initialRefresh: false,
);
int page = 1;
@override
void initState() {
super.initState();
_loadData();
}
@override
void dispose() {
Provider.of<ChatVibeDynamicContentManager>(context, listen: false).reset();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Consumer<ChatVibeDynamicContentManager>(
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<ChatVibeUserProfileManager>(
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<ChatVibeUserProfileManager>(
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<ChatVibeDynamicContentManager>(
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<ChatVibeDynamicContentManager>(
context,
listen: false,
).likeComment(
context,
res.dynamicId ?? "",
res.id ?? "",
res.rootCommentId ?? 0,
res.toUserId ?? "",
!(res.like ?? false),
false,
() {
setState(() {});
},
);
},
),
],
),
],
),
),
],
);
}
void _loadData() {
Provider.of<ChatVibeDynamicContentManager>(context, listen: false).dynamicListComment(
widget.dynamicId,
page,
(hasMore) {
setState(() {});
_refreshController.refreshCompleted();
_refreshController.loadComplete();
if (hasMore) {
_refreshController.loadNoData();
}
},
() {
setState(() {});
_refreshController.loadComplete();
_refreshController.loadFailed();
},
);
}
}