I am trying to implement a comment and reply feature under 1 level. Just like every other social media apps with comments and reply. I am having problem in laying out comments reply. I created a listview builder for getting the parent comments of a post. Each comments have its own ID (commentId). I am finding it difficult to show the replies of each comments accordingly under it's parents comment.
What i am trying to do:
I get user comment from api and show it on the UI. under the comment, I want to show the replies of every comment.
This is what i have tried:
Comment page for showing the comment using getx state management
class CommentWidget extends StatelessWidget {
CommentWidget({Key? key, required this.postId}) : super(key: key);
final String postId;
final isShowReply = false.obs;
@override
Widget build(BuildContext context) {
return GetBuilder<CommentPaginationController>(
init: CommentPaginationController(
pId: postId,
),
builder: (controller) {
return controller.isFetchingComment.value
? Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 200,
child: LinearProgressIndicator(
backgroundColor: AppColors.backgroundColor,
valueColor: AlwaysStoppedAnimation<Color?>(
AppColors.secondaryColor,
),
),
),
)
: controller.commentsModel.isNotEmpty
? ListView.builder(
// reverse: true,
controller: controller.scrollController,
shrinkWrap: true,
itemCount: controller.commentsModel.length + 1,
itemBuilder: (context, index) {
if (index < controller.commentsModel.length) {
final comment = controller.commentsModel[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Build comment widget
const SizedBox(height: 10.0),
CommentHeaderWidget(
commentsModel: comment,
headerPadding: const EdgeInsets.fromLTRB(
14.0, 0.0, 14.0, 0.0),
radius: 26.0,
iconSize: 22,
headerSize: 14,
),
// Build reply widget
controller.commentsModel[index].nrComments != 0
? ReplyWidget(commentsModel: comment)
: const SizedBox()
],
);
} else if (controller.isLoadingMore.value == true) {
return const Center(
child: LoadingAnimation(
height: 16.0,
width: 16.0,
),
);
} else {
return const SizedBox();
}
},
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
NoUPdateWidget(
title: 'No comments yet',
content:
'Be the first to add a comment on this post.',
action: Icon(
FluentIcons.comment_off_24_regular,
size: 50.0,
color: AppColors.secondaryColor,
),
),
],
),
);
},
);
}
}
State management code for getting comment details from api
class CommentPaginationController extends GetxController {
CommentPaginationController({required this.pId});
final String pId;
final _postService = UserPostService();
final scrollController = ScrollController();
List<GetCommentsModel> commentsModel = [];
RxBool isLoadingMore = false.obs;
RxBool hasMoreItems = true.obs;
RxBool isFetchingComment = false.obs;
RxInt offset = 0.obs;
RxInt maxCount = 12.obs;
Future<void> loadInitialItem() async {
isFetchingComment.value = true;
try {
final value = await _postService.getComments(
GetCommentsModel(
pId: pId,
offset: offset.value,
maxCount: maxCount.value,
),
);
isFetchingComment.value = false;
if (value.isNotEmpty) {
offset.value++;
commentsModel = value;
isFetchingComment.value = false;
}
} catch (e) {
isFetchingComment.value = false;
}
update();
}
Future<void> loadMore() async {
if (hasMoreItems.value == true &&
isFetchingComment.value == false &&
isLoadingMore.value == false) {
isLoadingMore.value = true;
try {
final posts = await _postService.getComments(
GetCommentsModel(
pId: pId, offset: offset.value, maxCount: maxCount.value),
);
if (posts.isNotEmpty) {
offset.value++;
commentsModel.addAll(posts);
} else {
hasMoreItems.value = false;
}
} catch (e) {
isLoadingMore.value = false;
}
isLoadingMore.value = false;
}
update();
}
@override
void onInit() {
loadInitialItem();
scrollController.addListener(() {
if (scrollController.position.minScrollExtent ==
scrollController.offset) {
loadMore();
}
});
super.onInit();
}
@override
void onClose() {
scrollController.removeListener(() {});
super.onClose();
}
}
I can successfully get the comments and it's details using pagination. I am wondering how to get the reply of the comments and display them under their parent comments.