-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
revert: don't use ios pods package until we publish it (#17)
* feat: remove env for compatibility * revert: don't use ios pods package until we publish it
- Loading branch information
1 parent
e96e177
commit 3f51337
Showing
8 changed files
with
279 additions
and
12 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# EXAMPLE USAGE: | ||
# | ||
# Refer for explanation to following link: | ||
# https://github.com/evilmartians/lefthook/blob/master/docs/configuration.md | ||
# | ||
# pre-push: | ||
# commands: | ||
# packages-audit: | ||
# tags: frontend security | ||
# run: yarn audit | ||
# gems-audit: | ||
# tags: backend security | ||
# run: bundle audit | ||
# | ||
# pre-commit: | ||
# parallel: true | ||
# commands: | ||
# eslint: | ||
# glob: "*.{js,ts,jsx,tsx}" | ||
# run: yarn eslint {staged_files} | ||
# rubocop: | ||
# tags: backend style | ||
# glob: "*.rb" | ||
# exclude: '(^|/)(application|routes)\.rb$' | ||
# run: bundle exec rubocop --force-exclusion {all_files} | ||
# govet: | ||
# tags: backend style | ||
# files: git ls-files -m | ||
# glob: "*.go" | ||
# run: go vet {files} | ||
# scripts: | ||
# "hello.js": | ||
# runner: node | ||
# "any.go": | ||
# runner: go run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import SafariServices | ||
import WebKit | ||
import SwiftUI | ||
|
||
class WebViewModel: ObservableObject { | ||
@Published var webView: WKWebView? = nil | ||
public init() {} | ||
} | ||
|
||
enum CustomError: Error { | ||
case message(String) | ||
} | ||
|
||
public struct PasskeysMobileView: View { | ||
@ObservedObject private var viewModel: WebViewModel | ||
|
||
public init() { | ||
self.viewModel = WebViewModel() | ||
} | ||
|
||
public var body: some View { | ||
let delegate = WebviewDelegate() | ||
|
||
Group { | ||
if let url = URL(string: "https://wallet-d.passkeys.foundation?relay") { | ||
Webview( | ||
url: url, | ||
uiDelegate: delegate, | ||
onWebViewCreated: { webView in | ||
self.viewModel.webView = webView | ||
} | ||
) | ||
.ignoresSafeArea() | ||
.navigationTitle("Passkeys") | ||
.navigationBarTitleDisplayMode(.inline) | ||
} else { | ||
Text("Error: Invalid URL") | ||
} | ||
} | ||
} | ||
|
||
public func callAsyncJavaScript(_ script: String, completion: @escaping (Result<Any?, Error>) -> Void) { | ||
guard let webviewInstance = viewModel.webView else { | ||
completion(.failure(CustomError.message("WebView not found"))) | ||
return | ||
} | ||
|
||
Task { | ||
do { | ||
let jsResult = try await webviewInstance.callAsyncJavaScript( | ||
script, | ||
arguments: [:], | ||
contentWorld: .page | ||
) | ||
|
||
if let jsResult = jsResult as? String, | ||
let jsonData = jsResult.data(using: .utf8), | ||
let jsonObject = try? JSONSerialization.jsonObject(with: jsonData) { | ||
completion(.success(jsonObject)) | ||
} else { | ||
completion(.failure(CustomError.message("Invalid JavaScript response format"))) | ||
} | ||
} catch { | ||
completion(.failure(error)) | ||
} | ||
} | ||
} | ||
|
||
public func callMethod(_ method: String, data: [String: Any]?, completion: @escaping (Result<Any?, Error>) -> Void) { | ||
let dataJSON: String | ||
if let data = data, | ||
let jsonData = try? JSONSerialization.data(withJSONObject: data, options: []), | ||
let jsonString = String(data: jsonData, encoding: .utf8) { | ||
dataJSON = jsonString | ||
} else { | ||
dataJSON = "{}" | ||
} | ||
|
||
let script = """ | ||
const result = window.\(method)(\(dataJSON)); | ||
if (result instanceof Promise) { | ||
return result | ||
.then(resolved => JSON.stringify(resolved)) | ||
.catch(error => { throw error; }); | ||
} else { | ||
return JSON.stringify(result); | ||
} | ||
""" | ||
callAsyncJavaScript(script, completion: completion) | ||
} | ||
} | ||
|
||
struct SafariView: UIViewControllerRepresentable { | ||
let url: URL | ||
let onDismiss: () -> Void | ||
|
||
func makeUIViewController(context: Context) -> SFSafariViewController { | ||
let safariVC = SFSafariViewController(url: url) | ||
safariVC.delegate = context.coordinator | ||
return safariVC | ||
} | ||
|
||
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {} | ||
|
||
func makeCoordinator() -> Coordinator { | ||
Coordinator(onDismiss: onDismiss) | ||
} | ||
|
||
class Coordinator: NSObject, SFSafariViewControllerDelegate { | ||
let onDismiss: () -> Void | ||
|
||
init(onDismiss: @escaping () -> Void) { | ||
self.onDismiss = onDismiss | ||
} | ||
|
||
func safariViewControllerDidFinish(_ controller: SFSafariViewController) { | ||
onDismiss() | ||
} | ||
} | ||
} | ||
|
||
class WebviewDelegate: NSObject, WKUIDelegate { | ||
private weak var hostingController: UIViewController? | ||
|
||
func presentSafariView(from viewController: UIViewController, url: URL) { | ||
let safariView = SafariView(url: url, onDismiss: { | ||
viewController.dismiss(animated: true) | ||
self.hostingController = nil | ||
}) | ||
let hostingController = UIHostingController(rootView: safariView) | ||
self.hostingController = hostingController | ||
viewController.present(hostingController, animated: true) | ||
} | ||
|
||
func closeSafariView() { | ||
hostingController?.dismiss(animated: true) { | ||
self.hostingController = nil | ||
} | ||
} | ||
|
||
func getPresentedViewController() -> UIViewController? { | ||
if let reactNativeController = (NSClassFromString("RCTPresentedViewController") as? () -> UIViewController)?() { | ||
return reactNativeController | ||
} | ||
|
||
var topController = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController | ||
while let presentedController = topController?.presentedViewController { | ||
topController = presentedController | ||
} | ||
return topController | ||
} | ||
|
||
func openSafariView(url: String) { | ||
guard let viewController = getPresentedViewController(), | ||
let safariURL = URL(string: url) else { | ||
print("Failed to retrieve presented view controller or invalid URL.") | ||
return | ||
} | ||
presentSafariView(from: viewController, url: safariURL) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import WebKit | ||
import SwiftUI | ||
|
||
struct Webview: UIViewRepresentable { | ||
let url: URL | ||
let uiDelegate: WebviewDelegate | ||
var onWebViewCreated: ((WKWebView) -> Void)? | ||
|
||
func makeCoordinator() -> Coordinator { | ||
Coordinator(self) | ||
} | ||
|
||
func makeUIView(context: Context) -> WKWebView { | ||
let configuration = WKWebViewConfiguration() | ||
configuration.websiteDataStore = WKWebsiteDataStore.default() | ||
|
||
let contentController = WKUserContentController() | ||
contentController.add(context.coordinator, name: "closeSigner") | ||
contentController.add(context.coordinator, name: "openSigner") | ||
configuration.userContentController = contentController | ||
|
||
let js = """ | ||
if (!window.nativeBridge) { | ||
window.nativeBridge = {}; | ||
} | ||
window.nativeBridge.closeSigner = function() { | ||
window.webkit.messageHandlers.closeSigner.postMessage(null); | ||
}; | ||
window.nativeBridge.openSigner = function(url) { | ||
if (typeof url !== 'string') throw new Error('url is not a string') | ||
window.webkit.messageHandlers.openSigner.postMessage(url); | ||
} | ||
""" | ||
contentController.addUserScript(WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: false)) | ||
|
||
let webView = WKWebView(frame: .zero, configuration: configuration) | ||
webView.uiDelegate = uiDelegate | ||
if #available(iOS 16.4, *) { | ||
webView.isInspectable = true | ||
} | ||
|
||
webView.load(URLRequest(url: url)) | ||
|
||
DispatchQueue.main.async { | ||
self.onWebViewCreated?(webView) | ||
} | ||
|
||
return webView | ||
} | ||
|
||
func updateUIView(_ webView: WKWebView, context: Context) { | ||
DispatchQueue.main.async { | ||
self.onWebViewCreated?(webView) | ||
} | ||
} | ||
|
||
class Coordinator: NSObject, WKScriptMessageHandler { | ||
var parent: Webview | ||
|
||
init(_ parent: Webview) { | ||
self.parent = parent | ||
} | ||
|
||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { | ||
if message.name == "closeSigner" { | ||
DispatchQueue.main.async { | ||
self.parent.uiDelegate.closeSafariView() | ||
} | ||
} | ||
if message.name == "openSigner" { | ||
if let url = message.body as? String { | ||
DispatchQueue.main.async { | ||
self.parent.uiDelegate.openSafariView(url: url) | ||
} | ||
} else { | ||
print("url is not a String") | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters