Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
Deep link support
Full Scope: https://github.com/Automattic/wordpress-mobile/issues/47
Design: [IqhXWz3Iir7RMb5XH5gGfZ-fi-883%3A4006](https://href.li/?https://www.figma.com/file/IqhXWz3Iir7RMb5XH5gGfZ/?node-id=883%3A4006)

- Deep link to Subscribers tab
- Deep link to Traffic tab with appropriate granularity selected


Discussion hints:
Thanks for reporting! 👍 <!-- generated_by_dangermattic -->


Pull request: "stats/subscribers" deeplink
Fixes #20691 

This makes `site` parameter optional in the stats deeplink and adds support for "jetpack://stats/subscribers" deeplink.

|deeplink|description|
|-|-|
|jetpack://stats|opens the latest tab from stats|
|jetpack://stats/insights|opens the INSIGHTS tab|
|jetpack://stats/day|opens the TRAFFIC tab and Days granularity|
|jetpack://stats/week|opens the TRAFFIC tab and Weeks granularity|
|jetpack://stats/month|opens the TRAFFIC tab and Months granularity|
|jetpack://stats/year|opens the TRAFFIC tab and Years granularity|
|jetpack://stats/irfanotest.wordpress.com|if you add /{siteAdress} to any deeplink, it opens stats for that site|

https://github.com/wordpress-mobile/WordPress-Android/assets/2471769/7f379c4e-5608-4473-9ff5-8b51ef9ded75

-----

## To Test:

<!-- Test instructions per dependency update: https://github.com/wordpress-mobile/WordPress-Android/blob/trunk/docs/test_instructions_per_dependency_update.md -->

You can use an online HTML editor or any other method you prefer to test deeplinks.

-----

## Regression Notes

1. Potential unintended areas of impact

    - None

2. What I did to test those areas of impact (or what existing automated tests I relied on)

    - N/A

3. What automated tests I added (or what prevented me from doing so)

    - Updated `StatsLinkHandlerTest`

-----

## PR Submission Checklist:

- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

-----

## Testing Checklist (strike-out the not-applying and unnecessary ones):

- [ ] ~WordPress.com sites and self-hosted Jetpack sites.~
- [ ] ~Portrait and landscape orientations.~
- [ ] ~Light and dark modes.~
- [ ] ~Fonts: Larger, smaller and bold text.~
- [ ] ~High contrast.~
- [ ] ~Talkback.~
- [ ] ~Languages with large words or with letters/accents not frequently used in English.~
- [ ] ~Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)~
- [ ] ~Large and small screen sizes. (Tablet and smaller phones)~
- [ ] ~Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)~


Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.deeplinks.handlers.StatsLinkHandlerTest"

Fix patch:
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index ca376cca8b49..70f9185bdb38 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -2,7 +2,7 @@
 
 24.9
 -----
-
+* [***] [Jetpack-only] Reorganized Stats to include updated Traffic and Insights tabs, along with a newly added Subscribers tab to improve subscriber metrics analysis [https://github.com/wordpress-mobile/WordPress-Android/pull/20756]
 
 24.8
 -----
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandler.kt
index ceed1dbb5b12..c083f900c464 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandler.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandler.kt
@@ -2,11 +2,11 @@ package org.wordpress.android.ui.deeplinks.handlers
 
 import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction
+import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenJetpackStaticPosterView
 import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenStats
 import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenStatsForSite
 import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenStatsForSiteAndTimeframe
 import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenStatsForTimeframe
-import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenJetpackStaticPosterView
 import org.wordpress.android.ui.deeplinks.DeepLinkUriUtils
 import org.wordpress.android.ui.deeplinks.DeepLinkingIntentReceiverViewModel.Companion.APPLINK_SCHEME
 import org.wordpress.android.ui.deeplinks.DeepLinkingIntentReceiverViewModel.Companion.HOST_WORDPRESS_COM
@@ -32,7 +32,8 @@ class StatsLinkHandler
         val pathSegments = uri.pathSegments
         val length = pathSegments.size
         val site = pathSegments.getOrNull(length - 1)?.toSite()
-        val statsTimeframe = pathSegments.getOrNull(length - 2)?.toStatsTimeframe()
+        val timeframeIndex = if (site == null) (length - 1) else (length - 2)
+        val statsTimeframe = pathSegments.getOrNull(timeframeIndex)?.toStatsTimeframe()
         return when {
             jetpackFeatureRemovalPhaseHelper.shouldShowStaticPage() -> OpenJetpackStaticPosterView
             site != null && statsTimeframe != null -> {
@@ -98,6 +99,7 @@ class StatsLinkHandler
             "month" -> StatsTimeframe.MONTH
             "year" -> StatsTimeframe.YEAR
             "insights" -> StatsTimeframe.INSIGHTS
+            "subscribers" -> StatsTimeframe.SUBSCRIBERS
             else -> null
         }
     }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
index 915d8637eb93..faabf6c0f856 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/StatsFragment.kt
@@ -19,6 +19,7 @@ import dagger.hilt.android.AndroidEntryPoint
 import org.wordpress.android.R
 import org.wordpress.android.WordPress
 import org.wordpress.android.databinding.StatsFragmentBinding
+import org.wordpress.android.models.JetpackPoweredScreen
 import org.wordpress.android.ui.ScrollableViewInitializedListener
 import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureFullScreenOverlayFragment
 import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil.JetpackFeatureOverlayScreenType
@@ -38,13 +39,12 @@ import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSect
 import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.TOTAL_COMMENTS_DETAIL
 import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.TOTAL_FOLLOWERS_DETAIL
 import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.TOTAL_LIKES_DETAIL
+import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.TRAFFIC
 import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.WEEKS
 import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.YEARS
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider.SiteUpdateResult
 import org.wordpress.android.ui.utils.UiHelpers
 import org.wordpress.android.util.JetpackBrandingUtils
-import org.wordpress.android.models.JetpackPoweredScreen
-import org.wordpress.android.ui.stats.refresh.lists.StatsListViewModel.StatsSection.TRAFFIC
 import org.wordpress.android.util.WPSwipeToRefreshHelper
 import org.wordpress.android.util.config.StatsTrafficSubscribersTabFeatureConfig
 import org.wordpress.android.util.helpers.SwipeToRefreshHelper
@@ -224,10 +224,7 @@ class StatsFragment : Fragment(R.layout.stats_fragment), ScrollableViewInitializ
         }
     }
 
