Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSoC - Adding / Removing || Adding comment #903

6 changes: 5 additions & 1 deletion lib/locator.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:get_it/get_it.dart';
import 'package:talawa/main.dart';
import 'package:talawa/services/comment_service.dart';
import 'package:talawa/services/database_mutation_functions.dart';
import 'package:talawa/services/event_service.dart';
import 'package:talawa/services/graphql_config.dart';
Expand All @@ -19,6 +20,7 @@ import 'package:talawa/view_model/pre_auth_view_models/select_organization_view_
import 'package:talawa/view_model/pre_auth_view_models/set_url_view_model.dart';
import 'package:talawa/view_model/pre_auth_view_models/signup_details_view_model.dart';
import 'package:talawa/view_model/pre_auth_view_models/waiting_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/comments_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/custom_drawer_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/like_button_view_model.dart';
import 'package:talawa/view_model/widgets_view_models/progress_dialog_view_model.dart';
Expand All @@ -41,9 +43,10 @@ void setupLocator() {
//userConfig
locator.registerSingleton(UserConfig());

//Services
locator.registerLazySingleton(() => PostService());

locator.registerLazySingleton(() => EventService());
locator.registerLazySingleton(() => CommentService());

//graphql
locator.registerSingleton(GraphqlConfig());
Expand Down Expand Up @@ -74,4 +77,5 @@ void setupLocator() {
locator.registerFactory(() => ProgressDialogViewModel());
locator.registerFactory(() => CustomDrawerViewModel());
locator.registerFactory(() => LikeButtonViewModel());
locator.registerFactory(() => CommentsViewModel());
}
32 changes: 32 additions & 0 deletions lib/services/comment_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:talawa/locator.dart';
import 'package:talawa/services/database_mutation_functions.dart';
import 'package:talawa/utils/comment_queries.dart';

class CommentService {
CommentService() {
_dbFunctions = locator<DataBaseMutationFunctions>();
}
late DataBaseMutationFunctions _dbFunctions;

Future<void> createComments(String postId, String text) async {
print("comment service called");
final String _createCommentQuery = CommentQueries().createComment();
final result =
await _dbFunctions.gqlAuthMutation(_createCommentQuery, variables: {
'postId': postId, //Add your variables here
'text': text
});
print("comment added");
print(result);
return result;
}

Future getCommentsForPost(String postId) async {
final String _getCommmentQuery = CommentQueries().getPostsComments(postId);
final result = await _dbFunctions.gqlAuthMutation(_getCommmentQuery);
if (result.data != null) {
return result.data["commentsByPost"] as List;
}
return [];
}
}
76 changes: 69 additions & 7 deletions lib/services/post_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,36 @@ import 'package:talawa/utils/post_queries.dart';
class PostService {
PostService() {
_postStream = _postStreamController.stream.asBroadcastStream();
_updatedPostStream =
_updatedPostStreamController.stream.asBroadcastStream();
_currentOrg = _userConfig.currentOrg;
setOrgStreamSubscription();
}
// Stream for entire posts
final StreamController<List<Post>> _postStreamController =
StreamController<List<Post>>();
late Stream<List<Post>> _postStream;

//Stream for individul post update
final StreamController<Post> _updatedPostStreamController =
StreamController<Post>();
late Stream<Post> _updatedPostStream;

final StreamController<Post> _postStreamController = StreamController<Post>();
late Stream<Post> _postStream;
final _userConfig = locator<UserConfig>();
final _dbFunctions = locator<DataBaseMutationFunctions>();
late OrgInfo _currentOrg;
final Set<String> _renderedPostID = {};
// ignore: prefer_final_fields
List<Post> _posts = [];

//Getters
Stream<Post> get postStream => _postStream;
Stream<List<Post>> get postStream => _postStream;
Stream<Post> get updatedPostStream => _updatedPostStream;

//Setters
void setOrgStreamSubscription() {
_userConfig.currentOrfInfoStream.listen((updatedOrganization) {
_renderedPostID.clear();
_currentOrg = updatedOrganization;
});
}
Expand All @@ -42,16 +56,64 @@ class PostService {
if (result.data!['postsByOrganization'] == null) return;

final List postsJson = result.data!['postsByOrganization'] as List;

final List<Post> _newPosts = [];
postsJson.forEach((postJson) {
final Post post = Post.fromJson(postJson as Map<String, dynamic>);
_postStreamController.add(post);
if (!_renderedPostID.contains(post.sId)) {
_newPosts.add(post);
_renderedPostID.add(post.sId);
}
});
_postStreamController.add(_newPosts);
_posts = _newPosts;
}

Future<void> addLike(String postID) {
// --- Functions related to Likes --- //
Future<void> addLike(String postID) async {
_localAddLike(postID);
final String mutation = PostQueries().addLike();
final result =
_dbFunctions.gqlAuthMutation(mutation, variables: {"postID": postID});
final result = await _dbFunctions
.gqlAuthMutation(mutation, variables: {"postID": postID});
print(result);
return result;
}

void _localAddLike(String postID) {
_posts.forEach((post) {
if (post.sId == postID) {
post.likedBy!.add(LikedBy(sId: _userConfig.currentUser.id));
_updatedPostStreamController.add(post);
}
});
}

Future<void> removeLike(String postID) async {
_removeLocal(postID);
final String mutation = PostQueries().removeLike();
final result = await _dbFunctions
.gqlAuthMutation(mutation, variables: {"postID": postID});
print(result);
return result;
}

void _removeLocal(String postID) {
_posts.forEach((post) {
if (post.sId == postID) {
post.likedBy!.removeWhere(
(likeUser) => likeUser.sId == _userConfig.currentUser.id);
_updatedPostStreamController.add(post);
}
});
}

// --- Functions related to comments --- //
void addCommentLocally(String postID) {
for (int i = 0; i < _posts.length; i++) {
if (_posts[i].sId == postID) {
_posts[i].comments!.add(Comments(sId: postID));
_updatedPostStreamController.add(_posts[i]);
}
}
}
}
31 changes: 31 additions & 0 deletions lib/utils/comment_queries.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class CommentQueries {
String createComment() {
return """
mutation createComment(\$postId: ID!, \$text: String!) {
createComment(postId: \$postId,
data:{
text: \$text,
}
){
_id
}
}
""";
}

String getPostsComments(String postId) {
return """
query{
commentsByPost(id: "$postId"){
_id
text
createdAt
creator{
firstName
lastName
}
}
}
""";
}
}
14 changes: 14 additions & 0 deletions lib/utils/post_queries.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,18 @@ class PostQueries {
}
""";
}

String removeLike() {
return """
mutation unlikePost(\$postID: ID!) {
unlikePost( id: \$postID,)
{
_id
likedBy{
_id
}
}
}
""";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import 'package:talawa/view_model/base_view_model.dart';

class OrganizationFeedViewModel extends BaseModel {
// Local caching variables for a session.
final List<Post> _posts = [], _pinnedPosts = [];
// ignore: prefer_final_fields
List<Post> _posts = [], _pinnedPosts = [];
final Set<String> _renderedPostID = {};
late String _currentOrgname = "";

Expand All @@ -22,6 +23,7 @@ class OrganizationFeedViewModel extends BaseModel {
// Stream variables
late StreamSubscription _currentOrganizationStreamSubscription;
late StreamSubscription _postsSubscription;
late StreamSubscription _updatePostSubscription;

// Getters
List<Post> get posts => _posts;
Expand All @@ -44,15 +46,18 @@ class OrganizationFeedViewModel extends BaseModel {
void initialise() {
// For caching/initalizing the current organization after the stream subsciption has canceled and the stream is updated
_currentOrgname = _userConfig.currentOrg.name!;

_postService.getPosts();
// ------
// Attasching the stream subscription to rebuild the widgets automatically
_currentOrganizationStreamSubscription = _userConfig.currentOrfInfoStream
.listen((updatedOrganization) =>
setCurrentOrganizationName(updatedOrganization.name!));

_postsSubscription = _postService.postStream
.listen((newPost) => checkIfExistsAndAddNewPost(newPost));
_postsSubscription =
_postService.postStream.listen((newPosts) => buildNewPosts(newPosts));

_updatePostSubscription =
_postService.updatedPostStream.listen((post) => updatedPost(post));
}

void initializeWithDemoData() {
Expand All @@ -69,13 +74,9 @@ class OrganizationFeedViewModel extends BaseModel {
// });
}

void checkIfExistsAndAddNewPost(Post newPost) {
if (!_renderedPostID.contains(newPost.sId)) {
// print(newPost.sId);
_renderedPostID.add(newPost.sId);
_posts.add(newPost);
notifyListeners();
}
void buildNewPosts(List<Post> newPosts) {
_posts = newPosts;
notifyListeners();
}

void navigateToIndividualPage(Post post) {
Expand All @@ -92,11 +93,22 @@ class OrganizationFeedViewModel extends BaseModel {
// Canceling the subscription so that there will be no rebuild after the widget is disposed.
_currentOrganizationStreamSubscription.cancel();
_postsSubscription.cancel();
_updatePostSubscription.cancel();
super.dispose();
}

addNewPost(Post newPost) {
_posts.insert(0, newPost);
notifyListeners();
}

updatedPost(Post post) {
for (int i = 0; i < _posts.length; i++) {
if (_posts[i].sId == post.sId) {
_posts[i] = post;
notifyListeners();
break;
}
}
}
}
54 changes: 54 additions & 0 deletions lib/view_model/widgets_view_models/comments_view_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/models/comment/comment_model.dart';
import 'package:talawa/services/comment_service.dart';
import 'package:talawa/services/post_service.dart';
import 'package:talawa/services/user_config.dart';
import 'package:talawa/view_model/base_view_model.dart';

class CommentsViewModel extends BaseModel {
late CommentService _commentService;
late PostService _postService;
late String _postID;
late List<Comment> _commentlist;
late UserConfig _userConfig;

// Getters
List<Comment> get commentList => _commentlist;

void initialise(String postID) {
_commentlist = [];
_postID = postID;
_commentService = locator<CommentService>();
_userConfig = locator<UserConfig>();
_postService = locator<PostService>();
notifyListeners();
getComments();
}

Future getComments() async {
setState(ViewState.busy);
final List _commentsJSON =
await _commentService.getCommentsForPost(_postID) as List;
print(_commentsJSON);
_commentsJSON.forEach((commentJson) {
_commentlist.add(Comment.fromJson(commentJson as Map<String, dynamic>));
});
setState(ViewState.idle);
}

Future createComment(String msg) async {
print("comment viewModel called");
await _commentService.createComments(_postID, msg);
addCommentLocally(msg);
}

void addCommentLocally(String msg) {
_postService.addCommentLocally(_postID);
final _creator = _userConfig.currentUser;
final Comment _localComment = Comment(
text: msg, createdAt: DateTime.now().toString(), creator: _creator);
_commentlist.insert(0, _localComment);
notifyListeners();
}
}
Loading