diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index b09d155d17..382e08548b 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -1919,7 +1919,7 @@ processChatCommand vr nm = \case where recreateConn user conn@PendingContactConnection {customUserProfileId, connLinkInv} newUser = do subMode <- chatReadVar subscriptionMode - let short = isJust $ connShortLink =<< connLinkInv + let short = isJust $ (\(CCLink _ sl) -> sl) =<< connLinkInv userLinkData_ | short = Just $ UserInvLinkData $ contactShortLinkData (userProfileDirect newUser Nothing Nothing True) Nothing | otherwise = Nothing @@ -2059,8 +2059,8 @@ processChatCommand vr nm = \case gInfo <- withFastStore $ \db -> getGroupInfo db vr user groupId case gInfo of GroupInfo {preparedGroup = Nothing} -> throwCmdError "group doesn't have link to connect" - GroupInfo {useRelays = BoolDef True, preparedGroup = Just PreparedGroup {connLinkToConnect}} -> do - sLnk <- case toShortLinkContact connLinkToConnect of + GroupInfo {useRelays = BoolDef True, preparedGroup = Just PreparedGroup {connLinkToConnect = PreparedGroupLink {connShortLink = sLnk_}}} -> do + sLnk <- case sLnk_ of Just sl -> pure sl Nothing -> throwChatError $ CEException "failed to retrieve relays: no short link" (FixedLinkData {linkConnReq = mainCReq@(CRContactUri crData), linkEntityId, rootKey}, cData@(ContactLinkData _ UserContactData {owners, relays})) <- getShortLinkConnReq nm user sLnk @@ -2136,6 +2136,9 @@ processChatCommand vr nm = \case newConnIds <- getAgentConnShortLinkAsync user CFGetRelayDataJoin Nothing relayLink withStore' $ \db -> createRelayMemberConnectionAsync db user gInfo' relayMember relayLink newConnIds subMode GroupInfo {preparedGroup = Just PreparedGroup {connLinkToConnect, welcomeSharedMsgId, requestSharedMsgId}} -> do + ccLink <- case toCreatedLinkContact connLinkToConnect of + Just cl -> pure cl + Nothing -> throwChatError $ CEException "no full link to connect" hostMember <- withFastStore $ \db -> getHostMember db vr user groupId msg_ <- forM msgContent_ $ \mc -> case requestSharedMsgId of Just smId -> pure (smId, mc) @@ -2143,7 +2146,7 @@ processChatCommand vr nm = \case smId <- getSharedMsgId withFastStore' $ \db -> setRequestSharedMsgIdForGroup db groupId smId pure (smId, mc) - r <- connectViaContact user (Just $ PCEGroup gInfo hostMember) incognito connLinkToConnect welcomeSharedMsgId msg_ `catchAllErrors` \e -> do + r <- connectViaContact user (Just $ PCEGroup gInfo hostMember) incognito ccLink welcomeSharedMsgId msg_ `catchAllErrors` \e -> do -- get updated group info, in case connection was started (connLinkPreparedConnection) - in UI it would lock ability to change -- user or incognito profile for group or business chat, in case server received request while client got network error gInfo' <- withFastStore $ \db -> getGroupInfo db vr user groupId @@ -4070,7 +4073,7 @@ processChatCommand vr nm = \case encodeShortLinkData $ RelayAddressLinkData {relayProfile = RelayProfile {displayName, fullName, shortDescr, image}} updatePCCShortLinkData :: PendingContactConnection -> Profile -> CM (Maybe ShortLinkInvitation) updatePCCShortLinkData conn@PendingContactConnection {connLinkInv} profile = - forM (connShortLink =<< connLinkInv) $ \_ -> do + forM ((\(CCLink _ sl) -> sl) =<< connLinkInv) $ \_ -> do let userData = contactShortLinkData profile Nothing userLinkData = UserInvLinkData userData shortenShortLink' =<< withAgent (\a -> setConnShortLink a nm (aConnId' conn) SCMInvitation userLinkData Nothing) diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 93fdf1868a..86315266d9 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -604,7 +604,7 @@ deleteContactCardKeepConn db connId Contact {contactId, profile = LocalProfile { createPreparedGroup :: DB.Connection -> TVar ChaChaDRG -> VersionRangeChat -> User -> GroupProfile -> Bool -> CreatedLinkContact -> Maybe SharedMsgId -> Bool -> GroupMemberRole -> Maybe Int64 -> ExceptT StoreError IO (GroupInfo, Maybe GroupMember) createPreparedGroup db gVar vr user@User {userId, userContactId} groupProfile business connLinkToConnect welcomeSharedMsgId useRelays userMemberRole publicMemberCount_ = do currentTs <- liftIO getCurrentTime - let prepared = Just (connLinkToConnect, welcomeSharedMsgId) + let prepared = Just (toPreparedGroupLink connLinkToConnect, welcomeSharedMsgId) (groupId, groupLDN) <- createGroup_ db userId groupProfile prepared Nothing useRelays Nothing publicMemberCount_ currentTs hostMemberId_ <- if useRelays @@ -841,7 +841,7 @@ createGroupViaLink' ) insertedRowId db -createGroup_ :: DB.Connection -> UserId -> GroupProfile -> Maybe (CreatedLinkContact, Maybe SharedMsgId) -> Maybe BusinessChatInfo -> Bool -> Maybe RelayStatus -> Maybe Int64 -> UTCTime -> ExceptT StoreError IO (GroupId, Text) +createGroup_ :: DB.Connection -> UserId -> GroupProfile -> Maybe (PreparedGroupLink, Maybe SharedMsgId) -> Maybe BusinessChatInfo -> Bool -> Maybe RelayStatus -> Maybe Int64 -> UTCTime -> ExceptT StoreError IO (GroupId, Text) createGroup_ db userId groupProfile prepared business useRelays relayOwnStatus publicMemberCount_ currentTs = ExceptT $ do let GroupProfile {displayName, fullName, shortDescr, description, image, publicGroup, groupPreferences, memberAdmission} = groupProfile (groupType_, groupLink_, publicGroupId_) = case publicGroup of diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index af0958ed35..43324c5bb6 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -38,7 +38,7 @@ import Simplex.Chat.Types import Simplex.Chat.Types.Preferences import Simplex.Chat.Types.Shared import Simplex.Chat.Types.UITheme -import Simplex.Messaging.Agent.Protocol (AConnShortLink (..), AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionRequestUri, CreatedConnLink (..), UserId, connMode) +import Simplex.Messaging.Agent.Protocol (AConnShortLink (..), AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionMode (..), ConnectionRequestUri, CreatedConnLink (..), UserId, connMode) import Simplex.Messaging.Agent.Store (AnyStoreError (..)) import Simplex.Messaging.Agent.Store.AgentStore (firstRow, maybeFirstRow) import Simplex.Messaging.Agent.Store.Common (withSavepoint) @@ -456,9 +456,9 @@ toPreparedContactRow = \case type NewPreparedGroupRow m = (Maybe (ConnectionRequestUri m), Maybe (ConnShortLink m), Maybe SharedMsgId) -toPreparedGroupRow :: Maybe (CreatedConnLink m, Maybe SharedMsgId) -> NewPreparedGroupRow m +toPreparedGroupRow :: Maybe (PreparedGroupLink, Maybe SharedMsgId) -> NewPreparedGroupRow 'CMContact toPreparedGroupRow = \case - Just (CCLink fullLink shortLink, welcomeSharedMsgId) -> (Just fullLink, shortLink, welcomeSharedMsgId) + Just (PreparedGroupLink {connFullLink, connShortLink}, welcomeSharedMsgId) -> (connFullLink, connShortLink, welcomeSharedMsgId) Nothing -> (Nothing, Nothing, Nothing) {-# INLINE toPreparedGroupRow #-} @@ -686,8 +686,9 @@ toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, toPreparedGroup :: PreparedGroupRow -> Maybe PreparedGroup toPreparedGroup = \case - (Just fullLink, shortLink_, BI connLinkPreparedConnection, BI connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId) -> - Just PreparedGroup {connLinkToConnect = CCLink fullLink shortLink_, connLinkPreparedConnection, connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId} + (fullLink_, shortLink_, BI connLinkPreparedConnection, BI connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId) + | isJust fullLink_ || isJust shortLink_ -> + Just PreparedGroup {connLinkToConnect = PreparedGroupLink {connFullLink = fullLink_, connShortLink = shortLink_}, connLinkPreparedConnection, connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId} _ -> Nothing toPublicGroupProfile :: Maybe GroupType -> Maybe ShortLinkContact -> Maybe B64UrlByteString -> Maybe PublicGroupProfile diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index b24d3e0a0c..479f08d062 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -52,7 +52,7 @@ import Simplex.Chat.Types.Shared import Simplex.Chat.Types.UITheme import Simplex.FileTransfer.Description (FileDigest) import Simplex.FileTransfer.Types (RcvFileId, SndFileId) -import Simplex.Messaging.Agent.Protocol (ACorrId, ACreatedConnLink, AEventTag (..), AEvtTag (..), ConnId, ConnShortLink, ConnectionLink, ConnectionMode (..), ConnectionRequestUri, CreatedConnLink, InvitationId, SAEntity (..), UserId) +import Simplex.Messaging.Agent.Protocol (ACorrId, ACreatedConnLink, AEventTag (..), AEvtTag (..), ConnId, ConnShortLink, ConnectionLink, ConnectionMode (..), ConnectionRequestUri, CreatedConnLink (..), InvitationId, SAEntity (..), UserId) import Simplex.Messaging.Agent.Store.DB (Binary (..), blobFieldDecoder, fromTextField_) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFileArgs (..)) @@ -518,8 +518,21 @@ instance FromField BusinessChatType where fromField = fromTextField_ textDecode instance ToField BusinessChatType where toField = toField . textEncode +data PreparedGroupLink = PreparedGroupLink + { connFullLink :: Maybe ConnReqContact, + connShortLink :: Maybe ShortLinkContact + } + deriving (Eq, Show) + +toPreparedGroupLink :: CreatedLinkContact -> PreparedGroupLink +toPreparedGroupLink (CCLink fl sl) = PreparedGroupLink (Just fl) sl + +toCreatedLinkContact :: PreparedGroupLink -> Maybe CreatedLinkContact +toCreatedLinkContact PreparedGroupLink {connFullLink = Just fl, connShortLink} = Just $ CCLink fl connShortLink +toCreatedLinkContact _ = Nothing + data PreparedGroup = PreparedGroup - { connLinkToConnect :: CreatedLinkContact, + { connLinkToConnect :: PreparedGroupLink, connLinkPreparedConnection :: Bool, connLinkStartedConnection :: Bool, welcomeSharedMsgId :: Maybe SharedMsgId, -- it is stored only for business chats, and only if welcome message is specified @@ -2090,6 +2103,8 @@ $(JQ.deriveJSON (enumJSON $ dropPrefix "BC") ''BusinessChatType) $(JQ.deriveJSON defaultJSON ''BusinessChatInfo) +$(JQ.deriveJSON defaultJSON ''PreparedGroupLink) + $(JQ.deriveJSON defaultJSON ''PreparedGroup) $(JQ.deriveToJSON defaultJSON ''GroupSummary)