// // Copyright (c) 2021 Open Whisper Systems. All rights reserved. // import Foundation import PromiseKit @objc public protocol CameraFirstCaptureDelegate: AnyObject { func cameraFirstCaptureSendFlowDidComplete(_ cameraFirstCaptureSendFlow: CameraFirstCaptureSendFlow) func cameraFirstCaptureSendFlowDidCancel(_ cameraFirstCaptureSendFlow: CameraFirstCaptureSendFlow) } @objc public class CameraFirstCaptureSendFlow: NSObject { @objc public weak var delegate: CameraFirstCaptureDelegate? var approvedAttachments: [SignalAttachment]? var approvalMessageBody: MessageBody? var selectedConversations: [ConversationItem] = [] } extension CameraFirstCaptureSendFlow: SendMediaNavDelegate { func sendMediaNavDidCancel(_ sendMediaNavigationController: SendMediaNavigationController) { delegate?.cameraFirstCaptureSendFlowDidCancel(self) } func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didApproveAttachments attachments: [SignalAttachment], messageBody: MessageBody?) { self.approvedAttachments = attachments self.approvalMessageBody = messageBody let pickerVC = ConversationPickerViewController() pickerVC.delegate = self sendMediaNavigationController.pushViewController(pickerVC, animated: true) } func sendMediaNavInitialMessageBody(_ sendMediaNavigationController: SendMediaNavigationController) -> MessageBody? { return approvalMessageBody } func sendMediaNav(_ sendMediaNavigationController: SendMediaNavigationController, didChangeMessageBody newMessageBody: MessageBody?) { self.approvalMessageBody = newMessageBody } var sendMediaNavApprovalButtonImageName: String { return "arrow-right-24" } var sendMediaNavCanSaveAttachments: Bool { return true } var sendMediaNavTextInputContextIdentifier: String? { return nil } var sendMediaNavRecipientNames: [String] { return selectedConversations.map { $0.title } } var sendMediaNavMentionableAddresses: [SignalServiceAddress] { guard selectedConversations.count == 1, case .group(let groupThreadId) = selectedConversations.first?.messageRecipient, let groupThread = SDSDatabaseStorage.shared.uiRead(block: { transaction in return TSGroupThread.anyFetchGroupThread(uniqueId: groupThreadId, transaction: transaction) }), Mention.threadAllowsMentionSend(groupThread) else { return [] } return groupThread.recipientAddresses } } extension CameraFirstCaptureSendFlow: ConversationPickerDelegate { public var selectedConversationsForConversationPicker: [ConversationItem] { return selectedConversations } public func conversationPicker(_ conversationPickerViewController: ConversationPickerViewController, didSelectConversation conversation: ConversationItem) { self.selectedConversations.append(conversation) } public func conversationPicker(_ conversationPickerViewController: ConversationPickerViewController, didDeselectConversation conversation: ConversationItem) { self.selectedConversations = self.selectedConversations.filter { $0.messageRecipient != conversation.messageRecipient } } public func conversationPickerDidCompleteSelection(_ conversationPickerViewController: ConversationPickerViewController) { guard let approvedAttachments = self.approvedAttachments else { owsFailDebug("approvedAttachments was unexpectedly nil") delegate?.cameraFirstCaptureSendFlowDidCancel(self) return } let conversations = selectedConversationsForConversationPicker firstly { AttachmentMultisend.sendApprovedMedia(conversations: conversations, approvalMessageBody: self.approvalMessageBody, approvedAttachments: approvedAttachments) }.done { _ in self.delegate?.cameraFirstCaptureSendFlowDidComplete(self) }.catch { error in owsFailDebug("Error: \(error)") } } public func conversationPickerCanCancel(_ conversationPickerViewController: ConversationPickerViewController) -> Bool { return false } public func conversationPickerDidCancel(_ conversationPickerViewController: ConversationPickerViewController) { owsFailDebug("Camera-first capture flow should never cancel conversation picker.") } public func approvalMode(_ conversationPickerViewController: ConversationPickerViewController) -> ApprovalMode { return .send } }