Skip to content

Commit

Permalink
updated requestFocus implementation, macos: implemented requestFocus …
Browse files Browse the repository at this point in the history
…and clearFocus WebView methods, implemented workaround for macos #2380
  • Loading branch information
pichillilorenzo committed Nov 4, 2024
1 parent bd5960d commit a273635
Show file tree
Hide file tree
Showing 21 changed files with 443 additions and 23 deletions.
5 changes: 5 additions & 0 deletions flutter_inappwebview/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Implemented security features to better manage access to the native javascript b
- Added `PlatformInAppLocalhostServer.onData` parameter to set a custom on data server callback
- Added `javaScriptBridgeEnabled`, `javaScriptBridgeOriginAllowList`, `javaScriptBridgeForMainFrameOnly`, `pluginScriptsOriginAllowList`, `pluginScriptsForMainFrameOnly`, `javaScriptHandlersOriginAllowList`, `javaScriptHandlersForMainFrameOnly`, `scrollMultiplier` InAppWebViewSettings parameters
- Added `setJavaScriptBridgeName`, `getJavaScriptBridgeName` static WebView controller methods
- Added `requestFocus` WebView method
- Added `onProcessFailed` WebView event
- Added `JavaScriptHandlerFunctionData` type
- Deprecated `JavaScriptHandlerCallback` type in favor of `JavaScriptHandlerFunction` type
Expand All @@ -27,6 +28,7 @@ Implemented security features to better manage access to the native javascript b
- Added `InAppWebViewController.enableSlowWholeDocumentDraw` static method
- Added `CookieManager.flush` method
- Added support for `UserScript.forMainFrameOnly` parameter
- Implemented `requestFocus` WebView method
- Updated UserScript at document end implementation
- Updated `InAppWebViewController.takeScreenshot` implementation to support screenshot out of visible viewport when `InAppWebViewController.enableSlowWholeDocumentDraw` is called
- Fixed "After dispose a InAppWebViewKeepAlive using InAppWebViewController.disposeKeepAlive. NullPointerException is thrown when main activity enter destroyed state." [#2025](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2025)
Expand All @@ -35,10 +37,13 @@ Implemented security features to better manage access to the native javascript b
- Merged "Update Android Cookie Expiration date format to 24-hour format (HH)" [#2389](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2389) (thanks to [takuyaaaaaaahaaaaaa](https://github.com/takuyaaaaaaahaaaaaa))

#### macOS and iOS Platforms
- Implemented `requestFocus` WebView method
- Updated ConsoleLogJS internal PluginScript to main-frame only as using it on non-main frames could cause issues such as [#1738](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1738)
- Moved `WKUserContentController` initialization on `preWKWebViewConfiguration` to fix possible `undefined is not an object (evaluating 'window.webkit.messageHandlers')` javascript error
- Added support for `UserScript.allowedOriginRules` parameter
- Merged "change priority of DispatchQueue" [#2322](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2322) (thanks to [nnnlog](https://github.com/nnnlog))
- macOS: Implemented also `clearFocus` WebView method
- macOS: Implemented workaround for "[macOS] Copy Shortcut does not work if TextField outside of WebView has focus" [#2380](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2380)

#### Windows Platform
- Updated `scrollMultiplier` default value from 6 to 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:collection';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Expand Down Expand Up @@ -116,7 +117,7 @@ class _InAppWebViewExampleScreenState extends State<InAppWebViewExampleScreen> {
key: webViewKey,
webViewEnvironment: webViewEnvironment,
initialUrlRequest:
URLRequest(url: WebUri('https://flutter.dev')),
URLRequest(url: WebUri('https://flutter.dev')),
// initialUrlRequest:
// URLRequest(url: WebUri(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html')),
// initialFile: "assets/index.html",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import 'dart:core';
import 'dart:typed_data';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';

import '../print_job/main.dart';
import '../web_message/main.dart';
import '../web_storage/web_storage.dart';
import 'android/in_app_webview_controller.dart';
import 'apple/in_app_webview_controller.dart';

import '../print_job/main.dart';

///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController}
class InAppWebViewController {
///Use [InAppWebViewController] instead.
Expand Down Expand Up @@ -289,7 +285,11 @@ class InAppWebViewController {
platform.getHitTestResult();

///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.requestFocus}
Future<void> requestFocus() => platform.requestFocus();
Future<bool?> requestFocus(
{FocusDirection? direction,
InAppWebViewRect? previouslyFocusedRect}) =>
platform.requestFocus(
direction: direction, previouslyFocusedRect: previouslyFocusedRect);

///{@macro flutter_inappwebview_platform_interface.PlatformInAppWebViewController.clearFocus}
Future<void> clearFocus() => platform.clearFocus();
Expand Down
1 change: 1 addition & 0 deletions flutter_inappwebview_android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Added `InAppWebViewController.enableSlowWholeDocumentDraw` static method
- Added `CookieManager.flush` method
- Added support for `UserScript.forMainFrameOnly` parameter
- Implemented `requestFocus` WebView method
- Updated UserScript at document end implementation
- Updated `InAppWebViewController.takeScreenshot` implementation to support screenshot out of visible viewport when `InAppWebViewController.enableSlowWholeDocumentDraw` is called
- Fixed "After dispose a InAppWebViewKeepAlive using InAppWebViewController.disposeKeepAlive. NullPointerException is thrown when main activity enter destroyed state." [#2025](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2025)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.pichillilorenzo.flutter_inappwebview_android.types;

import android.graphics.Rect;

import androidx.annotation.Nullable;

import java.util.HashMap;
import java.util.Map;

public class InAppWebViewRect {
private double height;
private double width;
private double x;
private double y;

public InAppWebViewRect(double height, double width, double x, double y) {
this.height = height;
this.width = width;
this.x = x;
this.y = y;
}

@Nullable
public static InAppWebViewRect fromMap(@Nullable Map<String, Object> map) {
if (map == null) {
return null;
}
double height = (double) map.get("height");
double width = (double) map.get("width");
double x = (double) map.get("x");
double y = (double) map.get("y");
return new InAppWebViewRect(height, width, x, y);
}

public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("height", height);
map.put("width", width);
map.put("x", x);
map.put("y", y);
return map;
}

public Rect toRect() {
return new Rect((int) x, (int) y, (int) (x + width), (int) (y + height));
}

public double getHeight() {
return height;
}

public void setHeight(double height) {
this.height = height;
}

public double getWidth() {
return width;
}

public void setWidth(double width) {
this.width = width;
}

public double getX() {
return x;
}

public void setX(double x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(double y) {
this.y = y;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

InAppWebViewRect that = (InAppWebViewRect) o;
return Double.compare(height, that.height) == 0 && Double.compare(width, that.width) == 0 && Double.compare(x, that.x) == 0 && Double.compare(y, that.y) == 0;
}

@Override
public int hashCode() {
int result = Double.hashCode(height);
result = 31 * result + Double.hashCode(width);
result = 31 * result + Double.hashCode(x);
result = 31 * result + Double.hashCode(y);
return result;
}

@Override
public String toString() {
return "InAppWebViewRect{" +
"height=" + height +
", width=" + width +
", x=" + x +
", y=" + y +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.pichillilorenzo.flutter_inappwebview_android.webview;

import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.webkit.ValueCallback;
Expand Down Expand Up @@ -29,6 +30,7 @@
import com.pichillilorenzo.flutter_inappwebview_android.types.HitTestResult;
import com.pichillilorenzo.flutter_inappwebview_android.types.HttpAuthResponse;
import com.pichillilorenzo.flutter_inappwebview_android.types.HttpAuthenticationChallenge;
import com.pichillilorenzo.flutter_inappwebview_android.types.InAppWebViewRect;
import com.pichillilorenzo.flutter_inappwebview_android.types.JavaScriptHandlerFunctionData;
import com.pichillilorenzo.flutter_inappwebview_android.types.JsAlertResponse;
import com.pichillilorenzo.flutter_inappwebview_android.types.JsBeforeUnloadResponse;
Expand Down Expand Up @@ -477,9 +479,20 @@ public void onReceiveValue(String value) {
break;
case requestFocus:
if (webView != null) {
webView.requestFocus();
boolean resultValue = false;
Integer direction = (Integer) call.argument("direction");
InAppWebViewRect previouslyFocusedRect = InAppWebViewRect.fromMap((Map<String, Object>) call.argument("previouslyFocusedRect"));
if (direction != null && previouslyFocusedRect != null) {
resultValue = webView.requestFocus(direction, previouslyFocusedRect.toRect());
} else if (direction != null) {
resultValue = webView.requestFocus(direction);
} else {
resultValue = webView.requestFocus();
}
result.success(resultValue);
} else {
result.success(false);
}
result.success(true);
break;
case setContextMenu:
if (webView != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2240,9 +2240,13 @@ class AndroidInAppWebViewController extends PlatformInAppWebViewController
}

@override
Future<void> requestFocus() async {
Future<bool?> requestFocus(
{FocusDirection? direction,
InAppWebViewRect? previouslyFocusedRect}) async {
Map<String, dynamic> args = <String, dynamic>{};
return await channel?.invokeMethod('requestFocus', args);
args.putIfAbsent("direction", () => direction?.toNativeValue());
args.putIfAbsent("previouslyFocusedRect", () => previouslyFocusedRect?.toMap());
return await channel?.invokeMethod<bool>('requestFocus', args);
}

@override
Expand Down
1 change: 1 addition & 0 deletions flutter_inappwebview_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## 1.2.0-beta.1

- Updated flutter_inappwebview_platform_interface version to ^1.4.0
- Implemented `requestFocus` WebView method
- Updated ConsoleLogJS internal PluginScript to main-frame only as using it on non-main frames could cause issues such as [#1738](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1738)
- Added support for `UserScript.allowedOriginRules` parameter
- Moved `WKUserContentController` initialization on `preWKWebViewConfiguration` to fix possible `undefined is not an object (evaluating 'window.webkit.messageHandlers')` javascript error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3259,12 +3259,12 @@ if(window.\(JavaScriptBridgeJS.get_JAVASCRIPT_BRIDGE_NAME())[\(_callHandlerID)]
}
}

public func clearFocus() {
self.scrollView.subviews.first?.resignFirstResponder()
public func clearFocus() -> Bool {
return self.scrollView.subviews.first?.resignFirstResponder() ?? false
}

public func requestFocus() {
self.scrollView.subviews.first?.becomeFirstResponder()
public func requestFocus() -> Bool {
return self.scrollView.subviews.first?.becomeFirstResponder() ?? false
}

public func getCertificate() -> SslCertificate? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,10 @@ public class WebViewChannelDelegate: ChannelDelegate {
}
break
case .clearFocus:
webView?.clearFocus()
result(true)
result(webView?.clearFocus())
break
case .requestFocus:
webView?.requestFocus()
result(true)
result(webView?.requestFocus())
break
case .setContextMenu:
if let webView = webView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2233,9 +2233,13 @@ class IOSInAppWebViewController extends PlatformInAppWebViewController
}

@override
Future<void> requestFocus() async {
Future<bool?> requestFocus(
{FocusDirection? direction,
InAppWebViewRect? previouslyFocusedRect}) async {
Map<String, dynamic> args = <String, dynamic>{};
return await channel?.invokeMethod('requestFocus', args);
args.putIfAbsent("direction", () => direction?.toNativeValue());
args.putIfAbsent("previouslyFocusedRect", () => previouslyFocusedRect?.toMap());
return await channel?.invokeMethod<bool>('requestFocus', args);
}

@override
Expand Down
2 changes: 2 additions & 0 deletions flutter_inappwebview_macos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
## 1.2.0-beta.1

- Updated flutter_inappwebview_platform_interface version to ^1.4.0
- Implemented `requestFocus`, `clearFocus` WebView methods
- Updated ConsoleLogJS internal PluginScript to main-frame only as using it on non-main frames could cause issues such as [#1738](https://github.com/pichillilorenzo/flutter_inappwebview/issues/1738)
- Added support for `UserScript.allowedOriginRules` parameter
- Moved `WKUserContentController` initialization on `preWKWebViewConfiguration` to fix possible `undefined is not an object (evaluating 'window.webkit.messageHandlers')` javascript error
- Merged "change priority of DispatchQueue" [#2322](https://github.com/pichillilorenzo/flutter_inappwebview/pull/2322) (thanks to [nnnlog](https://github.com/nnnlog))
- Implemented workaround for "[macOS] Copy Shortcut does not work if TextField outside of WebView has focus" [#2380](https://github.com/pichillilorenzo/flutter_inappwebview/issues/2380)

## 1.1.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';
import 'headless_in_app_webview.dart';

import '../find_interaction/find_interaction_controller.dart';
import 'headless_in_app_webview.dart';
import 'in_app_webview_controller.dart';

/// Object specifying creation parameters for creating a [PlatformInAppWebViewWidget].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview_platform_interface/flutter_inappwebview_platform_interface.dart';

import '../in_app_browser/in_app_browser.dart';
Expand Down Expand Up @@ -188,6 +189,13 @@ class MacOSInAppWebViewController extends PlatformInAppWebViewController
}

Future<dynamic> _handleMethod(MethodCall call) async {
if (call.method == "_onMouseDown") {
// Workaround for https://github.com/pichillilorenzo/flutter_inappwebview/issues/2380
// TODO: remove when Flutter fixes this
FocusManager.instance.primaryFocus?.unfocus();
return;
}

if (PlatformInAppWebViewController.debugLoggingSettings.enabled &&
call.method != "onCallJsHandler") {
_debugLog(call.method, call.arguments);
Expand Down Expand Up @@ -2202,6 +2210,22 @@ class MacOSInAppWebViewController extends PlatformInAppWebViewController
return await channel?.invokeMethod<String?>('getSelectedText', args);
}

@override
Future<bool?> requestFocus(
{FocusDirection? direction,
InAppWebViewRect? previouslyFocusedRect}) async {
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent("direction", () => direction?.toNativeValue());
args.putIfAbsent("previouslyFocusedRect", () => previouslyFocusedRect?.toMap());
return await channel?.invokeMethod<bool>('requestFocus', args);
}

@override
Future<void> clearFocus() async {
Map<String, dynamic> args = <String, dynamic>{};
return await channel?.invokeMethod('clearFocus', args);
}

@override
Future<List<MetaTag>> getMetaTags() async {
List<MetaTag> metaTags = [];
Expand Down
Loading

0 comments on commit a273635

Please sign in to comment.