From 351e981bcfaee2a382e9c9d12454c808a7227d03 Mon Sep 17 00:00:00 2001 From: Tyler Little Date: Tue, 13 Jun 2023 01:12:48 -0600 Subject: [PATCH] Handle more URL types This is a partial fix to #556, but it at least prevents crashing when an unknown URL type is encountered. There is still some work to do, since the markdown plugin doesn't properly interpret URLs the way we want. User-related parsing still doesn't work because there's work needed in the markdown layer, but once that's done, this should just work as intended. --- app/src/main/java/com/jerboa/Utils.kt | 42 +++++++++++++++++++++ app/src/test/java/com/jerboa/UtilsKtTest.kt | 16 ++++++++ 2 files changed, 58 insertions(+) diff --git a/app/src/main/java/com/jerboa/Utils.kt b/app/src/main/java/com/jerboa/Utils.kt index 4a59e6123..406a129c4 100644 --- a/app/src/main/java/com/jerboa/Utils.kt +++ b/app/src/main/java/com/jerboa/Utils.kt @@ -379,7 +379,49 @@ fun LazyListState.isScrolledToEnd(): Boolean { return out } +/* + * Parses a "url" and returns a spec-compliant Url: + * + * - https://host/path - leave as-is + * - /c/community -> https://currentInstance/c/community + * - /c/community@instance -> https://instance/c/community + * - !community@instance -> https://instance/c/community + * - @user@instance -> https://instance/u/user + */ +fun parseUrl(url: String): String? { + if (url.startsWith("https://")) { + return url + } else if (url.startsWith("/c/")) { + if (url.count({ c -> c == '@' }) == 1) { + val (community, host) = url.split("@", limit = 2) + return "https://$host$community" + } + return "https://${API.currentInstance}$url" + } else if (url.startsWith("/u/")) { + if (url.count({ c -> c == '@' }) == 1) { + val (userPath, host) = url.split("@", limit = 2) + return "https://$host$userPath" + } + return "https://${API.currentInstance}$url" + } else if (url.startsWith("!")) { + if (url.count({ c -> c == '@' }) == 1) { + val (community, host) = url.substring(1).split("@", limit = 2) + return "https://$host/c/$community" + } + return "https://${API.currentInstance}/c/${url.substring(1)}" + } else if (url.startsWith("@")) { + if (url.count({ c -> c == '@' }) == 2) { + val (user, host) = url.substring(1).split("@", limit = 2) + return "https://$host/u/$user" + } + return "https://${API.currentInstance}/u/${url.substring(1)}" + } + return null +} + fun openLink(url: String, ctx: Context, useCustomTab: Boolean, usePrivateTab: Boolean) { + val url = parseUrl(url) ?: return + if (useCustomTab) { val intent = CustomTabsIntent.Builder() .build().apply { diff --git a/app/src/test/java/com/jerboa/UtilsKtTest.kt b/app/src/test/java/com/jerboa/UtilsKtTest.kt index 246171428..c6987c574 100644 --- a/app/src/test/java/com/jerboa/UtilsKtTest.kt +++ b/app/src/test/java/com/jerboa/UtilsKtTest.kt @@ -3,6 +3,7 @@ package com.jerboa import androidx.compose.ui.unit.dp import com.jerboa.datatypes.api.GetUnreadCountResponse import com.jerboa.ui.theme.SMALL_PADDING +import com.jerboa.api.API import org.junit.Assert.* import org.junit.Test @@ -136,4 +137,19 @@ class UtilsKtTest { assertEquals("1.2M", siFormat(1234500)) assertEquals("12M", siFormat(12345000)) } + + @Test + fun testParseUrl() { + val cases = mapOf( + "https://feddit.de" to "https://feddit.de", + "/c/community" to "https://${API.currentInstance}/c/community", + "/c/community@instance.ml" to "https://instance.ml/c/community", + "!community@instance.ml" to "https://instance.ml/c/community", + "!community" to "https://${API.currentInstance}/c/community", + "/u/user@instance.ml" to "https://instance.ml/u/user", + "@user@instance.ml" to "https://instance.ml/u/user", + ) + + cases.forEach { (url, exp) -> assertEquals(exp, parseUrl(url)) } + } }