@calvingoh-hexa/capacitor-inappbrowser 6.9.36
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/CapgoInappbrowser.podspec +17 -0
- package/LICENSE +21 -0
- package/README.md +690 -0
- package/android/build.gradle +64 -0
- package/android/src/main/AndroidManifest.xml +12 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/InAppBrowserPlugin.java +741 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +340 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +15 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +1177 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/android/src/main/res/drawable/arrow_back_disabled.xml +9 -0
- package/android/src/main/res/drawable/arrow_back_enabled.xml +9 -0
- package/android/src/main/res/drawable/arrow_forward_disabled.xml +9 -0
- package/android/src/main/res/drawable/arrow_forward_enabled.xml +9 -0
- package/android/src/main/res/drawable/ic_clear_24px.xml +9 -0
- package/android/src/main/res/drawable/ic_refresh.xml +9 -0
- package/android/src/main/res/layout/activity_browser.xml +22 -0
- package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
- package/android/src/main/res/layout/content_browser.xml +16 -0
- package/android/src/main/res/layout/tool_bar.xml +72 -0
- package/android/src/main/res/values/browser_theme.xml +3 -0
- package/android/src/main/res/values/colors.xml +5 -0
- package/android/src/main/res/values/dimens.xml +3 -0
- package/android/src/main/res/values/strings.xml +11 -0
- package/android/src/main/res/values/styles.xml +4 -0
- package/dist/docs.json +1865 -0
- package/dist/esm/definitions.d.ts +361 -0
- package/dist/esm/definitions.js +13 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +19 -0
- package/dist/esm/web.js +48 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +75 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +78 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Back@3x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Back.imageset/Contents.json +26 -0
- package/ios/Plugin/Assets.xcassets/Contents.json +6 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Contents.json +26 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@2x.png +0 -0
- package/ios/Plugin/Assets.xcassets/Forward.imageset/Forward@3x.png +0 -0
- package/ios/Plugin/Enums.swift +65 -0
- package/ios/Plugin/InAppBrowserPlugin.h +10 -0
- package/ios/Plugin/InAppBrowserPlugin.m +21 -0
- package/ios/Plugin/InAppBrowserPlugin.swift +434 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/WKWebViewController.swift +1021 -0
- package/package.json +83 -0
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"images" : [
|
|
3
|
+
{
|
|
4
|
+
"idiom" : "universal",
|
|
5
|
+
"filename" : "Back.png",
|
|
6
|
+
"scale" : "1x"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom" : "universal",
|
|
10
|
+
"filename" : "Back@2x.png",
|
|
11
|
+
"scale" : "2x"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"idiom" : "universal",
|
|
15
|
+
"filename" : "Back@3x.png",
|
|
16
|
+
"scale" : "3x"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"info" : {
|
|
20
|
+
"version" : 1,
|
|
21
|
+
"author" : "xcode"
|
|
22
|
+
},
|
|
23
|
+
"properties" : {
|
|
24
|
+
"template-rendering-intent" : "template"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"images" : [
|
|
3
|
+
{
|
|
4
|
+
"idiom" : "universal",
|
|
5
|
+
"filename" : "Forward.png",
|
|
6
|
+
"scale" : "1x"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom" : "universal",
|
|
10
|
+
"filename" : "Forward@2x.png",
|
|
11
|
+
"scale" : "2x"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"idiom" : "universal",
|
|
15
|
+
"filename" : "Forward@3x.png",
|
|
16
|
+
"scale" : "3x"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"info" : {
|
|
20
|
+
"version" : 1,
|
|
21
|
+
"author" : "xcode"
|
|
22
|
+
},
|
|
23
|
+
"properties" : {
|
|
24
|
+
"template-rendering-intent" : "template"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Enums.swift
|
|
3
|
+
// Sample
|
|
4
|
+
//
|
|
5
|
+
// Created by Meniny on 2018-01-20.
|
|
6
|
+
// Copyright © 2018年 Meniny. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import UIKit
|
|
11
|
+
|
|
12
|
+
public enum WKWebSource: Equatable {
|
|
13
|
+
case remote(URL)
|
|
14
|
+
case file(URL, access: URL)
|
|
15
|
+
case string(String, base: URL?)
|
|
16
|
+
|
|
17
|
+
public var url: URL? {
|
|
18
|
+
switch self {
|
|
19
|
+
case .remote(let u): return u
|
|
20
|
+
case .file(let u, access: _): return u
|
|
21
|
+
default: return nil
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public var remoteURL: URL? {
|
|
26
|
+
switch self {
|
|
27
|
+
case .remote(let u): return u
|
|
28
|
+
default: return nil
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public var absoluteString: String? {
|
|
33
|
+
switch self {
|
|
34
|
+
case .remote(let u): return u.absoluteString
|
|
35
|
+
case .file(let u, access: _): return u.absoluteString
|
|
36
|
+
default: return nil
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public enum BarButtonItemType {
|
|
42
|
+
case back
|
|
43
|
+
case forward
|
|
44
|
+
case reload
|
|
45
|
+
case stop
|
|
46
|
+
case activity
|
|
47
|
+
case done
|
|
48
|
+
case flexibleSpace
|
|
49
|
+
case custom(icon: UIImage?, title: String?, action: (WKWebViewController) -> Void)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public enum NavigationBarPosition: String, Equatable, Codable {
|
|
53
|
+
case none
|
|
54
|
+
case left
|
|
55
|
+
case right
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc public enum NavigationType: Int, Equatable, Codable {
|
|
59
|
+
case linkActivated
|
|
60
|
+
case formSubmitted
|
|
61
|
+
case backForward
|
|
62
|
+
case reload
|
|
63
|
+
case formResubmitted
|
|
64
|
+
case other
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
//! Project version number for Plugin.
|
|
4
|
+
FOUNDATION_EXPORT double PluginVersionNumber;
|
|
5
|
+
|
|
6
|
+
//! Project version string for Plugin.
|
|
7
|
+
FOUNDATION_EXPORT const unsigned char PluginVersionString[];
|
|
8
|
+
|
|
9
|
+
// In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
|
|
10
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <Capacitor/Capacitor.h>
|
|
3
|
+
|
|
4
|
+
// Define the plugin using the CAP_PLUGIN Macro, and
|
|
5
|
+
// each method the plugin supports using the CAP_PLUGIN_METHOD macro.
|
|
6
|
+
CAP_PLUGIN(InAppBrowserPlugin, "InAppBrowser",
|
|
7
|
+
CAP_PLUGIN_METHOD(openWebView, CAPPluginReturnPromise);
|
|
8
|
+
CAP_PLUGIN_METHOD(clearCookies, CAPPluginReturnPromise);
|
|
9
|
+
CAP_PLUGIN_METHOD(getCookies, CAPPluginReturnPromise);
|
|
10
|
+
CAP_PLUGIN_METHOD(clearAllCookies, CAPPluginReturnPromise);
|
|
11
|
+
CAP_PLUGIN_METHOD(clearCache, CAPPluginReturnPromise);
|
|
12
|
+
CAP_PLUGIN_METHOD(reload, CAPPluginReturnPromise);
|
|
13
|
+
CAP_PLUGIN_METHOD(open, CAPPluginReturnPromise);
|
|
14
|
+
CAP_PLUGIN_METHOD(setUrl, CAPPluginReturnPromise);
|
|
15
|
+
CAP_PLUGIN_METHOD(show, CAPPluginReturnPromise);
|
|
16
|
+
CAP_PLUGIN_METHOD(close, CAPPluginReturnPromise);
|
|
17
|
+
CAP_PLUGIN_METHOD(hide, CAPPluginReturnPromise);
|
|
18
|
+
CAP_PLUGIN_METHOD(executeScript, CAPPluginReturnPromise);
|
|
19
|
+
CAP_PLUGIN_METHOD(postMessage, CAPPluginReturnPromise);
|
|
20
|
+
CAP_PLUGIN_METHOD(insertCSS, CAPPluginReturnPromise);
|
|
21
|
+
)
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
import WebKit
|
|
4
|
+
|
|
5
|
+
extension UIColor {
|
|
6
|
+
|
|
7
|
+
convenience init(hexString: String) {
|
|
8
|
+
let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
|
9
|
+
var int = UInt64()
|
|
10
|
+
Scanner(string: hex).scanHexInt64(&int)
|
|
11
|
+
let components = (
|
|
12
|
+
R: CGFloat((int >> 16) & 0xff) / 255,
|
|
13
|
+
G: CGFloat((int >> 08) & 0xff) / 255,
|
|
14
|
+
B: CGFloat((int >> 00) & 0xff) / 255
|
|
15
|
+
)
|
|
16
|
+
self.init(red: components.R, green: components.G, blue: components.B, alpha: 1)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Please read the Capacitor iOS Plugin Development Guide
|
|
23
|
+
* here: https://capacitorjs.com/docs/plugins/ios
|
|
24
|
+
*/
|
|
25
|
+
@objc(InAppBrowserPlugin)
|
|
26
|
+
public class InAppBrowserPlugin: CAPPlugin {
|
|
27
|
+
var navigationWebViewController: UINavigationController?
|
|
28
|
+
private var privacyScreen: UIImageView?
|
|
29
|
+
private var isSetupDone = false
|
|
30
|
+
var currentPluginCall: CAPPluginCall?
|
|
31
|
+
var isPresentAfterPageLoad = false
|
|
32
|
+
var webViewController: WKWebViewController?
|
|
33
|
+
|
|
34
|
+
private func setup() {
|
|
35
|
+
self.isSetupDone = true
|
|
36
|
+
|
|
37
|
+
#if swift(>=4.2)
|
|
38
|
+
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive(_:)), name: UIApplication.didBecomeActiveNotification, object: nil)
|
|
39
|
+
NotificationCenter.default.addObserver(self, selector: #selector(appWillResignActive(_:)), name: UIApplication.willResignActiveNotification, object: nil)
|
|
40
|
+
#else
|
|
41
|
+
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive(_:)), name: .UIApplicationDidBecomeActive, object: nil)
|
|
42
|
+
NotificationCenter.default.addObserver(self, selector: #selector(appWillResignActive(_:)), name: .UIApplicationWillResignActive, object: nil)
|
|
43
|
+
#endif
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func presentView(isAnimated: Bool = true) {
|
|
47
|
+
self.bridge?.viewController?.present(self.navigationWebViewController!, animated: isAnimated, completion: {
|
|
48
|
+
self.currentPluginCall?.resolve()
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@objc func clearAllCookies(_ call: CAPPluginCall) {
|
|
53
|
+
DispatchQueue.main.async {
|
|
54
|
+
let dataStore = WKWebsiteDataStore.default()
|
|
55
|
+
let dataTypes = Set([WKWebsiteDataTypeCookies])
|
|
56
|
+
|
|
57
|
+
dataStore.removeData(ofTypes: dataTypes,
|
|
58
|
+
modifiedSince: Date(timeIntervalSince1970: 0)) {
|
|
59
|
+
call.resolve()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc func clearCache(_ call: CAPPluginCall) {
|
|
65
|
+
DispatchQueue.main.async {
|
|
66
|
+
let dataStore = WKWebsiteDataStore.default()
|
|
67
|
+
let dataTypes = Set([WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
|
|
68
|
+
|
|
69
|
+
dataStore.removeData(ofTypes: dataTypes,
|
|
70
|
+
modifiedSince: Date(timeIntervalSince1970: 0)) {
|
|
71
|
+
call.resolve()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@objc func clearCookies(_ call: CAPPluginCall) {
|
|
77
|
+
guard let url = call.getString("url"),
|
|
78
|
+
let host = URL(string: url)?.host else {
|
|
79
|
+
call.reject("Invalid URL")
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
DispatchQueue.main.async {
|
|
84
|
+
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { cookies in
|
|
85
|
+
for cookie in cookies {
|
|
86
|
+
|
|
87
|
+
if cookie.domain == host || cookie.domain.hasSuffix(".\(host)") || host.hasSuffix(cookie.domain) {
|
|
88
|
+
let semaphore = DispatchSemaphore(value: 1)
|
|
89
|
+
WKWebsiteDataStore.default().httpCookieStore.delete(cookie) {
|
|
90
|
+
semaphore.signal()
|
|
91
|
+
}
|
|
92
|
+
semaphore.wait()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
call.resolve()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@objc func getCookies(_ call: CAPPluginCall) {
|
|
102
|
+
let urlString = call.getString("url") ?? ""
|
|
103
|
+
let includeHttpOnly = call.getBool("includeHttpOnly") ?? true
|
|
104
|
+
|
|
105
|
+
guard let url = URL(string: urlString), let host = url.host else {
|
|
106
|
+
call.reject("Invalid URL")
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
DispatchQueue.main.async {
|
|
111
|
+
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { cookies in
|
|
112
|
+
var cookieDict = [String: String]()
|
|
113
|
+
for cookie in cookies {
|
|
114
|
+
|
|
115
|
+
if (includeHttpOnly || !cookie.isHTTPOnly) && (cookie.domain == host || cookie.domain.hasSuffix(".\(host)") || host.hasSuffix(cookie.domain)) {
|
|
116
|
+
cookieDict[cookie.name] = cookie.value
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
call.resolve(cookieDict)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@objc func openWebView(_ call: CAPPluginCall) {
|
|
126
|
+
if !self.isSetupDone {
|
|
127
|
+
self.setup()
|
|
128
|
+
}
|
|
129
|
+
self.currentPluginCall = call
|
|
130
|
+
|
|
131
|
+
guard let urlString = call.getString("url") else {
|
|
132
|
+
call.reject("Must provide a URL to open")
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if urlString.isEmpty {
|
|
137
|
+
call.reject("URL must not be empty")
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var buttonNearDoneIcon: UIImage?
|
|
142
|
+
if let buttonNearDoneSettings = call.getObject("buttonNearDone") {
|
|
143
|
+
guard let iosSettingsRaw = buttonNearDoneSettings["ios"] else {
|
|
144
|
+
call.reject("IOS settings not found")
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
if !(iosSettingsRaw is JSObject) {
|
|
148
|
+
call.reject("IOS settings are not an object")
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
let iosSettings = iosSettingsRaw as! JSObject
|
|
152
|
+
|
|
153
|
+
guard let iconType = iosSettings["iconType"] as? String else {
|
|
154
|
+
call.reject("buttonNearDone.iconType is empty")
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if iconType != "sf-symbol" && iconType != "asset" {
|
|
158
|
+
call.reject("IconType is neither 'sf-symbol' nor 'asset'")
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
guard let icon = iosSettings["icon"] as? String else {
|
|
162
|
+
call.reject("buttonNearDone.icon is empty")
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if iconType == "sf-symbol" {
|
|
167
|
+
buttonNearDoneIcon = UIImage(systemName: icon)
|
|
168
|
+
} else {
|
|
169
|
+
// UIImage(resource: ImageResource(name: "public/monkey.svg", bundle: Bundle.main))
|
|
170
|
+
buttonNearDoneIcon = UIImage(named: icon, in: Bundle.main, with: nil)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let headers = call.getObject("headers", [:]).mapValues { String(describing: $0 as Any) }
|
|
175
|
+
let closeModal = call.getBool("closeModal", false)
|
|
176
|
+
let closeModalTitle = call.getString("closeModalTitle", "Close")
|
|
177
|
+
let closeModalDescription = call.getString("closeModalDescription", "Are you sure you want to close this window?")
|
|
178
|
+
let closeModalOk = call.getString("closeModalOk", "OK")
|
|
179
|
+
let closeModalCancel = call.getString("closeModalCancel", "Cancel")
|
|
180
|
+
let isInspectable = call.getBool("isInspectable", false)
|
|
181
|
+
let preventDeeplink = call.getBool("preventDeeplink", false)
|
|
182
|
+
let isAnimated = call.getBool("isAnimated", true)
|
|
183
|
+
|
|
184
|
+
var disclaimerContent = call.getObject("shareDisclaimer")
|
|
185
|
+
let toolbarType = call.getString("toolbarType", "")
|
|
186
|
+
let backgroundColor = call.getString("backgroundColor", "black") == "white" ? UIColor.white : UIColor.black
|
|
187
|
+
if toolbarType != "activity" {
|
|
188
|
+
disclaimerContent = nil
|
|
189
|
+
}
|
|
190
|
+
let ignoreUntrustedSSLError = call.getBool("ignoreUntrustedSSLError", false)
|
|
191
|
+
|
|
192
|
+
self.isPresentAfterPageLoad = call.getBool("isPresentAfterPageLoad", false)
|
|
193
|
+
let showReloadButton = call.getBool("showReloadButton", false)
|
|
194
|
+
|
|
195
|
+
let credentials = self.readCredentials(call)
|
|
196
|
+
|
|
197
|
+
DispatchQueue.main.async {
|
|
198
|
+
let url = URL(string: urlString)
|
|
199
|
+
|
|
200
|
+
if self.isPresentAfterPageLoad {
|
|
201
|
+
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials, preventDeeplink: preventDeeplink)
|
|
202
|
+
} else {
|
|
203
|
+
self.webViewController = WKWebViewController.init()
|
|
204
|
+
self.webViewController?.setHeaders(headers: headers)
|
|
205
|
+
self.webViewController?.setCredentials(credentials: credentials)
|
|
206
|
+
self.webViewController?.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
self.webViewController?.source = .remote(url!)
|
|
210
|
+
self.webViewController?.leftNavigationBarItemTypes = self.getToolbarItems(toolbarType: toolbarType) + [.reload]
|
|
211
|
+
self.webViewController?.leftNavigationBarItemTypes = self.getToolbarItems(toolbarType: toolbarType)
|
|
212
|
+
self.webViewController?.toolbarItemTypes = []
|
|
213
|
+
self.webViewController?.doneBarButtonItemPosition = .right
|
|
214
|
+
|
|
215
|
+
self.webViewController?.buttonNearDoneIcon = buttonNearDoneIcon
|
|
216
|
+
|
|
217
|
+
if call.getBool("showArrow", false) {
|
|
218
|
+
self.webViewController?.stopBarButtonItemImage = UIImage(named: "Forward@3x", in: Bundle(for: InAppBrowserPlugin.self), compatibleWith: nil)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
self.webViewController?.capBrowserPlugin = self
|
|
222
|
+
self.webViewController?.title = call.getString("title", "New Window")
|
|
223
|
+
self.webViewController?.shareSubject = call.getString("shareSubject")
|
|
224
|
+
self.webViewController?.shareDisclaimer = disclaimerContent
|
|
225
|
+
self.webViewController?.preShowScript = call.getString("preShowScript")
|
|
226
|
+
self.webViewController?.websiteTitleInNavigationBar = call.getBool("visibleTitle", true)
|
|
227
|
+
if closeModal {
|
|
228
|
+
self.webViewController?.closeModal = true
|
|
229
|
+
self.webViewController?.closeModalTitle = closeModalTitle
|
|
230
|
+
self.webViewController?.closeModalDescription = closeModalDescription
|
|
231
|
+
self.webViewController?.closeModalOk = closeModalOk
|
|
232
|
+
self.webViewController?.closeModalCancel = closeModalCancel
|
|
233
|
+
}
|
|
234
|
+
self.webViewController?.ignoreUntrustedSSLError = ignoreUntrustedSSLError
|
|
235
|
+
self.navigationWebViewController = UINavigationController.init(rootViewController: self.webViewController!)
|
|
236
|
+
self.navigationWebViewController?.navigationBar.isTranslucent = false
|
|
237
|
+
self.navigationWebViewController?.toolbar.isTranslucent = false
|
|
238
|
+
self.navigationWebViewController?.navigationBar.backgroundColor = backgroundColor
|
|
239
|
+
self.navigationWebViewController?.toolbar.backgroundColor = backgroundColor
|
|
240
|
+
self.navigationWebViewController?.toolbar.tintColor = backgroundColor == UIColor.black ? UIColor.white : UIColor.black
|
|
241
|
+
self.navigationWebViewController?.modalPresentationStyle = .fullScreen
|
|
242
|
+
if toolbarType == "blank" {
|
|
243
|
+
self.navigationWebViewController?.navigationBar.isHidden = true
|
|
244
|
+
}
|
|
245
|
+
if showReloadButton {
|
|
246
|
+
let toolbarItems = self.getToolbarItems(toolbarType: toolbarType)
|
|
247
|
+
self.webViewController?.leftNavigationBarItemTypes = toolbarItems + [.reload]
|
|
248
|
+
}
|
|
249
|
+
if !self.isPresentAfterPageLoad {
|
|
250
|
+
self.presentView(isAnimated: isAnimated)
|
|
251
|
+
}
|
|
252
|
+
call.resolve()
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
func getToolbarItems(toolbarType: String) -> [BarButtonItemType] {
|
|
257
|
+
var result: [BarButtonItemType] = []
|
|
258
|
+
if toolbarType == "activity" {
|
|
259
|
+
result.append(.activity)
|
|
260
|
+
} else if toolbarType == "navigation" {
|
|
261
|
+
result.append(.back)
|
|
262
|
+
result.append(.forward)
|
|
263
|
+
}
|
|
264
|
+
return result
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@objc func reload(_ call: CAPPluginCall) {
|
|
268
|
+
self.webViewController?.reload()
|
|
269
|
+
call.resolve()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@objc func setUrl(_ call: CAPPluginCall) {
|
|
273
|
+
guard let urlString = call.getString("url") else {
|
|
274
|
+
call.reject("Cannot get new url to set")
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
guard let url = URL(string: urlString) else {
|
|
279
|
+
call.reject("Invalid URL")
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
self.webViewController?.load(remote: url)
|
|
284
|
+
call.resolve()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@objc func executeScript(_ call: CAPPluginCall) {
|
|
288
|
+
guard let script = call.getString("code") else {
|
|
289
|
+
call.reject("Cannot get script to execute")
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
self.webViewController?.executeScript(script: script)
|
|
293
|
+
call.resolve()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@objc func postMessage(_ call: CAPPluginCall) {
|
|
297
|
+
let eventData = call.getObject("detail", [:])
|
|
298
|
+
// Check if eventData is empty
|
|
299
|
+
if eventData.isEmpty {
|
|
300
|
+
call.reject("Event data must not be empty")
|
|
301
|
+
return
|
|
302
|
+
}
|
|
303
|
+
print("Event data: \(eventData)")
|
|
304
|
+
|
|
305
|
+
self.webViewController?.postMessageToJS(message: eventData)
|
|
306
|
+
call.resolve()
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
func isHexColorCode(_ input: String) -> Bool {
|
|
310
|
+
let hexColorRegex = "^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$"
|
|
311
|
+
|
|
312
|
+
do {
|
|
313
|
+
let regex = try NSRegularExpression(pattern: hexColorRegex)
|
|
314
|
+
let range = NSRange(location: 0, length: input.utf16.count)
|
|
315
|
+
if let _ = regex.firstMatch(in: input, options: [], range: range) {
|
|
316
|
+
return true
|
|
317
|
+
}
|
|
318
|
+
} catch {
|
|
319
|
+
print("Error creating regular expression: \(error)")
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return false
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@objc func open(_ call: CAPPluginCall) {
|
|
326
|
+
if !self.isSetupDone {
|
|
327
|
+
self.setup()
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
let isInspectable = call.getBool("isInspectable", false)
|
|
331
|
+
let preventDeeplink = call.getBool("preventDeeplink", false)
|
|
332
|
+
|
|
333
|
+
self.currentPluginCall = call
|
|
334
|
+
|
|
335
|
+
guard let urlString = call.getString("url") else {
|
|
336
|
+
call.reject("Must provide a URL to open")
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if urlString.isEmpty {
|
|
341
|
+
call.reject("URL must not be empty")
|
|
342
|
+
return
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let headers = call.getObject("headers", [:]).mapValues { String(describing: $0 as Any) }
|
|
346
|
+
|
|
347
|
+
self.isPresentAfterPageLoad = call.getBool("isPresentAfterPageLoad", false)
|
|
348
|
+
|
|
349
|
+
let credentials = self.readCredentials(call)
|
|
350
|
+
|
|
351
|
+
DispatchQueue.main.async {
|
|
352
|
+
let url = URL(string: urlString)
|
|
353
|
+
|
|
354
|
+
if self.isPresentAfterPageLoad {
|
|
355
|
+
self.webViewController = WKWebViewController.init(url: url!, headers: headers, isInspectable: isInspectable, credentials: credentials, preventDeeplink: preventDeeplink)
|
|
356
|
+
} else {
|
|
357
|
+
self.webViewController = WKWebViewController.init()
|
|
358
|
+
self.webViewController?.setHeaders(headers: headers)
|
|
359
|
+
self.webViewController?.setCredentials(credentials: credentials)
|
|
360
|
+
self.webViewController?.setPreventDeeplink(preventDeeplink: preventDeeplink)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
self.webViewController?.source = .remote(url!)
|
|
364
|
+
self.webViewController?.leftNavigationBarItemTypes = [.reload]
|
|
365
|
+
self.webViewController?.toolbarItemTypes = [.back, .forward, .activity]
|
|
366
|
+
self.webViewController?.capBrowserPlugin = self
|
|
367
|
+
self.webViewController?.hasDynamicTitle = true
|
|
368
|
+
self.navigationWebViewController = UINavigationController.init(rootViewController: self.webViewController!)
|
|
369
|
+
self.navigationWebViewController?.navigationBar.isTranslucent = false
|
|
370
|
+
self.navigationWebViewController?.toolbar.isTranslucent = false
|
|
371
|
+
self.navigationWebViewController?.navigationBar.backgroundColor = .white
|
|
372
|
+
let inputString: String = call.getString("toolbarColor", "#ffffff")
|
|
373
|
+
var color: UIColor = UIColor(hexString: "#ffffff")
|
|
374
|
+
if self.isHexColorCode(inputString) {
|
|
375
|
+
color = UIColor(hexString: inputString)
|
|
376
|
+
} else {
|
|
377
|
+
print("\(inputString) is not a valid hex color code.")
|
|
378
|
+
}
|
|
379
|
+
self.navigationWebViewController?.toolbar.backgroundColor = color
|
|
380
|
+
self.navigationWebViewController?.modalPresentationStyle = .fullScreen
|
|
381
|
+
if !self.isPresentAfterPageLoad {
|
|
382
|
+
self.presentView()
|
|
383
|
+
}
|
|
384
|
+
call.resolve()
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
@objc func close(_ call: CAPPluginCall) {
|
|
389
|
+
DispatchQueue.main.async {
|
|
390
|
+
self.navigationWebViewController?.dismiss(animated: true, completion: nil)
|
|
391
|
+
self.notifyListeners("closeEvent", data: ["url": self.webViewController?.url?.absoluteString ?? ""])
|
|
392
|
+
call.resolve()
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private func showPrivacyScreen() {
|
|
397
|
+
if privacyScreen == nil {
|
|
398
|
+
self.privacyScreen = UIImageView()
|
|
399
|
+
if let launchImage = UIImage(named: "LaunchImage") {
|
|
400
|
+
privacyScreen!.image = launchImage
|
|
401
|
+
privacyScreen!.frame = UIScreen.main.bounds
|
|
402
|
+
privacyScreen!.contentMode = .scaleAspectFill
|
|
403
|
+
privacyScreen!.isUserInteractionEnabled = false
|
|
404
|
+
} else if let launchImage = UIImage(named: "Splash") {
|
|
405
|
+
privacyScreen!.image = launchImage
|
|
406
|
+
privacyScreen!.frame = UIScreen.main.bounds
|
|
407
|
+
privacyScreen!.contentMode = .scaleAspectFill
|
|
408
|
+
privacyScreen!.isUserInteractionEnabled = false
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
self.navigationWebViewController?.view.addSubview(self.privacyScreen!)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private func hidePrivacyScreen() {
|
|
415
|
+
self.privacyScreen?.removeFromSuperview()
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@objc func appDidBecomeActive(_ notification: NSNotification) {
|
|
419
|
+
self.hidePrivacyScreen()
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@objc func appWillResignActive(_ notification: NSNotification) {
|
|
423
|
+
self.showPrivacyScreen()
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private func readCredentials(_ call: CAPPluginCall) -> WKWebViewCredentials? {
|
|
427
|
+
var credentials: WKWebViewCredentials?
|
|
428
|
+
let credentialsDict = call.getObject("credentials", [:]).mapValues { String(describing: $0 as Any) }
|
|
429
|
+
if !credentialsDict.isEmpty, let username = credentialsDict["username"], let password = credentialsDict["password"] {
|
|
430
|
+
credentials = WKWebViewCredentials(username: username, password: password)
|
|
431
|
+
}
|
|
432
|
+
return credentials
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSPrincipalClass</key>
|
|
22
|
+
<string></string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|