From bcd2bc066b397be2ac0e712ab4f5f2504d70f7f2 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 18 Feb 2026 14:56:07 -0500 Subject: [PATCH] - Removes nip96 and updates Blossom recommendations --- .../amethyst/ImageUploadTesting.kt | 38 ++--- .../vitorpamplona/amethyst/model/Account.kt | 6 - .../FileStorageServerListState.kt | 81 ----------- .../nipB7Blossom/BlossomServerListState.kt | 26 ++++ .../model/preferences/TorSharedPreferences.kt | 4 +- .../RoleBasedHttpClientBuilder.kt | 4 +- .../model/serverList/MergedServerListState.kt | 73 ---------- .../service/uploads/MultiOrchestrator.kt | 1 + .../amethyst/ui/actions/EditPostView.kt | 5 +- .../amethyst/ui/actions/NewMediaView.kt | 14 +- .../mediaServers/AllMediaServersLIstView.kt | 37 +---- .../mediaServers/AllMediaServersScreen.kt | 10 +- .../mediaServers/BlossomServersViewModel.kt | 2 + .../mediaServers/FileServerSelectionRow.kt | 6 +- .../mediaServers/NIP96ServersViewModel.kt | 131 ------------------ .../ui/actions/mediaServers/ServerName.kt | 18 +-- .../creators/uploads/ImageVideoDescription.kt | 33 +---- .../nip22Comments/GenericCommentPostScreen.kt | 5 +- .../chats/privateDM/send/NewGroupDMScreen.kt | 5 +- .../send/upload/ChatFileUploadDialog.kt | 5 +- .../send/ChannelFileUploadDialog.kt | 5 +- .../chats/utils/ChatFileUploadDialog.kt | 11 +- .../nip99Classifieds/NewProductScreen.kt | 6 +- .../loggedIn/home/ShortNotePostScreen.kt | 7 +- .../loggedIn/home/ShortNotePostViewModel.kt | 5 +- .../screen/loggedIn/home/VoiceReplyScreen.kt | 7 +- .../loggedIn/home/VoiceReplyViewModel.kt | 5 +- .../publicMessages/NewPublicMessageScreen.kt | 5 +- .../amethyst/ui/tor/TorDialogViewModel.kt | 10 +- .../amethyst/ui/tor/TorSettings.kt | 12 +- .../amethyst/ui/tor/TorSettingsDialog.kt | 6 +- .../amethyst/ui/tor/TorSettingsFlow.kt | 12 +- .../src/main/res/values-ar-rSA/strings.xml | 4 +- .../src/main/res/values-cs-rCZ/strings.xml | 4 +- amethyst/src/main/res/values-cs/strings.xml | 4 +- .../src/main/res/values-de-rDE/strings.xml | 4 +- amethyst/src/main/res/values-de/strings.xml | 4 +- .../src/main/res/values-es-rES/strings.xml | 6 +- .../src/main/res/values-es-rMX/strings.xml | 6 +- .../src/main/res/values-es-rUS/strings.xml | 6 +- .../src/main/res/values-fa-rIR/strings.xml | 4 +- amethyst/src/main/res/values-fa/strings.xml | 4 +- .../src/main/res/values-fr-rFR/strings.xml | 4 +- amethyst/src/main/res/values-fr/strings.xml | 4 +- .../src/main/res/values-hi-rIN/strings.xml | 4 +- .../src/main/res/values-hu-rHU/strings.xml | 4 +- amethyst/src/main/res/values-hu/strings.xml | 4 +- .../src/main/res/values-nl-rNL/strings.xml | 4 +- amethyst/src/main/res/values-nl/strings.xml | 4 +- .../src/main/res/values-pl-rPL/strings.xml | 4 +- .../src/main/res/values-pt-rBR/strings.xml | 4 +- .../src/main/res/values-sl-rSI/strings.xml | 4 +- .../src/main/res/values-sv-rSE/strings.xml | 4 +- .../src/main/res/values-zh-rCN/strings.xml | 4 +- amethyst/src/main/res/values/strings.xml | 5 +- 55 files changed, 158 insertions(+), 536 deletions(-) delete mode 100644 amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip96FileStorage/FileStorageServerListState.kt delete mode 100644 amethyst/src/main/java/com/vitorpamplona/amethyst/model/serverList/MergedServerListState.kt delete mode 100644 amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/NIP96ServersViewModel.kt diff --git a/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/ImageUploadTesting.kt b/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/ImageUploadTesting.kt index b3dcb47c54..3aebe1c1c0 100644 --- a/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/ImageUploadTesting.kt +++ b/amethyst/src/androidTest/java/com/vitorpamplona/amethyst/ImageUploadTesting.kt @@ -121,10 +121,10 @@ class ImageUploadTesting { context = InstrumentationRegistry.getInstrumentation().targetContext, ) - assertEquals("image/png", result.type) - assertEquals(paylod.size.toLong(), result.size) - assertEquals(initialHash, result.sha256) - assertEquals("${server.baseUrl}/$initialHash", result.url?.removeSuffix(".png")) + assertEquals(server.baseUrl, "image/png", result.type) + assertEquals(server.baseUrl, paylod.size.toLong(), result.size) + assertEquals(server.baseUrl, initialHash, result.sha256) + // assertEquals(server.baseUrl, "${server.baseUrl}/$initialHash", result.url?.removeSuffix(".png")) val imageData: ByteArray = ImageDownloader().waitAndGetImage(result.url!!, { client })?.bytes @@ -134,7 +134,7 @@ class ImageUploadTesting { } val downloadedHash = sha256(imageData).toHexKey() - assertEquals(initialHash, downloadedHash) + assertEquals(server.baseUrl, initialHash, downloadedHash) } private suspend fun testNip96(server: ServerName) { @@ -207,8 +207,13 @@ class ImageUploadTesting { runBlocking { DEFAULT_MEDIA_SERVERS.forEach { // skip paid servers and primal server is buggy. - if (!it.name.contains("Paid") && !it.name.contains("Primal")) { - testBase(it) + try { + if (!it.name.contains("Paid") && !it.name.contains("Primal")) { + testBase(it) + } + } catch (e: Exception) { + e.printStackTrace() + fail("Could not upload to: ${it.baseUrl}: ${e.message}") } } } @@ -226,14 +231,6 @@ class ImageUploadTesting { testBase(ServerName("nostrage", "https://nostrage.com", ServerType.NIP96)) } - @Test() - @Ignore("Not Working anymore") - fun testSove() = - runBlocking { - testBase(ServerName("sove", "https://sove.rent", ServerType.NIP96)) - } - - @Ignore("Not Working anymore") @Test() fun testNostrBuild() = runBlocking { @@ -241,10 +238,10 @@ class ImageUploadTesting { } @Test() - @Ignore("Not Working anymore") + @Ignore("Returns invalid hash") fun testSovbit() = runBlocking { - testBase(ServerName("sovbit", "https://files.sovbit.host", ServerType.NIP96)) + testBase(ServerName("sovbit", "https://cdn.sovbit.host", ServerType.Blossom)) } @Test() @@ -260,13 +257,6 @@ class ImageUploadTesting { testBase(ServerName("sprovoost.nl", "https://img.sprovoost.nl/", ServerType.NIP96)) } - @Test() - @Ignore("Not Working anymore") - fun testNostrOnch() = - runBlocking { - testBase(ServerName("nostr.onch.services", "https://nostr.onch.services", ServerType.NIP96)) - } - @Ignore("Changes sha256") fun testPrimalBlossom() = runBlocking { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index a74b41df16..ab3ce13b2c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -82,14 +82,12 @@ import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState import com.vitorpamplona.amethyst.model.nip72Communities.CommunityListDecryptionCache import com.vitorpamplona.amethyst.model.nip72Communities.CommunityListState import com.vitorpamplona.amethyst.model.nip78AppSpecific.AppSpecificState -import com.vitorpamplona.amethyst.model.nip96FileStorage.FileStorageServerListState import com.vitorpamplona.amethyst.model.nipA3PaymentTargets.NipA3PaymentTargetsState import com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState import com.vitorpamplona.amethyst.model.serverList.MergedFollowListsState import com.vitorpamplona.amethyst.model.serverList.MergedFollowPlusMineRelayListsState import com.vitorpamplona.amethyst.model.serverList.MergedFollowPlusMineWithIndexRelayListsState import com.vitorpamplona.amethyst.model.serverList.MergedFollowPlusMineWithSearchRelayListsState -import com.vitorpamplona.amethyst.model.serverList.MergedServerListState import com.vitorpamplona.amethyst.model.serverList.TrustedRelayListsState import com.vitorpamplona.amethyst.model.topNavFeeds.FeedDecryptionCaches import com.vitorpamplona.amethyst.model.topNavFeeds.FeedTopNavFilterState @@ -317,8 +315,6 @@ class Account( val appSpecific = AppSpecificState(signer, cache, scope, settings) val blossomServers = BlossomServerListState(signer, cache, scope, settings) - val fileStorageServers = FileStorageServerListState(signer, cache, scope, settings) - val serverLists = MergedServerListState(fileStorageServers, blossomServers, scope) // Relay settings val homeRelays = AccountHomeRelayState(nip65RelayList, privateStorageRelayList, localRelayList, scope) @@ -1916,8 +1912,6 @@ class Account( suspend fun sendNip65RelayList(relays: List) = sendLiterallyEverywhere(nip65RelayList.saveRelayList(relays)) - suspend fun sendFileServersList(servers: List) = sendMyPublicAndPrivateOutbox(fileStorageServers.saveFileServersList(servers)) - suspend fun sendBlossomServersList(servers: List) = sendMyPublicAndPrivateOutbox(blossomServers.saveBlossomServersList(servers)) fun markAsRead( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip96FileStorage/FileStorageServerListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip96FileStorage/FileStorageServerListState.kt deleted file mode 100644 index 6868249962..0000000000 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nip96FileStorage/FileStorageServerListState.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2025 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.amethyst.model.nip96FileStorage - -import com.vitorpamplona.amethyst.model.AccountSettings -import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.model.NoteState -import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner -import com.vitorpamplona.quartz.nip96FileStorage.config.FileServersEvent -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.stateIn - -class FileStorageServerListState( - val signer: NostrSigner, - val cache: LocalCache, - val scope: CoroutineScope, - val settings: AccountSettings, -) { - // Creates a long-term reference for this note so that the GC doesn't collect the note it self - val fileStorageListNote = cache.getOrCreateAddressableNote(getFileServersAddress()) - - fun getFileServersAddress() = FileServersEvent.createAddress(signer.pubKey) - - fun getFileServersListFlow(): StateFlow = fileStorageListNote.flow().metadata.stateFlow - - fun getFileServersList(): FileServersEvent? = fileStorageListNote.event as? FileServersEvent - - fun normalizeServers(note: Note): List { - val event = note.event as? FileServersEvent - return event?.servers() ?: emptyList() - } - - val flow = - getFileServersListFlow() - .map { normalizeServers(it.note) } - .onStart { emit(normalizeServers(fileStorageListNote)) } - .flowOn(Dispatchers.IO) - .stateIn( - scope, - SharingStarted.Eagerly, - emptyList(), - ) - - suspend fun saveFileServersList(servers: List): FileServersEvent { - val serverList = getFileServersList() - - val template = - if (serverList != null && serverList.tags.isNotEmpty()) { - FileServersEvent.replaceServers(serverList, servers) - } else { - FileServersEvent.build(servers) - } - - return signer.sign(template) - } -} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nipB7Blossom/BlossomServerListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nipB7Blossom/BlossomServerListState.kt index 39539fadfa..735868c780 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nipB7Blossom/BlossomServerListState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/nipB7Blossom/BlossomServerListState.kt @@ -24,10 +24,14 @@ import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.NoteState +import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS +import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName +import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nipB7Blossom.BlossomAuthorizationEvent import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent +import com.vitorpamplona.quartz.utils.Rfc3986 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted @@ -57,6 +61,13 @@ class BlossomServerListState( return event?.servers() ?: emptyList() } + fun host(url: String): String = + try { + Rfc3986.host(url).removePrefix("cdn.").removePrefix("blossom.") + } catch (e: Exception) { + url.removePrefix("cdn.").removePrefix("blossom.") + } + val flow = getBlossomServersListFlow() .map { normalizeServers(it.note) } @@ -68,6 +79,21 @@ class BlossomServerListState( emptyList(), ) + fun mergeServerList(blossom: List?): List = blossom?.map { ServerName(host(it), it, ServerType.Blossom) } ?: emptyList() + + val hostNameFlow: StateFlow> = + flow + .map { blossoms -> + mergeServerList(blossoms) + }.onStart { + emit(mergeServerList(flow.value)) + }.flowOn(Dispatchers.IO) + .stateIn( + scope, + SharingStarted.Eagerly, + DEFAULT_MEDIA_SERVERS, + ) + suspend fun saveBlossomServersList(servers: List): BlossomServersEvent { val serverList = getBlossomServersList() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt index 7e6284ec7b..97422d41bd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/TorSharedPreferences.kt @@ -101,7 +101,7 @@ class TorSharedPreferences( videosViaTor = preferences[VIDEOS_VIA_TOR_KEY] ?: false, moneyOperationsViaTor = preferences[MONEY_OPERATIONS_VIA_TOR_KEY] ?: false, nip05VerificationsViaTor = preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] ?: false, - nip96UploadsViaTor = preferences[MEDIA_UPLOADS_VIA_TOR_KEY] ?: false, + mediaUploadsViaTor = preferences[MEDIA_UPLOADS_VIA_TOR_KEY] ?: false, ) } catch (e: Exception) { if (e is CancellationException) throw e @@ -125,7 +125,7 @@ class TorSharedPreferences( preferences[VIDEOS_VIA_TOR_KEY] = torSettings.videosViaTor preferences[MONEY_OPERATIONS_VIA_TOR_KEY] = torSettings.moneyOperationsViaTor preferences[NIP05_VERIFICATIONS_VIA_TOR_KEY] = torSettings.nip05VerificationsViaTor - preferences[MEDIA_UPLOADS_VIA_TOR_KEY] = torSettings.nip96UploadsViaTor + preferences[MEDIA_UPLOADS_VIA_TOR_KEY] = torSettings.mediaUploadsViaTor } } catch (e: Exception) { if (e is CancellationException) throw e diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/privacyOptions/RoleBasedHttpClientBuilder.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/privacyOptions/RoleBasedHttpClientBuilder.kt index 76d918be79..aacb3e2621 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/privacyOptions/RoleBasedHttpClientBuilder.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/privacyOptions/RoleBasedHttpClientBuilder.kt @@ -122,8 +122,8 @@ class RoleBasedHttpClientBuilder( fun shouldUseTorForUploads(url: String) = when (torSettings.torType.value) { TorType.OFF -> false - TorType.INTERNAL -> checkLocalHostOnionAndThen(url, torSettings.nip96UploadsViaTor.value) - TorType.EXTERNAL -> checkLocalHostOnionAndThen(url, torSettings.nip96UploadsViaTor.value) + TorType.INTERNAL -> checkLocalHostOnionAndThen(url, torSettings.mediaUploadsViaTor.value) + TorType.EXTERNAL -> checkLocalHostOnionAndThen(url, torSettings.mediaUploadsViaTor.value) } override fun proxyPortForVideo(url: String): Int? = okHttpClient.getCurrentProxyPort(shouldUseTorForVideoDownload(url)) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/serverList/MergedServerListState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/serverList/MergedServerListState.kt deleted file mode 100644 index 9889f0b188..0000000000 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/serverList/MergedServerListState.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2025 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.amethyst.model.serverList - -import com.vitorpamplona.amethyst.model.nip96FileStorage.FileStorageServerListState -import com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState -import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType -import com.vitorpamplona.quartz.utils.Rfc3986 -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.stateIn - -class MergedServerListState( - val fileServers: FileStorageServerListState, - val blossomServers: BlossomServerListState, - val scope: CoroutineScope, -) { - fun host(url: String): String = - try { - Rfc3986.host(url) - } catch (e: Exception) { - url - } - - fun mergeServerList( - nip96: List?, - blossom: List?, - ): List { - val nip96servers = nip96?.map { ServerName(host(it), it, ServerType.NIP96) } ?: emptyList() - val blossomServers = blossom?.map { ServerName(host(it), it, ServerType.Blossom) } ?: emptyList() - - val result = (nip96servers + blossomServers).ifEmpty { DEFAULT_MEDIA_SERVERS } - - return result + ServerName("NIP95", "", ServerType.NIP95) - } - - val liveServerList: StateFlow> = - combine(fileServers.flow, blossomServers.flow) { nip96s, blossoms -> - mergeServerList(nip96s, blossoms) - }.onStart { - emit(mergeServerList(fileServers.flow.value, blossomServers.flow.value)) - }.flowOn(Dispatchers.IO) - .stateIn( - scope, - SharingStarted.Eagerly, - DEFAULT_MEDIA_SERVERS, - ) -} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/MultiOrchestrator.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/MultiOrchestrator.kt index 6c7a0939c2..ada46f1dd4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/MultiOrchestrator.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/MultiOrchestrator.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch +@Stable class MultiOrchestrator( uris: List, ) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt index 2945de5dc4..3dd0ba8ab0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/EditPostView.kt @@ -78,7 +78,6 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextParser import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.service.playback.composable.VideoView import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserInfo -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.components.BechLink import com.vitorpamplona.amethyst.ui.components.LoadUrlPreview @@ -264,9 +263,7 @@ fun EditPostView( accountViewModel.account.settings.defaultFileServer, onAdd = { alt, server, sensitiveContent, mediaQuality, _ -> postViewModel.upload(alt, sensitiveContent, mediaQuality, false, server, accountViewModel.toastManager::toast, context) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, onCancel = { postViewModel.multiOrchestrator = null }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt index 7f812155fd..1263816fc2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewMediaView.kt @@ -54,7 +54,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge @@ -110,9 +109,7 @@ fun NewMediaView( onPost = { postViewModel.upload(context, onClose, accountViewModel.toastManager::toast) postViewModel.selectedServer?.let { - if (it.type != ServerType.NIP95) { - account.settings.changeDefaultFileServer(it) - } + account.settings.changeDefaultFileServer(it) } }, ) @@ -148,19 +145,14 @@ fun ImageVideoPost( postViewModel: NewMediaModel, accountViewModel: AccountViewModel, ) { - val nip95description = stringRes(id = R.string.upload_server_relays_nip95) - val fileServers by accountViewModel.account.serverLists.liveServerList + val fileServers by accountViewModel.account.blossomServers.hostNameFlow .collectAsState() val fileServerOptions = remember(fileServers) { fileServers .map { - if (it.type == ServerType.NIP95) { - TitleExplainer(it.name, nip95description) - } else { - TitleExplainer(it.name, it.baseUrl) - } + TitleExplainer(it.name, it.baseUrl) }.toImmutableList() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersLIstView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersLIstView.kt index 3055595567..ddab82030a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersLIstView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersLIstView.kt @@ -56,11 +56,7 @@ import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.grayText @Composable -fun AllMediaBody( - nip96ServersViewModel: NIP96ServersViewModel, - blossomServersViewModel: BlossomServersViewModel, -) { - val nip96ServersState by nip96ServersViewModel.fileServers.collectAsStateWithLifecycle() +fun AllMediaBody(blossomServersViewModel: BlossomServersViewModel) { val blossomServersState by blossomServersViewModel.fileServers.collectAsStateWithLifecycle() LazyColumn( @@ -89,40 +85,15 @@ fun AllMediaBody( }, ) - item { - SettingsCategory( - R.string.media_servers_nip96_section, - R.string.media_servers_nip96_explainer, - SettingsCategorySpacingModifier, - ) - } - - renderMediaServerList( - mediaServersState = nip96ServersState, - keyType = "nip96", - editLabel = R.string.add_a_nip96_server, - emptyLabel = R.string.no_nip96_server_message, - onAddServer = { server -> - nip96ServersViewModel.addServer(server) - }, - onDeleteServer = { - nip96ServersViewModel.removeServer(serverUrl = it) - }, - ) - DEFAULT_MEDIA_SERVERS.let { item { SettingsCategoryWithButton( - title = R.string.built_in_media_servers_title, + title = R.string.recommended_media_servers, description = R.string.built_in_servers_description, modifier = SettingsCategorySpacingModifier, ) { OutlinedButton( onClick = { - nip96ServersViewModel.addServerList( - it.mapNotNull { s -> if (s.type == ServerType.NIP96) s.baseUrl else null }, - ) - blossomServersViewModel.addServerList( it.mapNotNull { s -> if (s.type == ServerType.Blossom) s.baseUrl else null }, ) @@ -142,9 +113,7 @@ fun AllMediaBody( serverEntry = server, isAmethystDefault = true, onAddOrDelete = { serverUrl -> - if (server.type == ServerType.NIP96) { - nip96ServersViewModel.addServer(serverUrl) - } else if (server.type == ServerType.Blossom) { + if (server.type == ServerType.Blossom) { blossomServersViewModel.addServer(serverUrl) } }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersScreen.kt index 9f32890c34..6924b98d81 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/AllMediaServersScreen.kt @@ -49,18 +49,15 @@ fun AllMediaServersScreen( accountViewModel: AccountViewModel, nav: INav, ) { - val nip96ServersViewModel: NIP96ServersViewModel = viewModel() val blossomServersViewModel: BlossomServersViewModel = viewModel() - nip96ServersViewModel.init(accountViewModel) blossomServersViewModel.init(accountViewModel) LaunchedEffect(key1 = accountViewModel) { - nip96ServersViewModel.load() blossomServersViewModel.load() } - MediaServersScaffold(nip96ServersViewModel, blossomServersViewModel) { + MediaServersScaffold(blossomServersViewModel) { nav.popBack() } } @@ -68,7 +65,6 @@ fun AllMediaServersScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable fun MediaServersScaffold( - nip96ServersViewModel: NIP96ServersViewModel, blossomServersViewModel: BlossomServersViewModel, onClose: () -> Unit, ) { @@ -77,12 +73,10 @@ fun MediaServersScaffold( SavingTopBar( titleRes = R.string.media_servers, onCancel = { - nip96ServersViewModel.refresh() blossomServersViewModel.refresh() onClose() }, onPost = { - nip96ServersViewModel.saveFileServers() blossomServersViewModel.saveFileServers() onClose() }, @@ -111,7 +105,7 @@ fun MediaServersScaffold( color = MaterialTheme.colorScheme.grayText, ) - AllMediaBody(nip96ServersViewModel, blossomServersViewModel) + AllMediaBody(blossomServersViewModel) } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/BlossomServersViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/BlossomServersViewModel.kt index efac80079c..84142984be 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/BlossomServersViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/BlossomServersViewModel.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.ui.actions.mediaServers +import androidx.compose.runtime.Stable import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vitorpamplona.amethyst.model.Account @@ -31,6 +32,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +@Stable class BlossomServersViewModel : ViewModel() { private lateinit var accountViewModel: AccountViewModel private lateinit var account: Account diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/FileServerSelectionRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/FileServerSelectionRow.kt index 2726f9487c..2239d0b946 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/FileServerSelectionRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/FileServerSelectionRow.kt @@ -41,11 +41,7 @@ fun FileServerSelectionRow( remember(fileServers) { fileServers .map { - if (it.type == ServerType.NIP95) { - TitleExplainer(it.name, nip95description) - } else { - TitleExplainer(it.name, it.baseUrl) - } + TitleExplainer(it.name, it.baseUrl) }.toImmutableList() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/NIP96ServersViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/NIP96ServersViewModel.kt deleted file mode 100644 index e4d8d873db..0000000000 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/NIP96ServersViewModel.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2025 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.amethyst.ui.actions.mediaServers - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.vitorpamplona.amethyst.model.Account -import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.quartz.utils.Log -import com.vitorpamplona.quartz.utils.Rfc3986 -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch - -class NIP96ServersViewModel : ViewModel() { - private lateinit var accountViewModel: AccountViewModel - private lateinit var account: Account - - private val _fileServers = MutableStateFlow>(emptyList()) - val fileServers = _fileServers.asStateFlow() - private var isModified = false - - fun init(accountViewModel: AccountViewModel) { - this.accountViewModel = accountViewModel - this.account = accountViewModel.account - } - - fun load() { - refresh() - } - - fun refresh() { - isModified = false - _fileServers.update { - val obtainedFileServers = obtainFileServers() ?: emptyList() - obtainedFileServers.mapNotNull { serverUrl -> - try { - ServerName( - Rfc3986.host(serverUrl), - serverUrl, - ServerType.NIP96, - ) - } catch (e: Exception) { - Log.d("MediaServersViewModel", "Invalid URL in NIP-96 server list") - null - } - } - } - } - - fun addServerList(serverList: List) { - serverList.forEach { serverUrl -> - addServer(serverUrl) - } - } - - fun addServer(serverUrl: String) { - val normalizedUrl = - try { - Rfc3986.normalize(serverUrl.trim()) - } catch (e: Exception) { - serverUrl - } - val serverNameReference = - try { - Rfc3986.host(normalizedUrl) - } catch (e: Exception) { - normalizedUrl - } - val serverRef = ServerName(serverNameReference, normalizedUrl, ServerType.NIP96) - if (_fileServers.value.contains(serverRef)) { - return - } else { - _fileServers.update { - it.plus(serverRef) - } - } - isModified = true - } - - fun removeServer( - name: String = "", - serverUrl: String, - ) { - viewModelScope.launch { - val serverName = if (name.isNotBlank()) name else Rfc3986.host(serverUrl) - _fileServers.update { - it.minus( - ServerName(serverName, serverUrl, ServerType.NIP96), - ) - } - isModified = true - } - } - - fun removeAllServers() { - _fileServers.update { emptyList() } - isModified = true - } - - fun saveFileServers() { - if (isModified) { - accountViewModel.launchSigner { - val serverList = _fileServers.value.map { it.baseUrl } - account.sendFileServersList(serverList) - refresh() - } - } - } - - private fun obtainFileServers(): List? = account.fileStorageServers.flow.value -} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/ServerName.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/ServerName.kt index c17e5b62cd..e81f65e51c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/ServerName.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/ServerName.kt @@ -26,22 +26,24 @@ import kotlinx.serialization.Serializable data class ServerName( val name: String, val baseUrl: String, - val type: ServerType = ServerType.NIP96, + val type: ServerType = ServerType.Blossom, ) enum class ServerType { - NIP96, - NIP95, Blossom, + NIP95, + NIP96, } val DEFAULT_MEDIA_SERVERS: List = listOf( - ServerName("Nostr.Build", "https://nostr.build", ServerType.NIP96), - ServerName("NostrCheck.me (NIP-96)", "https://nostrcheck.me", ServerType.NIP96), - ServerName("Sovbit", "https://files.sovbit.host", ServerType.NIP96), - ServerName("Satellite (Paid)", "https://cdn.satellite.earth", ServerType.Blossom), - ServerName("NostrCheck.me (Blossom)", "https://cdn.nostrcheck.me", ServerType.Blossom), + ServerName("Nostr.Build", "https://blossom.band/", ServerType.Blossom), + ServerName("24242.io", "https://24242.io/", ServerType.Blossom), + ServerName("Azzamo", "https://blossom.azzamo.media", ServerType.Blossom), + ServerName("YakiHonne", "https://blossom.yakihonne.com/", ServerType.Blossom), + ServerName("Primal", "https://blossom.primal.net/", ServerType.Blossom), + ServerName("Sovbit", "https://cdn.sovbit.host", ServerType.Blossom), ServerName("Nostr.Download", "https://nostr.download", ServerType.Blossom), + ServerName("Satellite (Paid)", "https://cdn.satellite.earth", ServerType.Blossom), ServerName("NostrMedia (Paid)", "https://nostrmedia.com", ServerType.Blossom), ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/uploads/ImageVideoDescription.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/uploads/ImageVideoDescription.kt index cc6b1fc6bd..075f0aaf75 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/uploads/ImageVideoDescription.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/uploads/ImageVideoDescription.kt @@ -58,7 +58,6 @@ import androidx.compose.ui.unit.sp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery import com.vitorpamplona.amethyst.ui.components.TextSpinner @@ -83,38 +82,12 @@ fun ImageVideoDescription( onCancel: () -> Unit, accountViewModel: AccountViewModel, ) { - ImageVideoDescription(uris, defaultServer, true, onAdd, onDelete, onCancel, accountViewModel) -} - -@Composable -fun ImageVideoDescription( - uris: MultiOrchestrator, - defaultServer: ServerName, - includeNIP95: Boolean, - onAdd: (String, ServerName, Boolean, Int, Boolean) -> Unit, - onDelete: (SelectedMediaProcessing) -> Unit, - onCancel: () -> Unit, - accountViewModel: AccountViewModel, -) { - val nip95description = stringRes(id = R.string.upload_server_relays_nip95) - - val fileServers by accountViewModel.account.serverLists.liveServerList + val fileServers by accountViewModel.account.blossomServers.hostNameFlow .collectAsState() val fileServerOptions = - remember(fileServers, includeNIP95) { - fileServers - .mapNotNull { - if (it.type == ServerType.NIP95) { - if (includeNIP95) { - TitleExplainer(it.name, nip95description) - } else { - null - } - } else { - TitleExplainer(it.name, it.baseUrl) - } - }.toImmutableList() + remember(fileServers) { + fileServers.map { TitleExplainer(it.name, it.baseUrl) }.toImmutableList() } var selectedServer by remember { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt index bedcfbc701..17c3c7b735 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/GenericCommentPostScreen.kt @@ -49,7 +49,6 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton @@ -287,9 +286,7 @@ private fun GenericCommentPostBody( accountViewModel.account.settings.defaultFileServer, onAdd = { alt, server, sensitiveContent, mediaQuality, _ -> postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, onCancel = { postViewModel.multiOrchestrator = null }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/NewGroupDMScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/NewGroupDMScreen.kt index b9f35449bb..f2cd402497 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/NewGroupDMScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/NewGroupDMScreen.kt @@ -82,7 +82,6 @@ import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo import com.vitorpamplona.amethyst.commons.richtext.RichTextParser import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton @@ -284,9 +283,7 @@ fun GroupDMScreenContent( context, onceUploaded = { }, ) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = { postViewModel.uploadState?.deleteMediaToUpload(it) }, onCancel = uploading::reset, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/upload/ChatFileUploadDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/upload/ChatFileUploadDialog.kt index 6d46f1e0a5..1dca30b9fd 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/upload/ChatFileUploadDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/upload/ChatFileUploadDialog.kt @@ -28,7 +28,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.note.NonClickableUserPictures import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -70,9 +69,7 @@ fun RoomChatFileUploadDialog( onceUploaded = onUpload, ) - if (state.selectedServer.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(state.selectedServer) - } + accountViewModel.account.settings.changeDefaultFileServer(state.selectedServer) }, onCancel, accountViewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelFileUploadDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelFileUploadDialog.kt index 1888c8b5ec..2ef6776d83 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelFileUploadDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelFileUploadDialog.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.commons.model.nip53LiveActivities.LiveActivitiesChannel -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.note.UserPicture @@ -131,9 +130,7 @@ fun ChannelFileUploadDialog( onceUploaded = onUpload, ) - if (state.selectedServer.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(state.selectedServer) - } + accountViewModel.account.settings.changeDefaultFileServer(state.selectedServer) }, onCancel, accountViewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/utils/ChatFileUploadDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/utils/ChatFileUploadDialog.kt index 2c28ba396e..de7626e471 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/utils/ChatFileUploadDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/utils/ChatFileUploadDialog.kt @@ -55,7 +55,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge import com.vitorpamplona.amethyst.ui.components.TextSpinner @@ -145,18 +144,14 @@ private fun ImageVideoPostChat( fileUploadState: ChatFileUploadState, accountViewModel: AccountViewModel, ) { - val fileServers by accountViewModel.account.serverLists.liveServerList + val fileServers by accountViewModel.account.blossomServers.hostNameFlow .collectAsState() val fileServerOptions = remember(fileServers) { fileServers - .mapNotNull { - if (it.type != ServerType.NIP95) { - TitleExplainer(it.name, it.baseUrl) - } else { - null - } + .map { + TitleExplainer(it.name, it.baseUrl) }.toImmutableList() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt index 26a3e1222a..cac04a8697 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductScreen.kt @@ -48,7 +48,6 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton @@ -255,12 +254,9 @@ private fun NewProductBody( ImageVideoDescription( uris = it, defaultServer = accountViewModel.account.settings.defaultFileServer, - includeNIP95 = false, onAdd = { alt, server, sensitiveContent, mediaQuality, _ -> postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, onCancel = { postViewModel.multiOrchestrator = null }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt index 3e83c58604..369f06947d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostScreen.kt @@ -62,7 +62,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.actions.mediaServers.FileServerSelectionRow -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.MAX_VOICE_RECORD_SECONDS import com.vitorpamplona.amethyst.ui.actions.uploads.RecordVoiceButton import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery @@ -343,9 +342,7 @@ private fun NewPostScreenBody( accountViewModel.account.settings.defaultFileServer, onAdd = { alt, server, sensitiveContent, mediaQuality, useH265 -> postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context, useH265) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, onCancel = { postViewModel.multiOrchestrator = null }, @@ -357,7 +354,7 @@ private fun NewPostScreenBody( // Show preview for both uploaded messages (voiceMetadata) and pending recordings (postViewModel.voiceMetadata ?: postViewModel.getVoicePreviewMetadata())?.let { metadata -> val fileServersState = - accountViewModel.account.serverLists.liveServerList + accountViewModel.account.blossomServers.hostNameFlow .collectAsState() val fileServers = fileServersState.value diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt index 88de6da658..c45eb4b203 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt @@ -48,7 +48,6 @@ import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.UploadingState import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.RecordingResult import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing @@ -563,8 +562,8 @@ open class ShortNotePostViewModel : return } // Update default server if voice message was successfully uploaded - if (voiceSelectedServer != null && voiceSelectedServer?.type != ServerType.NIP95) { - account.settings.changeDefaultFileServer(voiceSelectedServer!!) + voiceSelectedServer?.let { + account.settings.changeDefaultFileServer(it) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyScreen.kt index f23dd893bf..b9da0ce39b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel @@ -164,10 +165,10 @@ private fun VoiceReplyScreenBody( Spacer(modifier = Modifier.height(16.dp)) // Server selection - val fileServers = - accountViewModel.account.serverLists.liveServerList + val fileServers by + accountViewModel.account.blossomServers.hostNameFlow .collectAsState() - .value + FileServerSelectionRow( fileServers = fileServers, selectedServer = viewModel.voiceSelectedServer ?: accountViewModel.account.settings.defaultFileServer, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyViewModel.kt index d20e9d3a4b..d44630a468 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/VoiceReplyViewModel.kt @@ -33,7 +33,6 @@ import com.vitorpamplona.amethyst.service.uploads.CompressorQuality import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.UploadingState import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.RecordingResult import com.vitorpamplona.amethyst.ui.actions.uploads.VoiceAnonymizationController import com.vitorpamplona.amethyst.ui.actions.uploads.VoicePreset @@ -274,9 +273,7 @@ class VoiceReplyViewModel : ViewModel() { accountViewModel.account.signAndComputeBroadcast(template) } - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) deleteVoiceLocalFile() voiceAnonymization.deleteDistortedFiles() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt index 281dd35f4e..78b2749735 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageScreen.kt @@ -58,7 +58,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation -import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton @@ -233,9 +232,7 @@ fun PublicMessageScreenContent( accountViewModel.account.settings.defaultFileServer, onAdd = { alt, server, sensitiveContent, mediaQuality, _ -> postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context) - if (server.type != ServerType.NIP95) { - accountViewModel.account.settings.changeDefaultFileServer(server) - } + accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, onCancel = { postViewModel.multiOrchestrator = null }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorDialogViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorDialogViewModel.kt index ef1e4fc09e..8db02d3228 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorDialogViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorDialogViewModel.kt @@ -42,7 +42,7 @@ class TorDialogViewModel : ViewModel() { val videosViaTor = mutableStateOf(false) val moneyOperationsViaTor = mutableStateOf(false) val nip05VerificationsViaTor = mutableStateOf(false) - val nip96UploadsViaTor = mutableStateOf(false) + val mediaUploadsViaTor = mutableStateOf(false) val preset = derivedStateOf { @@ -60,7 +60,7 @@ class TorDialogViewModel : ViewModel() { videosViaTor = videosViaTor.value, moneyOperationsViaTor = moneyOperationsViaTor.value, nip05VerificationsViaTor = nip05VerificationsViaTor.value, - nip96UploadsViaTor = nip96UploadsViaTor.value, + mediaUploadsViaTor = mediaUploadsViaTor.value, ), ) } @@ -78,7 +78,7 @@ class TorDialogViewModel : ViewModel() { videosViaTor.value = torSettings.videosViaTor moneyOperationsViaTor.value = torSettings.moneyOperationsViaTor nip05VerificationsViaTor.value = torSettings.nip05VerificationsViaTor - nip96UploadsViaTor.value = torSettings.nip96UploadsViaTor + mediaUploadsViaTor.value = torSettings.mediaUploadsViaTor } fun save(): TorSettings = @@ -95,7 +95,7 @@ class TorDialogViewModel : ViewModel() { videosViaTor = videosViaTor.value, moneyOperationsViaTor = moneyOperationsViaTor.value, nip05VerificationsViaTor = nip05VerificationsViaTor.value, - nip96UploadsViaTor = nip96UploadsViaTor.value, + mediaUploadsViaTor = mediaUploadsViaTor.value, ) fun setPreset(preset: TorPresetType) { @@ -119,6 +119,6 @@ class TorDialogViewModel : ViewModel() { videosViaTor.value = torSettings.videosViaTor moneyOperationsViaTor.value = torSettings.moneyOperationsViaTor nip05VerificationsViaTor.value = torSettings.nip05VerificationsViaTor - nip96UploadsViaTor.value = torSettings.nip96UploadsViaTor + mediaUploadsViaTor.value = torSettings.mediaUploadsViaTor } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettings.kt index d60b06de0d..ff1146c706 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettings.kt @@ -35,7 +35,7 @@ data class TorSettings( val videosViaTor: Boolean = false, val moneyOperationsViaTor: Boolean = false, val nip05VerificationsViaTor: Boolean = false, - val nip96UploadsViaTor: Boolean = false, + val mediaUploadsViaTor: Boolean = false, ) enum class TorType( @@ -90,7 +90,7 @@ fun isPreset( torSettings.videosViaTor == preset.videosViaTor && torSettings.moneyOperationsViaTor == preset.moneyOperationsViaTor && torSettings.nip05VerificationsViaTor == preset.nip05VerificationsViaTor && - torSettings.nip96UploadsViaTor == preset.nip96UploadsViaTor + torSettings.mediaUploadsViaTor == preset.mediaUploadsViaTor fun whichPreset(torSettings: TorSettings): TorPresetType { if (isPreset(torSettings, torOnlyWhenNeededPreset)) return TorPresetType.ONLY_WHEN_NEEDED @@ -112,7 +112,7 @@ val torOnlyWhenNeededPreset = videosViaTor = false, moneyOperationsViaTor = false, nip05VerificationsViaTor = false, - nip96UploadsViaTor = false, + mediaUploadsViaTor = false, ) val torDefaultPreset = TorSettings( @@ -126,7 +126,7 @@ val torDefaultPreset = videosViaTor = false, moneyOperationsViaTor = false, nip05VerificationsViaTor = false, - nip96UploadsViaTor = false, + mediaUploadsViaTor = false, ) val torSmallPayloadsPreset = TorSettings( @@ -140,7 +140,7 @@ val torSmallPayloadsPreset = videosViaTor = false, moneyOperationsViaTor = true, nip05VerificationsViaTor = true, - nip96UploadsViaTor = false, + mediaUploadsViaTor = false, ) val torFullyPrivate = TorSettings( @@ -154,5 +154,5 @@ val torFullyPrivate = videosViaTor = true, moneyOperationsViaTor = true, nip05VerificationsViaTor = true, - nip96UploadsViaTor = true, + mediaUploadsViaTor = true, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsDialog.kt index d98bb953ae..d64e072ee9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsDialog.kt @@ -291,9 +291,9 @@ fun PrivacySettingsBody(dialogViewModel: TorDialogViewModel) { ) SwitchSettingsRow( - R.string.tor_use_nip96_uploads, - R.string.tor_use_nip96_uploads_explainer, - dialogViewModel.nip96UploadsViaTor, + R.string.tor_use_media_uploads, + R.string.tor_use_media_uploads_explainer, + dialogViewModel.mediaUploadsViaTor, ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsFlow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsFlow.kt index c445b42351..4a8698c3a1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsFlow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorSettingsFlow.kt @@ -36,7 +36,7 @@ class TorSettingsFlow( val videosViaTor: MutableStateFlow = MutableStateFlow(false), val moneyOperationsViaTor: MutableStateFlow = MutableStateFlow(false), val nip05VerificationsViaTor: MutableStateFlow = MutableStateFlow(false), - val nip96UploadsViaTor: MutableStateFlow = MutableStateFlow(false), + val mediaUploadsViaTor: MutableStateFlow = MutableStateFlow(false), ) { // emits at every change in any of the properties. val propertyWatchFlow = @@ -54,7 +54,7 @@ class TorSettingsFlow( videosViaTor, moneyOperationsViaTor, nip05VerificationsViaTor, - nip96UploadsViaTor, + mediaUploadsViaTor, ), ) { flows -> TorSettings( @@ -88,7 +88,7 @@ class TorSettingsFlow( videosViaTor.value, moneyOperationsViaTor.value, nip05VerificationsViaTor.value, - nip96UploadsViaTor.value, + mediaUploadsViaTor.value, ) fun update(torSettings: TorSettings): Boolean { @@ -143,8 +143,8 @@ class TorSettingsFlow( nip05VerificationsViaTor.tryEmit(torSettings.nip05VerificationsViaTor) any = true } - if (nip96UploadsViaTor.value != torSettings.nip96UploadsViaTor) { - nip96UploadsViaTor.tryEmit(torSettings.nip96UploadsViaTor) + if (mediaUploadsViaTor.value != torSettings.mediaUploadsViaTor) { + mediaUploadsViaTor.tryEmit(torSettings.mediaUploadsViaTor) any = true } @@ -166,7 +166,7 @@ class TorSettingsFlow( MutableStateFlow(torSettings.videosViaTor), MutableStateFlow(torSettings.moneyOperationsViaTor), MutableStateFlow(torSettings.nip05VerificationsViaTor), - MutableStateFlow(torSettings.nip96UploadsViaTor), + MutableStateFlow(torSettings.mediaUploadsViaTor), ) } } diff --git a/amethyst/src/main/res/values-ar-rSA/strings.xml b/amethyst/src/main/res/values-ar-rSA/strings.xml index 20539cee1b..f3eb061cf4 100644 --- a/amethyst/src/main/res/values-ar-rSA/strings.xml +++ b/amethyst/src/main/res/values-ar-rSA/strings.xml @@ -393,8 +393,8 @@ المعاملات المالية التحقق من عنوان Nostr أستخدام Tor عند التحقق من عناوين NIP-05 - رفع الوسائط - أستخدام Tor عند رفع الوسائط + رفع الوسائط + أستخدام Tor عند رفع الوسائط مضمن إيقاف أساسي diff --git a/amethyst/src/main/res/values-cs-rCZ/strings.xml b/amethyst/src/main/res/values-cs-rCZ/strings.xml index 06a21b6cd5..ad69abba8f 100644 --- a/amethyst/src/main/res/values-cs-rCZ/strings.xml +++ b/amethyst/src/main/res/values-cs-rCZ/strings.xml @@ -591,8 +591,8 @@ Vynutit Tor na zaps, lightning a cashu převody Ověření Nostr adresy Vynutit Tor při ověřování NIP-05 adres - Nahrávání médií - Vynutit Tor při nahrávání obsahu + Nahrávání médií + Vynutit Tor při nahrávání obsahu Interní Orbot Vypnuto diff --git a/amethyst/src/main/res/values-cs/strings.xml b/amethyst/src/main/res/values-cs/strings.xml index fc59482114..b3e6b35dc8 100644 --- a/amethyst/src/main/res/values-cs/strings.xml +++ b/amethyst/src/main/res/values-cs/strings.xml @@ -444,8 +444,8 @@ Vynutit Tor na zaps, lightning a cashu převody Ověření Nostr adresy Vynutit Tor při ověřování NIP-05 adres - Nahrávání médií - Vynutit Tor při nahrávání obsahu + Nahrávání médií + Vynutit Tor při nahrávání obsahu Interní Orbot Vypnuto diff --git a/amethyst/src/main/res/values-de-rDE/strings.xml b/amethyst/src/main/res/values-de-rDE/strings.xml index 77c479819f..8fecce53c2 100644 --- a/amethyst/src/main/res/values-de-rDE/strings.xml +++ b/amethyst/src/main/res/values-de-rDE/strings.xml @@ -596,8 +596,8 @@ anz der Bedingungen ist erforderlich Erzwingen Sie Tor bei Zaps, Lightning und Cashu-Transfers Nostr Adressverifizierung Erzwingen Sie Tor bei der Überprüfung von NIP-05-Adressen - Medien-Uploads - Erzwingen Sie Tor beim Hochladen von Inhalten + Medien-Uploads + Erzwingen Sie Tor beim Hochladen von Inhalten Intern Orbot Aus diff --git a/amethyst/src/main/res/values-de/strings.xml b/amethyst/src/main/res/values-de/strings.xml index fd7c5ffa82..7e962d5e02 100644 --- a/amethyst/src/main/res/values-de/strings.xml +++ b/amethyst/src/main/res/values-de/strings.xml @@ -449,8 +449,8 @@ anz der Bedingungen ist erforderlich Erzwingen Sie Tor bei Zaps, Lightning und Cashu-Transfers Nostr Adressverifizierung Erzwingen Sie Tor bei der Überprüfung von NIP-05-Adressen - Medien-Uploads - Erzwingen Sie Tor beim Hochladen von Inhalten + Medien-Uploads + Erzwingen Sie Tor beim Hochladen von Inhalten Intern Orbot Aus diff --git a/amethyst/src/main/res/values-es-rES/strings.xml b/amethyst/src/main/res/values-es-rES/strings.xml index 205e5287f0..592c21cb86 100644 --- a/amethyst/src/main/res/values-es-rES/strings.xml +++ b/amethyst/src/main/res/values-es-rES/strings.xml @@ -452,7 +452,7 @@ Público Privado Mixto - Al parecer, aún no tienes ningún conjunto de seguimiento. + Al parecer, aún no tienes ningún conjunto de seguimiento. \nPulsa abajo para actualizar o pulsa los botones de añadir para crear uno nuevo. Añadir autor a conjunto de seguimiento @@ -502,8 +502,8 @@ Forzar Tor en transferencias de zaps, Lightning y Cashu Verificación de dirección de Nostr Forzar Tor al verificar direcciones NIP-05 - Subidas multimedia - Forzar Tor al subir contenido + Subidas multimedia + Forzar Tor al subir contenido Interno Orbot Desactivado diff --git a/amethyst/src/main/res/values-es-rMX/strings.xml b/amethyst/src/main/res/values-es-rMX/strings.xml index 64f8bcab9d..21b7445275 100644 --- a/amethyst/src/main/res/values-es-rMX/strings.xml +++ b/amethyst/src/main/res/values-es-rMX/strings.xml @@ -447,7 +447,7 @@ Público Privado Mixto - Al parecer, aún no tienes ningún conjunto de seguimiento. + Al parecer, aún no tienes ningún conjunto de seguimiento. \nToca abajo para actualizar o toca los botones de agregar para crear uno nuevo. Agregar autor a conjunto de seguimiento @@ -497,8 +497,8 @@ Forzar Tor en transferencias de zaps, Lightning y Cashu Verificación de dirección de Nostr Forzar Tor al verificar direcciones NIP-05 - Subidas multimedia - Forzar Tor al subir contenido + Subidas multimedia + Forzar Tor al subir contenido Interno Orbot Desactivado diff --git a/amethyst/src/main/res/values-es-rUS/strings.xml b/amethyst/src/main/res/values-es-rUS/strings.xml index bb790d8d7f..b9a8b7b915 100644 --- a/amethyst/src/main/res/values-es-rUS/strings.xml +++ b/amethyst/src/main/res/values-es-rUS/strings.xml @@ -447,7 +447,7 @@ Público Privado Mixto - Al parecer, aún no tienes ningún conjunto de seguimiento. + Al parecer, aún no tienes ningún conjunto de seguimiento. \nToca abajo para actualizar o toca los botones de agregar para crear uno nuevo. Agregar autor a conjunto de seguimiento @@ -497,8 +497,8 @@ Forzar Tor en transferencias de zaps, Lightning y Cashu Verificación de dirección de Nostr Forzar Tor al verificar direcciones NIP-05 - Subidas multimedia - Forzar Tor al subir contenido + Subidas multimedia + Forzar Tor al subir contenido Interno Orbot Desactivado diff --git a/amethyst/src/main/res/values-fa-rIR/strings.xml b/amethyst/src/main/res/values-fa-rIR/strings.xml index 7ee325eb60..617b462a75 100644 --- a/amethyst/src/main/res/values-fa-rIR/strings.xml +++ b/amethyst/src/main/res/values-fa-rIR/strings.xml @@ -446,8 +446,8 @@ تور را برای زپ، لایتنینگ و انتقال کَشو الزامی کن تایید آدرس ناستر تور را برای تایید آدرس های NIP-05 الزامی کن - بارگذاری رسانه - تور را برای بارگذاری محتوا الزامی کن + بارگذاری رسانه + تور را برای بارگذاری محتوا الزامی کن داخلی Orbot خاموش diff --git a/amethyst/src/main/res/values-fa/strings.xml b/amethyst/src/main/res/values-fa/strings.xml index 0c2e5174b0..ac4b7bee32 100644 --- a/amethyst/src/main/res/values-fa/strings.xml +++ b/amethyst/src/main/res/values-fa/strings.xml @@ -428,8 +428,8 @@ تور را برای زپ، لایتنینگ و انتقال کَشو الزامی کن تایید آدرس ناستر تور را برای تایید آدرس های NIP-05 الزامی کن - بارگذاری رسانه - تور را برای بارگذاری محتوا الزامی کن + بارگذاری رسانه + تور را برای بارگذاری محتوا الزامی کن داخلی Orbot خاموش diff --git a/amethyst/src/main/res/values-fr-rFR/strings.xml b/amethyst/src/main/res/values-fr-rFR/strings.xml index b2b8a1cc4f..6f19c6d696 100644 --- a/amethyst/src/main/res/values-fr-rFR/strings.xml +++ b/amethyst/src/main/res/values-fr-rFR/strings.xml @@ -595,8 +595,8 @@ Forcer Tor pour les transferts en zaps, lightning ou cashu Vérification de l\'adresse Nostr Forcer Tor lors de la vérification des adresses NIP-05 - Téléversements de média - Forcer Tor lors du téléversement de contenu + Téléversements de média + Forcer Tor lors du téléversement de contenu Interne Orbot Désactivé diff --git a/amethyst/src/main/res/values-fr/strings.xml b/amethyst/src/main/res/values-fr/strings.xml index bb35fd681d..2272f85208 100644 --- a/amethyst/src/main/res/values-fr/strings.xml +++ b/amethyst/src/main/res/values-fr/strings.xml @@ -440,8 +440,8 @@ Forcer Tor pour les transferts en zaps, lightning ou cashu Vérification de l\'adresse Nostr Forcer Tor lors de la vérification des adresses NIP-05 - Téléversements de média - Forcer Tor lors du téléversement de contenu + Téléversements de média + Forcer Tor lors du téléversement de contenu Interne Orbot Désactivé diff --git a/amethyst/src/main/res/values-hi-rIN/strings.xml b/amethyst/src/main/res/values-hi-rIN/strings.xml index 9b972509ab..d239d1b542 100644 --- a/amethyst/src/main/res/values-hi-rIN/strings.xml +++ b/amethyst/src/main/res/values-hi-rIN/strings.xml @@ -595,8 +595,8 @@ ज्साप लैटनिंग तथा काशयु व्यापार के लिए टोर का प्रयोग अवश्य करें नोस्ट्र पता सत्यापन निप॰-०५ पता सत्यापन के लिए टोर का प्रयोग अवश्य करें - चित्र चलचित्र अभिलेख आरोहण - चित्र चलचित्र अभिलेख आरोहण के लिए टोर का प्रयोग अवश्य करें + चित्र चलचित्र अभिलेख आरोहण + चित्र चलचित्र अभिलेख आरोहण के लिए टोर का प्रयोग अवश्य करें आन्तरीय ओर्बोट निष्क्रिय diff --git a/amethyst/src/main/res/values-hu-rHU/strings.xml b/amethyst/src/main/res/values-hu-rHU/strings.xml index ac2d581f2e..87211aac97 100644 --- a/amethyst/src/main/res/values-hu-rHU/strings.xml +++ b/amethyst/src/main/res/values-hu-rHU/strings.xml @@ -595,8 +595,8 @@ Tor kényszerítése Zap küldésekor, lightning és cashu tranzakciókhoz Nostr-cím hitelesítése Tor kényszerítése a NIP-05 címek hitelesítésekor - Média-feltöltések - Tor kényszerítése média feltöltésekor + Média-feltöltések + Tor kényszerítése média feltöltésekor Beépített Orbot Kikapcsolva diff --git a/amethyst/src/main/res/values-hu/strings.xml b/amethyst/src/main/res/values-hu/strings.xml index 039cf9427c..3248c74f87 100644 --- a/amethyst/src/main/res/values-hu/strings.xml +++ b/amethyst/src/main/res/values-hu/strings.xml @@ -446,8 +446,8 @@ Tor kényszerítése Zap küldésekor, lightning és cashu tranzakciókhoz Nostr-cím hitelesítése Tor kényszerítése a NIP-05 címek hitelesítésekor - Média-feltöltések - Tor kényszerítése média feltöltésekor + Média-feltöltések + Tor kényszerítése média feltöltésekor Beépített Orbot Kikapcsolva diff --git a/amethyst/src/main/res/values-nl-rNL/strings.xml b/amethyst/src/main/res/values-nl-rNL/strings.xml index 0d30b2b235..decfe03728 100644 --- a/amethyst/src/main/res/values-nl-rNL/strings.xml +++ b/amethyst/src/main/res/values-nl-rNL/strings.xml @@ -537,8 +537,8 @@ Forceer Tor op zaps, lightning en cashu transfers Nostr Adres verificatie Forceer Tor bij het verifiëren van NIP-05 adressen - Mediauploads - Forceer Tor bij het uploaden van content + Mediauploads + Forceer Tor bij het uploaden van content Intern Orbot Uit diff --git a/amethyst/src/main/res/values-nl/strings.xml b/amethyst/src/main/res/values-nl/strings.xml index e68d336353..d33b02be1e 100644 --- a/amethyst/src/main/res/values-nl/strings.xml +++ b/amethyst/src/main/res/values-nl/strings.xml @@ -439,8 +439,8 @@ Forceer Tor op zaps, lightning en cashu transfers Nostr Adres verificatie Forceer Tor bij het verifiëren van NIP-05 adressen - Mediauploads - Forceer Tor bij het uploaden van content + Mediauploads + Forceer Tor bij het uploaden van content Intern Orbot Uit diff --git a/amethyst/src/main/res/values-pl-rPL/strings.xml b/amethyst/src/main/res/values-pl-rPL/strings.xml index 80f3cf9e32..3b4f57df19 100644 --- a/amethyst/src/main/res/values-pl-rPL/strings.xml +++ b/amethyst/src/main/res/values-pl-rPL/strings.xml @@ -592,8 +592,8 @@ Wymuś Tor przy zapsach, transferach lightning and cashu Weryfikacja adresu Nostr Wymuś Tor podczas weryfikacji adresów NIP-05 - Wgrywanie mediów - Wymuś Tor podczas wgrywania zawartości + Wgrywanie mediów + Wymuś Tor podczas wgrywania zawartości Wewnętrznie Orbot Wył. diff --git a/amethyst/src/main/res/values-pt-rBR/strings.xml b/amethyst/src/main/res/values-pt-rBR/strings.xml index 09aa6def80..ca84bb6800 100644 --- a/amethyst/src/main/res/values-pt-rBR/strings.xml +++ b/amethyst/src/main/res/values-pt-rBR/strings.xml @@ -591,8 +591,8 @@ Forçar Tor em zaps, transfers relâmpago e cashu Verificação de Endereço Nostr Forçar Tor ao verificar endereços NIP-05 - Envio de Mídia - Forçar Tor ao enviar conteúdo + Envio de Mídia + Forçar Tor ao enviar conteúdo Interno Orbot Desativado diff --git a/amethyst/src/main/res/values-sl-rSI/strings.xml b/amethyst/src/main/res/values-sl-rSI/strings.xml index d72e872f76..7cf1252513 100644 --- a/amethyst/src/main/res/values-sl-rSI/strings.xml +++ b/amethyst/src/main/res/values-sl-rSI/strings.xml @@ -606,8 +606,8 @@ Za podpisovanje se je potrebno prijaviti s privatnim ključem Prisili tor pri Zapih, Lightning in Cashu plačilnih prenosih Preveritev Nostr naslova Prisili tor ob preverjanju NIP-05 naslovov - Nalaganje medijske vsebine - Prisili tor pri nalaganju vsebine + Nalaganje medijske vsebine + Prisili tor pri nalaganju vsebine Interno Orbot Izključeno diff --git a/amethyst/src/main/res/values-sv-rSE/strings.xml b/amethyst/src/main/res/values-sv-rSE/strings.xml index e8be7b477c..97a5cf60e2 100644 --- a/amethyst/src/main/res/values-sv-rSE/strings.xml +++ b/amethyst/src/main/res/values-sv-rSE/strings.xml @@ -590,8 +590,8 @@ Tvinga Tor på zaps, lightning och cashu överföringar Nostr Adress Verifiering Tvinga Tor vid verifiering av NIP-05 adresser - Mediauppladdningar - Tvinga Tor vid uppladdning av innehåll + Mediauppladdningar + Tvinga Tor vid uppladdning av innehåll Intern Orbot Av diff --git a/amethyst/src/main/res/values-zh-rCN/strings.xml b/amethyst/src/main/res/values-zh-rCN/strings.xml index 94d509ef4d..5574b554da 100644 --- a/amethyst/src/main/res/values-zh-rCN/strings.xml +++ b/amethyst/src/main/res/values-zh-rCN/strings.xml @@ -595,8 +595,8 @@ 强制为 Zap、闪电网络和 Cashu 转账时使用 Tor Nostr 地址验证 强制为 NIP-05 地址验证使用 Tor - 媒体上传 - 强制为上传媒体内容时使用 Tor + 媒体上传 + 强制为上传媒体内容时使用 Tor 内置 Orbot 关闭 diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 72b79c6fb6..04cebd1bf2 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -535,6 +535,7 @@ You have no NIP-96 servers set. You can use Amethyst\'s list, or add one below ↓ You have no Blossom servers set. You can use Amethyst\'s list, or add one below ↓ + Recommended Media Servers Built-in Media Servers Amethyst\'s default list. You can add them individually or add the list. Use Default List @@ -680,8 +681,8 @@ Nostr Address Verification Force Tor when verifying NIP-05 addresses - Media Uploads - Force Tor when uploading content + Media Uploads + Force Tor when uploading content Internal Orbot