diff --git a/.gitignore b/.gitignore index 8eaeaff8de55..2edcfa00e584 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .atom/ .idea/ .vscode/ +**/.fvm/ .packages .pub/ diff --git a/packages/webview_flutter/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/webview_flutter/example/pubspec.yaml index 4d8d7889d733..478acb9b4479 100644 --- a/packages/webview_flutter/webview_flutter/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/example/pubspec.yaml @@ -38,3 +38,9 @@ flutter: - assets/sample_video.mp4 - assets/www/index.html - assets/www/styles/style.css + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../../webview_flutter/webview_flutter_platform_interface diff --git a/packages/webview_flutter/webview_flutter/pubspec.yaml b/packages/webview_flutter/webview_flutter/pubspec.yaml index a494f9e9276c..0f57ff99bf61 100644 --- a/packages/webview_flutter/webview_flutter/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter/pubspec.yaml @@ -31,3 +31,9 @@ dev_dependencies: sdk: flutter mockito: ^5.3.2 plugin_platform_interface: ^2.1.3 + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../webview_flutter/webview_flutter_platform_interface diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index ed6c546ed147..455f72fe261a 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.3.1 + +* Added `setOnContentOffsetChanged` method to the `AndroidWebViewController`. + ## 3.3.0 * Adds support to access native `WebView`. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ContentOffsetChangedListener.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ContentOffsetChangedListener.java new file mode 100644 index 000000000000..5737261f9601 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ContentOffsetChangedListener.java @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.webviewflutter; + +public interface ContentOffsetChangedListener { + void onContentOffsetChange(int left, int top, int oldLeft, int oldTop); +} 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 425f6c1415bd..0066a936d21a 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 @@ -692,6 +692,8 @@ void removeJavaScriptChannel( void setBackgroundColor(@NonNull Long instanceId, @NonNull Long color); + void enableContentOffsetChangedListener(@NonNull Long instanceId, @NonNull Boolean enabled); + /** The codec used by WebViewHostApi. */ static MessageCodec getCodec() { return WebViewHostApiCodec.INSTANCE; @@ -1558,6 +1560,40 @@ public void error(Throwable error) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewHostApi.enableContentOffsetChangedListener", + 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."); + } + Boolean enabledArg = (Boolean) args.get(1); + if (enabledArg == null) { + throw new NullPointerException("enabledArg unexpectedly null."); + } + api.enableContentOffsetChangedListener( + (instanceIdArg == null) ? null : instanceIdArg.longValue(), enabledArg); + 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. */ @@ -2438,6 +2474,41 @@ public void onDownloadStart( }); } } + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class WebViewFlutterApi { + private final BinaryMessenger binaryMessenger; + + public WebViewFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + /** The codec used by WebViewFlutterApi. */ + static MessageCodec getCodec() { + return new StandardMessageCodec(); + } + + public void onScrollPosChange( + @NonNull Long webViewInstanceIdArg, + @NonNull Long xArg, + @NonNull Long yArg, + @NonNull Long oldXArg, + @NonNull Long oldYArg, + Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(webViewInstanceIdArg, xArg, yArg, oldXArg, oldYArg)), + channelReply -> { + callback.reply(null); + }); + } + } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface WebChromeClientHostApi { void create(@NonNull Long instanceId); diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewExtendedApi.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewExtendedApi.java new file mode 100644 index 000000000000..7adad9219c1b --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewExtendedApi.java @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.webviewflutter; + +import androidx.annotation.Nullable; +/** Define extending APIs for {@link android.webkit.WebView} */ +public interface WebViewExtendedApi { + void setContentOffsetChangedListener( + @Nullable ContentOffsetChangedListener contentOffsetChangedListener); +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterApiImpl.java new file mode 100644 index 000000000000..3e7844aaf687 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterApiImpl.java @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.webviewflutter; + +import android.webkit.WebView; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewFlutterApi; + +/** + * Flutter Api implementation for {@link ContentOffsetChangedListener}. + * + *

