Page MenuHomePhabricator

[GSoC Proposal] Modularize Commons Android App and Migrate to Jetpack Compose
Closed, DeclinedPublic

Description

Profile Information

Name - Rohit Verma
Email - rv17837@outlook.com | rv17837@gmail.com
LinkedIn - rohit0111
GitHub - rohit9625
Location - Ghaziabad, Uttar Pradesh, India
Typical working hours - 9 am to 7 pm (IST) UTC+5:30

Synopsis

Possible Mentor(s):-

@Neeldoshii @Kaartic

Have you contacted your mentors already?

YES.

Summary

The Wikimedia Commons Android app allows users to upload pictures from their Android phone/tablet to Wikimedia Commons. It also provides several features like - Nearby, Maps, etc. for more usability.

Problem Statement

In this section, I explained the problems we have in the current codebase that is affecting developer experience directly and user experience indirectly.

  1. Inconsistent Architecture: The Commons Android app codebase has outdated architecture and all the code exists inside one app module. Most of the codebase follows the legacy MVP pattern and MVVM at some places. Since both are very different from each other and we can't combine them, so better to stick with only one. The modern Android development recommends MVVM, and we have a lifecycle-aware ViewModel class from androidx. So, it make sense to refactor the codebase to follow MVVM.
  2. Outdated UI: Some users have been complaining about the UI of Wikimedia Commons Android app, saying it is outdated. I also feel the need to revamp the current UI to comply with current industry standards and best practices. This will affect the users positively and will definitely enhance the overall UX of the app.
  3. Multiple Activities: Currently, we have multiple Activity components in our app; almost each screen has an Activity associated with it. It is a problem because:
    • An activity is an Android component and it has it's own lifecycle as well as it comes with its own memory overhead. Although it provides better separation of concern among different features, but this is not something that can't achieve without it.
    • So, using separate Activity classes for simple screens like About, Profile, Achievements, etc., can badly affect UX and result in lags, especially on low-end devices.
    • Navigating to each screen means a new activity instantiation which is comparetively heavy than replacing Fragments. Also, transitioning from one screen to another might not be smooth enough on some devices.
    • Data is shared between screens via Bundle or Intent, which increases complexity and we can't even share a single ViewModel instance easily between two activities for easy logic sharing.
  4. Memory Leaks: Managing Contexts in a Multi-Activity Architecture can be challenging and require careful cleanup. However, cleaning some references could lead to crashes or IllegalStateException, as in the current state of our codebase. That's why some memory leaks can't be resolved easily right now.
  5. Build Time: Modularizing the codebase will also reduce build times by a fraction of seconds which might not matter much when building locally. But, these seconds will compound over time for GitHub Actions runtime and save computational resources + time.
Solution

To address the above challenges, I propose an incremental and non-disruptive transformation of the existing codebase by introducing modular architecture, adopting a consistent MVVM + MVI pattern, and migrating the UI to Jetpack Compose.

1. Adopting Modular Architecture

The current monolithic architecture will be broken down into multiple well-defined isolated modules such as:

  • The core module: for shared (network, database, utilities, common UI components, etc.)
  • Feature modules (:auth, :nearby, :upload, :profile, etc.) focused on individual features of the app

The goal is to create loosely coupled but highly cohesive modules for different features of the Commons Android app. This will:

  • Reduce coupling between different features of the app
  • Enable independent development and testing of features
  • Improve code readability and maintainability
2. Standardizing Architecture with MVVM + MVI(Optional)

The codebase will be gradually refactored to follow a single architectural pattern, i.e., MVVM(Model View ViewModel) + MVI(Model View Intent). Here, using the MVP pattern will introduce more boilerplate code, which is why it needs to be used only when needed and should not be enforced for every screen.

  • Replace legacy MVP components with ViewModel-based implementations
  • Introduce unidirectional data flow using StateFlow or SharedFlow
  • Make the codebase more consistent and easier to understand
  • Simplify state management and testing
3. Migrating UI to Jetpack Compose

To modernize the UI and improve developer experience, the existing XML-based layouts will be gradually migrated to Jetpack Compose. This will:

  • Reduce boilerplate code (no XML files, Adapters, Fragment classes, etc.)
  • Improve UI consistency and reusability
  • Enable faster UI development and iteration
