diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index d0d08ce6b..37904c7a2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -40,6 +40,7 @@ import com.vitorpamplona.quartz.encoders.Hex import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.LnInvoiceUtil import com.vitorpamplona.quartz.encoders.Nip19Bech32 +import com.vitorpamplona.quartz.encoders.RelayUrlFormatter import com.vitorpamplona.quartz.encoders.toNote import com.vitorpamplona.quartz.events.AddressableEvent import com.vitorpamplona.quartz.events.BaseTextNoteEvent @@ -1122,8 +1123,7 @@ object RelayBriefInfoCache { @Immutable data class RelayBriefInfo( val url: String, - val displayUrl: String = - url.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/").intern(), + val displayUrl: String = RelayUrlFormatter.displayUrl(url).intern(), val favIcon: String = "https://$displayUrl/favicon.ico".intern(), ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt index ac4480c9b..c43a15279 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/Nip11RelayInfoRetriever.kt @@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.service import android.util.Log import android.util.LruCache import com.vitorpamplona.quartz.encoders.Nip11RelayInformation +import com.vitorpamplona.quartz.encoders.RelayUrlFormatter import com.vitorpamplona.quartz.utils.TimeUtils import kotlinx.coroutines.CancellationException import okhttp3.Call @@ -42,7 +43,7 @@ object Nip11CachedRetriever { val retriever = Nip11Retriever() fun getFromCache(dirtyUrl: String): Nip11RelayInformation? { - val result = relayInformationDocumentCache.get(retriever.cleanUrl(dirtyUrl)) ?: return null + val result = relayInformationDocumentCache.get(RelayUrlFormatter.getHttpsUrl(dirtyUrl)) ?: return null if (result is RetrieveResultSuccess) return result.data return null } @@ -52,7 +53,7 @@ object Nip11CachedRetriever { onInfo: (Nip11RelayInformation) -> Unit, onError: (String, Nip11Retriever.ErrorCode, String?) -> Unit, ) { - val url = retriever.cleanUrl(dirtyUrl) + val url = RelayUrlFormatter.getHttpsUrl(dirtyUrl) val doc = relayInformationDocumentCache.get(url) if (doc != null) { @@ -62,35 +63,33 @@ object Nip11CachedRetriever { if (TimeUtils.now() - doc.time < TimeUtils.ONE_HOUR) { onError(dirtyUrl, doc.error, null) } else { - Nip11Retriever() - .loadRelayInfo( - url = url, - dirtyUrl = dirtyUrl, - onInfo = { - relayInformationDocumentCache.put(url, RetrieveResultSuccess(it)) - onInfo(it) - }, - onError = { dirtyUrl, code, errorMsg -> - relayInformationDocumentCache.put(url, RetrieveResultError(code, errorMsg)) - onError(url, code, errorMsg) - }, - ) + retriever.loadRelayInfo( + url = url, + dirtyUrl = dirtyUrl, + onInfo = { + relayInformationDocumentCache.put(url, RetrieveResultSuccess(it)) + onInfo(it) + }, + onError = { dirtyUrl, code, errorMsg -> + relayInformationDocumentCache.put(url, RetrieveResultError(code, errorMsg)) + onError(url, code, errorMsg) + }, + ) } } } else { - Nip11Retriever() - .loadRelayInfo( - url = url, - dirtyUrl = dirtyUrl, - onInfo = { - relayInformationDocumentCache.put(url, RetrieveResultSuccess(it)) - onInfo(it) - }, - onError = { dirtyUrl, code, errorMsg -> - relayInformationDocumentCache.put(url, RetrieveResultError(code, errorMsg)) - onError(url, code, errorMsg) - }, - ) + retriever.loadRelayInfo( + url = url, + dirtyUrl = dirtyUrl, + onInfo = { + relayInformationDocumentCache.put(url, RetrieveResultSuccess(it)) + onInfo(it) + }, + onError = { dirtyUrl, code, errorMsg -> + relayInformationDocumentCache.put(url, RetrieveResultError(code, errorMsg)) + onError(url, code, errorMsg) + }, + ) } } } @@ -103,14 +102,6 @@ class Nip11Retriever { FAIL_WITH_HTTP_STATUS, } - fun cleanUrl(dirtyUrl: String): String { - return if (dirtyUrl.contains("://")) { - dirtyUrl.replace("wss://", "https://").replace("ws://", "http://") - } else { - "https://$dirtyUrl" - } - } - suspend fun loadRelayInfo( url: String, dirtyUrl: String, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt index d09233e89..ff56c6f65 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt @@ -102,6 +102,7 @@ import com.vitorpamplona.amethyst.ui.theme.allGoodColor import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.warningColor +import com.vitorpamplona.quartz.encoders.RelayUrlFormatter import kotlinx.coroutines.launch import java.lang.Math.round @@ -899,17 +900,7 @@ fun EditableServerConfig( Button( onClick = { if (url.isNotBlank() && url != "/") { - var addedWSS = - if (!url.startsWith("wss://") && !url.startsWith("ws://")) { - if (url.endsWith(".onion") || url.endsWith(".onion/")) { - "ws://$url" - } else { - "wss://$url" - } - } else { - url - } - if (url.endsWith("/")) addedWSS = addedWSS.dropLast(1) + val addedWSS = RelayUrlFormatter.normalize(url) onNewRelay(RelaySetupInfo(addedWSS, read, write, feedTypes = FeedType.values().toSet())) url = "" write = true diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt index 73f4d923d..4d3fd7f65 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt @@ -110,6 +110,7 @@ import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NotificationViewModel import com.vitorpamplona.amethyst.ui.screen.SharedPreferencesViewModel +import com.vitorpamplona.quartz.encoders.RelayUrlFormatter import kotlinx.coroutines.launch import kotlin.math.abs @@ -521,7 +522,7 @@ private fun DisplayNotifyMessages( title = stringResource( id = R.string.payment_required_title, - request.relayUrl.removePrefix("wss://").removeSuffix("/"), + RelayUrlFormatter.displayUrl(request.relayUrl), ), textContent = request.description, accountViewModel = accountViewModel, diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/encoders/RelayUrlFormatter.kt b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/RelayUrlFormatter.kt new file mode 100644 index 000000000..7417f7209 --- /dev/null +++ b/quartz/src/main/java/com/vitorpamplona/quartz/encoders/RelayUrlFormatter.kt @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2024 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.quartz.encoders + +class RelayUrlFormatter { + companion object { + fun displayUrl(url: String): String { + return url.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/") + } + + fun normalize(url: String): String { + var newUrl = + if (!url.startsWith("wss://") && !url.startsWith("ws://")) { + if (url.endsWith(".onion") || url.endsWith(".onion/")) { + "ws://$url" + } else { + "wss://$url" + } + } else { + url + } + + if (url.endsWith("/")) newUrl = newUrl.dropLast(1) + + return newUrl + } + + fun getHttpsUrl(dirtyUrl: String): String { + return if (dirtyUrl.contains("://")) { + dirtyUrl.replace("wss://", "https://").replace("ws://", "http://") + } else { + "https://$dirtyUrl" + } + } + } +}