From dcaf9915361e25ca1135220c95c55751299a670b Mon Sep 17 00:00:00 2001 From: Jameson Little Date: Thu, 15 Jun 2023 17:57:31 -0600 Subject: [PATCH] Handle /c/community@host URLs (#583) * 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. * Support http links --- app/src/main/java/com/jerboa/Utils.kt | 43 +++++++++++++++++++++ app/src/test/java/com/jerboa/UtilsKtTest.kt | 17 ++++++++ 2 files changed, 60 insertions(+) diff --git a/app/src/main/java/com/jerboa/Utils.kt b/app/src/main/java/com/jerboa/Utils.kt index 4a59e6123..935bfa0c8 100644 --- a/app/src/main/java/com/jerboa/Utils.kt +++ b/app/src/main/java/com/jerboa/Utils.kt @@ -379,7 +379,50 @@ fun LazyListState.isScrolledToEnd(): Boolean { return out } +/* + * Parses a "url" and returns a spec-compliant Url: + * + * - https://host/path - leave as-is + * - http://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://") || url.startsWith("http://")) { + 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..dd06c4690 100644 --- a/app/src/test/java/com/jerboa/UtilsKtTest.kt +++ b/app/src/test/java/com/jerboa/UtilsKtTest.kt @@ -1,6 +1,7 @@ package com.jerboa import androidx.compose.ui.unit.dp +import com.jerboa.api.API import com.jerboa.datatypes.api.GetUnreadCountResponse import com.jerboa.ui.theme.SMALL_PADDING import org.junit.Assert.* @@ -136,4 +137,20 @@ class UtilsKtTest { assertEquals("1.2M", siFormat(1234500)) assertEquals("12M", siFormat(12345000)) } + + @Test + fun testParseUrl() { + val cases = mapOf( + "https://feddit.de" to "https://feddit.de", + "http://example.com" to "http://example.com", + "/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)) } + } }