GSOC 2023: Feed Section in Android App

Personal Information

Name: Jasjeet Singh

IRC nick: jasje

Email: 07jasjeet@gmail.com

Github: 07jasjeet

Time Zone: UTC+05:30

Feed Section in ListenBrainz Android App

Project Overview

Currently, ListenBrainz Android app consists of various features like BrainzPlayer, Listens Service, Listens history, YIM and many more which already make the app very interesting.

ListenBrainz website is an amazing platform that inculcates an idea which I believed in past but had no power to do so, i.e., having a social media app that revolves around music. Feed section is one of the core functionalities of this idea and the Android app lacks it. This feature has the potential to attract more users than ever because social media is something people access frequently and a mobile device is the best place to have it.

This project aims to integrate the Feed Section into the Android app.

My contributions up till now:

My Pull Requests: Check Out

My Commits: Check Out

Implementation

Going with the flow that ListenBrainz Android Docs mentions, this project will be implemented through the following stages:

  1. Planning

    These are the following additions according to the ideas page.

    • Feed section is a replacement for home page (tentative), hence a lot of the burden comes to optimising this page to induce smooth startup experience.

    • The feed should showcase all ListenBrainz social events like whenever a user’s follower listens to a track, recommends a track in general or to them personally, follows another user or a user follows them, pins a track, reviews an album, reviews a track, or ListenBrainz has new announcements. ListenBrainz server has appropriate APIs for these tasks which will be mentioned in Knowing the APIs section.

    • Spotify remote player must be used in order to play songs on demand when the user clicks on an event that consists of a recording.

    • Follow/Following functionality is required is to bundled with appropriate methods to allow user to search for another user.

    • Test first approach will be followed for unit tests and proper testing architecture will be followed throughout. Instrumented tests will be implemented once the project has a screen flow.

  2. Designing

    Designing process will be done under the watch of MetaBrainz team’s in-house designer and my mentor. Being accustomed to how things work in the organisation, it will be a smooth process. All designs will be created on Figma with frequent reviews from mentors.

    These are some quick mockups of what feed might look like:

  3. Knowing the APIs

    The following API endpoints will be responsible for the functionality of this feature:

    • GET /1/user/(user_name)/feed/events?count=20&max_ts=<max_ts> : This API endpoint is responsible to provide information for all feed events. count and max_ts will be used to get events in batches of 20. LB Token required.

    • POST /1/user/(user_name)/timeline-event/create/recommend-personal : This API endpoint will let the user to personally recommend a recording to their some of their followers. LB Token required.

    • POST /1/user/(user_name)/timeline-event/create/recording : This API endpoint will let the user to recommend a recording to all their followers without any message or blurb content. LB Token required.

    • POST /1/user/(user_name)/timeline-event/create/review : This API endpoint will let the user post a CritiqueBrainz Review to the feed. The user must link their CritiqueBrainz account with ListenBrainz for this functionality to work. Error will be thrown if they haven’t. LB Token required.

    • GET /1/user/(user_name)/services : This API endpoint will allow us to verify if the user has linked CritiqueBrainz account with ListenBrainz or not. LB Token required.

    • POST /1/user/(user_name)/feed/events/delete : This API endpoint will allow the user to delete an event that belongs to themselves. This endpoint supports deletion of recommendation and notification, so delete option will be limited to those only. User will also be given an appropriate window to cancel this action in order to avoid accidents. LB Token required.

    • POST /1/user/(user_name)/feed/events/hide : This API endpoint allows user to hide recording_recommendation and recording_pin events of users they are following. Appropriate time interval to undo hide action will be given to avoid accidents and an extra call to unhide. LB Token required.

    • POST /1/user/(user_name)/feed/events/unhide : This API endpoint will allow the user to unhide a previously hidden event. LB Token required.

    • POST /1/pin : This API endpoint is used to pin a recording. LB Token required.

    • POST /1/user/(user_name)/follow : This API endpoint will let user follow another ListenBrainz user. LB Token required.

    • POST /1/user/(user_name)/unfollow : This API endpoint will let user unfollow another ListenBrainz user (which they are following). LB Token required.

    • GET /1/user/(user_name)/followers : This API endpoint will fetch the list of followers of the user.

    • GET /1/user/(user_name)/following : This API endpoint will fetch the list of users followed by the user.

    • GET /1/user/(user_name)/similar-users : This API endpoint returns an array of dictionaries which contain a “similar” user. This endpoint will be used to recommend the user, other users on ListenBrainz that have same taste as the user itself.

    • GET /1/search/users?search_term=<user_name> : This API endpoint returns list of users that closely resemble input username. This endpoint will be used to search ListenBrainz users through their username. Debouncing will be implemented.

    Most these API endpoints require Authorization headers which must include LB access token.

  4. Coding

    Step by step process of how coding part will go:

    1. API calls setup for User Search page with tests.

    2. View-model setup for User Search page. This will consist of SearchViewModel which will contain all code related to follow/unfollow interactions and User Search methods.

    3. User Search page UI implementation and performance testing. This page will probably be merged via tabination (Use of Tabs) with Feed but is kept tentative as of writing this proposal. This requires a brief discussion with mentors such that the app design is in line with the website. Mockup of components to be used in user page (tentative):

    4. API calls setup for Feed page with tests.

    5. View-model setup for Feed page consisting of two view-models namely: FeedViewModel (will only consist of strictly feed related business logic and follow/unfollow logic) and SocialViewModel (will consist all the reusable drop down calls such as recommend, personally recommend, write a review and more).

      For FeedViewModel we may need some helper functions and variables all packed up as a seald class as follows:

      sealed class FeedEvent (
            val type: String, 
            /*
            @DrawableRes val icon: Int, 
            val isPlayable: Boolean
            */
      ) {
            object RECORDING_RECOMMENDATION : FeedEvent("recording_recommendation"){
                 // Function to get composable with appropriate params.
                 @Composable
                 fun Content(/*params*/) {
                    // Content
                 }
                 // Other helper functions
             }
            object PERSONAL_RECORDING_RECOMMENDATION : FeedEvent("personal_recording_recommendation")
            object RECORDING_PIN : FeedEvent("recording_pin")
            object LIKE : FeedEvent("like")
            object LISTEN : FeedEvent("listen")
            object FOLLOW : FeedEvent("follow")
            object NOTIFICATION : FeedEvent("notification")
            object REVIEW : FeedEvent("critiquebrainz_review")
            object UNKNOWN : FeedEvent("update_app")     // In case a new event is added in future that had not been published to the app.
       }
      
    6. Spotify App Remote SDK is currently used in ListensViewModel. Since the App Remote is very dependent on context, testing scope is hampered. To tackle this, Spotify App Remote SDK will be converted into a repository (which is easier to mock) and a mock will be established. ListensViewModel will be refactored for the same.

    7. Creating Compose UI for the feed page.
      Workflow:

      1. Implement Basic cards and list item for showcasing various events. Example:

      2. Integrate Spotify App Remote.

      3. Create drop-down menu for feed cards.

      4. Implement each mini-feature which consists of the following:

        • Implement drop down that mutates according to the feed event.
        • Implement all the required reusable components for the functionalities inside the drop down.

        This includes:

        1. SnackBar implementation to accommodate Undo for accidental events.

        2. Delete an event from feed functionality. Only recommendations and notifications can be deleted. Example Body of the post request:

          {
              "event_type": "<recording_recommendation or notification or recording_pin>",
              "id": "<integer ID of the event>"
          }
          
        3. Hidden Card component when a user hides or unhides an event.
          Example Body for post request to hide an event:

          {
              "event_type": "<recording_recommendation or recording_pin>",   # Can only hide pins/recommendations of followed users from our feed.
              "event_id": "<integer id of the event>"
          }
          

          Example Body for post request to unhide an event:

          {
                "event_type": "recording_pin",   # Can only unhide pins/recommendations of followed users from our feed.
                "event_id": "<integer id of the event>"
          }
          
        4. Personally Recommend feature requires a dialog that contains a search box where users can search and select through their followers to whom they want to recommend the recording. Draft saving (Point 5) will be implemented for Personally Recommend. Both recommend to followers and personally recommend to followers share the same data class as follows:

          {
             "metadata": {
                "artist_name": "<The name of the artist, required>",
                "track_name": "<The name of the track, required>",
                "recording_msid": "<The MessyBrainz ID of the recording, required>",
                "release_name": "<The name of the release, optional>",
                "recording_mbid": "<The MusicBrainz ID of the recording, optional>",
                "users": [<usernames of the persons you want to recommend to, required>]  # Only required in Personal recommendation.
                "blurb_content": "<String containing personalized recommendation>"  # Only required in Personal recommendation.
             }
          }
          
        5. Write a CritiqueBrainz Review feature requires another dialog that allows user to input text which is then sent as a review. For this task, POST /1/user/(user_name)/timeline-event/create/review endpoint will be used. Example body data:

          {
             "metadata": {
               "entity_name": "Shakira",
               "entity_id": "bf24ca37-25f4-4e34-9aec-460b94364cfc",
               "entity_type": "artist",
               "text": "TEXT",    # Text should be minimum 25 characters, error should be thrown if not.
               "language": "en",
               "rating": 4,    # Rating should lie between 1..5
             },
          }
          

          Since CritiqueBrainz should be linked to ListenBrainz account for this to work, login check will be performed first. If the user is not logged in, they will be redirected to this page in order to link their account to ListenBrainz.

          Also, draft saving will be implemented for reviews. When a user leaves a review in-between to check some things, user may lose progress accidentally. To prevent this, reviews will be cached and a new caching system will be implemented. Proper time-out system will be implemented to clear cache after some specified time interval. Tests included.

        6. Pin recordings directly from feed. Example Body of the post request:

          {
              "recording_msid": "<required>",
              "recording_mbid": "<this field is optional>",
              "blurb_content": "TEXT",
              "pinned_until": 1824001816
          }
          

        These are all the features included in this package. Given that Inspect Listen and Link with MusicBrainz ultimately lead to the website, those features will be kept tentative.

      5. Performance test the feed composable.

    8. Implementing instrumented tests for both features.

    Manual testing will be part of this project throughout thus encouraging TDD (Test driven development).

