mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-04 15:21:43 +00:00
wip
This commit is contained in:
@@ -2770,8 +2770,9 @@ processChatCommand cxt nm = \case
|
||||
(errs1, changed1) <- changeRoleInvitedMems user gInfo invitedMems
|
||||
let doBumpRoster = useRelays' gInfo && memberRole' (membership gInfo) == GROwner && (isRosterRole newRole || anyPrivilegedTarget)
|
||||
rosterVer <- if doBumpRoster then Just <$> reserveRosterVersion gInfo else pure Nothing
|
||||
-- roster (with the change projected in) before the delta, so a relay stores the blob at this version before forwarding the delta
|
||||
forM_ rosterVer $ \v -> broadcastRoster user gInfo v (RDRoleChanged newRole currentMems) `catchAllErrors` eToView
|
||||
(errs2, changed2, acis, msgSigned) <- changeRoleCurrentMems user g rosterVer currentMems
|
||||
forM_ rosterVer $ \v -> broadcastRoster user gInfo v `catchAllErrors` eToView
|
||||
unless (null acis) $ toView $ CEvtNewChatItems user acis
|
||||
let errs = errs1 <> errs2
|
||||
unless (null errs) $ toView $ CEvtChatErrors errs
|
||||
@@ -2898,13 +2899,14 @@ processChatCommand cxt nm = \case
|
||||
let recipients = filter memberCurrent members
|
||||
let doBumpRoster = useRelays' gInfo && memberRole' (membership gInfo) == GROwner && anyPrivilegedRemoved
|
||||
rosterVer <- if doBumpRoster then Just <$> reserveRosterVersion gInfo else pure Nothing
|
||||
-- roster (excluding the removed members) before the delta, so a relay stores the blob at this version before forwarding the delta
|
||||
forM_ rosterVer $ \v -> broadcastRoster user gInfo v (RDRemoved currentMems) `catchAllErrors` eToView
|
||||
(errs2, deleted2, acis2, signed2) <- deleteMemsSend user gInfo Nothing rosterVer recipients currentMems
|
||||
(errs3, deleted3, acis3, signed3) <-
|
||||
foldM (\acc m -> deletePendingMember acc user gInfo [m] m) ([], [], [], False) pendingApprvMems
|
||||
let moderators = filter (\GroupMember {memberRole} -> memberRole >= GRModerator) members
|
||||
(errs4, deleted4, acis4, signed4) <-
|
||||
foldM (\acc m -> deletePendingMember acc user gInfo (m : moderators) m) ([], [], [], False) pendingRvwMems
|
||||
forM_ rosterVer $ \v -> broadcastRoster user gInfo v `catchAllErrors` eToView
|
||||
let acis = acis2 <> acis3 <> acis4
|
||||
errs = errs1 <> errs2 <> errs3 <> errs4
|
||||
deleted = deleted1 <> deleted2 <> deleted3 <> deleted4
|
||||
|
||||
@@ -2271,20 +2271,34 @@ sendGroupMessage' user gInfo members chatMsgEvent =
|
||||
-- TODO after restoring from a stale backup (relays accept only strictly-greater versions)
|
||||
-- Persist the next roster version before sending the events that carry it (so a recipient never advances
|
||||
-- past a version the owner hasn't recorded). The matching blob is broadcast separately, by broadcastRoster,
|
||||
-- after the change is applied to the owner's members - so the served roster excludes demoted/removed members.
|
||||
-- with the change projected onto the served roster - so it excludes demoted/removed members.
|
||||
reserveRosterVersion :: GroupInfo -> CM VersionRoster
|
||||
reserveRosterVersion gInfo = do
|
||||
let rosterVer = maybe (VersionRoster 0) (\(VersionRoster n) -> VersionRoster (n + 1)) (rosterVersion gInfo)
|
||||
withStore' $ \db -> setGroupRosterVersion db gInfo rosterVer
|
||||
pure rosterVer
|
||||
|
||||
broadcastRoster :: User -> GroupInfo -> VersionRoster -> CM ()
|
||||
broadcastRoster user gInfo rosterVer = do
|
||||
-- The roster change being broadcast, projected onto the current roster members in broadcastRoster. This lets the
|
||||
-- roster blob be built (and sent) before the change is applied to the owner's own member records, so the owner
|
||||
-- never demotes/removes a member locally before the change has been propagated to relays.
|
||||
data RosterDelta
|
||||
= RDRoleChanged GroupMemberRole [GroupMember] -- these members now hold this role
|
||||
| RDRemoved [GroupMember] -- these members are removed from the group
|
||||
|
||||
applyRosterDelta :: RosterDelta -> [GroupMember] -> [GroupMember]
|
||||
applyRosterDelta delta current = case delta of
|
||||
RDRoleChanged role changed -> map (\m -> (m :: GroupMember) {memberRole = role}) changed <> without changed
|
||||
RDRemoved removed -> without removed
|
||||
where
|
||||
without ms = let ids = S.fromList (map groupMemberId' ms) in filter ((`S.notMember` ids) . groupMemberId') current
|
||||
|
||||
broadcastRoster :: User -> GroupInfo -> VersionRoster -> RosterDelta -> CM ()
|
||||
broadcastRoster user gInfo rosterVer delta = do
|
||||
cxt <- chatStoreCxt
|
||||
(relays, rosterMems) <- withStore' $ \db ->
|
||||
(,) <$> getGroupRelayMembers db cxt user gInfo <*> getGroupRosterMembers db cxt user gInfo
|
||||
forM_ (L.nonEmpty relays) $ \relays' ->
|
||||
sendRoster user gInfo (L.toList relays') rosterVer (buildGroupRoster rosterMems)
|
||||
sendRoster user gInfo (L.toList relays') rosterVer (buildGroupRoster $ applyRosterDelta delta rosterMems)
|
||||
|
||||
-- Send the current roster (no version bump) to a newly added relay so it can serve joiners.
|
||||
sendGroupRosterToRelay :: User -> GroupInfo -> GroupMember -> CM ()
|
||||
|
||||
Reference in New Issue
Block a user