diff --git a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift index 0096c4a0e..1522c24c5 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemInfoView.swift @@ -49,6 +49,9 @@ struct ChatItemInfoView: View { if !chatItemSent { infoRow("Received at", localTimestamp(chatItemInfo.createdAt)) } + if let deleteAt = chatItemInfo.deleteAt { + infoRow("To be deleted at", localTimestamp(deleteAt)) + } if !chatItemInfo.itemVersions.isEmpty { Divider() @@ -122,6 +125,9 @@ struct ChatItemInfoView: View { if !chatItemSent { shareText += "Received at: \(localTimestamp(chatItemInfo.createdAt))" + nl } + if let deleteAt = chatItemInfo.deleteAt { + shareText += "To be deleted at: \(localTimestamp(deleteAt))" + nl + } if !chatItemInfo.itemVersions.isEmpty { shareText += nl + "Edit history" + nl + nl for (index, itemVersion) in chatItemInfo.itemVersions.enumerated() { diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 668b90111..4bcbb1f62 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -2954,6 +2954,7 @@ public struct ChatItemInfo: Decodable { public var itemTs: Date public var createdAt: Date public var updatedAt: Date + public var deleteAt: Date? public var itemVersions: [ChatItemVersion] } diff --git a/cabal.project b/cabal.project index d4c50d9e3..f587eb6b7 100644 --- a/cabal.project +++ b/cabal.project @@ -7,7 +7,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: ce64c91d5a6e4cbc6cfae6b4a5b312224931f10c + tag: d693868bc0ce0926f5b890dfced56960c8bcf2ab source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index c2cf8dbda..54821c669 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."ce64c91d5a6e4cbc6cfae6b4a5b312224931f10c" = "0iz4hyh1s469vd9nry7wbxbqhc7p1z3qvlyawfayzna1jm0c1mcq"; + "https://github.com/simplex-chat/simplexmq.git"."d693868bc0ce0926f5b890dfced56960c8bcf2ab" = "1g9p7b7da90ac3zrr0hwk6bjn3x3zrl0yq314f5w4a54zlg785zx"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb"; "https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c07228e7c..fe86fcdd7 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -473,8 +473,16 @@ processChatCommand = \case ci <- getAChatItem db user itemId versions <- liftIO $ getChatItemVersions db itemId pure (ci, versions) - let CIMeta {itemTs, createdAt, updatedAt} = meta - ciInfo = ChatItemInfo {chatItemId = itemId, itemTs, createdAt, updatedAt, itemVersions} + let CIMeta {itemTs, createdAt, updatedAt, itemTimed} = meta + ciInfo = + ChatItemInfo + { chatItemId = itemId, + itemTs, + createdAt, + updatedAt, + deleteAt = itemTimed >>= timedDeleteAt', + itemVersions + } pure $ CRChatItemInfo user chatItem ciInfo APISendMessage (ChatRef cType chatId) live itemTTL (ComposedMessage file_ quotedItemId_ mc) -> withUser $ \user@User {userId} -> withChatLock "sendMessage" $ case cType of CTDirect -> do @@ -493,7 +501,7 @@ processChatCommand = \case sendDirectFileInline ct ft sharedMsgId _ -> pure () ci <- saveSndChatItem' user (CDDirectSnd ct) msg (CISndMsgContent mc) ciFile_ quotedItem_ timed_ live - forM_ (timed_ >>= deleteAt) $ + forM_ (timed_ >>= timedDeleteAt') $ startProximateTimedItemThread user (ChatRef CTDirect contactId, chatItemId' ci) setActive $ ActiveC c pure $ CRNewChatItem user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) @@ -550,7 +558,7 @@ processChatCommand = \case msg@SndMessage {sharedMsgId} <- sendGroupMessage user gInfo ms (XMsgNew msgContainer) mapM_ (sendGroupFileInline ms sharedMsgId) ft_ ci <- saveSndChatItem' user (CDGroupSnd gInfo) msg (CISndMsgContent mc) ciFile_ quotedItem_ timed_ live - forM_ (timed_ >>= deleteAt) $ + forM_ (timed_ >>= timedDeleteAt') $ startProximateTimedItemThread user (ChatRef CTGroup groupId, chatItemId' ci) setActive $ ActiveG gName pure $ CRNewChatItem user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) @@ -1853,8 +1861,8 @@ processChatCommand = \case forM (chatTTL >>= (itemTTL <|>)) $ \ttl -> CITimed ttl <$> if live - then pure Nothing - else Just . addUTCTime (realToFrac ttl) <$> liftIO getCurrentTime + then pure Nothing + else Just . addUTCTime (realToFrac ttl) <$> liftIO getCurrentTime drgRandomBytes :: Int -> m ByteString drgRandomBytes n = asks idsDrg >>= liftIO . (`randomBytes` n) privateGetUser :: UserId -> m User @@ -2345,7 +2353,7 @@ subscribeUserConnections agentBatchSubscribe user = do Just _ -> Nothing _ -> Just . ChatError . CEAgentNoSubResult $ AgentConnId connId -cleanupManagerInterval :: Int64 +cleanupManagerInterval :: NominalDiffTime cleanupManagerInterval = 1800 -- 30 minutes cleanupManager :: forall m. ChatMonad m => m () @@ -2358,13 +2366,13 @@ cleanupManager = do forM_ us cleanupUser forM_ us' cleanupUser cleanupMessages `catchError` (toView . CRChatError Nothing) - liftIO $ threadDelay' $ cleanupManagerInterval * 1000000 + liftIO $ threadDelay' $ diffToMicroseconds cleanupManagerInterval where cleanupUser user = cleanupTimedItems user `catchError` (toView . CRChatError (Just user)) cleanupTimedItems user = do ts <- liftIO getCurrentTime - let startTimedThreadCutoff = addUTCTime (realToFrac cleanupManagerInterval) ts + let startTimedThreadCutoff = addUTCTime cleanupManagerInterval ts timedItems <- withStore' $ \db -> getTimedItems db user startTimedThreadCutoff forM_ timedItems $ \(itemRef, deleteAt) -> startTimedItemThread user itemRef deleteAt `catchError` const (pure ()) cleanupMessages = do @@ -2375,7 +2383,7 @@ cleanupManager = do startProximateTimedItemThread :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m () startProximateTimedItemThread user itemRef deleteAt = do ts <- liftIO getCurrentTime - when (diffInSeconds deleteAt ts <= cleanupManagerInterval) $ + when (diffUTCTime deleteAt ts <= cleanupManagerInterval) $ startTimedItemThread user itemRef deleteAt startTimedItemThread :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m () @@ -2396,7 +2404,7 @@ startTimedItemThread user itemRef deleteAt = do deleteTimedItem :: ChatMonad m => User -> (ChatRef, ChatItemId) -> UTCTime -> m () deleteTimedItem user (ChatRef cType chatId, itemId) deleteAt = do ts <- liftIO getCurrentTime - liftIO $ threadDelay' $ diffInMicros deleteAt ts + liftIO $ threadDelay' $ diffToMicroseconds $ diffUTCTime deleteAt ts waitChatStarted case cType of CTDirect -> do @@ -2409,7 +2417,7 @@ deleteTimedItem user (ChatRef cType chatId, itemId) deleteAt = do startUpdatedTimedItemThread :: ChatMonad m => User -> ChatRef -> ChatItem c d -> ChatItem c d -> m () startUpdatedTimedItemThread user chatRef ci ci' = - case (chatItemTimed ci >>= deleteAt, chatItemTimed ci' >>= deleteAt) of + case (chatItemTimed ci >>= timedDeleteAt', chatItemTimed ci' >>= timedDeleteAt') of (Nothing, Just deleteAt') -> startProximateTimedItemThread user (chatRef, chatItemId' ci') deleteAt' _ -> pure () @@ -3455,7 +3463,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do setGroupReaction db g m itemMemberId sharedMsgId False reaction add msgId brokerTs reactions <- getGroupCIReactions db g itemMemberId sharedMsgId let ci' = CChatItem md ci {reactions} - r = ACIReaction SCTGroup SMDRcv (GroupChat g) $ CIReaction (CIGroupRcv m) ci' brokerTs reaction + r = ACIReaction SCTGroup SMDRcv (GroupChat g) $ CIReaction (CIGroupRcv m) ci' brokerTs reaction pure $ Just $ CRChatItemReaction user r add else pure Nothing mapM_ toView cr_ @@ -5047,9 +5055,6 @@ timeItToView s action = do t1 <- liftIO getCurrentTime a <- action t2 <- liftIO getCurrentTime - let diff = diffInMillis t2 t1 + let diff = diffToMilliseconds $ diffUTCTime t2 t1 toView $ CRTimedAction s diff pure a - -diffInMillis :: UTCTime -> UTCTime -> Int64 -diffInMillis a b = (`div` 1000000000) $ diffInPicos a b diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index a3841412e..328fdffeb 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -204,6 +204,9 @@ chatItemTs' ChatItem {meta = CIMeta {itemTs}} = itemTs chatItemTimed :: ChatItem c d -> Maybe CITimed chatItemTimed ChatItem {meta = CIMeta {itemTimed}} = itemTimed +timedDeleteAt' :: CITimed -> Maybe UTCTime +timedDeleteAt' CITimed {deleteAt} = deleteAt + chatItemMember :: GroupInfo -> ChatItem 'CTGroup d -> GroupMember chatItemMember GroupInfo {membership} ChatItem {chatDir} = case chatDir of CIGroupSnd -> membership @@ -1502,6 +1505,7 @@ data ChatItemInfo = ChatItemInfo itemTs :: UTCTime, createdAt :: UTCTime, updatedAt :: UTCTime, + deleteAt :: Maybe UTCTime, itemVersions :: [ChatItemVersion] } deriving (Eq, Show, Generic) diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index d270f2cd7..4ef4da295 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -426,16 +426,19 @@ viewChatItem chat ci@ChatItem {chatDir, meta = meta, content, quotedItem, file} prohibited = styled (colored Red) ("[unexpected chat item created, please report to developers]" :: String) viewChatItemInfo :: AChatItem -> ChatItemInfo -> TimeZone -> [StyledString] -viewChatItemInfo (AChatItem _ msgDir _ _) ChatItemInfo {itemTs, createdAt, itemVersions} tz = case msgDir of - SMDRcv -> - [ "sent at: " <> ts itemTs, - "received at: " <> ts createdAt - ] - <> versions - SMDSnd -> - ["sent at: " <> ts itemTs] <> versions +viewChatItemInfo (AChatItem _ msgDir _ _) ChatItemInfo {itemTs, createdAt, deleteAt, itemVersions} tz = + ["sent at: " <> ts itemTs] + <> receivedAt + <> toBeDeletedAt + <> versions where ts = styleTime . localTs tz + receivedAt = case msgDir of + SMDRcv -> ["received at: " <> ts createdAt] + SMDSnd -> [] + toBeDeletedAt = case deleteAt of + Just d -> ["to be deleted at: " <> ts d] + Nothing -> [] versions = if null itemVersions then [] diff --git a/stack.yaml b/stack.yaml index b73cca745..4e3b3c81e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -49,7 +49,7 @@ extra-deps: # - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561 # - ../simplexmq - github: simplex-chat/simplexmq - commit: ce64c91d5a6e4cbc6cfae6b4a5b312224931f10c + commit: d693868bc0ce0926f5b890dfced56960c8bcf2ab - github: kazu-yamamoto/http2 commit: b5a1b7200cf5bc7044af34ba325284271f6dff25 # - ../direct-sqlcipher