Timeline

Following is an overview of how I will be spending my time during the duration of GSOC:

Pre-Community Bonding Period (4 April - 3 May):

Work on restructuring and write tests for the app. Discuss the UI for the feed with my mentors. Work on the UI ideas.

Community Bonding Period (3 May - 29 May):

Start Phase 1 early if no work persists. Since my college exams are scheduled in this period, work will be affected.

Phase 1 : User Search Page

Week 1 (29 May - 5 June)

  • Setting up API calls to the following required endpoints with their respective Unit tests:

    1. POST /1/user/(user_name)/follow
    2. POST /1/user/(user_name)/unfollow
    3. GET /1/user/(user_name)/followers
    4. GET /1/user/(user_name)/following
    5. GET /1/user/(user_name)/similar-users
    6. GET /1/search/users?search_term=<user_name>
  • Setting up dependency injection.

Week 2-3 (5 June - 19 June)

  • Implementing Search Page user interface. This includes the following:

    1. Search Bar with debouncing technique to limit API calls.
    2. Follow/Following list.
    3. Similar users list.
    4. Tabination (Use of Tabs) to inculcate this page with feed page. Both, Feed and Search-User pages will share the same bottom navigation icon and have tabs to navigate internally.
  • Performance test the screen.

Phase 2 : Feed page

