From f40ba6f04ddf908dc36df403a02dd4d811b2199b Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 16:51:54 +0400 Subject: [PATCH 1/7] core: api to differentiate contacts and conversations (#4111) --- simplex-chat.cabal | 1 + src/Simplex/Chat.hs | 58 +++++++++++++------ src/Simplex/Chat/AppSettings.hs | 16 +++-- src/Simplex/Chat/Controller.hs | 10 +++- src/Simplex/Chat/Messages.hs | 6 ++ .../Chat/Migrations/M20240501_chat_deleted.hs | 18 ++++++ src/Simplex/Chat/Migrations/chat_schema.sql | 1 + src/Simplex/Chat/Store/Connections.hs | 6 +- src/Simplex/Chat/Store/Direct.hs | 28 ++++++--- src/Simplex/Chat/Store/Groups.hs | 4 +- src/Simplex/Chat/Store/Messages.hs | 2 +- src/Simplex/Chat/Store/Migrations.hs | 4 +- src/Simplex/Chat/Store/Shared.hs | 7 ++- src/Simplex/Chat/Types.hs | 8 ++- tests/ChatTests/Direct.hs | 41 ++++++++++++- 15 files changed, 164 insertions(+), 46 deletions(-) create mode 100644 src/Simplex/Chat/Migrations/M20240501_chat_deleted.hs diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 6d66e19696..8f31af7ccc 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -142,6 +142,7 @@ library Simplex.Chat.Migrations.M20240324_custom_data Simplex.Chat.Migrations.M20240402_item_forwarded Simplex.Chat.Migrations.M20240430_ui_theme + Simplex.Chat.Migrations.M20240501_chat_deleted Simplex.Chat.Mobile Simplex.Chat.Mobile.File Simplex.Chat.Mobile.Shared diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 9ddcd28876..8b333e7a1d 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1022,22 +1022,41 @@ processChatCommand' vr = \case liftIO $ updateNoteFolderUnreadChat db user nf unreadChat ok user _ -> pure $ chatCmdError (Just user) "not supported" - APIDeleteChat (ChatRef cType chatId) notify -> withUser $ \user@User {userId} -> case cType of + APIDeleteChat cRef@(ChatRef cType chatId) chatDeleteMode -> withUser $ \user@User {userId} -> case cType of CTDirect -> do ct <- withStore $ \db -> getContact db vr user chatId filesInfo <- withStore' $ \db -> getContactFileInfo db user ct - withContactLock "deleteChat direct" chatId . procCmd $ do - cancelFilesInProgress user filesInfo - deleteFilesLocally filesInfo - let doSendDel = contactReady ct && contactActive ct && notify - when doSendDel $ void (sendDirectContactMessage user ct XDirectDel) `catchChatError` const (pure ()) - contactConnIds <- map aConnId <$> withStore' (\db -> getContactConnections db vr userId ct) - deleteAgentConnectionsAsync' user contactConnIds doSendDel - -- functions below are called in separate transactions to prevent crashes on android - -- (possibly, race condition on integrity check?) - withStore' $ \db -> deleteContactConnectionsAndFiles db userId ct - withStore $ \db -> deleteContact db user ct - pure $ CRContactDeleted user ct + withContactLock "deleteChat direct" chatId . procCmd $ + case chatDeleteMode of + CDMFull notify -> do + cancelFilesInProgress user filesInfo + deleteFilesLocally filesInfo + sendDelDeleteConns ct notify + -- functions below are called in separate transactions to prevent crashes on android + -- (possibly, race condition on integrity check?) + withStore' $ \db -> do + deleteContactConnections db user ct + deleteContactFiles db user ct + withStore $ \db -> deleteContact db user ct + pure $ CRContactDeleted user ct + CDMEntity notify -> do + cancelFilesInProgress user filesInfo + sendDelDeleteConns ct notify + ct' <- withStore $ \db -> do + liftIO $ deleteContactConnections db user ct + liftIO $ void $ updateContactStatus db user ct CSDeletedByUser + getContact db vr user chatId + pure $ CRContactDeleted user ct' + CDMMessages -> do + void $ processChatCommand $ APIClearChat cRef + withStore' $ \db -> setContactChatDeleted db user ct True + pure $ CRContactDeleted user ct {chatDeleted = True} + where + sendDelDeleteConns ct notify = do + let doSendDel = contactReady ct && contactActive ct && notify + when doSendDel $ void (sendDirectContactMessage user ct XDirectDel) `catchChatError` const (pure ()) + contactConnIds <- map aConnId <$> withStore' (\db -> getContactConnections db vr userId ct) + deleteAgentConnectionsAsync' user contactConnIds doSendDel CTContactConnection -> withConnectionLock "deleteChat contactConnection" chatId . procCmd $ do conn@PendingContactConnection {pccAgentConnId = AgentConnId acId} <- withStore $ \db -> getPendingContactConnection db userId chatId deleteAgentConnectionAsync user acId @@ -1554,7 +1573,7 @@ processChatCommand' vr = \case CPContactAddress (CAPContactViaAddress Contact {contactId}) -> processChatCommand $ APIConnectContactViaAddress userId incognito contactId _ -> processChatCommand $ APIConnect userId incognito (Just cReqUri) - DeleteContact cName -> withContactName cName $ \ctId -> APIDeleteChat (ChatRef CTDirect ctId) True + DeleteContact cName -> withContactName cName $ \ctId -> APIDeleteChat (ChatRef CTDirect ctId) (CDMFull True) ClearContact cName -> withContactName cName $ APIClearChat . ChatRef CTDirect APIListContacts userId -> withUserId userId $ \user -> CRContactsList user <$> withStore' (\db -> getUserContacts db vr user) @@ -1889,7 +1908,7 @@ processChatCommand' vr = \case processChatCommand $ APILeaveGroup groupId DeleteGroup gName -> withUser $ \user -> do groupId <- withStore $ \db -> getGroupIdByName db user gName - processChatCommand $ APIDeleteChat (ChatRef CTGroup groupId) True + processChatCommand $ APIDeleteChat (ChatRef CTGroup groupId) (CDMFull True) ClearGroup gName -> withUser $ \user -> do groupId <- withStore $ \db -> getGroupIdByName db user gName processChatCommand $ APIClearChat (ChatRef CTGroup groupId) @@ -6676,7 +6695,7 @@ saveSndChatItem' :: ChatTypeI c => User -> ChatDirection c 'MDSnd -> SndMessage saveSndChatItem' user cd msg@SndMessage {sharedMsgId} content ciFile quotedItem itemForwarded itemTimed live = do createdAt <- liftIO getCurrentTime ciId <- withStore' $ \db -> do - when (ciRequiresAttention content) $ updateChatTs db user cd createdAt + when (ciRequiresAttention content || contactChatDeleted cd) $ updateChatTs db user cd createdAt ciId <- createNewSndChatItem db user cd msg content quotedItem itemForwarded itemTimed live createdAt forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt pure ciId @@ -6690,7 +6709,7 @@ saveRcvChatItem' :: (ChatTypeI c, ChatTypeQuotable c) => User -> ChatDirection c saveRcvChatItem' user cd msg@RcvMessage {forwardedByMember} sharedMsgId_ brokerTs content ciFile itemTimed live = do createdAt <- liftIO getCurrentTime (ciId, quotedItem, itemForwarded) <- withStore' $ \db -> do - when (ciRequiresAttention content) $ updateChatTs db user cd createdAt + when (ciRequiresAttention content || contactChatDeleted cd) $ updateChatTs db user cd createdAt r@(ciId, _, _) <- createNewRcvChatItem db user cd msg sharedMsgId_ content itemTimed live brokerTs createdAt forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt pure r @@ -6956,7 +6975,7 @@ createInternalItemsForChats user itemTs_ dirsCIContents = do where updateChat :: DB.Connection -> UTCTime -> ChatDirection c d -> [CIContent d] -> IO () updateChat db createdAt cd contents - | any ciRequiresAttention contents = updateChatTs db user cd createdAt + | any ciRequiresAttention contents || contactChatDeleted cd = updateChatTs db user cd createdAt | otherwise = pure () createACIs :: DB.Connection -> UTCTime -> UTCTime -> ChatDirection c d -> [CIContent d] -> [IO AChatItem] createACIs db itemTs createdAt cd = map $ \content -> do @@ -7104,7 +7123,8 @@ chatCommandP = "/read user" $> UserRead, "/_read chat " *> (APIChatRead <$> chatRefP <*> optional (A.space *> ((,) <$> ("from=" *> A.decimal) <* A.space <*> ("to=" *> A.decimal)))), "/_unread chat " *> (APIChatUnread <$> chatRefP <* A.space <*> onOffP), - "/_delete " *> (APIDeleteChat <$> chatRefP <*> (A.space *> "notify=" *> onOffP <|> pure True)), + "/_delete " *> (APIDeleteChat <$> chatRefP <* A.space <*> jsonP), + "/_delete " *> (APIDeleteChat <$> chatRefP <*> (CDMFull <$> (A.space *> "notify=" *> onOffP <|> pure True))), "/_clear chat " *> (APIClearChat <$> chatRefP), "/_accept" *> (APIAcceptContact <$> incognitoOnOffP <* A.space <*> A.decimal), "/_reject " *> (APIRejectContact <$> A.decimal), diff --git a/src/Simplex/Chat/AppSettings.hs b/src/Simplex/Chat/AppSettings.hs index 62fc900bd0..3d63cb2109 100644 --- a/src/Simplex/Chat/AppSettings.hs +++ b/src/Simplex/Chat/AppSettings.hs @@ -50,7 +50,8 @@ data AppSettings = AppSettings uiColorScheme :: Maybe UIColorScheme, uiDarkColorScheme :: Maybe DarkColorScheme, uiCurrentThemeIds :: Maybe (Map ThemeColorScheme Text), - uiThemes :: Maybe [UITheme] + uiThemes :: Maybe [UITheme], + oneHandUI :: Maybe Bool } deriving (Show) @@ -81,7 +82,8 @@ defaultAppSettings = uiColorScheme = Just UCSSystem, uiDarkColorScheme = Just DCSSimplex, uiCurrentThemeIds = Nothing, - uiThemes = Nothing + uiThemes = Nothing, + oneHandUI = Just True } defaultParseAppSettings :: AppSettings @@ -111,7 +113,8 @@ defaultParseAppSettings = uiColorScheme = Nothing, uiDarkColorScheme = Nothing, uiCurrentThemeIds = Nothing, - uiThemes = Nothing + uiThemes = Nothing, + oneHandUI = Nothing } combineAppSettings :: AppSettings -> AppSettings -> AppSettings @@ -141,7 +144,8 @@ combineAppSettings platformDefaults storedSettings = uiColorScheme = p uiColorScheme, uiDarkColorScheme = p uiDarkColorScheme, uiCurrentThemeIds = p uiCurrentThemeIds, - uiThemes = p uiThemes + uiThemes = p uiThemes, + oneHandUI = p oneHandUI } where p :: (AppSettings -> Maybe a) -> Maybe a @@ -184,6 +188,7 @@ instance FromJSON AppSettings where uiDarkColorScheme <- p "uiDarkColorScheme" uiCurrentThemeIds <- p "uiCurrentThemeIds" uiThemes <- p "uiThemes" + oneHandUI <- p "oneHandUI" pure AppSettings { appPlatform, @@ -210,7 +215,8 @@ instance FromJSON AppSettings where uiColorScheme, uiDarkColorScheme, uiCurrentThemeIds, - uiThemes + uiThemes, + oneHandUI } where p key = v .:? key <|> pure Nothing diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 26ace9c772..5f71657ed8 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -296,7 +296,7 @@ data ChatCommand | UserRead | APIChatRead ChatRef (Maybe (ChatItemId, ChatItemId)) | APIChatUnread ChatRef Bool - | APIDeleteChat ChatRef Bool -- `notify` flag is only applied to direct chats + | APIDeleteChat ChatRef ChatDeleteMode -- currently delete mode settings are only applied to direct chats | APIClearChat ChatRef | APIAcceptContact IncognitoEnabled Int64 | APIRejectContact Int64 @@ -824,6 +824,12 @@ data ChatListQuery clqNoFilters :: ChatListQuery clqNoFilters = CLQFilters {favorite = False, unread = False} +data ChatDeleteMode + = CDMFull {notify :: Bool} -- delete both contact and conversation + | CDMEntity {notify :: Bool} -- delete contact (connection), keep conversation + | CDMMessages -- delete conversation, keep contact - can be re-opened from Contacts view + deriving (Show) + data ConnectionPlan = CPInvitationLink {invitationLinkPlan :: InvitationLinkPlan} | CPContactAddress {contactAddressPlan :: ContactAddressPlan} @@ -1392,6 +1398,8 @@ $(JQ.deriveJSON (enumJSON $ dropPrefix "HS") ''HelpSection) $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CLQ") ''ChatListQuery) +$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CDM") ''ChatDeleteMode) + $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "ILP") ''InvitationLinkPlan) $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CAP") ''ContactAddressPlan) diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index b1c314c04b..9ca191d3f9 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -278,6 +278,12 @@ toChatInfo = \case CDLocalSnd l -> LocalChat l CDLocalRcv l -> LocalChat l +contactChatDeleted :: ChatDirection c d -> Bool +contactChatDeleted = \case + CDDirectSnd Contact {chatDeleted} -> chatDeleted + CDDirectRcv Contact {chatDeleted} -> chatDeleted + _ -> False + data NewChatItem d = NewChatItem { createdByMsgId :: Maybe MessageId, itemSent :: SMsgDirection d, diff --git a/src/Simplex/Chat/Migrations/M20240501_chat_deleted.hs b/src/Simplex/Chat/Migrations/M20240501_chat_deleted.hs new file mode 100644 index 0000000000..a7faf33472 --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240501_chat_deleted.hs @@ -0,0 +1,18 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240501_chat_deleted where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240501_chat_deleted :: Query +m20240501_chat_deleted = + [sql| +ALTER TABLE contacts ADD COLUMN chat_deleted INTEGER NOT NULL DEFAULT 0; +|] + +down_m20240501_chat_deleted :: Query +down_m20240501_chat_deleted = + [sql| +ALTER TABLE contacts DROP COLUMN chat_deleted; +|] diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql index f2f94d019c..e700acd4d4 100644 --- a/src/Simplex/Chat/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Migrations/chat_schema.sql @@ -76,6 +76,7 @@ CREATE TABLE contacts( contact_status TEXT NOT NULL DEFAULT 'active', custom_data BLOB, ui_themes TEXT, + chat_deleted INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(user_id, local_display_name) REFERENCES display_names(user_id, local_display_name) ON DELETE CASCADE diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index bae9d00bfd..1c3e949562 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -98,19 +98,19 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do [sql| SELECT c.contact_profile_id, c.local_display_name, c.via_group, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, c.contact_used, c.contact_status, c.enable_ntfs, c.send_rcpts, c.favorite, - p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.contact_group_member_id, c.contact_grp_inv_sent, c.ui_themes, c.custom_data + p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.contact_group_member_id, c.contact_grp_inv_sent, c.ui_themes, c.chat_deleted, c.custom_data FROM contacts c JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id WHERE c.user_id = ? AND c.contact_id = ? AND c.deleted = 0 |] (userId, contactId) toContact' :: Int64 -> Connection -> [ContactRow'] -> Either StoreError Contact - toContact' contactId conn [(profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, customData)] = + toContact' contactId conn [(profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)] = let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias} chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito conn activeConn = Just conn - in Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, customData} + in Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData} toContact' _ _ _ = Left $ SEInternalError "referenced contact not found" getGroupAndMember_ :: Int64 -> Connection -> ExceptT StoreError IO (GroupInfo, GroupMember) getGroupAndMember_ groupMemberId c = ExceptT $ do diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index deb0f9fc4c..ecba9be7fa 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -30,7 +30,8 @@ module Simplex.Chat.Store.Direct getConnReqContactXContactId, getContactByConnReqHash, createDirectContact, - deleteContactConnectionsAndFiles, + deleteContactConnections, + deleteContactFiles, deleteContact, deleteContactWithoutGroups, setContactDeleted, @@ -70,6 +71,7 @@ module Simplex.Chat.Store.Direct resetContactConnInitiated, setContactCustomData, setContactUIThemes, + setContactChatDeleted, ) where @@ -178,7 +180,7 @@ getContactByConnReqHash db vr user@User {userId} cReqHash = SELECT -- Contact ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite, - cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.custom_data, + cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, @@ -241,12 +243,13 @@ createDirectContact db user@User {userId} conn@Connection {connId, localAlias} p chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, - customData = Nothing, - uiThemes = Nothing + uiThemes = Nothing, + chatDeleted = False, + customData = Nothing } -deleteContactConnectionsAndFiles :: DB.Connection -> UserId -> Contact -> IO () -deleteContactConnectionsAndFiles db userId Contact {contactId} = do +deleteContactConnections :: DB.Connection -> User -> Contact -> IO () +deleteContactConnections db User {userId} Contact {contactId} = do DB.execute db [sql| @@ -258,6 +261,9 @@ deleteContactConnectionsAndFiles db userId Contact {contactId} = do ) |] (userId, contactId) + +deleteContactFiles :: DB.Connection -> User -> Contact -> IO () +deleteContactFiles db User {userId} Contact {contactId} = do DB.execute db "DELETE FROM files WHERE user_id = ? AND contact_id = ?" (userId, contactId) deleteContact :: DB.Connection -> User -> Contact -> ExceptT StoreError IO () @@ -600,7 +606,7 @@ createOrUpdateContactRequest db vr user@User {userId} userContactLinkId invId (V SELECT -- Contact ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite, - cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.custom_data, + cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, @@ -764,6 +770,7 @@ createAcceptedContact db user@User {userId, profile = LocalProfile {preferences} contactGroupMemberId = Nothing, contactGrpInvSent = False, uiThemes = Nothing, + chatDeleted = False, customData = Nothing } @@ -784,7 +791,7 @@ getContact_ db vr user@User {userId} contactId deleted = SELECT -- Contact ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite, - cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.custom_data, + cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, @@ -934,3 +941,8 @@ setContactUIThemes :: DB.Connection -> User -> Contact -> Maybe UIThemeEntityOve setContactUIThemes db User {userId} Contact {contactId} uiThemes = do updatedAt <- getCurrentTime DB.execute db "UPDATE contacts SET ui_themes = ?, updated_at = ? WHERE user_id = ? AND contact_id = ?" (uiThemes, updatedAt, userId, contactId) + +setContactChatDeleted :: DB.Connection -> User -> Contact -> Bool -> IO () +setContactChatDeleted db User {userId} Contact {contactId} chatDeleted = do + updatedAt <- getCurrentTime + DB.execute db "UPDATE contacts SET chat_deleted = ?, updated_at = ? WHERE user_id = ? AND contact_id = ?" (chatDeleted, updatedAt, userId, contactId) diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index d8655c818b..5e603a40c9 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -1960,7 +1960,7 @@ createMemberContact authErrCounter = 0 } mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn - pure Contact {contactId, localDisplayName, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False, uiThemes = Nothing, customData = Nothing} + pure Contact {contactId, localDisplayName, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False, uiThemes = Nothing, chatDeleted = False, customData = Nothing} getMemberContact :: DB.Connection -> VersionRangeChat -> User -> ContactId -> ExceptT StoreError IO (GroupInfo, GroupMember, Contact, ConnReqInvitation) getMemberContact db vr user contactId = do @@ -1997,7 +1997,7 @@ createMemberContactInvited contactId <- createContactUpdateMember currentTs userPreferences ctConn <- createMemberContactConn_ db user connIds gInfo mConn contactId subMode let mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn - mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, uiThemes = Nothing, customData = Nothing} + mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = Just ctConn, viaGroup = Nothing, contactUsed = True, contactStatus = CSActive, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False, uiThemes = Nothing, chatDeleted = False, customData = Nothing} m' = m {memberContactId = Just contactId} pure (mCt', m') where diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 8163bd336c..35e515cc2a 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -315,7 +315,7 @@ updateChatTs db User {userId} chatDirection chatTs = case toChatInfo chatDirecti DirectChat Contact {contactId} -> DB.execute db - "UPDATE contacts SET chat_ts = ? WHERE user_id = ? AND contact_id = ?" + "UPDATE contacts SET chat_ts = ?, chat_deleted = 0 WHERE user_id = ? AND contact_id = ?" (chatTs, userId, contactId) GroupChat GroupInfo {groupId} -> DB.execute diff --git a/src/Simplex/Chat/Store/Migrations.hs b/src/Simplex/Chat/Store/Migrations.hs index 2b44778272..e25f255bd8 100644 --- a/src/Simplex/Chat/Store/Migrations.hs +++ b/src/Simplex/Chat/Store/Migrations.hs @@ -106,6 +106,7 @@ import Simplex.Chat.Migrations.M20240313_drop_agent_ack_cmd_id import Simplex.Chat.Migrations.M20240324_custom_data import Simplex.Chat.Migrations.M20240402_item_forwarded import Simplex.Chat.Migrations.M20240430_ui_theme +import Simplex.Chat.Migrations.M20240501_chat_deleted import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..)) schemaMigrations :: [(String, Query, Maybe Query)] @@ -211,7 +212,8 @@ schemaMigrations = ("20240313_drop_agent_ack_cmd_id", m20240313_drop_agent_ack_cmd_id, Just down_m20240313_drop_agent_ack_cmd_id), ("20240324_custom_data", m20240324_custom_data, Just down_m20240324_custom_data), ("20240402_item_forwarded", m20240402_item_forwarded, Just down_m20240402_item_forwarded), - ("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme) + ("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme), + ("20240501_chat_deleted", m20240501_chat_deleted, Just down_m20240501_chat_deleted) ] -- | The list of migrations in ascending order by date diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index 1f16ebfef0..113a84966d 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -381,18 +381,19 @@ deleteUnusedIncognitoProfileById_ db User {userId} profileId = |] [":user_id" := userId, ":profile_id" := profileId] -type ContactRow' = (ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Bool, ContactStatus) :. (Maybe MsgFilter, Maybe Bool, Bool, Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime, Maybe GroupMemberId, Bool, Maybe UIThemeEntityOverrides, Maybe CustomData) + +type ContactRow' = (ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Bool, ContactStatus) :. (Maybe MsgFilter, Maybe Bool, Bool, Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime) :. (Maybe GroupMemberId, Bool, Maybe UIThemeEntityOverrides, Bool, Maybe CustomData) type ContactRow = Only ContactId :. ContactRow' toContact :: VersionRangeChat -> User -> ContactRow :. MaybeConnectionRow -> Contact -toContact vr user ((Only contactId :. (profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, customData)) :. connRow) = +toContact vr user ((Only contactId :. (profileId, localDisplayName, viaGroup, displayName, fullName, image, contactLink, localAlias, contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. (contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData)) :. connRow) = let profile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias} activeConn = toMaybeConnection vr connRow chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts, favorite} incognito = maybe False connIncognito activeConn mergedPreferences = contactUserPreferences user userPreferences preferences incognito - in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, customData} + in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, contactGroupMemberId, contactGrpInvSent, uiThemes, chatDeleted, customData} getProfileById :: DB.Connection -> UserId -> Int64 -> ExceptT StoreError IO LocalProfile getProfileById db userId profileId = diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index 4d8e954312..336448d7f5 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -177,6 +177,7 @@ data Contact = Contact contactGroupMemberId :: Maybe GroupMemberId, contactGrpInvSent :: Bool, uiThemes :: Maybe UIThemeEntityOverrides, + chatDeleted :: Bool, customData :: Maybe CustomData } deriving (Eq, Show) @@ -226,7 +227,7 @@ contactActive :: Contact -> Bool contactActive Contact {contactStatus} = contactStatus == CSActive contactDeleted :: Contact -> Bool -contactDeleted Contact {contactStatus} = contactStatus == CSDeleted +contactDeleted Contact {contactStatus} = contactStatus == CSDeleted || contactStatus == CSDeletedByUser contactSecurityCode :: Contact -> Maybe SecurityCode contactSecurityCode Contact {activeConn} = connectionCode =<< activeConn @@ -236,7 +237,8 @@ contactPQEnabled Contact {activeConn} = maybe PQEncOff connPQEnabled activeConn data ContactStatus = CSActive - | CSDeleted -- contact deleted by contact + | CSDeleted + | CSDeletedByUser deriving (Eq, Show, Ord) instance FromField ContactStatus where fromField = fromTextField_ textDecode @@ -254,10 +256,12 @@ instance TextEncoding ContactStatus where textDecode = \case "active" -> Just CSActive "deleted" -> Just CSDeleted + "deletedByUser" -> Just CSDeletedByUser _ -> Nothing textEncode = \case CSActive -> "active" CSDeleted -> "deleted" + CSDeletedByUser -> "deletedByUser" data ContactRef = ContactRef { contactId :: ContactId, diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index 1579dedaa7..16082cb30b 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -37,6 +37,8 @@ chatDirectTests = do describe "add contact and send/receive messages" testAddContact it "clear chat with contact" testContactClear it "deleting contact deletes profile" testDeleteContactDeletesProfile + it "delete contact keeping conversation" testDeleteContactKeepConversation + it "delete conversation keeping contact" testDeleteConversationKeepContact it "unused contact is deleted silently" testDeleteUnusedContactSilent it "direct message quoted replies" testDirectMessageQuotedReply it "direct message update" testDirectMessageUpdate @@ -344,7 +346,7 @@ testDeleteContactDeletesProfile = connectUsers alice bob alice <##> bob -- alice deletes contact, profile is deleted - alice ##> "/d bob" + alice ##> "/_delete @2 {\"type\": \"full\", \"notify\": true}" alice <## "bob: contact is deleted" bob <## "alice (Alice) deleted contact with you" alice ##> "/_contacts 1" @@ -357,6 +359,43 @@ testDeleteContactDeletesProfile = (bob FilePath -> IO () +testDeleteContactKeepConversation = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + connectUsers alice bob + alice <##> bob + + alice ##> "/_delete @2 {\"type\": \"entity\", \"notify\": true}" + alice <## "bob: contact is deleted" + bob <## "alice (Alice) deleted contact with you" + + alice @@@ [("@bob", "hey")] + alice ##> "@bob hi" + alice <## "bob: not ready" + bob @@@ [("@alice", "contact deleted")] + bob ##> "@alice hey" + bob <## "alice: not ready" + +testDeleteConversationKeepContact :: HasCallStack => FilePath -> IO () +testDeleteConversationKeepContact = + testChat2 aliceProfile bobProfile $ + \alice bob -> do + connectUsers alice bob + alice <##> bob + + alice @@@ [("@bob", "hey")] + + alice ##> "/_delete @2 {\"type\": \"messages\", \"notify\": true}" + alice <## "bob: contact is deleted" + + alice @@@ [("@bob", "")] -- UI would filter + bob @@@ [("@alice", "hey")] + bob #> "@alice hi" + alice <# "bob> hi" + alice @@@ [("@bob", "hi")] + alice <##> bob + testDeleteUnusedContactSilent :: HasCallStack => FilePath -> IO () testDeleteUnusedContactSilent = testChatCfg3 testCfgCreateGroupDirect aliceProfile bobProfile cathProfile $ From f091384aa78f299249f1716d4ae474753fb90741 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 20:25:24 +0400 Subject: [PATCH 2/7] ui: apply model updates only for active user for switch and ratchet sync events (#4175) --- apps/ios/Shared/Model/SimpleXAPI.swift | 32 ++++++++++++------- .../chat/simplex/common/model/SimpleXAPI.kt | 16 +++++++--- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index b4c9a48d5d..4a982e18bb 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -1849,21 +1849,29 @@ func processReceivedMsg(_ res: ChatResponse) async { } case .chatSuspended: chatSuspended() - case let .contactSwitch(_, contact, switchProgress): - await MainActor.run { - m.updateContactConnectionStats(contact, switchProgress.connectionStats) + case let .contactSwitch(user, contact, switchProgress): + if active(user) { + await MainActor.run { + m.updateContactConnectionStats(contact, switchProgress.connectionStats) + } } - case let .groupMemberSwitch(_, groupInfo, member, switchProgress): - await MainActor.run { - m.updateGroupMemberConnectionStats(groupInfo, member, switchProgress.connectionStats) + case let .groupMemberSwitch(user, groupInfo, member, switchProgress): + if active(user) { + await MainActor.run { + m.updateGroupMemberConnectionStats(groupInfo, member, switchProgress.connectionStats) + } } - case let .contactRatchetSync(_, contact, ratchetSyncProgress): - await MainActor.run { - m.updateContactConnectionStats(contact, ratchetSyncProgress.connectionStats) + case let .contactRatchetSync(user, contact, ratchetSyncProgress): + if active(user) { + await MainActor.run { + m.updateContactConnectionStats(contact, ratchetSyncProgress.connectionStats) + } } - case let .groupMemberRatchetSync(_, groupInfo, member, ratchetSyncProgress): - await MainActor.run { - m.updateGroupMemberConnectionStats(groupInfo, member, ratchetSyncProgress.connectionStats) + case let .groupMemberRatchetSync(user, groupInfo, member, ratchetSyncProgress): + if active(user) { + await MainActor.run { + m.updateGroupMemberConnectionStats(groupInfo, member, ratchetSyncProgress.connectionStats) + } } case let .remoteCtrlFound(remoteCtrl, ctrlAppInfo_, appVersion, compatible): await MainActor.run { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index b71610597e..281bcefd45 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -2031,13 +2031,21 @@ object ChatController { } } is CR.ContactSwitch -> - chatModel.updateContactConnectionStats(rhId, r.contact, r.switchProgress.connectionStats) + if (active(r.user)) { + chatModel.updateContactConnectionStats(rhId, r.contact, r.switchProgress.connectionStats) + } is CR.GroupMemberSwitch -> - chatModel.updateGroupMemberConnectionStats(rhId, r.groupInfo, r.member, r.switchProgress.connectionStats) + if (active(r.user)) { + chatModel.updateGroupMemberConnectionStats(rhId, r.groupInfo, r.member, r.switchProgress.connectionStats) + } is CR.ContactRatchetSync -> - chatModel.updateContactConnectionStats(rhId, r.contact, r.ratchetSyncProgress.connectionStats) + if (active(r.user)) { + chatModel.updateContactConnectionStats(rhId, r.contact, r.ratchetSyncProgress.connectionStats) + } is CR.GroupMemberRatchetSync -> - chatModel.updateGroupMemberConnectionStats(rhId, r.groupInfo, r.member, r.ratchetSyncProgress.connectionStats) + if (active(r.user)) { + chatModel.updateGroupMemberConnectionStats(rhId, r.groupInfo, r.member, r.ratchetSyncProgress.connectionStats) + } is CR.RemoteHostSessionCode -> { chatModel.remoteHostPairing.value = r.remoteHost_ to RemoteHostSessionState.PendingConfirmation(r.sessionCode) } From 29db2b4e9bee5f4f5cb4edf11bb0a29800d7d30a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 13 May 2024 19:55:57 +0100 Subject: [PATCH 3/7] core: command to show duplicate message count (#4172) * core: command to show duplicate message count * update * updated * update * update * simplexmq --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat.hs | 6 ++++++ src/Simplex/Chat/Controller.hs | 2 ++ src/Simplex/Chat/View.hs | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index f45ff7bfb7..0557ca5060 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 4455b8bd0e243aa3bb4dc854037b2e64677963b0 + tag: 512afa1e2bc721241a78e8cc9feaf68b5775d919 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 83e2abe3c7..bd5ff1d34c 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."4455b8bd0e243aa3bb4dc854037b2e64677963b0" = "11vmr7r9r611lcamf9ay34axw0yz402gif59bhpipjkn95bgjx0p"; + "https://github.com/simplex-chat/simplexmq.git"."512afa1e2bc721241a78e8cc9feaf68b5775d919" = "0y51sdsy9611vx6ph0vamw30yhhv2lwz52vbv8g51zg2hz4yz9pg"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 8b333e7a1d..27b9cfa0cd 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -46,6 +46,7 @@ import qualified Data.List.NonEmpty as L import Data.Map.Strict (Map) import qualified Data.Map.Strict as M import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, listToMaybe, mapMaybe, maybeToList) +import Data.Ord (Down (..)) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeLatin1, encodeUtf8) @@ -2222,6 +2223,10 @@ processChatCommand' vr = \case stat (AgentStatsKey {host, clientTs, cmd, res}, count) = map B.unpack [host, clientTs, cmd, res, bshow count] ResetAgentStats -> lift (withAgent' resetAgentStats) >> ok_ + GetAgentMsgCounts -> lift $ do + counts <- map (first decodeLatin1) <$> withAgent' getMsgCounts + let allMsgs = foldl' (\(ts, ds) (_, (t, d)) -> (ts + t, ds + d)) (0, 0) counts + pure CRAgentMsgCounts {msgCounts = ("all", allMsgs) : sortOn (Down . snd) (filter (\(_, (_, d)) -> d /= 0) counts)} GetAgentSubs -> lift $ summary <$> withAgent' getAgentSubscriptions where summary SubscriptionsInfo {activeSubscriptions, pendingSubscriptions, removedSubscriptions} = @@ -7361,6 +7366,7 @@ chatCommandP = "/get subs details" $> GetAgentSubsDetails, "/get workers" $> GetAgentWorkers, "/get workers details" $> GetAgentWorkersDetails, + "/get msgs" $> GetAgentMsgCounts, "//" *> (CustomChatCommand <$> A.takeByteString) ] where diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 5f71657ed8..c21d1bf768 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -501,6 +501,7 @@ data ChatCommand | GetAgentSubsDetails | GetAgentWorkers | GetAgentWorkersDetails + | GetAgentMsgCounts | -- The parser will return this command for strings that start from "//". -- This command should be processed in preCmdHook CustomChatCommand ByteString @@ -746,6 +747,7 @@ data ChatResponse | CRAgentWorkersSummary {agentWorkersSummary :: AgentWorkersSummary} | CRAgentSubs {activeSubs :: Map Text Int, pendingSubs :: Map Text Int, removedSubs :: Map Text [String]} | CRAgentSubsDetails {agentSubs :: SubscriptionsInfo} + | CRAgentMsgCounts {msgCounts :: [(Text, (Int, Int))]} | CRConnectionDisabled {connectionEntity :: ConnectionEntity} | CRAgentRcvQueueDeleted {agentConnId :: AgentConnId, server :: SMPServer, agentQueueId :: AgentQueueId, agentError_ :: Maybe AgentErrorType} | CRAgentConnDeleted {agentConnId :: AgentConnId} diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index ba3e468b1a..236730e45d 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -375,6 +375,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe [ "agent workers details:", plain . LB.unpack $ J.encode agentWorkersDetails -- this would be huge, but copypastable when has its own line ] + CRAgentMsgCounts {msgCounts} -> ["received messages (total, duplicates):", plain . LB.unpack $ J.encode msgCounts] CRConnectionDisabled entity -> viewConnectionEntityDisabled entity CRAgentRcvQueueDeleted acId srv aqId err_ -> [ ("completed deleting rcv queue, agent connection id: " <> sShow acId) From 331b4633fc951c90df9a03c34e1a4804ce675149 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 13 May 2024 20:39:13 +0100 Subject: [PATCH 4/7] core: platform independent encoding for delete command (#4176) --- src/Simplex/Chat.hs | 20 ++++++++++++++------ src/Simplex/Chat/Controller.hs | 8 +++----- tests/ChatTests/Direct.hs | 6 +++--- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 27b9cfa0cd..2925ef000e 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1023,12 +1023,12 @@ processChatCommand' vr = \case liftIO $ updateNoteFolderUnreadChat db user nf unreadChat ok user _ -> pure $ chatCmdError (Just user) "not supported" - APIDeleteChat cRef@(ChatRef cType chatId) chatDeleteMode -> withUser $ \user@User {userId} -> case cType of + APIDeleteChat cRef@(ChatRef cType chatId) cdm -> withUser $ \user@User {userId} -> case cType of CTDirect -> do ct <- withStore $ \db -> getContact db vr user chatId filesInfo <- withStore' $ \db -> getContactFileInfo db user ct withContactLock "deleteChat direct" chatId . procCmd $ - case chatDeleteMode of + case cdm of CDMFull notify -> do cancelFilesInProgress user filesInfo deleteFilesLocally filesInfo @@ -1574,7 +1574,7 @@ processChatCommand' vr = \case CPContactAddress (CAPContactViaAddress Contact {contactId}) -> processChatCommand $ APIConnectContactViaAddress userId incognito contactId _ -> processChatCommand $ APIConnect userId incognito (Just cReqUri) - DeleteContact cName -> withContactName cName $ \ctId -> APIDeleteChat (ChatRef CTDirect ctId) (CDMFull True) + DeleteContact cName cdm -> withContactName cName $ \ctId -> APIDeleteChat (ChatRef CTDirect ctId) cdm ClearContact cName -> withContactName cName $ APIClearChat . ChatRef CTDirect APIListContacts userId -> withUserId userId $ \user -> CRContactsList user <$> withStore' (\db -> getUserContacts db vr user) @@ -7128,8 +7128,7 @@ chatCommandP = "/read user" $> UserRead, "/_read chat " *> (APIChatRead <$> chatRefP <*> optional (A.space *> ((,) <$> ("from=" *> A.decimal) <* A.space <*> ("to=" *> A.decimal)))), "/_unread chat " *> (APIChatUnread <$> chatRefP <* A.space <*> onOffP), - "/_delete " *> (APIDeleteChat <$> chatRefP <* A.space <*> jsonP), - "/_delete " *> (APIDeleteChat <$> chatRefP <*> (CDMFull <$> (A.space *> "notify=" *> onOffP <|> pure True))), + "/_delete " *> (APIDeleteChat <$> chatRefP <*> chatDeleteMode), "/_clear chat " *> (APIClearChat <$> chatRefP), "/_accept" *> (APIAcceptContact <$> incognitoOnOffP <* A.space <*> A.decimal), "/_reject " *> (APIRejectContact <$> A.decimal), @@ -7235,7 +7234,7 @@ chatCommandP = ("/remove " <|> "/rm ") *> char_ '#' *> (RemoveMember <$> displayName <* A.space <* char_ '@' <*> displayName), ("/leave " <|> "/l ") *> char_ '#' *> (LeaveGroup <$> displayName), ("/delete #" <|> "/d #") *> (DeleteGroup <$> displayName), - ("/delete " <|> "/d ") *> char_ '@' *> (DeleteContact <$> displayName), + ("/delete " <|> "/d ") *> char_ '@' *> (DeleteContact <$> displayName <*> chatDeleteMode), "/clear *" $> ClearNoteFolder, "/clear #" *> (ClearGroup <$> displayName), "/clear " *> char_ '@' *> (ClearContact <$> displayName), @@ -7387,6 +7386,15 @@ chatCommandP = mcTextP = MCText . safeDecodeUtf8 <$> A.takeByteString msgContentP = "text " *> mcTextP <|> "json " *> jsonP ciDeleteMode = "broadcast" $> CIDMBroadcast <|> "internal" $> CIDMInternal + chatDeleteMode = + A.choice + [ " full" *> (CDMFull <$> notifyP), + " entity" *> (CDMEntity <$> notifyP), + " messages" $> CDMMessages, + CDMFull <$> notifyP -- backwards compatible + ] + where + notifyP = " notify=" *> onOffP <|> pure True displayName = safeDecodeUtf8 <$> (quoted "'" <|> takeNameTill isSpace) where takeNameTill p = diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index c21d1bf768..58e0e2e321 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -395,7 +395,7 @@ data ChatCommand | Connect IncognitoEnabled (Maybe AConnectionRequestUri) | APIConnectContactViaAddress UserId IncognitoEnabled ContactId | ConnectSimplex IncognitoEnabled -- UserId (not used in UI) - | DeleteContact ContactName + | DeleteContact ContactName ChatDeleteMode | ClearContact ContactName | APIListContacts UserId | ListContacts @@ -827,9 +827,9 @@ clqNoFilters :: ChatListQuery clqNoFilters = CLQFilters {favorite = False, unread = False} data ChatDeleteMode - = CDMFull {notify :: Bool} -- delete both contact and conversation + = CDMFull {notify :: Bool} -- delete both contact and conversation | CDMEntity {notify :: Bool} -- delete contact (connection), keep conversation - | CDMMessages -- delete conversation, keep contact - can be re-opened from Contacts view + | CDMMessages -- delete conversation, keep contact - can be re-opened from Contacts view deriving (Show) data ConnectionPlan @@ -1400,8 +1400,6 @@ $(JQ.deriveJSON (enumJSON $ dropPrefix "HS") ''HelpSection) $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CLQ") ''ChatListQuery) -$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CDM") ''ChatDeleteMode) - $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "ILP") ''InvitationLinkPlan) $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CAP") ''ContactAddressPlan) diff --git a/tests/ChatTests/Direct.hs b/tests/ChatTests/Direct.hs index 16082cb30b..54f31ff50f 100644 --- a/tests/ChatTests/Direct.hs +++ b/tests/ChatTests/Direct.hs @@ -346,7 +346,7 @@ testDeleteContactDeletesProfile = connectUsers alice bob alice <##> bob -- alice deletes contact, profile is deleted - alice ##> "/_delete @2 {\"type\": \"full\", \"notify\": true}" + alice ##> "/_delete @2 full notify=on" alice <## "bob: contact is deleted" bob <## "alice (Alice) deleted contact with you" alice ##> "/_contacts 1" @@ -366,7 +366,7 @@ testDeleteContactKeepConversation = connectUsers alice bob alice <##> bob - alice ##> "/_delete @2 {\"type\": \"entity\", \"notify\": true}" + alice ##> "/_delete @2 entity notify=on" alice <## "bob: contact is deleted" bob <## "alice (Alice) deleted contact with you" @@ -386,7 +386,7 @@ testDeleteConversationKeepContact = alice @@@ [("@bob", "hey")] - alice ##> "/_delete @2 {\"type\": \"messages\", \"notify\": true}" + alice ##> "/_delete @2 messages" alice <## "bob: contact is deleted" alice @@@ [("@bob", "")] -- UI would filter From 396b73b4800238d38df68e097f3aa58b24fb4660 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 13 May 2024 21:13:07 +0100 Subject: [PATCH 5/7] core: 5.8.0.0 --- cabal.project | 2 +- package.yaml | 2 +- scripts/nix/sha256map.nix | 2 +- simplex-chat.cabal | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cabal.project b/cabal.project index 0557ca5060..80e42fc652 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 512afa1e2bc721241a78e8cc9feaf68b5775d919 + tag: 762909ce33c01d71bbabfed156e1e9faeebbedca source-repository-package type: git diff --git a/package.yaml b/package.yaml index eba20290ef..70b91b7bc5 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.7.3.0 +version: 5.8.0.0 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index bd5ff1d34c..2b168c51ba 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."512afa1e2bc721241a78e8cc9feaf68b5775d919" = "0y51sdsy9611vx6ph0vamw30yhhv2lwz52vbv8g51zg2hz4yz9pg"; + "https://github.com/simplex-chat/simplexmq.git"."762909ce33c01d71bbabfed156e1e9faeebbedca" = "0jsfi792n84zk6bhfhg138mn0mv6wvvfmm0d6qxmplpb6glcbqaj"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 8f31af7ccc..e8f3601d96 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 5.7.3.0 +version: 5.8.0.0 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat From a1948d549b9d5fca9f6cb69f390ac83da9df9a3d Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 13 May 2024 22:24:10 +0100 Subject: [PATCH 6/7] ios: update core library --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 30345d6895..3ad4ca426b 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -115,11 +115,11 @@ 5CD67B8F2B0E858A00C510B1 /* hs_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CD67B8D2B0E858A00C510B1 /* hs_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5CD67B902B0E858A00C510B1 /* hs_init.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CD67B8E2B0E858A00C510B1 /* hs_init.c */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; - 5CE0E8AB2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */; }; - 5CE0E8AC2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */; }; - 5CE0E8AD2BF0C1B5008D6E06 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */; }; - 5CE0E8AE2BF0C1B5008D6E06 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */; }; - 5CE0E8AF2BF0C1B5008D6E06 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */; }; + 5CE0E8B52BF2B9ED008D6E06 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8B02BF2B9ED008D6E06 /* libgmp.a */; }; + 5CE0E8B62BF2B9ED008D6E06 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8B12BF2B9ED008D6E06 /* libgmpxx.a */; }; + 5CE0E8B72BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8B22BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a */; }; + 5CE0E8B82BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8B32BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a */; }; + 5CE0E8B92BF2B9ED008D6E06 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE0E8B42BF2B9ED008D6E06 /* libffi.a */; }; 5CE2BA702845308900EC33A6 /* SimpleXChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; }; 5CE2BA712845308900EC33A6 /* SimpleXChat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5CE2BA77284530BF00EC33A6 /* SimpleXChat.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CE2BA76284530BF00EC33A6 /* SimpleXChat.h */; }; @@ -420,11 +420,11 @@ 5CDCAD7428188D2900503DA2 /* APITypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APITypes.swift; sourceTree = ""; }; 5CDCAD7D2818941F00503DA2 /* API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = ""; }; 5CDCAD80281A7E2700503DA2 /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = ""; }; - 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a"; sourceTree = ""; }; - 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a"; sourceTree = ""; }; - 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5CE0E8B02BF2B9ED008D6E06 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5CE0E8B12BF2B9ED008D6E06 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5CE0E8B22BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a"; sourceTree = ""; }; + 5CE0E8B32BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a"; sourceTree = ""; }; + 5CE0E8B42BF2B9ED008D6E06 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; 5CE1330328E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = "de.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5CE1330428E118CC00FFFD8C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; 5CE2BA682845308900EC33A6 /* SimpleXChat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SimpleXChat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -529,13 +529,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5CE0E8B72BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a in Frameworks */, + 5CE0E8B62BF2B9ED008D6E06 /* libgmpxx.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5CE0E8AE2BF0C1B5008D6E06 /* libffi.a in Frameworks */, - 5CE0E8AD2BF0C1B5008D6E06 /* libgmp.a in Frameworks */, + 5CE0E8B52BF2B9ED008D6E06 /* libgmp.a in Frameworks */, + 5CE0E8B92BF2B9ED008D6E06 /* libffi.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 5CE0E8AC2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a in Frameworks */, - 5CE0E8AB2BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a in Frameworks */, - 5CE0E8AF2BF0C1B5008D6E06 /* libgmpxx.a in Frameworks */, + 5CE0E8B82BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -601,11 +601,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5CE0E8A92BF0C1B5008D6E06 /* libffi.a */, - 5CE0E8A82BF0C1B5008D6E06 /* libgmp.a */, - 5CE0E8AA2BF0C1B5008D6E06 /* libgmpxx.a */, - 5CE0E8A62BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg-ghc9.6.3.a */, - 5CE0E8A72BF0C1B5008D6E06 /* libHSsimplex-chat-5.7.3.0-BQ0iWJUV1AuAQdR2Nu1hMg.a */, + 5CE0E8B42BF2B9ED008D6E06 /* libffi.a */, + 5CE0E8B02BF2B9ED008D6E06 /* libgmp.a */, + 5CE0E8B12BF2B9ED008D6E06 /* libgmpxx.a */, + 5CE0E8B22BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9-ghc9.6.3.a */, + 5CE0E8B32BF2B9ED008D6E06 /* libHSsimplex-chat-5.8.0.0-4rkacYU1Nfn5xrDMCOexv9.a */, ); path = Libraries; sourceTree = ""; From e359ec02f533335e44c3847431d33936a19e15b0 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Mon, 13 May 2024 23:34:14 +0100 Subject: [PATCH 7/7] 5.8-beta.0: ios 216, android 208, desktop 45 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 24 +++++++++++----------- apps/multiplatform/gradle.properties | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 3ad4ca426b..3957e3c8fd 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -1552,7 +1552,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1577,7 +1577,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES_THIN; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1601,7 +1601,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1626,7 +1626,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1687,7 +1687,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -1702,7 +1702,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1724,7 +1724,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -1739,7 +1739,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1761,7 +1761,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1787,7 +1787,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -1812,7 +1812,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 215; + CURRENT_PROJECT_VERSION = 216; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1838,7 +1838,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.7.3; + MARKETING_VERSION = 5.8; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index fcbf8b9d9e..69097e29e0 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -26,11 +26,11 @@ android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.jvm.target=11 -android.version_name=5.7.3 -android.version_code=206 +android.version_name=5.8-beta.0 +android.version_code=208 -desktop.version_name=5.7.3 -desktop.version_code=44 +desktop.version_name=5.8-beta.0 +desktop.version_code=45 kotlin.version=1.9.23 gradle.plugin.version=8.2.0