-    @Suppress("MagicNumber")
-    private fun StatsFragmentBinding.handleSelectedSectionWithTrafficTab(
-        selectedSection: StatsSection
-    ) {
+    private fun StatsFragmentBinding.handleSelectedSectionWithTrafficTab(selectedSection: StatsSection) {
         val position = when (selectedSection) {
             TRAFFIC -> 0
             INSIGHTS -> 1
@@ -243,16 +240,14 @@ class StatsFragment : Fragment(R.layout.stats_fragment), ScrollableViewInitializ
         position?.let {
             if (statsPager.currentItem != position) {
                 tabLayout.removeOnTabSelectedListener(selectedTabListener)
-                statsPager.setCurrentItem(position, false)
+                statsPager.currentItem = position
                 tabLayout.addOnTabSelectedListener(selectedTabListener)
             }
         }
     }
 
     @Suppress("MagicNumber")
-    private fun StatsFragmentBinding.handleSelectedSection(
-        selectedSection: StatsSection
-    ) {
+    private fun StatsFragmentBinding.handleSelectedSection(selectedSection: StatsSection) {
         val position = when (selectedSection) {
             INSIGHTS -> 0
             DAYS -> 1
@@ -270,7 +265,7 @@ class StatsFragment : Fragment(R.layout.stats_fragment), ScrollableViewInitializ
         position?.let {
             if (statsPager.currentItem != position) {
                 tabLayout.removeOnTabSelectedListener(selectedTabListener)
-                statsPager.setCurrentItem(position, false)
+                statsPager.currentItem = position
                 tabLayout.addOnTabSelectedListener(selectedTabListener)
             }
         }


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandlerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandlerTest.kt
index 1c6984ff5c9d..35fa892d67c7 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandlerTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/deeplinks/handlers/StatsLinkHandlerTest.kt
@@ -15,6 +15,7 @@ import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper
 import org.wordpress.android.ui.stats.StatsTimeframe.DAY
 import org.wordpress.android.ui.stats.StatsTimeframe.INSIGHTS
 import org.wordpress.android.ui.stats.StatsTimeframe.MONTH
+import org.wordpress.android.ui.stats.StatsTimeframe.SUBSCRIBERS
 import org.wordpress.android.ui.stats.StatsTimeframe.WEEK
 import org.wordpress.android.ui.stats.StatsTimeframe.YEAR
 
@@ -108,7 +109,8 @@ class StatsLinkHandlerTest {
             "week" to WEEK,
             "month" to MONTH,
             "year" to YEAR,
-            "insights" to INSIGHTS
+            "insights" to INSIGHTS,
+            "subscribers" to SUBSCRIBERS
         )
         timeframes.forEach { (key, timeframe) ->
             val uri = buildUri(host = null, "stats", key, siteUrl)
@@ -125,6 +127,25 @@ class StatsLinkHandlerTest {
         }
     }
 
+    @Test
+    fun `opens stats screen for a stats timeframe and no site present in URL`() {
+        val timeframes = mapOf(
+            "day" to DAY,
+            "week" to WEEK,
+            "month" to MONTH,
+            "year" to YEAR,
+            "insights" to INSIGHTS,
+            "subscribers" to SUBSCRIBERS
+        )
+        timeframes.forEach { (key, timeframe) ->
+            val uri = buildUri(host = null, "stats", key)
+
+            val buildNavigateAction = statsLinkHandler.buildNavigateAction(uri)
+
+            assertThat(buildNavigateAction).isEqualTo(NavigateAction.OpenStatsForTimeframe(timeframe))
+        }
+    }
+
     @Test
     fun `opens stats screen for a site when timeframe not valid`() {
         val siteUrl = "example.com"