diff --git a/deltachat-ios/Chat/ChatViewController.swift b/deltachat-ios/Chat/ChatViewController.swift index 1f73c0ea7..e36e6efa8 100644 --- a/deltachat-ios/Chat/ChatViewController.swift +++ b/deltachat-ios/Chat/ChatViewController.swift @@ -307,6 +307,10 @@ class ChatViewController: UITableViewController, UITableViewDropDelegate { if RelayHelper.shared.isForwarding() { if RelayHelper.shared.forwardIds != nil { askToForwardMessage() + } else if let vcardData = RelayHelper.shared.forwardVCardData, + let vcardURL = prepareVCardData(vcardData) { + stageVCard(url: vcardURL) + RelayHelper.shared.finishRelaying() } else if RelayHelper.shared.forwardFileData != nil || RelayHelper.shared.forwardText != nil { if let text = RelayHelper.shared.forwardText { messageInputBar.inputTextView.text = text @@ -2803,16 +2807,23 @@ extension ChatViewController: ChatDropInteractionDelegate { extension ChatViewController: SendContactViewControllerDelegate { func contactSelected(_ viewController: SendContactViewController, contactId: Int) { - guard let vcardData = dcContext.makeVCard(contactIds: [contactId]), - let fileName = FileHelper.saveData(data: vcardData, - name: UUID().uuidString, - suffix: "vcf", - directory: .cachesDirectory), - let vcardURL = URL(string: fileName) - else { return } + guard let vcardData = dcContext.makeVCard(contactIds: [contactId]), + let vcardURL = prepareVCardData(vcardData) else { return } stageVCard(url: vcardURL) } + + private func prepareVCardData(_ vcardData: Data) -> URL? { + guard let fileName = FileHelper.saveData(data: vcardData, + name: UUID().uuidString, + suffix: "vcf", + directory: .cachesDirectory), + let vcardURL = URL(string: fileName) else { + return nil + } + + return vcardURL + } } // MARK: - ReactionsOverviewViewControllerDelegate diff --git a/deltachat-ios/Controller/ContactDetailViewController.swift b/deltachat-ios/Controller/ContactDetailViewController.swift index 515bbd929..c03bdbb67 100644 --- a/deltachat-ios/Controller/ContactDetailViewController.swift +++ b/deltachat-ios/Controller/ContactDetailViewController.swift @@ -29,6 +29,13 @@ class ContactDetailViewController: UITableViewController { return cell }() + private lazy var shareContactCell: ActionCell = { + let cell = ActionCell() + cell.actionTitle = String.localized("menu_share") + cell.actionColor = UIColor.systemBlue + return cell + }() + private lazy var ephemeralMessagesCell: UITableViewCell = { let cell = UITableViewCell(style: .value1, reuseIdentifier: nil) cell.textLabel?.text = String.localized("ephemeral_messages") @@ -196,6 +203,8 @@ class ContactDetailViewController: UITableViewController { return ephemeralMessagesCell case .startChat: return startChatCell + case .shareContact: + return shareContactCell } case .statusArea: return statusCell @@ -235,6 +244,7 @@ class ContactDetailViewController: UITableViewController { let chatId = viewModel.getSharedChatIdAt(indexPath: indexPath) showChat(chatId: chatId) } + tableView.deselectRow(at: indexPath, animated: true) } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { @@ -329,6 +339,12 @@ class ContactDetailViewController: UITableViewController { } // MARK: - actions + @objc private func shareContact() { + guard let vcardData = viewModel.context.makeVCard(contactIds: [viewModel.contactId]) else { return } + + RelayHelper.shared.setForwardVCard(dialogTitle: String.localized("forward_to"), vcardData: vcardData) + navigationController?.popToRootViewController(animated: true) + } @objc private func showCopyToClipboard() { UIMenuController.shared.menuItems = [ @@ -387,6 +403,8 @@ class ContactDetailViewController: UITableViewController { tableView.deselectRow(at: indexPath, animated: false) let contactId = viewModel.contactId chatWith(contactId: contactId) + case .shareContact: + shareContact() } } diff --git a/deltachat-ios/Helper/RelayHelper.swift b/deltachat-ios/Helper/RelayHelper.swift index 613003fc5..b45e4f2c3 100644 --- a/deltachat-ios/Helper/RelayHelper.swift +++ b/deltachat-ios/Helper/RelayHelper.swift @@ -11,6 +11,7 @@ class RelayHelper { var forwardText: String? var forwardFileData: Data? var forwardFileName: String? + var forwardVCardData: Data? var mailtoDraft: String = "" var mailtoAddress: String? @@ -30,6 +31,11 @@ class RelayHelper { // forwarding messages + func setForwardVCard(dialogTitle: String, vcardData: Data) { + self.dialogTitle = dialogTitle + self.forwardVCardData = vcardData + } + func setForwardMessage(dialogTitle: String, text: String?, fileData: Data?, fileName: String?) { finishRelaying() self.dialogTitle = dialogTitle @@ -53,7 +59,7 @@ class RelayHelper { } func isForwarding() -> Bool { - return forwardIds != nil || forwardText != nil || forwardFileData != nil + return forwardIds != nil || forwardText != nil || forwardFileData != nil || forwardVCardData != nil } func forwardIdsAndFinishRelaying(to chat: Int) { @@ -69,6 +75,7 @@ class RelayHelper { forwardText = nil forwardFileData = nil forwardFileName = nil + forwardVCardData = nil mailtoDraft = "" mailtoAddress = nil askToChatWithMailto = true diff --git a/deltachat-ios/ViewModel/ContactDetailViewModel.swift b/deltachat-ios/ViewModel/ContactDetailViewModel.swift index 6bb06287a..9adc0cfef 100644 --- a/deltachat-ios/ViewModel/ContactDetailViewModel.swift +++ b/deltachat-ios/ViewModel/ContactDetailViewModel.swift @@ -17,6 +17,7 @@ class ContactDetailViewModel { case allMedia case locations case ephemeralMessages + case shareContact case startChat } @@ -89,11 +90,13 @@ class ContactDetailViewModel { if chatId != 0 { if !isDeviceTalk { chatOptions.append(.ephemeralMessages) - } - if !isDeviceTalk { chatOptions.append(.startChat) } + if isSavedMessages == false && isDeviceTalk == false { + chatOptions.append(.shareContact) + } + chatActions = [.archiveChat] if !isDeviceTalk && !isSavedMessages { chatActions.append(.showEncrInfo) @@ -177,10 +180,9 @@ class ContactDetailViewModel { func titleFor(section: Int) -> String? { switch sections[section] { - case .chatOptions: return nil case .statusArea: return (isSavedMessages || isDeviceTalk) ? nil : String.localized("pref_default_status_label") case .sharedChats: return String.localized("profile_shared_chats") - case .chatActions: return nil + case .chatOptions, .chatActions: return nil } } @@ -194,10 +196,7 @@ class ContactDetailViewModel { } else { return String.localizedStringWithFormat(String.localized("last_seen_at"), DateUtils.getExtendedAbsTimeSpanString(timeStamp: Double(lastSeen))) } - - case .statusArea: return nil - case .sharedChats: return nil - case .chatActions: return nil + case .statusArea, .sharedChats, .chatActions: return nil } }