diff --git a/lib/helpers/comments_helper.dart b/lib/helpers/comments_helper.dart new file mode 100644 index 0000000..135a13c --- /dev/null +++ b/lib/helpers/comments_helper.dart @@ -0,0 +1,21 @@ +import 'package:comunic/models/comment.dart'; + +/// Comments helper +/// +/// @author Pierre HUBERT + +class CommentsHelper { + /// Turn an API entry into a [Comment] object + static Comment apiToComment(Map entry) { + return Comment( + id: entry["ID"], + userID: entry["userID"], + postID: entry["postID"], + timeSent: entry["time_sent"], + content: entry["content"], + imageURL: entry["img_url"], + likes: entry["likes"], + userLike: entry["userlike"], + ); + } +} diff --git a/lib/helpers/posts_helper.dart b/lib/helpers/posts_helper.dart index f209443..94e482d 100644 --- a/lib/helpers/posts_helper.dart +++ b/lib/helpers/posts_helper.dart @@ -1,6 +1,8 @@ import 'package:comunic/enums/post_kind.dart'; import 'package:comunic/enums/post_visibility_level.dart'; import 'package:comunic/enums/user_access_levels.dart'; +import 'package:comunic/helpers/comments_helper.dart'; +import 'package:comunic/lists/comments_list.dart'; import 'package:comunic/lists/posts_list.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/post.dart'; @@ -56,6 +58,14 @@ class PostsHelper { /// Turn an API entry into a [Post] object Post _apiToPost(Map map) { + // Parse comments + CommentsList comments; + if (map["comments"] != null) { + comments = CommentsList(); + map["comments"] + .forEach((v) => comments.add(CommentsHelper.apiToComment(v))); + } + return Post( id: map["ID"], userID: map["userID"], @@ -77,6 +87,7 @@ class PostsHelper { likes: map["likes"], userLikes: map["userlike"], access: _APIUserAccessMap[map["user_access"]], + comments: comments, ); } } diff --git a/lib/lists/comments_list.dart b/lib/lists/comments_list.dart new file mode 100644 index 0000000..7351e69 --- /dev/null +++ b/lib/lists/comments_list.dart @@ -0,0 +1,26 @@ +import 'dart:collection'; + +import 'package:comunic/models/comment.dart'; + +/// Comments list +/// +/// Contains the list of comments for a post +/// +/// @author Pierre HUBERT + +class CommentsList extends ListBase { + List _list = List(); + + int get length => _list.length; + + set length(int l) => _list.length = l; + + @override + Comment operator [](int index) => _list[index]; + + @override + void operator []=(int index, Comment value) => _list[index] = value; + + /// Get the list of users in this comments, as a set + Set get usersID => map((f) => f.userID).toSet(); +} diff --git a/lib/lists/posts_list.dart b/lib/lists/posts_list.dart index 44f9146..9275533 100644 --- a/lib/lists/posts_list.dart +++ b/lib/lists/posts_list.dart @@ -31,6 +31,9 @@ class PostsList extends ListBase { if(p.userPageID != null && p.userPageID > 0) set.add(p.userPageID); + + if(p.comments != null) + set.addAll(p.comments.usersID); }); return set; diff --git a/lib/models/comment.dart b/lib/models/comment.dart new file mode 100644 index 0000000..acfd733 --- /dev/null +++ b/lib/models/comment.dart @@ -0,0 +1,39 @@ +import 'package:meta/meta.dart'; + +/// Comments +/// +/// Contains information about a single comment +/// +/// @author Pierre HUBERT + +class Comment { + final int id; + final int userID; + final int postID; + final int timeSent; + final String content; + final String imageURL; + final int likes; + final bool userLike; + + Comment({ + @required this.id, + @required this.userID, + @required this.postID, + @required this.timeSent, + @required this.content, + @required this.imageURL, + @required this.likes, + @required this.userLike, + }) : assert(id != null), + assert(userID != null), + assert(postID != null), + assert(timeSent != null), + assert(content != null), + assert(likes != null), + assert(userLike != null); + + bool get hasContent => content != null && content.length > 0; + + bool get hasImage => imageURL != null; +} diff --git a/lib/models/post.dart b/lib/models/post.dart index c2cc30e..8afc0fd 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -1,6 +1,7 @@ import 'package:comunic/enums/post_kind.dart'; import 'package:comunic/enums/post_visibility_level.dart'; import 'package:comunic/enums/user_access_levels.dart'; +import 'package:comunic/lists/comments_list.dart'; import 'package:meta/meta.dart'; /// Single post information @@ -28,6 +29,7 @@ class Post { int likes; bool userLikes; final UserAccessLevels access; + final CommentsList comments; Post({ @required this.id, @@ -50,6 +52,7 @@ class Post { @required this.likes, @required this.userLikes, @required this.access, + @required this.comments }) : assert(id != null), assert(userID != null), assert(userPageID != 0 || groupID != 0), @@ -63,4 +66,6 @@ class Post { assert(access != null); bool get hasContent => content != null; + + bool get hasComments => comments != null; } diff --git a/lib/ui/tiles/comment_tile.dart b/lib/ui/tiles/comment_tile.dart new file mode 100644 index 0000000..42f6511 --- /dev/null +++ b/lib/ui/tiles/comment_tile.dart @@ -0,0 +1,53 @@ +import 'package:comunic/models/comment.dart'; +import 'package:comunic/models/user.dart'; +import 'package:comunic/ui/widgets/account_image_widget.dart'; +import 'package:comunic/ui/widgets/network_image_widget.dart'; +import 'package:flutter/material.dart'; + +/// Single comment tile +/// +/// @author Pierre HUBERT + +class CommentTile extends StatelessWidget { + final Comment comment; + final User user; + + const CommentTile({Key key, this.comment, this.user}) + : assert(comment != null), + assert(user != null), + super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: AccountImageWidget( + user: user, + ), + title: Text(user.displayName,), + subtitle: _buildCommentContent(), + ); + } + + Widget _buildCommentContent() { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Comment image + Container( + child: comment.hasImage + ? NetworkImageWidget( + url: comment.imageURL, + allowFullScreen: true, + height: 100.0, + ) + : null, + ), + + // Comment text + Container( + child: comment.hasContent ? Text(comment.content,) : null, + ), + ], + ); + } +} diff --git a/lib/ui/tiles/post_tile.dart b/lib/ui/tiles/post_tile.dart index d3ef695..4f7a2bb 100644 --- a/lib/ui/tiles/post_tile.dart +++ b/lib/ui/tiles/post_tile.dart @@ -2,6 +2,7 @@ import 'package:comunic/enums/post_kind.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/post.dart'; import 'package:comunic/models/user.dart'; +import 'package:comunic/ui/tiles/comment_tile.dart'; import 'package:comunic/ui/widgets/account_image_widget.dart'; import 'package:comunic/ui/widgets/network_image_widget.dart'; import 'package:comunic/utils/date_utils.dart'; @@ -124,17 +125,23 @@ class PostTile extends StatelessWidget { Widget build(BuildContext context) { return Card( elevation: 1.0, - child: Padding( - padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + _buildHeaderRow(), + _buildContentRow(), + _buildButtonsArea(), + ], + ), + ), - // Main post column - child: Column( - children: [ - _buildHeaderRow(), - _buildContentRow(), - _buildButtonsArea(), - ], - ), + Container( + child: post.hasComments ? _buildComments() : null, + ), + ], ), ); } @@ -146,4 +153,27 @@ class PostTile extends StatelessWidget { roundedEdges: false, ); } + + /// Build the list of comments + Widget _buildComments() { + assert(post.hasComments); + + final comments = List.generate( + post.comments.length, + (num) => CommentTile( + comment: post.comments[num], + user: usersInfo.getUser(post.comments[num].userID), + ), + ); + + return Container( + color: Colors.grey[300], + child: Padding( + padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), + child: Column( + children: comments, + ), + ), + ); + } }