Home > Mobile >  Flutter - Sort Comment Replies under their parent comment
Flutter - Sort Comment Replies under their parent comment

Time:05-03

I'm trying to sort all of my comments so that the replies will be threaded under their parent comment, going from oldest to newest in both the original comment along with their replies.

Comments will have an id, a date, and an optional parentId.

Parent Comments will not have a parentId, whereas the replies will have a parentId that is the id of their parent comment.

I'm getting my data from Firebase and adding it to a List.

From that List, I am separating out the comments that contain a parentId and those that do not.

final commentsWithoutParentID = comments
    .where(
        (c) => c.parentId.isEmpty,
    ).toList();

final commentsWithParentID = comments
   .where(
       (c) => c.parentId.isNotEmpty,
   ).toList();

I then sort these as:

// Sort comments with no parent id by date
commentsWithoutParentID.sort((a, b) => a.date!.compareTo(b.date!));

// Sort comments with a parentId by date
commentsWithParentID.sort((a, b) => a.date!.compareTo(b.date!));

// Sort comments with a parentId by comparing the various parentId
commentsWithParentID.sort((a, b) => a.parentId.compareTo(b.parentId));

After this I add these two Lists to an empty List:

sortedComments = commentsWithoutParentID   commentsWithParentID;

I then sort this to compare the parentId to the id:

sortedComments.sort((a, b) => a.parentId.compareTo(b.id));

The result I am getting is that all of the comments are sorted by date from oldest at the top to newest at the bottom and some of the replies get threaded under the incorrect parent comment.

So it seems that the date is taking a higher priority possibly.

I've altered these sorts but I either get the same result as I am getting now or something that is further from my desired result.

CodePudding user response:

When you call sort after other sort, you break previous.

Consider group method (dart:collection dependency is required). Or you can use temporary map to group children.

import 'package:collection/collection.dart';

class Comment {
  final String date;
  final int id;

  Comment(this.date, this.id);

  @override
  String toString() => "($date, $id)";
}

class ThreadComment extends Comment {
  final int parentId;

  ThreadComment(String date, int id, this.parentId) : super(date, id);

  @override
  String toString() => "(parentId: $parentId, $date, $id)";
}

    final threadComments = [
      ThreadComment("day1", 1, 1),
      ThreadComment("day2", 4, 1),
      ThreadComment("day2", 3, 3),
      ThreadComment("day1", 2, 3),
    ];
    final parentComments = [
      Comment("day3", 5),
      Comment("day1", 1),
      Comment("day2", 3),
      Comment("day1", 2),
      Comment("day3", 4),
    ];
    
int compare(v1, v2) => v1.date.compareTo(v2.date);
final comments = <Comment, List<ThreadComment>>{};

// group comments by parent id
for (final Comment c
        in parentComments.sorted((a, b) => a.id.compareTo(b.id))) {
      comments[c] = threadComments
          .where((element) => element.parentId == c.id)
// sort children by date
          .sorted(compare);
    }
// sort parents by date
final sortedMap = comments.keys
        .toList()
        .sorted(compare)
        .asMap()
        .map((_, v) => MapEntry(v, comments[v]));

//expand map to one list
final sortedList = <List<Comment>>[
      for (final parent in sortedMap.keys) [parent, ...?sortedMap[parent]]
    ].expand((element) => element).toList();

sortedList.forEach((element) => print("$element\n"));

// (day1, 1)
// (parentId: 1, day1, 1)
// (parentId: 1, day2, 4)
// (day1, 2)
// (day2, 3)
// (parentId: 3, day1, 2)
// (parentId: 3, day2, 3)
// (day3, 4)
// (day3, 5)
  • Related