diff --git a/lib/enums/post_kind.dart b/lib/enums/post_kind.dart new file mode 100644 index 0000000..bb5ecb3 --- /dev/null +++ b/lib/enums/post_kind.dart @@ -0,0 +1,14 @@ +/// Different kinds of posts +/// +/// @author Pierre HUBERT + +enum PostKind { + TEXT, + IMAGE, + WEB_LINK, + PDF, + MOVIE, + COUNTDOWN, + SURVEY, + YOUTUBE +} diff --git a/lib/enums/post_visibility_level.dart b/lib/enums/post_visibility_level.dart new file mode 100644 index 0000000..e122ac3 --- /dev/null +++ b/lib/enums/post_visibility_level.dart @@ -0,0 +1,5 @@ +/// Post visibility level +/// +/// @author Pierre HUBERT + +enum PostVisibilityLevel { PUBLIC, FRIENDS, USER, GROUP_MEMBERS } diff --git a/lib/enums/user_access_levels.dart b/lib/enums/user_access_levels.dart new file mode 100644 index 0000000..90235e9 --- /dev/null +++ b/lib/enums/user_access_levels.dart @@ -0,0 +1,5 @@ +/// User access levels +/// +/// @author Pierre HUBERT + +enum UserAccessLevels { NONE, BASIC, INTERMEDIATE, FULL} \ No newline at end of file diff --git a/lib/helpers/posts_helper.dart b/lib/helpers/posts_helper.dart new file mode 100644 index 0000000..f209443 --- /dev/null +++ b/lib/helpers/posts_helper.dart @@ -0,0 +1,82 @@ +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/posts_list.dart'; +import 'package:comunic/models/api_request.dart'; +import 'package:comunic/models/post.dart'; + +/// Posts helper +/// +/// @author Pierre HUBERT + +const _APIPostsVisibilityLevelMap = { + "public": PostVisibilityLevel.PUBLIC, + "friends": PostVisibilityLevel.FRIENDS, + "private": PostVisibilityLevel.USER, + "members": PostVisibilityLevel.GROUP_MEMBERS +}; + +const _APIPostsKindsMap = { + "text": PostKind.TEXT, + "image": PostKind.IMAGE, + "weblink": PostKind.WEB_LINK, + "pdf": PostKind.PDF, + "movie": PostKind.MOVIE, + "countdown": PostKind.COUNTDOWN, + "survey": PostKind.SURVEY, + "youtube": PostKind.YOUTUBE +}; + +const _APIUserAccessMap = { + "no-access": UserAccessLevels.NONE, + "basic": UserAccessLevels.BASIC, + "intermediate": UserAccessLevels.INTERMEDIATE, + "full": UserAccessLevels.FULL +}; + +class PostsHelper { + /// Get the list of latest posts. Return the list of posts or null in case of + /// failure + Future getLatest() async { + final response = await APIRequest( + uri: "posts/get_latest", + needLogin: true, + ).exec(); + + if (response.code != 200) return null; + + try { + // Parse & return the list of posts + return PostsList()..addAll(response.getArray().map((f) => _apiToPost(f))); + } catch (e) { + print(e.toString()); + return null; + } + } + + /// Turn an API entry into a [Post] object + Post _apiToPost(Map map) { + return Post( + id: map["ID"], + userID: map["userID"], + userPageID: map["user_page_id"], + groupID: map["group_id"], + timeSent: map["post_time"], + content: map["content"], + visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]], + kind: _APIPostsKindsMap[map["kind"]], + fileSize: map["file_size"], + fileType: map["file_type"], + filePath: map["file_path"], + fileURL: map["file_path_url"], + timeEnd: map["time_end"], + linkURL: map["link_url"], + linkTitle: map["link_title"], + linkDescription: map["link_description"], + linkImage: map["link_image"], + likes: map["likes"], + userLikes: map["userlike"], + access: _APIUserAccessMap[map["user_access"]], + ); + } +} diff --git a/lib/helpers/users_helper.dart b/lib/helpers/users_helper.dart index ac93705..fa6524c 100644 --- a/lib/helpers/users_helper.dart +++ b/lib/helpers/users_helper.dart @@ -51,6 +51,12 @@ class UsersHelper { return list; } + /// Get users information from a given [Set] + Future getList(Set users, + {bool forceDownload = false}) async { + return await getUsersInfo(users.toList()); + } + /// Get users information /// /// If [forceDownload] is set to true, the data will always be retrieved from diff --git a/lib/lists/posts_list.dart b/lib/lists/posts_list.dart new file mode 100644 index 0000000..44f9146 --- /dev/null +++ b/lib/lists/posts_list.dart @@ -0,0 +1,39 @@ +import 'dart:collection'; + +import 'package:comunic/models/post.dart'; + +/// Posts List +/// +/// Contains method to easily process a list of posts +/// +/// @author Pierre HUBERT + +class PostsList extends ListBase { + + List _list = List(); + + int get length => _list.length; + + set length(int l) => _list.length = l; + + @override + Post operator [](int index) => _list[index]; + + @override + void operator []=(int index, Post value) => _list[index] = value; + + // Get the list of users ID in this set + Set get usersID { + Set set = Set(); + + forEach((p) { + set.add(p.userID); + + if(p.userPageID != null && p.userPageID > 0) + set.add(p.userPageID); + }); + + return set; + } + +} \ No newline at end of file diff --git a/lib/models/post.dart b/lib/models/post.dart new file mode 100644 index 0000000..1fd356f --- /dev/null +++ b/lib/models/post.dart @@ -0,0 +1,64 @@ +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:meta/meta.dart'; + +/// Single post information +/// +/// @author Pierre HUBERT + +class Post { + final int id; + final int userID; + final int userPageID; + final int groupID; + final int timeSent; + final String content; + final PostVisibilityLevel visibilityLevel; + final PostKind kind; + final int fileSize; + final String fileType; + final String filePath; + final String fileURL; + final int timeEnd; + final String linkURL; + final String linkTitle; + final String linkDescription; + final String linkImage; + final int likes; + final bool userLikes; + final UserAccessLevels access; + + Post({ + @required this.id, + @required this.userID, + @required this.userPageID, + @required this.groupID, + @required this.timeSent, + @required this.content, + @required this.visibilityLevel, + @required this.kind, + @required this.fileSize, + @required this.fileType, + @required this.filePath, + @required this.fileURL, + @required this.timeEnd, + @required this.linkURL, + @required this.linkTitle, + @required this.linkDescription, + @required this.linkImage, + @required this.likes, + @required this.userLikes, + @required this.access, + }) : assert(id != null), + assert(userID != null), + assert(userPageID != 0 || groupID != 0), + assert(timeSent != null), + assert(kind != PostKind.TEXT || content != null), + assert(visibilityLevel != null), + assert(kind != null), + assert(kind != PostKind.COUNTDOWN || timeEnd != null), + assert(likes != null), + assert(userLikes != null), + assert(access != null); +} diff --git a/lib/ui/screens/newest_posts.dart b/lib/ui/screens/newest_posts.dart index bab2a7e..c790857 100644 --- a/lib/ui/screens/newest_posts.dart +++ b/lib/ui/screens/newest_posts.dart @@ -1,3 +1,10 @@ +import 'package:comunic/helpers/posts_helper.dart'; +import 'package:comunic/helpers/users_helper.dart'; +import 'package:comunic/lists/posts_list.dart'; +import 'package:comunic/lists/users_list.dart'; +import 'package:comunic/ui/screens/conversation_screen.dart'; +import 'package:comunic/ui/tiles/post_tile.dart'; +import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; @@ -11,10 +18,59 @@ class NewestPostsScreen extends StatefulWidget { } class _NewestPostsScreenState extends State { + // Helpers + final PostsHelper _postsHelper = PostsHelper(); + final UsersHelper _usersHelper = UsersHelper(); + + // Class members + PostsList _list; + UsersList _users; + ErrorLevel _error = ErrorLevel.NONE; + + set error(ErrorLevel err) => setState(() => _error = err); + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _loadPostsList(); + } + + void _loadError() => + error = _list == null ? ErrorLevel.MAJOR : ErrorLevel.MINOR; + + Future _loadPostsList() async { + final list = await _postsHelper.getLatest(); + + if (list == null) return _loadError(); + + final users = await _usersHelper.getList(list.usersID); + + if (users == null) return _loadError(); + + setState(() { + _list = list; + _users = users; + }); + } + + Widget _buildErrorCard() { + return buildErrorCard(tr("Could not get the list of posts !")); + } + + Widget _buildListView() { + return ListView.builder( + itemCount: _list.length, + itemBuilder: (c, i) => PostTile( + post: _list[i], + usersInfo: _users, + ), + ); + } @override Widget build(BuildContext context) { - return buildCenteredProgressBar(); + if (_error == ErrorLevel.MAJOR) return _buildErrorCard(); + if (_list == null) return buildCenteredProgressBar(); + return _buildListView(); } - -} \ No newline at end of file +} diff --git a/lib/ui/tiles/post_tile.dart b/lib/ui/tiles/post_tile.dart new file mode 100644 index 0000000..dfebf21 --- /dev/null +++ b/lib/ui/tiles/post_tile.dart @@ -0,0 +1,27 @@ +import 'package:comunic/lists/users_list.dart'; +import 'package:comunic/models/post.dart'; +import 'package:flutter/material.dart'; + +/// Single posts tile +/// +/// @author Pierre HUBERT + +class PostTile extends StatelessWidget { + final Post post; + final UsersList usersInfo; + + const PostTile({ + Key key, + @required this.post, + @required this.usersInfo, + }) : assert(post != null), + assert(usersInfo != null), + super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Text("a post"), + ); + } +}