Calling postMessage on iframeElement in flutter web - flutter

I have a flutter web application. I need to call postMessage to be handled by the page opened in an iframe element using
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => html.IFrameElement()
..width = '100%'
..height = '100%'
..src = widget.url
..style.border = 'none'
);
Is there a way to do this?

Technically, PostMessage sends to the main document's window, not to the iframe's.
Specify the iframe's window object in Javascript:
document.getElementById('hello-world-html').contentWindow.postMessage(.......)
or in Dart you can do:
import 'dart:html' as html;
// Your code
html.document.getElementById.getElementById('hello-world-html').contentWindow.postMessage(.......)

this works for an iframe that has a cross domain src
import 'dart:html';
IFrameElement element = document.getElementById('iframe') as IFrameElement;
element.contentWindow?.postMessage(data.toJson(),'*');

Related

NextAuth: authorize all APP with Layout wrapping

I'm trying to use NextAuth for authorize access to my app and I have two main issue.
1 - all the app is wrapped with a Layout in _app.js
<SessionProvider session={pageProps.session}>
<RecoilRoot>
<Layout>
<Component {...pageProps} />
</Layout>
</RecoilRoot>
</SessionProvider>
I'm using the email Provider and if I use the built in signin page everything works great but if I add a custom signin page under pages/signin.js I'm not able to proceed. My undeerstanding is that with custom signin page everything is wrapped with the layout. The layout has a useeffect with a call to an api to get items to show in the menu
import Navbar from "./navbar";
import Sidebar from "./sidebar";
import Main from "./main";
import { useEffect, useState } from "react";
const Layout = ({ children }) => {
const [menu, setMenu] = useState();
useEffect(async () => {
const data = await fetch("api/menu/menu", {
method: "GET",
headers: { "Content-Type": "application/json" },
});
const menuItems = await data.json();
setMenu(menuItems.data);
}, []);
return (
<>
{menu && <Navbar menu={menu.profile} />}
{menu && <Sidebar menu={menu.sidebar} />}
<Main children={children}></Main>
</>
);
};
export default Layout;
In _app.js I'm not able to retrieve the session to conditonally render the page.
Important to note that I'm using _middleware.js to protect all the app and define the custome signin page like so
import withAuth from "next-auth/middleware";
export default withAuth({
pages: {
signIn: "/auth/customSignin",
},
});
Does anyone is able to pint me in the right direction?
2 issue- I'd like top verify if user exists in the database before sending the email. Am I right I can handle it in the signin callback? If yes can I add a second filed like poassword so I can both verify user exists in db, verify with password and then send email?
Many thanks for any help
I solved the first issue using useRouter and checking the pathname for the customSignin page.
if (router.pathname === "/auth/customSignin") {
return (
<SessionProvider session={pageProps.session}>
<Component {...pageProps} />
</SessionProvider>
);
}
return (
<SessionProvider session={pageProps.session}>
<RecoilRoot>
<Layout>
<Component {...pageProps} />
</Layout>
</RecoilRoot>
</SessionProvider>
);
}
export default MyApp;
Now I'm dealing with the second one. Anybody can help on that.
Basically I need to add a second field to the built in Email Provider and check that field against the database

Experiencing redirect loop with a protected route in Gatsby using Auth0 [duplicate]

This question already has an answer here:
Login doesn't show up in Gatsby using Auth0, withAuthenticationRequired
(1 answer)
Closed 1 year ago.
Note: This question is not a duplicate, I'm not sure why anyone is thinking that...
I’m having issue with implementing protected pages(routes) in Gatsby with Auth0
Currently, when I point the browser to localhost:8000/user/protectedpage, it goes to the login screen, and after a successful login, it comes back to that route, and the browser seems to be stuck on a loop loading between two routes.
When I tested with this, the page was doing a indefinite redirect loop while showing "Redirect..." on the page:
export default withAuthenticationRequired(ProtectedPage, {
onRedirecting: () => <div>Redirecting...</div>
});
redirectUri in Auth0Provider is set to redirectUri={window.location.origin + '/user'}
Allowed Callback URLs in the auth0 admin page, is set to, http://localhost:8000/user
If I change these routes to window.location.origin and http://localhost:8000/, then after a successful login, it’ll redirect to that page and stay there.
I need it to redirect to where it was trying to go to instead.
As in, if I navigate to localhost:8000/user/protectedpage, then after logging in, it should redirect to that route and load that page successfully, instead of being stuck in a loop like mentioned earlier.
Here are some codes:
// File structure
src
> pages
> user
> index.js
> protectedpage
index.js
gatsby-browser.js
// gatsby-browser.js
import React from 'react';
import { Auth0Provider } from '#auth0/auth0-react';
import { navigate } from 'gatsby';
const onRedirectCallback = (appState) => {
navigate(appState?.returnTo || '/', { replace: true });
};
export const wrapRootElement = ({ element }) => {
return (
<Auth0Provider
domain={process.env.AUTH0_DOMAIN}
clientId={process.env.AUTH0_CLIENTID}
redirectUri={window.location.origin + '/user'}
onRedirectCallback={onRedirectCallback}
>
{element}
</Auth0Provider>
);
};
// protectedpage.js
import React from 'react';
import { withAuthenticationRequired } from '#auth0/auth0-react';
const ProtectedPage = () => {
return (
<div>
Protected Page
</div>
);
};
export default withAuthenticationRequired(ProtectedPage);
// auth0 Application URIs
Allowed Callback URLs
http://localhost:8000/user
I'm not sure about your full implementation but to me, the fact that it gets stuck in an infinite loop could be related to the fact that you are replacing the history by removing the last visited page in:
navigate(appState?.returnTo || '/', { replace: true });
In addition, the callback is receiving an appState otherwise, it makes the history replacing but you are never providing it at (onRedirectCallback={onRedirectCallback}):
// gatsby-browser.js
import React from 'react';
import { Auth0Provider } from '#auth0/auth0-react';
import { navigate } from 'gatsby';
const onRedirectCallback = (appState) => {
navigate(appState?.returnTo || '/', { replace: true });
};
export const wrapRootElement = ({ element }) => {
return (
<Auth0Provider
domain={process.env.AUTH0_DOMAIN}
clientId={process.env.AUTH0_CLIENTID}
redirectUri={window.location.origin + '/user'}
onRedirectCallback={onRedirectCallback} //<-- here you are not providing an appState
>
{element}
</Auth0Provider>
);
};

