diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 04d72b2012..deb50a69a6 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -1366,6 +1366,15 @@ 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." + } + 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)) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 0034bb9822..98b9d1de9a 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -265,7 +265,7 @@ struct GroupChatInfoView: View { } return nil } catch { - return responseError(error) + return setSimplexNameError(error, isChannel: true) } } ) diff --git a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift index 5d1263f383..407668f52c 100644 --- a/apps/ios/Shared/Views/UserSettings/UserAddressView.swift +++ b/apps/ios/Shared/Views/UserSettings/UserAddressView.swift @@ -204,7 +204,7 @@ struct UserAddressView: View { await MainActor.run { chatModel.updateUser(u) } return nil } catch { - return responseError(error) + return setSimplexNameError(error, isChannel: false) } } ) @@ -757,7 +757,7 @@ struct SetSimplexNameView: View { } .navigationTitle(titleKey) .alert(isPresented: $showAlert) { - Alert(title: Text("Error saving SimpleX name"), message: Text(alertMessage)) + Alert(title: Text("Error saving name"), message: Text(alertMessage)) } } 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 d7a942445b..aa562b6559 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,6 +1629,13 @@ object ChatController { } } + fun setSimplexNameErrorText(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 + fun connErrorText(e: ChatError): String = when { e is ChatError.ChatErrorChat && e.errorType is ChatErrorType.InvalidConnReq -> generalGetString(MR.strings.invalid_connection_link) @@ -1821,7 +1828,10 @@ object ChatController { return when { 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 -> throw Exception("failed to set SimpleX name: ${r.responseType} ${r.details}") + else -> { + if (r is API.Error) AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), setSimplexNameErrorText(r.err, false)) + throw Exception("failed to set SimpleX name: ${r.responseType} ${r.details}") + } } } @@ -2385,7 +2395,7 @@ 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), r.err.string) + AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), setSimplexNameErrorText(r.err, true)) null } else -> { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt index eb2ef42b29..183cd8e4c1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt @@ -373,7 +373,7 @@ private fun UserAddressLayout( withContext(Dispatchers.Main) { chatModel.updateUser(u) } true } catch (e: Exception) { - AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_saving_simplex_name), e.message ?: "") + Log.e(TAG, "apiSetUserName: ${e.message}") false } }, diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index 15b6433223..b4d77fc4cd 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -946,7 +946,9 @@ SimpleX name not verified Set SimpleX name name.simplex - Error saving SimpleX name + Error saving name + The SimpleX name %1$s is registered without channel link. Add channel link to the name via the registration page. + The SimpleX name %1$s is registered without SimpleX address. Add your SimpleX address to the name via the registration page. Set a SimpleX name so people can connect to you using @yourname instead of a link. The name must already be registered to your address. Set a SimpleX name so people can find this channel as #name. The name must be registered to this channel\'s address. Or show this code diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index 3588d5d207..dc03cd58dc 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -1499,12 +1499,12 @@ processChatCommand cxt nm = \case else do cl' <- case name_ of Nothing -> pure contactLink - Just SimplexNameInfo {nameDomain} -> do - UserContactLink {shortLinkDataSet, connLinkContact = CCLink fl sl_} <- withFastStore (`getUserAddress` user) + Just ni@SimplexNameInfo {nameDomain} -> do + UserContactLink {shortLinkDataSet, connLinkContact = CCLink fl sl_} <- withFastStore (`getUserAddress` user) case sl_ of Just sl | shortLinkDataSet -> do NameRecord {nrSimplexContact} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain - unless (nameResolvesTo sl nrSimplexContact) $ throwCmdError "name does not point to your address" + unless (nameResolvesTo sl nrSimplexContact) $ throwChatError $ CESimplexName ni SNENoValidLink pure $ Just (CLShort sl) _ -> throwCmdError "create the address short link and add it to name" let p' = (fromLocalProfile p :: Profile) {simplexName = mkSimplexNameClaim name_ Nothing, contactLink = cl'} @@ -3141,7 +3141,7 @@ processChatCommand cxt nm = \case forM_ (claimName <$> simplexName) $ \newName@SimplexNameInfo {nameDomain} -> when (Just newName /= (claimName <$> (existingAccess >>= publicGroupClaim))) $ do NameRecord {nrSimplexChannel} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain - unless (nameResolvesTo groupLink nrSimplexChannel) $ throwCmdError "name is not registered to this channel" + unless (nameResolvesTo groupLink nrSimplexChannel) $ throwChatError $ CESimplexName newName SNENoValidLink runUpdateGroupProfile user gInfo p {publicGroup = Just pg {publicGroupAccess = Just access}} Nothing -> throwChatError $ CECommandError "not a public group" APICreateGroupLink groupId mRole -> withUser $ \user -> withGroupLock "createGroupLink" groupId $ do