|
@@ -93,6 +93,72 @@ class ChatViewController: UITableViewController {
|
|
|
return UIBarButtonItem(customView: badge)
|
|
|
}()
|
|
|
|
|
|
+ private lazy var contextMenu: ContextMenuProvider = {
|
|
|
+ let copyItem = ContextMenuProvider.ContextMenuItem(
|
|
|
+ title: String.localized("global_menu_edit_copy_desktop"),
|
|
|
+ imageNames: ("ic_content_copy_white_36pt", nil),
|
|
|
+ isDestructive: false,
|
|
|
+ action: #selector(UIResponderStandardEditActions.copy(_:)),
|
|
|
+ onPerform: { [weak self] indexPath in
|
|
|
+ guard let self = self else { return }
|
|
|
+ let id = self.messageIds[indexPath.row]
|
|
|
+ let msg = DcMsg(id: id)
|
|
|
+
|
|
|
+ let pasteboard = UIPasteboard.general
|
|
|
+ if msg.type == DC_MSG_TEXT {
|
|
|
+ pasteboard.string = msg.text
|
|
|
+ } else {
|
|
|
+ pasteboard.string = msg.summary(chars: 10000000)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ let infoItem = ContextMenuProvider.ContextMenuItem(
|
|
|
+ title: String.localized("info"),
|
|
|
+ imageNames: ("info", nil),
|
|
|
+ isDestructive: false,
|
|
|
+ action: #selector(BaseMessageCell.messageInfo),
|
|
|
+ onPerform: { [weak self] indexPath in
|
|
|
+ guard let self = self else { return }
|
|
|
+ let msg = DcMsg(id: self.messageIds[indexPath.row])
|
|
|
+ let msgViewController = MessageInfoViewController(dcContext: self.dcContext, message: msg)
|
|
|
+ if let ctrl = self.navigationController {
|
|
|
+ ctrl.pushViewController(msgViewController, animated: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ let deleteItem = ContextMenuProvider.ContextMenuItem(
|
|
|
+ title: String.localized("delete"),
|
|
|
+ imageNames: ("trash", nil),
|
|
|
+ isDestructive: true,
|
|
|
+ action: #selector(BaseMessageCell.messageDelete),
|
|
|
+ onPerform: { [weak self] indexPath in
|
|
|
+ guard let self = self else { return }
|
|
|
+ logger.debug("delete message")
|
|
|
+ let msg = DcMsg(id: self.messageIds[indexPath.row])
|
|
|
+ self.askToDeleteMessage(id: msg.id)
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ let forwardItem = ContextMenuProvider.ContextMenuItem(
|
|
|
+ title: String.localized("forward"),
|
|
|
+ imageNames: ("ic_reply", nil),
|
|
|
+ isDestructive: false,
|
|
|
+ action: #selector(BaseMessageCell.messageForward),
|
|
|
+ onPerform: { [weak self] indexPath in
|
|
|
+ guard let self = self else { return }
|
|
|
+ let msg = DcMsg(id: self.messageIds[indexPath.row])
|
|
|
+ RelayHelper.sharedInstance.setForwardMessage(messageId: msg.id)
|
|
|
+ self.navigationController?.popViewController(animated: true)
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ let config = ContextMenuProvider()
|
|
|
+ config.setMenu([copyItem, infoItem, forwardItem, deleteItem])
|
|
|
+ return config
|
|
|
+ }()
|
|
|
+
|
|
|
/// The `BasicAudioController` controll the AVAudioPlayer state (play, pause, stop) and update audio cell UI accordingly.
|
|
|
private lazy var audioController = AudioController(dcContext: dcContext, chatId: chatId)
|
|
|
|
|
@@ -994,11 +1060,7 @@ class ChatViewController: UITableViewController {
|
|
|
|
|
|
// MARK: - Context menu
|
|
|
private func prepareContextMenu() {
|
|
|
- UIMenuController.shared.menuItems = [
|
|
|
- UIMenuItem(title: String.localized("info"), action: #selector(BaseMessageCell.messageInfo)),
|
|
|
- UIMenuItem(title: String.localized("delete"), action: #selector(BaseMessageCell.messageDelete)),
|
|
|
- UIMenuItem(title: String.localized("forward"), action: #selector(BaseMessageCell.messageForward))
|
|
|
- ]
|
|
|
+ UIMenuController.shared.menuItems = contextMenu.menuItems
|
|
|
UIMenuController.shared.update()
|
|
|
}
|
|
|
|
|
@@ -1007,42 +1069,24 @@ class ChatViewController: UITableViewController {
|
|
|
}
|
|
|
|
|
|
override func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
|
|
|
- return action == #selector(UIResponderStandardEditActions.copy(_:))
|
|
|
- || action == #selector(BaseMessageCell.messageInfo)
|
|
|
- || action == #selector(BaseMessageCell.messageDelete)
|
|
|
- || action == #selector(BaseMessageCell.messageForward)
|
|
|
+ return contextMenu.canPerformAction(action: action)
|
|
|
}
|
|
|
|
|
|
override func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
|
|
|
// handle standard actions here, but custom actions never trigger this. it still needs to be present for the menu to display, though.
|
|
|
- switch action {
|
|
|
- case #selector(copy(_:)):
|
|
|
- let id = messageIds[indexPath.row]
|
|
|
- let msg = DcMsg(id: id)
|
|
|
-
|
|
|
- let pasteboard = UIPasteboard.general
|
|
|
- if msg.type == DC_MSG_TEXT {
|
|
|
- pasteboard.string = msg.text
|
|
|
- } else {
|
|
|
- pasteboard.string = msg.summary(chars: 10000000)
|
|
|
- }
|
|
|
- case #selector(BaseMessageCell.messageInfo(_:)):
|
|
|
- let msg = DcMsg(id: messageIds[indexPath.row])
|
|
|
- let msgViewController = MessageInfoViewController(dcContext: dcContext, message: msg)
|
|
|
- if let ctrl = navigationController {
|
|
|
- ctrl.pushViewController(msgViewController, animated: true)
|
|
|
+ contextMenu.performAction(action: action, indexPath: indexPath)
|
|
|
+ }
|
|
|
+
|
|
|
+ // context menu for iOS 13+
|
|
|
+ @available(iOS 13, *)
|
|
|
+ override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
|
|
+ return UIContextMenuConfiguration(
|
|
|
+ identifier: nil,
|
|
|
+ previewProvider: nil,
|
|
|
+ actionProvider: { [weak self] _ in
|
|
|
+ self?.contextMenu.actionProvider(indexPath: indexPath)
|
|
|
}
|
|
|
- case #selector(BaseMessageCell.messageDelete(_:)):
|
|
|
- let msg = DcMsg(id: messageIds[indexPath.row])
|
|
|
- askToDeleteMessage(id: msg.id)
|
|
|
-
|
|
|
- case #selector(BaseMessageCell.messageForward(_:)):
|
|
|
- let msg = DcMsg(id: messageIds[indexPath.row])
|
|
|
- RelayHelper.sharedInstance.setForwardMessage(messageId: msg.id)
|
|
|
- navigationController?.popViewController(animated: true)
|
|
|
- default:
|
|
|
- break
|
|
|
- }
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
func showMediaGalleryFor(indexPath: IndexPath) {
|