Is there AdMob support for Flutter web?

Is there AdMob support for Flutter web? All libraries that I found are intended only for Android and IOS
As you can see in the image below, Google Admobe is not supported for the web so you can not use it for flutter web or other web frameworks.
On other hand, you can use adsense and set your ads for flutter web,
and I find this solution for using Adsense as HTML(with IFrameElement)
first created an html file adview.html
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
style="display:inline-block;width:320px;height:80px"
data-ad-client="ca-pub-xxxxxx"
data-ad-slot="xxxxxxx"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
And then, an IFrameElement to make use of the HTML:
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
Widget adsenseAdsView() {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'adViewType',
(int viewID) => IFrameElement()
..width = '320'
..height = '100'
..src = 'adview.html'
..style.border = 'none');
return SizedBox(
height: 100.0,
width: 320.0,
child: HtmlElementView(
viewType: 'adViewType',
),
);
}
firebase_admob is now deprecated in favour of google_mobile_ads and both of them do not support flutter web. However, you can use display ads on websites using Google Adsense.
You can create a blank web page and add ads and embed the flutter app in the HTML page.
Ref:
Google Adsense
Embed flutter App in website

Embedding a Youtube video in Flutter Web

Is it possible to embed a Youtube video in a Flutter web page? I tried the following code to have a Youtube embedded in my Flutter website, but nothing appears on the page without any error message.
import 'package:flutter_html_view/flutter_html_view.dart';
Container(child: HtmlView(data: """
<iframe src="https://www.youtube.com/embed/xMzkWfIR9Pk" width="560" height="315"></iframe>
""")),
Also tried the solution recommended here (WebView in Flutter Web) but that doesn't work either.
import 'dart:ui' as ui
//ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'hello-world-html',
(int viewId) => html.IFrameElement()
..width = '640'
..height = '360'
..src = 'https://www.youtube.com/embed/IyFZznAk69U'
..style.border = 'none');
I used to package called flutter_html
But this gave me some scrolling issues.
Html(
data: '<iframe width="560" height="315" src="https://www.youtube.com/embed/D_mCZlQZg9Y" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
)
You should go like this
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:ui' as ui;
String viewID = "your-view-id";
#override
Widget build(BuildContext context) {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
viewID,
(int id) => html.IFrameElement()
..width = MediaQuery.of(context).size.width.toString()
..height = MediaQuery.of(context).size.height.toString()
..src = 'https://www.youtube.com/embed/IyFZznAk69U'
..style.border = 'none');
return SizedBox(
height: 500,
child: HtmlElementView(
viewType: viewID,
),
);
}
You can use the youtube_player_iframe
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: 'K18cpp_-gP8',
params: YoutubePlayerParams(
playlist: ['nPt8bK2gbaU', 'gQDByCdjUXw'], // Defining custom playlist
startAt: Duration(seconds: 30),
showControls: true,
showFullscreenButton: true,
),
);
YoutubePlayerIFrame(
controller: _controller,
aspectRatio: 16 / 9,
),
ext_video_player supports Android, iOS and web for YouTube. You can try running sample code from ext_video_player repo.
I tested with different browsers of different OS. Android, Mac, Windows browsers are working fine with ext_video_player. But it's not playing with iOS browser.
There are, at least, two solutions:
a) video_player package now works fine in the three main platforms: android, ios and web
b) This article explains a good way to embed video source in a flutter web widget, even when the article is for local files, the final procedure works fine for web sources, like youtube, too: https://vermahitesh.medium.com/play-local-video-on-flutter-web-d757bab0141c

How to onRowClick redirected to another page with mui-datatables npm package?

I have a react app that uses package mui-datatables. I want to be redirected to "/edit-form" onRowClick, but it didn't work (nothing happens, no errors either).
import React, { Component } from "react";
import { Link as RouterLink } from "react-router-dom";
import Link from "#material-ui/core/Link";
import MUIDataTable from "mui-datatables";
class DataTable extends Component {
state={...}
redirectToForm = props => <RouterLink to="/edit-form" {...props}/>
render() {
const options = {
onRowClick: rowData => this.redirectToForm(rowData)
};
return (
<Link
color="secondary"
className={classes.button}
component={this.goToDetailedTable}
>
Detail
</Link>
<MUIDataTable
title={title}
columns={value.state.columnName}
data={value.state.rowData}
options={options}
/>
)
}
When I console.log(rowData), it did print out the row data:
const options = {
onRowClick: rowData => console.log(rowData)
};
Instead of using <Link/> try calling history from the history package and then just history.push('edit/form').