core: decrease membersRequireAttention counter when member is deleted or leaves (#5919)

This commit is contained in:
spaced4ndy
2025-05-16 15:03:15 +00:00
committed by GitHub
parent 5e7f77d1d1
commit 041807c870
16 changed files with 111 additions and 68 deletions
+18 -6
View File
@@ -2077,8 +2077,8 @@ processChatCommand' vr = \case
void $ sendGroupMessage user gInfo scope ([m] <> rcpModMs') msg
when (maxVersion (memberChatVRange m) < groupKnockingVersion) $
forM_ (memberConn m) $ \mConn -> do
let msg = XMsgNew $ MCSimple $ extMsgContent (MCText acceptedToGroupMessage) Nothing
void $ sendDirectMemberMessage mConn msg groupId
let msg2 = XMsgNew $ MCSimple $ extMsgContent (MCText acceptedToGroupMessage) Nothing
void $ sendDirectMemberMessage mConn msg2 groupId
(m', gInfo') <- withFastStore' $ \db -> do
m' <- updateGroupMemberAccepted db user m newMemberStatus role
gInfo' <- updateGroupMembersRequireAttention db user gInfo m m'
@@ -2227,10 +2227,13 @@ processChatCommand' vr = \case
let acis = acis2 <> acis3 <> acis4
errs = errs1 <> errs2 <> errs3 <> errs4
deleted = deleted1 <> deleted2 <> deleted3 <> deleted4
unless (null acis) $ toView $ CEvtNewChatItems user acis
-- Read group info with updated membersRequireAttention
gInfo' <- withFastStore $ \db -> getGroupInfo db vr user groupId
let acis' = map (updateCIGroupInfo gInfo') acis
unless (null acis') $ toView $ CEvtNewChatItems user acis'
unless (null errs) $ toView $ CEvtChatErrors errs
when withMessages $ deleteMessages user gInfo deleted
pure $ CRUserDeletedMembers user gInfo deleted withMessages -- same order is not guaranteed
when withMessages $ deleteMessages user gInfo' deleted
pure $ CRUserDeletedMembers user gInfo' deleted withMessages -- same order is not guaranteed
where
selectMembers :: [GroupMember] -> (Int, [GroupMember], [GroupMember], [GroupMember], [GroupMember], GroupMemberRole, Bool)
selectMembers = foldl' addMember (0, [], [], [], [], GRObserver, False)
@@ -2280,8 +2283,17 @@ processChatCommand' vr = \case
ts = ciContentTexts content
in NewSndChatItemData msg content ts M.empty Nothing Nothing Nothing
delMember db m = do
deleteOrUpdateMemberRecordIO db user m
-- We're in a function used in batch member deletion, and since we're passing same gInfo for each member,
-- voided result (updated group info) may have incorrect state of membersRequireAttention.
-- To avoid complicating code by chaining group info updates,
-- instead we re-read it once after deleting all members before response.
void $ deleteOrUpdateMemberRecordIO db user gInfo m
pure m {memberStatus = GSMemRemoved}
updateCIGroupInfo :: GroupInfo -> AChatItem -> AChatItem
updateCIGroupInfo gInfo' = \case
AChatItem SCTGroup SMDSnd (GroupChat _gInfo chatScopeInfo) ci ->
AChatItem SCTGroup SMDSnd (GroupChat gInfo' chatScopeInfo) ci
aci -> aci
deleteMessages user gInfo@GroupInfo {membership} ms
| groupFeatureMemberAllowed SGFFullDelete membership gInfo = deleteGroupMembersCIs user gInfo ms membership
| otherwise = markGroupMembersCIsDeleted user gInfo ms membership
+10 -5
View File
@@ -1564,15 +1564,20 @@ deleteMemberConnection' GroupMember {activeConn} waitDelivery = do
deleteAgentConnectionAsync' (aConnId conn) waitDelivery
withStore' $ \db -> updateConnectionStatus db conn ConnDeleted
deleteOrUpdateMemberRecord :: User -> GroupMember -> CM ()
deleteOrUpdateMemberRecord user member =
withStore' $ \db -> deleteOrUpdateMemberRecordIO db user member
deleteOrUpdateMemberRecord :: User -> GroupInfo -> GroupMember -> CM GroupInfo
deleteOrUpdateMemberRecord user gInfo member =
withStore' $ \db -> deleteOrUpdateMemberRecordIO db user gInfo member
deleteOrUpdateMemberRecordIO :: DB.Connection -> User -> GroupMember -> IO ()
deleteOrUpdateMemberRecordIO db user@User {userId} member =
deleteOrUpdateMemberRecordIO :: DB.Connection -> User -> GroupInfo -> GroupMember -> IO GroupInfo
deleteOrUpdateMemberRecordIO db user@User {userId} gInfo member = do
gInfo' <-
if gmRequiresAttention member
then decreaseGroupMembersRequireAttention db user gInfo
else pure gInfo
checkGroupMemberHasItems db user member >>= \case
Just _ -> updateGroupMemberStatus db userId member GSMemRemoved
Nothing -> deleteGroupMember db user member
pure gInfo'
sendDirectContactMessages :: MsgEncodingI e => User -> Contact -> NonEmpty (ChatMsgEvent e) -> CM [Either ChatError SndMessage]
sendDirectContactMessages user ct events = do
+10 -6
View File
@@ -2697,10 +2697,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
-- ? prohibit deleting member if it's the sender - sender should use x.grp.leave
deleteMemberConnection member
-- undeleted "member connected" chat item will prevent deletion of member record
deleteOrUpdateMemberRecord user member
gInfo' <- deleteOrUpdateMemberRecord user gInfo member
when withMessages $ deleteMessages member SMDRcv
deleteMemberItem $ RGEMemberDeleted groupMemberId (fromLocalProfile memberProfile)
toView $ CEvtDeletedMember user gInfo m member {memberStatus = GSMemRemoved} withMessages
toView $ CEvtDeletedMember user gInfo' m member {memberStatus = GSMemRemoved} withMessages
where
checkRole GroupMember {memberRole} a
| senderRole < GRAdmin || senderRole < memberRole =
@@ -2719,11 +2719,15 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
xGrpLeave gInfo m msg brokerTs = do
deleteMemberConnection m
-- member record is not deleted to allow creation of "member left" chat item
withStore' $ \db -> updateGroupMemberStatus db userId m GSMemLeft
(gInfo', m', scopeInfo) <- mkGroupChatScope gInfo m
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
gInfo' <- withStore' $ \db -> do
updateGroupMemberStatus db userId m GSMemLeft
if gmRequiresAttention m
then decreaseGroupMembersRequireAttention db user gInfo
else pure gInfo
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo' m
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo'' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
groupMsgToView cInfo ci
toView $ CEvtLeftMember user gInfo' m' {memberStatus = GSMemLeft}
toView $ CEvtLeftMember user gInfo'' m' {memberStatus = GSMemLeft}
xGrpDel :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> CM ()
xGrpDel gInfo@GroupInfo {membership} m@GroupMember {memberRole} msg brokerTs = do
+16 -11
View File
@@ -81,6 +81,7 @@ module Simplex.Chat.Store.Groups
updateGroupMemberStatusById,
updateGroupMemberAccepted,
updateGroupMembersRequireAttention,
decreaseGroupMembersRequireAttention,
increaseGroupMembersRequireAttention,
createNewGroupMember,
checkGroupMemberHasItems,
@@ -1231,24 +1232,28 @@ updateGroupMemberAccepted db User {userId} m@GroupMember {groupMemberId} status
pure m {memberStatus = status, memberRole = role, updatedAt = currentTs}
updateGroupMembersRequireAttention :: DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> IO GroupInfo
updateGroupMembersRequireAttention db user@User {userId} g@GroupInfo {groupId, membersRequireAttention} member member'
updateGroupMembersRequireAttention db user g member member'
| nowRequires && not didRequire =
increaseGroupMembersRequireAttention db user g
| not nowRequires && didRequire = do
DB.execute
db
[sql|
UPDATE groups
SET members_require_attention = members_require_attention - 1
WHERE user_id = ? AND group_id = ?
|]
(userId, groupId)
pure g {membersRequireAttention = membersRequireAttention - 1}
| not nowRequires && didRequire =
decreaseGroupMembersRequireAttention db user g
| otherwise = pure g
where
didRequire = gmRequiresAttention member
nowRequires = gmRequiresAttention member'
decreaseGroupMembersRequireAttention :: DB.Connection -> User -> GroupInfo -> IO GroupInfo
decreaseGroupMembersRequireAttention db User {userId} g@GroupInfo {groupId, membersRequireAttention} = do
DB.execute
db
[sql|
UPDATE groups
SET members_require_attention = members_require_attention - 1
WHERE user_id = ? AND group_id = ?
|]
(userId, groupId)
pure g {membersRequireAttention = membersRequireAttention - 1}
increaseGroupMembersRequireAttention :: DB.Connection -> User -> GroupInfo -> IO GroupInfo
increaseGroupMembersRequireAttention db User {userId} g@GroupInfo {groupId, membersRequireAttention} = do
DB.execute
@@ -1335,14 +1335,6 @@ SEARCH group_profiles USING INTEGER PRIMARY KEY (rowid=?)
LIST SUBQUERY 1
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE groups
SET members_require_attention = members_require_attention - 1
WHERE user_id = ? AND group_id = ?
Plan:
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE user_contact_links
SET auto_accept = ?, business_address = ?, auto_accept_incognito = ?, auto_reply_msg_content = ?
@@ -4451,6 +4443,14 @@ Query:
Plan:
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE groups
SET members_require_attention = members_require_attention - 1
WHERE user_id = ? AND group_id = ?
Plan:
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE groups
SET via_group_link_uri_hash = (SELECT via_contact_uri_hash FROM connections WHERE connection_id = ?)