4. Replacing Multiple Activities with a Hybrid Architecture

Using multiple activities can be crucial for performance as well as developer experience, and is easily prone to memory leaks. However, migrating to a complete Single Activity Architecture still might not be the best option for our app. Therefore, we'll follow a Hybrid Approach. This will:

  • Reduce memory overhead caused by multiple Activity instances
  • Simplify navigation and back stack handling
  • Allow easier sharing of ViewModel across screens
  • Improve performance and provide smoother transitions between screens and we can add custom animation while navigating
  • Reducing Memory Leaks: Most of the memory leaks will be resolved automatically if we try to reduce Activitys and carefully refactor code to use lifecycle-aware components in Jetpack Compose.

Deliverables

Proposed Implementation Approach

The project will follow an incremental, feature-first approach to introduce modularization and migrate the UI to Jetpack Compose without disrupting the existing functionality of the app.

Screenshot 2026-03-28 at 9.59.41 PM.png (852×1 px, 115 KB)

Since all the code exists inside the app module, we'll gradually create separate feature modules and copy all feature-specific logic to individual modules. Once a module is finalized, we'll assemble it inside the app module.

Note: All this modularization + migration work has been done in a different branch, for eg, refactor/migrate-to-jetpack.

The modularized architecture is inspired by NowInAndroid repository, while keeping the code implementation or flow of data/events based on Clean Architecture and aligned with the current codebase.


1. Convention Plugins (build-logic)

Since we're heading towards a modular architecture, we can end up having duplicated build configurations(inside build.gradle.kts) for Room, Dagger Hilt, etc., in each module.
That's why we must extract the duplicate build setup for common libraries to a Convention Plugin and ensure consistency across modules by creating a dedicated build-logic module. It will:

  • Centralize dependency management and plugin configurations
  • Use Convention Plugins to standardize:
    • Kotlin setup
    • Setup for unit/instrumented tests
    • Compose configuration
    • Room, Dagger Hilt, Retrofit, etc., dependencies
  • Reduce duplication across build.gradle files

This will simplify scaling the project as new modules are introduced.

2. Feature-wise Modularization

The project will follow a feature-by-feature extraction strategy.

Screenshot 2026-03-29 at 1.40.40 PM.png (924×2 px, 274 KB)

  • Start with a smaller feature (e.g., auth or settings). It will help build pace in the initial days
  • Create a dedicated feature module (e.g., feature/auth)
  • Follow a layered architecture inside each feature:
    • ui → Screens (Compose), ViewModel, UI state/events
    • domain → Business logic, repository interfaces, feature-related models
    • data → Repository implementations, API/database interaction
  • Key Principles:
    • UI depends only on domain
    • Data implements domain contracts
    • Feature modules depend only on core, not on each other

This ensures Clean Architecture and Scalability.

3. The Core Module

A core module will be created to host shared logic, configurations and utilities used across different features/modules. It will be structured into the following layers:

  • data
    • /database (Room setup)
    • /network (Retrofit configuration)
    • /preferences (Preferences DataStore setup)
  • domain
    • /model: Contain data classes shared across. For example: generic ApiResponse, ApiError, etc.
    • /use_cases: Classes focused on one functionality that is used across the app
  • ui
    • /theme: Theme setup (colors, typography, shapes)
    • 'design-system: Reusable UI components/composables
    • /utils: UI related utility functions
  • di: Dependency injection modules (e.g., NetworkModule, DatabaseModule)
  • utils: Utility functions/classes used across the different modules

This module will act as the foundation layer, ensuring reusability and reducing duplication.

4. Jetpack Compose Migration

UI migration will be performed incrementally to avoid breaking existing functionality.

  • Start by building reusable UI components in core/ui
  • Introduce Compose in existing XML-based screens using ComposeView
  • Gradually migrate full screens to Compose
  • Maintain interoperability between XML and Compose during transition

This approach ensures:

  • Minimal risk during migration
  • Continuous feature delivery
  • Progressive UI improvement
5. Adapt to Hybrid-Activity Architecture

