瀏覽代碼

implement bot command support in chat messages (#1595)

* implement bot command support in chat messages

* fix comment

* improve bot command regex: lookahead for whitespace, but don't include it in the match

* to allow easier input of command paramters, add a space after the command (as on android)

Co-authored-by: B. Petersen <r10s@b44t.com>
cyBerta 3 年之前
父節點
當前提交
a4d6fe8cdf

+ 4 - 1
deltachat-ios/Chat/ChatViewController.swift

@@ -1897,7 +1897,10 @@ extension ChatViewController: BaseMessageCellDelegate {
         if handleUIMenu() || handleSelection(indexPath: indexPath) {
         if handleUIMenu() || handleSelection(indexPath: indexPath) {
             return
             return
         }
         }
-        logger.debug("command tapped \(command)")
+        if let text = messageInputBar.inputTextView.text, !text.isEmpty {
+            return
+        }
+        messageInputBar.inputTextView.text = command + " "
     }
     }
 
 
     @objc func urlTapped(url: URL, indexPath: IndexPath) {
     @objc func urlTapped(url: URL, indexPath: IndexPath) {

+ 9 - 1
deltachat-ios/Chat/Views/Cells/BaseMessageCell.swift

@@ -96,13 +96,14 @@ public class BaseMessageCell: UITableViewCell {
         view.setContentHuggingPriority(.defaultLow, for: .vertical)
         view.setContentHuggingPriority(.defaultLow, for: .vertical)
         view.font = UIFont.preferredFont(for: .body, weight: .regular)
         view.font = UIFont.preferredFont(for: .body, weight: .regular)
         view.delegate = self
         view.delegate = self
-        view.enabledDetectors = [.url, .phoneNumber]
+        view.enabledDetectors = [.url, .phoneNumber, .command]
         let attributes: [NSAttributedString.Key: Any] = [
         let attributes: [NSAttributedString.Key: Any] = [
             NSAttributedString.Key.foregroundColor: DcColors.defaultTextColor,
             NSAttributedString.Key.foregroundColor: DcColors.defaultTextColor,
             NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue,
             NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue,
             NSAttributedString.Key.underlineColor: DcColors.defaultTextColor ]
             NSAttributedString.Key.underlineColor: DcColors.defaultTextColor ]
         view.label.setAttributes(attributes, detector: .url)
         view.label.setAttributes(attributes, detector: .url)
         view.label.setAttributes(attributes, detector: .phoneNumber)
         view.label.setAttributes(attributes, detector: .phoneNumber)
+        view.label.setAttributes(attributes, detector: .command)
         view.isUserInteractionEnabled = true
         view.isUserInteractionEnabled = true
         view.isAccessibilityElement = false
         view.isAccessibilityElement = false
         return view
         return view
@@ -585,6 +586,13 @@ extension BaseMessageCell: MessageLabelDelegate {
 
 
     public func didSelectHashtag(_ hashtag: String) {}
     public func didSelectHashtag(_ hashtag: String) {}
 
 
+    public func didSelectCommand(_ command: String) {
+        if let tableView = self.superview as? UITableView, let indexPath = tableView.indexPath(for: self) {
+            logger.debug("did select command \(command)")
+            baseDelegate?.commandTapped(command: command, indexPath: indexPath)
+        }
+    }
+
     public func didSelectCustom(_ pattern: String, match: String?) {}
     public func didSelectCustom(_ pattern: String, match: String?) {}
 }
 }
 
 

+ 1 - 0
deltachat-ios/Chat/Views/DetectorType.swift

@@ -36,6 +36,7 @@ public enum DetectorType: Hashable {
     // swiftlint:disable force_try
     // swiftlint:disable force_try
     public static var hashtag = DetectorType.custom(try! NSRegularExpression(pattern: "#[a-zA-Z0-9]{4,}", options: []))
     public static var hashtag = DetectorType.custom(try! NSRegularExpression(pattern: "#[a-zA-Z0-9]{4,}", options: []))
     public static var mention = DetectorType.custom(try! NSRegularExpression(pattern: "@[a-zA-Z0-9]{4,}", options: []))
     public static var mention = DetectorType.custom(try! NSRegularExpression(pattern: "@[a-zA-Z0-9]{4,}", options: []))
+    public static var command = DetectorType.custom(try! NSRegularExpression(pattern: "(?<=\\s|^)/[a-zA-Z0-9_\\-.,$+]{2,}(?=\\s|$)", options: []))
     // swiftlint:enable force_try
     // swiftlint:enable force_try
 
 
     internal var textCheckingType: NSTextCheckingResult.CheckingType {
     internal var textCheckingType: NSTextCheckingResult.CheckingType {

+ 12 - 0
deltachat-ios/Chat/Views/MessageLabel.swift

@@ -146,6 +146,8 @@ open class MessageLabel: UILabel {
 
 
     open internal(set) var mentionAttributes: [NSAttributedString.Key: Any] = defaultAttributes
     open internal(set) var mentionAttributes: [NSAttributedString.Key: Any] = defaultAttributes
 
 
+    open internal(set) var commandAttributes: [NSAttributedString.Key: Any] = defaultAttributes
+
     open internal(set) var customAttributes: [NSRegularExpression: [NSAttributedString.Key: Any]] = [:]
     open internal(set) var customAttributes: [NSRegularExpression: [NSAttributedString.Key: Any]] = [:]
 
 
     public func setAttributes(_ attributes: [NSAttributedString.Key: Any], detector: DetectorType) {
     public func setAttributes(_ attributes: [NSAttributedString.Key: Any], detector: DetectorType) {
@@ -164,6 +166,8 @@ open class MessageLabel: UILabel {
             mentionAttributes = attributes
             mentionAttributes = attributes
         case .hashtag:
         case .hashtag:
             hashtagAttributes = attributes
             hashtagAttributes = attributes
+        case .command:
+            commandAttributes = attributes
         case .custom(let regex):
         case .custom(let regex):
             customAttributes[regex] = attributes
             customAttributes[regex] = attributes
         }
         }
@@ -299,6 +303,8 @@ open class MessageLabel: UILabel {
             return mentionAttributes
             return mentionAttributes
         case .hashtag:
         case .hashtag:
             return hashtagAttributes
             return hashtagAttributes
+        case .command:
+            return commandAttributes
         case .custom(let regex):
         case .custom(let regex):
             return customAttributes[regex] ?? MessageLabel.defaultAttributes
             return customAttributes[regex] ?? MessageLabel.defaultAttributes
         }
         }
@@ -494,6 +500,8 @@ open class MessageLabel: UILabel {
                 handleHashtag(match)
                 handleHashtag(match)
             case .mention:
             case .mention:
                 handleMention(match)
                 handleMention(match)
+            case .command:
+                handleCommand(match)
             default:
             default:
                 handleCustom(pattern, match: match)
                 handleCustom(pattern, match: match)
             }
             }
@@ -529,6 +537,10 @@ open class MessageLabel: UILabel {
         delegate?.didSelectMention(mention)
         delegate?.didSelectMention(mention)
     }
     }
 
 
+    private func handleCommand(_ command: String) {
+        delegate?.didSelectCommand(command)
+    }
+
     private func handleCustom(_ pattern: String, match: String) {
     private func handleCustom(_ pattern: String, match: String) {
         delegate?.didSelectCustom(pattern, match: match)
         delegate?.didSelectCustom(pattern, match: match)
     }
     }

+ 6 - 0
deltachat-ios/Chat/Views/MessageLabelDelegate.swift

@@ -69,6 +69,12 @@ public protocol MessageLabelDelegate: AnyObject {
     ///   - mention: The selected hashtag
     ///   - mention: The selected hashtag
     func didSelectHashtag(_ hashtag: String)
     func didSelectHashtag(_ hashtag: String)
 
 
+    /// Triggered when a tap occurs on a bot command
+    ///
+    /// - Parameters:
+    ///   - command: The selected bot command
+    func didSelectCommand(_ command: String)
+
     /// Triggered when a tap occurs on a custom regular expression
     /// Triggered when a tap occurs on a custom regular expression
     ///
     ///
     /// - Parameters:
     /// - Parameters:

+ 2 - 0
deltachat-ios/View/MultilineLabelCell.swift

@@ -88,6 +88,8 @@ extension MultilineLabelCell: MessageLabelDelegate {
 
 
     public func didSelectHashtag(_ hashtag: String) {}
     public func didSelectHashtag(_ hashtag: String) {}
 
 
+    public func didSelectCommand(_ command: String) {}
+
     public func didSelectCustom(_ pattern: String, match: String?) {}
     public func didSelectCustom(_ pattern: String, match: String?) {}
 }
 }