Week 4 (19 June - 26 June)

  • Setting up API calls to the following required endpoints with their respective Unit tests:

    • All endpoints except “GET /1/search/users?search_term=<user_name>” will be used in feed.

    • Since 6 of the all the calls would be setup already, rest 7 would be implemented. These following endpoints require heavy work, so, 1.5 to 2 weeks are required.

      1. GET /1/user/(user_name)/feed/events?count=20&max_ts=<max_ts>
      2. POST /1/user/(user_name)/timeline-event/create/recommend-personal
      3. POST /1/user/(user_name)/timeline-event/create/recording
      4. POST /1/user/(user_name)/timeline-event/create/review
      5. POST /1/user/(user_name)/feed/events/delete
      6. POST /1/user/(user_name)/feed/events/hide
      7. POST /1/user/(user_name)/feed/events/unhide
      8. GET /1/user/(user_name)/services
  • Setting up dependency injection.

Week 5-6 (26 June - 10 July)

  • Finish up remaining Unit tests, if any.
  • Setting up required view-model (with tests) and integrate connectivity observer.
  • Creating repository for Spotify App Remote, adding it to dependency tree and injecting it into view-model’s various cases where recordings are found.

Week 7-9 (10 July - 31 July)

  • Begin UI implementation.
    Please checkout point 4 of Coding part in implementation section for more clarity on the exact chronological order of implementation of each functionality.
  • Connect all UI components to prepare a beta product.