I plan to reduce the no. of Activitys during the whole modularization + migration task, as we'll be writing each feature module from scratch(inspired by existing code).
We can easily replace AboutActivity, NotificationActivity, ProfileActivity with Composable screens and reduce the complexity of launching individual activities for such small screens.

However, some features of the app will need separate Activity classes:

  • UploadActivity: Since we can upload to Wikimedia Commons by sharing images from other apps (like Gallery), we must have an entry point so that a specific Task can be initiated. That's why we have to keep UploadActivity
  • MainActivity: MainActivity is the primary entry point to the app. So, we must keep it.
  • SingleWebViewActivity: I think we should keep this as it will act as an entry point to a browser window, which will be helpful for certain use-cases.
  • Apart from that, we can consider removing other Activity classes unless there's a very specific reason to have it.
6. UI Events & State Management

To ensure predictable and maintainable UI behavior, the project will follow a Unidirectional Data Flow (UDF) approach using ViewModel + StateFlow.

  • UI State:
    • Represented using data classes that define the current state of the screen
    • Stored inside the ViewModel and exposed via StateFlow
  • UI Events:
    • Defined using sealed classes/interfaces representing user actions
    • Handled inside the ViewModel using when expressions
  • State Handling:
    • The ViewModel acts as the single source of truth
    • UI observes state changes and updates accordingly
  • For simpler screens, where defining separate event/state classes may be unnecessary, a lightweight approach will be used by directly exposing state through StateFlow.

Screenshot 2026-03-28 at 7.54.06 PM.png (1×1 px, 437 KB)

This approach ensures:

  • Better separation of concerns
  • Improved testability
  • Lifecycle-aware and predictable UI updates
7. Validation & Optimization
  • Add and refactor unit tests and UI (Compose) tests for migrated features
  • Perform regression testing after each major migration phase
  • Optimize module dependencies to avoid unnecessary coupling
  • Remove unused legacy code (XML layouts, Activities) after migration
  • Document architectural decisions and migration guidelines for future contributors
Timeline
PeriodTask
May 1 – May 24Community Bonding Period: Finalize modularization + migration approach with mentors, complete ongoing Compose migration (Image Selector), and identify module boundaries & priorities.
May 25Coding officially begins!
May 25 – Jun 14Project Setup + Auth Module: Set up build-logic, initialize core modules, create feature:auth, migrate login & tutorial UI to Compose, and establish hybrid navigation strategy.
Jun 15 – Jun 28Contributions Module: Extract feature:contributions, migrate key screens (UploadProgress, MediaDetail, etc.) to Compose, refactor to MVVM, and stabilize with testing.
Jun 29 – Jul 5Nearby Module (Phase 1): Extract feature:nearby, move data layer components, begin Compose migration (bottom sheet, search UI), and perform testing.
Jul 6 – Jul 10Midterm Evaluation: Stabilization, regression testing, and incorporation of mentor feedback.
Jul 11Post-midterm development begins
Jul 11 – Jul 25Upload Module: Extract feature:upload, migrate upload flow screens to Compose, refactor architecture (MVVM + MVI), and ensure end-to-end stability.
Jul 26 – Aug 1Explore + Bookmarks Modules: Extract feature:explore and feature:bookmarks, migrate key tabs (Featured, Map, etc.) to Compose, and refactor related logic.
Aug 2 – Aug 8Profile Module: Extract feature:profile, migrate profile, achievements, and leaderboard screens to Compose, and ensure integration across modules.
Aug 9 – Aug 16Finalization (Last Week): Remove legacy XML/Activities, optimize modules, complete testing, and finalize documentation.
Aug 17 – Aug 24Final Submission Period: Submit final work product and mentor evaluation.
Aug 24 to Aug 31Mentors submit final GSoC contributor evaluations (standard coding period)
Breakdown

Bonding Period(May 1 - May 24)

  • Finish my existing Custom Image Selector Migration to Jetpack Compose PR and extract it into a feature module
  • Finalize module boundaries (core, feature-*, build-logic) with mentor feedback
  • Study existing navigation, DI setup, and identify migration priorities

