From ff09510b09de0f5d6a926bc5f36ec6fd783d349d Mon Sep 17 00:00:00 2001 From: spacedandy-agents-simplex <342056592+spacedandy-agents-simplex@users.noreply.github.com> Date: Fri, 23 Oct 2026 10:40:16 +0000 Subject: [PATCH] ui: let channel owners turn on "Sign messages", warning that earlier messages will show signature missing The channel preference was hidden while signing was recipient-only. Owners now see the switch; turning it on asks for confirmation, because subscribers who join later receive the earlier posts unsigned through history and see them as "signature missing". The "Signature missing" explanation now says the message may predate signing or have been forwarded by a relay without its signature, instead of only implying tampering. Run: 001-channel-signing-moderators, slice 3 --- .../Chat/Group/GroupPreferencesView.swift | 17 +++++++++++++++-- apps/ios/SimpleXChat/ChatTypes.swift | 2 +- .../views/chat/group/GroupPreferences.kt | 19 +++++++++++++++---- .../moko-resources/base/strings.xml | 5 ++++- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift index da15ab98a5..d9db16b559 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupPreferencesView.swift @@ -50,8 +50,21 @@ struct GroupPreferencesView: View { featureSection(.history, $preferences.history.enable) featureSection(.support, $preferences.support.enable, disabled: true) } else { - // hidden until message signing is user-facing (recipient-only stage) -// featureSection(.signMessages, $preferences.signMessages.enable) + featureSection(.signMessages, $preferences.signMessages.enable) + .onChange(of: preferences.signMessages.enable) { enable in + if enable == .on { + showAlert( + NSLocalizedString("Sign messages?", comment: "alert title"), + message: NSLocalizedString("Messages sent before will show \"signature missing\" to subscribers who join later.", comment: "alert message"), + actions: {[ + UIAlertAction(title: NSLocalizedString("Enable", comment: "alert button"), style: .default) { _ in }, + UIAlertAction(title: NSLocalizedString("Cancel", comment: "alert button"), style: .cancel) { _ in + preferences.signMessages.enable = .off + } + ]} + ) + } + } featureSection(.timedMessages, $preferences.timedMessages.enable) featureSection(.fullDelete, $preferences.fullDelete.enable) featureSection(.reactions, $preferences.reactions.enable) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index c77811f969..68300193d5 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -3158,7 +3158,7 @@ public enum MsgVerified: Decodable, Equatable, Hashable { switch self { case .sigMissing: return ( NSLocalizedString("Signature missing", comment: "alert title"), - NSLocalizedString("The channel required this message to be signed, but the signature is missing.", comment: "alert message") + NSLocalizedString("This channel requires signed messages, but this message has no signature. It may have been sent before signing was required, or a relay may have forwarded it without one.", comment: "alert message") ) default: return nil } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt index bd3af10c37..2be256d074 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupPreferences.kt @@ -178,10 +178,14 @@ private fun GroupPreferencesLayout( } } } - @Composable fun SignMessagesPreference() { + @Composable fun SignMessagesPreference(onEnable: ((() -> Unit) -> Unit)? = null) { val enableSignMessages = remember(preferences) { mutableStateOf(preferences.signMessages.enable) } FeatureSection(GroupFeature.SignMessages, enableSignMessages, null, groupInfo, preferences, onTTLUpdated) { enable, _ -> applyPrefs(preferences.copy(signMessages = GroupPreference(enable = enable))) + if (enable == GroupFeatureEnabled.ON) onEnable?.invoke { + enableSignMessages.value = GroupFeatureEnabled.OFF + applyPrefs(preferences.copy(signMessages = GroupPreference(enable = GroupFeatureEnabled.OFF))) + } } } ColumnWithScrollBar { @@ -216,9 +220,16 @@ private fun GroupPreferencesLayout( SectionDividerSpaced() SupportPreference(disabled = true) } else { - // hidden until message signing is user-facing (recipient-only stage) -// SignMessagesPreference() -// SectionDividerSpaced() + SignMessagesPreference(onEnable = { revert -> + AlertManager.shared.showAlertDialog( + title = generalGetString(MR.strings.sign_messages_question), + text = generalGetString(MR.strings.sign_messages_alert_desc), + confirmText = generalGetString(MR.strings.sign_messages_enable), + onDismiss = revert, + onDismissRequest = revert, + ) + }) + SectionDividerSpaced() TimedMessagesPreference() SectionDividerSpaced() FullDeletePreference() diff --git a/apps/multiplatform/common/src/commonMain/moko-resources/base/strings.xml b/apps/multiplatform/common/src/commonMain/moko-resources/base/strings.xml index cd80492607..793d72244b 100644 --- a/apps/multiplatform/common/src/commonMain/moko-resources/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/moko-resources/base/strings.xml @@ -787,10 +787,13 @@ Do not require signing messages. Message signing is required. Message signing is not required. + Sign messages? + Messages sent before will show "signature missing" to subscribers who join later. + Enable Show signature Show encryption Signature missing - The channel required this message to be signed, but the signature is missing. + This channel requires signed messages, but this message has no signature. It may have been sent before signing was required, or a relay may have forwarded it without one. Live message! Send a live message - it will update for the recipient(s) as you type it Send