Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor shortcuts deep linking #2456

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package au.com.shiftyjelly.pocketcasts.deeplink

import android.content.Intent
import android.content.Intent.ACTION_VIEW
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
Expand Down Expand Up @@ -187,4 +188,49 @@ class DeepLinkFactoryTest {

assertEquals(ShowEpisodeDeepLink("Episode ID", "Podcast ID", sourceView = null), deepLink)
}

@Test
fun showPodcasts() {
val intent = Intent()
.setAction(ACTION_VIEW)
.putExtra("launch-page", "podcasts")

val deepLink = factory.create(intent)

assertEquals(ShowPodcastsDeepLink, deepLink)
}

@Test
fun showDiscover() {
val intent = Intent()
.setAction(ACTION_VIEW)
.putExtra("launch-page", "search")

val deepLink = factory.create(intent)

assertEquals(ShowDiscoverDeepLink, deepLink)
}

@Test
fun showUpNext() {
val intent = Intent()
.setAction(ACTION_VIEW)
.putExtra("launch-page", "upnext")

val deepLink = factory.create(intent)

assertEquals(ShowUpNextDeepLink, deepLink)
}

@Test
fun showFilter() {
val intent = Intent()
.setAction(ACTION_VIEW)
.putExtra("launch-page", "playlist")
.putExtra("playlist-id", 10L)

val deepLink = factory.create(intent)

assertEquals(ShowFilterDeepLink(filterId = 10), deepLink)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package au.com.shiftyjelly.pocketcasts.deeplink

import android.content.Intent.ACTION_VIEW
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class ShowPageDeepLinkTest {
private val context = InstrumentationRegistry.getInstrumentation().context

@Test
fun createShowPodcastsIntent() {
val intent = ShowPodcastsDeepLink.toIntent(context)

assertEquals(ACTION_VIEW, intent.action)
assertEquals("podcasts", intent.getStringExtra("launch-page"))
}

@Test
fun createShowDiscoverIntent() {
val intent = ShowDiscoverDeepLink.toIntent(context)

assertEquals(ACTION_VIEW, intent.action)
assertEquals("search", intent.getStringExtra("launch-page"))
}

@Test
fun createShowUpNextIntent() {
val intent = ShowUpNextDeepLink.toIntent(context)

assertEquals(ACTION_VIEW, intent.action)
assertEquals("upnext", intent.getStringExtra("launch-page"))
}

@Test
fun createShowFilterIntent() {
val intent = ShowFilterDeepLink(filterId = 15L).toIntent(context)

assertEquals(ACTION_VIEW, intent.action)
assertEquals("playlist", intent.getStringExtra("launch-page"))
assertEquals(15L, intent.getLongExtra("playlist-id", -1L))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,17 @@ import au.com.shiftyjelly.pocketcasts.analytics.SourceView
import au.com.shiftyjelly.pocketcasts.databinding.ActivityMainBinding
import au.com.shiftyjelly.pocketcasts.deeplink.AddBookmarkDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ChangeBookmarkTitleDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_PAGE
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLinkFactory
import au.com.shiftyjelly.pocketcasts.deeplink.DeleteBookmarkDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.DownloadsDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowBookmarkDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowDiscoverDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowEpisodeDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowFilterDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowPodcastDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowPodcastsDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowUpNextDeepLink
import au.com.shiftyjelly.pocketcasts.discover.view.DiscoverFragment
import au.com.shiftyjelly.pocketcasts.endofyear.StoriesFragment
import au.com.shiftyjelly.pocketcasts.endofyear.StoriesFragment.StoriesSource
Expand Down Expand Up @@ -104,8 +109,6 @@ import au.com.shiftyjelly.pocketcasts.repositories.podcast.PodcastManager
import au.com.shiftyjelly.pocketcasts.repositories.podcast.UserEpisodeManager
import au.com.shiftyjelly.pocketcasts.repositories.refresh.RefreshPodcastsTask
import au.com.shiftyjelly.pocketcasts.repositories.shortcuts.PocketCastsShortcuts
import au.com.shiftyjelly.pocketcasts.repositories.shortcuts.PocketCastsShortcuts.INTENT_EXTRA_PAGE
import au.com.shiftyjelly.pocketcasts.repositories.shortcuts.PocketCastsShortcuts.INTENT_EXTRA_PLAYLIST_ID
import au.com.shiftyjelly.pocketcasts.repositories.subscription.SubscriptionManager
import au.com.shiftyjelly.pocketcasts.repositories.sync.SyncManager
import au.com.shiftyjelly.pocketcasts.search.SearchFragment
Expand Down Expand Up @@ -968,8 +971,8 @@ class MainActivity :
settings.updateBottomInset(miniPlayerHeight)

// Handle up next shortcut
if (intent.getStringExtra(INTENT_EXTRA_PAGE) == "upnext") {
intent.putExtra(INTENT_EXTRA_PAGE, null as String?)
if (intent.getStringExtra(EXTRA_PAGE) == ShowUpNextDeepLink.pageId) {
intent.removeExtra(EXTRA_PAGE)
binding.playerBottomSheet.openPlayer()
showUpNextFragment(UpNextSource.UP_NEXT_SHORTCUT)
}
Expand Down Expand Up @@ -1266,32 +1269,31 @@ class MainActivity :
forceDark = false,
)
}
}
} else if (action == Intent.ACTION_VIEW) {
val extraPage = intent.extras?.getString(INTENT_EXTRA_PAGE, null)
if (extraPage != null) {
when (extraPage) {
"podcasts" -> openTab(VR.id.navigation_podcasts)
"search" -> openTab(VR.id.navigation_discover)
"playlist" -> {
val playlistId = intent.extras?.getLong(INTENT_EXTRA_PLAYLIST_ID, -1)
?: -1
launch(Dispatchers.Default) {
playlistManager.findById(playlistId)?.let {
withContext(Dispatchers.Main) {
settings.setSelectedFilter(it.uuid)

// HACK: Go diving to find if a filter fragment
openTab(VR.id.navigation_filters)
val filtersFragment =
supportFragmentManager.fragments.find { it is FiltersFragment } as? FiltersFragment
filtersFragment?.openPlaylist(it)
}
is ShowPodcastsDeepLink -> {
openTab(VR.id.navigation_podcasts)
}
is ShowDiscoverDeepLink -> {
openTab(VR.id.navigation_discover)
}
is ShowUpNextDeepLink -> {
// Do nothig, handled in onMiniPlayerVisible()
}
is ShowFilterDeepLink -> {
launch(Dispatchers.Default) {
playlistManager.findById(deepLink.filterId)?.let {
withContext(Dispatchers.Main) {
settings.setSelectedFilter(it.uuid)
// HACK: Go diving to find if a filter fragment
openTab(VR.id.navigation_filters)
val filtersFragment = supportFragmentManager.fragments.find { it is FiltersFragment } as? FiltersFragment
filtersFragment?.openPlaylist(it)
}
}
}
}
} else if (IntentUtil.isPocketCastsWebsite(intent)) {
}
} else if (action == Intent.ACTION_VIEW) {
if (IntentUtil.isPocketCastsWebsite(intent)) {
// when the user goes to https://pocketcasts.com/get it should either open the play store or the user's app
return
} else if (IntentUtil.isPodloveUrl(intent)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package au.com.shiftyjelly.pocketcasts.deeplink

import android.content.Context
import android.content.Intent
import android.content.Intent.ACTION_VIEW
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_ADD_BOOKMARK
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_BOOKMARK
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_CHANGE_BOOKMARK_TITLE
Expand All @@ -11,7 +12,9 @@ import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_EP
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_PODCAST
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_BOOKMARK_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_EPISODE_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_FILTER_ID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_NOTIFICATION_TAG
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_PAGE
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_PODCAST_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_SOURCE_VIEW

Expand All @@ -32,6 +35,8 @@ sealed interface DeepLink {
const val EXTRA_EPISODE_UUID = "episode_uuid"
const val EXTRA_SOURCE_VIEW = "source_view"
const val EXTRA_NOTIFICATION_TAG = "NOTIFICATION_TAG"
const val EXTRA_PAGE = "launch-page"
const val EXTRA_FILTER_ID = "playlist-id"
}
}

Expand Down Expand Up @@ -96,6 +101,35 @@ data class ShowEpisodeDeepLink(
.putExtra(EXTRA_SOURCE_VIEW, sourceView)
}

sealed interface ShowPageDeepLink : DeepLink {
val pageId: String

override fun toIntent(context: Context) = context.launcherIntent
.setAction(ACTION_VIEW)
.putExtra(EXTRA_PAGE, pageId)
}

data object ShowPodcastsDeepLink : ShowPageDeepLink {
override val pageId = "podcasts"
}

data object ShowDiscoverDeepLink : ShowPageDeepLink {
override val pageId = "search"
}

data object ShowUpNextDeepLink : ShowPageDeepLink {
override val pageId = "upnext"
}

data class ShowFilterDeepLink(
val filterId: Long,
) : ShowPageDeepLink {
override val pageId = "playlist"

override fun toIntent(context: Context) = super.toIntent(context)
.putExtra(EXTRA_FILTER_ID, filterId)
}

private val Context.launcherIntent get() = requireNotNull(packageManager.getLaunchIntentForPackage(packageName)) {
"Missing launcher intent for $packageName"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package au.com.shiftyjelly.pocketcasts.deeplink

import android.content.Intent
import android.content.Intent.ACTION_VIEW
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_ADD_BOOKMARK
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_BOOKMARK
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_CHANGE_BOOKMARK_TITLE
Expand All @@ -10,6 +11,8 @@ import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_EP
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.ACTION_OPEN_PODCAST
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_BOOKMARK_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_EPISODE_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_FILTER_ID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_PAGE
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_PODCAST_UUID
import au.com.shiftyjelly.pocketcasts.deeplink.DeepLink.Companion.EXTRA_SOURCE_VIEW
import timber.log.Timber
Expand All @@ -23,6 +26,7 @@ class DeepLinkFactory {
DeleteBookmarkAdapter(),
ShowPodcastAdapter(),
ShowEpisodeAdapter(),
ShowPageAdapter(),
)

fun create(intent: Intent): DeepLink? {
Expand Down Expand Up @@ -125,3 +129,17 @@ private class ShowEpisodeAdapter : DeepLinkAdapter {
private val ACTION_REGEX = ("^" + ACTION_OPEN_EPISODE + """\d*$""").toRegex()
}
}

private class ShowPageAdapter : DeepLinkAdapter {
override fun create(intent: Intent) = if (intent.action == ACTION_VIEW) {
when (intent.getStringExtra(EXTRA_PAGE)) {
"podcasts" -> ShowPodcastsDeepLink
"search" -> ShowDiscoverDeepLink
"upnext" -> ShowUpNextDeepLink
"playlist" -> ShowFilterDeepLink(filterId = intent.getLongExtra(EXTRA_FILTER_ID, -1))
else -> null
}
} else {
null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package au.com.shiftyjelly.pocketcasts.repositories.shortcuts

import android.annotation.TargetApi
import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.os.Build
import au.com.shiftyjelly.pocketcasts.deeplink.ShowFilterDeepLink
import au.com.shiftyjelly.pocketcasts.repositories.extensions.shortcutDrawableId
import au.com.shiftyjelly.pocketcasts.repositories.podcast.PlaylistManager
import au.com.shiftyjelly.pocketcasts.utils.log.LogBuffer
Expand All @@ -15,10 +15,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object PocketCastsShortcuts {

const val INTENT_EXTRA_PAGE = "launch-page"
const val INTENT_EXTRA_PLAYLIST_ID = "playlist-id"

/**
* Icon shortcuts
* - Podcasts
Expand Down Expand Up @@ -51,10 +47,8 @@ object PocketCastsShortcuts {
LogBuffer.i(PocketCastsShortcuts::class.java.simpleName, "Shortcut update from ${source.value}, top filter title: ${topPlaylist.title}")

if (shortcutManager.dynamicShortcuts.isEmpty() || force) {
val filterIntent = context.packageManager.getLaunchIntentForPackage(context.packageName) ?: return@launch
filterIntent.action = Intent.ACTION_VIEW
filterIntent.putExtra(INTENT_EXTRA_PAGE, "playlist")
filterIntent.putExtra(INTENT_EXTRA_PLAYLIST_ID, topPlaylist.id)
val filterId = topPlaylist.id ?: return@launch
val filterIntent = ShowFilterDeepLink(filterId).toIntent(context)

val playlistTitle = topPlaylist.title.ifEmpty { "Top filter" }

Expand Down
Loading