Week 1(May 25 - May 31)

  • Set up build-logic module with Convention Plugins for:
    • Kotlin, Compose, Hilt, Retrofit, Room, etc.
  • Create initial core module with:
    • core:network, core:database, core:di (basic setup)
  • Set up a shared :testing module for common test utilities

Note: The core module will be iteratively improved throughout the project

Week 2(Jun 1 - Jun 7)

  • Create feature:auth module with proper layering (ui, domain, data)
  • Revamp LoginActivity UI to a Composable Screen based on design as discussed here.
  • Create auth response, and error models as well as set up AuthenticationApi, renamed from LoginInterface.
  • Since auth-related screens will be re-created in Jetpack Compose and hosted on LoginActivity, we can use Compose Navigation for the auth flow.
  • Move existing tests from app module to the corresponding :auth module and refactor accordingly
  • The tutorial screens will be created in Jetpack Compose and will be placed inside the :auth module initially

Week 3(Jun 8 - Jun 14)

  • Extract the bottom navigation setup from MainActivity into the app module for fragment-based navigation
  • This navigation setup will be used until all XLM layouts (Fragments) have been replaced with Composable Screens and later will be migrated to Navigation 3 library
  • Finish any pending work for feature:auth feature module, otherwise start working on feature:contributions module

Week 4(Jun 15 - Jun 21)

  • Continue work on feature:contributions module
  • Start migrating key components:
    • UploadProgressActivity, MoreBottomSheetFragment, MediaDetailFragment, etc., → Jetpack Compose
  • Ensure interoperability between XML and Compose screens
  • Move and refactor related tests to :contributions module and begin writing UI tests

Week 5(Jun 22 - Jun 28)

  • Finish the work on feature:contributions module and migrate NearbyNotificationCardView to Jetpack Compose
  • Start working on feature:nearby module and create NearbyActivity to host nearby feature related screens
  • Replace NotificationActivity with a composable screen and refactor code

Week 6(Jun 29 - Jul 5)

  • Move data layer components, like PlacesDao, PlacesRepository, etc., to :nearby module
  • Begin UI migration of Nearby Bottom Sheet, Search UI, etc., to Jetpack Compose
  • Thoroughly test the work done so far and prepare for the mid-term evaluation of project

Week 7(Jul 6 - Jul 10) Mid-term Evaludation Period

  • Complete pending work (if any) in :nearby module
  • Incorporate feedback from mentors and improve execution

Week 8(Jul 11 - Jul 18)

  • Create feature:upload module and start extracting upload-related logic and UI
  • We'll keep UploadActivity as it is an entry point to the Commons App
  • Migrate DepictsPickerActivity, UploadCategoriesFragment, MediaLicenseFragment, etc., to Jetpack Compose

Week 9(Jul 19- Jul 25)

  • Continue the work on feature:upload module and ensure consistent results after migrations
  • Refactor code to follow MVVM + MVI pattern and move related tests to this module
  • May need to refactor UploadWorker to extract unrelated logic to separate files

Week 10(Jul 26- Aug 1)

  • Create feature:explore module for Explore feature and identify related files for migration
  • Migrate Featured, Uploaded by Mobile, and Map tabs to Jetpack Compose
  • Extract Bookmarks feature to a separate feature:bookmarks module

Week 11(Aug 2- Aug 8)

  • Complete the feature:bookmarks module and migrate to Jetpack Compose
  • Create feature:profile module and replace ProfileActivity with composable screens
  • Migrate Achievements and Leaderboard tabs to Jetpack Compose and refactor
  • Ensure proper integration within the app module and write UI/Instrumentation tests

[Final Week] Week 12(Aug 9- Aug 16)

  • Remove unused legacy code (XML, Activities where replaced) and clean app module
  • Make sure to remove any redundant files and dependencies before project submission
  • If time allows:
    • Move review and settings package to corresponding modules and refactor code
    • Replace SettingsActivity and ReviewActivity with composable screens

About Me

My name is Rohit, and I'm a Mobile App Developer specializing in Android. I've completed my Bachelor of Technology in Computer Science & Engineering from Babu Banarasi Das Institute of Technology, Ghaziabad in 2025.

How did I hear about this program?

