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 10e9d405c..6154f2693 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -529,6 +529,14 @@ class Account( return false } + suspend fun updateDisableClientTag(disable: Boolean): Boolean { + if (settings.updateDisableClientTag(disable)) { + sendNewAppSpecificData() + return true + } + return false + } + suspend fun updateFilterSpam(filterSpam: Boolean): Boolean { if (settings.updateFilterSpam(filterSpam)) { if (!settings.syncedSettings.security.filterSpamFromStrangers.value) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt index b6aace912..568925f1d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt @@ -403,6 +403,14 @@ class AccountSettings( } } + fun updateDisableClientTag(disable: Boolean): Boolean = + if (syncedSettings.security.updateDisableClientTag(disable)) { + saveAccountSettings() + true + } else { + false + } + // --- // list names // --- diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt index adc3299ca..9d3721b3b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettings.kt @@ -55,6 +55,7 @@ class AccountSyncedSettings( MutableStateFlow(internalSettings.security.filterSpamFromStrangers), MutableStateFlow(internalSettings.security.maxHashtagLimit), MutableStateFlow(internalSettings.security.sendKind0EventsToLocalRelay), + MutableStateFlow(internalSettings.security.disableClientTag), ) val videoPlayer = AccountVideoPlayerPreferences( @@ -82,6 +83,7 @@ class AccountSyncedSettings( security.filterSpamFromStrangers.value, security.maxHashtagLimit.value, security.sendKind0EventsToLocalRelay.value, + security.disableClientTag.value, ), videoPlayer = AccountVideoPlayerPreferencesInternal(videoPlayer.buttonItems.value), ) @@ -138,6 +140,10 @@ class AccountSyncedSettings( security.sendKind0EventsToLocalRelay.tryEmit(syncedSettingsInternal.security.sendKind0EventsToLocalRelay) } + if (security.disableClientTag.value != syncedSettingsInternal.security.disableClientTag) { + security.disableClientTag.tryEmit(syncedSettingsInternal.security.disableClientTag) + } + val newVideoPlayerButtonItems = syncedSettingsInternal.videoPlayer.buttonItems.toImmutableList() if (!equalImmutableLists(videoPlayer.buttonItems.value, newVideoPlayerButtonItems)) { videoPlayer.buttonItems.tryEmit(newVideoPlayerButtonItems) @@ -233,6 +239,7 @@ class AccountSecurityPreferences( var filterSpamFromStrangers: MutableStateFlow = MutableStateFlow(true), val maxHashtagLimit: MutableStateFlow = MutableStateFlow(5), var sendKind0EventsToLocalRelay: MutableStateFlow = MutableStateFlow(false), + val disableClientTag: MutableStateFlow = MutableStateFlow(false), ) { fun updateShowSensitiveContent(show: Boolean?): Boolean { if (showSensitiveContent.value != show) { @@ -273,4 +280,12 @@ class AccountSecurityPreferences( } else { false } + + fun updateDisableClientTag(disable: Boolean): Boolean = + if (disable != disableClientTag.value) { + disableClientTag.tryEmit(disable) + true + } else { + false + } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt index efc03475a..a272bfe02 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSyncedSettingsInternal.kt @@ -147,4 +147,5 @@ class AccountSecurityPreferencesInternal( var filterSpamFromStrangers: Boolean = true, val maxHashtagLimit: Int = 5, var sendKind0EventsToLocalRelay: Boolean = false, + var disableClientTag: Boolean = false, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt index bec0e724d..655af6970 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt @@ -135,7 +135,12 @@ class AccountCacheState( val cached = accounts.value[signer.pubKey] if (cached != null) return cached - val signerWithClientTag = NostrSignerWithClientTag(signer, CLIENT_TAG_NAME) + val signerWithClientTag = + NostrSignerWithClientTag( + inner = signer, + clientName = CLIENT_TAG_NAME, + disabled = { accountSettings.syncedSettings.security.disableClientTag.value }, + ) val accountDir = File(rootFilesDir(), "accounts/${signer.pubKey}").apply { mkdirs() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 60a1d5624..886cf761f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1112,6 +1112,8 @@ class AccountViewModel( fun updateWarnReports(warnReports: Boolean) = launchSigner { account.updateWarnReports(warnReports) } + fun updateDisableClientTag(disable: Boolean) = launchSigner { account.updateDisableClientTag(disable) } + fun updateFilterSpam(filterSpam: Boolean) = launchSigner { if (account.updateFilterSpam(filterSpam)) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/SecurityFiltersScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/SecurityFiltersScreen.kt index 0cd081e4d..2dda65234 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/SecurityFiltersScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/SecurityFiltersScreen.kt @@ -371,6 +371,21 @@ private fun HeaderOptions(accountViewModel: AccountViewModel) { ) } + SettingsRow( + R.string.disable_client_tag_title, + R.string.disable_client_tag_explainer, + ) { + var disableClientTag by remember { mutableStateOf(accountViewModel.account.settings.syncedSettings.security.disableClientTag.value) } + + Switch( + checked = disableClientTag, + onCheckedChange = { + disableClientTag = it + accountViewModel.updateDisableClientTag(disableClientTag) + }, + ) + } + SettingsRow( R.string.show_sensitive_content_title, R.string.show_sensitive_content_explainer, diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index f5bc69a87..5864d5bc0 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -1178,6 +1178,8 @@ Filter spam Hides posts from strangers that were exactly the same for 5 or more times + Don\'t add client tag to my events + When enabled, Amethyst will not append a NIP-89 client tag to events you publish. Warn on reports Shows a warning message when posts have 5 or more reports from your follows Show sensitive content diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/NostrSignerWithClientTag.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/NostrSignerWithClientTag.kt index 1aa8b4de6..5856a0ebf 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/NostrSignerWithClientTag.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip89AppHandlers/clientTag/NostrSignerWithClientTag.kt @@ -40,12 +40,19 @@ import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent class NostrSignerWithClientTag( val inner: NostrSigner, val clientTag: Array, + val disabled: () -> Boolean = { false }, ) : NostrSigner(inner.pubKey) { constructor( inner: NostrSigner, clientName: String, ) : this(inner, ClientTag.assemble(clientName)) + constructor( + inner: NostrSigner, + clientName: String, + disabled: () -> Boolean, + ) : this(inner, ClientTag.assemble(clientName), disabled) + constructor( inner: NostrSigner, clientName: String, @@ -60,7 +67,12 @@ class NostrSignerWithClientTag( kind: Int, tags: Array>, content: String, - ): T = inner.sign(createdAt, kind, appendClientTag(tags), content) + ): T = + if (disabled()) { + inner.sign(createdAt, kind, tags, content) + } else { + inner.sign(createdAt, kind, appendClientTag(tags), content) + } override suspend fun nip04Encrypt( plaintext: String,