From bfab76ed905bf67eade32305128bbe660954f026 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Thu, 18 Jul 2024 20:33:51 +0400 Subject: [PATCH] core: allow sending messages immediately on joinConnection, acceptContact (#4465) --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat.hs | 41 ++++++++++++++----- src/Simplex/Chat/Controller.hs | 1 + src/Simplex/Chat/Store/Direct.hs | 6 +-- src/Simplex/Chat/Store/Files.hs | 2 +- src/Simplex/Chat/Store/Groups.hs | 10 ++--- src/Simplex/Chat/Store/Profiles.hs | 2 +- src/Simplex/Chat/Store/Shared.hs | 8 ++-- src/Simplex/Chat/Terminal/Output.hs | 2 + src/Simplex/Chat/Types.hs | 6 +-- src/Simplex/Chat/View.hs | 8 +++- tests/ChatClient.hs | 5 ++- tests/ChatTests/Direct.hs | 10 ++--- tests/ChatTests/Groups.hs | 32 +++++---------- tests/ChatTests/Profiles.hs | 62 +++++++++++++++-------------- 16 files changed, 111 insertions(+), 88 deletions(-) diff --git a/cabal.project b/cabal.project index 3573976290..663bff2624 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 8d56b0ba8519bdc68a3777d8d0672fbe01957479 + tag: 0be7ebed5c343e9f55a93224121f8a6df9333522 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 9f1dd6d69c..9a22ea9fe4 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."8d56b0ba8519bdc68a3777d8d0672fbe01957479" = "1yfcgnkhal6kj26kcl805152b1gai2ncyfq9lyq5k8jvdh0hpq99"; + "https://github.com/simplex-chat/simplexmq.git"."0be7ebed5c343e9f55a93224121f8a6df9333522" = "1bx6p06nwrqsc5wc8hp86k8198vn36cs5zva2rb9zhixnjcx79ap"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 46c8f97d53..2983afa29a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -3323,8 +3323,9 @@ acceptContactRequest user UserContactRequest {agentInvitationId = AgentInvId inv chatV = vr `peerConnChatVersion` cReqChatVRange pqSup' = pqSup `CR.pqSupportAnd` pqSupport dm <- encodeConnInfoPQ pqSup' chatV $ XInfo profileToSend - acId <- withAgent $ \a -> acceptContact a True invId dm pqSup' subMode - withStore' $ \db -> createAcceptedContact db user acId chatV cReqChatVRange cName profileId cp userContactLinkId xContactId incognitoProfile subMode pqSup' contactUsed + (acId, sqSecured) <- withAgent $ \a -> acceptContact a True invId dm pqSup' subMode + let connStatus = if sqSecured then ConnSndReady else ConnNew + withStore' $ \db -> createAcceptedContact db user acId connStatus chatV cReqChatVRange cName profileId cp userContactLinkId xContactId incognitoProfile subMode pqSup' contactUsed acceptContactRequestAsync :: User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> PQSupport -> CM Contact acceptContactRequestAsync user UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = p, userContactLinkId, xContactId} incognitoProfile contactUsed pqSup = do @@ -3334,7 +3335,7 @@ acceptContactRequestAsync user UserContactRequest {agentInvitationId = AgentInvI let chatV = vr `peerConnChatVersion` cReqChatVRange (cmdId, acId) <- agentAcceptContactAsync user True invId (XInfo profileToSend) subMode pqSup chatV withStore' $ \db -> do - ct@Contact {activeConn} <- createAcceptedContact db user acId chatV cReqChatVRange cName profileId p userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed + ct@Contact {activeConn} <- createAcceptedContact db user acId ConnNew chatV cReqChatVRange cName profileId p userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed forM_ activeConn $ \Connection {connId} -> setCommandConnId db user cmdId connId pure ct @@ -3997,6 +3998,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = agentMsgConnStatus :: AEvent e -> Maybe ConnStatus agentMsgConnStatus = \case + JOINED True -> Just ConnSndReady CONF {} -> Just ConnRequested INFO {} -> Just ConnSndReady CON _ -> Just ConnReady @@ -4045,6 +4047,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + JOINED _ -> + -- [async agent commands] continuation on receiving JOINED + when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () QCONT -> void $ continueSending connEntity conn MWARN _ err -> @@ -4164,12 +4169,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withStore' $ \db -> resetContactConnInitiated db user conn' forM_ viaUserContactLink $ \userContactLinkId -> do ucl <- withStore $ \db -> getUserContactLinkById db userId userContactLinkId - let (UserContactLink {autoAccept}, groupId_, gLinkMemRole) = ucl - forM_ autoAccept $ \(AutoAccept {autoReply = mc_}) -> - forM_ mc_ $ \mc -> do - (msg, _) <- sendDirectContactMessage user ct' (XMsgNew $ MCSimple (extMsgContent mc Nothing)) - ci <- saveSndChatItem user (CDDirectSnd ct') msg (CISndMsgContent mc) - toView $ CRNewChatItem user (AChatItem SCTDirect SMDSnd (DirectChat ct') ci) + let (_, groupId_, gLinkMemRole) = ucl forM_ groupId_ $ \groupId -> do groupInfo <- withStore $ \db -> getGroupInfo db vr user groupId subMode <- chatReadVar subscriptionMode @@ -4223,6 +4223,20 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + JOINED sqSecured -> + -- [async agent commands] continuation on receiving JOINED + when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> + when (directOrUsed ct && sqSecured) $ do + lift $ setContactNetworkStatus ct NSConnected + toView $ CRContactSndReady user ct + forM_ viaUserContactLink $ \userContactLinkId -> do + ucl <- withStore $ \db -> getUserContactLinkById db userId userContactLinkId + let (UserContactLink {autoAccept}, _, _) = ucl + forM_ autoAccept $ \(AutoAccept {autoReply = mc_}) -> + forM_ mc_ $ \mc -> do + (msg, _) <- sendDirectContactMessage user ct (XMsgNew $ MCSimple (extMsgContent mc Nothing)) + ci <- saveSndChatItem user (CDDirectSnd ct) msg (CISndMsgContent mc) + toView $ CRNewChatItem user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) QCONT -> void $ continueSending connEntity conn MWARN msgId err -> do @@ -4620,6 +4634,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + JOINED _ -> + -- [async agent commands] continuation on receiving JOINED + when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () QCONT -> do continued <- continueSending connEntity conn when continued $ sendPendingGroupMessages user m conn @@ -4712,6 +4729,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + JOINED _ -> + -- [async agent commands] continuation on receiving JOINED + when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () @@ -4758,6 +4778,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + JOINED _ -> + -- [async agent commands] continuation on receiving JOINED + when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MERR _ err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) processConnMERR connEntity conn err diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 8e2a308986..fedfc463a3 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -675,6 +675,7 @@ data ChatResponse | CRContactPrefsUpdated {user :: User, fromContact :: Contact, toContact :: Contact} | CRContactConnecting {user :: User, contact :: Contact} | CRContactConnected {user :: User, contact :: Contact, userCustomProfile :: Maybe Profile} + | CRContactSndReady {user :: User, contact :: Contact} | CRContactAnotherClient {user :: User, contact :: Contact} | CRSubscriptionEnd {user :: User, connectionEntity :: ConnectionEntity} | CRContactsDisconnected {server :: SMPServer, contactRefs :: [ContactRef]} diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index 1145c2494b..508a992543 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -752,8 +752,8 @@ deleteContactRequest db User {userId} contactRequestId = do (userId, userId, contactRequestId, userId) DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND contact_request_id = ?" (userId, contactRequestId) -createAcceptedContact :: DB.Connection -> User -> ConnId -> VersionChat -> VersionRangeChat -> ContactName -> ProfileId -> Profile -> Int64 -> Maybe XContactId -> Maybe IncognitoProfile -> SubscriptionMode -> PQSupport -> Bool -> IO Contact -createAcceptedContact db user@User {userId, profile = LocalProfile {preferences}} agentConnId connChatVersion cReqChatVRange localDisplayName profileId profile userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed = do +createAcceptedContact :: DB.Connection -> User -> ConnId -> ConnStatus -> VersionChat -> VersionRangeChat -> ContactName -> ProfileId -> Profile -> Int64 -> Maybe XContactId -> Maybe IncognitoProfile -> SubscriptionMode -> PQSupport -> Bool -> IO Contact +createAcceptedContact db user@User {userId, profile = LocalProfile {preferences}} agentConnId connStatus connChatVersion cReqChatVRange localDisplayName profileId profile userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed = do DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName) createdAt <- getCurrentTime customUserProfileId <- forM incognitoProfile $ \case @@ -765,7 +765,7 @@ createAcceptedContact db user@User {userId, profile = LocalProfile {preferences} "INSERT INTO contacts (user_id, local_display_name, contact_profile_id, enable_ntfs, user_preferences, created_at, updated_at, chat_ts, xcontact_id, contact_used) VALUES (?,?,?,?,?,?,?,?,?,?)" (userId, localDisplayName, profileId, True, userPreferences, createdAt, createdAt, createdAt, xContactId, contactUsed) contactId <- insertedRowId db - conn <- createConnection_ db userId ConnContact (Just contactId) agentConnId connChatVersion cReqChatVRange Nothing (Just userContactLinkId) customUserProfileId 0 createdAt subMode pqSup + conn <- createConnection_ db userId ConnContact (Just contactId) agentConnId connStatus connChatVersion cReqChatVRange Nothing (Just userContactLinkId) customUserProfileId 0 createdAt subMode pqSup let mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito conn pure $ Contact diff --git a/src/Simplex/Chat/Store/Files.hs b/src/Simplex/Chat/Store/Files.hs index d70bbb8970..d1da081cee 100644 --- a/src/Simplex/Chat/Store/Files.hs +++ b/src/Simplex/Chat/Store/Files.hs @@ -455,7 +455,7 @@ lookupChatRefByFileId db User {userId} fileId = createSndFileConnection_ :: DB.Connection -> VersionRangeChat -> UserId -> Int64 -> ConnId -> SubscriptionMode -> IO Connection createSndFileConnection_ db vr userId fileId agentConnId subMode = do currentTs <- getCurrentTime - createConnection_ db userId ConnSndFile (Just fileId) agentConnId (minVersion vr) chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff + createConnection_ db userId ConnSndFile (Just fileId) agentConnId ConnNew (minVersion vr) chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff updateSndFileStatus :: DB.Connection -> SndFileTransfer -> FileStatus -> IO () updateSndFileStatus db SndFileTransfer {fileId, connId} status = do diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 42637d4169..55847114ca 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -191,7 +191,7 @@ createGroupLink db User {userId} groupInfo@GroupInfo {groupId, localDisplayName} "INSERT INTO user_contact_links (user_id, group_id, group_link_id, local_display_name, conn_req_contact, group_link_member_role, auto_accept, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?)" (userId, groupId, groupLinkId, "group_link_" <> localDisplayName, cReq, memberRole, True, currentTs, currentTs) userContactLinkId <- insertedRowId db - void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode PQSupportOff + void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId ConnNew initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode PQSupportOff getGroupLinkConnection :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> ExceptT StoreError IO Connection getGroupLinkConnection db vr User {userId} groupInfo@GroupInfo {groupId} = @@ -914,7 +914,7 @@ createAcceptedMemberConnection groupMemberId subMode = do createdAt <- liftIO getCurrentTime - Connection {connId} <- createConnection_ db userId ConnMember (Just groupMemberId) agentConnId chatV cReqChatVRange Nothing (Just userContactLinkId) Nothing 0 createdAt subMode PQSupportOff + Connection {connId} <- createConnection_ db userId ConnMember (Just groupMemberId) agentConnId ConnNew chatV cReqChatVRange Nothing (Just userContactLinkId) Nothing 0 createdAt subMode PQSupportOff setCommandConnId db user cmdId connId getContactViaMember :: DB.Connection -> VersionRangeChat -> User -> GroupMember -> ExceptT StoreError IO Contact @@ -1250,7 +1250,7 @@ createIntroReMember currentTs <- liftIO getCurrentTime newMember <- case directConnIds of Just (directCmdId, directAgentConnId) -> do - Connection {connId = directConnId} <- liftIO $ createConnection_ db userId ConnContact Nothing directAgentConnId chatV mcvr memberContactId Nothing customUserProfileId cLevel currentTs subMode PQSupportOff + Connection {connId = directConnId} <- liftIO $ createConnection_ db userId ConnContact Nothing directAgentConnId ConnNew chatV mcvr memberContactId Nothing customUserProfileId cLevel currentTs subMode PQSupportOff liftIO $ setCommandConnId db user directCmdId directConnId (localDisplayName, contactId, memProfileId) <- createContact_ db userId memberProfile "" (Just groupId) currentTs False liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, directConnId) @@ -1271,7 +1271,7 @@ createIntroToMemberContact db user@User {userId} GroupMember {memberContactId = Connection {connId = groupConnId} <- createMemberConnection_ db userId groupMemberId groupAgentConnId chatV mcvr viaContactId cLevel currentTs subMode setCommandConnId db user groupCmdId groupConnId forM_ directConnIds $ \(directCmdId, directAgentConnId) -> do - Connection {connId = directConnId} <- createConnection_ db userId ConnContact Nothing directAgentConnId chatV mcvr viaContactId Nothing customUserProfileId cLevel currentTs subMode PQSupportOff + Connection {connId = directConnId} <- createConnection_ db userId ConnContact Nothing directAgentConnId ConnNew chatV mcvr viaContactId Nothing customUserProfileId cLevel currentTs subMode PQSupportOff setCommandConnId db user directCmdId directConnId contactId <- createMemberContact_ directConnId currentTs updateMember_ contactId currentTs @@ -1303,7 +1303,7 @@ createIntroToMemberContact db user@User {userId} GroupMember {memberContactId = createMemberConnection_ :: DB.Connection -> UserId -> Int64 -> ConnId -> VersionChat -> VersionRangeChat -> Maybe Int64 -> Int -> UTCTime -> SubscriptionMode -> IO Connection createMemberConnection_ db userId groupMemberId agentConnId chatV peerChatVRange viaContact connLevel currentTs subMode = - createConnection_ db userId ConnMember (Just groupMemberId) agentConnId chatV peerChatVRange viaContact Nothing Nothing connLevel currentTs subMode PQSupportOff + createConnection_ db userId ConnMember (Just groupMemberId) agentConnId ConnNew chatV peerChatVRange viaContact Nothing Nothing connLevel currentTs subMode PQSupportOff getViaGroupMember :: DB.Connection -> VersionRangeChat -> User -> Contact -> IO (Maybe (GroupInfo, GroupMember)) getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = diff --git a/src/Simplex/Chat/Store/Profiles.hs b/src/Simplex/Chat/Store/Profiles.hs index cad06448e6..fb87662c27 100644 --- a/src/Simplex/Chat/Store/Profiles.hs +++ b/src/Simplex/Chat/Store/Profiles.hs @@ -328,7 +328,7 @@ createUserContactLink db User {userId} agentConnId cReq subMode = "INSERT INTO user_contact_links (user_id, conn_req_contact, created_at, updated_at) VALUES (?,?,?,?)" (userId, cReq, currentTs, currentTs) userContactLinkId <- insertedRowId db - void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff + void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId ConnNew initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff getUserAddressConnections :: DB.Connection -> VersionRangeChat -> User -> ExceptT StoreError IO [Connection] getUserAddressConnections db vr User {userId} = do diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index c364cf10c2..b80e2ce805 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -208,8 +208,8 @@ toMaybeConnection vr ((Just connId, Just agentConnId, Just connLevel, viaContact Just $ toConnection vr ((connId, agentConnId, connLevel, viaContact, viaUserContactLink, viaGroupLink, groupLinkId, customUserProfileId, connStatus, connType, contactConnInitiated, localAlias) :. (contactId, groupMemberId, sndFileId, rcvFileId, userContactLinkId) :. (createdAt, code_, verifiedAt_, pqSupport, pqEncryption, pqSndEnabled_, pqRcvEnabled_, authErrCounter, quotaErrCounter, connChatVersion, minVer, maxVer)) toMaybeConnection _ _ = Nothing -createConnection_ :: DB.Connection -> UserId -> ConnType -> Maybe Int64 -> ConnId -> VersionChat -> VersionRangeChat -> Maybe ContactId -> Maybe Int64 -> Maybe ProfileId -> Int -> UTCTime -> SubscriptionMode -> PQSupport -> IO Connection -createConnection_ db userId connType entityId acId connChatVersion peerChatVRange@(VersionRange minV maxV) viaContact viaUserContactLink customUserProfileId connLevel currentTs subMode pqSup = do +createConnection_ :: DB.Connection -> UserId -> ConnType -> Maybe Int64 -> ConnId -> ConnStatus -> VersionChat -> VersionRangeChat -> Maybe ContactId -> Maybe Int64 -> Maybe ProfileId -> Int -> UTCTime -> SubscriptionMode -> PQSupport -> IO Connection +createConnection_ db userId connType entityId acId connStatus connChatVersion peerChatVRange@(VersionRange minV maxV) viaContact viaUserContactLink customUserProfileId connLevel currentTs subMode pqSup = do viaLinkGroupId :: Maybe Int64 <- fmap join . forM viaUserContactLink $ \ucLinkId -> maybeFirstRow fromOnly $ DB.query db "SELECT group_id FROM user_contact_links WHERE user_id = ? AND user_contact_link_id = ? AND group_id IS NOT NULL" (userId, ucLinkId) let viaGroupLink = isJust viaLinkGroupId @@ -222,7 +222,7 @@ createConnection_ db userId connType entityId acId connChatVersion peerChatVRang conn_chat_version, peer_chat_min_version, peer_chat_max_version, to_subscribe, pq_support, pq_encryption ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) |] - ( (userId, acId, connLevel, viaContact, viaUserContactLink, viaGroupLink, customUserProfileId, ConnNew, connType) + ( (userId, acId, connLevel, viaContact, viaUserContactLink, viaGroupLink, customUserProfileId, connStatus, connType) :. (ent ConnContact, ent ConnMember, ent ConnSndFile, ent ConnRcvFile, ent ConnUserContact, currentTs, currentTs) :. (connChatVersion, minV, maxV, subMode == SMOnlyCreate, pqSup, pqSup) ) @@ -242,7 +242,7 @@ createConnection_ db userId connType entityId acId connChatVersion peerChatVRang groupLinkId = Nothing, customUserProfileId, connLevel, - connStatus = ConnNew, + connStatus, localAlias = "", createdAt = currentTs, connectionCode = Nothing, diff --git a/src/Simplex/Chat/Terminal/Output.hs b/src/Simplex/Chat/Terminal/Output.hs index be8aa12cfe..40f14a10de 100644 --- a/src/Simplex/Chat/Terminal/Output.hs +++ b/src/Simplex/Chat/Terminal/Output.hs @@ -189,6 +189,8 @@ responseNotification t@ChatTerminal {sendNotification} cc = \case CRContactConnected u ct _ -> when (contactNtf u ct False) $ do whenCurrUser cc u $ setActiveContact t ct sendNtf (viewContactName ct <> "> ", "connected") + CRContactSndReady u ct -> + whenCurrUser cc u $ setActiveContact t ct CRContactAnotherClient u ct -> do whenCurrUser cc u $ unsetActiveContact t ct when (contactNtf u ct False) $ sendNtf (viewContactName ct <> "> ", "connected to another client") diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index 04cc2bcc6f..93820365b0 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -1377,7 +1377,7 @@ data ConnStatus ConnRequested | -- | initiating party accepted connection with agent LET command (to be renamed to ACPT) (allowConnection) ConnAccepted - | -- | connection can be sent messages to (after joining party received INFO notification) + | -- | connection can be sent messages to (after joining party received INFO notification, or after securing snd queue on join) ConnSndReady | -- | connection is ready for both parties to send and receive messages ConnReady @@ -1588,9 +1588,9 @@ commandExpectedResponse = \case CFCreateConnGrpInv -> t INV_ CFCreateConnFileInvDirect -> t INV_ CFCreateConnFileInvGroup -> t INV_ - CFJoinConn -> t OK_ + CFJoinConn -> t JOINED_ CFAllowConn -> t OK_ - CFAcceptContact -> t OK_ + CFAcceptContact -> t JOINED_ CFAckMessage -> t OK_ CFDeleteConn -> t OK_ where diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index b0d3032ed3..a4c82b3b3f 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -176,7 +176,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRContactDeleted u c -> ttyUser u [ttyContact' c <> ": contact is deleted"] CRContactDeletedByContact u c -> ttyUser u [ttyFullContact c <> " deleted contact with you"] CRChatCleared u chatInfo -> ttyUser u $ viewChatCleared chatInfo - CRAcceptingContactRequest u c -> ttyUser u [ttyFullContact c <> ": accepting contact request..."] + CRAcceptingContactRequest u c -> ttyUser u $ viewAcceptingContactRequest c CRContactAlreadyExists u c -> ttyUser u [ttyFullContact c <> ": contact already exists"] CRContactRequestAlreadyAccepted u c -> ttyUser u [ttyFullContact c <> ": sent you a duplicate contact request, but you are already connected, no action needed"] CRUserContactLinkCreated u cReq -> ttyUser u $ connReqContact_ "Your new chat address is created!" cReq @@ -231,6 +231,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe CRStandaloneFileInfo info_ -> maybe ["no file information in URI"] (\j -> [viewJSON j]) info_ CRContactConnecting u _ -> ttyUser u [] CRContactConnected u ct userCustomProfile -> ttyUser u $ viewContactConnected ct userCustomProfile testView + CRContactSndReady u ct -> ttyUser u [ttyFullContact ct <> ": you can send messages to contact"] CRContactAnotherClient u c -> ttyUser u [ttyContact' c <> ": contact is connected to another client"] CRSubscriptionEnd u acEntity -> let Connection {connId} = entityConnection acEntity @@ -963,6 +964,11 @@ viewSentInvitation incognitoProfile testView = message = ["connection request sent incognito!"] Nothing -> ["connection request sent!"] +viewAcceptingContactRequest :: Contact -> [StyledString] +viewAcceptingContactRequest ct + | contactReady ct = [ttyFullContact ct <> ": accepting contact request, you can send messages to contact"] + | otherwise = [ttyFullContact ct <> ": accepting contact request..."] + viewReceivedContactRequest :: ContactName -> Profile -> [StyledString] viewReceivedContactRequest c Profile {fullName} = [ ttyFullName c fullName <> " wants to connect to you!", diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index ca5b92e04e..ffea6a3529 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -224,7 +224,10 @@ testCfgCreateGroupDirect = mkCfgCreateGroupDirect testCfg mkCfgCreateGroupDirect :: ChatConfig -> ChatConfig -mkCfgCreateGroupDirect cfg = cfg {chatVRange = groupCreateDirectVRange} +mkCfgCreateGroupDirect cfg = cfg { + chatVRange = groupCreateDirectVRange, + agentConfig = testAgentCfgSlow +} groupCreateDirectVRange :: VersionRangeChat groupCreateDirectVRange = mkVersionRange (VersionChat 1) (VersionChat 1) diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index aaf91af910..2bbcf87d5b 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -1150,7 +1150,7 @@ testSubscribeAppNSE tmp = alice <## "to accept: /ac bob" alice <## "to reject: /rc bob (the sender will NOT be notified)" alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -1376,7 +1376,7 @@ testMultipleUserAddresses = alice <#? bob alice @@@ [("<@bob", "")] alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -1394,7 +1394,7 @@ testMultipleUserAddresses = alice <#? bob alice #$> ("/_get chats 2 pcc=on", chats, [("<@bob", ""), ("*", "")]) alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alisa: contact is connected") (alice <## "bob (Bob): contact is connected") @@ -1425,7 +1425,7 @@ testMultipleUserAddresses = showActiveUser alice "alisa" alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alisa: contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -2649,7 +2649,7 @@ testConnReqChatVRange ct1VRange ct2VRange tmp = bob ##> ("/c " <> cLink) alice <#? bob alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index 6f1ba20246..67d1bfeae5 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -307,28 +307,6 @@ testGroupShared alice bob cath checkMessages directConnections = do alice ##> "/d bob" alice <## "bob: contact is deleted" bob <## "alice (Alice) deleted contact with you" - alice `send` "@bob hey" - if directConnections - then - alice - <### [ "@bob hey", - "member #team bob does not have direct connection, creating", - "peer chat protocol version range incompatible" - ] - else do - alice - <### [ WithTime "@bob hey", - "member #team bob does not have direct connection, creating", - "contact for member #team bob is created", - "sent invitation to connect directly to member #team bob", - "bob (Bob): contact is connected" - ] - bob - <### [ "#team alice is creating direct contact alice with you", - WithTime "alice> hey", - "alice: security code changed", - "alice (Alice): contact is connected" - ] when checkMessages $ threadDelay 1000000 alice #> "#team checking connection" bob <# "#team alice> checking connection" @@ -818,6 +796,7 @@ testGroupDeleteInvitedContact = WithTime "alice> hey", "alice: security code changed" ] + bob <## "alice (Alice): you can send messages to contact" concurrently_ (alice <## "bob (Bob): contact is connected") (bob <## "alice (Alice): contact is connected") @@ -1907,7 +1886,7 @@ testGroupLink = cath ##> ("/c " <> cLink) alice <#? cath alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -3965,6 +3944,7 @@ testMemberContactMessage = <### [ "#team alice is creating direct contact alice with you", WithTime "alice> hi" ] + bob <## "alice (Alice): you can send messages to contact" concurrently_ (alice <## "bob (Bob): contact is connected") (bob <## "alice (Alice): contact is connected") @@ -3998,6 +3978,7 @@ testMemberContactMessage = <### [ "#team bob is creating direct contact bob with you", WithTime "bob> hi" ] + cath <## "bob (Bob): you can send messages to contact" concurrently_ (bob <## "cath (Catherine): contact is connected") (cath <## "bob (Bob): contact is connected") @@ -4018,6 +3999,7 @@ testMemberContactNoMessage = bob ##> "/_invite member contact @3" bob <## "sent invitation to connect directly to member #team cath" cath <## "#team bob is creating direct contact bob with you" + cath <## "bob (Bob): you can send messages to contact" concurrently_ (bob <## "cath (Catherine): contact is connected") (cath <## "bob (Bob): contact is connected") @@ -4058,6 +4040,7 @@ testMemberContactProhibitedRepeatInv = <### [ "#team bob is creating direct contact bob with you", WithTime "bob> hi" ] + cath <## "bob (Bob): you can send messages to contact" concurrently_ (bob <## "cath (Catherine): contact is connected") (cath <## "bob (Bob): contact is connected") @@ -4087,6 +4070,7 @@ testMemberContactInvitedConnectionReplaced tmp = do WithTime "alice> hi", "alice: security code changed" ] + bob <## "alice (Alice): you can send messages to contact" concurrently_ (alice <## "bob (Bob): contact is connected") (bob <## "alice (Alice): contact is connected") @@ -4196,6 +4180,7 @@ testMemberContactIncognito = <### [ ConsoleString ("#team " <> bobIncognito <> " is creating direct contact " <> bobIncognito <> " with you"), WithTime ("i " <> bobIncognito <> "> hi") ] + cath <## (bobIncognito <> ": you can send messages to contact") _ <- getTermLine bob _ <- getTermLine cath concurrentlyN_ @@ -4267,6 +4252,7 @@ testMemberContactProfileUpdate = <### [ "#team bob is creating direct contact bob with you", WithTime "bob> hi" ] + cath <## "bob (Bob): you can send messages to contact" concurrentlyN_ [ do bob <## "contact cath changed to kate (Kate)" diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index a3352c7f4f..6971898ddf 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -198,6 +198,7 @@ testMultiWordProfileNames = ] cath <## "#'Our Team' 'Alice Jones' is creating direct contact 'Alice Jones' with you" cath <# "'Alice Jones'> hello" + cath <## "'Alice Jones': you can send messages to contact" cath <## "'Alice Jones': contact is connected" alice <## "'Cath Johnson': contact is connected" cath ##> "/p 'Cath J'" @@ -224,7 +225,7 @@ testUserContactLink = alice <#? bob alice @@@ [("<@bob", "")] alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -236,7 +237,7 @@ testUserContactLink = alice <#? cath alice @@@ [("<@cath", ""), ("@bob", "hey")] alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -254,7 +255,7 @@ testProfileLink = bob ##> ("/c " <> cLink) alice <#? bob alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -269,7 +270,7 @@ testProfileLink = cath ##> ("/c " <> cLink) alice <#? cath alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -336,7 +337,7 @@ testUserContactLinkAutoAccept = alice <#? bob alice @@@ [("<@bob", "")] alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -350,6 +351,7 @@ testUserContactLinkAutoAccept = cath ##> ("/c " <> cLink) cath <## "connection request sent!" alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -364,7 +366,7 @@ testUserContactLinkAutoAccept = alice <#? dan alice @@@ [("<@dan", ""), ("@cath", "hey"), ("@bob", "hey")] alice ##> "/ac dan" - alice <## "dan (Daniel): accepting contact request..." + alice <## "dan (Daniel): accepting contact request, you can send messages to contact" concurrently_ (dan <## "alice (Alice): contact is connected") (alice <## "dan (Daniel): contact is connected") @@ -391,7 +393,7 @@ testDeduplicateContactRequests = testChat3 aliceProfile bobProfile cathProfile $ bob @@@! [(":3", "", Just ConnJoined), (":2", "", Just ConnJoined), (":1", "", Just ConnJoined)] alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -423,7 +425,7 @@ testDeduplicateContactRequests = testChat3 aliceProfile bobProfile cathProfile $ alice <#? cath alice @@@ [("<@cath", ""), ("@bob", "hey")] alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -465,7 +467,7 @@ testDeduplicateContactRequestsProfileChange = testChat3 aliceProfile bobProfile alice ##> "/ac bob" alice <## "no contact request from bob" alice ##> "/ac robert" - alice <## "robert (Robert): accepting contact request..." + alice <## "robert (Robert): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "robert (Robert): contact is connected") @@ -500,7 +502,7 @@ testDeduplicateContactRequestsProfileChange = testChat3 aliceProfile bobProfile alice <#? cath alice @@@ [("<@cath", ""), ("@robert", "hey")] alice ##> "/ac cath" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" concurrently_ (cath <## "alice (Alice): contact is connected") (alice <## "cath (Catherine): contact is connected") @@ -566,13 +568,13 @@ testAutoReplyMessage = testChat2 aliceProfile bobProfile $ bob ##> ("/c " <> cLink) bob <## "connection request sent!" alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): you can send messages to contact" + alice <# "@bob hello!" concurrentlyN_ [ do - bob <## "alice (Alice): contact is connected" - bob <# "alice> hello!", - do - alice <## "bob (Bob): contact is connected" - alice <# "@bob hello!" + bob <# "alice> hello!" + bob <## "alice (Alice): contact is connected", + alice <## "bob (Bob): contact is connected" ] testAutoReplyMessageInIncognito :: HasCallStack => FilePath -> IO () @@ -588,17 +590,16 @@ testAutoReplyMessageInIncognito = testChat2 aliceProfile bobProfile $ bob ##> ("/c " <> cLink) bob <## "connection request sent!" alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): you can send messages to contact" + alice <# "i @bob hello!" aliceIncognito <- getTermLine alice concurrentlyN_ [ do - bob <## (aliceIncognito <> ": contact is connected") - bob <# (aliceIncognito <> "> hello!"), + bob <# (aliceIncognito <> "> hello!") + bob <## (aliceIncognito <> ": contact is connected"), do alice <## ("bob (Bob): contact is connected, your incognito profile for this contact is " <> aliceIncognito) - alice - <### [ "use /i bob to print out this incognito profile again", - WithTime "i @bob hello!" - ] + alice <## "use /i bob to print out this incognito profile again" ] testPlanAddressOkKnown :: HasCallStack => FilePath -> IO () @@ -615,7 +616,7 @@ testPlanAddressOkKnown = alice <#? bob alice @@@ [("<@bob", "")] alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -654,7 +655,7 @@ testPlanAddressOwn tmp = alice <## "to reject: /rc alice_1 (the sender will NOT be notified)" alice @@@ [("<@alice_1", ""), (":2", "")] alice ##> "/ac alice_1" - alice <## "alice_1 (Alice): accepting contact request..." + alice <## "alice_1 (Alice): accepting contact request, you can send messages to contact" alice <### [ "alice_1 (Alice): contact is connected", "alice_2 (Alice): contact is connected" @@ -705,7 +706,7 @@ testPlanAddressConnecting tmp = do alice <## "to accept: /ac bob" alice <## "to reject: /rc bob (the sender will NOT be notified)" alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" withTestChat tmp "bob" $ \bob -> do threadDelay 500000 bob <## "alice (Alice): contact is connected" @@ -772,7 +773,7 @@ testPlanAddressContactDeletedReconnected = bob ##> ("/c " <> cLink) alice <#? bob alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -803,7 +804,7 @@ testPlanAddressContactDeletedReconnected = alice <## "to accept: /ac bob" alice <## "to reject: /rc bob (the sender will NOT be notified)" alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice_1 (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -877,7 +878,7 @@ testPlanAddressContactViaAddress = alice <## "to accept: /ac bob" alice <## "to reject: /rc bob (the sender will NOT be notified)" alice ##> "/ac bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" concurrently_ (bob <## "alice (Alice): contact is connected") (alice <## "bob (Bob): contact is connected") @@ -971,7 +972,7 @@ testConnectIncognitoContactAddress = testChat2 aliceProfile bobProfile $ alice <## ("to accept: /ac " <> bobIncognito) alice <## ("to reject: /rc " <> bobIncognito <> " (the sender will NOT be notified)") alice ##> ("/ac " <> bobIncognito) - alice <## (bobIncognito <> ": accepting contact request...") + alice <## (bobIncognito <> ": accepting contact request, you can send messages to contact") _ <- getTermLine bob concurrentlyN_ [ do @@ -1005,7 +1006,7 @@ testAcceptContactRequestIncognito = testChat3 aliceProfile bobProfile cathProfil bob ##> ("/c " <> cLink) alice <#? bob alice ##> "/accept incognito bob" - alice <## "bob (Bob): accepting contact request..." + alice <## "bob (Bob): accepting contact request, you can send messages to contact" aliceIncognitoBob <- getTermLine alice concurrentlyN_ [ bob <## (aliceIncognitoBob <> ": contact is connected"), @@ -1033,7 +1034,7 @@ testAcceptContactRequestIncognito = testChat3 aliceProfile bobProfile cathProfil cath ##> ("/c " <> cLink) alice <#? cath alice ##> "/_accept incognito=on 1" - alice <## "cath (Catherine): accepting contact request..." + alice <## "cath (Catherine): accepting contact request, you can send messages to contact" aliceIncognitoCath <- getTermLine alice concurrentlyN_ [ cath <## (aliceIncognitoCath <> ": contact is connected"), @@ -2036,6 +2037,7 @@ testGroupPrefsDirectForRole = testChat4 aliceProfile bobProfile cathProfile danP <### [ "#team alice is creating direct contact alice with you", WithTime "alice> hello dan" ] + dan <## "alice (Alice): you can send messages to contact" concurrently_ (alice <## "dan (Daniel): contact is connected") (dan <## "alice (Alice): contact is connected")