From 11d2b91ab22f7c33f100cd43b11c0f7834a3411d Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Sat, 29 May 2021 01:01:10 +0900 Subject: [PATCH 1/2] Add javaScriptTextInputPanel to RxWKUIDelegate --- .../Sources/RxWKUIDelegateEvents+Rx.swift | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/RxWebKit/Sources/RxWKUIDelegateEvents+Rx.swift b/RxWebKit/Sources/RxWKUIDelegateEvents+Rx.swift index 862c69d..87b105c 100644 --- a/RxWebKit/Sources/RxWKUIDelegateEvents+Rx.swift +++ b/RxWebKit/Sources/RxWKUIDelegateEvents+Rx.swift @@ -16,6 +16,7 @@ import WebKit extension Reactive where Base: WKWebView { public typealias JSAlertEvent = (webView: WKWebView, message: String, frame: WKFrameInfo, handler: () -> ()) public typealias JSConfirmEvent = (webView: WKWebView, message: String, frame: WKFrameInfo, handler: (Bool) -> ()) + public typealias JSTextInputEvent = (webView: WKWebView, prompt: String, defaultText: String?, frame: WKFrameInfo, handler: (String?) -> ()) #if os(iOS) public typealias CommitPreviewEvent = (webView: WKWebView, controller: UIViewController) #endif @@ -67,6 +68,28 @@ extension Reactive where Base: WKWebView { return ControlEvent(events: source) } + /// Reactive wrapper for `func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Swift.Void)` + public var javaScriptTextInputPanel: ControlEvent { + typealias __CompletionHandler = @convention(block) (String?) -> () + let source:Observable = uiDelegate + .methodInvoked(.jsTextInput).map { args in + let view = try castOrThrow(WKWebView.self, args[0]) + let prompt = try castOrThrow(String.self, args[1]) + let defaultText = try castOrThrow(String?.self, args[2]) + let frame = try castOrThrow(WKFrameInfo.self, args[3]) + var closureObject: AnyObject? = nil + var mutableArgs = args + mutableArgs.withUnsafeMutableBufferPointer { ptr in + closureObject = ptr[4] as AnyObject + } + let __completionBlockPtr = UnsafeRawPointer(Unmanaged.passUnretained(closureObject as AnyObject).toOpaque()) + let handler = unsafeBitCast(__completionBlockPtr, to: __CompletionHandler.self) + return (view, prompt, defaultText, frame, handler) + } + + return ControlEvent(events: source) + } + #if os(iOS) /// Reactive wrappper for `func webView(_ webView: WKWebView, commitPreviewingViewController previewingViewController: UIViewController)` @available(iOS 10.0, *) @@ -87,6 +110,7 @@ extension Reactive where Base: WKWebView { fileprivate extension Selector { static let jsAlert = #selector(WKUIDelegate.webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)) static let jsConfirm = #selector(WKUIDelegate.webView(_:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)) + static let jsTextInput = #selector(WKUIDelegate.webView(_:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)) #if os(iOS) @available(iOS 10.0, *) From 3d3817e3901df5930dbcbf67e2a732f138dc8b2d Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Sat, 29 May 2021 01:01:25 +0900 Subject: [PATCH 2/2] Add example for javaScriptTextInputPanel --- ...vaScriptTextInputPanelViewController.swift | 55 +++++++++++++++++++ RxWebKit.xcodeproj/project.pbxproj | 4 ++ 2 files changed, 59 insertions(+) create mode 100644 Example/JavaScriptTextInputPanelViewController.swift diff --git a/Example/JavaScriptTextInputPanelViewController.swift b/Example/JavaScriptTextInputPanelViewController.swift new file mode 100644 index 0000000..ca1e005 --- /dev/null +++ b/Example/JavaScriptTextInputPanelViewController.swift @@ -0,0 +1,55 @@ +// +// JavaScriptTextInputPanelViewController.swift +// Example +// +// Created by TTOzzi on 2021/05/29. +// Copyright © 2021 RxSwift Community. All rights reserved. +// + +import UIKit +import WebKit +import RxWebKit +import RxSwift +import RxCocoa + +class JavaScriptTextInputPanelViewController: UIViewController { + + let bag = DisposeBag() + let wkWebView = WKWebView() + + override func viewDidLoad() { + super.viewDidLoad() + view.addSubview(wkWebView) + wkWebView.load(URLRequest(url: URL(string: "https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_prompt")!)) + + wkWebView.rx + .javaScriptTextInputPanel + .debug("javaScriptTextInputPanel") + .subscribe(onNext: { [weak self] webView, prompt, defaultText, frame, handler in + guard let self = self else { return } + let alert = UIAlertController(title: "JavaScriptTextInput", message: prompt, preferredStyle: .alert) + alert.addTextField { textField in + textField.text = defaultText + } + alert.addAction( + UIAlertAction(title: "Confirm", style: .default, handler: { _ in + let text = alert.textFields?.first?.text + handler(text) + }) + ) + alert.addAction( + UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in + handler(nil) + }) + ) + self.present(alert, animated: true, completion: nil) + }) + .disposed(by: bag) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + let originY = UIApplication.shared.statusBarFrame.maxY + wkWebView.frame = CGRect(x: 0, y: originY, width: view.bounds.width, height: view.bounds.height) + } +} diff --git a/RxWebKit.xcodeproj/project.pbxproj b/RxWebKit.xcodeproj/project.pbxproj index ef86fbb..fdac78d 100644 --- a/RxWebKit.xcodeproj/project.pbxproj +++ b/RxWebKit.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 42F426D11C6623C5001FED46 /* RxWebKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 42F426D01C6623C5001FED46 /* RxWebKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 42F426D61C6623C5001FED46 /* RxWebKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 42F426CE1C6623C5001FED46 /* RxWebKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 42F426DC1C662CF9001FED46 /* Rx+WebKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42F426DB1C662CF9001FED46 /* Rx+WebKit.swift */; }; + 449905C02661474C00C6E514 /* JavaScriptTextInputPanelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449905BF2661474C00C6E514 /* JavaScriptTextInputPanelViewController.swift */; }; C4135FFE22875FBE0061933C /* RxWebKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CB7D5322874EE700FB8D99 /* RxWebKitTests.swift */; }; C4136011228764840061933C /* Nimble.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C4D323B3228748A0004B05A5 /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C4136012228764840061933C /* Quick.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C4D323B2228748A0004B05A5 /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -138,6 +139,7 @@ 42F426D01C6623C5001FED46 /* RxWebKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RxWebKit.h; sourceTree = ""; }; 42F426D21C6623C5001FED46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42F426DB1C662CF9001FED46 /* Rx+WebKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Rx+WebKit.swift"; sourceTree = ""; }; + 449905BF2661474C00C6E514 /* JavaScriptTextInputPanelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptTextInputPanelViewController.swift; sourceTree = ""; }; C41360162287651B0061933C /* RxRelay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxRelay.framework; path = Carthage/Build/iOS/RxRelay.framework; sourceTree = ""; }; C41360192288135F0061933C /* HasEventsBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HasEventsBehavior.swift; sourceTree = ""; }; C4607FCF1FA0DAC9002DA12F /* RxWKUIDelegateProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxWKUIDelegateProxy.swift; sourceTree = ""; }; @@ -257,6 +259,7 @@ 42F426B41C66223E001FED46 /* ViewController.swift */, C4607FDA1FA0E68F002DA12F /* JavaScriptAlertPanelViewController.swift */, C4607FDC1FA0F1D3002DA12F /* JavaScriptConfirmPanelViewController.swift */, + 449905BF2661474C00C6E514 /* JavaScriptTextInputPanelViewController.swift */, C4607FE01FA0F549002DA12F /* AuthChallengeViewController.swift */, C4878CD51FA1066C00B12C60 /* FailedRequestViewController.swift */, C4878CD71FA117E900B12C60 /* RedirectViewController.swift */, @@ -504,6 +507,7 @@ C4607FDD1FA0F1D3002DA12F /* JavaScriptConfirmPanelViewController.swift in Sources */, C4878CD61FA1066C00B12C60 /* FailedRequestViewController.swift in Sources */, 42F426B61C66223E001FED46 /* AppDelegate.swift in Sources */, + 449905C02661474C00C6E514 /* JavaScriptTextInputPanelViewController.swift in Sources */, C4607FDB1FA0E68F002DA12F /* JavaScriptAlertPanelViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0;