I heard about this program in my 2nd year of college(2023) as I was searching "How can I improve my resume and work on real-world projects?". At the same time, I found the Wikimedia Commons app repository and wanted to contribute. But I barely had any development experience, and it required Android skills.
So, I spent another year learning Android App Development along with my college and started contributing to Wikimedia Commons in 2024.

It's been almost 2 years being a part of this project and learning from great mentors :)

Will you have any other time commitments, such as school work, another job, planned vacation, etc, during the duration of the program?

I don't have any other commitments like a job, vacation, college, etc., during the GSoC timeline and can put as many hours as required to complete the project with tasks as mentioned above.

We advise all candidates eligible for Google Summer of Code and Outreachy to apply for both programs. Are you planning to apply to both programs and, if so, with what organization(s)?

I am applying only to the Wikimedia Foundation this year(2026) and don't have plans for other organizations.

What does making this project happen mean to you?

When I started learning Android development, I began with Jetpack Compose and initially thought it would be enough. But while working on real-world codebases and contributing to open source, I realized that many apps still rely on XML-based UI. This project gives me a great opportunity to work with both and contribute to a structured transition towards modern Android development in the Wikimedia Commons app repository.

Through my contributions so far, I’ve become familiar with the Commons app and its challenges. This project allows me to apply that understanding in a practical way and improve the Commons app for both developers and users.
For me, this is not just about completing a GSoC project, but about spending focused time working on something meaningful. At this stage of my career, it’s an important step forward in becoming a better developer while contributing to the open-source community.

Past Experience

Bug Fixes

These are some of my PRs made for the Wikimedia Commons Android app, sorted based on impact:

Sr. No.TitlePR
1Migrated Custom Image Selector to Jetpack Compose#5964 [Draft]
2Fix infinite loading circular progress bar after nominating for deletion#6324
3Bump target sdk to API 35 and make the app UI compatible with edge to edge#6393
4Upgrade to SDK 34#5790
5Prevent deletion of other structured data when editing depicts#5741
6Migrated from Groovy to Kotlin DSL and upgrade AGP version#6322
7fix: status bar icons not visible on view image screen#6572
8fix: allow touch down event to propagate to double tap gesture listener#6573
9chore: upgrade native libraries for 16KB page size compatibility#6445
10Fix: IndexOutOfBoundsException crash when removing last two images of multiupload#6124
11Fix: enable H/W acceleration for UploadActivity to resolve keyboard not showing on Upload Screen#6418
12Fix crash when opening in-app Camera for the very first time#6139

After GSOC

After GSoC, I plan to continue contributing to the Commons Android app by:

  • Improving and extending the modular architecture introduced during the project
  • Possibly create some documentation files for the repository explaining the architecture and best practices to avoid confusion in the future
  • Fixing bugs, reviewing pull requests, and helping maintain code quality

I am also interested in supporting new contributors by sharing my learnings, helping with onboarding, etc.
In the long term, I would like to stay involved with the Wikimedia community and, if possible, contribute as a mentor in future GSoC programs.

Event Timeline

Great Proposal @Rohitverma9625

I plan to reduce the no. of Activitys during the whole modularization + migration task, as we'll be writing each feature module from scratch(inspired by existing code).
We can easily replace AboutActivity, NotificationActivity, ProfileActivity with Composable screens and reduce the complexity of launching individual activities for such small screens.

Nice thoughts 👍

Standardizing Architecture with MVVM + MVI(Optional)

WIll bring this to github discussion on what's great for us MVVM or MVI.

Can you also review the proposal once @Kaartic

Thanks for the review, Neel :)

WIll bring this to github discussion on what's great for us MVVM or MVI.

I thought we could use both approaches combined, unlike MVVM and MVP. Maybe I don't understand MVI completely, but I think handling actions(Intent) via sealed interfaces will definitely benefit the project atleast for most of the features. However, for simple screens, directly exposing public functions from ViewModel would be best. Looking forward to discussing more about it in near future.

Also, please have a look at my proposal @RitikaPahwa4444 and @Kaartic. I'm really sorry for asking for a review on the last day. I hope you understand :)

Hi, thanks for submitting your GSoC 2026 project proposal with Wikimedia!