Passes arguments of callbacks methods from a {@link ContentOffsetChangedListener} to Dart. + */ +public class WebViewFlutterApiImpl extends WebViewFlutterApi { + private final InstanceManager instanceManager; + + /** + * Creates a Flutter api that sends messages to Dart. + * + * @param binaryMessenger handles sending messages to Dart + * @param instanceManager maintains instances stored to communicate with Dart objects + */ + public WebViewFlutterApiImpl(BinaryMessenger binaryMessenger, InstanceManager instanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + } + + /** Passes arguments from {@link ContentOffsetChangedListener#onContentOffsetChange} to Dart. */ + public void onScrollPosChange( + WebView webView, long x, long y, long oldX, long oldY, Reply callback) { + final Long webViewIdentifier = instanceManager.getIdentifierForStrongReference(webView); + if (webViewIdentifier == null) { + throw new IllegalStateException("Could not find identifier for WebView."); + } + onScrollPosChange(webViewIdentifier, x, y, oldX, oldY, callback); + } +} diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java index 04a9735e0281..c092c8971239 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java @@ -92,6 +92,7 @@ private void setUp( instanceManager, binaryMessenger, new WebViewHostApiImpl.WebViewProxy(), + new WebViewFlutterApiImpl(binaryMessenger, instanceManager), context, containerView); javaScriptChannelHostApi = diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java index 77d535b78aed..cfc3f8918c98 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewHostApiImpl.java @@ -16,6 +16,7 @@ import androidx.annotation.Nullable; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.platform.PlatformView; +import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewFlutterApi; import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewHostApi; import java.util.Map; import java.util.Objects; @@ -31,6 +32,7 @@ public class WebViewHostApiImpl implements WebViewHostApi { // Only used with WebView using virtual displays. @Nullable private final View containerView; private final BinaryMessenger binaryMessenger; + private final WebViewFlutterApi webViewFlutterApi; private Context context; @@ -77,9 +79,11 @@ public void setWebContentsDebuggingEnabled(boolean enabled) { } /** Implementation of {@link WebView} that can be used as a Flutter {@link PlatformView}s. */ - public static class WebViewPlatformView extends WebView implements PlatformView { + public static class WebViewPlatformView extends WebView + implements PlatformView, WebViewExtendedApi { private WebViewClient currentWebViewClient; private WebChromeClientHostApiImpl.SecureWebChromeClient currentWebChromeClient; + private @Nullable ContentOffsetChangedListener contentOffsetChangedListener; /** * Creates a {@link WebViewPlatformView}. @@ -129,6 +133,20 @@ public void setWebChromeClient(WebChromeClient client) { public WebChromeClient getWebChromeClient() { return currentWebChromeClient; } + + @Override + protected void onScrollChanged(int l, int t, int oldL, int oldT) { + super.onScrollChanged(l, t, oldL, oldT); + if (contentOffsetChangedListener != null) { + contentOffsetChangedListener.onContentOffsetChange(l, t, oldL, oldT); + } + } + + @Override + public void setContentOffsetChangedListener( + ContentOffsetChangedListener contentOffsetChangedListener) { + this.contentOffsetChangedListener = contentOffsetChangedListener; + } } /** @@ -137,9 +155,10 @@ public WebChromeClient getWebChromeClient() { */ @SuppressLint("ViewConstructor") public static class InputAwareWebViewPlatformView extends InputAwareWebView - implements PlatformView { + implements PlatformView, WebViewExtendedApi { private WebViewClient currentWebViewClient; private WebChromeClientHostApiImpl.SecureWebChromeClient currentWebChromeClient; + private @Nullable ContentOffsetChangedListener contentOffsetChangedListener; /** * Creates a {@link InputAwareWebViewPlatformView}. @@ -206,6 +225,20 @@ public void setWebChromeClient(WebChromeClient client) { currentWebChromeClient = (WebChromeClientHostApiImpl.SecureWebChromeClient) client; currentWebChromeClient.setWebViewClient(currentWebViewClient); } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (contentOffsetChangedListener != null) { + contentOffsetChangedListener.onContentOffsetChange(l, t, oldl, oldt); + } + } + + @Override + public void setContentOffsetChangedListener( + ContentOffsetChangedListener contentOffsetChangedListener) { + this.contentOffsetChangedListener = contentOffsetChangedListener; + } } /** @@ -221,11 +254,13 @@ public WebViewHostApiImpl( InstanceManager instanceManager, BinaryMessenger binaryMessenger, WebViewProxy webViewProxy, + WebViewFlutterApi webViewFlutterApi, Context context, @Nullable View containerView) { this.instanceManager = instanceManager; this.binaryMessenger = binaryMessenger; this.webViewProxy = webViewProxy; + this.webViewFlutterApi = webViewFlutterApi; this.context = context; this.containerView = containerView; } @@ -420,6 +455,30 @@ public void setBackgroundColor(Long instanceId, Long color) { webView.setBackgroundColor(color.intValue()); } + @Override + public void enableContentOffsetChangedListener( + @NonNull Long instanceId, @NonNull Boolean enabled) { + final WebView webView = (WebView) instanceManager.getInstance(instanceId); + if (webView instanceof WebViewExtendedApi) { + if (enabled) { + ((WebViewExtendedApi) webView) + .setContentOffsetChangedListener( + (left, top, oldLeft, oldTop) -> { + webViewFlutterApi.onScrollPosChange( + instanceId, + (long) left, + (long) top, + (long) oldLeft, + (long) oldTop, + reply -> {}); + }); + + } else { + ((WebViewExtendedApi) webView).setContentOffsetChangedListener(null); + } + } + } + /** Maintains instances used to communicate with the corresponding WebView Dart object. */ public InstanceManager getInstanceManager() { return instanceManager; diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java index 1721ccdce8e4..a7c9a2d0a423 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java @@ -6,7 +6,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -37,6 +39,8 @@ public class WebViewTest { @Mock WebViewHostApiImpl.WebViewProxy mockWebViewProxy; + @Mock public GeneratedAndroidWebView.WebViewFlutterApi mockWebViewFlutterApi; + @Mock Context mockContext; @Mock BinaryMessenger mockBinaryMessenger; @@ -52,7 +56,12 @@ public void setUp() { .thenReturn(mockWebView); testHostApiImpl = new WebViewHostApiImpl( - testInstanceManager, mockBinaryMessenger, mockWebViewProxy, mockContext, null); + testInstanceManager, + mockBinaryMessenger, + mockWebViewProxy, + mockWebViewFlutterApi, + mockContext, + null); testHostApiImpl.create(0L, true); } @@ -314,4 +323,21 @@ public void destroy() { assertTrue(destroyCalled[0]); } + + @Test + public void disableContentOffsetChangedListener() { + testHostApiImpl.enableContentOffsetChangedListener(0L, false); + verify(mockWebView).setContentOffsetChangedListener(null); + } + + @Test + public void enableContentOffsetChangedListener() { + final ArgumentCaptor modeCaptor = + ArgumentCaptor.forClass(ContentOffsetChangedListener.class); + testHostApiImpl.enableContentOffsetChangedListener(0L, true); + verify(mockWebView).setContentOffsetChangedListener(modeCaptor.capture()); + assertNotNull(modeCaptor.getValue()); + modeCaptor.getValue().onContentOffsetChange(0, 1, 2, 3); + verify(mockWebViewFlutterApi).onScrollPosChange(eq(0L), eq(0L), eq(1L), eq(2L), eq(3L), any()); + } } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index 75f01b457b3a..497b3c38135f 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -32,7 +32,6 @@ The navigation delegate is set to block navigation to the youtube website. '''; - const String kLocalExamplePage = ''' @@ -51,7 +50,6 @@ const String kLocalExamplePage = ''' '''; - const String kTransparentBackgroundPage = ''' @@ -75,20 +73,16 @@ const String kTransparentBackgroundPage = ''' class WebViewExample extends StatefulWidget { const WebViewExample({Key? key, this.cookieManager}) : super(key: key); - final PlatformWebViewCookieManager? cookieManager; - @override State createState() => _WebViewExampleState(); } class _WebViewExampleState extends State { late final PlatformWebViewController _controller; - @override void initState() { super.initState(); - _controller = PlatformWebViewController( AndroidWebViewControllerCreationParams(), ) @@ -134,8 +128,12 @@ Page resource error: }, )) ..loadRequest(LoadRequestParams( - uri: Uri.parse('https://flutter.dev'), - )); + uri: Uri.parse('https://dantri.com.vn'), + )) + ..setOnContentOffsetChanged((int left, int top, int oldLeft, int oldTop) { + debugPrint( + 'Scroll offset change to left = $left y = $top oldX = $oldLeft oldY = $oldTop'); + }); } @override @@ -143,8 +141,8 @@ Page resource error: return Scaffold( backgroundColor: const Color(0xFF4CAF50), appBar: AppBar( - title: const Text('Flutter WebView example'), - // This drop down menu demonstrates that Flutter widgets can be shown over the web view. + title: const Text( + 'Flutter WebView example'), // This drop down menu demonstrates that Flutter widgets can be shown over the web view. actions: [ NavigationControls(webViewController: _controller), SampleMenu( @@ -201,10 +199,8 @@ class SampleMenu extends StatelessWidget { const PlatformWebViewCookieManagerCreationParams(), ), super(key: key); - final PlatformWebViewController webViewController; late final PlatformWebViewCookieManager cookieManager; - @override Widget build(BuildContext context) { return PopupMenuButton( @@ -347,9 +343,9 @@ class SampleMenu extends StatelessWidget { } Future _onListCache() { - return webViewController.runJavaScript('caches.keys()' - // ignore: missing_whitespace_between_adjacent_strings - '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' + return webViewController.runJavaScript( + 'caches.keys()' // ignore: missing_whitespace_between_adjacent_strings + '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' // ignore: missing_whitespace_between_adjacent_strings '.then((caches) => Toaster.postMessage(caches))'); } @@ -448,10 +444,8 @@ class SampleMenu extends StatelessWidget { final String tmpDir = (await getTemporaryDirectory()).path; final File indexFile = File( {tmpDir, 'www', 'index.html'}.join(Platform.pathSeparator)); - await indexFile.create(recursive: true); await indexFile.writeAsString(kLocalExamplePage); - return indexFile.path; } } @@ -459,9 +453,7 @@ class SampleMenu extends StatelessWidget { class NavigationControls extends StatelessWidget { const NavigationControls({Key? key, required this.webViewController}) : super(key: key); - final PlatformWebViewController webViewController; - @override Widget build(BuildContext context) { return Row( diff --git a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml index 0fc0daf84118..e6b348f92fbc 100644 --- a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml @@ -35,3 +35,9 @@ flutter: - assets/sample_video.mp4 - assets/www/index.html - assets/www/styles/style.css + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../../webview_flutter/webview_flutter_platform_interface 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 1ab30a9ea1fd..05ffef3ee68f 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 @@ -59,6 +59,10 @@ class JavaObject with Copyable { } } +/// Signature for the `onScrollChanged` callback responsible for listening to scroll's offset changed events. +typedef ScrollChangedCallback = void Function( + int left, int top, int oldLeft, int oldTop); + /// An Android View that displays web pages. /// /// **Basic usage** @@ -112,6 +116,9 @@ class WebView extends JavaObject { /// The [WebSettings] object used to control the settings for this WebView. late final WebSettings settings = WebSettings(this); + /// The [ScrollChangedCallback] object used to listen for scroll changed events. + late ScrollChangedCallback? onScrollChanged; + /// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application. /// /// This flag can be enabled in order to facilitate debugging of web layouts @@ -397,6 +404,11 @@ class WebView extends JavaObject { return api.setBackgroundColorFromInstance(this, color.value); } + ///Toggle scroll listener for this WebView + Future enableContentOffsetChangedListener(bool enabled) { + return api.enableContentOffsetChangedListenerFromInstance(this, enabled); + } + @override WebView copy() { return WebView.detached(useHybridComposition: useHybridComposition); 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 d3c306a10238..84c71b2948de 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 @@ -942,6 +942,30 @@ class WebViewHostApi { return; } } + + Future enableContentOffsetChangedListener( + int arg_instanceId, bool arg_enabled) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.enableContentOffsetChangedListener', + codec, + binaryMessenger: _binaryMessenger); + final List? replyList = await channel + .send([arg_instanceId, arg_enabled]) 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 WebSettingsHostApi { @@ -1673,6 +1697,49 @@ abstract class DownloadListenerFlutterApi { } } +abstract class WebViewFlutterApi { + static const MessageCodec codec = StandardMessageCodec(); + + void onScrollPosChange( + int webViewInstanceId, int x, int y, int oldX, int oldY); + + static void setup(WebViewFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null.'); + final List args = (message as List?)!; + final int? arg_webViewInstanceId = (args[0] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.'); + final int? arg_x = (args[1] as int?); + assert(arg_x != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.'); + final int? arg_y = (args[2] as int?); + assert(arg_y != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.'); + final int? arg_oldX = (args[3] as int?); + assert(arg_oldX != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.'); + final int? arg_oldY = (args[4] as int?); + assert(arg_oldY != null, + 'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.'); + api.onScrollPosChange( + arg_webViewInstanceId!, arg_x!, arg_y!, arg_oldX!, arg_oldY!); + return; + }); + } + } + } +} + class WebChromeClientHostApi { /// Constructor for [WebChromeClientHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default 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 127a2fa58ef8..9db471133e14 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 @@ -45,6 +45,7 @@ class AndroidWebViewFlutterApis { WebChromeClientFlutterApiImpl? webChromeClientFlutterApi, JavaScriptChannelFlutterApiImpl? javaScriptChannelFlutterApi, FileChooserParamsFlutterApiImpl? fileChooserParamsFlutterApi, + WebViewFlutterApiImpl? webViewFlutterApi, }) { this.javaObjectFlutterApi = javaObjectFlutterApi ?? JavaObjectFlutterApiImpl(); @@ -58,6 +59,7 @@ class AndroidWebViewFlutterApis { javaScriptChannelFlutterApi ?? JavaScriptChannelFlutterApiImpl(); this.fileChooserParamsFlutterApi = fileChooserParamsFlutterApi ?? FileChooserParamsFlutterApiImpl(); + this.webViewFlutterApi = webViewFlutterApi ?? WebViewFlutterApiImpl(); } static bool _haveBeenSetUp = false; @@ -85,6 +87,9 @@ class AndroidWebViewFlutterApis { /// Flutter Api for [FileChooserParams]. late final FileChooserParamsFlutterApiImpl fileChooserParamsFlutterApi; + /// Flutter Api for [ScrollListener]. + late final WebViewFlutterApiImpl webViewFlutterApi; + /// Ensures all the Flutter APIs have been setup to receive calls from native code. void ensureSetUp() { if (!_haveBeenSetUp) { @@ -94,6 +99,7 @@ class AndroidWebViewFlutterApis { WebChromeClientFlutterApi.setup(webChromeClientFlutterApi); JavaScriptChannelFlutterApi.setup(javaScriptChannelFlutterApi); FileChooserParamsFlutterApi.setup(fileChooserParamsFlutterApi); + WebViewFlutterApi.setup(webViewFlutterApi); _haveBeenSetUp = true; } } @@ -344,6 +350,13 @@ class WebViewHostApiImpl extends WebViewHostApi { Future setBackgroundColorFromInstance(WebView instance, int color) { return setBackgroundColor(instanceManager.getIdentifier(instance)!, color); } + + /// Helper method to convert instances ids to objects. + Future enableContentOffsetChangedListenerFromInstance( + WebView instance, bool enabled) { + return enableContentOffsetChangedListener( + instanceManager.getIdentifier(instance)!, enabled); + } } /// Host api implementation for [WebSettings]. @@ -905,3 +918,25 @@ class FileChooserParamsFlutterApiImpl extends FileChooserParamsFlutterApi { ); } } + +/// Flutter api implementation for [ScrollListenerFlutterApi]. +class WebViewFlutterApiImpl extends WebViewFlutterApi { + /// Constructs a [JavaScriptChannelFlutterApiImpl]. + WebViewFlutterApiImpl({InstanceManager? instanceManager}) + : instanceManager = instanceManager ?? JavaObject.globalInstanceManager; + + /// Maintains instances stored to communicate with java objects. + final InstanceManager instanceManager; + + @override + void onScrollPosChange( + int webViewInstanceId, int x, int y, int oldX, int oldY) { + final WebView? webViewInstance = instanceManager + .getInstanceWithWeakReference(webViewInstanceId) as WebView?; + assert( + webViewInstance != null, + 'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId', + ); + webViewInstance!.onScrollChanged!(x, y, oldX, oldY); + } +} 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 6bd3dc03746c..0397a325a6c1 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 @@ -350,6 +350,14 @@ class AndroidWebViewController extends PlatformWebViewController { Future setUserAgent(String? userAgent) => _webView.settings.setUserAgentString(userAgent); + @override + Future setOnContentOffsetChanged( + void Function(int left, int top, int oldLeft, int oldTop)? + onOffsetChange) async { + _webView.onScrollChanged = onOffsetChange; + _webView.enableContentOffsetChangedListener(onOffsetChange != null); + } + /// Sets the restrictions that apply on automatic media playback. Future setMediaPlaybackRequiresUserGesture(bool require) { return _webView.settings.setMediaPlaybackRequiresUserGesture(require); diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/legacy/webview_android_widget.dart b/packages/webview_flutter/webview_flutter_android/lib/src/legacy/webview_android_widget.dart index cd4ba820cf4c..ead7dca568e8 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/legacy/webview_android_widget.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/legacy/webview_android_widget.dart @@ -96,21 +96,20 @@ class _WebViewAndroidWidgetState extends State { /// Implementation of [WebViewPlatformController] with the Android WebView api. class WebViewAndroidPlatformController extends WebViewPlatformController { /// Construct a [WebViewAndroidPlatformController]. - WebViewAndroidPlatformController({ - required bool useHybridComposition, - required CreationParams creationParams, - required this.callbacksHandler, - required this.javascriptChannelRegistry, - @visibleForTesting this.webViewProxy = const WebViewProxy(), - @visibleForTesting - this.flutterAssetManager = const android_webview.FlutterAssetManager(), - @visibleForTesting android_webview.WebStorage? webStorage, - }) : webStorage = webStorage ?? android_webview.WebStorage.instance, + WebViewAndroidPlatformController( + {required bool useHybridComposition, + required CreationParams creationParams, + required this.callbacksHandler, + required this.javascriptChannelRegistry, + @visibleForTesting this.webViewProxy = const WebViewProxy(), + @visibleForTesting this.flutterAssetManager = + const android_webview.FlutterAssetManager(), + @visibleForTesting android_webview.WebStorage? webStorage}) + : webStorage = webStorage ?? android_webview.WebStorage.instance, assert(creationParams.webSettings?.hasNavigationDelegate != null), super(callbacksHandler) { - webView = webViewProxy.createWebView( - useHybridComposition: useHybridComposition, - ); + webView = + webViewProxy.createWebView(useHybridComposition: useHybridComposition); webView.settings.setDomStorageEnabled(true); webView.settings.setJavaScriptCanOpenWindowsAutomatically(true); 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 7f4d362c9273..225f3722ae56 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webview.dart @@ -189,6 +189,8 @@ abstract class WebViewHostApi { void setWebChromeClient(int instanceId, int? clientInstanceId); void setBackgroundColor(int instanceId, int color); + + void enableContentOffsetChangedListener(int instanceId, bool enabled); } @HostApi(dartHostTestHandler: 'TestWebSettingsHostApi') @@ -287,6 +289,12 @@ abstract class DownloadListenerFlutterApi { ); } +@FlutterApi() +abstract class WebViewFlutterApi { + void onScrollPosChange( + int webViewInstanceId, int x, int y, int oldX, int oldY); +} + @HostApi(dartHostTestHandler: 'TestWebChromeClientHostApi') abstract class WebChromeClientHostApi { void create(int instanceId); diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index ac8971006ba2..fcfecf312245 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/plugins/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.0 +version: 3.3.1 environment: sdk: ">=2.17.0 <3.0.0" @@ -30,3 +30,9 @@ dev_dependencies: sdk: flutter mockito: ^5.3.2 pigeon: ^4.2.14 + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../webview_flutter/webview_flutter_platform_interface 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 43bab384e0cc..dfa3e4d72532 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 @@ -870,6 +870,18 @@ void main() { verify(mockWebView.settings).called(1); verify(mockSettings.setUserAgentString('Test Framework')).called(1); }); + + test('setScrollListener', () async { + final MockWebView mockWebView = MockWebView(); + final AndroidWebViewController controller = createControllerWithMocks( + mockWebView: mockWebView, + ); + await controller.setOnContentOffsetChanged( + (int left, int top, int oldLeft, int oldTop) {}); + verify(mockWebView.enableContentOffsetChangedListener(true)).called(1); + await controller.setOnContentOffsetChanged(null); + verify(mockWebView.enableContentOffsetChangedListener(false)).called(1); + }); }); test('setMediaPlaybackRequiresUserGesture', () async { 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 01885caff54c..a5b82c436b87 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 @@ -349,6 +349,12 @@ class MockAndroidNavigationDelegate extends _i1.Mock class MockAndroidWebViewController extends _i1.Mock implements _i8.AndroidWebViewController { @override + int get webViewIdentifier => (super.noSuchMethod( + Invocation.getter(#webViewIdentifier), + returnValue: 0, + returnValueForMissingStub: 0, + ) as int); + @override _i3.PlatformWebViewControllerCreationParams get params => (super.noSuchMethod( Invocation.getter(#params), returnValue: _FakePlatformWebViewControllerCreationParams_4( @@ -638,6 +644,23 @@ class MockAndroidWebViewController extends _i1.Mock returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override + _i9.Future setOnContentOffsetChanged( + void Function( + int, + int, + int, + int, + )? + onOffsetChange) => + (super.noSuchMethod( + Invocation.method( + #setOnContentOffsetChanged, + [onOffsetChange], + ), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) as _i9.Future); + @override _i9.Future setMediaPlaybackRequiresUserGesture(bool? require) => (super.noSuchMethod( Invocation.method( @@ -650,11 +673,11 @@ class MockAndroidWebViewController extends _i1.Mock @override _i9.Future setOnShowFileSelector( _i9.Future> Function(_i8.FileSelectorParams)? - onShowFileSelectorCallback) => + onShowFileSelector) => (super.noSuchMethod( Invocation.method( #setOnShowFileSelector, - [onShowFileSelectorCallback], + [onShowFileSelector], ), returnValue: _i9.Future.value(), returnValueForMissingStub: _i9.Future.value(), @@ -1776,6 +1799,15 @@ class MockWebView extends _i1.Mock implements _i2.WebView { ), ) as _i2.WebSettings); @override + set onScrollChanged(_i2.ScrollChangedCallback? _onScrollChanged) => + super.noSuchMethod( + Invocation.setter( + #onScrollChanged, + _onScrollChanged, + ), + returnValueForMissingStub: null, + ); + @override _i9.Future loadData({ required String? data, String? mimeType, @@ -2064,6 +2096,16 @@ class MockWebView extends _i1.Mock implements _i2.WebView { returnValueForMissingStub: _i9.Future.value(), ) as _i9.Future); @override + _i9.Future enableContentOffsetChangedListener(bool? enabled) => + (super.noSuchMethod( + Invocation.method( + #enableContentOffsetChangedListener, + [enabled], + ), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) as _i9.Future); + @override _i2.WebView copy() => (super.noSuchMethod( Invocation.method( #copy, 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 0b5afbaf5b13..1268149877c7 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 @@ -930,6 +930,21 @@ class MockTestWebViewHostApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override + void enableContentOffsetChangedListener( + int? instanceId, + bool? enabled, + ) => + super.noSuchMethod( + Invocation.method( + #enableContentOffsetChangedListener, + [ + instanceId, + enabled, + ], + ), + returnValueForMissingStub: null, + ); } /// A class which mocks [TestAssetManagerHostApi]. @@ -1015,6 +1030,15 @@ class MockWebView extends _i1.Mock implements _i2.WebView { ), ) as _i2.WebSettings); @override + set onScrollChanged(_i2.ScrollChangedCallback? _onScrollChanged) => + super.noSuchMethod( + Invocation.setter( + #onScrollChanged, + _onScrollChanged, + ), + returnValueForMissingStub: null, + ); + @override _i5.Future loadData({ required String? data, String? mimeType, @@ -1289,6 +1313,16 @@ class MockWebView extends _i1.Mock implements _i2.WebView { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override + _i5.Future enableContentOffsetChangedListener(bool? enabled) => + (super.noSuchMethod( + Invocation.method( + #enableContentOffsetChangedListener, + [enabled], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override _i2.WebView copy() => (super.noSuchMethod( Invocation.method( #copy, 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 03489ce5c1e0..47e9a0d5fa38 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 @@ -339,6 +339,15 @@ class MockWebView extends _i1.Mock implements _i2.WebView { ), ) as _i2.WebSettings); @override + set onScrollChanged(_i2.ScrollChangedCallback? _onScrollChanged) => + super.noSuchMethod( + Invocation.setter( + #onScrollChanged, + _onScrollChanged, + ), + returnValueForMissingStub: null, + ); + @override _i5.Future loadData({ required String? data, String? mimeType, @@ -613,6 +622,16 @@ class MockWebView extends _i1.Mock implements _i2.WebView { returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); @override + _i5.Future enableContentOffsetChangedListener(bool? enabled) => + (super.noSuchMethod( + Invocation.method( + #enableContentOffsetChangedListener, + [enabled], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override _i2.WebView 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 56ba79a66622..5583361dae90 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 @@ -128,6 +128,8 @@ abstract class TestWebViewHostApi { void setBackgroundColor(int instanceId, int color); + void enableContentOffsetChangedListener(int instanceId, bool enabled); + static void setup(TestWebViewHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -689,6 +691,29 @@ abstract class TestWebViewHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WebViewHostApi.enableContentOffsetChangedListener', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.enableContentOffsetChangedListener 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.WebViewHostApi.enableContentOffsetChangedListener was null, expected non-null int.'); + final bool? arg_enabled = (args[1] as bool?); + assert(arg_enabled != null, + 'Argument for dev.flutter.pigeon.WebViewHostApi.enableContentOffsetChangedListener was null, expected non-null bool.'); + api.enableContentOffsetChangedListener(arg_instanceId!, arg_enabled!); + return []; + }); + } + } } } diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index 5c33fdbcea59..9d76c3656dc9 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md @@ -1,5 +1,6 @@ ## NEXT +* Added `setScrollListener` method to the `PlatformWebViewController` interface. * Updates minimum Flutter version to 3.0. ## 2.0.1 diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_webview_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_webview_controller.dart index bdeaa977d3dd..d6b5e2b1629d 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_webview_controller.dart @@ -259,6 +259,14 @@ abstract class PlatformWebViewController extends PlatformInterface { throw UnimplementedError( 'setUserAgent is not implemented on the current platform'); } + + /// Toggle the listener for content offset changes. Set to null to stop listening. + Future setOnContentOffsetChanged( + void Function(int left, int top, int oldLeft, int oldTop)? + onOffsetChange) { + throw UnimplementedError( + 'setOnContentOffsetChanged is not implemented on the current platform'); + } } /// Describes the parameters necessary for registering a JavaScript channel. diff --git a/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml index 4685135acdf1..254badccb80e 100644 --- a/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml @@ -30,3 +30,9 @@ dev_dependencies: flutter: uses-material-design: true + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../../webview_flutter/webview_flutter_platform_interface diff --git a/packages/webview_flutter/webview_flutter_web/pubspec.yaml b/packages/webview_flutter/webview_flutter_web/pubspec.yaml index f3ea67d68dad..81e14e3f9977 100644 --- a/packages/webview_flutter/webview_flutter_web/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_web/pubspec.yaml @@ -30,3 +30,9 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.3.2 + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../webview_flutter/webview_flutter_platform_interface diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index 718eb282018b..ba642578c8ef 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -34,3 +34,9 @@ flutter: - assets/sample_video.mp4 - assets/www/index.html - assets/www/styles/style.css + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../../webview_flutter/webview_flutter_platform_interface diff --git a/packages/webview_flutter/webview_flutter_wkwebview/generatePigeons.sh b/packages/webview_flutter/webview_flutter_wkwebview/generatePigeons.sh new file mode 100755 index 000000000000..6450ba3c454a --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/generatePigeons.sh @@ -0,0 +1,8 @@ +# Copyright 2013 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +flutter pub run pigeon \ +--input pigeons/web_kit.dart \ +--dart_out lib/src/common/web_kit.pigeon.dart \ +--dart_test_out test/common/test_web_kit.pigeon.dart \ diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index d1aaa7cf9203..fa6f9793fb02 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -30,3 +30,9 @@ dev_dependencies: sdk: flutter mockito: ^5.3.2 pigeon: ^4.2.13 + + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + webview_flutter_platform_interface: + path: ../../webview_flutter/webview_flutter_platform_interface