@capacitor/ios 8.3.2 → 9.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift +0 -1
- package/Capacitor/Capacitor/CAPBridgeProtocol.swift +3 -0
- package/Capacitor/Capacitor/CAPBridgeViewController.swift +12 -6
- package/Capacitor/Capacitor/CAPInstanceDescriptor.h +2 -2
- package/Capacitor/Capacitor/CAPInstanceDescriptor.m +0 -1
- package/Capacitor/Capacitor/CAPInstanceDescriptor.swift +1 -18
- package/Capacitor/Capacitor/CapacitorBridge.swift +41 -92
- package/Capacitor/Capacitor/JS.swift +5 -5
- package/Capacitor/Capacitor/JSExport.swift +0 -40
- package/Capacitor/Capacitor/WebViewDelegationHandler.swift +2 -11
- package/Capacitor.podspec +0 -1
- package/CapacitorCordova/CapacitorCordova/Classes/Public/Plugin.swift +126 -0
- package/CapacitorCordova.podspec +2 -1
- package/package.json +2 -2
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.h +0 -6
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.m +0 -5
- package/Capacitor/Capacitor/TmpViewController.swift +0 -8
|
@@ -79,6 +79,9 @@ import WebKit
|
|
|
79
79
|
func registerPluginType(_ pluginType: CAPPlugin.Type)
|
|
80
80
|
func registerPluginInstance(_ pluginInstance: CAPPlugin)
|
|
81
81
|
|
|
82
|
+
// MARK: - Interceptors
|
|
83
|
+
func registerCallInterceptor(_ name: String, handler: @escaping ([String: Any]) -> Void)
|
|
84
|
+
|
|
82
85
|
// MARK: - View Presentation
|
|
83
86
|
func showAlertWith(title: String, message: String, buttonTitle: String)
|
|
84
87
|
@available(*, deprecated, message: "Use self?.bridge?.viewController?.present")
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
import WebKit
|
|
3
|
-
import Cordova
|
|
4
3
|
|
|
5
4
|
@objc open class CAPBridgeViewController: UIViewController {
|
|
6
5
|
private var capacitorBridge: CapacitorBridge?
|
|
@@ -47,10 +46,10 @@ import Cordova
|
|
|
47
46
|
// create the bridge
|
|
48
47
|
capacitorBridge = CapacitorBridge(with: configuration,
|
|
49
48
|
delegate: self,
|
|
50
|
-
cordovaConfiguration: configDescriptor.cordovaConfiguration,
|
|
51
49
|
assetHandler: assetHandler,
|
|
52
50
|
delegationHandler: delegationHandler)
|
|
53
51
|
capacitorDidLoad()
|
|
52
|
+
updateAppLocationIfNeeded()
|
|
54
53
|
|
|
55
54
|
if configDescriptor.instanceType == .fixed {
|
|
56
55
|
updateBinaryVersion()
|
|
@@ -89,18 +88,25 @@ import Cordova
|
|
|
89
88
|
- Note: This is called early in the View Controller's lifecycle. Not all properties will be set at invocation.
|
|
90
89
|
*/
|
|
91
90
|
open func instanceDescriptor() -> InstanceDescriptor {
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
return InstanceDescriptor()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// This function must be called after plugins are loaded or it will have no effect.
|
|
95
|
+
open func updateAppLocationIfNeeded() {
|
|
96
|
+
let cordovaPlugin = bridge?.plugin(withName: "__CordovaPlugin")
|
|
97
|
+
let cordovaDeployDisabled = cordovaPlugin?.perform(Selector(("cordovaDeployDisabled"))).takeUnretainedValue() as? Bool ?? false
|
|
98
|
+
|
|
99
|
+
if !isNewBinary && !cordovaDeployDisabled {
|
|
94
100
|
if let persistedPath = KeyValueStore.standard["serverBasePath", as: String.self], !persistedPath.isEmpty {
|
|
95
101
|
if let libPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {
|
|
96
|
-
|
|
102
|
+
let serverBasePath = URL(fileURLWithPath: libPath, isDirectory: true)
|
|
97
103
|
.appendingPathComponent("NoCloud")
|
|
98
104
|
.appendingPathComponent("ionic_built_snapshots")
|
|
99
105
|
.appendingPathComponent(URL(fileURLWithPath: persistedPath, isDirectory: true).lastPathComponent)
|
|
106
|
+
setServerBasePath(path: serverBasePath.path)
|
|
100
107
|
}
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
|
-
return descriptor
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
open func router() -> Router {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#define CAPInstanceDescriptor_h
|
|
3
3
|
|
|
4
4
|
@import UIKit;
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
|
|
7
7
|
typedef NS_ENUM(NSInteger, CAPInstanceType) {
|
|
8
8
|
CAPInstanceTypeFixed NS_SWIFT_NAME(fixed),
|
|
@@ -137,7 +137,7 @@ NS_SWIFT_NAME(InstanceDescriptor)
|
|
|
137
137
|
/**
|
|
138
138
|
@brief The parser used to load the cofiguration for Cordova plugins.
|
|
139
139
|
*/
|
|
140
|
-
@property (nonatomic, copy, nonnull)
|
|
140
|
+
@property (nonatomic, copy, nonnull) NSObject *cordovaConfiguration;
|
|
141
141
|
/**
|
|
142
142
|
@brief Warnings generated during initialization.
|
|
143
143
|
*/
|
|
@@ -45,7 +45,6 @@ NSString* const CAPInstanceDescriptorDefaultHostname = @"localhost";
|
|
|
45
45
|
_contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|
46
46
|
_appLocation = location;
|
|
47
47
|
_limitsNavigationsToAppBoundDomains = FALSE;
|
|
48
|
-
_cordovaConfiguration = [[CDVConfigParser alloc] init];
|
|
49
48
|
_warnings = 0;
|
|
50
49
|
if (location == nil) {
|
|
51
50
|
_warnings |= CAPInstanceWarningMissingAppDir;
|
|
@@ -52,23 +52,6 @@ internal extension InstanceDescriptor {
|
|
|
52
52
|
warnings.update(with: .missingFile)
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// parse the cordova configuration
|
|
56
|
-
var configParser: XMLParser?
|
|
57
|
-
if let cordovaURL = cordovaURL,
|
|
58
|
-
FileManager.default.fileExists(atPath: cordovaURL.path, isDirectory: &isDirectory),
|
|
59
|
-
isDirectory.boolValue == false {
|
|
60
|
-
configParser = XMLParser(contentsOf: cordovaURL)
|
|
61
|
-
} else {
|
|
62
|
-
warnings.update(with: .missingCordovaFile)
|
|
63
|
-
// we don't want to break up string literals
|
|
64
|
-
// swiftlint:disable:next line_length
|
|
65
|
-
if let cordovaXML = "<?xml version='1.0' encoding='utf-8'?><widget version=\"1.0.0\" xmlns=\"http://www.w3.org/ns/widgets\" xmlns:cdv=\"http://cordova.apache.org/ns/1.0\"><access origin=\"*\" /></widget>".data(using: .utf8) {
|
|
66
|
-
configParser = XMLParser(data: cordovaXML)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
configParser?.delegate = cordovaConfiguration
|
|
70
|
-
configParser?.parse()
|
|
71
|
-
|
|
72
55
|
// extract our configuration values
|
|
73
56
|
if let config = config {
|
|
74
57
|
// to be removed
|
|
@@ -160,7 +143,7 @@ internal extension InstanceDescriptor {
|
|
|
160
143
|
|
|
161
144
|
extension InstanceDescriptor {
|
|
162
145
|
@objc public var cordovaDeployDisabled: Bool {
|
|
163
|
-
return
|
|
146
|
+
return false
|
|
164
147
|
}
|
|
165
148
|
|
|
166
149
|
@objc public func normalize() {
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import Dispatch
|
|
3
3
|
import WebKit
|
|
4
|
-
import Cordova
|
|
5
4
|
|
|
6
5
|
internal typealias CapacitorPlugin = CAPPlugin & CAPBridgedPlugin
|
|
7
6
|
|
|
8
7
|
struct RegistrationList: Codable {
|
|
9
|
-
|
|
8
|
+
var packageClassList: Set<String>
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
/**
|
|
@@ -93,10 +92,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
|
-
@available(*, deprecated, message: "obsolete")
|
|
97
|
-
var tmpWindow: UIWindow?
|
|
98
|
-
@available(*, deprecated, message: "obsolete")
|
|
99
|
-
static let tmpVCAppeared = Notification(name: Notification.Name(rawValue: "tmpViewControllerAppeared"))
|
|
100
95
|
public static let capacitorSite = "https://capacitorjs.com/"
|
|
101
96
|
public static let fileStartIdentifier = "/_capacitor_file_"
|
|
102
97
|
public static let httpInterceptorStartIdentifier = "/_capacitor_http_interceptor_"
|
|
@@ -117,18 +112,16 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
117
112
|
@objc public var config: InstanceConfiguration
|
|
118
113
|
// Map of all loaded and instantiated plugins by pluginId -> instance
|
|
119
114
|
var plugins = [String: CapacitorPlugin]()
|
|
120
|
-
// Manager for getting Cordova plugins
|
|
121
|
-
var cordovaPluginManager: CDVPluginManager?
|
|
122
115
|
// Calls we are storing to resolve later
|
|
123
116
|
var storedCalls = ConcurrentDictionary<CAPPluginCall>()
|
|
124
117
|
// Whether to inject the Cordova files
|
|
125
|
-
private var
|
|
126
|
-
private var cordovaParser: CDVConfigParser?
|
|
118
|
+
private var cordovaIsPresent = false
|
|
127
119
|
private var injectMiscFiles: [String] = []
|
|
128
120
|
private var canInjectJS: Bool = true
|
|
129
121
|
|
|
130
122
|
// Background dispatch queue for plugin calls
|
|
131
123
|
open private(set) var dispatchQueue = DispatchQueue(label: "bridge")
|
|
124
|
+
internal private(set) var callInterceptors: [String: ([String: Any]) -> Void] = [:]
|
|
132
125
|
// Array of block based observers
|
|
133
126
|
var observers: [NSObjectProtocol] = []
|
|
134
127
|
|
|
@@ -205,12 +198,17 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
205
198
|
|
|
206
199
|
// MARK: - Initialization
|
|
207
200
|
|
|
208
|
-
|
|
201
|
+
@available(*, deprecated, renamed: "init", message: "Use different init")
|
|
202
|
+
public convenience init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, cordovaConfiguration: Any, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
|
|
203
|
+
self.init(with: configuration, delegate: bridgeDelegate, assetHandler: assetHandler, delegationHandler: delegationHandler, autoRegisterPlugins: autoRegisterPlugins)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
|
|
207
|
+
|
|
209
208
|
self.bridgeDelegate = bridgeDelegate
|
|
210
209
|
self.webViewAssetHandler = assetHandler
|
|
211
210
|
self.webViewDelegationHandler = delegationHandler
|
|
212
211
|
self.config = configuration
|
|
213
|
-
self.cordovaParser = cordovaConfiguration
|
|
214
212
|
self.notificationRouter = NotificationRouter()
|
|
215
213
|
self.notificationRouter.handleApplicationNotifications = configuration.handleApplicationNotifications
|
|
216
214
|
self.autoRegisterPlugins = autoRegisterPlugins
|
|
@@ -220,12 +218,9 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
220
218
|
|
|
221
219
|
exportCoreJS(localUrl: configuration.localURL.absoluteString)
|
|
222
220
|
registerPlugins()
|
|
223
|
-
|
|
221
|
+
setupListeners()
|
|
224
222
|
exportMiscJS()
|
|
225
223
|
canInjectJS = false
|
|
226
|
-
observers.append(NotificationCenter.default.addObserver(forName: type(of: self).tmpVCAppeared.name, object: .none, queue: .none) { [weak self] _ in
|
|
227
|
-
self?.tmpWindow = nil
|
|
228
|
-
})
|
|
229
224
|
|
|
230
225
|
self.setupWebDebugging(configuration: configuration)
|
|
231
226
|
}
|
|
@@ -262,31 +257,27 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
262
257
|
injectMiscFiles.removeAll()
|
|
263
258
|
}
|
|
264
259
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
do {
|
|
287
|
-
try JSExport.exportCordovaJS(userContentController: webViewDelegationHandler.contentController)
|
|
288
|
-
} catch {
|
|
289
|
-
type(of: self).fatalError(error, error)
|
|
260
|
+
func setupListeners() {
|
|
261
|
+
if !cordovaIsPresent {
|
|
262
|
+
observers.append(
|
|
263
|
+
NotificationCenter.default.addObserver(
|
|
264
|
+
forName: UIApplication.willEnterForegroundNotification,
|
|
265
|
+
object: nil,
|
|
266
|
+
queue: .main
|
|
267
|
+
) { [weak self] _ in
|
|
268
|
+
self?.triggerDocumentJSEvent(eventName: "resume")
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
observers.append(
|
|
273
|
+
NotificationCenter.default.addObserver(
|
|
274
|
+
forName: UIApplication.didEnterBackgroundNotification,
|
|
275
|
+
object: nil,
|
|
276
|
+
queue: .main
|
|
277
|
+
) { [weak self] _ in
|
|
278
|
+
self?.triggerDocumentJSEvent(eventName: "pause")
|
|
279
|
+
}
|
|
280
|
+
)
|
|
290
281
|
}
|
|
291
282
|
}
|
|
292
283
|
|
|
@@ -309,14 +300,13 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
309
300
|
do {
|
|
310
301
|
if let pluginJSON = Bundle.main.url(forResource: "capacitor.config", withExtension: "json") {
|
|
311
302
|
let pluginData = try Data(contentsOf: pluginJSON)
|
|
312
|
-
|
|
303
|
+
var registrationList = try JSONDecoder().decode(RegistrationList.self, from: pluginData)
|
|
313
304
|
|
|
314
305
|
for plugin in registrationList.packageClassList {
|
|
315
|
-
if let pluginClass = NSClassFromString(plugin) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
pluginList.append(pluginClass)
|
|
306
|
+
if let pluginClass = NSClassFromString(plugin), pluginClass is CAPPlugin.Type {
|
|
307
|
+
pluginList.append(pluginClass)
|
|
308
|
+
if plugin == "CordovaPlugin" {
|
|
309
|
+
cordovaIsPresent = true
|
|
320
310
|
}
|
|
321
311
|
}
|
|
322
312
|
}
|
|
@@ -393,6 +383,10 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
393
383
|
|
|
394
384
|
// MARK: - CAPBridgeProtocol: Call Management
|
|
395
385
|
|
|
386
|
+
public func registerCallInterceptor(_ name: String, handler: @escaping ([String: Any]) -> Void) {
|
|
387
|
+
callInterceptors[name] = handler
|
|
388
|
+
}
|
|
389
|
+
|
|
396
390
|
@objc public func saveCall(_ call: CAPPluginCall) {
|
|
397
391
|
storedCalls[call.callbackId] = call
|
|
398
392
|
}
|
|
@@ -425,23 +419,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
425
419
|
return self.dispatchQueue
|
|
426
420
|
}
|
|
427
421
|
|
|
428
|
-
func registerCordovaPlugins() {
|
|
429
|
-
guard let cordovaParser = cordovaParser else {
|
|
430
|
-
return
|
|
431
|
-
}
|
|
432
|
-
cordovaPluginManager = CDVPluginManager.init(parser: cordovaParser, viewController: self.viewController, webView: self.getWebView())
|
|
433
|
-
if cordovaParser.startupPluginNames.count > 0 {
|
|
434
|
-
for pluginName in cordovaParser.startupPluginNames {
|
|
435
|
-
_ = cordovaPluginManager?.getCommandInstance(pluginName as? String)
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
do {
|
|
439
|
-
try JSExport.exportCordovaPluginsJS(userContentController: webViewDelegationHandler.contentController)
|
|
440
|
-
} catch {
|
|
441
|
-
type(of: self).fatalError(error, error)
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
422
|
func reload() {
|
|
446
423
|
self.getWebView()?.reload()
|
|
447
424
|
}
|
|
@@ -540,34 +517,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
|
|
|
540
517
|
}
|
|
541
518
|
}
|
|
542
519
|
|
|
543
|
-
/**
|
|
544
|
-
Handle a Cordova call from JavaScript. First, find the corresponding plugin,
|
|
545
|
-
construct a selector, and perform that selector on the plugin instance.
|
|
546
|
-
*/
|
|
547
|
-
func handleCordovaJSCall(call: JSCall) {
|
|
548
|
-
// Create a selector to send to the plugin
|
|
549
|
-
|
|
550
|
-
if let plugin = self.cordovaPluginManager?.getCommandInstance(call.pluginId.lowercased()) {
|
|
551
|
-
let selector = NSSelectorFromString("\(call.method):")
|
|
552
|
-
if !plugin.responds(to: selector) {
|
|
553
|
-
CAPLog.print("Error: Plugin \(plugin.className ?? "") does not respond to method call \(selector).")
|
|
554
|
-
CAPLog.print("Ensure plugin method exists and uses @objc in its declaration")
|
|
555
|
-
return
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
let arguments: [Any] = call.options["options"] as? [Any] ?? []
|
|
559
|
-
let pluginCall = CDVInvokedUrlCommand(arguments: arguments,
|
|
560
|
-
callbackId: call.callbackId,
|
|
561
|
-
className: plugin.className,
|
|
562
|
-
methodName: call.method)
|
|
563
|
-
plugin.perform(selector, with: pluginCall)
|
|
564
|
-
|
|
565
|
-
} else {
|
|
566
|
-
CAPLog.print("Error: Cordova Plugin mapping not found")
|
|
567
|
-
return
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
520
|
func removeAllPluginListeners() {
|
|
572
521
|
for plugin in plugins.values {
|
|
573
522
|
plugin.perform(#selector(CAPPlugin.removeAllListeners(_:)), with: nil)
|
|
@@ -14,11 +14,11 @@ public typealias JSResultBody = [String: Any]
|
|
|
14
14
|
/**
|
|
15
15
|
* A call originating from JavaScript land
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
let options: [String: Any]
|
|
19
|
-
let pluginId: String
|
|
20
|
-
let method: String
|
|
21
|
-
let callbackId: String
|
|
17
|
+
public struct JSCall {
|
|
18
|
+
public let options: [String: Any]
|
|
19
|
+
public let pluginId: String
|
|
20
|
+
public let method: String
|
|
21
|
+
public let callbackId: String
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
internal protocol JSResultProtocol {
|
|
@@ -35,24 +35,6 @@ internal class JSExport {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
static func exportCordovaJS(userContentController: WKUserContentController) throws {
|
|
39
|
-
guard let cordovaUrl = Bundle.main.url(forResource: "public/cordova", withExtension: "js") else {
|
|
40
|
-
CAPLog.print("ERROR: Required cordova.js file not found. Cordova plugins will not function!")
|
|
41
|
-
throw CapacitorBridgeError.errorExportingCoreJS
|
|
42
|
-
}
|
|
43
|
-
guard let cordovaPluginsUrl = Bundle.main.url(forResource: "public/cordova_plugins", withExtension: "js") else {
|
|
44
|
-
CAPLog.print("ERROR: Required cordova_plugins.js file not found. Cordova plugins will not function!")
|
|
45
|
-
throw CapacitorBridgeError.errorExportingCoreJS
|
|
46
|
-
}
|
|
47
|
-
do {
|
|
48
|
-
try self.injectFile(fileURL: cordovaUrl, userContentController: userContentController)
|
|
49
|
-
try self.injectFile(fileURL: cordovaPluginsUrl, userContentController: userContentController)
|
|
50
|
-
} catch {
|
|
51
|
-
CAPLog.print("ERROR: Unable to read required cordova files. Cordova plugins will not function!")
|
|
52
|
-
throw CapacitorBridgeError.errorExportingCoreJS
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
38
|
static func exportMiscFileJS(paths: [String], userContentController: WKUserContentController) {
|
|
57
39
|
for path in paths {
|
|
58
40
|
if let miscJSFilePath = Bundle.main.url(forResource: "public/\(path.replacingOccurrences(of: ".js", with: ""))", withExtension: "js") {
|
|
@@ -184,28 +166,6 @@ internal class JSExport {
|
|
|
184
166
|
return lines.joined(separator: "\n")
|
|
185
167
|
}
|
|
186
168
|
|
|
187
|
-
static func exportCordovaPluginsJS(userContentController: WKUserContentController) throws {
|
|
188
|
-
if let pluginsJSFolder = Bundle.main.url(forResource: "public/plugins", withExtension: nil) {
|
|
189
|
-
self.injectFilesForFolder(folder: pluginsJSFolder, userContentController: userContentController)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
static func injectFilesForFolder(folder: URL, userContentController: WKUserContentController) {
|
|
194
|
-
let fileManager = FileManager.default
|
|
195
|
-
do {
|
|
196
|
-
let fileURLs = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil, options: [])
|
|
197
|
-
for fileURL in fileURLs {
|
|
198
|
-
if fileURL.hasDirectoryPath {
|
|
199
|
-
injectFilesForFolder(folder: fileURL, userContentController: userContentController)
|
|
200
|
-
} else {
|
|
201
|
-
try self.injectFile(fileURL: fileURL, userContentController: userContentController)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
} catch {
|
|
205
|
-
CAPLog.print("Error while enumerating files")
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
169
|
static func injectFile(fileURL: URL, userContentController: WKUserContentController) throws {
|
|
210
170
|
do {
|
|
211
171
|
let data = try String(contentsOf: fileURL, encoding: .utf8)
|
|
@@ -208,17 +208,8 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
bridge.handleJSCall(call: JSCall(options: options, pluginId: pluginId, method: method, callbackId: callbackId))
|
|
211
|
-
} else if
|
|
212
|
-
|
|
213
|
-
let method = dict["action"] as? String ?? ""
|
|
214
|
-
let callbackId = dict["callbackId"] as? String ?? ""
|
|
215
|
-
|
|
216
|
-
let args = dict["actionArgs"] as? Array ?? []
|
|
217
|
-
let options = ["options": args]
|
|
218
|
-
|
|
219
|
-
CAPLog.print("To Native Cordova -> ", pluginId, method, callbackId, options)
|
|
220
|
-
|
|
221
|
-
bridge.handleCordovaJSCall(call: JSCall(options: options, pluginId: pluginId, method: method, callbackId: callbackId))
|
|
211
|
+
} else if let handler = bridge.callInterceptors[type] {
|
|
212
|
+
handler(dict)
|
|
222
213
|
}
|
|
223
214
|
}
|
|
224
215
|
}
|
package/Capacitor.podspec
CHANGED
|
@@ -19,6 +19,5 @@ Pod::Spec.new do |s|
|
|
|
19
19
|
s.module_map = "#{prefix}Capacitor/Capacitor/Capacitor.modulemap"
|
|
20
20
|
s.resources = ["#{prefix}Capacitor/Capacitor/assets/native-bridge.js"]
|
|
21
21
|
s.resource_bundles = { 'Capacitor' => ["#{prefix}Capacitor/Capacitor/PrivacyInfo.xcprivacy"] }
|
|
22
|
-
s.dependency 'CapacitorCordova'
|
|
23
22
|
s.swift_version = '5.1'
|
|
24
23
|
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import Capacitor
|
|
2
|
+
|
|
3
|
+
@objc(CordovaPlugin)
|
|
4
|
+
public class CordovaPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
5
|
+
public let jsName = "__CordovaPlugin"
|
|
6
|
+
public let pluginMethods: [CAPPluginMethod] = []
|
|
7
|
+
public var identifier: String { jsName }
|
|
8
|
+
|
|
9
|
+
private var _cordovaDeployDisabled = false
|
|
10
|
+
|
|
11
|
+
override public func load() {
|
|
12
|
+
injectJavascript()
|
|
13
|
+
configureRuntime()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func configureRuntime() {
|
|
17
|
+
guard let configURL = Bundle.main.url(forResource: "config", withExtension: "xml") else { fatalError() }
|
|
18
|
+
guard let bridge, let webView = bridge.webView else { return }
|
|
19
|
+
|
|
20
|
+
let cordovaConfigParser = CDVConfigParser()
|
|
21
|
+
|
|
22
|
+
let xmlParser = XMLParser(contentsOf: configURL)
|
|
23
|
+
xmlParser?.delegate = cordovaConfigParser
|
|
24
|
+
xmlParser?.parse()
|
|
25
|
+
|
|
26
|
+
guard let pluginManager = CDVPluginManager(
|
|
27
|
+
parser: cordovaConfigParser,
|
|
28
|
+
viewController: bridge.viewController,
|
|
29
|
+
webView: bridge.webView
|
|
30
|
+
) else { return }
|
|
31
|
+
|
|
32
|
+
for plugin in cordovaConfigParser.startupPluginNames.compactMap({ $0 as? String }) {
|
|
33
|
+
_ = pluginManager.getCommandInstance(plugin)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exportCordovaPluginsJS(userContentController: webView.configuration.userContentController)
|
|
37
|
+
|
|
38
|
+
bridge.registerCallInterceptor("cordova") { [pluginManager] dict in
|
|
39
|
+
let pluginId = dict["service"] as? String ?? ""
|
|
40
|
+
let method = dict["action"] as? String ?? ""
|
|
41
|
+
let callbackId = dict["callbackId"] as? String ?? ""
|
|
42
|
+
|
|
43
|
+
let args = dict["actionArgs"] as? Array ?? []
|
|
44
|
+
let options = ["options": args]
|
|
45
|
+
|
|
46
|
+
CAPLog.print("To Native Cordova -> ", pluginId, method, callbackId, options)
|
|
47
|
+
|
|
48
|
+
if let plugin = pluginManager.getCommandInstance(pluginId.lowercased()) {
|
|
49
|
+
let selector = NSSelectorFromString("\(method):")
|
|
50
|
+
if !plugin.responds(to: selector) {
|
|
51
|
+
CAPLog.print("Error: Plugin \(plugin.className ?? "") does not respond to method call \(selector).")
|
|
52
|
+
CAPLog.print("Ensure plugin method exists and uses @objc in its declaration")
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let arguments = options["options"] ?? []
|
|
57
|
+
let pluginCall = CDVInvokedUrlCommand(
|
|
58
|
+
arguments: arguments,
|
|
59
|
+
callbackId: callbackId,
|
|
60
|
+
className: plugin.className,
|
|
61
|
+
methodName: method
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
plugin.perform(selector, with: pluginCall)
|
|
65
|
+
|
|
66
|
+
} else {
|
|
67
|
+
CAPLog.print("Error: Cordova Plugin mapping not found")
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
_cordovaDeployDisabled = (cordovaConfigParser.settings?["DisableDeploy".lowercased()] as? NSString)?.boolValue ?? false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@objc
|
|
76
|
+
func cordovaDeployDisabled() -> NSNumber {
|
|
77
|
+
return _cordovaDeployDisabled as NSNumber
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
func injectJavascript() {
|
|
81
|
+
guard let cordovaUrl = Bundle.main.url(forResource: "public/cordova", withExtension: "js") else {
|
|
82
|
+
fatalError("ERROR: Required cordova.js file not found. Cordova plugins will not function!")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
guard let cordovaPluginsUrl = Bundle.main.url(forResource: "public/cordova_plugins", withExtension: "js") else {
|
|
86
|
+
fatalError("ERROR: Required cordova_plugins.js file not found. Cordova plugins will not function!")
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
guard let webView = bridge?.webView else { return }
|
|
90
|
+
|
|
91
|
+
injectFile(fileURL: cordovaUrl, userContentController: webView.configuration.userContentController)
|
|
92
|
+
injectFile(fileURL: cordovaPluginsUrl, userContentController: webView.configuration.userContentController)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func exportCordovaPluginsJS(userContentController: WKUserContentController) {
|
|
96
|
+
if let pluginsJSFolder = Bundle.main.url(forResource: "public/plugins", withExtension: nil) {
|
|
97
|
+
injectFilesForFolder(folder: pluginsJSFolder, userContentController: userContentController)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func injectFile(fileURL: URL, userContentController: WKUserContentController) {
|
|
102
|
+
do {
|
|
103
|
+
let data = try String(contentsOf: fileURL, encoding: .utf8)
|
|
104
|
+
let userScript = WKUserScript(source: data, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
|
105
|
+
userContentController.addUserScript(userScript)
|
|
106
|
+
} catch {
|
|
107
|
+
fatalError("Unable to inject js file")
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func injectFilesForFolder(folder: URL, userContentController: WKUserContentController) {
|
|
112
|
+
let fileManager = FileManager.default
|
|
113
|
+
do {
|
|
114
|
+
let fileURLs = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil, options: [])
|
|
115
|
+
for fileURL in fileURLs {
|
|
116
|
+
if fileURL.hasDirectoryPath {
|
|
117
|
+
injectFilesForFolder(folder: fileURL, userContentController: userContentController)
|
|
118
|
+
} else {
|
|
119
|
+
injectFile(fileURL: fileURL, userContentController: userContentController)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
CAPLog.print("Error while enumerating files")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
package/CapacitorCordova.podspec
CHANGED
|
@@ -16,11 +16,12 @@ Pod::Spec.new do |s|
|
|
|
16
16
|
s.authors = { 'Ionic Team' => 'hi@ionicframework.com' }
|
|
17
17
|
s.source = { git: 'https://github.com/ionic-team/capacitor', tag: s.version.to_s }
|
|
18
18
|
s.platform = :ios, 15.0
|
|
19
|
-
s.source_files = "#{prefix}CapacitorCordova/CapacitorCordova/**/*.{h,m}"
|
|
19
|
+
s.source_files = "#{prefix}CapacitorCordova/CapacitorCordova/**/*.{h,m,swift}"
|
|
20
20
|
s.public_header_files = "#{prefix}CapacitorCordova/CapacitorCordova/Classes/Public/*.h",
|
|
21
21
|
"#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.h"
|
|
22
22
|
s.module_map = "#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap"
|
|
23
23
|
s.resource_bundles = { 'CapacitorCordova' => ["#{prefix}CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy"] }
|
|
24
24
|
s.requires_arc = true
|
|
25
|
+
s.dependency 'Capacitor', s.version.to_s
|
|
25
26
|
s.framework = 'WebKit'
|
|
26
27
|
end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/ios",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-alpha.0",
|
|
4
4
|
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capacitorjs.com",
|
|
6
6
|
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"xc:build:CapacitorCordova": "cd CapacitorCordova && xcodebuild && cd .."
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@capacitor/core": "^
|
|
28
|
+
"@capacitor/core": "^9.0.0-alpha.0"
|
|
29
29
|
},
|
|
30
30
|
"publishConfig": {
|
|
31
31
|
"access": "public"
|