Implementing Syde An online Forum in Flutter (Update 2 : Post A Story, Retrieve All Stories)

in #utopian-io6 years ago

Repository

https://github.com/enyason/Syde

History

New Features

  • Create and post a new Story
  • Display All Stories in Home Screen with a List
  • Detailed Screen for the Stories
  • Post Reaction Implementation (e.g like or unlike a story)

Create And Save a New Story

As part of the functionalities of SYDE, users on the platform can post their stories to the platform. This feature which is part of the back-end implementation is Handled by Fire-base.

Implementation

Implementing this part of the platform, FireStore of FireBase was used. FireStore NoSQL cloud database to store and sync data for a client- and server-side development. Firebase handles most of the back-end complexities allow the developer to focus on implementing important features of a product

  • The code block below is a method that handles creating a new story.

    void makePost({String body, List images}) {
        images = ["image001", "image002"];
        Firestore.instance.collection("all_post").add({
          "post_id": "not available",
          "time_stamp": DateTime.now().millisecondsSinceEpoch.toString(),
          "user":{
    
            "user_id": _user.uid,
            "user_name": _user.displayName,
            "user_photo": _user.photoUrl,
          },
          "post_body": body,
          "like_count": 0,
          "comment_count": 0,
          "image_url": images
        }).then((docRef) {
          docRef.updateData({"post_id": docRef.documentID});
    
          Navigator.pop(context);
          print(docRef.documentID);
        });
    }
    
    • The method accepts the story content with images if available. Data Storage is not implemented yet with Firebase so we just use a dummy list with fake data.
    • Firestore works with Collections and documents. So we get a firestore instance and get reference to a collection and add a new map.
    • In the Map, we have defined all the post attribute.
    • The then callback returns the document reference which is used to update the story id ()"post_id)

Retrieve All Stories and Display in Home Screen with a List

Users can view all stories made on the platform by navigating to the story tab. The Stories are displayed as a list of items, which users can scroll through.

Implementation

With Firestore i listen to the document reference created by the "all_post" collection using Flutter out of the box stream builder Widget.

StreamBuilder<QuerySnapshot>(
        //listen to changes in the document reference
        stream: Firestore.instance
            .collection('all_post')
            .orderBy("time_stamp", descending: true)
            .snapshots(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> document) {
          //return error message if there is an error
          if (document.hasError)
            return Center(child: Text('Error: ${document.error}'));
          switch (document.connectionState) {
            case ConnectionState.waiting:
              //show progress dialog while state is waiting
              return Center(
                  child: CircularProgressIndicator(
                      valueColor: AlwaysStoppedAnimation<Color>(Colors.blue)));
            default:
        // returns a listView : builds children lazily
              return ListView.builder(
                itemCount: document.data.documents.length,
                itemBuilder: (context, index) {
                ...
                });})

Internally, the stream builder subscribes to the firstore to receive changes in real time.D epending on return values from firebase, the appropriate UI is displayed

Detailed Screen for the Stories

Implementation

For the detailed screen, I created a model class that has fields related to a story. The Story object is passed onto the detail screen which provides the contents that will be displayed on the Screen.

class Store{

  String storyTitle,storyBody,storyId,timeStamp;
  int likeCount,commentCount;
  Map user;

   //cretates story from a map
   Story.fromMap(Map story){

    storyTitle = "Not Available";
    storyBody = story["post_body"];
    storyId = story["post_id"];
    timeStamp = story["time_stamp"];
    user = story["user"];
    likeCount = story["like_count"];
    commentCount = story["commentCount"];

  }

}

The Model class defines required attributes that will be needed structuring the UI

Post Reaction Implementation

Users can react to a story made by a user in the platform . They can either like it or unlike it.

Like Implementation

 // this method handles liking a psot
  likePost(int index, AsyncSnapshot<QuerySnapshot> document) async {
    //use transaction on the fire store instance to prevent race condition
    Firestore.instance.runTransaction((transaction) async {
      //get a document snapshot at the current position
      DocumentSnapshot snapshot =
          await transaction.get(document.data.documents[index].reference);

      //include uid to the like collection of the story
      // and set "like" field to true
      await transaction.set(
          snapshot.reference.collection("likes").document(widget.user.uid),
          {"like": true});

      //increment like count for the story
      await transaction.update(snapshot.reference,
          {"like_count": document.data.documents[index]["like_count"] + 1});
    });
  }

Here I used firebase transaction so we don't have issues of race condition. Suppose multiple users are updating the value of data at the same time, we could get unexpected results. To handle this, firebase provides an atomic operation called Transaction.

Unlike Implementation

//this method handles unlike a post
unLikePost(int index, AsyncSnapshot<QuerySnapshot> document) async {
  Firestore.instance.runTransaction((transaction) async {
    DocumentSnapshot snapshot =
        await transaction.get(document.data.documents[index].reference);

    //unlike only when like count is > 0
    if (document.data.documents[index]["like_count"] > 0) {
      // and set "like" field to false
      await transaction.set(
          snapshot.reference.collection("likes").document(widget.user.uid),
          {"like": false});

      // decrement like count
      await transaction.update(snapshot.reference,
          {"like_count": document.data.documents[index]["like_count"] - 1});
    }
  });
}

This implementation is similar to that of the like.

IMPORTANT RESOURCES

*Github *: https://github.com/enyason/Syde

RoadMap

  • Authenticate User
  • Persisting user post
  • Displaying all post
  • Detailed screen implementation
  • Story Reaction Implementation (like and unlike a story)
  • Searching all posts
  • Providing different layouts
  • ToDo for users to track their daily progress
  • Push Notifications
  • Posts sharing
  • Users dashboard
  • Searching all users
  • Direct Messaging with Users
  • ChatGroup
  • Bookmarking post

Demo Video

How to contribute?

You can reach me by commenting on this post or send a message via [email protected] you want to make this application better, you can make a Pull Request.
Github

Sort:  
  • This article could use an introduction image that represents the project.
  • Since you're making an application with a visual interface, it would be expected that you share images of the app in your articles.
  • Your repo needs an open source license to be considered open source.
  • You need to list your pull request or commit list in you articles for evaluation. I use this link today: https://github.com/enyason/Syde/compare/master@%7B1day%7D...master
  • You also need to update your repo's readme file with at least the update name for the app.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thanks for the review... I'll improve on my next contribution

Thank you for your review, @helo! Keep up the good work!

Hi, @ideba!

You just got a 0.7% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Hi @ideba!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @ideba!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Congratulations @ideba! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You received more than 500 as payout for your posts. Your next target is to reach a total payout of 1000

You can view your badges on your Steem Board and compare to others on the Steem Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Do not miss the last post from @steemitboard:

The Steem blockchain survived its first virus plague!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!