From 32b772e280242c7420dddc623b80d933f77ad61f Mon Sep 17 00:00:00 2001 From: lanistzhang Date: Mon, 30 Sep 2024 15:09:27 +0800 Subject: [PATCH 1/5] feat: Add keyboardDisplayRequiresUserAction to focus automaticlly in iOS --- .../Classes/InAppWebView/InAppWebView.swift | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift index 43ac03776..8a25f0f61 100755 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift @@ -9,6 +9,75 @@ import Flutter import Foundation import WebKit +// Support `keyboardDisplayRequiresUserAction` to focus automaticlly +typealias OldClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void +typealias NewClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void +extension WKWebView{ + var keyboardDisplayRequiresUserAction: Bool? { + get { + return self.keyboardDisplayRequiresUserAction + } + set { + self.setKeyboardRequiresUserInteraction(newValue ?? true) + } + } + + func setKeyboardRequiresUserInteraction( _ value: Bool) { + guard let WKContentView: AnyClass = NSClassFromString("WKContentView") else { + print("keyboardDisplayRequiresUserAction extension: Cannot find the WKContentView class") + return + } + // For iOS 10, * + let sel_10: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:") + // For iOS 11.3, * + let sel_11_3: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:") + // For iOS 12.2, * + let sel_12_2: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:") + // For iOS 13.0, * + let sel_13_0: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:") + + if let method = class_getInstanceMethod(WKContentView, sel_10) { + let originalImp: IMP = method_getImplementation(method) + let original: OldClosureType = unsafeBitCast(originalImp, to: OldClosureType.self) + let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3) in + original(me, sel_10, arg0, !value, arg2, arg3) + } + let imp: IMP = imp_implementationWithBlock(block) + method_setImplementation(method, imp) + } + + if let method = class_getInstanceMethod(WKContentView, sel_11_3) { + let originalImp: IMP = method_getImplementation(method) + let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self) + let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in + original(me, sel_11_3, arg0, !value, arg2, arg3, arg4) + } + let imp: IMP = imp_implementationWithBlock(block) + method_setImplementation(method, imp) + } + + if let method = class_getInstanceMethod(WKContentView, sel_12_2) { + let originalImp: IMP = method_getImplementation(method) + let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self) + let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in + original(me, sel_12_2, arg0, !value, arg2, arg3, arg4) + } + let imp: IMP = imp_implementationWithBlock(block) + method_setImplementation(method, imp) + } + + if let method = class_getInstanceMethod(WKContentView, sel_13_0) { + let originalImp: IMP = method_getImplementation(method) + let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self) + let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in + original(me, sel_13_0, arg0, !value, arg2, arg3, arg4) + } + let imp: IMP = imp_implementationWithBlock(block) + method_setImplementation(method, imp) + } + } +} + public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIGestureRecognizerDelegate, WKDownloadDelegate, @@ -81,6 +150,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, } self.contextMenu = contextMenu self.initialUserScripts = userScripts + self.keyboardDisplayRequiresUserAction = false uiDelegate = self navigationDelegate = self scrollView.delegate = self From 752da19aa8e36376caccf29e7e89d9048e7d8ed5 Mon Sep 17 00:00:00 2001 From: lanistzhang Date: Mon, 30 Sep 2024 15:11:17 +0800 Subject: [PATCH 2/5] fix: Close keyboard when call `clearFocus` in Android. --- .../webview/in_app_webview/InputAwareWebView.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InputAwareWebView.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InputAwareWebView.java index e4c5e96d7..3a5468a04 100755 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InputAwareWebView.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/in_app_webview/InputAwareWebView.java @@ -150,6 +150,11 @@ public boolean checkInputConnectionProxy(final View view) { public void clearFocus() { super.clearFocus(); + InputMethodManager inputManager = (InputMethodManager) this.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputManager != null) { + inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0); + } + if (useHybridComposition) { return; } From 3fe84549f1d365db9990e18565ff9cd929a13516 Mon Sep 17 00:00:00 2001 From: lanistzhang Date: Mon, 30 Sep 2024 15:16:11 +0800 Subject: [PATCH 3/5] feat: Support `requestFocus` method on WebView --- .../lib/src/in_app_webview/in_app_webview_controller.dart | 3 +++ .../webview/WebViewChannelDelegate.java | 6 ++++++ .../webview/WebViewChannelDelegateMethods.java | 1 + .../lib/src/in_app_webview/in_app_webview_controller.dart | 6 ++++++ .../ios/Classes/InAppWebView/InAppWebView.swift | 4 ++++ .../ios/Classes/InAppWebView/WebViewChannelDelegate.swift | 4 ++++ .../InAppWebView/WebViewChannelDelegateMethods.swift | 1 + .../lib/src/in_app_webview/in_app_webview_controller.dart | 6 ++++++ .../in_app_webview/platform_inappwebview_controller.dart | 7 +++++++ 9 files changed, 38 insertions(+) diff --git a/flutter_inappwebview/lib/src/in_app_webview/in_app_webview_controller.dart b/flutter_inappwebview/lib/src/in_app_webview/in_app_webview_controller.dart index 1544754d3..871afe217 100644 --- a/flutter_inappwebview/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/flutter_inappwebview/lib/src/in_app_webview/in_app_webview_controller.dart @@ -290,6 +290,9 @@ class InAppWebViewController { Future getHitTestResult() => platform.getHitTestResult(); + ///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.requestFocus} + Future requestFocus() => platform.requestFocus(); + ///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.clearFocus} Future clearFocus() => platform.clearFocus(); diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegate.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegate.java index 5f87b93c0..2a6a52a3a 100644 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegate.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegate.java @@ -468,6 +468,12 @@ public void onReceiveValue(String value) { result.success(false); } break; + case requestFocus: + if (webView != null) { + webView.requestFocus(); + } + result.success(true); + break; case clearFocus: if (webView != null) { webView.clearFocus(); diff --git a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegateMethods.java b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegateMethods.java index 3c6d6ae1f..d2a4b5e8e 100644 --- a/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegateMethods.java +++ b/flutter_inappwebview_android/android/src/main/java/com/pichillilorenzo/flutter_inappwebview_android/webview/WebViewChannelDelegateMethods.java @@ -62,6 +62,7 @@ public enum WebViewChannelDelegateMethods { saveWebArchive, zoomIn, zoomOut, + requestFocus, clearFocus, setContextMenu, requestFocusNodeHref, diff --git a/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview_controller.dart b/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview_controller.dart index ceb4bc9a9..1d5c37408 100644 --- a/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/flutter_inappwebview_android/lib/src/in_app_webview/in_app_webview_controller.dart @@ -2241,6 +2241,12 @@ class AndroidInAppWebViewController extends PlatformInAppWebViewController return InAppWebViewHitTestResult(type: type, extra: extra); } + @override + Future requestFocus() async { + Map args = {}; + return await channel?.invokeMethod('requestFocus', args); + } + @override Future clearFocus() async { Map args = {}; diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift index 8a25f0f61..5cf384305 100755 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/InAppWebView.swift @@ -3208,6 +3208,10 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { } } + public func requestFocus() { + self.scrollView.subviews.first?.becomeFirstResponder() + } + public func clearFocus() { self.scrollView.subviews.first?.resignFirstResponder() } diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift index 46bab6d05..39be859a5 100644 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegate.swift @@ -344,6 +344,10 @@ public class WebViewChannelDelegate: ChannelDelegate { result(nil) } break + case .requestFocus: + webView?.requestFocus() + result(true) + break case .clearFocus: webView?.clearFocus() result(true) diff --git a/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift index 899cd769b..29a82bfd4 100644 --- a/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift +++ b/flutter_inappwebview_ios/ios/Classes/InAppWebView/WebViewChannelDelegateMethods.swift @@ -58,6 +58,7 @@ public enum WebViewChannelDelegateMethods: String { case hasOnlySecureContent = "hasOnlySecureContent" case getSelectedText = "getSelectedText" case getHitTestResult = "getHitTestResult" + case requestFocus = "requestFocus" case clearFocus = "clearFocus" case setContextMenu = "setContextMenu" case requestFocusNodeHref = "requestFocusNodeHref" diff --git a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart index 7e847f14f..d5b9b45c7 100644 --- a/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/flutter_inappwebview_ios/lib/src/in_app_webview/in_app_webview_controller.dart @@ -2228,6 +2228,12 @@ class IOSInAppWebViewController extends PlatformInAppWebViewController return InAppWebViewHitTestResult(type: type, extra: extra); } + @override + Future requestFocus() async { + Map args = {}; + return await channel?.invokeMethod('requestFocus', args); + } + @override Future clearFocus() async { Map args = {}; diff --git a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart index 4026e6162..b8ea6066c 100644 --- a/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart +++ b/flutter_inappwebview_platform_interface/lib/src/in_app_webview/platform_inappwebview_controller.dart @@ -1048,6 +1048,13 @@ abstract class PlatformInAppWebViewController extends PlatformInterface 'getHitTestResult is not implemented on the current platform'); } + ///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.requestFocus} + ///{@endtemplate} + Future requestFocus() { + throw UnimplementedError( + 'requestFocus is not implemented on the current platform'); + } + ///{@template flutter_inappwebview_platform_interface.PlatformInAppWebViewController.clearFocus} ///Clears the current focus. On iOS and Android native WebView, it will clear also, for example, the current text selection. /// From 8b05c4861a09658b5fa272ee90de8b4530378f52 Mon Sep 17 00:00:00 2001 From: lanistor Date: Wed, 2 Oct 2024 00:46:07 +0800 Subject: [PATCH 4/5] feat: dart version 3.5 -> 3.4 --- dev_packages/generators/pubspec.yaml | 2 +- flutter_inappwebview/pubspec.yaml | 2 +- flutter_inappwebview_android/pubspec.yaml | 2 +- flutter_inappwebview_ios/pubspec.yaml | 2 +- flutter_inappwebview_macos/pubspec.yaml | 2 +- flutter_inappwebview_platform_interface/pubspec.yaml | 2 +- flutter_inappwebview_web/pubspec.yaml | 2 +- flutter_inappwebview_windows/pubspec.yaml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_packages/generators/pubspec.yaml b/dev_packages/generators/pubspec.yaml index ffa31b464..82bd68784 100755 --- a/dev_packages/generators/pubspec.yaml +++ b/dev_packages/generators/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: none environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview/pubspec.yaml b/flutter_inappwebview/pubspec.yaml index e69c66d4a..5fcd7c8c0 100755 --- a/flutter_inappwebview/pubspec.yaml +++ b/flutter_inappwebview/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ^3.4.0 flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_android/pubspec.yaml b/flutter_inappwebview_android/pubspec.yaml index 9c5739383..4107c9557 100644 --- a/flutter_inappwebview_android/pubspec.yaml +++ b/flutter_inappwebview_android/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_ios/pubspec.yaml b/flutter_inappwebview_ios/pubspec.yaml index bc642819a..23b391fcb 100644 --- a/flutter_inappwebview_ios/pubspec.yaml +++ b/flutter_inappwebview_ios/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_macos/pubspec.yaml b/flutter_inappwebview_macos/pubspec.yaml index 46e2261c6..fc1670621 100644 --- a/flutter_inappwebview_macos/pubspec.yaml +++ b/flutter_inappwebview_macos/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_platform_interface/pubspec.yaml b/flutter_inappwebview_platform_interface/pubspec.yaml index ffce8c177..34690259b 100644 --- a/flutter_inappwebview_platform_interface/pubspec.yaml +++ b/flutter_inappwebview_platform_interface/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_web/pubspec.yaml b/flutter_inappwebview_web/pubspec.yaml index c1146eb87..62e596f30 100644 --- a/flutter_inappwebview_web/pubspec.yaml +++ b/flutter_inappwebview_web/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: diff --git a/flutter_inappwebview_windows/pubspec.yaml b/flutter_inappwebview_windows/pubspec.yaml index 4f09d6896..b05d61367 100644 --- a/flutter_inappwebview_windows/pubspec.yaml +++ b/flutter_inappwebview_windows/pubspec.yaml @@ -14,7 +14,7 @@ topics: - browser environment: - sdk: ^3.5.0 + sdk: ">=3.4.0" flutter: ">=3.24.0" dependencies: From 811f2f202f3e7f505f9782044e6b48a228fba28c Mon Sep 17 00:00:00 2001 From: lanistor Date: Wed, 2 Oct 2024 00:50:22 +0800 Subject: [PATCH 5/5] feat: flutter version 3.24 -> 3.22 --- dev_packages/generators/pubspec.yaml | 2 +- flutter_inappwebview/pubspec.yaml | 2 +- flutter_inappwebview_android/pubspec.yaml | 2 +- flutter_inappwebview_ios/pubspec.yaml | 2 +- flutter_inappwebview_macos/pubspec.yaml | 2 +- flutter_inappwebview_platform_interface/pubspec.yaml | 2 +- flutter_inappwebview_web/pubspec.yaml | 2 +- flutter_inappwebview_windows/pubspec.yaml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev_packages/generators/pubspec.yaml b/dev_packages/generators/pubspec.yaml index 82bd68784..890263e45 100755 --- a/dev_packages/generators/pubspec.yaml +++ b/dev_packages/generators/pubspec.yaml @@ -5,7 +5,7 @@ publish_to: none environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview/pubspec.yaml b/flutter_inappwebview/pubspec.yaml index 5fcd7c8c0..5e7fcfb55 100755 --- a/flutter_inappwebview/pubspec.yaml +++ b/flutter_inappwebview/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ^3.4.0 - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_android/pubspec.yaml b/flutter_inappwebview_android/pubspec.yaml index 4107c9557..de1d0ca37 100644 --- a/flutter_inappwebview_android/pubspec.yaml +++ b/flutter_inappwebview_android/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_ios/pubspec.yaml b/flutter_inappwebview_ios/pubspec.yaml index 23b391fcb..48847217d 100644 --- a/flutter_inappwebview_ios/pubspec.yaml +++ b/flutter_inappwebview_ios/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_macos/pubspec.yaml b/flutter_inappwebview_macos/pubspec.yaml index fc1670621..e42ad182d 100644 --- a/flutter_inappwebview_macos/pubspec.yaml +++ b/flutter_inappwebview_macos/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_platform_interface/pubspec.yaml b/flutter_inappwebview_platform_interface/pubspec.yaml index 34690259b..b03e64ae1 100644 --- a/flutter_inappwebview_platform_interface/pubspec.yaml +++ b/flutter_inappwebview_platform_interface/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_web/pubspec.yaml b/flutter_inappwebview_web/pubspec.yaml index 62e596f30..948193959 100644 --- a/flutter_inappwebview_web/pubspec.yaml +++ b/flutter_inappwebview_web/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: diff --git a/flutter_inappwebview_windows/pubspec.yaml b/flutter_inappwebview_windows/pubspec.yaml index b05d61367..3905cce34 100644 --- a/flutter_inappwebview_windows/pubspec.yaml +++ b/flutter_inappwebview_windows/pubspec.yaml @@ -15,7 +15,7 @@ topics: environment: sdk: ">=3.4.0" - flutter: ">=3.24.0" + flutter: ">=3.22.3" dependencies: flutter: