Skip to content

Commit

Permalink
Refactor Podlove podcast deep linking (#2460)
Browse files Browse the repository at this point in the history
  • Loading branch information
MiSikora committed Jul 10, 2024
1 parent 1d4cde0 commit 99e00e6
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,81 @@ class DeepLinkFactoryTest {

assertEquals(PocketCastsWebsiteDeepLink, deepLink)
}

@Test
fun podloveHttps() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribehttps/mypodcast.com/rss/123"))

val deepLink = factory.create(intent)

assertEquals(ShowPodcastFromUrlDeepLink("https://mypodcast.com/rss/123"), deepLink)
}

@Test
fun podloveHttpsWithParams() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribehttps/mypodcast.com/rss/123?someKey=someValue"))

val deepLink = factory.create(intent)

assertEquals(ShowPodcastFromUrlDeepLink("https://mypodcast.com/rss/123?someKey=someValue"), deepLink)
}

@Test
fun podloveHttp() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribe/mypodcast.com/rss/123"))

val deepLink = factory.create(intent)

assertEquals(ShowPodcastFromUrlDeepLink("http://mypodcast.com/rss/123"), deepLink)
}

@Test
fun podloveHttpWithParams() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribe/mypodcast.com/rss/123?someKey=someValue"))

val deepLink = factory.create(intent)

assertEquals(ShowPodcastFromUrlDeepLink("http://mypodcast.com/rss/123?someKey=someValue"), deepLink)
}

@Test
fun podloveWithWrongScheme() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("https://subscribehttps/mypodcast.com/rss/123"))

val deepLink = factory.create(intent)

assertNull(deepLink)
}

@Test
fun podloveWithWrongHost() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribehttp/mypodcast.com/rss/123"))

val deepLink = factory.create(intent)

assertNull(deepLink)
}