Please make sure you’ve also submitted your proposal on the official Summer of Code website: https://summerofcode.withgoogle.com. The deadline for both submission and any edits is the same, so ensure everything is finalized before March 31, 18:00 UTC, as changes won’t be possible after that.

We strongly recommend completing any updates at least 30 minutes before the deadline to avoid last-minute glitches or unexpected technical issues.

Wishing you all the best for your application. Hope to see you as part of the program soon! 🚀

Is there any specific format for a GSoC proposal there, or should it look exactly the same, @Gopavasanth?

Hi Rohit,

Sorry for the lack of answer above. Yes, it is fine (and expected) that the GSoC proposal is exactly the same.

It seems like you selected "Project Size: Medium" on the GSoC website.
I know it is confusing, but the template "Expected size of the project: 350 hours" actually translates to "Project Size: Large" on GSoC... the choice affects the stipend amount.

Did you choose that "Medium" value on purpose, for instance because you have less time available than required for "Large"?
I don't know whether that can be modified, but if it can, do you want to switch to "Large"?
Thank you!

Hi @Nicolas_Raoul,

I'm so sorry, I didn't receive the notification of this. Yes, it was confusing that 350 hours were supposed to be a large project, but were listed as Medium on the Wikimedia Idea list; that's why I chose the same on the GSoC website. I'm fine with switching project size to Large if possible, but I don't think this project should extend to November 2026 for completion. That will be more time than required.

I'd love to know your thoughts about this :)

Nice proposal, @Rohitverma9625

I suppose the timeline is a bit ambitious, though. Its almost trying to wrap up modularization of all modules within GSoC. One thing I wanted to mention specifically:

Note: All this modularization + migration work has been done in a different branch, for eg, refactor/migrate-to-jetpack.

It seems the plan is to do modularization in a long living feature branch and merge it once its fully complete. This may not be an ideal thing to do as this would result in a take-all or none situation. It is better to take the refactoring part by part such that the core modules are extracted and used by the existing code. We could then merge in the corresponding parts within main branch and proceed further on the migration. This would ensure we don't totally diverge away and face issues when merging in the changes.

Thanks for the review @Kaartic

I suppose the timeline is a bit ambitious, though. Its almost trying to wrap up modularization of all modules within GSoC.

Yes, I believe some modules are so small that they won't take more than 2 days.

It seems the plan is to do modularization in a long living feature branch and merge it once its fully complete. This may not be an ideal thing to do as this would result in a take-all or none situation. It is better to take the refactoring part by part such that the core modules are extracted and used by the existing code. We could then merge in the corresponding parts within main branch and proceed further on the migration. This would ensure we don't totally diverge away and face issues when merging in the changes.

That totally makes sense. I thought that doing this task in a separate branch is a best practice, but your concern is 100% correct, and I agree with merging PRs directly into the main branch.

That totally makes sense. I thought that doing this task in a separate branch is a best practice, but your concern is 100% correct, and I agree with merging PRs directly into the main branch.

It is even more crucial to merge it earlier since we'll have another GSoC project going on in parallel. So, as much as we delay merge, the more code churn there would be when trying to merge this in.

Got it. I think the other project, i.e., Implement lossless JPG transformations, would be related to one or two modules. So, I'm expecting fewer critical merge conflicts as long as the other project follows best practices and the suggested architecture. However, this project would require more PRs to be merged and fewer for the other project. That's why other contributor needs to timely pull from the main branch to avoid conflicts later.

Also, we'll avoid delaying the tasks for sure :)

Hi, thank you for your submission and the effort you put into your proposal. This year we received over 380 strong applications, and unfortunately we were not able to offer you a slot. This was a very competitive process, and many high quality proposals could not be selected. We truly encourage you to stay engaged and continue contributing to Wikimedia projects. Over the years, many contributors who were not selected for Google Summer of Code have gone on to make impactful contributions and become long term members of the community. Please do not see this as a failure, but as a step forward in your journey. We would love to stay in touch and support your continued involvement.

If you would like guidance on how to contribute to our projects outside GSoC, feel free to reach out to any of the mentors or org admins, they will be happy to help you get started.

You can get started or continue contributing here:

We hope to see your contributions in our community soon.