Cannot stack multiple push notifications - javascript

I am working on a code to push notifications to the browser. My code to display notifications look like below
const imageWithTextNotification = (reg) => {
// more options at https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification#Syntax
const options = {
icon: "imgs/notification.png",
// 07 - Notification with a body
body: "Alert!! This is image notification",
// 09 - Actions on notification click (see sw.js for log)
actions: [
{ action: "search", title: "Try Searching!" },
// 10 - More Actions
{ action: "close", title: "Forget it!" },
],
data: {
notificationTime: Date.now(),
githubUser: "hhimanshu"
}
}
reg.showNotification("Counter=" + counter++, options)
}
After reading the documentation from MDN, the code should stack multiple notifications since I am not using the tag property in the options object.
However, in my observation, multiple notifications do not stack. The same notification is replaced (see counter value increased in the demo below). Please see below
The reproducible codebase is available at https://codesandbox.io/s/charming-hellman-8q4t3 and the demo is available at https://8q4t3.sse.codesandbox.io/
I have tested this on
Google Chrome => Version 80.0.3987.163 (Official Build) (64-bit)
Firefox => 75.0 (64-bit)
Could someone please help me understand how can I get the multiple stacked notifications?
Thank you

I was also in touch with #gauntface on twitter and with his help, I was able to fix this issue.
Here is the Twitter thread
And here is the solution

Related

Web Share API not working on iOS: Angular

I am trying to share an image like a native app via web. I am using Angular for the same. I have used the web share API. This works normally on Android however, throws an error while in iOS(Both Safari and Chrome). I am using a share button to trigger this.
This is my code:
if (
this.windowNavigator.canShare &&
this.windowNavigator.canShare({ files: [file] })
) {
this.windowNavigator
.share({
files: [file],
title: "Vacation Pictures",
text: "Photos from September 27 to October 14.",
})
.then(() => console.log("Share was successful."))
.catch((error) => console.log("Sharing failed", error));
} else {
console.error("Cannot use Web Share API");
}
The error I receive is: Cannot use Web Share API
This should typically happen if the browser is not supported.
However, according to https://caniuse.com/#search=web%20share , Safari 13 on iOS is supported.
Please note that I tried logging the navigator object to the console and it does have the share() proto. I am running it over an HTTPS server.
Kindly guide me as to how to proceed.
The error message you receive is, as you know, propagated by your own code. You log the error when navigator does not have a canShare property or navigator.canShare({ files: [file] }) returns falsy.
But the API you need to consume is navigator.share not navigator.canShare as support for the latter is much more limited.
According to MDN as of May 13, 2020:
To work around this problem, consider the following approach
if (typeof this.windowNavigator.share === "function") {
try {
await this.windowNavigator.share({
files: [file],
title: "Vacation Pictures",
text: "Photos from September 27 to October 14.",
});
console.log("Share was successful.");
}
catch (error) {
console.log("Sharing failed", error);
}
}
else {
console.error("Cannot use Web Share API: API unavailable.");
}
Edit (9 June 2021): Web Share API Level 2 is available and usable by default in the iOS 15 Developer Beta, which means it most likely will be available in the final public release of iOS 15.
Like Aluan noted, the API has limited support and is not supported on iOS at all. Keep in mind that this means it is not supported on any iOS browser, even Chrome, since all browsers on iOS use the same (WebKit) engine.
From the App Store Review Guidelines:
2.5.6 Apps that browse the web must use the appropriate WebKit framework and WebKit Javascript.

listen for gamepad connection and input

