From 1b01dcec6da9f5058a03b5eb91d325d1f7aa6c7d Mon Sep 17 00:00:00 2001 From: JRoberts <8711996+jr-simplex@users.noreply.github.com> Date: Mon, 23 Jan 2023 19:55:19 +0400 Subject: [PATCH 1/3] core: fix inline file transfer - optional connection ids in RcvFileInfo, update rcv_file_inline on accept (#1823) * core: optional connection id in RcvFileInfo * query * check snd cancel * Revert "check snd cancel" This reverts commit f16651345d92dba3ab00fb84ce79f5ef065feb59. * update rcv_file_inline --- src/Simplex/Chat.hs | 6 +++--- src/Simplex/Chat/Store.hs | 38 +++++++++++++++----------------------- src/Simplex/Chat/Types.hs | 7 ++++--- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 524d05ac8..87709e38d 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -2545,7 +2545,7 @@ processAgentMessage (Just user@User {userId}) corrId agentConnId agentMessage = (filePath, fileStatus) <- case inline of Just IFMSent -> do fPath <- getRcvFilePath fileId Nothing fileName - withStore' $ \db -> startRcvInlineFT db user ft fPath + withStore' $ \db -> startRcvInlineFT db user ft fPath inline pure (Just fPath, CIFSRcvAccepted) _ -> pure (Nothing, CIFSRcvInvitation) pure CIFile {fileId, fileName, fileSize, filePath, fileStatus} @@ -3291,9 +3291,9 @@ cancelRcvFileTransfer user ft@RcvFileTransfer {fileId, fileStatus, rcvFileInline updateRcvFileStatus db ft FSCancelled deleteRcvFileChunks db ft when (isNothing rcvFileInline) $ case fileStatus of - RFSAccepted RcvFileInfo {connId, agentConnId} -> + RFSAccepted RcvFileInfo {connId = Just connId, agentConnId = Just agentConnId} -> deleteAgentConnectionAsync' user connId agentConnId - RFSConnected RcvFileInfo {connId, agentConnId} -> + RFSConnected RcvFileInfo {connId = Just connId, agentConnId = Just agentConnId} -> deleteAgentConnectionAsync' user connId agentConnId _ -> pure () diff --git a/src/Simplex/Chat/Store.hs b/src/Simplex/Chat/Store.hs index fd5e27b77..3787c40f6 100644 --- a/src/Simplex/Chat/Store.hs +++ b/src/Simplex/Chat/Store.hs @@ -2743,14 +2743,14 @@ createRcvGroupFileTransfer db userId GroupMember {groupId, groupMemberId, localD pure RcvFileTransfer {fileId, fileInvitation = f, fileStatus = RFSNew, rcvFileInline, senderDisplayName = c, chunkSize, cancelled = False, grpMemberId = Just groupMemberId} getRcvFileTransfer :: DB.Connection -> User -> Int64 -> ExceptT StoreError IO RcvFileTransfer -getRcvFileTransfer db user@User {userId} fileId = do +getRcvFileTransfer db User {userId} fileId = do rftRow <- ExceptT . firstRow id (SERcvFileNotFound fileId) $ DB.query db [sql| SELECT r.file_status, r.file_queue_info, r.group_member_id, f.file_name, - f.file_size, f.chunk_size, f.cancelled, cs.contact_id, cs.local_display_name, m.group_id, m.group_member_id, m.local_display_name, + f.file_size, f.chunk_size, f.cancelled, cs.local_display_name, m.local_display_name, f.file_path, r.file_inline, r.rcv_file_inline, c.connection_id, c.agent_conn_id FROM rcv_files r JOIN files f USING (file_id) @@ -2763,11 +2763,11 @@ getRcvFileTransfer db user@User {userId} fileId = do rcvFileTransfer rftRow where rcvFileTransfer :: - (FileStatus, Maybe ConnReqInvitation, Maybe Int64, String, Integer, Integer, Maybe Bool) :. (Maybe Int64, Maybe ContactName, Maybe Int64, Maybe Int64, Maybe ContactName, Maybe FilePath, Maybe InlineFileMode, Maybe InlineFileMode) :. (Maybe Int64, Maybe AgentConnId) -> + (FileStatus, Maybe ConnReqInvitation, Maybe Int64, String, Integer, Integer, Maybe Bool) :. (Maybe ContactName, Maybe ContactName, Maybe FilePath, Maybe InlineFileMode, Maybe InlineFileMode) :. (Maybe Int64, Maybe AgentConnId) -> ExceptT StoreError IO RcvFileTransfer - rcvFileTransfer ((fileStatus', fileConnReq, grpMemberId, fileName, fileSize, chunkSize, cancelled_) :. (contactId_, contactName_, groupId_, groupMemberId_, memberName_, filePath_, fileInline, rcvFileInline) :. (connId_, agentConnId_)) = do + rcvFileTransfer ((fileStatus', fileConnReq, grpMemberId, fileName, fileSize, chunkSize, cancelled_) :. (contactName_, memberName_, filePath_, fileInline, rcvFileInline) :. (connId_, agentConnId_)) = do let fileInv = FileInvitation {fileName, fileSize, fileConnReq, fileInline} - fileInfo = (filePath_, connId_, agentConnId_, contactId_, groupId_, groupMemberId_, isJust fileInline) + fileInfo = (filePath_, connId_, agentConnId_) case contactName_ <|> memberName_ of Nothing -> throwError $ SERcvFileInvalid fileId Just name -> do @@ -2782,22 +2782,14 @@ getRcvFileTransfer db user@User {userId} fileId = do RcvFileTransfer {fileId, fileInvitation, fileStatus, rcvFileInline, senderDisplayName, chunkSize, cancelled, grpMemberId} rfi fileInfo = maybe (throwError $ SERcvFileInvalid fileId) pure =<< rfi_ fileInfo rfi_ = \case - (Just filePath, Just connId, Just agentConnId, _, _, _, _) -> pure $ Just RcvFileInfo {filePath, connId, agentConnId} - (Just filePath, Nothing, Nothing, Just contactId, _, _, True) -> do - Contact {activeConn = Connection {connId, agentConnId}} <- getContact db user contactId - pure $ Just RcvFileInfo {filePath, connId, agentConnId} - (Just filePath, Nothing, Nothing, _, Just groupId, Just groupMemberId, True) -> do - getGroupMember db user groupId groupMemberId >>= \case - GroupMember {activeConn = Just Connection {connId, agentConnId}} -> - pure $ Just RcvFileInfo {filePath, connId, agentConnId} - _ -> pure Nothing + (Just filePath, connId, agentConnId) -> pure $ Just RcvFileInfo {filePath, connId, agentConnId} _ -> pure Nothing cancelled = fromMaybe False cancelled_ acceptRcvFileTransfer :: DB.Connection -> User -> Int64 -> (CommandId, ConnId) -> ConnStatus -> FilePath -> ExceptT StoreError IO AChatItem acceptRcvFileTransfer db user@User {userId} fileId (cmdId, acId) connStatus filePath = ExceptT $ do currentTs <- getCurrentTime - acceptRcvFT_ db user fileId filePath currentTs + acceptRcvFT_ db user fileId filePath Nothing currentTs DB.execute db "INSERT INTO connections (agent_conn_id, conn_status, conn_type, rcv_file_id, user_id, created_at, updated_at) VALUES (?,?,?,?,?,?,?)" @@ -2817,23 +2809,23 @@ getContactByFileId db user@User {userId} fileId = do acceptRcvInlineFT :: DB.Connection -> User -> Int64 -> FilePath -> ExceptT StoreError IO AChatItem acceptRcvInlineFT db user fileId filePath = do - liftIO $ acceptRcvFT_ db user fileId filePath =<< getCurrentTime + liftIO $ acceptRcvFT_ db user fileId filePath (Just IFMOffer) =<< getCurrentTime getChatItemByFileId db user fileId -startRcvInlineFT :: DB.Connection -> User -> RcvFileTransfer -> FilePath -> IO () -startRcvInlineFT db user RcvFileTransfer {fileId} filePath = - acceptRcvFT_ db user fileId filePath =<< getCurrentTime +startRcvInlineFT :: DB.Connection -> User -> RcvFileTransfer -> FilePath -> Maybe InlineFileMode -> IO () +startRcvInlineFT db user RcvFileTransfer {fileId} filePath rcvFileInline = + acceptRcvFT_ db user fileId filePath rcvFileInline =<< getCurrentTime -acceptRcvFT_ :: DB.Connection -> User -> Int64 -> FilePath -> UTCTime -> IO () -acceptRcvFT_ db User {userId} fileId filePath currentTs = do +acceptRcvFT_ :: DB.Connection -> User -> Int64 -> FilePath -> Maybe InlineFileMode -> UTCTime -> IO () +acceptRcvFT_ db User {userId} fileId filePath rcvFileInline currentTs = do DB.execute db "UPDATE files SET file_path = ?, ci_file_status = ?, updated_at = ? WHERE user_id = ? AND file_id = ?" (filePath, CIFSRcvAccepted, currentTs, userId, fileId) DB.execute db - "UPDATE rcv_files SET file_status = ?, updated_at = ? WHERE file_id = ?" - (FSAccepted, currentTs, fileId) + "UPDATE rcv_files SET rcv_file_inline = ?, file_status = ?, updated_at = ? WHERE file_id = ?" + (rcvFileInline, FSAccepted, currentTs, fileId) updateRcvFileStatus :: DB.Connection -> RcvFileTransfer -> FileStatus -> IO () updateRcvFileStatus db RcvFileTransfer {fileId} status = do diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index bf884b7fa..2fc46aa11 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -1481,8 +1481,8 @@ instance ToJSON RcvFileStatus where data RcvFileInfo = RcvFileInfo { filePath :: FilePath, - connId :: Int64, - agentConnId :: AgentConnId + connId :: Maybe Int64, + agentConnId :: Maybe AgentConnId } deriving (Eq, Show, Generic) @@ -1494,7 +1494,8 @@ liveRcvFileTransferConnId RcvFileTransfer {fileStatus} = case fileStatus of RFSConnected fi -> acId fi _ -> Nothing where - acId RcvFileInfo {agentConnId = AgentConnId cId} = Just cId + acId RcvFileInfo {agentConnId = Just (AgentConnId cId)} = Just cId + acId _ = Nothing newtype AgentConnId = AgentConnId ConnId deriving (Eq, Show) From 3bc4fd222c15618f323dabec20ba890d7ab322d1 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Mon, 23 Jan 2023 17:17:42 +0000 Subject: [PATCH 2/3] core: fix cancelling sending inline files (#1826) * core: fix cancelling sending inline files * add comments * typos Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> --- src/Simplex/Chat.hs | 4 ++-- src/Simplex/Chat/Migrations/M20221012_inline_files.hs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 87709e38d..fc948314a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -3303,13 +3303,13 @@ cancelSndFile user FileTransferMeta {fileId} fts = do forM_ fts $ \ft' -> cancelSndFileTransfer user ft' cancelSndFileTransfer :: ChatMonad m => User -> SndFileTransfer -> m () -cancelSndFileTransfer user ft@SndFileTransfer {connId, agentConnId = agentConnId@(AgentConnId acId), fileStatus} = +cancelSndFileTransfer user ft@SndFileTransfer {connId, agentConnId = agentConnId@(AgentConnId acId), fileStatus, fileInline} = unless (fileStatus == FSCancelled || fileStatus == FSComplete) $ do withStore' $ \db -> do updateSndFileStatus db ft FSCancelled deleteSndFileChunks db ft withAgent $ \a -> void (sendMessage a acId SMP.noMsgFlags $ smpEncode FileChunkCancel) `catchError` \_ -> pure () - deleteAgentConnectionAsync' user connId agentConnId + when (isNothing fileInline) $ deleteAgentConnectionAsync' user connId agentConnId closeFileHandle :: ChatMonad m => Int64 -> (ChatController -> TVar (Map Int64 Handle)) -> m () closeFileHandle fileId files = do diff --git a/src/Simplex/Chat/Migrations/M20221012_inline_files.hs b/src/Simplex/Chat/Migrations/M20221012_inline_files.hs index 51133d6b6..4b069f088 100644 --- a/src/Simplex/Chat/Migrations/M20221012_inline_files.hs +++ b/src/Simplex/Chat/Migrations/M20221012_inline_files.hs @@ -10,10 +10,10 @@ m20221012_inline_files = [sql| DROP INDEX idx_messages_direct_shared_msg_id; -ALTER TABLE files ADD COLUMN file_inline TEXT; -ALTER TABLE rcv_files ADD COLUMN rcv_file_inline TEXT; -ALTER TABLE rcv_files ADD COLUMN file_inline TEXT; -ALTER TABLE snd_files ADD COLUMN file_inline TEXT; +ALTER TABLE files ADD COLUMN file_inline TEXT; -- based on offer, determined by file sender for both sides +ALTER TABLE rcv_files ADD COLUMN rcv_file_inline TEXT; -- actual mode when receiving file, determined when invitation is accepted +ALTER TABLE rcv_files ADD COLUMN file_inline TEXT; -- based on offer, determined when invitation is processed +ALTER TABLE snd_files ADD COLUMN file_inline TEXT; -- actual mode when sending file, determined when invitation is accepted ALTER TABLE snd_files ADD COLUMN last_inline_msg_delivery_id INTEGER; CREATE UNIQUE INDEX idx_snd_files_last_inline_msg_delivery_id ON snd_files(last_inline_msg_delivery_id); From a393bc8163f82612c4e8e4617ebd4182b63d16cc Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Mon, 23 Jan 2023 18:17:33 +0000 Subject: [PATCH 3/3] ios: Testing workaround of a crash (#1789) * ios: Testing workaround of a crash * another try * complete * added file * enable swipe to go back from ChatView * Revert "enable swipe to go back from ChatView" This reverts commit 22de79505c19fd89c593610d04067ff0c8e1e622. * refactor Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- apps/ios/Shared/Views/Chat/ChatView.swift | 4 ++ .../Shared/Views/ChatList/ChatListView.swift | 18 +++----- .../Shared/Views/Helpers/NavStackCompat.swift | 43 +++++++++++++++++++ apps/ios/SimpleX.xcodeproj/project.pbxproj | 4 ++ 4 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 apps/ios/Shared/Views/Helpers/NavStackCompat.swift diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index fd94e96a3..68ab7c191 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -15,6 +15,7 @@ private let memberImageSize: CGFloat = 34 struct ChatView: View { @EnvironmentObject var chatModel: ChatModel @Environment(\.colorScheme) var colorScheme + @Environment(\.dismiss) var dismiss @State @ObservedObject var chat: Chat @State private var showChatInfoSheet: Bool = false @State private var showAddMembersSheet: Bool = false @@ -70,6 +71,9 @@ struct ChatView: View { } } } + .onChange(of: chatModel.chatId) { _ in + if chatModel.chatId == nil { dismiss() } + } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { diff --git a/apps/ios/Shared/Views/ChatList/ChatListView.swift b/apps/ios/Shared/Views/ChatList/ChatListView.swift index f35bb32aa..4b66f53d9 100644 --- a/apps/ios/Shared/Views/ChatList/ChatListView.swift +++ b/apps/ios/Shared/Views/ChatList/ChatListView.swift @@ -17,7 +17,13 @@ struct ChatListView: View { @State private var showAddChat = false var body: some View { - NavigationView { + NavStackCompat( + isActive: Binding( + get: { ChatModel.shared.chatId != nil }, + set: { _ in } + ), + destination: chatView + ) { VStack { if chatModel.chats.isEmpty { onboardingButtons() @@ -29,7 +35,6 @@ struct ChatListView: View { } } } - .navigationViewStyle(.stack) } var chatList: some View { @@ -75,15 +80,6 @@ struct ChatListView: View { } } } - .background( - NavigationLink( - destination: chatView(), - isActive: Binding( - get: { chatModel.chatId != nil }, - set: { _ in } - ) - ) { EmptyView() } - ) } private func onboardingButtons() -> some View { diff --git a/apps/ios/Shared/Views/Helpers/NavStackCompat.swift b/apps/ios/Shared/Views/Helpers/NavStackCompat.swift new file mode 100644 index 000000000..6e3b89c9b --- /dev/null +++ b/apps/ios/Shared/Views/Helpers/NavStackCompat.swift @@ -0,0 +1,43 @@ +// +// NavStackCompat.swift +// SimpleX (iOS) +// +// Created by Evgeny on 23/01/2023. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI + +struct NavStackCompat : View { + let isActive: Binding + let destination: () -> D + let content: () -> C + + var body: some View { + if #available(iOS 16, *) { + NavigationStack(path: Binding( + get: { isActive.wrappedValue ? [true] : [] }, + set: { _ in } + )) { + ZStack { + NavigationLink(value: true) { EmptyView() } + content() + } + .navigationDestination(for: Bool.self) { show in + if show { destination() } + } + } + } else { + NavigationView { + ZStack { + NavigationLink( + destination: destination(), + isActive: isActive + ) { EmptyView() } + content() + } + } + .navigationViewStyle(.stack) + } + } +} diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index ef7898ce0..158c3e8ce 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -110,6 +110,7 @@ 5CC2C0FC2809BF11000C35E3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FA2809BF11000C35E3 /* Localizable.strings */; }; 5CC2C0FF2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5CC2C0FD2809BF11000C35E3 /* SimpleX--iOS--InfoPlist.strings */; }; 5CCA7DF32905735700C8FEBA /* AcceptRequestsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */; }; + 5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */; }; 5CCD403427A5F6DF00368C90 /* AddContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403327A5F6DF00368C90 /* AddContactView.swift */; }; 5CCD403727A5F9A200368C90 /* ScanToConnectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */; }; 5CDCAD482818589900503DA2 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDCAD472818589900503DA2 /* NotificationService.swift */; }; @@ -341,6 +342,7 @@ 5CC2C0FB2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; 5CC2C0FE2809BF11000C35E3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = "ru.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = ""; }; 5CCA7DF22905735700C8FEBA /* AcceptRequestsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcceptRequestsView.swift; sourceTree = ""; }; + 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavStackCompat.swift; sourceTree = ""; }; 5CCD403327A5F6DF00368C90 /* AddContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactView.swift; sourceTree = ""; }; 5CCD403627A5F9A200368C90 /* ScanToConnectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanToConnectView.swift; sourceTree = ""; }; 5CDCAD452818589900503DA2 /* SimpleX NSE.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "SimpleX NSE.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -538,6 +540,7 @@ 5C6BA666289BD954009B8ECC /* DismissSheets.swift */, 5C00164328A26FBC0094D739 /* ContextMenu.swift */, 5CA7DFC229302AF000F7FDDE /* AppSheet.swift */, + 5CCB939B297EFCB100399E78 /* NavStackCompat.swift */, ); path = Helpers; sourceTree = ""; @@ -1051,6 +1054,7 @@ 5CB346E52868AA7F001FD2EF /* SuspendChat.swift in Sources */, 5C9C2DA52894777E00CC63B1 /* GroupProfileView.swift in Sources */, 5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */, + 5CCB939C297EFCB100399E78 /* NavStackCompat.swift in Sources */, 5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */, 5C971E1D27AEBEF600C8A3CE /* ChatInfoView.swift in Sources */, 5CBD285C29575B8E00EC2CF4 /* WhatsNewView.swift in Sources */,