NetNewsWire/iOS/KeyboardManager.swift

110 lines
3.0 KiB
Swift

//
// KeyboardManager.swift
// NetNewsWire-iOS
//
// Created by Maurice Parker on 9/4/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import UIKit
enum KeyboardType: String {
case global = "GlobalKeyboardShortcuts"
case sidebar = "SidebarKeyboardShortcuts"
case timeline = "TimelineKeyboardShortcuts"
case detail = "DetailKeyboardShortcuts"
}
class KeyboardManager {
private let coordinator: SceneCoordinator
private(set) var keyCommands: [UIKeyCommand]?
init(type: KeyboardType, coordinator: SceneCoordinator) {
self.coordinator = coordinator
load(type: type)
}
}
private extension KeyboardManager {
func load(type: KeyboardType) {
let globalFile = Bundle.main.path(forResource: KeyboardType.global.rawValue, ofType: "plist")!
let globalEntries = NSArray(contentsOfFile: globalFile)! as! [[String: Any]]
var globalCommands = globalEntries.compactMap { createKeyCommand(keyEntry: $0) }
let specificFile = Bundle.main.path(forResource: type.rawValue, ofType: "plist")!
let specificEntries = NSArray(contentsOfFile: specificFile)! as! [[String: Any]]
let specificCommands = specificEntries.compactMap { createKeyCommand(keyEntry: $0) }
globalCommands.append(contentsOf: specificCommands)
keyCommands = globalCommands
}
func createKeyCommand(keyEntry: [String: Any]) -> UIKeyCommand? {
guard let input = createKeyCommandInput(keyEntry: keyEntry) else { return nil }
let modifiers = createKeyModifierFlags(keyEntry: keyEntry)
let action = NSSelectorFromString(keyEntry["action"] as! String)
if let title = keyEntry["title"] as? String {
return UIKeyCommand(title: title, image: nil, action: action, input: input, modifierFlags: modifiers, propertyList: nil, alternates: [], discoverabilityTitle: nil, attributes: [], state: .on)
} else {
return UIKeyCommand(input: input, modifierFlags: modifiers, action: action)
}
}
func createKeyCommandInput(keyEntry: [String: Any]) -> String? {
guard let key = keyEntry["key"] as? String else { return nil }
switch(key) {
case "[space]":
return " "
case "[uparrow]":
return UIKeyCommand.inputUpArrow
case "[downarrow]":
return UIKeyCommand.inputDownArrow
case "[leftarrow]":
return UIKeyCommand.inputLeftArrow
case "[rightarrow]":
return UIKeyCommand.inputRightArrow
case "[return]":
return "\r"
case "[enter]":
return nil
case "[delete]":
return "\u{8}"
case "[deletefunction]":
return nil
case "[tab]":
return "\t"
default:
return key
}
}
func createKeyModifierFlags(keyEntry: [String: Any]) -> UIKeyModifierFlags {
var flags = UIKeyModifierFlags()
if keyEntry["shiftModifier"] as? Bool ?? false {
flags.insert(.shift)
}
if keyEntry["optionModifier"] as? Bool ?? false {
flags.insert(.alternate)
}
if keyEntry["commandModifier"] as? Bool ?? false {
flags.insert(.command)
}
if keyEntry["controlModifier"] as? Bool ?? false {
flags.insert(.control)
}
return flags
}
}