Week 10 (31 July - 7 August)

  • Compose UI is prone to performance issues (or recompositions to be exact) if not implemented correctly, hence improve code quality overall.
  • UI has to be tested for each screen aspect-ratio as the app supports Android phones with a minimum of Android 5.0 (Lollipop).
  • Test all the services and linked components for error/edge cases.
  • Start implementing Instrumented Tests for the feature if the project seems stable.

Week 11 (7 August - 14 August)

  • Implement Instrumented Tests for the feature. This includes tests for both Search page and Feed page.

Week 12 (14 August - 21 August)

  • Finish up pending work, if any.
  • Start writing documentation for the project.
  • Discuss with mentors about any final changes.

Stretch goals

  • Integrate BrainzPlayer with Remote Players such that users are able to control media playback from mini-player and only from notification of original service by removing notification of BrainzPlayer when remote players are active. Removing notification helps in keeping notification bar clean from unnecessary notifications in Android 10 and below.

Detailed Information About Yourself

My name is Jasjeet Singh, currently residing in Chandigarh. I am a sophomore pursuing Bachelors in IT from University Institute of Engineering and Technology, Panjab University, Chandigarh, India. I had not known much about coding until I came to college. Started with C in my 1st semester. Didn’t last long due to distractions and slight obsession with games (CS; and yes 1v1 accepted :smiling_imp:). Soon after, I realized this habit won’t help me in the long run. I had to pick any development to make “things” or projects as we call them. I’ve always had a thing for Android, so I picked it!

Tell us about the computer(s) you have available for working on your SoC project!

I have my Lenovo Legion 5 Pro, with Ryzen 7 5800H, RTX 3060 and 16 GB of RAM.

When did you first start programming?

I stepped into the coding world with C as my first programming language last year.

What type of music do you listen to? (Please list a series of MBIDs as examples.)

I mostly listen to Punjabi music artists like Arjan Dhillon, Karan Aujla, Sidhu Moose Wala or Tame Impala for some change.
I’ve also added one recording and artist to MusicBrainz database respectively:

Some MBIDs of my favorite recodings :smiling_face_with_three_hearts: :

5279bc04-6b83-4897-814d-4f604fedd79c (The one I added to MusicBrainz)
5ecd8c60-c756-4532-8207-c45886df2feb
f078699c-9b68-4040-9ba4-b1e4f7d86598
31eeb9db-cff0-40ab-bc5a-5474a432519c

What aspects of the project you’re applying for the interest you the most?

I love Android Development and listening to music, so there’s no better project than ListenBrainz that keeps me engaged and happy. I’ve been working on ListenBrainz Android for some months now and honestly, I really have passion about moving the app further, exploring its scope and making it better continuously.

Have you contributed to other Open Source projects? If so, which projects and can we see some of your code?

ListenBrainz is my first point of contact with open source and feels really good to be this way.

What sorts of programming projects have you done on your own time?

I mostly play with Android Development, hence most of my projects are Android projects like Drawing App and Quiz App. I also have some C projects (here) and some flask projects (which I’m currently learning btw) but they are pretty teensy and under active development.

How much time do you have available, and how would you plan to use it?

I will be providing 40 to 45 hours per week to the project. There may be slight ups and downs due to college exams and other activities.

7 Likes

Thanks a lot for your proposal @Jasjeet! :100:

I would like to clarify a few things before we move ahead with this:

  1. We need a way to allow users to search for other users. This would allow them to follow that particular user. Only then, we can proceed with the idea of a feed section. Hence, a search box and the relevant screen for that will be a part of this project.

  2. Reviews will be a part of the feed. In order for a user to be able to add a review to a listen, a connection to CritiqueBrainz has to be made prior, like the one made on the website.

  3. If we take a look at the options available for the listens card, this is the list.

