Skip to content

Conversation

@tonyteate
Copy link
Contributor

@tonyteate tonyteate commented Dec 8, 2025

📲 What

Re-enable support for Discover deep links

🤔 Why

The initial introduction of a Splash Screen in #2443 removed support for Discover deep links, which were originally supported by DiscoveryActivity via Intent Filter, but only for the ksr:// scheme. Here we re-enable support for Discover deep links (and app links), through the splash screen, for both the ksr:// and https:// schemes.

🛠 How

Update the Intent-processing logic in SplashScreenViewModel to filter for Discover URLs via regex and emit an Optional<Uri>. When present, a new instance of DiscoveryActivity is launched with action.VIEW and the Uri as Data; when empty, delegate to the existing logic for starting a new DiscoveryActivity (with action.MAIN).

DiscoveryViewModel already knows how to handle these Intents, including parsing and transforming Uris into DiscoveryParams. To help mitigate the existing possibility of race condition between handling DiscoveryParams and rendering the ViewPager with the correct tab selected, we update DiscoveryActivity to call provideIntent() only after a first-pass render of the view tree has completed.

👀 See

Before 🐛

Screen_recording_20251208_124014.mp4

After 🦋 |

Screen_recording_20251208_124319.mp4

📋 QA

Setup

  • Precondition: Fresh install of the app, unopened.
  • Launch the app from the Home Screen or App Drawer (or Android Studio)
  • Result:
    • The system navigates to Discover and immediately displays Onboarding
  • Step through Onboarding to enable Personalization and enable Push Notifications, then click
    'Explore the app'
  • Terminate the app
  • Go to app Settings (long press the app icon and select 'App info')
  • Click 'Open by default'
  • Click 'Add link'
  • Select both *.kickstarter.com and www.kickstarter.com
  • Click 'Add'
  • Results:
    • 'In the app' should be selected
    • Under 'Links to open in this app', one label reads '0 verified links', but both options underneath
      are selected.

Discover Category via App Link

  • Open the app (will also work if the app is terminated)
  • Open Chrome
  • Search in Google: "https://www.kickstarter.com/discover/categories/journalism"
  • Click the first result for "Discover » Journalism" pointing to
    https://www.kickstarter.com › discover › categories › journalism
  • Results:
    • The system should navigate to a new Discover screen filtered to the "Journalism" Category

Discover Category via Banner Deep Link

  • Open the app (will also work if the app is terminated)
  • Open Chrome
  • Visit https://www.kickstarter.com
  • Click any Category in the top-left corner
  • Click the 'Open' button in the app banner (which uses the ksr:// scheme)
  • Results:
    • The system should navigate to a new Discover screen filtered to the selected Category

Discover Sort via ADB

  • Open the app (will also work if the app is terminated)

  • Run the following command to simulate opening an LCM deep link to a sorted Discover

    adb shell 'am start -a android.intent.action.VIEW -d "https://www.kickstarter.com/discover/advanced?sort=newest" com.kickstarter.kickstarter.internal.debug'
    
  • Results:

    • The system should navigate to a new Discover screen for All Projects sorted by Newest

Story 📖

[MBL-2851] [Fast Follow] Support LCM deep links to Discover - Jira

@codecov-commenter
Copy link

codecov-commenter commented Dec 8, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.27%. Comparing base (5d3a87b) to head (b1b1def).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff            @@
##             master    #2456   +/-   ##
=========================================
  Coverage     64.27%   64.27%           
- Complexity     2403     2405    +2     
=========================================
  Files           378      378           
  Lines         28744    28754   +10     
  Branches       4145     4147    +2     
=========================================
+ Hits          18474    18483    +9     
  Misses         8011     8011           
- Partials       2259     2260    +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tonyteate tonyteate marked this pull request as ready for review December 8, 2025 17:46
Copy link
Contributor

@ycheng-kickstarter ycheng-kickstarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked great, just make sure to actually ticket the todos lest they be forgotten forever

fun testUri_isDiscoverUri() {
val discoverBaseUri1 = Uri.parse("https://www.ksr.com/discover")
val discoverBaseUri2 = Uri.parse("https://www.ksr.com/discover/")
val discoverScopeUri = Uri.parse("https://www.ksr.com/discover/ending-soon")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question about the url of these tests 🤔 , in which scenario do we see something like https://www.ksr.com/discover were the domain is www.ksr.com?
ksr is used as schema instead of https but never saw it as domain

Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question. For flexibility, isDiscoverUri() follows a pattern in similar parts of UriExt by calling isKickstarterUri(webEndpoint) in its implementation. So in the test case we also follow the pattern of using in the top-level webEndpoint variable defined in the test suite (L72), which is set to "https://www.ksr.com".

binding.root.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
binding.root.viewTreeObserver.removeOnGlobalLayoutListener(this)
viewModel.provideIntent(intent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💖

@tonyteate tonyteate merged commit 215c91c into master Jan 7, 2026
3 checks passed
@tonyteate tonyteate deleted the tony/mbl-2851 branch January 7, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants