From ab2ff98f37b44ac51f9d4e5dae844753824dcbdd Mon Sep 17 00:00:00 2001 From: James Magahern Date: Mon, 9 May 2022 14:37:41 -0700 Subject: [PATCH] KeyboardShortcuts: Better organization --- App/AppDelegate.swift | 116 ++++--------------------- App/KeyboardShortcuts.swift | 164 ++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 100 deletions(-) diff --git a/App/AppDelegate.swift b/App/AppDelegate.swift index 2f35e8b..8d73772 100644 --- a/App/AppDelegate.swift +++ b/App/AppDelegate.swift @@ -28,113 +28,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return UISceneConfiguration(name: "Browser", sessionRole: connectingSceneSession.role) } - static func appMenuShortcuts() -> [UIKeyCommand] { - [ - // Preferences - UIKeyCommand( - modifiers: .command, - input: ",", - title: "Preferences", - action: #selector(ShortcutResponder.showPreferences) - ) - ] - } - - static func fileMenuShortcuts() -> [UIKeyCommand] { - [ - // Open Location... - UIKeyCommand( - modifiers: .command, input: "L", - title: "Open Location", - action: #selector(ShortcutResponder.focusURLBar) - ), - - // Focus Web View - UIKeyCommand( - modifiers: .command, input: "e", - title: "Focus Web View", - action: #selector(ShortcutResponder.focusWebView) - ), - - // Go Back - UIKeyCommand( - modifiers: .command, input: "[", - title: "Go Back", - action: #selector(ShortcutResponder.goBack) - ), - - // Go Forward - UIKeyCommand( - modifiers: .command, input: "]", - title: "Go Forward", - action: #selector(ShortcutResponder.goForward) - ), - - // Create Tab - UIKeyCommand( - modifiers: .command, input: "T", - title: "New Tab", - action: #selector(ShortcutResponder.createTab) - ), - - // Previous Tab - UIKeyCommand( - modifiers: [.command, .shift], input: "[", - title: "Previous Tab", - action: #selector(ShortcutResponder.previousTab) - ), - - // Close tab - UIKeyCommand( - modifiers: [.command], input: "W", - title: "Close Tab", - action: #selector(ShortcutResponder.closeTab) - ), - - // Next Tab - UIKeyCommand( - modifiers: [.command, .shift], input: "]", - title: "Next Tab", - action: #selector(ShortcutResponder.nextTab) - ), - - // Find on page - (FindOnPageViewController.isEnabled() ? - UIKeyCommand( - modifiers: [.command], input: "F", - title: "Find on Page", - action: #selector(ShortcutResponder.findOnPage) - ) - : UIKeyCommand.null() - ), - - // Refresh - UIKeyCommand( - modifiers: [.command], input: "R", - title: "Refresh", - action: #selector(ShortcutResponder.refresh) - ), - - // Toggle Dark Mode - UIKeyCommand( - modifiers: [.command], input: "M", - title: "Toggle Dark Mode", - action: #selector(ShortcutResponder.toggleDarkMode) - ), - ] - } - override var keyCommands: [UIKeyCommand]? { - get { return Self.fileMenuShortcuts() + Self.appMenuShortcuts() } + get { KeyboardShortcuts.allKeyCommands() } } override func buildMenu(with builder: UIMenuBuilder) { + // File builder.replaceChildren(ofMenu: .file) { children in - return Self.fileMenuShortcuts() + children + return KeyboardShortcuts.menu(for: .file) + children } + // X Format X builder.remove(menu: .format) + // Application builder.replaceChildren(ofMenu: .application, from: { children in let index = children.firstIndex(where: { elem in if let elem = elem as? UIMenu { @@ -144,14 +51,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate { }) var newChildren = children + let shortcuts = KeyboardShortcuts.menu(for: .application) if let index = index { - newChildren.insert(contentsOf: Self.appMenuShortcuts(), at: index + 1) + newChildren.insert(contentsOf: shortcuts, at: index + 1) } else { - newChildren.append(contentsOf: Self.appMenuShortcuts()) + newChildren.append(contentsOf: shortcuts) } return newChildren }) + + // Go + builder.insertSibling(UIMenu(title: "Go", children: KeyboardShortcuts.menu(for: .go)), beforeMenu: .view) + + // View + builder.replaceChildren(ofMenu: .view) { children in + KeyboardShortcuts.menu(for: .view) + children + } } } diff --git a/App/KeyboardShortcuts.swift b/App/KeyboardShortcuts.swift index 9cd67a8..d57987b 100644 --- a/App/KeyboardShortcuts.swift +++ b/App/KeyboardShortcuts.swift @@ -39,9 +39,173 @@ protocol ShortcutResponder: AnyObject { @objc optional func refresh(_ sender: Any?) + @objc + optional func stop(_ sender: Any?) + @objc optional func showPreferences(_ sender: Any?) @objc optional func toggleDarkMode(_ sender: Any?) } + +public class KeyboardShortcuts { + public enum Category: CaseIterable { + case application + case file + case go + case view + } + + public static func menu(for category: Category) -> [UIMenuElement] { + switch category { + case .application: + return [ + // Preferences + UIKeyCommand( + modifiers: .command, + input: ",", + title: "Preferences", + action: #selector(ShortcutResponder.showPreferences) + ) + ] + + case .file: + return [ + // Open Location... + UIKeyCommand( + modifiers: .command, input: "L", + title: "Open Location", + action: #selector(ShortcutResponder.focusURLBar) + ), + + // Tabs + UIMenu(options: .displayInline, children: [ + // Create Tab + UIKeyCommand( + modifiers: .command, input: "T", + title: "New Tab", + action: #selector(ShortcutResponder.createTab) + ), + + // Close tab + UIKeyCommand( + modifiers: [.command], input: "W", + title: "Close Tab", + action: #selector(ShortcutResponder.closeTab) + ), + ]), + + // Find on page + (FindOnPageViewController.isEnabled() ? + UIKeyCommand( + modifiers: [.command], input: "F", + title: "Find on Page", + action: #selector(ShortcutResponder.findOnPage) + ) + : UIKeyCommand.null() + ), + + UIMenu(options: .displayInline, children: [ + // Refresh + UIKeyCommand( + modifiers: [.command], input: "R", + title: "Refresh", + action: #selector(ShortcutResponder.refresh) + ), + + // Stop + UIKeyCommand( + modifiers: [.command], input: ".", + title: "Stop", + action: #selector(ShortcutResponder.stop) + ) + ]), + ] + + case .go: + return [ + // Focus Web View + UIKeyCommand( + modifiers: .command, input: "e", + title: "Focus Web View", + action: #selector(ShortcutResponder.focusWebView) + ), + + // Back/Forward + UIMenu(options: .displayInline, children: [ + // Go Back + UIKeyCommand( + modifiers: .command, input: "[", + title: "Go Back", + action: #selector(ShortcutResponder.goBack) + ), + + // Go Forward + UIKeyCommand( + modifiers: .command, input: "]", + title: "Go Forward", + action: #selector(ShortcutResponder.goForward) + ), + ]), + + // Tab Navigation + UIMenu(options: .displayInline, children: [ + // Previous Tab + UIKeyCommand( + modifiers: [.command, .shift], input: "[", + title: "Previous Tab", + action: #selector(ShortcutResponder.previousTab) + ), + + // Next Tab + UIKeyCommand( + modifiers: [.command, .shift], input: "]", + title: "Next Tab", + action: #selector(ShortcutResponder.nextTab) + ), + ]) + ] + + case .view: + return [ + // Toggle Dark Mode + UIKeyCommand( + modifiers: [.command], input: "M", + title: "Toggle Dark Mode", + action: #selector(ShortcutResponder.toggleDarkMode) + ), + ] + } + } + + public static func hiddenKeyCommands() -> [UIKeyCommand] { + return [ + // Go Back + UIKeyCommand(input: UIKeyCommand.inputLeftArrow, + modifierFlags: [.command, .control], + action: #selector(ShortcutResponder.goBack)), + + // Go Forward + UIKeyCommand(input: UIKeyCommand.inputRightArrow, + modifierFlags: [.command, .control], + action: #selector(ShortcutResponder.goForward)), + ] + } + + public static func allKeyCommands() -> [UIKeyCommand] { + var commands: [UIKeyCommand] = [] + for category in Category.allCases { + let menuElements = menu(for: category) + for element in menuElements { + if let command = element as? UIKeyCommand { + commands.append(command) + } else if let menu = element as? UIMenu { + commands.append(contentsOf: menu.children as! [UIKeyCommand]) + } + } + } + + return commands + Self.hiddenKeyCommands() + } +}