Pin this track, Recommend to my followers, Personally recommend, Write a review directly affect the feed and are an integral part of it. These would be considered as a pre-requisite for this project. Also, Open in Spotify has already been mentioned by you in the proposal.

  1. Hide, Unhide, Delete, etc are all parts of the feed and would be taken up with the project.

That being said, I would like to point out that this project is not just a UI/UX project which dumps the exisiting feed info of a user from the website to the app.
Our major focus has to be on the accessibility of these features for the feed. For example, last year we had an entire gsoc project which only focused on adding the ability to add reviews on ListenBrainz. But with this project, we are considering that as a pre-requisite.

It is important that we are on the same page about the expectations. Your contributions to the ListenBrainz app have already been so helpful and amazing. Just to be clear, when I think of the Feed project, I imagine it to be complete. Also, this is a long project. Hence, given your caliber and from my understanding, we could cover up the entire Feed with this Summer of Code project.

Feel free to comment and re-work on your proposal with the exact descriptions of the features which will be taken up and those which won’t. I am fine with leaving out certain things that you feel won’t be an adequate part of this project, but we should have that clarified before itself.

Also, looking at your weekly breakdown, it is quite generic and doesn’t mention the features being worked on exaclty. I would like a mention of the exact features/api calls being worked on and which feature will be taken up when. For example, review feature comes before listen track intimation on the feed, etc.

We could also take up push notifications in stretch goals btw, just a suggestion.

Let me know if you have any questions.
Great to see your enthusiasm and dedication to this project. Thank you! :smiley:

3 Likes

Good one Jasjeet :))

2 Likes

Thankyou for the amazing feed-back (pun intented). All the recommendations are duly noted :smile:. Just updated the proposal with your analysis in mind.

1 Like

Hi @Jasjeet , I went through your proposal again. And as someone who has no idea about this project, I gotta say it looks flawless to me!

Good job keeping it super succinct!

IMO your proposal clearly demonstrates your passion and capability to pull off the project - so there’s not much to comment there.

Just to nitpick, I’d like to point out a couple of things in the “detailed information about yourself” section.

I mostly play with Android Development, hence most of my projects are Android projects. I also have some C projects and some flask projects (which I’m currently learning btw) but they are pretty teensy.

Folks at MetaBrainz already are aware of your capabilities. But in general, always try to include GitHub links when talking about your projects. It will definitely also open up more doors for you along the way.

I will be providing 40 to 45 hours per week to the project. There may be slight ups and downs due to college exams and other activities.

Refer your timetable, and try to mention specific dates, e.g. Exams from 4th July - 10th July, Going on a Family trip from 3rd Aug - 6th Aug, etc. Setting the expectations right from the get-go really helps :))

What type of music do you listen to? (Please list a series of MBIDs as examples.)

Doesn’t really matter, but I’ve personally included my listenbrainz profile, and some recording MBIDs in this section too. Might help :person_shrugging:

1 Like

Exams are a big unknown in our university, they just keep changing :frowning:. I actually included some buffer time in week 9-13. I’ll clarify it there. Thanks for pointing this one!

As far as family trips are concerned, I have no clue about when those hit :skull:.

I’ll rework on this section, seems generic to me too now that I’ve seen it again :skull:.

Thanks for the feedback! Much appreciated :raised_hands:.

1 Like

@Jasjeet Overall, the proposal looks great to me now! Ready for submission I believe :100:
The only thing which I could suggest for now is to try and break Week 9-13 a bit more because that is literally clubbing a chunck of weeks, which doesn’t sound right. I understand what you mean, but just for sanity, it would be better to just communicate it better.

1 Like

Thanks for pointing this out! @snaekboi pointed it out beforehand but I couldn’t think of any reasons at that time. But now I’ve recalled some stuff (my memory is terrible at remembering dates) and made a separate week schedule for the buffer period with reasons. Also, please note that the buffer period may coincide with UI implementation so as to not suffocate the UI implementation period itself.

Also, I know the coding part doesn’t have exact weeks timeline. This is due to the fact that The whole UI is so interdependent and if I started laying out timeline for each functionality, it will come down to days and given that a lot of decisions are made while actual implementation itself, I deemed it unfaithful to give each functionality a timeline. A chronological order has been given to ensure what steps will taken in what flow.