瀏覽代碼

initial message forwarding implementation (#390)

cyberta 5 年之前
父節點
當前提交
fbbb72c37c

+ 6 - 2
deltachat-ios.xcodeproj/project.pbxproj

@@ -12,6 +12,8 @@
 		30149D9322F21129003C12B5 /* QrViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30149D9222F21129003C12B5 /* QrViewController.swift */; };
 		3022E6BE22E8768800763272 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3022E6C022E8768800763272 /* InfoPlist.strings */; };
 		30260CA7238F02F700D8D52C /* MultilineTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30260CA6238F02F700D8D52C /* MultilineTextFieldCell.swift */; };
+		302B84C6239676F0001C261F /* AvatarHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AC265E237F1807002A943F /* AvatarHelper.swift */; };
+		302B84C72396770B001C261F /* RelayHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302B84C42396627F001C261F /* RelayHelper.swift */; };
 		3040F45E234DFBC000FA34D5 /* Audio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3040F45D234DFBC000FA34D5 /* Audio.swift */; };
 		3040F460234F419400FA34D5 /* BasicAudioController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3040F45F234F419300FA34D5 /* BasicAudioController.swift */; };
 		3040F462234F550300FA34D5 /* AudioPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3040F461234F550300FA34D5 /* AudioPlayerView.swift */; };
@@ -84,7 +86,6 @@
 		306011B622E5E7FB00C1CE6F /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 306011B422E5E7FB00C1CE6F /* Localizable.stringsdict */; };
 		3095A351237DD1F700AB07F7 /* MediaPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3095A350237DD1F700AB07F7 /* MediaPicker.swift */; };
 		30A4D9AE2332672700544344 /* QrInviteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A4D9AD2332672600544344 /* QrInviteViewController.swift */; };
-		30AC265F237F1807002A943F /* AvatarHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AC265E237F1807002A943F /* AvatarHelper.swift */; };
 		30C0D49D237C4908008E2A0E /* CertificateCheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C0D49C237C4908008E2A0E /* CertificateCheckController.swift */; };
 		30F9B9EC235F2116006E7ACF /* MessageCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F9B9EB235F2116006E7ACF /* MessageCounter.swift */; };
 		6795F63A82E94FF7CD2CEC0F /* Pods_deltachat_iosTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F7009234DB9408201A6CDCB /* Pods_deltachat_iosTests.framework */; };
@@ -183,6 +184,7 @@
 		3022E6D222E8769F00763272 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		3022E6D322E876A100763272 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		30260CA6238F02F700D8D52C /* MultilineTextFieldCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineTextFieldCell.swift; sourceTree = "<group>"; };
+		302B84C42396627F001C261F /* RelayHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayHelper.swift; sourceTree = "<group>"; };
 		3040F45D234DFBC000FA34D5 /* Audio.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Audio.swift; sourceTree = "<group>"; };
 		3040F45F234F419300FA34D5 /* BasicAudioController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicAudioController.swift; sourceTree = "<group>"; };
 		3040F461234F550300FA34D5 /* AudioPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerView.swift; sourceTree = "<group>"; };
@@ -698,6 +700,7 @@
 				AE851AC4227C755A00ED86F0 /* Protocols.swift */,
 				3095A350237DD1F700AB07F7 /* MediaPicker.swift */,
 				30AC265E237F1807002A943F /* AvatarHelper.swift */,
+				302B84C42396627F001C261F /* RelayHelper.swift */,
 			);
 			path = Helper;
 			sourceTree = "<group>";
@@ -1058,12 +1061,12 @@
 				305961ED2346125100C80F33 /* DetectorType.swift in Sources */,
 				305962062346125100C80F33 /* TypingIndicatorCellSizeCalculator.swift in Sources */,
 				AE851AC7227C776400ED86F0 /* Location.swift in Sources */,
-				30AC265F237F1807002A943F /* AvatarHelper.swift in Sources */,
 				7AE0A5491FC42F65005ECB4B /* NewChatViewController.swift in Sources */,
 				305961E52346125100C80F33 /* LabelAlignment.swift in Sources */,
 				305961E82346125100C80F33 /* Sender.swift in Sources */,
 				305961EE2346125100C80F33 /* AvatarPosition.swift in Sources */,
 				AE25F09022807AD800CDEA66 /* AvatarSelectionCell.swift in Sources */,
+				302B84C6239676F0001C261F /* AvatarHelper.swift in Sources */,
 				305961E62346125100C80F33 /* LocationMessageSnapshotOptions.swift in Sources */,
 				AEE6EC3F2282C59C00EDC689 /* GroupMembersViewController.swift in Sources */,
 				B26B3BC7236DC3DC008ED35A /* SwitchCell.swift in Sources */,
