From 48a4221ed68a72e4b675d5baa66b41b9e0718d6a Mon Sep 17 00:00:00 2001 From: shum Date: Wed, 3 Jun 2026 17:59:00 +0000 Subject: [PATCH] chat: share/copy output prefers simplexName when present When a contact or group has a simplex_name stored, the share-link render path emits the canonical simplex:/name... URI (via strEncode) instead of the underlying connection link. Falls back to the existing link rendering when simplexName is Nothing. Final commit of the ConnectTarget plumbing chain: end-to-end users can now (a) connect via @alice.simplex / #group.simplex with the agent layer carrying the name, (b) see the simplex name on the contact/group records and in viewConnectionPlan, (c) share the contact using the namespace-canonical form rather than the raw URI. --- src/Simplex/Chat/View.hs | 19 +++++++++++++------ tests/ViewTests.hs | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index a6e1a7216a..58b4c0c078 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -1124,6 +1124,13 @@ simplexChatContact' = \case CLFull (CRContactUri crData) -> CLFull $ CRContactUri crData {crScheme = simplexChat} l@(CLShort _) -> l +-- Prefer the canonical "simplex:/name@..." / "#..." URI when a +-- SimplexNameInfo is present on the entity; fall back to the raw +-- connection-link bytes. +shareLinkStr :: Maybe SimplexNameInfo -> B.ByteString -> B.ByteString +shareLinkStr (Just ni) _ = strEncode ni +shareLinkStr Nothing fallback = fallback + -- TODO [short links] show all settings viewAddressSettings :: AddressSettings -> [StyledString] viewAddressSettings AddressSettings {businessAddress, autoAccept, autoReply} = case autoAccept of @@ -1138,10 +1145,10 @@ viewAddressSettings AddressSettings {businessAddress, autoAccept, autoReply} = c _ -> ["auto_accept off"] groupLink_ :: StyledString -> GroupInfo -> GroupLink -> [StyledString] -groupLink_ intro g GroupLink {connLinkContact = CCLink cReq shortLink, acceptMemberRole} = +groupLink_ intro g@GroupInfo {simplexName} GroupLink {connLinkContact = CCLink cReq shortLink, acceptMemberRole} = [ intro, "", - plain $ maybe cReqStr strEncode shortLink, + plain $ shareLinkStr simplexName $ maybe cReqStr strEncode shortLink, "", "Anybody can connect to you and join group as " <> showRole acceptMemberRole <> " with: " <> highlight' "/c ", "to show it again: " <> highlight ("/show link #" <> viewGroupName g), @@ -1215,12 +1222,12 @@ viewGroupRelays g relays = <> map showRelay relays viewGroupLinkRelaysUpdated :: GroupInfo -> GroupLink -> [GroupRelay] -> [StyledString] -viewGroupLinkRelaysUpdated g groupLink relays = +viewGroupLinkRelaysUpdated g@GroupInfo {simplexName} groupLink relays = [ttyFullGroup g <> ": group link relays updated, current relays:"] <> map showRelay relays <> [ "group link:", - plain $ maybe cReqStr strEncode shortLink + plain $ shareLinkStr simplexName $ maybe cReqStr strEncode shortLink ] where GroupLink {connLinkContact = CCLink cReq shortLink} = groupLink @@ -1765,10 +1772,10 @@ smpProxyModeStr SPMNever _ = "private message routing disabled." smpProxyModeStr mode fallback = T.unpack $ safeDecodeUtf8 $ "private message routing mode: " <> strEncode mode <> ", fallback: " <> strEncode fallback viewContactInfo :: Contact -> Maybe ConnectionStats -> Maybe Profile -> [StyledString] -viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink}, activeConn, uiThemes, customData} stats incognitoProfile = +viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink}, activeConn, uiThemes, customData, simplexName} stats incognitoProfile = ["contact ID: " <> sShow contactId] <> maybe [] viewConnectionStats stats - <> maybe [] (\l -> ["contact address: " <> (plain . strEncode) (simplexChatContact' l)]) contactLink + <> maybe [] (\l -> ["contact address: " <> plain (shareLinkStr simplexName (strEncode (simplexChatContact' l)))]) contactLink <> maybe ["you've shared main profile with this contact"] (\p -> ["you've shared incognito profile with this contact: " <> incognitoProfile' p]) diff --git a/tests/ViewTests.hs b/tests/ViewTests.hs index 085a56af44..8c34ebb5e2 100644 --- a/tests/ViewTests.hs +++ b/tests/ViewTests.hs @@ -4,11 +4,25 @@ module ViewTests where import Data.Time import Simplex.Chat.View +import Simplex.Messaging.Agent.Protocol (SimplexNameDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..)) import Test.Hspec viewTests :: Spec viewTests = do testRecent + testShareLinkStr + +testShareLinkStr :: Spec +testShareLinkStr = describe "shareLinkStr" $ do + let alice = SimplexNameInfo NTContact (SimplexNameDomain TLDSimplex "alice" []) + grp = SimplexNameInfo NTPublicGroup (SimplexNameDomain TLDSimplex "team" []) + fallback = "simplex:/contact#/?v=2-7&smp=smp%3A%2F%2Fexample" + it "uses simplex:/name URI for a contact's simplex name" $ + shareLinkStr (Just alice) fallback `shouldBe` "simplex:/name@alice.simplex" + it "uses simplex:/name URI for a public group simplex name" $ + shareLinkStr (Just grp) fallback `shouldBe` "simplex:/name#team.simplex" + it "falls back to the raw connection link when simplexName is Nothing" $ + shareLinkStr Nothing fallback `shouldBe` fallback testRecent :: Spec testRecent = describe "recent" $ do