Easy Like and Dislike
The like
unctionality can be applied to various entities in the app, such as user profiles, uploaded photos, posts, and comments.
A simple way to handle this is by saving a list of user IDs who liked or disliked an item. However, if the document becomes too large, it can slow down the app and increase costs for network usage on Firebase. Additionally, Firestore documents have a 1MB size limit, which can cause issues when there are too many like.
The easy_like
package provides an easy and efficient way to manage the like
functionality.
It does not support dislike
since most of the community don't provide dislike
button. It discourages usres to participate the community.
Installation
Security rules
- On the document, the
likes
should be open to be written by any one.
Terms
vote
is the action of voting(doing) like or unlike.like document
is the document under/likes
collection.target document
is the original document that hte like is refering. It can be a user document, post document, commnet document, chat room document, or what ever.
Database structure for Like and Dislike
-
/likes/{documentId}
: This is where like information saved. And the id of the document is the target document. -
documentReference
: This field is reference of the target document. It's a reference. So it can access the target document regardless of any collection. -
likedBy
: This field is the list of user uid who did like. If the user unlikes, then the uid will be removed from this field. -
likeCount
: This field is the no of the likes. It can be used for search purpose. -
Note that, the
like document ID
is the same as the target document ID.
Logic
- It uses transaction to increase and decrease.
- Whenever there is a changes on
vote
, the number oflikeCount
must be updated in the original document. - When the user unlike(or the like again), then the no of like will be decrease.
Displaying the no of likes
-
Since the
likeCount
field is saved on the document, it can simply display with the document. so, theeasy_like
package does not provide andy widgets. -
Below is how to diplay
likeCount
on a post detail screen. Note the the post detail screen should listen to the database update.
Example:
TextButton(
onPressed: () async {
final like = Like(uid: my.uid, documentReference: widget.post.ref);
await like.like();
},
child: Text(
'Like'.tr( args: {'n': widget.post.likeCount}, form: widget.post.likeCount),
),
),
Changing Icons if like or unlike
-
You can display diffrent widget base on the status of the like (like or unlike)
-
LikeDoc
is a widget that you can use to determine of the like status(like or unlike)
Example
IconButton(
onPressed: () async {
final like = Like(documentReference: post.ref);
await like.like();
},
icon: LikeDoc(
uid: my.uid,
documentReference: post.ref,
sync: true,
builder: (islike) {
return FaIcon(
islike
? FontAwesomeIcons.solidHeart
: FontAwesomeIcons.heart,
color: Colors.pink[700],
size: 30,
);
}),
),
onLiked CallBack
The onLiked
is a callback after the liked/unliked is triggered using the Like.like() model is fired.
Usage: (e.g. send push notification to other user)
In the example below, we can send push notification to the post owner after the like is triggered. It contains the Like
information, and isLiked
if the like is liked or not.
LikeService.instance.init(
onLiked: ({required Like like, required bool isLiked}) async {
/// only send notification if it is liked
if (isLiked == false) return;
/// get the like document reference for more information
/// then base from the document reference you can swich or decide where the notificaiton should go
/// set push notification. e.g. send push notification to post like
if (like.documentReference.toString().contains('posts/')) {
Post post = await Post.get(like.documentReference.id);
/// dont send push notification if the owner of the post is the loggin user.
if (post.uid == myUid) return;
/// can get more information base from the documentReference
/// can give more details on the push notification
MessagingService.instance.sendMessageToUids(
uids: [post.uid],
title: 'Your post got liked',
body: '${my.displayName} liked ${post.title}',
data: {
"action": 'like',
"source": 'post',
'postId': post.id,
'documentReference': like.documentReference.toString(),
},
);
}
},
);