Creating a Facebook Timeline using ComponentKit

Creating a Facebook Timeline using ComponentKit

In the past few days I have taken a special interest in learning ComponentKit framework. From the official GitHub page, it's a React-inspired view framework built for the iOS.

ComponentKit is written in Objective-C++. Although those ++ look scary, the library hides all the complexities associated with both Objective-C and C++. GitHub page has nice instructions on how to install ComponentKit framework through Carthage. There is one caveat though. I ran into obscure and highly complicated errors while pulling the framework through Carthage. For more help please Google the error or this issue reported under Issues tag will help.

It took me few hours to fetch the framework and link it with my project. However, when I was done, I was the happiest person in the whole world. But that was only the first step.

So what am I going to build?

I heard about ComponentKit a few years ago. However, it being in Objective-C++ scared me away or I was just too lazy. As everyone was jumping on Swift bandwagon, that may also have added to me deciding to postpone it for some time in future.

As recently I took liking to ComponentKit, I decided to use it in the side-project. And the side-project is none other than Facebook timeline as that is one of the major component of Facebook iOS app where ComponentKit is heavily used.

What was my design goal?

I decided to use the Facebook's mobile web designs as mock-ups for building UI using ComponentKit. Here's how it looks like,

How did I divide problem into sub-components?

No matter how great the framework is, you still have to come up with creative ways to make its effective use. Let's make the list of sections we will need to build the complete card,

  1. Post Identity Component

         - Profile picture
         - Username
         - When posted
         - Where posted
         - Three dots

2.  Description Component

       - The post description

3. Image Component

       - The post image

4. Emotions/Likes/Comments Component

       - List of reactions emojis
       - Count of people reacted on post
       - Number of comments
       - Number of shares

5. Bottom button bar Component

       - Like button
       - Comment button
       - Share button

Now, let's take a look at the actual app and will start annotating each of these components,

Thinking in terms of ComponentKit

However, it doesn't give us clue on how we can transform this design in terms of ComponentKit components. Let's go ahead and start naming every sub-component with the name of class file written in Objective-C++ using ComponentKit.

As ComponentKit emphasizes, the goal here is to maintain atomic components which when combined together will form the bigger component. So to build bigger component, we will start with smaller parts and then group them together to form the component representing a single Facebook post.

Before I dive into (another) annotated diagram, let's take a look at components hierarchy,

MainPostComponent
 - InsetComponent
  - BackgroundComponent
   - InnerComponent 
    - PostIdentifyComponent
     - CKFlexboxComponent
      - CKFlexboxComponent
       - CKImageComponent
       - CKFlexboxComponent
        - CKLabelComponent
        - CKFlexboxComponent
         - CKLabelComponent
         - CKImageComponent
      - CKImageComponent
    - DescriptionComponent
    - ImageComponent
    - ReactionCommentsComponent
     - CKFlexboxComponent
      - CKFlexboxComponent
       - CKLabelComponent
       - CKImageComponent
      - CKFlexboxComponent
       - CKLabelComponent
       - CKLabelComponent
    - BottomButtonsRowComponent
     - CKFlexboxComponent
      - ButtonWithTitleComponent
       - CKFlexboxComponent
        - CKButtonComponent
        - CKSpacing
        - CKButtonComponent
      - ButtonWithTitleComponent
      - CKFlexboxComponent
        - CKButtonComponent
        - CKSpacing
        - CKButtonComponent
      - ButtonWithTitleComponent 
      - CKFlexboxComponent
        - CKButtonComponent
        - CKSpacing
        - CKButtonComponent

I know it sounds scary, but let's divide them into separate subsection and we will start analyzing them. Here's the snapshot of full Miro board.

And for more detailed view, here's the link to Miro board. The hierarchy mentioned here has been completely transformed into the graphical representation of components and their parent-child relationship.

In order to demonstrate slightly complicated example, I have also added support to like/unlike post which causes component to change the state which in turn causes tapped component to change image and color of the text. However, in the interest of keeping this post terse, I won't go into these details

I won't go into detailed source code for each component, but here's how the code looks like if we want to create BottomButtonsRowComponent out of child ButtonWithTitleComponent components.

Thanks to Carbon.now.sh for supporting the code formatting

So what are we doing here?

  1. We are maintaining an array called as subComponents to store all the ButtonWithTitleComponent that will go into the parent BottomButtonsRowComponent
  2. We initialize and store all the ButtonWithTitleComponent in array to act as children for next CKFlexboxComponent
  3. Next, we create a Flexbox where we ask it to arrange its children horizontally, vertically center them and organize them in such a way that they are separated by the fixed spacing on all the sides
  4. In order to maintain visual aspects, we also add a fixed space insets on all sides of this component
  5. Next we call the superclass static method + (instancetype)newWithComponent:(CKComponent *)component in order to create the instance of our component

And here is the final result of this code,

BottomButtonsRowComponent

And after combining all the subcomponents this is how our MainPostComponent looks like,

But this component gets displayed as a UICollectionViewCell and having just one post on timeline is not enough. So what we will do is, we will create random array of Post content and provide it to the Component data source and with that, this is how our timeline will look like with random posts,


And that's it folks! ComponentKit is a delightful framework that makes working with dynamic and responsive layouts really easy. I haven't played with the data transfer and interaction yet, but that's something I am curious about next.

The full source code for ComponentKitPractice is available to view on GitHub. Feel free to take a look. I am open to any suggestion or feedback

I am still learning the framework, but if you have any questions or comments on my code, feel free to post them in comments section under this post

References:

Timeline - Facebook.com
Basic Designs - Freepik.com
ComponentKit Docs
ComponentKit on GitHub
Facebook's iOS Architecture
Facebook's iOS Architecture - @Scale 2014 - Mobile