diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index c5564afcb94..6bd586155fa 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 3.4.0 +* Adds support to set text zoom of a page. See `AndroidWebViewController.setTextZoom`. * Aligns Dart and Flutter SDK constraints. ## 3.3.2 diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java index 989747256b0..6fa20feb1d0 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/GeneratedAndroidWebView.java @@ -1603,6 +1603,8 @@ public interface WebSettingsHostApi { void setAllowFileAccess(@NonNull Long instanceId, @NonNull Boolean enabled); + void setTextZoom(@NonNull Long instanceId, @NonNull Long textZoom); + /** The codec used by WebSettingsHostApi. */ static MessageCodec getCodec() { return new StandardMessageCodec(); @@ -2050,6 +2052,39 @@ static void setup(BinaryMessenger binaryMessenger, WebSettingsHostApi api) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.WebSettingsHostApi.setTextZoom", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + ArrayList args = (ArrayList) message; + assert args != null; + Number instanceIdArg = (Number) args.get(0); + if (instanceIdArg == null) { + throw new NullPointerException("instanceIdArg unexpectedly null."); + } + Number textZoomArg = (Number) args.get(1); + if (textZoomArg == null) { + throw new NullPointerException("textZoomArg unexpectedly null."); + } + api.setTextZoom( + (instanceIdArg == null) ? null : instanceIdArg.longValue(), + (textZoomArg == null) ? null : textZoomArg.longValue()); + wrapped.add(0, null); + } catch (Error | RuntimeException exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } } } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java index 98fd4fcfb53..2215320e6af 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebSettingsHostApiImpl.java @@ -120,4 +120,10 @@ public void setAllowFileAccess(Long instanceId, Boolean enabled) { final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); webSettings.setAllowFileAccess(enabled); } + + @Override + public void setTextZoom(Long instanceId, Long textZoom) { + final WebSettings webSettings = (WebSettings) instanceManager.getInstance(instanceId); + webSettings.setTextZoom(textZoom.intValue()); + } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java index 3217316ff56..3abb4247c18 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java @@ -107,4 +107,10 @@ public void setBuiltInZoomControls() { testHostApiImpl.setBuiltInZoomControls(0L, true); verify(mockWebSettings).setBuiltInZoomControls(true); } + + @Test + public void setTextZoom() { + testHostApiImpl.setTextZoom(0L, 100L); + verify(mockWebSettings).setTextZoom(100); + } } diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart index 1ab30a9ea1f..1f80e51d5ab 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.dart @@ -591,6 +591,13 @@ class WebSettings extends JavaObject { return api.setAllowFileAccessFromInstance(this, enabled); } + /// Sets the text zoom of the page in percent. + /// + /// The default is 100. See https://developer.android.com/reference/android/webkit/WebSettings#setTextZoom(int) + Future setTextZoom(int textZoom) { + return api.setSetTextZoomFromInstance(this, textZoom); + } + @override WebSettings copy() { return WebSettings.detached(); diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.g.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.g.dart index 5210879262e..6c9ba8e66fb 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.g.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview.g.dart @@ -1250,6 +1250,28 @@ class WebSettingsHostApi { return; } } + + Future setTextZoom(int arg_instanceId, int arg_textZoom) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setTextZoom', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_textZoom]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else { + return; + } + } } class JavaScriptChannelHostApi { diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart index 127a2fa58ef..0db0f047727 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_api_impls.dart @@ -434,6 +434,14 @@ class WebSettingsHostApiImpl extends WebSettingsHostApi { return setSupportZoom(instanceManager.getIdentifier(instance)!, support); } + /// Helper method to convert instances ids to objects. + Future setSetTextZoomFromInstance( + WebSettings instance, + int textZoom, + ) { + return setTextZoom(instanceManager.getIdentifier(instance)!, textZoom); + } + /// Helper method to convert instances ids to objects. Future setLoadWithOverviewModeFromInstance( WebSettings instance, diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart index 6bd3dc03746..3a7d0777e21 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart @@ -355,6 +355,12 @@ class AndroidWebViewController extends PlatformWebViewController { return _webView.settings.setMediaPlaybackRequiresUserGesture(require); } + /// Sets the text zoom of the page in percent. + /// + /// The default is 100. + Future setTextZoom(int textZoom) => + _webView.settings.setTextZoom(textZoom); + /// Sets the callback that is invoked when the client should show a file /// selector. Future setOnShowFileSelector( diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart index 7f4d362c927..b8c22e56f1e 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -218,6 +218,8 @@ abstract class WebSettingsHostApi { void setBuiltInZoomControls(int instanceId, bool enabled); void setAllowFileAccess(int instanceId, bool enabled); + + void setTextZoom(int instanceId, int textZoom); } @HostApi(dartHostTestHandler: 'TestJavaScriptChannelHostApi') diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 16d9eda1e86..32172631309 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.3.2 +version: 3.4.0 environment: sdk: ">=2.17.0 <3.0.0" diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart index 43bab384e0c..a9a4b0e49bb 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart @@ -885,6 +885,22 @@ void main() { verify(mockSettings.setMediaPlaybackRequiresUserGesture(true)).called(1); }); + test('setTextZoom', () async { + final MockWebView mockWebView = MockWebView(); + final MockWebSettings mockSettings = MockWebSettings(); + final AndroidWebViewController controller = createControllerWithMocks( + mockWebView: mockWebView, + mockSettings: mockSettings, + ); + + clearInteractions(mockWebView); + + await controller.setTextZoom(100); + + verify(mockWebView.settings).called(1); + verify(mockSettings.setTextZoom(100)).called(1); + }); + test('webViewIdentifier', () { final MockWebView mockWebView = MockWebView(); final InstanceManager instanceManager = InstanceManager( diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart index 4bb2afb614b..2aaab4f2c89 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart @@ -654,6 +654,15 @@ class MockAndroidWebViewController extends _i1.Mock returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override + _i9.Future setTextZoom(int? textZoom) => (super.noSuchMethod( + Invocation.method( + #setTextZoom, + [textZoom], + ), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) as _i9.Future); + @override _i9.Future setOnShowFileSelector( _i9.Future> Function(_i8.FileSelectorParams)? onShowFileSelector) => @@ -1737,6 +1746,15 @@ class MockWebSettings extends _i1.Mock implements _i2.WebSettings { returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override + _i9.Future setTextZoom(int? textZoom) => (super.noSuchMethod( + Invocation.method( + #setTextZoom, + [textZoom], + ), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) as _i9.Future); + @override _i2.WebSettings copy() => (super.noSuchMethod( Invocation.method( #copy, diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart index 236d87da44e..79b5b3fdcd0 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.dart @@ -497,6 +497,14 @@ void main() { test('copy', () { expect(webSettings.copy(), isA()); }); + + test('setTextZoom', () { + webSettings.setTextZoom(100); + verify(mockPlatformHostApi.setTextZoom( + webSettingsInstanceId, + 100, + )); + }); }); group('JavaScriptChannel', () { diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.mocks.dart index 0b5afbaf5b1..0de71948cb8 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_test.mocks.dart @@ -525,6 +525,21 @@ class MockTestWebSettingsHostApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override + void setTextZoom( + int? instanceId, + int? textZoom, + ) => + super.noSuchMethod( + Invocation.method( + #setTextZoom, + [ + instanceId, + textZoom, + ], + ), + returnValueForMissingStub: null, + ); } /// A class which mocks [TestWebStorageHostApi]. diff --git a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart index 03489ce5c1e..0562bb7b09d 100644 --- a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart @@ -269,6 +269,15 @@ class MockWebSettings extends _i1.Mock implements _i2.WebSettings { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override + _i5.Future setTextZoom(int? textZoom) => (super.noSuchMethod( + Invocation.method( + #setTextZoom, + [textZoom], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override _i2.WebSettings copy() => (super.noSuchMethod( Invocation.method( #copy, diff --git a/packages/webview_flutter/webview_flutter_android/test/test_android_webview.g.dart b/packages/webview_flutter/webview_flutter_android/test/test_android_webview.g.dart index 1b372e62b2c..f1a19ecf0ed 100644 --- a/packages/webview_flutter/webview_flutter_android/test/test_android_webview.g.dart +++ b/packages/webview_flutter/webview_flutter_android/test/test_android_webview.g.dart @@ -720,6 +720,8 @@ abstract class TestWebSettingsHostApi { void setAllowFileAccess(int instanceId, bool enabled); + void setTextZoom(int instanceId, int textZoom); + static void setup(TestWebSettingsHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -1012,6 +1014,28 @@ abstract class TestWebSettingsHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebSettingsHostApi.setTextZoom', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setTextZoom was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setTextZoom was null, expected non-null int.'); + final int? arg_textZoom = (args[1] as int?); + assert(arg_textZoom != null, + 'Argument for dev.flutter.pigeon.WebSettingsHostApi.setTextZoom was null, expected non-null int.'); + api.setTextZoom(arg_instanceId!, arg_textZoom!); + return []; + }); + } + } } }