diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 644bd3f370..68a7953dc9 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -794,7 +794,7 @@ processChatCommand' vr = \case forM_ quotedItemId_ $ \_ -> throwError $ ChatError $ CECommandError "not supported" nf <- withStore $ \db -> getNoteFolder db user folderId -- TODO: assertLocalAllowed user MDSnd nf XMsgNew_ - ci'@ChatItem {meta = CIMeta {itemId, itemTs}} <- createInternalChatItem_ user (CDLocalSnd nf) (CISndMsgContent mc) Nothing + ci'@ChatItem {meta = CIMeta {itemId, itemTs}} <- createLocalChatItem user (CDLocalSnd nf) (CISndMsgContent mc) Nothing ciFile_ <- forM file_ $ \cf@CryptoFile {filePath, cryptoArgs} -> do fsFilePath <- toFSFilePath filePath -- XXX: only used for size?.. fileSize <- liftIO $ CF.getFileContentsSize $ CryptoFile fsFilePath cryptoArgs @@ -926,7 +926,20 @@ processChatCommand' vr = \case r = ACIReaction SCTGroup SMDSnd (GroupChat g) $ CIReaction CIGroupSnd ci' createdAt reaction pure $ CRChatItemReaction user add r _ -> throwChatError $ CECommandError "reaction not possible - no shared item ID" - CTLocal -> pure $ chatCmdError (Just user) "TODO: APIChatItemReaction.CTLocal" + CTLocal -> do + (nf, CChatItem md ci) <- withStore $ \db -> (,) <$> getNoteFolder db user chatId <*> getLocalChatItem db user chatId itemId + itemSharedMId <- case ci of + ChatItem {meta = CIMeta {itemSharedMsgId = Just itemSharedMId}} -> pure itemSharedMId + _ -> throwChatError $ CECommandError "reaction not possible - no shared item ID" + rs <- withStore' $ \db -> getLocalReactions db nf itemSharedMId True + checkReactionAllowed rs + createdAt <- liftIO getCurrentTime + reactions <- withStore' $ \db -> do + setLocalReaction db nf itemSharedMId reaction add createdAt + liftIO $ getLocalCIReactions db nf itemSharedMId + let ci' = CChatItem md ci {reactions} + r = ACIReaction SCTLocal SMDSnd (LocalChat nf) $ CIReaction CILocalSnd ci' createdAt reaction + pure $ CRChatItemReaction user add r CTContactRequest -> pure $ chatCmdError (Just user) "not supported" CTContactConnection -> pure $ chatCmdError (Just user) "not supported" where @@ -6096,6 +6109,18 @@ createInternalChatItem_ user cd content itemTs_ = do createNewChatItemNoMsg db user cd content itemTs createdAt liftIO $ mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs Nothing createdAt +createLocalChatItem :: (MsgDirectionI d, ChatMonad m) => User -> ChatDirection 'CTLocal d -> CIContent d -> Maybe UTCTime -> m (ChatItem 'CTLocal d) +createLocalChatItem user cd content itemTs_ = do + createdAt <- liftIO getCurrentTime + let itemTs = fromMaybe createdAt itemTs_ + gVar <- asks random + ciId <- withStore $ \db -> do + when (ciRequiresAttention content) . liftIO $ updateChatTs db user cd createdAt + createWithRandomId gVar $ \sharedMsgId -> + let smi_ = Just (SharedMsgId sharedMsgId) + in createNewChatItem_ db user cd Nothing smi_ content (Nothing, Nothing, Nothing, Nothing, Nothing) Nothing False itemTs Nothing createdAt + liftIO $ mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs Nothing createdAt + getCreateActiveUser :: SQLiteStore -> Bool -> IO User getCreateActiveUser st testView = do user <- diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 35b0ddb9b7..71b014628c 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -34,6 +34,7 @@ module Simplex.Chat.Store.Messages createNewSndChatItem, createNewRcvChatItem, createNewChatItemNoMsg, + createNewChatItem_, getChatPreviews, getDirectChat, getGroupChat, @@ -68,6 +69,9 @@ module Simplex.Chat.Store.Messages getGroupCIReactions, getGroupReactions, setGroupReaction, + getLocalReactions, + getLocalCIReactions, + setLocalReaction, getChatItemIdByAgentMsgId, getDirectChatItem, getDirectCIWithReactions, @@ -131,7 +135,7 @@ import Simplex.Chat.Messages.CIContent import Simplex.Chat.Protocol import Simplex.Chat.Store.Direct import Simplex.Chat.Store.Groups -import Simplex.Chat.Store.NoteFolders (getNoteFolder) +import Simplex.Chat.Store.NoteFolders import Simplex.Chat.Store.Shared import Simplex.Chat.Types import Simplex.Messaging.Agent.Protocol (AgentMsgId, ConnId, MsgMeta (..), UserId) @@ -2139,6 +2143,9 @@ getACIReactions db aci@(AChatItem _ md chat ci@ChatItem {meta = CIMeta {itemShar let GroupMember {memberId} = chatItemMember g ci reactions <- getGroupCIReactions db g memberId itemSharedMId pure $ AChatItem SCTGroup md chat ci {reactions} + LocalChat nf -> do + reactions <- getLocalCIReactions db nf itemSharedMId + pure $ AChatItem SCTLocal md chat ci {reactions} _ -> pure aci _ -> pure aci @@ -2228,6 +2235,38 @@ setGroupReaction db GroupInfo {groupId} m itemMemberId itemSharedMId sent reacti |] (groupId, groupMemberId' m, itemSharedMId, itemMemberId, sent, reaction) +getLocalReactions :: DB.Connection -> NoteFolder -> SharedMsgId -> Bool -> IO [MsgReaction] +getLocalReactions db NoteFolder {noteFolderId} itemSharedMId sent = + map fromOnly + <$> DB.query + db + [sql| + SELECT reaction + FROM chat_item_reactions + WHERE note_folder_id = ? AND shared_msg_id = ? AND reaction_sent = ? + |] + (noteFolderId, itemSharedMId, sent) + +setLocalReaction :: DB.Connection -> NoteFolder -> SharedMsgId -> MsgReaction -> Bool -> UTCTime -> IO () +setLocalReaction db NoteFolder {noteFolderId} itemSharedMId reaction add reactionTs + | add = + DB.execute + db + [sql| + INSERT INTO chat_item_reactions + (note_folder_id, shared_msg_id, reaction_sent, reaction, reaction_ts) + VALUES (?,?,?,?,?) + |] + (noteFolderId, itemSharedMId, True, reaction, reactionTs) + | otherwise = + DB.execute + db + [sql| + DELETE FROM chat_item_reactions + WHERE note_folder_id = ? AND shared_msg_id = ? AND reaction_sent = ? AND reaction = ? + |] + (noteFolderId, itemSharedMId, True, reaction) + getTimedItems :: DB.Connection -> User -> UTCTime -> IO [((ChatRef, ChatItemId), UTCTime)] getTimedItems db User {userId} startTimedThreadCutoff = mapMaybe toCIRefDeleteAt diff --git a/tests/ChatTests/Local.hs b/tests/ChatTests/Local.hs index ebf499fe3e..9897393685 100644 --- a/tests/ChatTests/Local.hs +++ b/tests/ChatTests/Local.hs @@ -30,6 +30,9 @@ testNotes tmp = withNewTestChat tmp "alice" aliceProfile $ \alice -> do alice ##> "/? keep" alice <# "$self keep in mind" + alice ##> "/_reaction $1 1 on {\"type\":\"emoji\",\"emoji\":\"🚀\"}" + alice <## "added 🚀" + alice ##> "/_delete item $1 1 internal" alice <## "message deleted" alice ##> "/tail"