diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 4286f019e3..a7896da75d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -101,7 +101,7 @@ class ChatModel(val controller: ChatController) { fun updateContactConnection(contactConnection: PendingContactConnection) = updateChat(ChatInfo.ContactConnection(contactConnection)) - fun updateContact(contact: Contact) = updateChat(ChatInfo.Direct(contact), addMissing = contact.directContact) + fun updateContact(contact: Contact) = updateChat(ChatInfo.Direct(contact), addMissing = contact.directOrUsed) fun updateGroup(groupInfo: GroupInfo) = updateChat(ChatInfo.Group(groupInfo)) @@ -575,7 +575,7 @@ data class Contact( override val image get() = profile.image override val localAlias get() = profile.localAlias - val directContact: Boolean get() = + val directOrUsed: Boolean get() = (activeConn.connLevel == 0 && !activeConn.viaGroupLink) || contactUsed val contactConnIncognito = diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 15be456e0b..30f5bd2fe3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -993,7 +993,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a chatModel.removeChat(r.connection.id) } is CR.ContactConnected -> { - if (r.contact.directContact) { + if (r.contact.directOrUsed) { chatModel.updateContact(r.contact) chatModel.dismissConnReqView(r.contact.activeConn.id) chatModel.removeChat(r.contact.activeConn.id) @@ -1002,7 +1002,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a } } is CR.ContactConnecting -> { - if (r.contact.directContact) { + if (r.contact.directOrUsed) { chatModel.updateContact(r.contact) chatModel.dismissConnReqView(r.contact.activeConn.id) chatModel.removeChat(r.contact.activeConn.id) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt index 0fe15b084d..bf7e1bb280 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt @@ -25,7 +25,6 @@ import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.chat.SimplexServers import chat.simplex.app.views.chat.SwitchAddressButton -import chat.simplex.app.views.chatlist.openChat import chat.simplex.app.views.helpers.* import chat.simplex.app.views.usersettings.SettingsActionItem @@ -141,19 +140,21 @@ fun GroupMemberInfoLayout( } SectionSpacer() - val contactId = member.memberContactId - if (contactId != null) { - val chat = getContactChat(contactId) - if (chat != null && chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.directContact) { - SectionView { - OpenChatButton(onClick = { knownDirectChat(chat) }) + if (member.memberActive) { + val contactId = member.memberContactId + if (contactId != null) { + val chat = getContactChat(contactId) + if (chat != null && chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.directOrUsed) { + SectionView { + OpenChatButton(onClick = { knownDirectChat(chat) }) + } + SectionSpacer() + } else if (groupInfo.fullGroupPreferences.directMessages.on) { + SectionView { + OpenChatButton(onClick = { newDirectChat(contactId) }) + } + SectionSpacer() } - SectionSpacer() - } else if (groupInfo.fullGroupPreferences.directMessages.on) { - SectionView { - OpenChatButton(onClick = { newDirectChat(contactId) }) - } - SectionSpacer() } } diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index db4b13f9c2..7d68a2e415 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -101,7 +101,7 @@ final class ChatModel: ObservableObject { } func updateContact(_ contact: Contact) { - updateChat(.direct(contact: contact), addMissing: contact.directContact) + updateChat(.direct(contact: contact), addMissing: contact.directOrUsed) } func updateGroup(_ groupInfo: GroupInfo) { diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index a38f1229f2..f3452e35b9 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -949,7 +949,7 @@ func processReceivedMsg(_ res: ChatResponse) async { case let .contactConnectionDeleted(connection): m.removeChat(connection.id) case let .contactConnected(contact, _): - if contact.directContact { + if contact.directOrUsed { m.updateContact(contact) m.dismissConnReqView(contact.activeConn.id) m.removeChat(contact.activeConn.id) @@ -957,7 +957,7 @@ func processReceivedMsg(_ res: ChatResponse) async { NtfManager.shared.notifyContactConnected(contact) } case let .contactConnecting(contact): - if contact.directContact { + if contact.directOrUsed { m.updateContact(contact) m.dismissConnReqView(contact.activeConn.id) m.removeChat(contact.activeConn.id) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index e43e39f2c0..5bcfa72ea2 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -51,16 +51,18 @@ struct GroupMemberInfoView: View { groupMemberInfoHeader(member) .listRowBackground(Color.clear) - Section { - if let contactId = member.memberContactId { - if let chat = chatModel.getContactChat(contactId), - chat.chatInfo.contact?.directContact ?? false { - knownDirectChatButton(chat) - } else if groupInfo.fullGroupPreferences.directMessages.on { - newDirectChatButton(contactId) + if member.memberActive { + Section { + if let contactId = member.memberContactId { + if let chat = chatModel.getContactChat(contactId), + chat.chatInfo.contact?.directOrUsed ?? false { + knownDirectChatButton(chat) + } else if groupInfo.fullGroupPreferences.directMessages.on { + newDirectChatButton(contactId) + } } + if let code = connectionCode { verifyCodeButton(code) } } - if let code = connectionCode { verifyCodeButton(code) } } Section("Member") { diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index f0735bdb4a..3eb258be81 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -819,7 +819,7 @@ public struct Contact: Identifiable, Decodable, NamedChat { public var localAlias: String { profile.localAlias } public var verified: Bool { activeConn.connectionCode != nil } - public var directContact: Bool { + public var directOrUsed: Bool { (activeConn.connLevel == 0 && !activeConn.viaGroupLink) || contactUsed } diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 8ef369fffe..e15a1abc5a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -531,7 +531,7 @@ processChatCommand = \case where deleteUnusedContact contactId = do ct <- withStore $ \db -> getContact db user contactId - unless (directContact ct) $ do + unless (directOrUsed ct) $ do ctGroupId <- withStore' $ \db -> checkContactHasGroups db user ct when (isNothing ctGroupId) $ do conns <- withStore $ \db -> getContactConnections db userId ct @@ -862,7 +862,7 @@ processChatCommand = \case contacts <- withStore' (`getUserContacts` user) withChatLock "sendMessageBroadcast" . procCmd $ do let mc = MCText $ safeDecodeUtf8 msg - cts = filter (\ct -> isReady ct && directContact ct) contacts + cts = filter (\ct -> isReady ct && directOrUsed ct) contacts forM_ cts $ \ct -> void ( do @@ -1234,7 +1234,7 @@ processChatCommand = \case let mergedProfile = userProfileToSend user' Nothing $ Just ct ct' = updateMergedPreferences user' ct void (sendDirectContactMessage ct $ XInfo mergedProfile) `catchError` (toView . CRChatError) - when (directContact ct) $ createFeatureChangedItems user' ct ct' CDDirectSnd CISndChatFeature + when (directOrUsed ct) $ createFeatureChangedItems user' ct ct' CDDirectSnd CISndChatFeature pure $ CRUserProfileUpdated (fromLocalProfile p) p' updateContactPrefs :: User -> Contact -> Preferences -> m ChatResponse updateContactPrefs user@User {userId} ct@Contact {activeConn = Connection {customUserProfileId}, userPreferences = contactUserPrefs} contactUserPrefs' @@ -1246,7 +1246,7 @@ processChatCommand = \case let p' = userProfileToSend user (fromLocalProfile <$> incognitoProfile) (Just ct') withChatLock "updateProfile" . procCmd $ do void (sendDirectContactMessage ct' $ XInfo p') `catchError` (toView . CRChatError) - when (directContact ct) $ createFeatureChangedItems user ct ct' CDDirectSnd CISndChatFeature + when (directOrUsed ct) $ createFeatureChangedItems user ct ct' CDDirectSnd CISndChatFeature pure $ CRContactPrefsUpdated ct ct' runUpdateGroupProfile :: User -> Group -> GroupProfile -> m ChatResponse runUpdateGroupProfile user (Group g@GroupInfo {groupProfile = p} ms) p' = do @@ -1317,7 +1317,7 @@ processChatCommand = \case assertDirectAllowed :: ChatMonad m => User -> MsgDirection -> Contact -> CMEventTag e -> m () assertDirectAllowed user dir ct event = - unless (allowedChatEvent || anyDirectContact ct) . unlessM directMessagesAllowed $ + unless (allowedChatEvent || anyDirectOrUsed ct) . unlessM directMessagesAllowed $ throwChatError $ CEDirectMessagesProhibited dir ct where directMessagesAllowed = any (groupFeatureAllowed' GFDirectMessages) <$> withStore' (\db -> getContactGroupPreferences db user ct) @@ -1842,7 +1842,7 @@ processAgentMessage (Just user@User {userId}) corrId agentConnId agentMessage = -- [incognito] print incognito profile used for this contact incognitoProfile <- forM customUserProfileId $ \profileId -> withStore (\db -> getProfileById db userId profileId) toView $ CRContactConnected ct (fmap fromLocalProfile incognitoProfile) - when (directContact ct) $ createFeatureEnabledItems ct + when (directOrUsed ct) $ createFeatureEnabledItems ct setActive $ ActiveC c showToast (c <> "> ") "connected" forM_ groupLinkId $ \_ -> probeMatchingContacts ct $ contactConnIncognito ct @@ -2600,7 +2600,7 @@ processAgentMessage (Just user@User {userId}) corrId agentConnId agentMessage = xInfo c@Contact {profile = p} p' = unless (fromLocalProfile p == p') $ do c' <- withStore $ \db -> updateContactProfile db user c p' toView $ CRContactUpdated c c' - when (directContact c) $ createFeatureChangedItems user c c' CDDirectRcv CIRcvChatFeature + when (directOrUsed c) $ createFeatureChangedItems user c c' CDDirectRcv CIRcvChatFeature createFeatureEnabledItems :: Contact -> m () createFeatureEnabledItems ct@Contact {mergedPreferences} = diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index 3f7599d325..0df7e935cc 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -120,12 +120,12 @@ contactConnId = aConnId . contactConn contactConnIncognito :: Contact -> Bool contactConnIncognito = connIncognito . contactConn -directContact :: Contact -> Bool -directContact Contact {contactUsed, activeConn = Connection {connLevel, viaGroupLink}} = +directOrUsed :: Contact -> Bool +directOrUsed Contact {contactUsed, activeConn = Connection {connLevel, viaGroupLink}} = (connLevel == 0 && not viaGroupLink) || contactUsed -anyDirectContact :: Contact -> Bool -anyDirectContact Contact {contactUsed, activeConn = Connection {connLevel}} = connLevel == 0 || contactUsed +anyDirectOrUsed :: Contact -> Bool +anyDirectOrUsed Contact {contactUsed, activeConn = Connection {connLevel}} = connLevel == 0 || contactUsed contactSecurityCode :: Contact -> Maybe SecurityCode contactSecurityCode Contact {activeConn} = connectionCode activeConn