@@ -1092,6 +1095,7 @@
 				3059620C2346125100C80F33 /* MessageSizeCalculator.swift in Sources */,
 				305962042346125100C80F33 /* MessagesCollectionViewLayoutAttributes.swift in Sources */,
 				305961D02346125100C80F33 /* NSAttributedString+Extensions.swift in Sources */,
+				302B84C72396770B001C261F /* RelayHelper.swift in Sources */,
 				305961CF2346125100C80F33 /* UIColor+Extensions.swift in Sources */,
 				AEACE2E51FB32E1900DCDD78 /* Utils.swift in Sources */,
 				300C509D234B551900F8AE22 /* TextMediaMessageCell.swift in Sources */,

+ 2 - 0
deltachat-ios/AppDelegate.swift

@@ -19,6 +19,7 @@ enum ApplicationState {
 class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
     private let dcContext = DcContext()
     var appCoordinator: AppCoordinator!
+    var relayHelper: RelayHelper!
     // static let appCoordinatorDeprecated = AppCoordinatorDeprecated()
     static var progress: Float = 0 // TODO: delete
     static var lastErrorString: String?
@@ -77,6 +78,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
         open()
         appCoordinator = AppCoordinator(window: window, dcContext: dcContext)
         appCoordinator.start()
+        RelayHelper.setup(dcContext)
         UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
         start()
         setStockTranslations()

+ 61 - 26
deltachat-ios/Controller/ChatViewController.swift

@@ -150,6 +150,10 @@ class ChatViewController: MessagesViewController {
                 }
             }
         }
