-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathQuickActions.swift
142 lines (115 loc) · 6.43 KB
/
QuickActions.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import Storage
import Shared
import XCGLogger
enum ShortcutType: String {
case newTab = "NewTab"
case newPrivateTab = "NewPrivateTab"
case openLastBookmark = "OpenLastBookmark"
case qrCode = "QRCode"
init?(fullType: String) {
guard let last = fullType.components(separatedBy: ".").last else { return nil }
self.init(rawValue: last)
}
var type: String {
return Bundle.main.bundleIdentifier! + ".\(self.rawValue)"
}
}
protocol QuickActionHandlerDelegate {
func handleShortCutItemType(_ type: ShortcutType, userData: [String: NSSecureCoding]?)
}
class QuickActions: NSObject {
fileprivate let log = Logger.browserLogger
static let QuickActionsVersion = "1.0"
static let QuickActionsVersionKey = "dynamicQuickActionsVersion"
static let TabURLKey = "url"
static let TabTitleKey = "title"
fileprivate let lastBookmarkTitle = NSLocalizedString("Open Last Bookmark", tableName: "3DTouchActions", comment: "String describing the action of opening the last added bookmark from the home screen Quick Actions via 3D Touch")
fileprivate let _lastTabTitle = NSLocalizedString("Open Last Tab", tableName: "3DTouchActions", comment: "String describing the action of opening the last tab sent to Firefox from the home screen Quick Actions via 3D Touch")
static var sharedInstance = QuickActions()
var launchedShortcutItem: UIApplicationShortcutItem?
// MARK: Administering Quick Actions
func addDynamicApplicationShortcutItemOfType(_ type: ShortcutType, fromShareItem shareItem: ShareItem, toApplication application: UIApplication) {
var userData = [QuickActions.TabURLKey: shareItem.url]
if let title = shareItem.title {
userData[QuickActions.TabTitleKey] = title
}
QuickActions.sharedInstance.addDynamicApplicationShortcutItemOfType(type, withUserData: userData, toApplication: application)
}
@discardableResult func addDynamicApplicationShortcutItemOfType(_ type: ShortcutType, withUserData userData: [AnyHashable: Any] = [AnyHashable: Any](), toApplication application: UIApplication) -> Bool {
// add the quick actions version so that it is always in the user info
var userData: [AnyHashable: Any] = userData
userData[QuickActions.QuickActionsVersionKey] = QuickActions.QuickActionsVersion
var dynamicShortcutItems = application.shortcutItems ?? [UIApplicationShortcutItem]()
switch type {
case .openLastBookmark:
let openLastBookmarkShortcut = UIMutableApplicationShortcutItem(type: ShortcutType.openLastBookmark.type,
localizedTitle: lastBookmarkTitle,
localizedSubtitle: userData[QuickActions.TabTitleKey] as? String,
icon: UIApplicationShortcutIcon(templateImageName: "quick_action_last_bookmark"),
userInfo: userData
)
if let index = (dynamicShortcutItems.index { $0.type == ShortcutType.openLastBookmark.type }) {
dynamicShortcutItems[index] = openLastBookmarkShortcut
} else {
dynamicShortcutItems.append(openLastBookmarkShortcut)
}
default:
log.warning("Cannot add static shortcut item of type \(type)")
return false
}
application.shortcutItems = dynamicShortcutItems
return true
}
func removeDynamicApplicationShortcutItemOfType(_ type: ShortcutType, fromApplication application: UIApplication) {
guard var dynamicShortcutItems = application.shortcutItems,
let index = (dynamicShortcutItems.index { $0.type == type.type }) else { return }
dynamicShortcutItems.remove(at: index)
application.shortcutItems = dynamicShortcutItems
}
// MARK: Handling Quick Actions
@discardableResult func handleShortCutItem(_ shortcutItem: UIApplicationShortcutItem, withBrowserViewController bvc: BrowserViewController ) -> Bool {
// Verify that the provided `shortcutItem`'s `type` is one handled by the application.
guard let shortCutType = ShortcutType(fullType: shortcutItem.type) else { return false }
DispatchQueue.main.async {
self.handleShortCutItemOfType(shortCutType, userData: shortcutItem.userInfo, browserViewController: bvc)
}
return true
}
fileprivate func handleShortCutItemOfType(_ type: ShortcutType, userData: [String : NSSecureCoding]?, browserViewController: BrowserViewController) {
switch type {
case .newTab:
handleOpenNewTab(withBrowserViewController: browserViewController, isPrivate: false)
case .newPrivateTab:
handleOpenNewTab(withBrowserViewController: browserViewController, isPrivate: true)
// even though we're removing OpenLastTab, it's possible that someone will use an existing last tab quick action to open the app
// the first time after upgrading, so we should still handle it
case .openLastBookmark:
if let urlToOpen = (userData?[QuickActions.TabURLKey] as? String)?.asURL {
handleOpenURL(withBrowserViewController: browserViewController, urlToOpen: urlToOpen)
}
case .qrCode:
handleQRCode(with: browserViewController)
}
}
fileprivate func handleOpenNewTab(withBrowserViewController bvc: BrowserViewController, isPrivate: Bool) {
bvc.openBlankNewTab(focusLocationField: true, isPrivate: isPrivate)
}
fileprivate func handleOpenURL(withBrowserViewController bvc: BrowserViewController, urlToOpen: URL) {
// open bookmark in a non-private browsing tab
bvc.switchToPrivacyMode(isPrivate: false)
// find out if bookmarked URL is currently open
// if so, open to that tab,
// otherwise, create a new tab with the bookmarked URL
bvc.switchToTabForURLOrOpen(urlToOpen, isPrivileged: true)
}
fileprivate func handleQRCode(with vc: QRCodeViewControllerDelegate & UIViewController) {
let qrCodeViewController = QRCodeViewController()
qrCodeViewController.qrCodeDelegate = vc
let controller = UINavigationController(rootViewController: qrCodeViewController)
vc.present(controller, animated: true, completion: nil)
}
}