Web Share API permission missing - javascript

I'm trying to implement the Web Share Api functionality on my test web app but it doesn't seem I'm able to do it. This is the code:
const newVariable: any = navigator;
{newVariable && newVariable.share && <IconButton aria-label="Share" onClick={async (e) => {
try {
const id = await shareRepository.shareTrip(this.props.todolist)
const url = "https://something.com/share/" + id
await newVariable.share({
title: 'Check my todolist for ' + this.props.todolist.trip.departure + ' - ' + this.props.todolist.trip.arrival,
text: 'Check my todolist for ' + this.props.todolist.trip.departure + ' - ' + this.props.todolist.trip.arrival,
url: url,
})
} catch (error) {
alert(error)
}
}}>
<ShareIcon />
</IconButton>}
Every time I try on both Firefox and Safari for iOS, I'm getting an error saying:
NotAllowedError: the request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
If on those browser I try to share something from google.com I get the native dialog to choose with which app to share.
I cannot understand why. On this page there is no discussion about permission: https://developers.google.com/web/updates/2016/09/navigator-share
UPDATE:
on Chrome for android works just fine, on Firefox for Android doesn't work. On Chrome, Firefox and Safari (which I believe they use safari engine all three) is only working if I pass "" which means the page itself, or "https://something.com/share/", it breaks If I pass "https://something.com/share/"+id :/

For other future users where the current answer is too specific to that code. The root issue is that the share() method must be called from a user gesture.
If the method call was not triggered by user activation, return a promise rejected with with a "NotAllowedError" DOMException.
From the Web Share API.
A user activation is any of the following:
change
click
contextmenu
dblclick
mouseup
pointerup
reset
submit
touchend

I understood what was the issue, which is absolutely annoying.
So:
const id = await shareRepository.shareTrip(this.props.todolist)
This call is the one that is causing problems. If I comment it, on iOS there is no issue.
If I keep it I have no problem at all on Android but iOS will complain.
So I need to rethink the flow of the application to pass the id from outside the 'onClick' event.

Related

Chrome, allow autoconnect for HID device

So I'm trying to read out a USB-scale thats connected to my pc. I use chrome's experimental HID api.
I use Tampermonekey as userscript injector to extend a website's functionality.
The script I inject looks like this:
navigator.hid.requestDevice({ filters: [{ vendorId: 0x0922, productId: 0x8003}] }).then((devices) => {
if (devices.length == 0) return;
devices[0].open().then(() => {
if(disconnected) {
disconnected = false
}
console.log("Opened device: " + devices[0].productName);
devices[0].addEventListener("inputreport", handleInputReport);
devices[0].sendReport(outputReportId, outputReport).then(() => {
console.log("Sent output report " + outputReportId);
});
});
});
When I run it just like this(inline) I get the message in chrome:
DOMException: Failed to execute 'requestDevice' on 'HID': Must be handling a user gesture to show a permission request.
Basically, the code needs to be inside an event listener and the listener needs to be triggered by user input to run.
Al fine and dandy, except that this has to be initialized hundreds of times a day. I tried running this code in edge and here it just works without user input.
Is there a way I can disable this security feature(completely or only for the site im using it on) in chrome? I know edge is based on chromium so I expect it to be possible, but am unable to find how/where
You can use HID.getDevices() to retrieve an HID device that the user has already granted access to.
My suggestion would be to check for the device you want with getDevices first. If you can't find the device, then make something the user can interact with that will allow you to use requestDevice to connect to the device.

Not allowed to launch cutom protocol because a user gesture is required

I need to run my custom protocol twice but it doesn't work the second time, I got this error ( Not allowed to launch 'cutomProtocol' because user gesture is required. ) I tried to find a solution but I did not find any!
Same problem with chrome, firefox and edge.
I need to see this popup twice
window.location.href = 'my-protocol://${base64}';
and
customProtocolVerify(
`my-protocol://${base64}`,
() => {
// successCb: Callback function which gets called when custom protocol is found.
console.log('My protocol found and opened the file successfully..');
},
() => {
// failCb: Callback function which gets called when custom protocol not found.
console.log('My protocol not found.');
}
);
I tried with these two and didn't work
Clarification
I have a custom protocol.
My scenario:
check if it's installed successfully (I'm using customProtocolVerify method) and that method makes the launch if the protocol is found
run some APIs
launch the protocol again
My problem:
Step 3 doesn't work, I have the error on the console that says " Not allowed to launch... " and of course I can't see my popup to open my protocol.
I'm asking for help to make step 3 work
The only way to bypass this "bug" is to ask the user twice (or in a loop) by showing a OK alert or some sort of user confirm box.
My solution:
OpenLinkInExternalApp(Link);
alerty.alert('', { title: '', okLabel: 'Open Link' }, function () {
OpenLinkInExternalApp(Link);
});
The above code will open the external app, then a OK alert will pop up, after clicking OK, I call the same code again. Do this in a loop if needed.
TIP:
We guide our users to use split screen at this stage. This is where users can dock your web-app on the left and the external app on the right as an example.
Alert Box:
We user Alerty.js https://github.com/undead25/alerty#readme

