mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 12:19:54 +00:00
core: mentions in history, unread mentions in stats (#5594)
* core: mentions in history, unread mentions in stats * fix * update plans
This commit is contained in:
parent
4ed67f094f
commit
3bc822a1e9
7 changed files with 131 additions and 62 deletions
|
@ -894,16 +894,16 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
in Just (fInv, fileDescrText)
|
||||
| otherwise = Nothing
|
||||
processContentItem :: GroupMember -> ChatItem 'CTGroup d -> MsgContent -> Maybe (FileInvitation, RcvFileDescrText) -> CM [ChatMsgEvent 'Json]
|
||||
processContentItem sender ChatItem {meta, quotedItem} mc fInvDescr_ =
|
||||
processContentItem sender ChatItem {formattedText, meta, quotedItem, mentions} mc fInvDescr_ =
|
||||
if isNothing fInvDescr_ && not (msgContentHasText mc)
|
||||
then pure []
|
||||
else do
|
||||
let CIMeta {itemTs, itemSharedMsgId, itemTimed} = meta
|
||||
quotedItemId_ = quoteItemId =<< quotedItem
|
||||
fInv_ = fst <$> fInvDescr_
|
||||
-- TODO [mentions] history?
|
||||
-- let (_t, ft_) = msgContentTexts mc
|
||||
(chatMsgEvent, _) <- withStore $ \db -> prepareGroupMsg db user gInfo mc M.empty quotedItemId_ Nothing fInv_ itemTimed False
|
||||
(mc', _, mentions') = updatedMentionNames mc formattedText mentions
|
||||
mentions'' = M.map (\CIMention {memberId} -> MsgMention {memberId}) mentions'
|
||||
(chatMsgEvent, _) <- withStore $ \db -> prepareGroupMsg db user gInfo mc' mentions'' quotedItemId_ Nothing fInv_ itemTimed False
|
||||
let senderVRange = memberChatVRange' sender
|
||||
xMsgNewChatMsg = ChatMessage {chatVRange = senderVRange, msgId = itemSharedMsgId, chatMsgEvent}
|
||||
fileDescrEvents <- case (snd <$> fInvDescr_, itemSharedMsgId) of
|
||||
|
|
|
@ -320,6 +320,7 @@ deriving instance Show AChat
|
|||
|
||||
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
|
||||
minUnreadItemId :: ChatItemId,
|
||||
unreadChat :: Bool
|
||||
|
@ -327,7 +328,7 @@ data ChatStats = ChatStats
|
|||
deriving (Show)
|
||||
|
||||
emptyChatStats :: ChatStats
|
||||
emptyChatStats = ChatStats 0 0 0 False
|
||||
emptyChatStats = ChatStats 0 0 0 0 False
|
||||
|
||||
data NavigationInfo = NavigationInfo
|
||||
{ afterUnread :: Int,
|
||||
|
|
|
@ -570,7 +570,12 @@ data AChatPreviewData = forall c. ChatTypeI c => ACPD (SChatType c) (ChatPreview
|
|||
type ChatStatsRow = (Int, Int, ChatItemId, BoolInt)
|
||||
|
||||
toChatStats :: ChatStatsRow -> ChatStats
|
||||
toChatStats (unreadCount, reportsCount, minUnreadItemId, BI unreadChat) = ChatStats {unreadCount, reportsCount, minUnreadItemId, unreadChat}
|
||||
toChatStats (unreadCount, reportsCount, minUnreadItemId, BI unreadChat) = ChatStats {unreadCount, unreadMentions = 0, reportsCount, minUnreadItemId, unreadChat}
|
||||
|
||||
type GroupStatsRow = (Int, Int, Int, ChatItemId, BoolInt)
|
||||
|
||||
toGroupStats :: GroupStatsRow -> ChatStats
|
||||
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 =
|
||||
|
@ -674,9 +679,9 @@ findGroupChatPreviews_ :: DB.Connection -> User -> PaginationByTime -> ChatListQ
|
|||
findGroupChatPreviews_ db User {userId} pagination clq =
|
||||
map toPreview <$> getPreviews
|
||||
where
|
||||
toPreview :: (GroupId, UTCTime, Maybe ChatItemId) :. ChatStatsRow -> AChatPreviewData
|
||||
toPreview :: (GroupId, UTCTime, Maybe ChatItemId) :. GroupStatsRow -> AChatPreviewData
|
||||
toPreview ((groupId, ts, lastItemId_) :. statsRow) =
|
||||
ACPD SCTGroup $ GroupChatPD ts groupId lastItemId_ (toChatStats statsRow)
|
||||
ACPD SCTGroup $ GroupChatPD ts groupId lastItemId_ (toGroupStats statsRow)
|
||||
baseQuery =
|
||||
[sql|
|
||||
SELECT
|
||||
|
@ -690,12 +695,13 @@ findGroupChatPreviews_ db User {userId} pagination clq =
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -761,7 +767,7 @@ findGroupChatPreviews_ db User {userId} pagination clq =
|
|||
|]
|
||||
p = baseParams :. (userId, search, search, search, search)
|
||||
queryWithPagination q p
|
||||
queryWithPagination :: ToRow p => Query -> p -> IO [(GroupId, UTCTime, Maybe ChatItemId) :. ChatStatsRow]
|
||||
queryWithPagination :: ToRow p => Query -> p -> IO [(GroupId, UTCTime, Maybe ChatItemId) :. GroupStatsRow]
|
||||
queryWithPagination query params = case pagination of
|
||||
PTLast count -> DB.query db (query <> " ORDER BY g.chat_ts DESC LIMIT ?") (params :. Only count)
|
||||
PTAfter ts count -> DB.query db (query <> " AND g.chat_ts > ? ORDER BY g.chat_ts ASC LIMIT ?") (params :. (ts, count))
|
||||
|
@ -1353,19 +1359,19 @@ getGroupChatInitial_ db user g contentFilter count = do
|
|||
stats <- liftIO $ getStats minUnreadItemId =<< getGroupUnreadCount_ db user g Nothing
|
||||
getGroupChatAround' db user g contentFilter minUnreadItemId count "" stats
|
||||
Nothing -> liftIO $ do
|
||||
stats <- getStats 0 0
|
||||
stats <- getStats 0 (0, 0)
|
||||
(,Just $ NavigationInfo 0 0) <$> getGroupChatLast_ db user g contentFilter count "" stats
|
||||
where
|
||||
getStats minUnreadItemId unreadCount = do
|
||||
getStats minUnreadItemId (unreadCount, unreadMentions) = do
|
||||
reportsCount <- getGroupReportsCount_ db user g False
|
||||
pure ChatStats {unreadCount, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
|
||||
getGroupStats_ :: DB.Connection -> User -> GroupInfo -> IO ChatStats
|
||||
getGroupStats_ db user g = do
|
||||
minUnreadItemId <- fromMaybe 0 <$> getGroupMinUnreadId_ db user g Nothing
|
||||
unreadCount <- getGroupUnreadCount_ db user g Nothing
|
||||
(unreadCount, unreadMentions) <- getGroupUnreadCount_ db user g Nothing
|
||||
reportsCount <- getGroupReportsCount_ db user g False
|
||||
pure ChatStats {unreadCount, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
pure ChatStats {unreadCount, unreadMentions, reportsCount, minUnreadItemId, unreadChat = False}
|
||||
|
||||
getGroupMinUnreadId_ :: DB.Connection -> User -> GroupInfo -> Maybe MsgContentTag -> IO (Maybe ChatItemId)
|
||||
getGroupMinUnreadId_ db user g contentFilter =
|
||||
|
@ -1375,11 +1381,11 @@ getGroupMinUnreadId_ db user g contentFilter =
|
|||
baseQuery = "SELECT chat_item_id FROM chat_items WHERE user_id = ? AND group_id = ? "
|
||||
orderLimit = " ORDER BY item_ts ASC, chat_item_id ASC LIMIT 1"
|
||||
|
||||
getGroupUnreadCount_ :: DB.Connection -> User -> GroupInfo -> Maybe MsgContentTag -> IO Int
|
||||
getGroupUnreadCount_ :: DB.Connection -> User -> GroupInfo -> Maybe MsgContentTag -> IO (Int, Int)
|
||||
getGroupUnreadCount_ db user g contentFilter =
|
||||
fromOnly . head <$> queryUnreadGroupItems db user g contentFilter baseQuery ""
|
||||
head <$> queryUnreadGroupItems db user g contentFilter baseQuery ""
|
||||
where
|
||||
baseQuery = "SELECT COUNT(1) FROM chat_items WHERE user_id = ? AND group_id = ? "
|
||||
baseQuery = "SELECT COUNT(1), COALESCE(SUM(user_mention), 0) FROM chat_items WHERE user_id = ? AND group_id = ? "
|
||||
|
||||
getGroupReportsCount_ :: DB.Connection -> User -> GroupInfo -> Bool -> IO Int
|
||||
getGroupReportsCount_ db User {userId} GroupInfo {groupId} archived =
|
||||
|
@ -3111,10 +3117,9 @@ getGroupSndStatusCounts db itemId =
|
|||
(Only itemId)
|
||||
|
||||
getGroupHistoryItems :: DB.Connection -> User -> GroupInfo -> GroupMember -> Int -> IO [Either StoreError (CChatItem 'CTGroup)]
|
||||
getGroupHistoryItems db user@User {userId} GroupInfo {groupId} m count = do
|
||||
getGroupHistoryItems db user@User {userId} g@GroupInfo {groupId} m count = do
|
||||
ciIds <- getLastItemIds_
|
||||
-- use getGroupCIWithReactions to read reactions data
|
||||
reverse <$> mapM (runExceptT . getGroupChatItem db user groupId) ciIds
|
||||
reverse <$> mapM (runExceptT . getGroupCIWithReactions db user g) ciIds
|
||||
where
|
||||
getLastItemIds_ :: IO [ChatItemId]
|
||||
getLastItemIds_ =
|
||||
|
|
|
@ -22,11 +22,15 @@ CREATE INDEX idx_chat_item_mentions_group_id ON chat_item_mentions(group_id);
|
|||
CREATE INDEX idx_chat_item_mentions_chat_item_id ON chat_item_mentions(chat_item_id);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_display_name ON chat_item_mentions(chat_item_id, display_name);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_member_id ON chat_item_mentions(chat_item_id, member_id);
|
||||
|
||||
CREATE INDEX idx_chat_items_groups_user_mention ON chat_items(user_id, group_id, item_status, user_mention);
|
||||
|]
|
||||
|
||||
down_m20250126_mentions :: Query
|
||||
down_m20250126_mentions =
|
||||
[sql|
|
||||
DROP INDEX idx_chat_items_groups_user_mention;
|
||||
|
||||
DROP INDEX idx_chat_item_mentions_group_id;
|
||||
DROP INDEX idx_chat_item_mentions_chat_item_id;
|
||||
DROP INDEX idx_chat_item_mentions_display_name;
|
||||
|
|
|
@ -157,7 +157,7 @@ Query:
|
|||
WHERE i.user_id = ? AND i.item_status = ? AND (g.enable_ntfs = 1 OR g.enable_ntfs IS NULL)
|
||||
|
||||
Plan:
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups (user_id=?)
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
|
@ -480,7 +480,7 @@ Query:
|
|||
LIMIT ?
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_history (user_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
|
@ -491,7 +491,7 @@ Query:
|
|||
LIMIT ?
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_history (user_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
|
@ -985,7 +985,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
|
@ -1005,7 +1005,7 @@ Query:
|
|||
LIMIT ?
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_history (user_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
|
@ -1151,7 +1151,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH i USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
SEARCH i USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INTEGER PRIMARY KEY (rowid=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
@ -1920,12 +1920,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -1949,7 +1950,7 @@ Query:
|
|||
ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
@ -1971,12 +1972,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -1995,7 +1997,7 @@ Query:
|
|||
ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
@ -2016,12 +2018,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2039,7 +2042,7 @@ Query:
|
|||
AND g.chat_ts < ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
|
@ -2060,12 +2063,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2083,7 +2087,7 @@ Query:
|
|||
AND g.chat_ts > ? ORDER BY g.chat_ts ASC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
|
@ -2104,12 +2108,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2127,7 +2132,7 @@ Query:
|
|||
ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
@ -2148,12 +2153,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2171,7 +2177,7 @@ Query:
|
|||
AND g.chat_ts < ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
|
@ -2192,12 +2198,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2215,7 +2222,7 @@ Query:
|
|||
AND g.chat_ts > ? ORDER BY g.chat_ts ASC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
|
@ -2236,12 +2243,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2259,7 +2267,7 @@ Query:
|
|||
ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
@ -2280,12 +2288,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2300,7 +2309,7 @@ Query:
|
|||
WHERE g.user_id = ? AND g.chat_ts < ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts<?)
|
||||
|
@ -2321,12 +2330,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2341,7 +2351,7 @@ Query:
|
|||
WHERE g.user_id = ? AND g.chat_ts > ? ORDER BY g.chat_ts ASC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=? AND chat_ts>?)
|
||||
|
@ -2362,12 +2372,13 @@ Query:
|
|||
LIMIT 1
|
||||
) AS chat_item_id,
|
||||
COALESCE(ChatStats.UnreadCount, 0),
|
||||
COALESCE(ChatStats.UnreadMentions, 0),
|
||||
COALESCE(ReportCount.Count, 0),
|
||||
COALESCE(ChatStats.MinUnread, 0),
|
||||
g.unread_chat
|
||||
FROM groups g
|
||||
LEFT JOIN (
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, MIN(chat_item_id) AS MinUnread
|
||||
SELECT group_id, COUNT(1) AS UnreadCount, SUM(user_mention) as UnreadMentions, MIN(chat_item_id) AS MinUnread
|
||||
FROM chat_items
|
||||
WHERE user_id = ? AND group_id IS NOT NULL AND item_status = ?
|
||||
GROUP BY group_id
|
||||
|
@ -2382,7 +2393,7 @@ Query:
|
|||
WHERE g.user_id = ? ORDER BY g.chat_ts DESC LIMIT ?
|
||||
Plan:
|
||||
MATERIALIZE ChatStats
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id>?)
|
||||
SEARCH chat_items USING COVERING 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>?)
|
||||
SEARCH g USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
@ -2930,7 +2941,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
|
@ -4080,7 +4091,7 @@ Query:
|
|||
WHERE user_id = ? AND group_id = ? AND item_status = ? AND timed_ttl IS NOT NULL AND timed_delete_at IS NULL
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups (user_id=? AND group_id=? AND item_status=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=? AND item_status=?)
|
||||
|
||||
Query:
|
||||
SELECT group_snd_item_status, COUNT(1)
|
||||
|
@ -4171,7 +4182,7 @@ Query:
|
|||
WHERE user_id = ? AND group_id = ? AND item_status = ?
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups (user_id=? AND group_id=? AND item_status=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=? AND item_status=?)
|
||||
|
||||
Query:
|
||||
UPDATE chat_items SET item_status = ?, updated_at = ?
|
||||
|
@ -4666,7 +4677,7 @@ Query:
|
|||
JOIN files f ON f.chat_item_id = i.chat_item_id
|
||||
WHERE i.user_id = ?
|
||||
Plan:
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups_history (user_id=?)
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -4693,7 +4704,7 @@ Query:
|
|||
JOIN files f ON f.chat_item_id = i.chat_item_id
|
||||
WHERE i.user_id = ? AND i.group_id = ?
|
||||
Plan:
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
SEARCH i USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -5013,7 +5024,7 @@ SEARCH groups USING COVERING INDEX idx_groups_chat_item_id (chat_item_id=?)
|
|||
|
||||
Query: DELETE FROM chat_items WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_item_ts (user_id=? AND group_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
SEARCH chat_item_mentions USING COVERING INDEX idx_chat_item_mentions_chat_item_id (chat_item_id=?)
|
||||
SEARCH group_snd_item_statuses USING COVERING INDEX idx_group_snd_item_statuses_chat_item_id (chat_item_id=?)
|
||||
SEARCH chat_item_versions USING COVERING INDEX idx_chat_item_versions_chat_item_id (chat_item_id=?)
|
||||
|
@ -5198,7 +5209,7 @@ SEARCH chat_tags_chats USING COVERING INDEX idx_chat_tags_chats_chat_tag_id_grou
|
|||
SEARCH chat_item_moderations USING COVERING INDEX idx_chat_item_moderations_group_id (group_id=?)
|
||||
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_group_id (group_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_fwd_from_group_id (fwd_from_group_id=?)
|
||||
SCAN chat_items USING COVERING INDEX idx_chat_items_groups_item_ts
|
||||
SCAN chat_items USING COVERING INDEX idx_chat_items_groups_user_mention
|
||||
SEARCH messages USING COVERING INDEX idx_messages_group_id (group_id=?)
|
||||
SEARCH user_contact_links USING COVERING INDEX idx_user_contact_links_group_id (group_id=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_group_id (group_id=?)
|
||||
|
@ -5310,7 +5321,7 @@ SEARCH protocol_servers USING COVERING INDEX idx_smp_servers_user_id (user_id=?)
|
|||
SEARCH settings USING COVERING INDEX idx_settings_user_id (user_id=?)
|
||||
SEARCH commands USING COVERING INDEX idx_commands_user_id (user_id=?)
|
||||
SEARCH calls USING COVERING INDEX idx_calls_user_id (user_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_history (user_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=?)
|
||||
SEARCH contact_requests USING COVERING INDEX sqlite_autoindex_contact_requests_2 (user_id=?)
|
||||
SEARCH user_contact_links USING COVERING INDEX sqlite_autoindex_user_contact_links_1 (user_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_group_member (user_id=?)
|
||||
|
@ -5449,10 +5460,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 item_status = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups (user_id=? AND group_id=? AND item_status=?)
|
||||
|
||||
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=?)
|
||||
|
@ -5465,6 +5472,10 @@ Query: SELECT COUNT(1) FROM groups WHERE user_id = ? AND chat_item_ttl > 0
|
|||
Plan:
|
||||
SEARCH groups USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
||||
Query: SELECT COUNT(1), COALESCE(SUM(user_mention), 0) FROM chat_items WHERE user_id = ? AND group_id = ? AND item_status = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=? AND item_status=?)
|
||||
|
||||
Query: SELECT accepted_at FROM operator_usage_conditions WHERE server_operator_id = ? AND conditions_commit = ?
|
||||
Plan:
|
||||
SEARCH operator_usage_conditions USING INDEX idx_operator_usage_conditions_conditions_commit (conditions_commit=? AND server_operator_id=?)
|
||||
|
|
|
@ -1011,3 +1011,9 @@ CREATE UNIQUE INDEX idx_chat_item_mentions_member_id ON chat_item_mentions(
|
|||
chat_item_id,
|
||||
member_id
|
||||
);
|
||||
CREATE INDEX idx_chat_items_groups_user_mention ON chat_items(
|
||||
user_id,
|
||||
group_id,
|
||||
item_status,
|
||||
user_mention
|
||||
);
|
||||
|
|
|
@ -191,8 +191,9 @@ chatGroupTests = do
|
|||
describe "group member reports" $ do
|
||||
it "should send report to group owner, admins and moderators, but not other users" testGroupMemberReports
|
||||
describe "group member mentions" $ do
|
||||
it "should send messages with member mentions" testMemberMention
|
||||
it "should send and edit messages with member mentions" testMemberMention
|
||||
it "should forward and quote message updating mentioned member name" testForwardQuoteMention
|
||||
it "should send updated mentions in history" testGroupHistoryWithMentions
|
||||
describe "uniqueMsgMentions" testUniqueMsgMentions
|
||||
describe "updatedMentionNames" testUpdatedMentionNames
|
||||
where
|
||||
|
@ -6686,6 +6687,12 @@ testMemberMention =
|
|||
[ alice <# "#team cath> hello @Alice",
|
||||
bob <# "#team cath> hello @Alice"
|
||||
]
|
||||
cath ##> "! #team hello @alice @bob"
|
||||
cath <# "#team [edited] hello @alice @bob"
|
||||
concurrentlyN_
|
||||
[ alice <# "#team cath> [edited] hello @alice @bob",
|
||||
bob <# "#team cath> [edited] hello @alice @bob"
|
||||
]
|
||||
|
||||
testForwardQuoteMention :: HasCallStack => TestParams -> IO ()
|
||||
testForwardQuoteMention =
|
||||
|
@ -6753,6 +6760,41 @@ testForwardQuoteMention =
|
|||
bob <# "alice> -> forwarded"
|
||||
bob <## " hello @alice @alice_1"
|
||||
|
||||
testGroupHistoryWithMentions :: HasCallStack => TestParams -> IO ()
|
||||
testGroupHistoryWithMentions =
|
||||
testChat3 aliceProfile bobProfile cathProfile $
|
||||
\alice bob cath -> do
|
||||
createGroup2 "team" alice bob
|
||||
|
||||
threadDelay 1000000
|
||||
|
||||
alice #> "#team hello @bob"
|
||||
bob <# "#team alice!> hello @bob"
|
||||
|
||||
bob ##> "/p robert"
|
||||
bob <## "user profile is changed to robert (your 1 contacts are notified)"
|
||||
alice <## "contact bob changed to robert"
|
||||
alice <## "use @robert <message> to send messages"
|
||||
|
||||
alice ##> "/create link #team"
|
||||
gLink <- getGroupLink alice "team" GRMember True
|
||||
|
||||
cath ##> ("/c " <> gLink)
|
||||
cath <## "connection request sent!"
|
||||
alice <## "cath (Catherine): accepting request to join group #team..."
|
||||
concurrentlyN_
|
||||
[ alice <## "#team: cath joined the group",
|
||||
cath
|
||||
<### [ "#team: joining the group...",
|
||||
"#team: you joined the group",
|
||||
WithTime "#team alice> hello @robert [>>]",
|
||||
"#team: member robert is connected"
|
||||
],
|
||||
do
|
||||
bob <## "#team: alice added cath (Catherine) to the group (connecting...)"
|
||||
bob <## "#team: new member cath is connected"
|
||||
]
|
||||
|
||||
testUniqueMsgMentions :: SpecWith TestParams
|
||||
testUniqueMsgMentions = do
|
||||
it "1 correct mention" $ \_ ->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue