From fbb171019ffd390e631234b2778aa01d2d6f5333 Mon Sep 17 00:00:00 2001 From: "Evgeny @ SimpleX Chat" <259188159+evgeny-simplex@users.noreply.github.com> Date: Wed, 1 Jul 2026 16:35:10 +0000 Subject: [PATCH] better alert when saving names --- apps/ios/Shared/Model/SimpleXAPI.swift | 30 +++++++++++-------- .../Views/Chat/Group/GroupChatInfoView.swift | 4 +-- .../Views/UserSettings/UserAddressView.swift | 14 ++++----- .../chat/simplex/common/model/SimpleXAPI.kt | 15 +++++++--- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index deb50a69a6..bd4d417f97 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -1366,22 +1366,27 @@ func apiSetProfileAddress(on: Bool) async throws -> User? { } // name is the encoded SimplexName (e.g. "@alice.simplex"); nil clears it -func setSimplexNameError(_ error: Error, isChannel: Bool) -> String { - if let e = error as? ChatError, case let .error(.simplexName(name, .noValidLink)) = e { - return isChannel - ? "The SimpleX name \(name.shortName) is registered without channel link. Add channel link to the name via the registration page." - : "The SimpleX name \(name.shortName) is registered without SimpleX address. Add your SimpleX address to the name via the registration page." +// owner-specific SNENoValidLink wording; everything else reuses the general apiConnectResponseAlert +func showSetSimplexNameError(_ r: APIResult, isChannel: Bool) { + if case let .error(.simplexName(name, .noValidLink)) = r.unexpected { + let format = isChannel + ? NSLocalizedString("The SimpleX name %@ is registered without channel link. Add channel link to the name via the registration page.", comment: "alert message") + : NSLocalizedString("The SimpleX name %@ is registered without SimpleX address. Add your SimpleX address to the name via the registration page.", comment: "alert message") + showAlert(NSLocalizedString("Error saving name", comment: "alert title"), message: String.localizedStringWithFormat(format, name.shortName)) + } else { + AlertManager.shared.showAlert(apiConnectResponseAlert(r)) } - return responseError(error) } func apiSetUserName(_ name: String?) async throws -> User { let userId = try currentUserId("apiSetUserName") - let r: ChatResponse1 = try await chatSendCmd(.apiSetUserName(userId: userId, name: name)) + let r: APIResult = await chatApiSendCmd(.apiSetUserName(userId: userId, name: name)) switch r { - case let .userProfileUpdated(user, _, _, _): return user - case let .userProfileNoChange(user): return user - default: throw r.unexpected + case let .result(.userProfileUpdated(user, _, _, _)): return user + case let .result(.userProfileNoChange(user)): return user + default: + showSetSimplexNameError(r, isChannel: false) + throw r.unexpected } } @@ -2064,8 +2069,9 @@ func apiUpdateGroup(_ groupId: Int64, _ groupProfile: GroupProfile) async throws } func apiSetPublicGroupAccess(_ groupId: Int64, access: PublicGroupAccess) async throws -> GroupInfo { - let r: ChatResponse2 = try await chatSendCmd(.apiSetPublicGroupAccess(groupId: groupId, access: access)) - if case let .groupUpdated(_, toGroup) = r { return toGroup } + let r: APIResult = await chatApiSendCmd(.apiSetPublicGroupAccess(groupId: groupId, access: access)) + if case let .result(.groupUpdated(_, toGroup)) = r { return toGroup } + showSetSimplexNameError(r, isChannel: true) throw r.unexpected } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 72587a022f..251f0dd2d0 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -263,9 +263,9 @@ struct GroupChatInfoView: View { chatModel.updateGroup(gInfo) groupInfo = gInfo } - return nil + return true } catch { - return setSimplexNameError(error, isChannel: true) + return false } } ) diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift index 800504bf0f..6342d16ac7 100644 --- a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift +++ b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift @@ -202,9 +202,9 @@ struct UserAddressView: View { do { let u = try await apiSetUserName(name) await MainActor.run { chatModel.updateUser(u) } - return nil + return true } catch { - return setSimplexNameError(error, isChannel: false) + return false } } ) @@ -718,7 +718,7 @@ struct SetSimplexNameView: View { let footer: LocalizedStringKey let prefix: String @State var nameText: String - let save: (String?) async -> String? + let save: (String?) async -> Bool @Environment(\.dismiss) var dismiss @EnvironmentObject var theme: AppTheme @State private var saving = false @@ -738,14 +738,10 @@ struct SetSimplexNameView: View { Button { saving = true Task { - let err = await save(normalized()) + let ok = await save(normalized()) await MainActor.run { saving = false - if let err { - showAlert(NSLocalizedString("Error saving name", comment: "alert title"), message: err) - } else { - dismiss() - } + if ok { dismiss() } } } } label: { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index aa562b6559..68b058b963 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -1629,12 +1629,13 @@ object ChatController { } } - fun setSimplexNameErrorText(err: ChatError, isChannel: Boolean): String = + // owner-specific wording for setting one's own/channel name; null for other errors (handled by apiConnectResponseAlert) + fun simplexNameOwnerError(err: ChatError, isChannel: Boolean): String? = if (err is ChatError.ChatErrorChat && err.errorType is ChatErrorType.SimplexName && err.errorType.simplexNameError is SimplexNameError.NoValidLink) { val name = err.errorType.simplexName.shortName if (isChannel) generalGetString(MR.strings.simplex_name_owner_no_channel_link).format(name) else generalGetString(MR.strings.simplex_name_owner_no_address).format(name) - } else err.string + } else null fun connErrorText(e: ChatError): String = when { e is ChatError.ChatErrorChat && e.errorType is ChatErrorType.InvalidConnReq -> @@ -1829,7 +1830,11 @@ object ChatController { r is API.Result && r.res is CR.UserProfileUpdated -> r.res.user.updateRemoteHostId(rh) r is API.Result && r.res is CR.UserProfileNoChange -> r.res.user.updateRemoteHostId(rh) else -> { - if (r is API.Error) AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), setSimplexNameErrorText(r.err, false)) + if (r is API.Error) { + val ownerMsg = simplexNameOwnerError(r.err, isChannel = false) + if (ownerMsg != null) AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), ownerMsg) + else apiConnectResponseAlert(r) + } throw Exception("failed to set SimpleX name: ${r.responseType} ${r.details}") } } @@ -2395,7 +2400,9 @@ object ChatController { return when { r is API.Result && r.res is CR.GroupUpdated -> r.res.toGroup r is API.Error -> { - AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), setSimplexNameErrorText(r.err, true)) + val ownerMsg = simplexNameOwnerError(r.err, isChannel = true) + if (ownerMsg != null) AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), ownerMsg) + else apiConnectResponseAlert(r) null } else -> {