@Test
fun podloveWithShortPath() {
val intent = Intent()
.setAction(ACTION_VIEW)
.setData(Uri.parse("pktc://subscribe/aa"))

val deepLink = factory.create(intent)

assertNull(deepLink)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package au.com.shiftyjelly.pocketcasts.views.helper

import android.content.Intent
import android.net.Uri
import org.junit.Assert.assertEquals
import org.junit.Test

Expand All @@ -22,44 +21,4 @@ class IntentUtilTest {
assertEquals("http", intent.data?.scheme)
assertEquals("www.google.com", intent.data?.host)
}

@Test
fun testSubscribeUrlWithParams() {
val intent = Intent(Intent.ACTION_VIEW)
val url = "pktc://subscribe/mypodcast.memberfulcontent.com/rss/6618?someKey=someValue"
intent.data = Uri.parse(url)

val parsed = IntentUtil.getPodloveUrl(intent)
assertEquals("http://mypodcast.memberfulcontent.com/rss/6618?someKey=someValue", parsed)
}

@Test
fun testSubscribeUrlWithoutParams() {
val intent = Intent(Intent.ACTION_VIEW)
val url = "pktc://subscribe/mypodcast.com/rss/123"
intent.data = Uri.parse(url)

val parsed = IntentUtil.getPodloveUrl(intent)
assertEquals("http://mypodcast.com/rss/123", parsed)
}

@Test
fun testSubscribeUrlWithParamsHttps() {
val intent = Intent(Intent.ACTION_VIEW)
val url = "pktc://subscribehttps/mypodcast.memberfulcontent.com/rss/6618?someKey=someValue"
intent.data = Uri.parse(url)

val parsed = IntentUtil.getPodloveUrl(intent)
assertEquals("https://mypodcast.memberfulcontent.com/rss/6618?someKey=someValue", parsed)
}

@Test
fun testSubscribeUrlWithoutParamsHttps() {
val intent = Intent(Intent.ACTION_VIEW)
val url = "pktc://subscribehttps/mypodcast.com/rss/123"
intent.data = Uri.parse(url)

val parsed = IntentUtil.getPodloveUrl(intent)
assertEquals("https://mypodcast.com/rss/123", parsed)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ 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.ShowPodcastFromUrlDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowPodcastsDeepLink
import au.com.shiftyjelly.pocketcasts.deeplink.ShowUpNextDeepLink
import au.com.shiftyjelly.pocketcasts.discover.view.DiscoverFragment
Expand Down Expand Up @@ -1295,12 +1296,12 @@ class MainActivity :
is PocketCastsWebsiteDeepLink -> {
// Do nothing when the user goes to https://pocketcasts.com/get it should either open the play store or the user's app
}
is ShowPodcastFromUrlDeepLink -> {
openPodcastUrl(deepLink.url)
}
}
} else if (action == Intent.ACTION_VIEW) {
if (IntentUtil.isPodloveUrl(intent)) {
openPodcastUrl(IntentUtil.getPodloveUrl(intent))
return
} else if (IntentUtil.isSonosAppLinkUrl(intent)) {
if (IntentUtil.isSonosAppLinkUrl(intent)) {
startActivityForResult(
SonosAppLinkActivity.buildIntent(intent, this),
SonosAppLinkActivity.SONOS_APP_ACTIVITY_RESULT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ data class ShowFilterDeepLink(

data object PocketCastsWebsiteDeepLink : DeepLink

data class ShowPodcastFromUrlDeepLink(
val url: String,
) : DeepLink

private val Context.launcherIntent get() = requireNotNull(packageManager.getLaunchIntentForPackage(packageName)) {
"Missing launcher intent for $packageName"
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DeepLinkFactory(
ShowEpisodeAdapter(),
ShowPageAdapter(),
PocketCastsWebsiteAdapter(webBaseHost),
PodloveAdapter(),
)

fun create(intent: Intent): DeepLink? {
Expand Down Expand Up @@ -157,3 +158,21 @@ private class PocketCastsWebsiteAdapter(
null
}
}

private class PodloveAdapter : DeepLinkAdapter {
override fun create(intent: Intent): DeepLink? {
val uriData = intent.dataString.orEmpty()
val groupValues = PODLOVE_REGEX.matchEntire(uriData)?.groupValues

return if (intent.action == ACTION_VIEW && groupValues != null) {
val scheme = if (groupValues[1] == "subscribe") "http" else "https"
ShowPodcastFromUrlDeepLink("$scheme://${groupValues[2]}")
} else {
null
}
}

private companion object {
private val PODLOVE_REGEX = """^pktc://(subscribe|subscribehttps)/(.{3,})$""".toRegex()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ import timber.log.Timber

object IntentUtil {

fun isPodloveUrl(intent: Intent): Boolean {
val scheme = intent.scheme
if (scheme == null || scheme != "pktc" || intent.data == null || intent.data?.host == null) {
return false
}

val host = intent.data?.host
return host == "subscribe" || host == "subscribehttps"
}

fun isSonosAppLinkUrl(intent: Intent): Boolean {
val scheme = intent.scheme
if (scheme == null || scheme != "pktc" || intent.data == null || intent.data?.host == null) {
Expand All @@ -38,20 +28,6 @@ object IntentUtil {
return host == "applink"
}

fun getPodloveUrl(intent: Intent): String? {
val uri = intent.data ?: return null
var path = uri.path ?: return null
if (path.startsWith("/")) {
path = path.replaceFirst(Matcher.quoteReplacement("/").toRegex(), "")
}
if (path.length < 3) {
return null
}
val host = uri.host
val params = uri.encodedQuery
return (if (host == "subscribehttps") "https" else "http") + "://" + path + if (!params.isNullOrEmpty()) "?${uri.encodedQuery}" else ""
}

fun isShareLink(intent: Intent): Boolean {
val scheme = intent.scheme
return scheme != null && scheme == "pktc" && intent.data != null && intent.data?.path != null
Expand Down

0 comments on commit 99e00e6

Please sign in to comment.