service worker notificationclick event doesn't focus or open my website in tab

I use FCM push notification in my website and I want user can come into my website when He or She clicks on the push notification. Please notes that The user may be in other app or in other browser tab and I want when the user gets fcm notification the user will be able to come into my website by a click on the notification in the Firefox browser. For this reason, I used notificationclick event which Is available in the service worker. The code that I used is this:
self.addEventListener('notificationclick', event => {
console.log('On notification click: ', event.notification.tag);
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients
.matchAll({
type: 'window'
})
.then(clientList => {
for (let i = 0; i < clientList.length; i++) {
const client = clientList[i];
if (client.url === '/' && 'focus' in client) return client.focus();
}
if (clients.openWindow) return clients.openWindow('/');
})
);
});
It doesn't openwindow or focuses on my website tab. To debug the code I printed the clientList variable and It is an array with zero length.
The error that I get in the browser is this
On notification click:
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable firebase-messaging-sw.js:92
The above error refers to this line of code:
event.waitUntil(
OS: Mac
firefox:63.0.3
reactjs:16.2.0
Move your notificationclick handler BEFORE your line of code with messaging = firebase.messaging();. The FCM JS SDK installs its own global notificationclick handler and its e.waitUntil() call manages to (somehow) break the Firefox event object. If you install your global handler first, then it gets called first and so it will actually work. However, it will probably break the FCM handler in some obscure fashion.
This is, IMO, a bug in Firefox itself with regards to Service Workers rather than FCM, but FCM certainly contributes to the problem.
Relevant:
https://github.com/firebase/quickstart-js/issues/282 (same FCM bug)
https://bugzilla.mozilla.org/show_bug.cgi?id=1468935 (same FCM + Firefox bug, bad fix)
https://bugzilla.mozilla.org/show_bug.cgi?id=1313096 (the Firefox dev team doesn't have a way to test the callback in its Service Worker test suite, which makes this part of Firefox ripe for bugs)
https://bugzilla.mozilla.org/show_bug.cgi?id=1489800 (same browser bug, different product)
If the goal is to open a specific URL when the notification is clicked, there may be an easier way. You can sent a "click_action" field in the FCM notification payload.
Your payload would look something like this:
"notification" : {
"body" : "Sample body",
"title" : "Sample title",
"click_action": "http://google.com"
}
And when the notification is clicked, it will open google.com in this example.

I cannot get authData by using authWithOAuthRedirect with Chrome on IOS

I am integrating my project with facebook auth login, and I want to support Chrome on IOS. I noticed that I have to handle both authWithOAuthPopup and authWithRedirect (firebase user-auth) in this case. However Chrome IOS did not support Popup auth currently.
I simplify my code and shows the case how it won't work in Chrome on IOS
var rootRef = new Firebase('https://docs-sandbox.firebaseio.com/web/uauth');
rootRef.onAuth( function(authData){
alert('getAuth');
alert(authData);
console.log(authData);
});
$('#login').on('click', function(e){
rootRef.authWithOAuthPopup("facebook", function(err, authData){
if(err && err.code === 'TRANSPORT_UNAVAILABLE'){
rootRef.authWithOAuthRedirect("facebook", function(err, authData){
if(authData){
alert('redirect');
alert(authData);
}
})
}
})
});
Link here http://jsfiddle.net/blackbing/zjunuzec/5/ for more detail.
It works on Safari IOS. If login success, it will alert [object], but it shows null in Chrome on IOS.
any idea?
I think that I figure out what the problem is.
First of all, it is said getAuth is synchronized in document, but It is not reliable synchronized on authWithOAuthRedirect. So when the page redirect to the original page. I can't get authData so that I can't decide if user is signin. (but actually user is signed in).
Second, since callback in "authWithOAuthRedirect" is not possible to be called, the callback function can't get authData anyway. It just could be called if occur error, right? I suggest to notice this behavior that in document.
Anyway: I think the snippet in document have to correct :
https://www.firebase.com/docs/web/guide/user-auth.html#section-popups
the callback in authWithFunction is for handling error, not suggested to deal with authData, onAuth is a better way to get authData. I update a snippet on my gist [https://gist.github.com/blackbing/f77d04cbed4b0059af2e]
var ref = new Firebase("https://<your-firebase>.firebaseio.com");
rootRef.onAuth( function(authData){
//It is a better way to get authData instead of get from auth callback function
console.log(authData);
});
// prefer pop-ups, so we don't navigate away from the page
// auth callback is to handle if occur error
ref.authWithOAuthPopup("google", function(err) {
if (err) {
if (err.code === "TRANSPORT_UNAVAILABLE") {
// fall-back to browser redirects, and pick up the session
// automatically when we come back to the origin page
ref.authWithOAuthRedirect("google", function(err) { ... });
}
}
});
BTW, I found a similar question https://stackoverflow.com/a/26416696/797411, the workaround is not good but I think we met the same problem.

Is it possible to trigger share menu on smartphones (via HTML/JS)?

Is there an existing possibility to trigger the share functionality in local browsers on smartphones via HTML or JavaScript?
Of course there are many services which provide a share button. But when I e.g. want to share a website on facebook, I need to be logged in to facebook in the browser I am currently using.
Almost all browsers got an own share functionality build in, which triggers a system menu to choose which app you want to use to share:
This question is about: How to trigger this menu?
I know it is possible to trigger a phone call with a specified prefix in href attribute of links, like tel: or callto:. Maybe such a shortcut for this share menu is also existing? Or some javascript code? Or a totally different way how to do it?
Thanks in advance.
It is possible with a big catch. Currently only available in Chrome for Android, Samsung internet and on Safari (desktop and mobile). And support is coming to Edge and Chrome on desktop http://caniuse.com/#feat=web-share
if (navigator.share) {
navigator.share({
title: document.title,
text: "Hello World",
url: window.location.href
})
.then(() => console.log('Successful share'))
.catch(error => console.log('Error sharing:', error));
}
https://developers.google.com/web/updates/2016/10/navigator-share
I added this as all answers seems outdated by 2018-07-16.
It is possible, but only in a few browsers (MDN Reference), achieved througth the one method API in navigator:
navigator
.share({
title: document.title,
text: 'Hello World',
url: window.location.href
})
.then(() => console.log('Successful share! 🎉'))
.catch(err => console.error(err));
Google's reference: https://developers.google.com/web/updates/2016/10/navigator-share
Also, there was a thing called Web Intends which is a dead project, you should go with navigator.share instead.
It's now possible with the Web Share API!
However, it isn't widely supported as of yet. Currently, it's only available in Safari (mobile and desktop), and Chrome for Android. See Can I Use for details.
According to Introducing the Web Share API on Google Developers, there are several things to keep in mind:
your page needs to be served over HTTPS
you can only call navigator.share(…) in response to a user action, such as a click (i.e., you can't call it on page load)
you should feature-detect it in case it's not available on your users' platform (e.g., via navigator.share !== undefined)
The Google Developers article also notes that URLs shared with the Share API need not be on your own domain—you can share any URL.
Putting that all together, you could use something like this which uses the Share API if it's available, and falls back to sending an email if it's not*:
function createShareButton() {
const btn = document.createElement("button");
const title = document.title;
const text = "Check this out!";
const url = window.location.href;
btn.innerText = "share" in navigator ? "Share" : "Share via e-mail";
btn.onclick = () => {
if (navigator.share !== undefined) {
navigator
.share({
title,
text,
url
})
.then(() => console.log("Shared!"))
.catch(err => console.error(err));
} else {
window.location = `mailto:?subject=${title}&body=${text}%0A${url}`;
}
};
return btn;
}
document.title = "Demo";
document.body.appendChild(createShareButton());
*: Please do consider using a more appropriate fallback, (e.g., social sharing) depending on your use case.
Answered Apr 10 2013
To my knowledge, there is no such implementation in current browsers on mobile OS's. Since the question interested me - a google search revealed there is work being done in this direction:
https://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html
http://webintents.org/
Sorry - I do not know a workaround.
It is possible and I wrote a function to have pretty content to share and observe the asynchronous side effects:
const shareContact = async (title, content) => {
const text = `${title}
${content}`;
try {
await navigator.share({
text,
});
} catch (e) {
console.log(e);
}
};
You could use the WebView.addJavascriptInterface() method for android.
First you will need to write a class which fires the intent to open the share menu(take a look here) and then implement that class using the addJavascriptInterface() call. After that all you need to do is call the method from your Javascript.

Categories

Resources