mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 02:12:25 +00:00
core: member requires attention counter (#5881)
This commit is contained in:
1 parent
2a9df3e10b
commit
79991e84c9
33 files changed
+530
-494
No files matched your search
@@ -676,6 +676,7 @@ data ChatResponse
|
||||
| CRSentConfirmation {user :: User, connection :: PendingContactConnection}
|
||||
| CRSentInvitation {user :: User, connection :: PendingContactConnection, customUserProfile :: Maybe Profile}
|
||||
| CRSentInvitationToContact {user :: User, contact :: Contact, customUserProfile :: Maybe Profile}
|
||||
| CRItemsReadForChat {user :: User, chatInfo :: AChatInfo}
|
||||
| CRContactDeleted {user :: User, contact :: Contact}
|
||||
| CRChatCleared {user :: User, chatInfo :: AChatInfo}
|
||||
| CRUserContactLinkCreated {user :: User, connLinkContact :: CreatedLinkContact}
|
||||
|
||||
@@ -1017,22 +1017,26 @@ processChatCommand' vr = \case
|
||||
CTContactConnection -> throwCmdError "not supported"
|
||||
APIChatItemsRead chatRef@(ChatRef cType chatId scope) itemIds -> withUser $ \_ -> case cType of
|
||||
CTDirect -> do
|
||||
user <- withFastStore $ \db -> getUserByContactId db chatId
|
||||
(user, ct) <- withFastStore $ \db -> do
|
||||
user <- getUserByContactId db chatId
|
||||
ct <- getContact db vr user chatId
|
||||
pure (user, ct)
|
||||
timedItems <- withFastStore' $ \db -> do
|
||||
timedItems <- updateDirectChatItemsReadList db user chatId itemIds
|
||||
setDirectChatItemsDeleteAt db user chatId timedItems =<< getCurrentTime
|
||||
forM_ timedItems $ \(itemId, deleteAt) -> startProximateTimedItemThread user (chatRef, itemId) deleteAt
|
||||
ok user
|
||||
pure $ CRItemsReadForChat user (AChatInfo SCTDirect $ DirectChat ct)
|
||||
CTGroup -> do
|
||||
(user, gInfo) <- withFastStore $ \db -> do
|
||||
user <- getUserByGroupId db chatId
|
||||
gInfo <- getGroupInfo db vr user chatId
|
||||
pure (user, gInfo)
|
||||
timedItems <- withFastStore' $ \db -> do
|
||||
timedItems <- updateGroupChatItemsReadList db user gInfo scope itemIds
|
||||
setGroupChatItemsDeleteAt db user chatId timedItems =<< getCurrentTime
|
||||
(timedItems, gInfo') <- withFastStore $ \db -> do
|
||||
(timedItems, gInfo') <- updateGroupChatItemsReadList db vr user gInfo scope itemIds
|
||||
timedItems' <- liftIO $ setGroupChatItemsDeleteAt db user chatId timedItems =<< getCurrentTime
|
||||
pure (timedItems', gInfo')
|
||||
forM_ timedItems $ \(itemId, deleteAt) -> startProximateTimedItemThread user (chatRef, itemId) deleteAt
|
||||
ok user
|
||||
pure $ CRItemsReadForChat user (AChatInfo SCTGroup $ GroupChat gInfo' Nothing)
|
||||
CTLocal -> throwCmdError "not supported"
|
||||
CTContactRequest -> throwCmdError "not supported"
|
||||
CTContactConnection -> throwCmdError "not supported"
|
||||
@@ -2054,8 +2058,11 @@ processChatCommand' vr = \case
|
||||
void $ sendDirectMemberMessage mConn msg groupId
|
||||
introduceToRemaining vr user gInfo m {memberRole = role}
|
||||
when (groupFeatureAllowed SGFHistory gInfo) $ sendHistory user gInfo m
|
||||
m' <- withFastStore' $ \db -> updateGroupMemberAccepted db user m GSMemConnected role
|
||||
pure $ CRMemberAccepted user gInfo m'
|
||||
(m', gInfo') <- withFastStore' $ \db -> do
|
||||
m' <- updateGroupMemberAccepted db user m GSMemConnected role
|
||||
gInfo' <- updateGroupMembersRequireAttention db user gInfo m m'
|
||||
pure (m', gInfo')
|
||||
pure $ CRMemberAccepted user gInfo' m'
|
||||
Nothing -> throwChatError CEGroupMemberNotActive
|
||||
GSMemPendingReview -> do
|
||||
let scope = Just $ GCSMemberSupport $ Just (groupMemberId' m)
|
||||
@@ -2063,8 +2070,11 @@ processChatCommand' vr = \case
|
||||
let rcpModMs' = filter memberCurrent modMs
|
||||
msg = XGrpLinkAcpt GAAccepted role (memberId' m)
|
||||
void $ sendGroupMessage user gInfo scope ([m] <> rcpModMs') msg
|
||||
m' <- withFastStore' $ \db -> updateGroupMemberAccepted db user m newMemberStatus role
|
||||
pure $ CRMemberAccepted user gInfo m'
|
||||
(m', gInfo') <- withFastStore' $ \db -> do
|
||||
m' <- updateGroupMemberAccepted db user m newMemberStatus role
|
||||
gInfo' <- updateGroupMembersRequireAttention db user gInfo m m'
|
||||
pure (m', gInfo')
|
||||
pure $ CRMemberAccepted user gInfo' m'
|
||||
where
|
||||
newMemberStatus = case memberConn m of
|
||||
Just c | connReady c -> GSMemConnected
|
||||
|
||||
@@ -2032,8 +2032,9 @@ saveSndChatItems ::
|
||||
CM [Either ChatError (ChatItem c 'MDSnd)]
|
||||
saveSndChatItems user cd itemsData itemTimed live = do
|
||||
createdAt <- liftIO getCurrentTime
|
||||
vr <- chatVersionRange
|
||||
when (contactChatDeleted cd || any (\NewSndChatItemData {content} -> ciRequiresAttention content) (rights itemsData)) $
|
||||
withStore' (\db -> updateChatTsStats db user cd createdAt Nothing)
|
||||
void $ withStore' (\db -> updateChatTsStats db vr user cd createdAt Nothing)
|
||||
lift $ withStoreBatch (\db -> map (bindRight $ createItem db createdAt) itemsData)
|
||||
where
|
||||
createItem :: DB.Connection -> UTCTime -> NewSndChatItemData c -> IO (Either ChatError (ChatItem c 'MDSnd))
|
||||
@@ -2045,19 +2046,20 @@ saveSndChatItems user cd itemsData itemTimed live = do
|
||||
CDGroupSnd g _scope | not (null itemMentions) -> createGroupCIMentions db g ci itemMentions
|
||||
_ -> pure ci
|
||||
|
||||
saveRcvChatItemNoParse :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> CIContent 'MDRcv -> CM (ChatItem c 'MDRcv)
|
||||
saveRcvChatItemNoParse :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> CIContent 'MDRcv -> CM (ChatItem c 'MDRcv, ChatInfo c)
|
||||
saveRcvChatItemNoParse user cd msg brokerTs = saveRcvChatItem user cd msg brokerTs . ciContentNoParse
|
||||
|
||||
saveRcvChatItem :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> (CIContent 'MDRcv, (Text, Maybe MarkdownList)) -> CM (ChatItem c 'MDRcv)
|
||||
saveRcvChatItem :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> (CIContent 'MDRcv, (Text, Maybe MarkdownList)) -> CM (ChatItem c 'MDRcv, ChatInfo c)
|
||||
saveRcvChatItem user cd msg@RcvMessage {sharedMsgId_} brokerTs content =
|
||||
saveRcvChatItem' user cd msg sharedMsgId_ brokerTs content Nothing Nothing False M.empty
|
||||
|
||||
ciContentNoParse :: CIContent 'MDRcv -> (CIContent 'MDRcv, (Text, Maybe MarkdownList))
|
||||
ciContentNoParse content = (content, (ciContentToText content, Nothing))
|
||||
|
||||
saveRcvChatItem' :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> UTCTime -> (CIContent 'MDRcv, (Text, Maybe MarkdownList)) -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> Map MemberName MsgMention -> CM (ChatItem c 'MDRcv)
|
||||
saveRcvChatItem' :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> UTCTime -> (CIContent 'MDRcv, (Text, Maybe MarkdownList)) -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> Map MemberName MsgMention -> CM (ChatItem c 'MDRcv, ChatInfo c)
|
||||
saveRcvChatItem' user cd msg@RcvMessage {chatMsgEvent, forwardedByMember} sharedMsgId_ brokerTs (content, (t, ft_)) ciFile itemTimed live mentions = do
|
||||
createdAt <- liftIO getCurrentTime
|
||||
vr <- chatVersionRange
|
||||
withStore' $ \db -> do
|
||||
(mentions' :: Map MemberName CIMention, userMention) <- case cd of
|
||||
CDGroupRcv g@GroupInfo {membership} _scope _m -> do
|
||||
@@ -2068,13 +2070,16 @@ saveRcvChatItem' user cd msg@RcvMessage {chatMsgEvent, forwardedByMember} shared
|
||||
userMention' = userReply || any (\CIMention {memberId} -> sameMemberId memberId membership) mentions'
|
||||
in pure (mentions', userMention')
|
||||
CDDirectRcv _ -> pure (M.empty, False)
|
||||
when (ciRequiresAttention content || contactChatDeleted cd) $ updateChatTsStats db user cd createdAt (chatStatsCounts userMention)
|
||||
cInfo' <- if (ciRequiresAttention content || contactChatDeleted cd)
|
||||
then updateChatTsStats db vr user cd createdAt (chatStatsCounts userMention)
|
||||
else pure $ toChatInfo cd
|
||||
(ciId, quotedItem, itemForwarded) <- createNewRcvChatItem db user cd msg sharedMsgId_ content itemTimed live userMention brokerTs createdAt
|
||||
forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt
|
||||
let ci = mkChatItem_ cd ciId content (t, ft_) ciFile quotedItem sharedMsgId_ itemForwarded itemTimed live userMention brokerTs forwardedByMember createdAt
|
||||
case cd of
|
||||
ci' <- case cd of
|
||||
CDGroupRcv g _scope _m | not (null mentions') -> createGroupCIMentions db g ci mentions'
|
||||
_ -> pure ci
|
||||
pure (ci', cInfo')
|
||||
where
|
||||
chatStatsCounts :: Bool -> Maybe (Int, MemberAttention, Int)
|
||||
chatStatsCounts userMention = case cd of
|
||||
@@ -2297,12 +2302,13 @@ createInternalItemsForChats ::
|
||||
createInternalItemsForChats user itemTs_ dirsCIContents = do
|
||||
createdAt <- liftIO getCurrentTime
|
||||
let itemTs = fromMaybe createdAt itemTs_
|
||||
void . withStoreBatch' $ \db -> map (uncurry $ updateChat db createdAt) dirsCIContents
|
||||
vr <- chatVersionRange'
|
||||
void . withStoreBatch' $ \db -> map (uncurry $ updateChat db vr createdAt) dirsCIContents
|
||||
withStoreBatch' $ \db -> concatMap (uncurry $ createACIs db itemTs createdAt) dirsCIContents
|
||||
where
|
||||
updateChat :: DB.Connection -> UTCTime -> ChatDirection c d -> [CIContent d] -> IO ()
|
||||
updateChat db createdAt cd contents
|
||||
| any ciRequiresAttention contents || contactChatDeleted cd = updateChatTsStats db user cd createdAt chatStatsCounts
|
||||
updateChat :: DB.Connection -> VersionRangeChat -> UTCTime -> ChatDirection c d -> [CIContent d] -> IO ()
|
||||
updateChat db vr createdAt cd contents
|
||||
| any ciRequiresAttention contents || contactChatDeleted cd = void $ updateChatTsStats db vr user cd createdAt chatStatsCounts
|
||||
| otherwise = pure ()
|
||||
where
|
||||
chatStatsCounts :: Maybe (Int, MemberAttention, Int)
|
||||
@@ -2331,7 +2337,8 @@ createLocalChatItems ::
|
||||
UTCTime ->
|
||||
CM [ChatItem 'CTLocal 'MDSnd]
|
||||
createLocalChatItems user cd itemsData createdAt = do
|
||||
withStore' $ \db -> updateChatTsStats db user cd createdAt Nothing
|
||||
vr <- chatVersionRange
|
||||
void $ withStore' $ \db -> updateChatTsStats db vr user cd createdAt Nothing
|
||||
(errs, items) <- lift $ partitionEithers <$> withStoreBatch' (\db -> map (createItem db) $ L.toList itemsData)
|
||||
unless (null errs) $ toView $ CEvtChatErrors errs
|
||||
pure items
|
||||
|
||||
@@ -784,29 +784,33 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
memberConnectedChatItem gInfo' scopeInfo m'
|
||||
unless (memberPending membership) $ maybeCreateGroupDescrLocal gInfo' m'
|
||||
GCInviteeMember -> do
|
||||
mStatus <-
|
||||
(gInfo', mStatus) <-
|
||||
if not (memberPending m)
|
||||
then withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected $> GSMemConnected
|
||||
else pure $ memberStatus m
|
||||
(gInfo', m', scopeInfo) <- mkGroupChatScope gInfo m
|
||||
memberConnectedChatItem gInfo' scopeInfo m'
|
||||
then do
|
||||
mStatus <- withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected $> GSMemConnected
|
||||
pure (gInfo, mStatus)
|
||||
else do
|
||||
gInfo' <- withStore' $ \db -> increaseGroupMembersRequireAttention db user gInfo
|
||||
pure (gInfo', memberStatus m)
|
||||
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo' m
|
||||
memberConnectedChatItem gInfo'' scopeInfo m'
|
||||
case scopeInfo of
|
||||
Just (GCSIMemberSupport _) -> do
|
||||
createInternalChatItem user (CDGroupRcv gInfo' scopeInfo m') (CIRcvGroupEvent RGENewMemberPendingReview) Nothing
|
||||
createInternalChatItem user (CDGroupRcv gInfo'' scopeInfo m') (CIRcvGroupEvent RGENewMemberPendingReview) Nothing
|
||||
_ -> pure ()
|
||||
toView $ CEvtJoinedGroupMember user gInfo' m' {memberStatus = mStatus}
|
||||
toView $ CEvtJoinedGroupMember user gInfo'' m' {memberStatus = mStatus}
|
||||
let Connection {viaUserContactLink} = conn
|
||||
when (isJust viaUserContactLink && isNothing (memberContactId m')) $ sendXGrpLinkMem gInfo'
|
||||
when (isJust viaUserContactLink && isNothing (memberContactId m')) $ sendXGrpLinkMem gInfo''
|
||||
when (connChatVersion < batchSend2Version) sendGroupAutoReply
|
||||
case mStatus of
|
||||
GSMemPendingApproval -> pure ()
|
||||
GSMemPendingReview -> introduceToModerators vr user gInfo' m'
|
||||
GSMemPendingReview -> introduceToModerators vr user gInfo'' m'
|
||||
_ -> do
|
||||
introduceToAll vr user gInfo' m'
|
||||
when (groupFeatureAllowed SGFHistory gInfo') $ sendHistory user gInfo' m'
|
||||
introduceToAll vr user gInfo'' m'
|
||||
when (groupFeatureAllowed SGFHistory gInfo'') $ sendHistory user gInfo'' m'
|
||||
where
|
||||
sendXGrpLinkMem gInfo' = do
|
||||
let profileMode = ExistingIncognito <$> incognitoMembershipProfile gInfo'
|
||||
sendXGrpLinkMem gInfo'' = do
|
||||
let profileMode = ExistingIncognito <$> incognitoMembershipProfile gInfo''
|
||||
profileToSend = profileToSendOnAccept user profileMode True
|
||||
void $ sendDirectMemberMessage conn (XGrpLinkMem profileToSend) groupId
|
||||
_ -> do
|
||||
@@ -1466,9 +1470,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
where
|
||||
brokerTs = metaBrokerTs msgMeta
|
||||
newChatItem content ciFile_ timed_ live = do
|
||||
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content ciFile_ timed_ live M.empty
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content ciFile_ timed_ live M.empty
|
||||
reactions <- maybe (pure []) (\sharedMsgId -> withStore' $ \db -> getDirectCIReactions db ct sharedMsgId) sharedMsgId_
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct) ci {reactions}]
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci {reactions}]
|
||||
|
||||
autoAcceptFile :: Maybe (RcvFileTransfer, CIFile 'MDRcv) -> CM ()
|
||||
autoAcceptFile = mapM_ $ \(ft, CIFile {fileSize}) -> do
|
||||
@@ -1534,11 +1538,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
-- Chat item and update message which created it will have different sharedMsgId in this case...
|
||||
let timed_ = rcvContactCITimed ct ttl
|
||||
ts = ciContentTexts content
|
||||
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg (Just sharedMsgId) brokerTs (content, ts) Nothing timed_ live M.empty
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDDirectRcv ct) msg (Just sharedMsgId) brokerTs (content, ts) Nothing timed_ live M.empty
|
||||
ci' <- withStore' $ \db -> do
|
||||
createChatItemVersion db (chatItemId' ci) brokerTs mc
|
||||
updateDirectChatItem' db user contactId ci content True live Nothing Nothing
|
||||
toView $ CEvtChatItemUpdated user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci')
|
||||
toView $ CEvtChatItemUpdated user (AChatItem SCTDirect SMDRcv cInfo ci')
|
||||
where
|
||||
brokerTs = metaBrokerTs msgMeta
|
||||
content = CIRcvMsgContent mc
|
||||
@@ -1658,27 +1662,26 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
| groupFeatureAllowed SGFFullDelete gInfo = do
|
||||
(gInfo', m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
-- ignores member role when blocked by admin
|
||||
ci <- saveRcvCI gInfo' scopeInfo m' (ciContentNoParse CIRcvBlocked) Nothing timed' False M.empty
|
||||
(ci, cInfo) <- saveRcvCI gInfo' scopeInfo m' (ciContentNoParse CIRcvBlocked) Nothing timed' False M.empty
|
||||
ci' <- withStore' $ \db -> updateGroupCIBlockedByAdmin db user gInfo' ci brokerTs
|
||||
groupMsgToView gInfo' scopeInfo ci'
|
||||
groupMsgToView cInfo ci'
|
||||
| otherwise = do
|
||||
file_ <- processFileInv
|
||||
ci <- createNonLive file_
|
||||
(ci, cInfo) <- createNonLive file_
|
||||
ci' <- withStore' $ \db -> markGroupCIBlockedByAdmin db user gInfo ci
|
||||
(gInfo', _m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
groupMsgToView gInfo' scopeInfo ci'
|
||||
groupMsgToView cInfo ci'
|
||||
applyModeration CIModeration {moderatorMember = moderator@GroupMember {memberRole = moderatorRole}, moderatedAt}
|
||||
| moderatorRole < GRModerator || moderatorRole < memberRole =
|
||||
createContentItem
|
||||
| groupFeatureMemberAllowed SGFFullDelete moderator gInfo = do
|
||||
(gInfo', m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
ci <- saveRcvCI gInfo' scopeInfo m' (ciContentNoParse CIRcvModerated) Nothing timed' False M.empty
|
||||
(ci, cInfo) <- saveRcvCI gInfo' scopeInfo m' (ciContentNoParse CIRcvModerated) Nothing timed' False M.empty
|
||||
ci' <- withStore' $ \db -> updateGroupChatItemModerated db user gInfo' ci moderator moderatedAt
|
||||
groupMsgToView gInfo' scopeInfo ci'
|
||||
groupMsgToView cInfo ci'
|
||||
| otherwise = do
|
||||
(gInfo', _m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
file_ <- processFileInv
|
||||
ci <- createNonLive file_
|
||||
(ci, _cInfo) <- createNonLive file_
|
||||
deletions <- markGroupCIsDeleted user gInfo' scopeInfo [CChatItem SMDRcv ci] (Just moderator) moderatedAt
|
||||
toView $ CEvtChatItemsDeleted user deletions False False
|
||||
createNonLive file_ = do
|
||||
@@ -1693,10 +1696,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
newChatItem ciContent ciFile_ timed_ live = do
|
||||
let mentions' = if showMessages (memberSettings m) then mentions else []
|
||||
(gInfo', m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
ci <- saveRcvCI gInfo' scopeInfo m' ciContent ciFile_ timed_ live mentions'
|
||||
(ci, cInfo) <- saveRcvCI gInfo' scopeInfo m' ciContent ciFile_ timed_ live mentions'
|
||||
ci' <- blockedMember m' ci $ withStore' $ \db -> markGroupChatItemBlocked db user gInfo' ci
|
||||
reactions <- maybe (pure []) (\sharedMsgId -> withStore' $ \db -> getGroupCIReactions db gInfo' memberId sharedMsgId) sharedMsgId_
|
||||
groupMsgToView gInfo' scopeInfo ci' {reactions}
|
||||
groupMsgToView cInfo ci' {reactions}
|
||||
|
||||
groupMessageUpdate :: GroupInfo -> GroupMember -> SharedMsgId -> MsgContent -> Map MemberName MsgMention -> Maybe MsgScope -> RcvMessage -> UTCTime -> Maybe Int -> Maybe Bool -> CM ()
|
||||
groupMessageUpdate gInfo@GroupInfo {groupId} m@GroupMember {groupMemberId, memberId} sharedMsgId mc mentions msgScope_ msg@RcvMessage {msgId} brokerTs ttl_ live_
|
||||
@@ -1710,12 +1713,12 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
let timed_ = rcvGroupCITimed gInfo ttl_
|
||||
mentions' = if showMessages (memberSettings m) then mentions else []
|
||||
(gInfo', m', scopeInfo) <- mkGetMessageChatScope vr user gInfo m msgScope_
|
||||
ci <- saveRcvChatItem' user (CDGroupRcv gInfo' scopeInfo m') msg (Just sharedMsgId) brokerTs (content, ts) Nothing timed_ live mentions'
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDGroupRcv gInfo' scopeInfo m') msg (Just sharedMsgId) brokerTs (content, ts) Nothing timed_ live mentions'
|
||||
ci' <- withStore' $ \db -> do
|
||||
createChatItemVersion db (chatItemId' ci) brokerTs mc
|
||||
ci' <- updateGroupChatItem db user groupId ci content True live Nothing
|
||||
blockedMember m' ci' $ markGroupChatItemBlocked db user gInfo' ci'
|
||||
toView $ CEvtChatItemUpdated user (AChatItem SCTGroup SMDRcv (GroupChat gInfo' scopeInfo) ci')
|
||||
toView $ CEvtChatItemUpdated user (AChatItem SCTGroup SMDRcv cInfo ci')
|
||||
where
|
||||
content = CIRcvMsgContent mc
|
||||
ts@(_, ft_) = msgContentTexts mc
|
||||
@@ -1802,8 +1805,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
let fileProtocol = if isJust xftpRcvFile then FPXFTP else FPSMP
|
||||
ciFile = Just $ CIFile {fileId, fileName, fileSize, fileSource = Nothing, fileStatus = CIFSRcvInvitation, fileProtocol}
|
||||
content = ciContentNoParse $ CIRcvMsgContent $ MCFile ""
|
||||
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content ciFile Nothing False M.empty
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct) ci]
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content ciFile Nothing False M.empty
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
where
|
||||
brokerTs = metaBrokerTs msgMeta
|
||||
|
||||
@@ -1816,9 +1819,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
let fileProtocol = if isJust xftpRcvFile then FPXFTP else FPSMP
|
||||
ciFile = Just $ CIFile {fileId, fileName, fileSize, fileSource = Nothing, fileStatus = CIFSRcvInvitation, fileProtocol}
|
||||
content = ciContentNoParse $ CIRcvMsgContent $ MCFile ""
|
||||
ci <- saveRcvChatItem' user (CDGroupRcv gInfo Nothing m) msg sharedMsgId_ brokerTs content ciFile Nothing False M.empty
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDGroupRcv gInfo Nothing m) msg sharedMsgId_ brokerTs content ciFile Nothing False M.empty
|
||||
ci' <- blockedMember m ci $ withStore' $ \db -> markGroupChatItemBlocked db user gInfo ci
|
||||
groupMsgToView gInfo Nothing ci'
|
||||
groupMsgToView cInfo ci'
|
||||
|
||||
blockedMember :: Monad m' => GroupMember -> ChatItem c d -> m' (ChatItem c d) -> m' (ChatItem c d)
|
||||
blockedMember m ci blockedCI
|
||||
@@ -1969,9 +1972,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
_ -> messageError "x.file.acpt.inv: member connection is not active"
|
||||
else messageError "x.file.acpt.inv: fileName is different from expected"
|
||||
|
||||
groupMsgToView :: forall d. MsgDirectionI d => GroupInfo -> Maybe GroupChatScopeInfo -> ChatItem 'CTGroup d -> CM ()
|
||||
groupMsgToView gInfo chatScopeInfo ci = do
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTGroup (msgDirection @d) (GroupChat gInfo chatScopeInfo) ci]
|
||||
groupMsgToView :: forall d. MsgDirectionI d => ChatInfo 'CTGroup -> ChatItem 'CTGroup d -> CM ()
|
||||
groupMsgToView cInfo ci = do
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTGroup (msgDirection @d) cInfo ci]
|
||||
|
||||
processGroupInvitation :: Contact -> GroupInvitation -> RcvMessage -> MsgMeta -> CM ()
|
||||
processGroupInvitation ct inv msg msgMeta = do
|
||||
@@ -1996,9 +1999,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
toView $ CEvtUserAcceptedGroupSent user gInfo {membership = membership {memberStatus = GSMemAccepted}} (Just ct)
|
||||
else do
|
||||
let content = CIRcvGroupInvitation (CIGroupInvitation {groupId, groupMemberId, localDisplayName, groupProfile, status = CIGISPending}) memRole
|
||||
ci <- saveRcvChatItemNoParse user (CDDirectRcv ct) msg brokerTs content
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDDirectRcv ct) msg brokerTs content
|
||||
withStore' $ \db -> setGroupInvitationChatItemId db user groupId (chatItemId' ci)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct) ci]
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
toView $ CEvtReceivedGroupInvitation {user, groupInfo = gInfo, contact = ct, fromMemberRole = fromRole, memberRole = memRole}
|
||||
where
|
||||
brokerTs = metaBrokerTs msgMeta
|
||||
@@ -2024,8 +2027,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
forM_ contactConns $ \conn -> withStore' $ \db -> updateConnectionStatus db conn ConnDeleted
|
||||
activeConn' <- forM (contactConn ct') $ \conn -> pure conn {connStatus = ConnDeleted}
|
||||
let ct'' = ct' {activeConn = activeConn'} :: Contact
|
||||
ci <- saveRcvChatItemNoParse user (CDDirectRcv ct'') msg brokerTs (CIRcvDirectEvent RDEContactDeleted)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct'') ci]
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDDirectRcv ct'') msg brokerTs (CIRcvDirectEvent RDEContactDeleted)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
toView $ CEvtContactDeletedByContact user ct''
|
||||
else do
|
||||
contactConns <- withStore' $ \db -> getContactConnections db vr userId c
|
||||
@@ -2096,13 +2099,16 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
withStore' (\db -> runExceptT $ getGroupMemberByMemberId db vr user gInfo memberId) >>= \case
|
||||
Left _ -> messageError "x.grp.link.acpt error: referenced member does not exist"
|
||||
Right referencedMember -> do
|
||||
referencedMember' <- withFastStore' $ \db -> updateGroupMemberAccepted db user referencedMember (newMemberStatus referencedMember) role
|
||||
(referencedMember', gInfo') <- withFastStore' $ \db -> do
|
||||
referencedMember' <- updateGroupMemberAccepted db user referencedMember (newMemberStatus referencedMember) role
|
||||
gInfo' <- updateGroupMembersRequireAttention db user gInfo referencedMember referencedMember'
|
||||
pure (referencedMember', gInfo')
|
||||
when (memberCategory referencedMember == GCInviteeMember) $ introduceToRemainingMembers referencedMember'
|
||||
let scopeInfo = Just $ GCSIMemberSupport {groupMember_ = Just referencedMember'}
|
||||
gEvent = RGEMemberAccepted (groupMemberId' referencedMember') (fromLocalProfile $ memberProfile referencedMember')
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo scopeInfo m) msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView gInfo scopeInfo ci
|
||||
toView $ CEvtMemberAcceptedByOther user gInfo m referencedMember'
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m) msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView cInfo ci
|
||||
toView $ CEvtMemberAcceptedByOther user gInfo' m referencedMember'
|
||||
where
|
||||
newMemberStatus refMem = case memberConn refMem of
|
||||
Just c | connReady c -> GSMemConnected
|
||||
@@ -2112,8 +2118,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
GAAccepted -> do
|
||||
membership' <- withStore' $ \db -> updateGroupMemberAccepted db user membership GSMemConnected role
|
||||
let scopeInfo = Just $ GCSIMemberSupport {groupMember_ = Nothing}
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo scopeInfo m) msg brokerTs (CIRcvGroupEvent RGEUserAccepted)
|
||||
groupMsgToView gInfo scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo scopeInfo m) msg brokerTs (CIRcvGroupEvent RGEUserAccepted)
|
||||
groupMsgToView cInfo ci
|
||||
toView $ CEvtUserJoinedGroup user gInfo {membership = membership'} m
|
||||
let cd = CDGroupRcv gInfo Nothing m
|
||||
createInternalChatItem user cd (CIRcvGroupE2EEInfo E2EInfo {pqEnabled = PQEncOff}) Nothing
|
||||
@@ -2265,7 +2271,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
then do
|
||||
g <- asks random
|
||||
dhKeyPair <- atomically $ if encryptedCall callType then Just <$> C.generateKeyPair g else pure Nothing
|
||||
ci <- saveCallItem CISCallPending
|
||||
(ci, cInfo) <- saveCallItem CISCallPending
|
||||
callUUID <- UUID.toText <$> liftIO V4.nextRandom
|
||||
let sharedKey = C.Key . C.dhBytes' <$> (C.dh' <$> callDhPubKey <*> (snd <$> dhKeyPair))
|
||||
callState = CallInvitationReceived {peerCallType = callType, localDhPubKey = fst <$> dhKeyPair, sharedKey}
|
||||
@@ -2278,15 +2284,15 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
call_ <- atomically (TM.lookupInsert contactId call' calls)
|
||||
forM_ call_ $ \call -> updateCallItemStatus user ct call WCSDisconnected Nothing
|
||||
toView $ CEvtCallInvitation RcvCallInvitation {user, contact = ct, callType, sharedKey, callUUID, callTs = chatItemTs' ci}
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct) ci]
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
else featureRejected CFCalls
|
||||
where
|
||||
brokerTs = metaBrokerTs msgMeta
|
||||
saveCallItem status = saveRcvChatItemNoParse user (CDDirectRcv ct) msg brokerTs (CIRcvCall status 0)
|
||||
featureRejected f = do
|
||||
let content = ciContentNoParse $ CIRcvChatFeatureRejected f
|
||||
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content Nothing Nothing False M.empty
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat ct) ci]
|
||||
(ci, cInfo) <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs content Nothing Nothing False M.empty
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
|
||||
-- to party initiating call
|
||||
xCallOffer :: Contact -> CallId -> CallOffer -> RcvMessage -> CM ()
|
||||
@@ -2457,27 +2463,37 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
unless (sameMemberId memId $ membership gInfo) $
|
||||
withStore' (\db -> runExceptT $ getGroupMemberByMemberId db vr user gInfo memId) >>= \case
|
||||
Right unknownMember@GroupMember {memberStatus = GSMemUnknown} -> do
|
||||
updatedMember <- withStore $ \db -> updateUnknownMemberAnnounced db vr user m unknownMember memInfo initialStatus
|
||||
toView $ CEvtUnknownMemberAnnounced user gInfo m unknownMember updatedMember
|
||||
memberAnnouncedToView updatedMember
|
||||
(updatedMember, gInfo') <- withStore $ \db -> do
|
||||
updatedMember <- updateUnknownMemberAnnounced db vr user m unknownMember memInfo initialStatus
|
||||
gInfo' <- if memberPending updatedMember
|
||||
then liftIO $ increaseGroupMembersRequireAttention db user gInfo
|
||||
else pure gInfo
|
||||
pure (updatedMember, gInfo')
|
||||
toView $ CEvtUnknownMemberAnnounced user gInfo' m unknownMember updatedMember
|
||||
memberAnnouncedToView updatedMember gInfo'
|
||||
Right _ -> messageError "x.grp.mem.new error: member already exists"
|
||||
Left _ -> do
|
||||
newMember <- withStore $ \db -> createNewGroupMember db user gInfo m memInfo GCPostMember initialStatus
|
||||
memberAnnouncedToView newMember
|
||||
(newMember, gInfo') <- withStore $ \db -> do
|
||||
newMember <- createNewGroupMember db user gInfo m memInfo GCPostMember initialStatus
|
||||
gInfo' <- if memberPending newMember
|
||||
then liftIO $ increaseGroupMembersRequireAttention db user gInfo
|
||||
else pure gInfo
|
||||
pure (newMember, gInfo')
|
||||
memberAnnouncedToView newMember gInfo'
|
||||
where
|
||||
initialStatus = case msgScope_ of
|
||||
Just (MSMember _) -> GSMemPendingReview
|
||||
_ -> GSMemAnnounced
|
||||
memberAnnouncedToView announcedMember@GroupMember {groupMemberId, memberProfile} = do
|
||||
memberAnnouncedToView announcedMember@GroupMember {groupMemberId, memberProfile} gInfo' = do
|
||||
(announcedMember', scopeInfo) <- getMemNewChatScope announcedMember
|
||||
let event = RGEMemberAdded groupMemberId (fromLocalProfile memberProfile)
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo scopeInfo m) msg brokerTs (CIRcvGroupEvent event)
|
||||
groupMsgToView gInfo scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m) msg brokerTs (CIRcvGroupEvent event)
|
||||
groupMsgToView cInfo ci
|
||||
case scopeInfo of
|
||||
Just (GCSIMemberSupport _) -> do
|
||||
createInternalChatItem user (CDGroupRcv gInfo scopeInfo m) (CIRcvGroupEvent RGENewMemberPendingReview) (Just brokerTs)
|
||||
createInternalChatItem user (CDGroupRcv gInfo' scopeInfo m) (CIRcvGroupEvent RGENewMemberPendingReview) (Just brokerTs)
|
||||
_ -> pure ()
|
||||
toView $ CEvtJoinedGroupMemberConnecting user gInfo m announcedMember'
|
||||
toView $ CEvtJoinedGroupMemberConnecting user gInfo' m announcedMember'
|
||||
getMemNewChatScope announcedMember = case msgScope_ of
|
||||
Nothing -> pure (announcedMember, Nothing)
|
||||
Just (MSMember _) -> do
|
||||
@@ -2571,8 +2587,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
| otherwise = do
|
||||
withStore' $ \db -> updateGroupMemberRole db user member memRole
|
||||
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo' m
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo'' scopeInfo m') msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView gInfo'' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo'' scopeInfo m') msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView cInfo ci
|
||||
toView CEvtMemberRole {user, groupInfo = gInfo'', byMember = m', member = member {memberRole = memRole}, fromRole, toRole = memRole}
|
||||
|
||||
checkHostRole :: GroupMember -> GroupMemberRole -> CM ()
|
||||
@@ -2600,8 +2616,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
toggleNtf bm' (not blocked)
|
||||
let ciContent = CIRcvGroupEvent $ RGEMemberBlocked bmId (fromLocalProfile bmp) blocked
|
||||
(gInfo', m', scopeInfo) <- mkGroupChatScope gInfo m
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs ciContent
|
||||
groupMsgToView gInfo' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs ciContent
|
||||
groupMsgToView cInfo ci
|
||||
toView CEvtMemberBlockedForAll {user, groupInfo = gInfo', byMember = m', member = bm, blocked}
|
||||
Left (SEGroupMemberNotFoundByMemberId _) -> do
|
||||
bm <- createUnknownMember gInfo memId
|
||||
@@ -2685,8 +2701,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
| otherwise = a
|
||||
deleteMemberItem gEvent = do
|
||||
(gInfo', m', scopeInfo) <- mkGroupChatScope gInfo m
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView gInfo' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs (CIRcvGroupEvent gEvent)
|
||||
groupMsgToView cInfo ci
|
||||
deleteMessages :: MsgDirectionI d => GroupMember -> SMsgDirection d -> CM ()
|
||||
deleteMessages delMem msgDir
|
||||
| groupFeatureMemberAllowed SGFFullDelete m gInfo = deleteGroupMemberCIs user gInfo delMem m msgDir
|
||||
@@ -2698,8 +2714,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
-- 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 <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
|
||||
groupMsgToView gInfo' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
|
||||
groupMsgToView cInfo ci
|
||||
toView $ CEvtLeftMember user gInfo' m' {memberStatus = GSMemLeft}
|
||||
|
||||
xGrpDel :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> CM ()
|
||||
@@ -2712,8 +2728,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
-- member records are not deleted to keep history
|
||||
deleteMembersConnections user ms
|
||||
(gInfo'', m', scopeInfo) <- mkGroupChatScope gInfo m
|
||||
ci <- saveRcvChatItemNoParse user (CDGroupRcv gInfo'' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEGroupDeleted)
|
||||
groupMsgToView gInfo'' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user (CDGroupRcv gInfo'' scopeInfo m') msg brokerTs (CIRcvGroupEvent RGEGroupDeleted)
|
||||
groupMsgToView cInfo ci
|
||||
toView $ CEvtGroupDeleted user gInfo'' {membership = membership {memberStatus = GSMemGroupDeleted}} m'
|
||||
|
||||
xGrpInfo :: GroupInfo -> GroupMember -> GroupProfile -> RcvMessage -> UTCTime -> CM ()
|
||||
@@ -2726,8 +2742,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
toView $ CEvtGroupUpdated user g g'' (Just m')
|
||||
let cd = CDGroupRcv g'' scopeInfo m'
|
||||
unless (sameGroupProfileInfo p p') $ do
|
||||
ci <- saveRcvChatItemNoParse user cd msg brokerTs (CIRcvGroupEvent $ RGEGroupUpdated p')
|
||||
groupMsgToView g'' scopeInfo ci
|
||||
(ci, cInfo) <- saveRcvChatItemNoParse user cd msg brokerTs (CIRcvGroupEvent $ RGEGroupUpdated p')
|
||||
groupMsgToView cInfo ci
|
||||
createGroupFeatureChangedItems user cd CIRcvGroupFeature g g''
|
||||
Just _ -> updateGroupPrefs_ g m $ fromMaybe defaultBusinessGroupPrefs $ groupPreferences p'
|
||||
|
||||
@@ -2787,8 +2803,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
createInternalChatItem user (CDGroupRcv g' scopeInfo m'') (CIRcvGroupEvent RGEMemberCreatedContact) Nothing
|
||||
toView $ CEvtNewMemberContactReceivedInv user mCt' g' m''
|
||||
forM_ mContent_ $ \mc -> do
|
||||
ci <- saveRcvChatItem user (CDDirectRcv mCt') msg brokerTs (CIRcvMsgContent mc, msgContentTexts mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv (DirectChat mCt') ci]
|
||||
(ci, cInfo) <- saveRcvChatItem user (CDDirectRcv mCt') msg brokerTs (CIRcvMsgContent mc, msgContentTexts mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDRcv cInfo ci]
|
||||
|
||||
securityCodeChanged :: Contact -> CM ()
|
||||
securityCodeChanged ct = do
|
||||
|
||||
@@ -350,14 +350,13 @@ data ChatStats = ChatStats
|
||||
{ unreadCount :: Int, -- returned both in /_get chat initial API and in /_get chats API
|
||||
unreadMentions :: Int, -- returned both in /_get chat initial API and in /_get chats API
|
||||
reportsCount :: Int, -- returned both in /_get chat initial API and in /_get chats API
|
||||
supportChatsUnreadCount :: Int, -- returned both in /_get chat initial API and in /_get chats API
|
||||
minUnreadItemId :: ChatItemId,
|
||||
unreadChat :: Bool
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
emptyChatStats :: ChatStats
|
||||
emptyChatStats = ChatStats 0 0 0 0 0 False
|
||||
emptyChatStats = ChatStats 0 0 0 0 False
|
||||
|
||||
data NavigationInfo = NavigationInfo
|
||||
{ afterUnread :: Int,
|
||||
|
||||
@@ -137,7 +137,8 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -80,6 +80,8 @@ module Simplex.Chat.Store.Groups
|
||||
updateGroupMemberStatus,
|
||||
updateGroupMemberStatusById,
|
||||
updateGroupMemberAccepted,
|
||||
updateGroupMembersRequireAttention,
|
||||
increaseGroupMembersRequireAttention,
|
||||
createNewGroupMember,
|
||||
checkGroupMemberHasItems,
|
||||
deleteGroupMember,
|
||||
@@ -279,7 +281,8 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -362,7 +365,8 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc
|
||||
chatTags = [],
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
customData = Nothing
|
||||
customData = Nothing,
|
||||
membersRequireAttention = 0
|
||||
}
|
||||
|
||||
-- | creates a new group record for the group the current user was invited to, or returns an existing one
|
||||
@@ -432,7 +436,8 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
|
||||
chatTags = [],
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
customData = Nothing
|
||||
customData = Nothing,
|
||||
membersRequireAttention = 0
|
||||
},
|
||||
groupMemberId
|
||||
)
|
||||
@@ -768,7 +773,8 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
|
||||
mu.created_at, mu.updated_at,
|
||||
@@ -1224,6 +1230,37 @@ updateGroupMemberAccepted db User {userId} m@GroupMember {groupMemberId} status
|
||||
(status, role, currentTs, userId, groupMemberId)
|
||||
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'
|
||||
| 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}
|
||||
| otherwise = pure g
|
||||
where
|
||||
didRequire = gmRequiresAttention member
|
||||
nowRequires = gmRequiresAttention member'
|
||||
|
||||
increaseGroupMembersRequireAttention :: DB.Connection -> User -> GroupInfo -> IO GroupInfo
|
||||
increaseGroupMembersRequireAttention 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}
|
||||
|
||||
-- | add new member with profile
|
||||
createNewGroupMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> MemberInfo -> GroupMemberCategory -> GroupMemberStatus -> ExceptT StoreError IO GroupMember
|
||||
createNewGroupMember db user gInfo invitingMember memInfo@MemberInfo {profile} memCategory memStatus = do
|
||||
@@ -1561,7 +1598,8 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -369,56 +369,103 @@ type NewQuoteRow = (Maybe SharedMsgId, Maybe UTCTime, Maybe MsgContent, Maybe Bo
|
||||
data MemberAttention = MAInc Int | MAReset
|
||||
deriving (Show)
|
||||
|
||||
updateChatTsStats :: DB.Connection -> User -> ChatDirection c d -> UTCTime -> Maybe (Int, MemberAttention, Int) -> IO ()
|
||||
updateChatTsStats db User {userId} chatDirection chatTs chatStats_ = case toChatInfo chatDirection of
|
||||
DirectChat Contact {contactId} ->
|
||||
updateChatTsStats :: DB.Connection -> VersionRangeChat -> User -> ChatDirection c d -> UTCTime -> Maybe (Int, MemberAttention, Int) -> IO (ChatInfo c)
|
||||
updateChatTsStats db vr user@User {userId} chatDirection chatTs chatStats_ = case toChatInfo chatDirection of
|
||||
DirectChat ct@Contact {contactId} -> do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE contacts SET chat_ts = ?, chat_deleted = 0 WHERE user_id = ? AND contact_id = ?"
|
||||
(chatTs, userId, contactId)
|
||||
GroupChat GroupInfo {groupId, membership} scopeInfo -> do
|
||||
pure $ DirectChat ct {chatTs = Just chatTs}
|
||||
GroupChat g@GroupInfo {groupId} Nothing -> do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET chat_ts = ? WHERE user_id = ? AND group_id = ?"
|
||||
(chatTs, userId, groupId)
|
||||
forM_ scopeInfo $ \GCSIMemberSupport {groupMember_} -> do
|
||||
let gmId = groupMemberId' $ fromMaybe membership groupMember_
|
||||
case chatStats_ of
|
||||
Nothing ->
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE group_members SET support_chat_ts = ? WHERE group_member_id = ?"
|
||||
(chatTs, gmId)
|
||||
Just (unread, MAInc unanswered, mentions) ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention + ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(chatTs, unread, unanswered, mentions, gmId)
|
||||
Just (unread, MAReset, mentions) ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = 0,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(chatTs, unread, mentions, gmId)
|
||||
LocalChat NoteFolder {noteFolderId} ->
|
||||
pure $ GroupChat g {chatTs = Just chatTs} Nothing
|
||||
GroupChat g@GroupInfo {groupId, membership, membersRequireAttention} (Just GCSIMemberSupport {groupMember_}) ->
|
||||
case groupMember_ of
|
||||
Nothing -> do
|
||||
membership' <- updateGMStats membership
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET chat_ts = ? WHERE user_id = ? AND group_id = ?"
|
||||
(chatTs, userId, groupId)
|
||||
pure $ GroupChat g {membership = membership', chatTs = Just chatTs} (Just $ GCSIMemberSupport Nothing)
|
||||
Just member -> do
|
||||
member' <- updateGMStats member
|
||||
let didRequire = gmRequiresAttention member
|
||||
nowRequires = gmRequiresAttention member'
|
||||
if
|
||||
| nowRequires && not didRequire -> do
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE groups
|
||||
SET chat_ts = ?,
|
||||
members_require_attention = members_require_attention + 1
|
||||
WHERE user_id = ? AND group_id = ?
|
||||
|]
|
||||
(chatTs, userId, groupId)
|
||||
pure $ GroupChat g {membersRequireAttention = membersRequireAttention + 1, chatTs = Just chatTs} (Just $ GCSIMemberSupport (Just member'))
|
||||
| not nowRequires && didRequire -> do
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE groups
|
||||
SET chat_ts = ?,
|
||||
members_require_attention = members_require_attention - 1
|
||||
WHERE user_id = ? AND group_id = ?
|
||||
|]
|
||||
(chatTs, userId, groupId)
|
||||
pure $ GroupChat g {membersRequireAttention = membersRequireAttention - 1, chatTs = Just chatTs} (Just $ GCSIMemberSupport (Just member'))
|
||||
| otherwise -> do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET chat_ts = ? WHERE user_id = ? AND group_id = ?"
|
||||
(chatTs, userId, groupId)
|
||||
pure $ GroupChat g {chatTs = Just chatTs} (Just $ GCSIMemberSupport (Just member'))
|
||||
where
|
||||
updateGMStats m@GroupMember {groupMemberId} = do
|
||||
case chatStats_ of
|
||||
Nothing ->
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE group_members SET support_chat_ts = ? WHERE group_member_id = ?"
|
||||
(chatTs, groupMemberId)
|
||||
Just (unread, MAInc unanswered, mentions) ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention + ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(chatTs, unread, unanswered, mentions, groupMemberId)
|
||||
Just (unread, MAReset, mentions) ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = 0,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(chatTs, unread, mentions, groupMemberId)
|
||||
m_ <- runExceptT $ getGroupMemberById db vr user groupMemberId
|
||||
pure $ either (const m) id m_ -- Left shouldn't happen, but types require it
|
||||
LocalChat nf@NoteFolder {noteFolderId} -> do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE note_folders SET chat_ts = ? WHERE user_id = ? AND note_folder_id = ?"
|
||||
(chatTs, userId, noteFolderId)
|
||||
_ -> pure ()
|
||||
pure $ LocalChat nf {chatTs = chatTs}
|
||||
cInfo -> pure cInfo
|
||||
|
||||
setSupportChatTs :: DB.Connection -> GroupMemberId -> UTCTime -> IO ()
|
||||
setSupportChatTs db groupMemberId chatTs =
|
||||
@@ -636,13 +683,13 @@ type ChatStatsRow = (Int, ChatItemId, BoolInt)
|
||||
|
||||
toChatStats :: ChatStatsRow -> ChatStats
|
||||
toChatStats (unreadCount, minUnreadItemId, BI unreadChat) =
|
||||
ChatStats {unreadCount, unreadMentions = 0, reportsCount = 0, supportChatsUnreadCount = 0, minUnreadItemId, unreadChat}
|
||||
ChatStats {unreadCount, unreadMentions = 0, reportsCount = 0, minUnreadItemId, unreadChat}
|
||||
|
||||
type GroupStatsRow = (Int, Int, Int, Int, ChatItemId, BoolInt)
|
||||
type GroupStatsRow = (Int, Int, Int, ChatItemId, BoolInt)
|
||||
|
||||
toGroupStats :: GroupStatsRow -> ChatStats
|
||||
toGroupStats (unreadCount, unreadMentions, reportsCount, supportChatsUnreadCount, minUnreadItemId, BI unreadChat) =
|
||||
ChatStats {unreadCount, unreadMentions, reportsCount, supportChatsUnreadCount, minUnreadItemId, unreadChat}
|
||||
toGroupStats (unreadCount, unreadMentions, reportsCount, minUnreadItemId, BI unreadChat) =
|
||||
ChatStats {unreadCount, unreadMentions, reportsCount, minUnreadItemId, unreadChat}
|
||||
|
||||
findDirectChatPreviews_ :: DB.Connection -> User -> PaginationByTime -> ChatListQuery -> IO [AChatPreviewData]
|
||||
findDirectChatPreviews_ db User {userId} pagination clq =
|
||||
@@ -763,7 +810,6 @@ findGroupChatPreviews_ db User {userId} pagination clq =
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -780,16 +826,8 @@ findGroupChatPreviews_ db User {userId} pagination clq =
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|]
|
||||
baseParams = (userId, userId, CISRcvNew, userId, MCReport_, BI False, userId, CISRcvNew)
|
||||
baseParams = (userId, userId, CISRcvNew, userId, MCReport_, BI False)
|
||||
getPreviews = case clq of
|
||||
CLQFilters {favorite = False, unread = False} -> do
|
||||
let q = baseQuery <> " WHERE g.user_id = ?"
|
||||
@@ -1494,16 +1532,14 @@ getGroupChatInitial_ db user g scopeInfo_ contentFilter count = do
|
||||
where
|
||||
getStats minUnreadItemId (unreadCount, unreadMentions) = do
|
||||
reportsCount <- getGroupReportsCount_ db user g False
|
||||
supportChatsUnreadCount <- getGroupSupportChatsUnreadCount_ db user g
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, supportChatsUnreadCount, minUnreadItemId, unreadChat = False}
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
|
||||
getGroupStats_ :: DB.Connection -> User -> GroupInfo -> Maybe GroupChatScopeInfo -> ExceptT StoreError IO ChatStats
|
||||
getGroupStats_ db user g scopeInfo_ = do
|
||||
minUnreadItemId <- fromMaybe 0 <$> getGroupMinUnreadId_ db user g scopeInfo_ Nothing
|
||||
(unreadCount, unreadMentions) <- getGroupUnreadCount_ db user g scopeInfo_ Nothing
|
||||
reportsCount <- liftIO $ getGroupReportsCount_ db user g False
|
||||
supportChatsUnreadCount <- liftIO $ getGroupSupportChatsUnreadCount_ db user g
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, supportChatsUnreadCount, minUnreadItemId, unreadChat = False}
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
|
||||
getGroupMinUnreadId_ :: DB.Connection -> User -> GroupInfo -> Maybe GroupChatScopeInfo -> Maybe MsgContentTag -> ExceptT StoreError IO (Maybe ChatItemId)
|
||||
getGroupMinUnreadId_ db user g scopeInfo_ contentFilter =
|
||||
@@ -1527,14 +1563,6 @@ getGroupReportsCount_ db User {userId} GroupInfo {groupId} archived =
|
||||
"SELECT COUNT(1) FROM chat_items WHERE user_id = ? AND group_id = ? AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0"
|
||||
(userId, groupId, MCReport_, BI archived)
|
||||
|
||||
getGroupSupportChatsUnreadCount_ :: DB.Connection -> User -> GroupInfo -> IO Int
|
||||
getGroupSupportChatsUnreadCount_ db User {userId} GroupInfo {groupId} =
|
||||
fromOnly . head
|
||||
<$> DB.query
|
||||
db
|
||||
"SELECT COUNT(1) FROM chat_items WHERE user_id = ? AND group_id = ? AND group_scope_tag IS NOT NULL AND item_status = ?"
|
||||
(userId, groupId, CISRcvNew)
|
||||
|
||||
queryUnreadGroupItems :: FromRow r => DB.Connection -> User -> GroupInfo -> Maybe GroupChatScopeInfo -> Maybe MsgContentTag -> Query -> Query -> ExceptT StoreError IO [r]
|
||||
queryUnreadGroupItems db User {userId} GroupInfo {groupId} scopeInfo_ contentFilter baseQuery orderLimit =
|
||||
case (scopeInfo_, contentFilter) of
|
||||
@@ -1954,14 +1982,14 @@ getGroupUnreadTimedItems db User {userId} groupId =
|
||||
|]
|
||||
(userId, groupId, CISRcvNew)
|
||||
|
||||
updateGroupChatItemsReadList :: DB.Connection -> User -> GroupInfo -> Maybe GroupChatScope -> NonEmpty ChatItemId -> IO [(ChatItemId, Int)]
|
||||
updateGroupChatItemsReadList db User {userId} GroupInfo {groupId, membership} scope itemIds = do
|
||||
currentTs <- getCurrentTime
|
||||
updateGroupChatItemsReadList :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> Maybe GroupChatScope -> NonEmpty ChatItemId -> ExceptT StoreError IO ([(ChatItemId, Int)], GroupInfo)
|
||||
updateGroupChatItemsReadList db vr user@User {userId} g@GroupInfo {groupId, membership, membersRequireAttention} scope itemIds = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
-- Possible improvement is to differentiate retrieval queries for each scope,
|
||||
-- but we rely on UI to not pass item IDs from incorrect scope.
|
||||
readItemsData <- catMaybes . L.toList <$> mapM (getUpdateGroupItem currentTs) itemIds
|
||||
updateChatStats readItemsData
|
||||
pure $ timedItems readItemsData
|
||||
readItemsData <- liftIO $ catMaybes . L.toList <$> mapM (getUpdateGroupItem currentTs) itemIds
|
||||
g' <- updateChatStats readItemsData
|
||||
pure (timedItems readItemsData, g')
|
||||
where
|
||||
getUpdateGroupItem :: UTCTime -> ChatItemId -> IO (Maybe (ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt))
|
||||
getUpdateGroupItem currentTs itemId =
|
||||
@@ -1974,36 +2002,61 @@ updateGroupChatItemsReadList db User {userId} GroupInfo {groupId, membership} sc
|
||||
RETURNING chat_item_id, timed_ttl, timed_delete_at, group_member_id, user_mention
|
||||
|]
|
||||
(CISRcvRead, currentTs, userId, groupId, CISRcvNew, itemId)
|
||||
updateChatStats :: [(ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt)] -> IO ()
|
||||
updateChatStats :: [(ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt)] -> ExceptT StoreError IO GroupInfo
|
||||
updateChatStats readItemsData = case scope of
|
||||
Nothing -> pure ()
|
||||
Just GCSMemberSupport {groupMemberId_} -> do
|
||||
let unread = length readItemsData
|
||||
(unanswered, mentions) = decStats
|
||||
gmId = fromMaybe (groupMemberId' membership) groupMemberId_
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_items_unread = support_chat_items_unread - ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention - ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions - ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(unread, unanswered, mentions, gmId)
|
||||
Nothing -> pure g
|
||||
Just GCSMemberSupport {groupMemberId_} -> case groupMemberId_ of
|
||||
Nothing -> do
|
||||
membership' <- updateGMStats membership
|
||||
pure g {membership = membership'}
|
||||
Just groupMemberId -> do
|
||||
member <- getGroupMemberById db vr user groupMemberId
|
||||
member' <- updateGMStats member
|
||||
let didRequire = gmRequiresAttention member
|
||||
nowRequires = gmRequiresAttention member'
|
||||
if (not nowRequires && didRequire)
|
||||
then do
|
||||
liftIO $
|
||||
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}
|
||||
else
|
||||
pure g
|
||||
where
|
||||
decStats :: (Int, Int)
|
||||
decStats = foldl' countItem (0, 0) readItemsData
|
||||
updateGMStats GroupMember {groupMemberId} = do
|
||||
let unread = length readItemsData
|
||||
(unanswered, mentions) = decStats
|
||||
liftIO $
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET support_chat_items_unread = support_chat_items_unread - ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention - ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions - ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(unread, unanswered, mentions, groupMemberId)
|
||||
getGroupMemberById db vr user groupMemberId
|
||||
where
|
||||
countItem :: (Int, Int) -> (ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt) -> (Int, Int)
|
||||
countItem (!unanswered, !mentions) (_, _, _, itemGMId_, userMention_) =
|
||||
let unanswered' = case (groupMemberId_, itemGMId_) of
|
||||
(Just scopeGMId, Just itemGMId) | itemGMId == scopeGMId -> unanswered + 1
|
||||
_ -> unanswered
|
||||
mentions' = case userMention_ of
|
||||
Just (BI True) -> mentions + 1
|
||||
_ -> mentions
|
||||
in (unanswered', mentions')
|
||||
decStats :: (Int, Int)
|
||||
decStats = foldl' countItem (0, 0) readItemsData
|
||||
where
|
||||
countItem :: (Int, Int) -> (ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt) -> (Int, Int)
|
||||
countItem (!unanswered, !mentions) (_, _, _, itemGMId_, userMention_) =
|
||||
let unanswered' = case (groupMemberId_, itemGMId_) of
|
||||
(Just scopeGMId, Just itemGMId) | itemGMId == scopeGMId -> unanswered + 1
|
||||
_ -> unanswered
|
||||
mentions' = case userMention_ of
|
||||
Just (BI True) -> mentions + 1
|
||||
_ -> mentions
|
||||
in (unanswered', mentions')
|
||||
timedItems :: [(ChatItemId, Maybe Int, Maybe UTCTime, Maybe GroupMemberId, Maybe BoolInt)] -> [(ChatItemId, Int)]
|
||||
timedItems = foldl' addTimedItem []
|
||||
where
|
||||
|
||||
@@ -17,6 +17,8 @@ ALTER TABLE group_members ADD COLUMN support_chat_items_unread BIGINT NOT NULL D
|
||||
ALTER TABLE group_members ADD COLUMN support_chat_items_member_attention BIGINT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE group_members ADD COLUMN support_chat_items_mentions BIGINT NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE groups ADD COLUMN members_require_attention BIGINT NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE chat_items ADD COLUMN group_scope_tag TEXT;
|
||||
ALTER TABLE chat_items ADD COLUMN group_scope_group_member_id BIGINT REFERENCES group_members(group_member_id) ON DELETE CASCADE;
|
||||
|
||||
@@ -53,6 +55,8 @@ DROP INDEX idx_chat_items_group_scope_group_member_id;
|
||||
ALTER TABLE chat_items DROP COLUMN group_scope_tag;
|
||||
ALTER TABLE chat_items DROP COLUMN group_scope_group_member_id;
|
||||
|
||||
ALTER TABLE groups DROP COLUMN members_require_attention;
|
||||
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_ts;
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_items_unread;
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_items_member_attention;
|
||||
|
||||
@@ -15,6 +15,8 @@ ALTER TABLE group_members ADD COLUMN support_chat_items_unread INTEGER NOT NULL
|
||||
ALTER TABLE group_members ADD COLUMN support_chat_items_member_attention INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE group_members ADD COLUMN support_chat_items_mentions INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE groups ADD COLUMN members_require_attention INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE chat_items ADD COLUMN group_scope_tag TEXT;
|
||||
ALTER TABLE chat_items ADD COLUMN group_scope_group_member_id INTEGER REFERENCES group_members(group_member_id) ON DELETE CASCADE;
|
||||
|
||||
@@ -50,6 +52,8 @@ DROP INDEX idx_chat_items_group_scope_group_member_id;
|
||||
ALTER TABLE chat_items DROP COLUMN group_scope_tag;
|
||||
ALTER TABLE chat_items DROP COLUMN group_scope_group_member_id;
|
||||
|
||||
ALTER TABLE groups DROP COLUMN members_require_attention;
|
||||
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_ts;
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_items_unread;
|
||||
ALTER TABLE group_members DROP COLUMN support_chat_items_member_attention;
|
||||
|
||||
@@ -1,3 +1,39 @@
|
||||
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 group_members
|
||||
SET support_chat_items_unread = support_chat_items_unread - ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention - ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions - ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE groups
|
||||
SET chat_ts = ?,
|
||||
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 chat_ts = ?,
|
||||
members_require_attention = members_require_attention - 1
|
||||
WHERE user_id = ? AND group_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
INSERT INTO group_members
|
||||
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
|
||||
@@ -36,7 +72,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -81,6 +118,28 @@ Query:
|
||||
Plan:
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = 0,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention + ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
INSERT INTO contact_requests
|
||||
(user_contact_link_id, agent_invitation_id, peer_chat_min_version, peer_chat_max_version, contact_profile_id, local_display_name, user_id,
|
||||
@@ -621,38 +680,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH chat_items USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_items_unread = support_chat_items_unread - ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention - ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions - ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = 0,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_ts = ?,
|
||||
support_chat_items_unread = support_chat_items_unread + ?,
|
||||
support_chat_items_member_attention = support_chat_items_member_attention + ?,
|
||||
support_chat_items_mentions = support_chat_items_mentions + ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM chat_item_reactions
|
||||
WHERE contact_id = ? AND shared_msg_id = ? AND reaction_sent = ? AND reaction = ?
|
||||
@@ -840,7 +867,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -887,7 +915,8 @@ Query:
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
|
||||
mu.created_at, mu.updated_at,
|
||||
@@ -1270,16 +1299,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET support_chat_items_unread = 0,
|
||||
support_chat_items_member_attention = 0,
|
||||
support_chat_items_mentions = 0
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_profiles
|
||||
SET display_name = ?, full_name = ?, description = ?, image = ?, preferences = ?, member_admission = ?, updated_at = ?
|
||||
@@ -1294,6 +1313,14 @@ 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 = ?
|
||||
@@ -1948,7 +1975,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -1965,14 +1991,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
WHERE g.user_id = ?
|
||||
@@ -1988,13 +2006,10 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
SEARCH gp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2012,7 +2027,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2029,14 +2043,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND (g.favorite = 1
|
||||
@@ -2047,12 +2053,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2070,7 +2073,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2087,14 +2089,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND (g.unread_chat = 1 OR ChatStats.UnreadCount > 0)
|
||||
@@ -2104,12 +2098,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2127,7 +2118,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2144,14 +2134,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND (g.unread_chat = 1 OR ChatStats.UnreadCount > 0)
|
||||
@@ -2161,12 +2143,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2184,7 +2163,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2201,14 +2179,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND (g.unread_chat = 1 OR ChatStats.UnreadCount > 0)
|
||||
@@ -2218,12 +2188,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2241,7 +2208,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2258,14 +2224,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND g.favorite = 1
|
||||
@@ -2275,12 +2233,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2298,7 +2253,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2315,14 +2269,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND g.favorite = 1
|
||||
@@ -2332,12 +2278,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2355,7 +2298,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2372,14 +2314,6 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
|
||||
WHERE g.user_id = ?
|
||||
AND g.favorite = 1
|
||||
@@ -2389,12 +2323,9 @@ MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2412,7 +2343,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2429,26 +2359,15 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
WHERE g.user_id = ? AND g.chat_ts < ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2466,7 +2385,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2483,26 +2401,15 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
WHERE g.user_id = ? AND g.chat_ts > ? ORDER BY g.chat_ts ASC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -2520,7 +2427,6 @@ Query:
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(SupportChatsUnreadCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
@@ -2537,26 +2443,15 @@ Query:
|
||||
AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
GROUP BY group_id
|
||||
) ReportCount ON ReportCount.group_id = g.group_id
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS Count
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL
|
||||
AND group_scope_tag IS NOT NULL
|
||||
AND item_status = ?
|
||||
GROUP BY group_id
|
||||
) SupportChatsUnreadCount ON SupportChatsUnreadCount.group_id = g.group_id
|
||||
WHERE g.user_id = ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id>?)
|
||||
MATERIALIZE ReportCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id>?)
|
||||
MATERIALIZE SupportChatsUnreadCount
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
SEARCH ChatStats USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH ReportCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
SEARCH SupportChatsUnreadCount USING AUTOMATIC COVERING INDEX (group_id=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH ci USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
|
||||
@@ -4526,6 +4421,14 @@ Query:
|
||||
Plan:
|
||||
SEARCH group_snd_item_statuses USING INDEX idx_group_snd_item_statuses_chat_item_id_group_member_id (chat_item_id=? AND group_member_id=?)
|
||||
|
||||
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 = ?)
|
||||
@@ -4625,7 +4528,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -4648,7 +4552,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -5638,10 +5543,6 @@ Query: SELECT COUNT(1) FROM chat_item_versions WHERE chat_item_id = ?
|
||||
Plan:
|
||||
SEARCH chat_item_versions USING COVERING INDEX idx_chat_item_versions_chat_item_id (chat_item_id=?)
|
||||
|
||||
Query: SELECT COUNT(1) FROM chat_items WHERE user_id = ? AND group_id = ? AND group_scope_tag IS NOT NULL AND item_status = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_scope_item_status (user_id=? AND group_id=? AND group_scope_tag>?)
|
||||
|
||||
Query: SELECT COUNT(1) FROM chat_items WHERE user_id = ? AND group_id = ? AND msg_content_tag = ? AND item_deleted = ? AND item_sent = 0
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_msg_content_tag_deleted (user_id=? AND group_id=? AND msg_content_tag=? AND item_deleted=? AND item_sent=?)
|
||||
|
||||
@@ -134,7 +134,8 @@ CREATE TABLE groups(
|
||||
business_xcontact_id BLOB NULL,
|
||||
customer_member_id BLOB NULL,
|
||||
chat_item_ttl INTEGER,
|
||||
local_alias TEXT DEFAULT '', -- received
|
||||
local_alias TEXT DEFAULT '',
|
||||
members_require_attention INTEGER NOT NULL DEFAULT 0, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
|
||||
@@ -579,18 +579,18 @@ safeDeleteLDN db User {userId} localDisplayName = do
|
||||
|
||||
type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe MemberId)
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64, Int) :. GroupMemberRow
|
||||
|
||||
type GroupMemberRow = (Int64, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnLinkContact, LocalAlias, Maybe Preferences) :. (UTCTime, UTCTime) :. (Maybe UTCTime, Int64, Int64, Int64)
|
||||
|
||||
toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData, chatItemTTL) :. userMemberRow) =
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData, chatItemTTL, membersRequireAttention) :. userMemberRow) =
|
||||
let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
groupProfile = GroupProfile {displayName, fullName, description, image, groupPreferences, memberAdmission}
|
||||
businessChat = toBusinessChatInfo businessRow
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, chatTags, chatItemTTL, uiThemes, customData}
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, chatTags, chatItemTTL, uiThemes, customData, membersRequireAttention}
|
||||
|
||||
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
|
||||
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, BI showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences) :. (createdAt, updatedAt) :. (supportChatTs_, supportChatUnread, supportChatMemberAttention, supportChatMentions)) =
|
||||
@@ -622,7 +622,8 @@ groupInfoQuery =
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -421,7 +421,8 @@ data GroupInfo = GroupInfo
|
||||
chatTags :: [ChatTagId],
|
||||
chatItemTTL :: Maybe Int64,
|
||||
uiThemes :: Maybe UIThemeEntityOverrides,
|
||||
customData :: Maybe CustomData
|
||||
customData :: Maybe CustomData,
|
||||
membersRequireAttention :: Int
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -854,6 +855,13 @@ data GroupSupportChat = GroupSupportChat
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
gmRequiresAttention :: GroupMember -> Bool
|
||||
gmRequiresAttention m@GroupMember {supportChat} =
|
||||
memberPending m || maybe False supportChatAttention supportChat
|
||||
where
|
||||
supportChatAttention GroupSupportChat {memberAttention, mentions} =
|
||||
memberAttention > 0 || mentions > 0
|
||||
|
||||
data GroupMemberRef = GroupMemberRef {groupMemberId :: Int64, profile :: Profile}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
||||
@@ -192,6 +192,7 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, testView} liveIte
|
||||
CRSentConfirmation u _ -> ttyUser u ["confirmation sent!"]
|
||||
CRSentInvitation u _ customUserProfile -> ttyUser u $ viewSentInvitation customUserProfile testView
|
||||
CRSentInvitationToContact u _c customUserProfile -> ttyUser u $ viewSentInvitation customUserProfile testView
|
||||
CRItemsReadForChat u chatId -> ttyUser u ["items read for chat"]
|
||||
CRContactDeleted u c -> ttyUser u [ttyContact' c <> ": contact is deleted"]
|
||||
CRChatCleared u chatInfo -> ttyUser u $ viewChatCleared chatInfo
|
||||
CRAcceptingContactRequest u c -> ttyUser u $ viewAcceptingContactRequest c
|
||||
|
||||
Reference in new issue
Block a user