+
+        if RelayHelper.sharedInstance.isForwarding() {
+            askToForwardMessage()
+        }
     }
 
     override func viewDidAppear(_ animated: Bool) {
@@ -267,7 +271,8 @@ class ChatViewController: MessagesViewController {
 
         menuItems = [
             UIMenuItem(title: String.localized("info"), action: #selector(MessageCollectionViewCell.messageInfo(_:))),
-            UIMenuItem(title: String.localized("delete"), action: #selector(MessageCollectionViewCell.messageDelete(_:)))
+            UIMenuItem(title: String.localized("delete"), action: #selector(MessageCollectionViewCell.messageDelete(_:))),
+            UIMenuItem(title: String.localized("menu_forward"), action: #selector(MessageCollectionViewCell.messageForward(_:)))
         ]
 
         UIMenuController.shared.menuItems = menuItems
@@ -433,7 +438,8 @@ class ChatViewController: MessagesViewController {
 
     override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
         if action == NSSelectorFromString("messageInfo:") ||
-            action == NSSelectorFromString("messageDelete:") {
+            action == NSSelectorFromString("messageDelete:") ||
+            action == NSSelectorFromString("messageForward:") {
             return true
         } else {
             return super.collectionView(collectionView, canPerformAction: action, forItemAt: indexPath, withSender: sender)
@@ -454,39 +460,55 @@ class ChatViewController: MessagesViewController {
             let msg = messageList[indexPath.section]
             logger.info("message: delete \(msg.messageId)")
             askToDeleteMessage(id: msg.id)
+
+        case NSSelectorFromString("messageForward:"):
+            let msg = messageList[indexPath.section]
+            RelayHelper.sharedInstance.setForwardMessage(messageId: msg.id)
+            coordinator?.navigateBack()
         default:
             super.collectionView(collectionView, performAction: action, forItemAt: indexPath, withSender: sender)
         }
     }
 
+    private func confirmationAlert(title: String, actionTitle: String, actionStyle: UIAlertAction.Style = .default, actionHandler: @escaping ((UIAlertAction) -> Void), cancelHandler: ((UIAlertAction) -> Void)? = nil) {
+        let alert = UIAlertController(title: title,
+                                             message: nil,
+                                             preferredStyle: .actionSheet)
+               alert.addAction(UIAlertAction(title: actionTitle, style: actionStyle, handler: actionHandler))
+
+               alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: cancelHandler ?? { _ in
+                   self.dismiss(animated: true, completion: nil)
+               }))
+               present(alert, animated: true, completion: nil)
+    }
+
     private func askToChatWith(email: String) {
-        let alert = UIAlertController(title: String.localizedStringWithFormat(String.localized("ask_start_chat_with"), email),
-                                      message: nil,
-                                      preferredStyle: .actionSheet)
-        alert.addAction(UIAlertAction(title: String.localized("start_chat"), style: .default, handler: { _ in
-            self.dismiss(animated: true, completion: nil)
-            let contactId = self.dcContext.createContact(name: "", email: email)
-            let chatId = self.dcContext.createChat(contactId: contactId)
-            self.coordinator?.showChat(chatId: chatId)
-        }))
-        alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: { _ in
-            self.dismiss(animated: true, completion: nil)
-        }))
-        present(alert, animated: true, completion: nil)
+        confirmationAlert(title: String.localizedStringWithFormat(String.localized("ask_start_chat_with"), email),
+                          actionTitle: String.localized("start_chat"),
+                          actionHandler: { _ in
+                            self.dismiss(animated: true, completion: nil)
+                            let contactId = self.dcContext.createContact(name: "", email: email)
+                            let chatId = self.dcContext.createChat(contactId: contactId)
+                            self.coordinator?.showChat(chatId: chatId)})
     }
 
     private func askToDeleteMessage(id: Int) {
-        let alert = UIAlertController(title: String.localizedStringWithFormat(String.localized("ask_delete_messages"), 1),
-                                         message: nil,
-                                         preferredStyle: .actionSheet)
-        alert.addAction(UIAlertAction(title: String.localized("delete"), style: .destructive, handler: { _ in
-            self.dcContext.deleteMessage(msgId: id)
-            self.dismiss(animated: true, completion: nil)
-        }))
-        alert.addAction(UIAlertAction(title: String.localized("cancel"), style: .cancel, handler: { _ in
-            self.dismiss(animated: true, completion: nil)
-        }))
-        present(alert, animated: true, completion: nil)
+        confirmationAlert(title: String.localized("delete"), actionTitle: String.localized("delete"), actionStyle: .destructive,
+                          actionHandler: { _ in
+                            self.dcContext.deleteMessage(msgId: id)
+                            self.dismiss(animated: true, completion: nil)})
+    }
+
+    private func askToForwardMessage() {
+        let chat = DcChat(id: self.chatId)
+        confirmationAlert(title: String.localizedStringWithFormat(String.localized("ask_forward"), chat.name),
+                          actionTitle: String.localized("menu_forward"),
+                          actionHandler: { _ in
+                            RelayHelper.sharedInstance.forward(to: self.chatId)
+                            self.dismiss(animated: true, completion: nil)},
+                          cancelHandler: { _ in
+                            RelayHelper.sharedInstance.cancel()
+                            self.dismiss(animated: true, completion: nil)})
     }
 }
 
@@ -1088,6 +1110,19 @@ extension ChatViewController: InputBarAccessoryViewDelegate {
 // MARK: - MessageCollectionViewCell
 extension MessageCollectionViewCell {
 
+    @objc func messageForward(_ sender: Any?) {
+        // Get the collectionView
+       if let collectionView = self.superview as? UICollectionView {
+           // Get indexPath
+           if let indexPath = collectionView.indexPath(for: self) {
+               // Trigger action
+               collectionView.delegate?.collectionView?(collectionView,
+                   performAction: #selector(MessageCollectionViewCell.messageForward(_:)),
+                   forItemAt: indexPath, withSender: sender)
+            }
+        }
+    }
+
 
     @objc func messageDelete(_ sender: Any?) {
         // Get the collectionView

+ 4 - 0
deltachat-ios/Coordinator/AppCoordinator.swift

@@ -396,6 +396,10 @@ class ChatViewCoordinator: NSObject, Coordinator {
         self.chatId = chatId
     }
 
+    func navigateBack() {
+        navigationController.popViewController(animated: true)
+    }
+
     func showChatDetail(chatId: Int) {
         let chat = DcChat(id: chatId)
         switch chat.chatType {

+ 4 - 0
deltachat-ios/DC/Wrapper.swift

@@ -87,6 +87,10 @@ class DcContext {
         dc_delete_msgs(contextPointer, [UInt32(msgId)], 1)
     }
 
+    func forwardMessage(with msgId: Int, to chat: Int) {
+        dc_forward_msgs(contextPointer, [UInt32(msgId)], 1, UInt32(chat))
+    }
+
     func initiateKeyTransfer() -> String? {
         if let cString = dc_initiate_key_transfer(self.contextPointer) {
             let swiftString = String(cString: cString)

+ 36 - 0
deltachat-ios/Helper/RelayHelper.swift

@@ -0,0 +1,36 @@
+import Foundation
+
+class RelayHelper {
+    static var sharedInstance: RelayHelper = RelayHelper()
+    private static var dcContext: DcContext?
+    var messageId: Int?
+
+    private init() {
+        guard RelayHelper.dcContext != nil else {
+            fatalError("Error - you must call setContext before accessing RelayHelper.shared")
+        }
+    }
+
+    class func setup(_ dcContext: DcContext) {
+        RelayHelper.dcContext = dcContext
+    }
+
+    func setForwardMessage(messageId: Int) {
+        self.messageId = messageId
+    }
+
+    func isForwarding() -> Bool {
+        return messageId != nil
+    }
+
+    func forward(to chat: Int) {
+        if let messageId = self.messageId {
+            RelayHelper.dcContext?.forwardMessage(with: messageId, to: chat)
+        }
+        self.messageId = nil
+    }
+
+    func cancel() {
+        messageId = nil
+    }
+}