adrianflutur / webviewx Goto Github PK
View Code? Open in Web Editor NEWA feature-rich cross-platform webview using webview_flutter for mobile and iframe for web. JS interop-ready.
License: MIT License
A feature-rich cross-platform webview using webview_flutter for mobile and iframe for web. JS interop-ready.
License: MIT License
Im trying to build a webview which have a dynamic script and call a function of that script whent the page is loaded. But I'm getting no such method error on callJsMethod even though I have created the method in jsContent.
This is the log
Error: NoSuchMethodError: 'pay'
method not found
Receiver: Instance of 'JavaScriptObject'
Arguments: []
at Object.throw_ [as throw] (http://localhost:56359/dart_sdk.js:5061:11)
at js.JsObject._fromJs.callMethod (http://localhost:56359/dart_sdk.js:58823:19)
at web.WebViewXController.new.callJsMethod (http://localhost:56359/packages/webviewx/src/controller/impl/web.dart.lib.js:111:35)
at http://localhost:56359/packages/pasar_negeri/screens/transactions/transactions_screen.dart.lib.js:3938:42
at Generator.next (<anonymous>)
at runBody (http://localhost:56359/dart_sdk.js:38659:34)
at Object._async [as async] (http://localhost:56359/dart_sdk.js:38690:7)
at http://localhost:56359/packages/pasar_negeri/screens/transactions/transactions_screen.dart.lib.js:3937:151
at _RootZone.runUnary (http://localhost:56359/dart_sdk.js:38511:59)
at _FutureListener.then.handleValue (http://localhost:56359/dart_sdk.js:33713:29)
at handleValueCallback (http://localhost:56359/dart_sdk.js:34265:49)
at Function._propagateToListeners (http://localhost:56359/dart_sdk.js:34303:17)
at async._AsyncCallbackEntry.new.callback (http://localhost:56359/dart_sdk.js:34032:27)
at Object._microtaskLoop (http://localhost:56359/dart_sdk.js:38778:13)
at _startMicrotaskLoop (http://localhost:56359/dart_sdk.js:38784:13)
at http://localhost:56359/dart_sdk.js:34519:9
This is the page source code
import 'dart:convert';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter/services.dart';
import 'package:webviewx/webviewx.dart';
import '../../config/config.dart';
import '../../helpers/utils.dart';
import '../../models/checkout.dart';
import '../../models/midtrans.dart';
import '../../screens/authentication/authentication_wrapper.dart';
import '../../screens/transactions/transaction_details_screen.dart';
class SnapScreen extends StatefulWidget {
static const routeName = '/SNAP';
const SnapScreen({Key? key}) : super(key: key);
@override
_SnapScreenState createState() => _SnapScreenState();
}
class _SnapScreenState extends State<SnapScreen> {
@override
void initState() {
super.initState();
}
@override
void didUpdateWidget(SnapScreen oldWidget) {
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
final Checkout paymentInfo =
ModalRoute.of(context)?.settings.arguments as Checkout;
final mediaQuery = MediaQuery.of(context);
return Scaffold(
appBar: AppBar(
title: Text(
'PEMBAYARAN',
),
elevation: 2,
),
body: Stack(
children: <Widget>[
WebViewX(
height: mediaQuery.size.height - mediaQuery.padding.vertical,
width: mediaQuery.size.width - mediaQuery.padding.horizontal,
navigationDelegate: (navigation) async {
if (await canLaunch(navigation.content.source)) {
await launch(navigation.content.source);
}
return NavigationDecision.prevent;
},
initialContent: '<html></html>',
initialSourceType: SourceType.html,
javascriptMode: JavascriptMode.unrestricted,
jsContent: {
EmbeddedJsContent(
mobileJs: """
function pay(transactionToken, midtransUrl, midtransClientKey) {
var config = document.createElement('script');
config.type = 'text/javascript';
config.src = midtransUrl;
config.setAttribute('data-client-key', midtransClientKey);
config.onload = function () {
snap.pay(transactionToken, {
// Optional
onSuccess: function (result) {
Android.postMessage('ok');
Print.postMessage(result);
},
// Optional
onPending: function (result) {
Android.postMessage('pending');
Print.postMessage(result);
},
// Optional
onError: function (result) {
Android.postMessage('error');
Print.postMessage(result);
},
onClose: function () {
Android.postMessage('close');
Print.postMessage('close');
}
});
}
document.head.append(config);
}
""",
webJs: """
function pay(transactionToken, midtransUrl, midtransClientKey) {
var config = document.createElement('script');
config.type = 'text/javascript';
config.src = midtransUrl;
config.setAttribute('data-client-key', midtransClientKey);
config.onload = function () {
snap.pay(transactionToken, {
// Optional
onSuccess: function (result) {
Android('ok');
Print(result);
},
// Optional
onPending: function (result) {
Android('pending');
Print(result);
},
// Optional
onError: function (result) {
Android('error');
Print(result);
},
onClose: function () {
Android('close');
Print('close');
}
});
}
document.head.append(config);
}
""",
)
/*EmbeddedJsContent(
webJs: "function callPay() { pay('${paymentInfo.token}','${Config.midtransURL}','${Config.midtransClientKey}') }",
mobileJs: "function callPay() { pay('${paymentInfo.token}','${Config.midtransURL}','${Config.midtransClientKey}') }",
),*/
},
dartCallBacks: {
DartCallback(
name: 'Print',
callBack: (receiver) {
print('==========>>>>>>>>>>>>>> BEGIN');
print('Print Message : ' + receiver.message);
print(receiver.message);
if (receiver.message != 'undefined') {
_handleResponse(receiver.message, paymentInfo);
}
print('==========>>>>>>>>>>>>>> END');
},
),
DartCallback(
name: 'Android',
callBack: (receiver) {
print('==========>>>>>>>>>>>>>> BEGIN');
print('Android Message : ' + receiver.message);
if (Platform.isAndroid) {
if (receiver.message != 'undefined') {
if (receiver.message == 'close') {
Navigator.pop(context);
} else {
_handleResponse(receiver.message, paymentInfo);
}
}
}
print('==========>>>>>>>>>>>>>> END');
},
),
},
onWebViewCreated: (_controller) {
print('LOADING HTML WITH SNAP TOKEN : ' + paymentInfo.token);
_loadHtmlFromAssets(_controller, paymentInfo.token);
//await _loadHtmlFromAssets(_controller);
},
),
],
),
);
}
_loadHtmlFromAssets(
WebViewXController webViewController, transactionToken
) async {
webViewController
.loadContent('assets/html/snap.html', SourceType.html, fromAssets: true)
.then((_) async => await webViewController.callJsMethod("pay", [transactionToken, Config.midtransURL, Config.midtransClientKey]));
}
_handleResponse(message, paymentInfo) {
var title, desc;
Midtrans? midtrans;
Navigator.pop(context);
if (Platform.isAndroid) {
switch (message) {
case 'ok':
midtrans = Midtrans(MIDTRANS_PAYMENT_TYPE.bank_transfer,
MIDTRANS_STATUS_CODE.MIDTRANS_STATUS_CODE_200);
break;
case 'pending':
midtrans = Midtrans(MIDTRANS_PAYMENT_TYPE.bank_transfer,
MIDTRANS_STATUS_CODE.MIDTRANS_STATUS_CODE_201);
break;
case 'error':
midtrans = Midtrans(MIDTRANS_PAYMENT_TYPE.bank_transfer,
MIDTRANS_STATUS_CODE.MIDTRANS_STATUS_CODE_202);
break;
}
} else {
midtrans = Midtrans.fromString(message);
}
var result = midtrans?.getResult();
title = result?[0];
desc = result?[1];
if (title.length == null && desc.length == null)
utils.toast('Something went wrong!');
else
_showConfirmDialog(title, desc, paymentInfo);
}
void _showConfirmDialog(title, desc, paymentInfo) async {
await showModalBottomSheet(
context: context,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (BuildContext context) {
return Container(
height: 250,
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
style: AppConfig.theme?.styles.title3,
),
SizedBox(
height: 25,
),
Text(
desc,
style: AppConfig.theme?.styles.body1,
),
SizedBox(
height: 25,
),
TextButton(
onPressed: () async {
Navigator.popUntil(context, (route) {
return route.settings.name ==
AuthenticationWrapper.routeName;
});
Navigator.pushNamed(
context, TransactionDetailsScreen.routeName,
arguments: paymentInfo.orderId);
},
child: Text('Lihat Detail Pembayaran'),
)
],
),
),
);
},
);
}
}
This is the snap.html
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript">
</script>
</head>
<body>
</body>
</html>
when is use urlbypass source type , query parameters not detect on target web app.
what is my problem?
hello,
I am building a web app with flutter and I need to have a user log in. I am doing this by hitting a authentication endpoint on an azure AD so I can get a code and subsequently get a token. here it what the initial URL looks like. line breaks added for readability. Also anything in <> is info that I would rather keep private.
https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize?
client_id=<client_id>
&redirect_uri=$redirectUrl
&response_type=code
&response_mode=query
&scope=https://graph.microsoft.com/user.read
&code_challenge=<code_challenge>
&code_challenge_method=<code_challenge_method>
obviously this isn't of much help to anyone but i just wanted to give a sense of the structed or the URL. but if you would like to do you own test you can just use the link below which has the same result.
https://login.microsoftonline.com/
my webapp is hosted on firebase but also works on local host. however neither firebase or an azure ad are necessary to to reproduce the bug as you would just need a microsoft account and can use https://login.microsoftonline.com/ as the URL in WebViewX and make sure the flutter project has web.
Any clue as to how to get this working? any help would be greatly appreciated.
as for the set up of me WebViewx refer to code below
`@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("o365 login"),
actions: [
Padding(
padding: EdgeInsets.only(right: 20),
child: GestureDetector(
child: Icon(Icons.home),
onTap: () => _setUrl(), //I also has a method setup to set the same url as above to see if it was the initial URL causing the problem
),
)
],
),
//Builder is wrapped around the webview to allow SnackBar to access the build context of the scaffold.
// Without this the context would be from AuthLogin which does not contain a scaffold.
body: Builder(builder: (context) =>
WebViewX(
key: ValueKey('webviewx'),
initialContent: _initialUrl_noredirect,
initialSourceType: SourceType.URL_BYPASS,
onWebViewCreated: (controller) => webviewController = controller,
onPageStarted: (url) => print('A new page has started loading...\n'),
// onPageFinished: _getAuthCode,
javascriptMode: JavascriptMode.unrestricted,
webSpecificParams: WebSpecificParams(additionalSandboxOptions: ['allow-top-navigation', 'allow-top-navigation-by-user-activation', 'allow-downloads',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',])
)
),
);
}
`
// flutter
WebViewXController _wc = WebViewXController();
...
dartCallBacks: Set.from([
DartCallback(
name: "test",
callBack: (message) {
showSnackBar('${message.toString()}', context);
},
),
]),
void _evalRawJsInGlobalContext() async {
try {
var result = await _wc.evalRawJavascript(
"jstestFunction('string')",
);
} catch (e) {
showAlertDialog("${e}", context);
}
}
// html
<script> function jstestFunction(text){ console.log(text); if (window.test && window.test.postMessage) { console.log(document.documentElement.innerHTML); test.postMessage(text); test(text); } } </script>When running on mobile, the value delivered is displayed normally, but when running on the web, the value is generated as null. How do I fix this?
Or is it not supported on the web?
web Error message : nosuchmethoderror : nvalid member on null : 'callMethod'
On page finished redirection is based on the last getting url. but initialSourceType is SourceType.html, so onPageFinished section the src is html content. so how we can get the on finished url.
I know this is not stack overflow but still.
What method can i use to preload the webview before its pushed in stack.
navigationDelegate method don work in web render app.
How to get payment callback in flutter web.
This is my code:
WebViewX(
width: 1500,
height: 600,
initialContent: " https://api.sandbox.paypal.com/v1/payments/payment/PAYID-ABCCCCSCSCSCSCSC/execute",
javascriptMode: JavascriptMode.unrestricted,
initialSourceType: SourceType.url,
onWebViewCreated: (controller) => webviewController = controller,
// ignoreAllGestures: false,
onWebResourceError: (error) {
},
onPageFinished: (value) {
},
navigationDelegate: (NavigationRequest request) {
print('navigationDelegate=====>>>> ${request}');
return NavigationDecision.navigate;
},
dartCallBacks: {
DartCallback(
callBack: (url) {
print('DartCallback=====>>>> $url');
},
name: 'CaptchaMessenger')
},
),
Thank you in advance.
Hi,
In this issue you say "one should NOT use it (especially with SourceType.urlBypass) for security-related stuff, such as OAuth or similar."
Is this saying that we shouldn't host a page which requires normal username and password login in an Iframe?
What about hosting an iframe with the normal SourceType.url, are pages that have a log in form not secure?
I am just getting confused because you said OAuth which I believe is different to a username and password login.
Great package by the way. Extremely useful and very well organised!
Thanks.
I am trying load local asset html from assets folder in flutter and while doing so it is working fine in web, thanks webviewx team but while viewing in mobile I am seeing black spot on top and html page is not rendering at all due to import issue
`
import 'package:flutter/material.dart';
import 'package:webviewx/webviewx.dart';
class FormDetailPage extends StatefulWidget {
@OverRide
_FormDetailPageState createState() => _FormDetailPageState();
}
class _FormDetailPageState extends State {
WebViewXController webviewController;
String title = 'Form Page';
@OverRide
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: WebViewX(
javascriptMode: JavascriptMode.unrestricted,
initialContent:
'
}`
is there an example of how to add this and allow gestures like scrolling? Setting ignoreAllGestures to false doesn't seem to do the trick. can't scroll while cursor is over the embedded content.
Hi @adrianflutur , Thanks again for great package, I am facing issue with loading html content in webview, it is working fine in web but in mobile it does not work propery even with latest version.
Reproducible code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src='assets/test.js'></script>
</head>
<body>
<h2>Test</h2>
<div class="container">
<div class="content">
<button class="button" onclick="backClick()">Back</button>
</div>
</div>
</body>
</html>
b) In test.js
function backClick() {
alert("js called")
}
And in flutter
_loadHtmlFromAssets() {
webviewController.loadContent(
AppUtils.TEST_WEB_URL,
SourceType.HTML,
fromAssets: true,
);
}
though html content is loading in mobile js function is not triggering same goes for css style as well.
Note: In web it is working fine js,html and css as well.
Hi,
I would like to replace the current WebView with this to support for both mobile and web.
However, I find no way to handle the events such as navigationDelegate, onLoaded...
May I know how to do that?
Basically, I need to make sure this is work seamlessly as WebView before going further for web improvement.
Thanks!
not working url like this. https://connect.stripe.com/express/onboarding/*******
webviewx on pwa use a proxy from code tabs and have problem
Hello, here I'll try to create a helpful guide with all the differences I can find between the two and a variety of use cases when one can not bypass the intrinsic limitations of the package, since this is not really obvious from the documentation.
This will be updated from time to time. Here we go:
SourceType.urlBypass
for this). The package treats theese pages as follows:
SourceType.urlBypass
) for security-related stuff, such as OAuth or similar. This is because:SourceType.urlBypass
or SourceType.html
. This is because only in theese 2 situations the package can actually inject that JS code inside the page source. When using SourceType.url
, iframe's content does not actually belong to us - it is loaded from a different domain so we're not allowed to do that.BypassProxy
objects in the WebViewX's webSpecificParams
param.headers
only have effect when using SourceType.urlBypass
, because that's when the package fetches the page source.SourceType.urlBypass
because click handlers can only be registered for this type of source (for now, soon they may also work when using SourceType.html
- see src/view/impl/web.dart
around line 220)EmbeddedJsContent
param on the WebViewX, if you define JS functions as ES6 variable functions:const fn = () => ...
, then you also need to add them to the global scope to work: window.fn = fn
.
SourceType.urlBypass
. Redirects may work only if that website allows iframe embeddings, in which case you should use SourceType.url
.hi
when i do js shell like this
document.getElementsByClassName("ad top")[0].style.display="none";
error
TypeError: Cannot read property 'style' of undefined
TypeError: Cannot read property 'Symbol(dartx.location)' of null
at web$0._WebViewXWidgetState.new.[_updateSource] (http://localhost:54079/packages/webviewx/src/view/web.dart.lib.js:715:42)
at http://localhost:54079/packages/webviewx/src/view/web.dart.lib.js:539:28
at http://localhost:54079/dart_sdk.js:33443:33
at internalCallback (http://localhost:54079/dart_sdk.js:25104:11)
but do on chrom it's ok.
my code
class WebPageState extends State<WebPage> {
String js = '''
document.getElementsByClassName("ad top")[0].style.display="none";
''';
WebViewXController webviewController;
@override
Widget build(BuildContext context) {
return Scaffold(
body: WebViewX(
initialContent: 'https://online-video-cutter.com/cn/',
onWebViewCreated: (controller) {
webviewController = controller;
_evalRawJsInGlobalContext();
},
// jsContent: {
// EmbeddedJsContent(
// js: js
// )
// },
),
);
}
void _evalRawJsInGlobalContext() async {
try {
var result = await webviewController.evalRawJavascript(
js,
inGlobalContext: true,
);
print(result);
} catch (e) {
print(e);
}
}
}
Hi I am kinda new to flutter and this package does help me to achieve my goal but i need to tweak it, so how can I set the zoom level for the widget when runnning on the Web? thanks
It seems that embedded js content only works with HTML source type, but not URL source type (at least on web platform, didn't test on Android/iOS).
Test with HTML source type (on web platform):
WebViewX(
width: 500,
height: 500,
initialContent: "<h1>Hello</h1>",
initialSourceType: SourceType.html,
jsContent: {EmbeddedJsContent(js: "console.log('hello');")},
)
=> I can see the "hello" message in the browser's console.
Test with URL source type (on web platform):
WebViewX(
width: 500,
height: 500,
initialContent: "https://httpbin.org/get",
initialSourceType: SourceType.url,
jsContent: {EmbeddedJsContent(js: "console.log('hello');")},
)
=> no message in console
This is a thread for tracking implementation status for this package on Windows, Linux and MacOS.
It will also be used to point to news, commits, branches or merges related to this.
Feel free to comment if you have any news or thoughts.
Current status:
Windows - not implemented
See flutter/flutter#31713
There are two projects that claim to be doing this, but they are not using platform-views.
Linux - not implemented
There seems to be a PR for this here flutter/engine#26288
MacOS - not implemented
Hi,
I'm trying to load an Angular app on the web using urlBypass
. I set my own local proxy with nginx.
I'm using urlBypass
cause I need to inject JS into my Angular app.
When I access to my app through my proxy using a browser, my app is loaded fully.
When I access to my app through the webview, I only get the raw HTML.
I read through #27 and I saw:
normal URLs which do not support iframe embedding (such as https://google.com, you need to use SourceType.urlBypass for this). The package treats theese pages as follows:
It fetches the page's HTML source using a HTTP call to a Proxy server, which will remove the headers which block iframe embedding
It will set the HTML source to the iframe, just like we're doing at point 1) with HTML content
So my understanding is that when using urlBypass
we can only get plain HTML ? Or should I change my proxy so it returns more than the HTML ?
Hi,
How can I get informed about the new URL (full path) when I'm inside a WebView (Flutter Web project) and I clicked on a button (on the webpage) and got transmitted to a new webpage?
Thanks,
Lior
If you don't set the height and the width the plugin throws null pointer exception.
Hi,
Im prevented to load some pages because it says cookies aren't enabled and I haven't find a way to enable them.
i tried with differents URLs , with your example , unfortunatelly nothing is working
i cant access http domain and I just find the ios/android method.
Are you considering adding in null safe? Or is there a way to run this in a project using Null safety?
// in dart
dartCallBacks: Set.from([
DartCallback(
name: "test",
callBack: (message) {
showSnackBar('${message.toString()}', context);
},
),
]),
void _evalRawJsInGlobalContext() async {
try {
var result = await _wc.evalRawJavascript(
"jstestFunction('test')",
);
} catch (e) {
showAlertDialog("${e}", context);
}
}
// in html
<script> function jstestFunction(text){ console.log(text); if (window.test && window.test.postMessage) { console.log(document.documentElement.innerHTML); test.postMessage(text); test(text); } } </script>// output
mobile : 'test'
web : nosuchmethod: invalid member on null:'callmethod'
I want to show the values returned by the web using dartcallback and evalRawJavascript. Obviously, it works well on mobile, but when I run it on the web, I get an error message saying nosuchmethod: invalid member on null:'callmethod'. If I misunderstand and use it strangely, please explain how to fix it. Or, if you can't support it on the web, please tell us.
This article uses Google Translator.
thank you.
Hey!
I'm trying to open a jitsi meeting inside an WebViewX:
WebViewX(
webSpecificParams: WebSpecificParams(additionalAllowOptions: [
'camera',
'microphone',
]),
initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.alwaysAllow,
initialContent: this.widget.url, // https://meet.jit.si/somerandomtext
initialSourceType: SourceType.url,
onWebViewCreated: (controller) => webviewController = controller,
height: maxHeight,
width: maxWidth,
);
This is what I get on web:
And this is what I get on mobile (android):
None of that want to work.
I have added the following to AndroidManifest.xml
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
I was able to load small HTML markup from string, but failed with a 20kb file. This error is thrown about half way through the file, after page started loading. (The same file works fine in webview plugin)
Code loading the file:
Future<void> getHtml() async {
String c = await rootBundle.loadString('assets/index.html');
webviewController.loadContent(c, SourceType.html);
}
Exception thrown:
════════ Exception caught by foundation library ════════════════════════════════
The following RangeError was thrown while dispatching notifications for WebViewXController:
RangeError (end): Invalid value: Not in inclusive range 0..19853: -1
When the exception was thrown, this was the stack
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 251:49 throw_
dart-sdk/lib/core/errors.dart 338:9 checkValidRange
dart-sdk/lib/_internal/js_dev_runtime/private/js_string.dart 168:22 substring]
packages/webviewx/src/utils/html_utils.dart 208:36 embedInHtmlSource
packages/webviewx/src/utils/html_utils.dart 173:12 embedJsInHtmlSource
packages/webviewx/src/utils/html_utils.dart 235:12 embedWebIframeJsConnector
packages/webviewx/src/utils/html_utils.dart 64:14 preprocessSource
packages/webviewx/src/view/impl/web.dart 420:35 [_updateSource]
packages/webviewx/src/view/impl/web.dart 381:5 [_handleChange]
packages/flutter/src/foundation/change_notifier.dart 308:24 notifyListeners
packages/webviewx/src/controller/impl/web.dart 265:5 [_notifyWidget]
packages/webviewx/src/controller/impl/web.dart 110:5 loadContent
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54 runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5 _async
packages/webviewx/src/controller/impl/web.dart 82:27 loadContent
packages/wsm2/src/map/map_view.dart 108:23 getHtml
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50 <fn>
dart-sdk/lib/async/zone.dart 1687:54 runUnary
dart-sdk/lib/async/future_impl.dart 160:18 handleValue
dart-sdk/lib/async/future_impl.dart 767:44 handleValueCallback
dart-sdk/lib/async/future_impl.dart 796:13 _propagateToListeners
dart-sdk/lib/async/future_impl.dart 602:5 [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 640:7 callback
dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>
The WebViewXController sending notification was: Instance of 'WebViewXController'
════════════════════════════════════════════════════════════════════════════════
`
@OverRide
Widget build(BuildContext context) {
// if (isImageloaded == false) {
// return LoadingWidget();
// }
return Scaffold(
endDrawer: const NavigationPage(),
body: LayoutBuilder(builder: (context, constraints) {
return Stack(
children: [
_backgroundMapField(constraints),
SoundAndMenuWidget(
icons: isSoundOn ? Icons.volume_up : Icons.volume_mute,
onTapVolume: isSoundOn
? () {
setState(() {
isSoundOn = !isSoundOn;
backgroundplayer.pause();
});
}
: () {
setState(() {
isSoundOn = !isSoundOn;
backgroundplayer.play();
});
},
onTapMenu: () {
Scaffold.of(context).openEndDrawer();
},
),
],
);
}),
);
}
Widget _backgroundMapField(BoxConstraints constraints) {
return Container(
color: Colors.transparent,
child: WebViewX(
width: constraints.maxWidth,
height: 0.863 * constraints.maxHeight,
initialContent: '
import 'package:flutter/material.dart';
class SoundAndMenuWidget extends StatelessWidget {
final Function() onTapVolume;
final Function() onTapMenu;
final IconData icons;
final Color? color;
final Widget? widget;
const SoundAndMenuWidget(
{Key? key,
required this.onTapVolume,
required this.icons,
this.color,
this.widget,
required this.onTapMenu})
: super(key: key);
@OverRide
Widget build(BuildContext context) {
return Align(
alignment: Alignment.topCenter,
child: Container(
padding: const EdgeInsets.fromLTRB(24, 24, 24, 0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: onTapVolume,
icon: Icon(icons),
color: color ?? Colors.black,
),
widget ?? const SizedBox(),
IconButton(
onPressed: onTapMenu,
icon: Icon(
Icons.menu,
color: color ?? Colors.black,
))
],
),
),
);
}
}
`
Drawer not close on click over webview.
setIgnoreAllGestures reload the page
I am using the navigationDelegate
to show the link in a new scaffold using showCupertinoModalBottomSheet
(like Instagram), but I am not able to scroll to the bottom of the page. I am able to scroll only to the height of the MediaQuery.of(context).size.height
Result:
Code to launch the new page for the link
showCupertinoModalBottomSheet(
context: context,
builder: (context) => Container(
height: MediaQuery.of(context).size.height / 1.5,
child: NewsItemDisplayLink(
sourceType: navigation.content.sourceType,
source: navigation.content.source,
),
),
);
Widget Page:
CupertinoPageScaffold(
backgroundColor: Style.backgroundColor(context),
navigationBar: CupertinoNavigationBar(
backgroundColor: Style.menuColor(context),
padding: EdgeInsetsDirectional.only(bottom: 1),
leading: IconButton(
icon: Icon(
CupertinoIcons.clear,
color: Style.primaryColor,
size: 30,
),
onPressed: () => Navigator.of(context).pop(),
),
trailing: StatefulBuilder(
builder: (BuildContext context, StateSetter settingState) => Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(
CupertinoIcons.back,
color: Style.primaryColor,
size: 30,
),
onPressed: () async {
if (await webviewLinkController.canGoBack()) {
webviewLinkController.goBack();
}
},
),
IconButton(
icon: Icon(
CupertinoIcons.forward,
color: Style.primaryColor,
size: 30,
),
onPressed: () async {
if (await webviewLinkController.canGoForward()) {
webviewLinkController.goForward();
}
},
),
IconButton(
icon: Icon(
linkSaved
? CupertinoIcons.bookmark_fill
: CupertinoIcons.bookmark,
color: Style.primaryColor,
size: 30,
),
onPressed: () async {
//TODO implementare salva link
setState(() => linkSaved = !linkSaved);
EasyLoading.showToast(
linkSaved
? 'Link aggiunto ai salvati'
: 'Link rimosso dai salvati',
duration: Duration(seconds: 2),
dismissOnTap: true,
toastPosition: EasyLoadingToastPosition.bottom);
},
),
],
),
),
),
child: SafeArea(
child: SingleChildScrollView(
child: Container(
child: WebViewX(
initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.alwaysAllow,
initialContent: widget.source,
initialSourceType: SourceType.urlBypass,
onWebViewCreated: (controller) {
webviewLinkController = controller;
setState(() => loading = false);
},
height:
screenSize.height, //HERE is the problem
width: screenSize.width,
),
),
),
),
)
当html页面高度不确定时,webview顶部还有其它widget小部件时,webview的高度如何确定
I prserved a data in the session variable,
$_SESSION['final_amount'] = some_value
but when it is accessed in another page in the same webview says undefined final_amount
Hey I am using flutter web 2.0.4 stable
Getting this error while accessing google.com or any other web site using URLBypass
My flutter doctor:
[✓] Flutter (Channel stable, 2.0.4, on Linux, locale
en_GB.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version
30.0.0-rc1)
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] Connected device (1 available)
Hello,
thank you for developing this package. It has really large set of functionalities and it's well documented.
But I miss one thing: how can I bilateral communication using Javascript channels? There is no property for that in WebViewX widget. My use case is: on website there is postMessage call, which I have to capture. How can I achieve it with this package?
Of course I found TestDartCallback in example, but in my case I won't have option to edit website code to add these callbacks.
I use this plugin to access pdf file by url, Seems to be unreadable。does it support this?
C:\Flutter.pub-cache\hosted\pub.dartlang.org\webview_flutter-2.0.6\android\src\main\java\io\flutter\plugins\webviewflutter\InputAwareWebView.java:31:
error: cannot find symbol
private ThreadedInputConnectionProxyAdapterView proxyAdapterView;
^
symbol: class ThreadedInputConnectionProxyAdapterView
location: class InputAwareWebView
C:\Flutter.pub-cache\hosted\pub.dartlang.org\webview_flutter-2.0.6\android\src\main\java\io\flutter\plugins\webviewflutter\InputAwareWebView.java:112: error: cannot find symbol
new ThreadedInputConnectionProxyAdapterView(
^
symbol: class ThreadedInputConnectionProxyAdapterView
location: class InputAwareWebView
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
2 errors
FAILURE: Build failed with an exception.
Compilation failed; see the compiler error output for details.
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 53s
child: webx.WebViewX(
key: ValueKey('webx'),
onWebResourceError: (error) {
print('error yha h $error');
},
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
// initialContent: 'cuddi',
initialSourceType: webx.SourceType.urlBypass,
javascriptMode: webx.JavascriptMode.unrestricted,
onWebViewCreated: (controller) {
webviewController = controller;
webviewController.loadContent(
"https://google.co.in", webx.SourceType.urlBypass,
// headers: {'token': state.paymentToken}, body: context
);
},
)
also I. added a / after link but nothing changed
Payment gateway not working on flutter web as it is working on flutter mobile webview.. its not redirecting to bank website.. no error is showing
I have an app that loads some HTML from assets on first launch as the body of a Scaffold, and while this HTML is being displayed, I found that when I call showDialog(), all of the buttons in the alert are not clickable, and I am still somehow able to interact with the HTML behind it.
Rough example:
Scaffold(
body: WebViewX(
onWebViewCreated: (controller) {
webviewController = controller;
webviewController.loadContent(
'assets/welcome.html', SourceType.HTML,
fromAssets: true);
},
)
)
The alert is standard
showDialog(
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async => barrierDismissable,
child: AlertDialog(
title: Text(title),
content: content,
actions: actions,
),
);
})```
Could this be my implementation or has someone seen something similar?
Please help.
Hello,
I followed your example for running JS code from dart:
I've added this code:
return WebViewX(
width: 320,
height: 500,
initialContent:
'someUrl',
onWebViewCreated: (controller) => webviewController = controller,
onPageFinished: (_) {
webviewController
.callJsMethod('testPlatformSpecificMethod', <dynamic>['Hi']);
},
jsContent: const {
EmbeddedJsContent(
webJs:
"function testPlatformSpecificMethod(msg) { CaptchaMessenger('Web callback says: ' + msg) }",
mobileJs:
"function testPlatformSpecificMethod(msg) { CaptchaMessenger.postMessage('Mobile callback says: ' + msg) }",
),
},
dartCallBacks: {
DartCallback(callBack: recaptchaCallback, name: 'CaptchaMessenger')
},
);
But when I run this code I always get this error:
error: LateInitializationError: Field 'connector' has not been initialized.
.
Additional info:
code
class WebPageState extends State<WebPage> {
// String js = '''
// var remove=n=>{n.split(",").forEach(v=>{if(v.indexOf("@ID(")==0){document.getElementById(v.substring(4,v.length-1)).style.display="none"}else{for(let e of document.getElementsByClassName(v))e.style.display="none"}})}
// remove("ad top")
// ''';
String js = '''
document.getElementsByClassName("ad top")
''';
WebViewXController webviewController;
@override
Widget build(BuildContext context) {
return Scaffold(
body: WebViewX(
initialContent: 'https://online-video-cutter.com/cn/',
initialSourceType: SourceType.URL_BYPASS,
onWebViewCreated: (controller) {
webviewController = controller;
_evalRawJsInGlobalContext();
},
// jsContent: {
// EmbeddedJsContent(
// js: js,
// ),
// // EmbeddedJsContent(
// // webJs:
// // "function testPlatformSpecificMethod(msg) { TestDartCallback('Web callback says: ' + msg) }",
// // mobileJs:
// // "function testPlatformSpecificMethod(msg) { TestDartCallback.postMessage('Mobile callback says: ' + msg) }",
// // ),
// },
),
);
}
void _evalRawJsInGlobalContext() async {
try {
// webviewController.loadContent(
// 'https://online-video-cutter.com/cn/',
// SourceType.URL,
// );
Future.delayed(Duration(seconds: 4),() async {
var result = await webviewController.evalRawJavascript(js);
print(result);
});
} catch (e) {
print(e);
}
}
}
even if don't do any js shell,the console print
DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to 'about:srcdoc'.
at HTMLDocument.<anonymous> (https://static.123apps.com/js/shared-v3.js?6eeaf:1:264239)
[object HTMLCollection]
and the web page is't show normal. such as this link https://online-video-cutter.com/cn.
When I try I receive this:
Error: URI is missing protocol: about:srcdoc
at wh (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:422:311)
at Eh (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:441:42)
at VK.vv.ww (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:6520:174)
at VK.ww (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:7204:390)
at baa.l (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:3025:281)
at Aa (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:55:40)
at daa.next (https://www.youtube.com/s/player/2fa3f946/player_ias.vflset/en_US/base.js:56:92)
Hey! The example app looks kinda complex for my use case and I can't seem to get the webviewx
plugin working. I want to embed a webpage in a container in Flutter web, here's what my code currently looks like.
Container(
height: 520,
width: 780,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
), child: WebViewX(
initialContent: '<h2> Hello, world! </h2>',
initialSourceType: SourceType.html,
onWebViewCreated: (controller) => webviewController = controller,
),
I want the initial content to be the webpage I plan to embed itself, the idea is that a user will click an icon and it will bring up a webpage. I tried changing the initialContent
parameter to a link and the initialSourceType
parameter to SourceType.url
but that gives me an unexpected null value
error when running build.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.