Эх сурвалжийг харах

add inline submenu capabilities to ContextMenuController, use it to show select more separated from other menu items

cyberta 4 жил өмнө
parent
commit
b291fb79d6

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

@@ -186,7 +186,8 @@ class ChatViewController: UITableViewController {
 
         let config = ContextMenuProvider()
         if #available(iOS 13.0, *), !disableWriting {
-            config.setMenu([replyItem, forwardItem, infoItem, copyItem, selectMoreItem, deleteItem])
+            let mainContextMenu = ContextMenuProvider.ContextMenuItem(submenuitems: [replyItem, forwardItem, infoItem, copyItem, deleteItem])
+            config.setMenu([mainContextMenu, selectMoreItem])
         } else {
             config.setMenu([forwardItem, infoItem, copyItem, deleteItem, selectMoreItem])
         }

+ 44 - 16
deltachat-ios/Controller/ContextMenuController.swift

@@ -132,7 +132,9 @@ class ContextMenuProvider {
 
     // iOS 12- action menu
     var menuItems: [UIMenuItem] {
-        return menu.map { UIMenuItem(title: $0.title, action: $0.action) }
+        return menu
+            .filter({ $0.title != nil && $0.action != nil })
+            .map({ return UIMenuItem(title: $0.title!, action: $0.action!) })
     }
 
     // iOS13+ action menu
@@ -142,18 +144,17 @@ class ContextMenuProvider {
         var children: [UIMenuElement] = []
 
         for item in menu {
-            let image = UIImage(systemName: item.imageName) ??
-                UIImage(named: item.imageName)
-
-            let action = UIAction(
-                title: item.title,
-                image: image,
-                handler: { _ in item.onPerform?(indexPath) }
-            )
-            if item.isDestructive {
-                action.attributes = [.destructive]
+            //we only support 1 submenu layer for now
+            if let subMenus = item.children {
+                var submenuChildren: [UIMenuElement] = []
+                for submenuItem in subMenus {
+                    submenuChildren.append(generateUIAction(item: submenuItem, indexPath: indexPath))
+                }
+                let submenu = UIMenu(title: "", options: .displayInline, children: submenuChildren)
+                children.append(submenu)
+            } else {
+                children.append(generateUIAction(item: item, indexPath: indexPath))
             }
-            children.append(action)
         }
 
         return UIMenu(
@@ -164,6 +165,23 @@ class ContextMenuProvider {
         )
     }
 
+    @available(iOS 13, *)
+    private func generateUIAction(item: ContextMenuItem, indexPath: IndexPath) -> UIAction {
+        let image = UIImage(systemName: item.imageName ?? "") ??
+            UIImage(named: item.imageName ?? "")
+
+        let action = UIAction(
+            title: item.title ?? "",
+            image: image,
+            handler: { _ in item.onPerform?(indexPath) }
+        )
+        if item.isDestructive ?? false {
+            action.attributes = [.destructive]
+        }
+
+        return action
+    }
+
     func canPerformAction(action: Selector) -> Bool {
         return !menu.filter {
             $0.action == action
@@ -180,11 +198,12 @@ class ContextMenuProvider {
 
 extension ContextMenuProvider {
     struct ContextMenuItem {
-        var title: String
-        var imageName: String
-        let isDestructive: Bool
-        var action: Selector
+        var title: String?
+        var imageName: String?
+        let isDestructive: Bool?
+        var action: Selector?
         var onPerform: ((IndexPath) -> Void)?
+        var children: [ContextMenuItem]?
 
         init(title: String, imageName: String, isDestructive: Bool = false, action: Selector, onPerform: ((IndexPath) -> Void)?) {
             self.title = title
@@ -193,5 +212,14 @@ extension ContextMenuProvider {
             self.action = action
             self.onPerform = onPerform
         }
+
+        init(submenuitems: [ContextMenuItem]) {
+            title = nil
+            imageName = nil
+            isDestructive = nil
+            action = nil
+            onPerform = nil
+            children = submenuitems
+        }
     }
 }