I would like to provide gamepad support for my web application. This application is a socket client (using socket.io) and it should also being able to deal with gamepad input.
So when plugging in a gamepad via USB or Bluetooth I would like to fire an event, same for input. I was hoping that the Gamepad API would solve it. Unfortunately it didn't.
I created this example
$(document).ready(() => {
window.addEventListener("gamepadconnected", e => {
console.log("connected gamepad");
});
window.addEventListener("gamepaddisconnected", e => {
console.log("disconnected gamepad");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I plug in my XBox360 controller but unfortunately no event was fired. Am I missing something?
I use Chrome Version 76.0.3809.132 (Official Build) on Manjaro Linux (64-bit)
When running navigator.getGamepads() in the console I get this result GamepadList {0: null, 1: null, 2: null, 3: null, length: 4}
And btw. of course my controller is working on other applications e.g. games :)
Update
I installed Firefox 68.0.1 (64-bit) and it worked... but Chromium seems to struggle
TLDR
Refresh gamepad status in a loop and build your own events.
Remind players to press button on their gamepad to get started.
I wrote a little experiment with the Gamepad API, which I have running on thepointless.com. The full source is available on Github.
Essentially, my experiment does the following in a loop and just prints the output to the screen:
JSON.stringify(
[...navigator.getGamepads()]
.filter(p => p)
.map(pad => ({
index: pad.index,
id: pad.id,
mapping: pad.mapping,
axes: pad.axes,
buttons: [...pad.buttons].map(b => ({
pressed: b.pressed,
touched: b.touched,
value: b.value
})),
vibrationActuator: pad.vibrationActuator
})),
null,
2
);
In my writeup, I've noted a few things that I anticipate will be generally helpful for working with the API. But, of more relevance to the OP:
The event listeners are a little unreliable.
Gamepads are not accessible via navigator.getGamepads() until a gamepad button is pressed.
The gamepad objects returned by navigator.getGamepads() are not "live"; you actually need to re-fetch them to gate latest axis and button status.
For those reasons, and particularly because you always need to query navigator.getGamepads() to refresh button/axes statuses anyway, any serious work I do with the API will always re-query for gamepads in my game loop, then check statuses, and instruct users to press a gamepad button if gamepads can't be found. If I need "events", I'll build out my own.
I would suggest others do that same.

bindRows is not a function

I am trying to bind data from NWGW to an existing javascript table for Input value help using getTable().bindRows.
Development tool is WebIDE, All connections are checked. All oData services are OK and providing Live Data, metadata OK.
But I keep getting
Uncaught TypeError: oValueHelpDialog.getTable(...).bindRows is not a
function.
This only happens if the app is running on a small screen device (phone or if I choose phone layout in Chrome Dev Tool).
I don't know if it is because it can get the odata to bind to the table? Does phone handle UI5 differently?
I would appreciate any help. Thanks
-------Update-------
Thank to a nice guy in Answer.SAP. Here is the sample project
Step to reproduce the error:
Import the project to Web IDE
Execute the index.html
Open Chrome Dev Tool
Choose device: iPhone 6/7/8 or whatever phone
Refresh (F5) the app
Click on Value Help Dialog again > lead to a blank table
-------Update END-------
Fragment view
var oValueHelpDialog = new sap.ui.comp.valuehelpdialog.ValueHelpDialog({
title : oController.getStrTextSite(),
supportMultiselect : false,
supportRanges : false,
supportRangesOnly : false,
key : oController.getStrWERKS(),
descriptionKey : oController.getStrNAME1(),
ok: function(oControlEvent) {
oController.setDefaultSiteFromHelp(oControlEvent);
oValueHelpDialog.close();
},
cancel: function(oControlEvent) {
oValueHelpDialog.close();
},
afterClose: function() {
oValueHelpDialog.destroy();
}
});
...
return oValueHelpDialog;
}
Controller
onValueHelpForDefaultSite : function(oEvent) {
var oValueHelpDialog = this.getFragmentForValueHelp();
oValueHelpDialog.open();
...
oValueHelpDialog.getTable().bindRows(
this.getEntitySet(
"ODATA_10_DEFAULT_SITE_SET",
"ODATA_10"
)
);
}
Turns out that in mobile, function bindRows() does not exist so we have to replace it with function bindItems()

Asterisk goes mute in android but works on PC

I have an asterisk for web(calls in the website only) working, on PC, but when I run the same client on my android 5 no sound, at least not in my android, it does send voice to PC, but just cant reproduce the incomming voice.
Everthing seems to be just fine with my asterisk, it shows in call:
servidor-asterisk*CLI> core show channels
Channel Location State Application(Data)
SIP/002670-0000003d (None) Up AppDial((Outgoing Line))
SIP/000001-0000003c 002670#from-internal Up Dial(SIP/002670,60)
2 active channels
1 active call
31 calls processed
But in eclipse console i receive code 405 from android:
"__tsip_transport_ws_onmessage", source: http://IP/videoNodeJs/scripts/sip_api.js (1)
"recv=OPTIONS sip:000001#df7jal23ls0d.invalid;rtcweb-breaker=no;transport=ws SIP/2.0
"Not implemented", source: http://IP/videoNodeJs/scripts/sip_api.js (1)
"SEND: SIP/2.0 405 Method Not Allowed
Any suggestions?
UPDATE:
SIPML5 Client:
<audio id="audio-remote"/>
var opcoes_chamada = {
audio_remote: document.getElementById('audio-remote'),
screencast_window_id: 0x00000000, // entire desktop
bandwidth: { audio:undefined, video:undefined },
video_size: { minWidth:undefined, minHeight:undefined, maxWidth:undefined, maxHeight:undefined },
events_listener: { events: '*', listener: sipEventsListener },
sip_caps: [
{ name: '+g.oma.sip-im' },
{ name: 'language', value: '\"en,fr\"' }
]
};
To make a call:
callSession = sipStack.newSession('call-audio', opcoes_chamada);
callSession.call(sip_id_d);
To answere a call:
e.newSession.setConfiguration(opcoes_chamada);
e.newSession.accept();
405 Method Not Allowed
The method specified in the Request-Line is understood, but not
allowed for the address identified by the Request-URI.
The response MUST include an Allow header field containing a
list of valid methods for the indicated address.
Some interpretation of this, any chance that everthing is fine but the audio TAG is the problem in the mobile client? If not, what is the 'address identified by the Request-URI'?
So, it's working.
Here is the deal, the SIP was just fine, the client to. The hole problem was a chrome limitation that makes necessary a click from the user to play any sound in the browser, it's something like this:
I have my audio tag:
<audio id="audio-remote"/>
and later I feed the source with sipml5:
var opcoes_chamada = {
audio_remote: document.getElementById('audio-remote'),
screencast_window_id: 0x00000000, // entire desktop
bandwidth: { audio:undefined, video:undefined },
video_size: { minWidth:undefined, minHeight:undefined, maxWidth:undefined, maxHeight:undefined },
events_listener: { events: '*', listener: sipEventsListener },
sip_caps: [
{ name: '+g.oma.sip-im' },
{ name: 'language', value: '\"en,fr\"' }
]
};
And here is the catch, the audio tag it's been feed with the SIPML5 source, but it's in pause( or hold, dont know what...) as long the user don't give a onclick action, so right after the 2 lines to make and answere a call I add a button with:
onClick="document.getElementById('audio-remote').play();"
and everthing finally works!

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