Service Worker "notificationclick" not firing - web-notifications

The notification is showing fine, but when I click on it, or any of the actions, nothing happens. I see no logging, no error messages, but the notification does close (although it closes even when I comment out the event.notification.close()).
I've tried using the Chrome debugger, and I can set a break point in the code that shows the notification, but all breakpoints within the notificationclick handler fail to pause execution.
I've spent days trying to get this to work and I'm at my wits' end.
const auth = firebase.auth();
const functions = firebase.functions();
const done = functions.httpsCallable("done");
const snooze = functions.httpsCallable("snooze");
self.addEventListener("notificationclick", event => {
console.log("notificationclick", event);
const uid = auth.currentUser.uid;
const { id, url } = event.notification.data;
event.notification.close();
event.waitUntil(() => {
switch (event.action) {
case "done":
console.log("Done");
return done({ uid, id });
case "snooze1":
console.log("Snooze 1 Hour");
return snooze({ uid, id, hours: 1 });
case "snooze24":
console.log("Snooze 1 Day");
return snooze({ uid, id, hours: 24 });
default:
console.log("Open App");
return clients
.matchAll({
includeUncontrolled: true,
type: "window"
})
.then(clientList => {
for (let i = 0; i < clientList.length; i++) {
let client = clientList[i];
if (url[0] === "#") {
if (client.url.endsWith(url) && "focus" in client) {
return client.focus();
}
} else {
if (
client.url.replace(/#.*$/, "") === url &&
"focus" in client
) {
return client.focus();
}
}
}
if (clients.openWindow) {
return clients.openWindow(location.origin + url);
}
});
}
});
});
firebase
.messaging()
.setBackgroundMessageHandler(({ data: { title, options } }) => {
options = JSON.parse(options);
options.actions = [
{ action: "done", title: "Done" },
{ action: "snooze1", title: "Snooze 1 Hour" },
{ action: "snooze24", title: "Snooze 1 Day" }
];
return self.registration.showNotification(title, options);
});

Hi Could you try below code and see if this is getting called-
self.addEventListener('notificationclick', function (event) {
event.notification.close();
var redirectUrl = null;
var tag = event.notification.tag;
if (event.action) {
redirectUrl = event.action
}
if (redirectUrl) {
event.waitUntil(async function () {
var allClients = await clients.matchAll({
includeUncontrolled: !0
});
var chatClient;
for (const client of allClients) {
if (redirectUrl != '/' && client.url.indexOf(redirectUrl) >= 0) {
client.focus();
chatClient = client;
break
}
}
if (chatClient == null || chatClient == 'undefined') {
chatClient = clients.openWindow(redirectUrl);
return chatClient
}
}().then(result => {
if (tag) {
//PostAction(tag, "click")
}
}))
}
});
Edited-
Attaching both js files. it is working at my end.
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
var config = {
apiKey: "your api key",
authDomain: "you firebase domain",
databaseURL: "your firbase db url",
projectId: "your project id",
storageBucket: "",
messagingSenderId: "sender id"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload.data);
var notificationTitle = payload.data.Title;
var notificationOptions = {
body: payload.data.Body,
icon: payload.data.Icon,
image: payload.data.Image,
action: payload.data.ClickAction
};
console.log("strated sending msg" + notificationOptions);
return self.registration.showNotification(notificationTitle,notificationOptions);
});
self.addEventListener('notificationclick', function (event) {
console.log('On notification click: ', event.notification);
event.notification.close();
var redirectUrl = null;
if (event.notification.data) {
if (event.notification.data.FCM_MSG) {
redirectUrl = event.notification.data.FCM_MSG.data ? event.notification.data.FCM_MSG.data.click_action : null
} else {
redirectUrl = event.notification.data ? event.notification.data.click_action : null
}
}
console.log("redirect url is : " + redirectUrl);
if (redirectUrl) {
event.waitUntil(async function () {
var allClients = await clients.matchAll({
includeUncontrolled: true
});
var chatClient;
for (var i = 0; i < allClients.length; i++) {
var client = allClients[i];
if (client['url'].indexOf(redirectUrl) >= 0) {
client.focus();
chatClient = client;
break;
}
}
if (chatClient == null || chatClient == 'undefined') {
chatClient = clients.openWindow(redirectUrl);
return chatClient;
}
}());
}
});
self.addEventListener("notificationclose", function (event) {
event.notification.close();
console.log('user has clicked notification close');
});
application.js file :
/// <reference path="scripts/jquery-3.3.1.js" />
try {
var config = {
apiKey: "your api key",
authDomain: "you firebase domain",
databaseURL: "your firbase db url",
projectId: "your project id",
storageBucket: "",
messagingSenderId: "sender id"
};
firebase.initializeApp(config);
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push is supported');
navigator.serviceWorker
.register('/firebase-messaging-sw.js')
.then((swReg) => {
firebase.messaging().useServiceWorker(swReg);
askForPermissioToReceiveNotifications();
})
.catch(function (error) {
console.error('Service Worker Error', error);
window.alert("Service Worker Error" + error);
})
} else {
console.warn('Push messaging is not supported');
window.alert("Push messaging is not supported " + (navigator.serviceWorker));
}
const askForPermissioToReceiveNotifications = async () => {
try {
const messaging = firebase.messaging();
console.log(messaging);
await messaging.requestPermission();
const token = await messaging.getToken();
if (token !== null || token !== 'undefined') {
await sendDeviceTokenToServerSide(token);
}
console.log('Got token : ' + token);
messaging.onMessage(function (payload) {
console.log('onMessage: ', payload);
setTimeout(() => {
navigator.serviceWorker.ready.then(function (registration) {
var notificationTitle = payload.notification.title;
var notificationOptions = {
body: payload.notification.body,
data: payload.data,
icon: payload.notification.icon,
image: payload.data.Image,
requireInteraction: payload.notification.requireInteraction,
tag: payload.notification.tag,
click_action: payload.data.click_action,
requireInteraction: true
};
registration.showNotification(notificationTitle, notificationOptions);
},50)
});
});
}
catch (e) { console.log('error in getting token: ' + e); window.alert("error in getting token: " + e); }
}
function sendDeviceTokenToServerSide(token) {
$.ajax({
type: 'POST',
url: '/Home/StoreToken',
timeout: 5000000,
data: { token: token },
success: function (success) {
console.log("device token is sent to server");
},
error: function (error) {
console.log("device error sending token to server : " + error);
window.alert("device error sending token to server : " + error);
}
});
}
} catch (e) {
window.alert("error: " + e);
}
function GetFcmUserToken(messaging) {
messaging.onTokenRefresh(function () {
messaging.getToken()
.then(function (refreshedToken) {
console.log('Token refreshed.');
return refreshedToken;
})
.catch(function (err) {
console.log('Unable to retrieve refreshed token ', err);
showToken('Unable to retrieve refreshed token ', err);
});
});
}

self.addEventListener('notificationclick', function (event) {
const clickedNotification = event.notification;
// Do something as the result of the notification click
const promiseChain = clients.openWindow(clickedNotification.data.Url);
event.waitUntil(promiseChain);
});
This code inside service worker js worked fine for me on chrome Desktop and Android.

Related

Unable to call any API from onAppointmentSend? Is this a limtation? Codes working on web outlook but not for Desktop Outlook

these are similar issues posted online
Relative fetch or XHR in a UI-Less Outlook add-in on Windows
How to make a http request in Outlook add-ins?
Officejs - Addin Outlook - SmartAlerts
Add-in built on jQuery framework works well on web-based outlook but doesn't on Desktop App
Outlook OnNewMessageCompose event not firing in Windows client
In outlook add-ins make salesforce oauth2 auth request getting CORS error
Common JavaScript function for Outlook Add-ins
React fetch not working with localhost endpoint with spring boot backend but ok with dummy JSON data
What is the easiest way to integrate Outlook web add-in into an existing ASP.NET Core 6 application?
Outlook Addin getting CORS when making request to ewsURL
if (_contextInfo.platform == "PC") {
console.log("PC");
Office.context.mailbox.item.subject.setAsync("Set by: New", { "asyncContext": event },
function (asyncResultPC) {
if (asyncResultPC.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultPC.error));
}
asyncResult.asyncContext.completed();
});
$.when(GetToken()).done(function () {
Office.context.mailbox.item.subject.setAsync("GetToken" + objResourceCurrent.token, { "asyncContext": event },
function (asyncResultToken) {
if (asyncResultToken.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultToken.error));
}
asyncResult.asyncContext.completed();
});
/*if (isNotNull(originalAppointment)) {
SetResourceAvailabilityByDatetimeRequest(originalAppointment);
if (objResourceCurrent.token != "" && objResourceCurrent.availabilityCriteria.length > 0) {
GetResourceAvailabilityByDatetime();
}
}*/
});
event.completed({ allowEvent: false, errorMessage: "From Desktop" });
}
else if (_contextInfo.platform == "OfficeOnline") {
console.log("OfficeOnline");
Office.context.mailbox.item.start.getAsync((asyncResultStartDt) => {
if (asyncResultStartDt.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`Start Error:: ${asyncResultStartDt.error.message}`);
event.completed();
return;
}
originalAppointment.start = convertDateCS(asyncResultStartDt.value);
Office.context.mailbox.item.end.getAsync(function (asyncResultEndDt) {
if (asyncResultEndDt.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`End Error:: ${asyncResultEndDt.error.message}`);
event.completed();
return;
}
originalAppointment.end = convertDateCS(asyncResultEndDt.value);
Office.context.mailbox.item.sessionData.getAsync("bookingObject", function (asyncResultBO) {
if (asyncResultBO.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`BO Error:: ${asyncResultBO.error.message}`);
event.completed();
return;
}
const bookingObjectAllData = JSON.parse(asyncResultBO.value);
$.each(bookingObjectAllData["Office365AddInBookingItem"], function (index, item) { if (item.IsAddon == false) { ResourceIds = ResourceIds + item.ResourceId + ","; } });
originalAppointment.ResourceIds = ResourceIds;
result = checkRoomAvailabilityOutlook(originalAppointment.ResourceIds, originalAppointment.start, originalAppointment.end);
if (result) {
$.each(result, function (id, item) {
if (item.Value) {
availableRooms.push(item.Key)
}
else {
unAvailableRooms.push(item.Key)
}
});
}
else {
event.completed({ allowEvent: false, errorMessage: "checkRoomAvailabilityOutlook API Responsed with No Data" });
}
if (unAvailableRooms.length > 0) {
$.each(bookingObjectAllData["Office365AddInBookingItem"], function (index, item) {
if ($.inArray(item.ResourceId, unAvailableRooms) !== -1)
unavailableEmails = unavailableEmails !== '' ? unavailableEmails + ', ' + item.ResourceEmailId : item.ResourceEmailId;
});
event.completed({ allowEvent: false, errorMessage: "Unavailable room(s): " + unavailableEmails });
}
else {
if (availableRooms.length > 0) {
$.each(bookingObjectAllData["Office365AddInBookingItem"], function (index, item) {
if ($.inArray(item.ResourceId, availableRooms) !== -1)
availableEmails = availableEmails !== '' ? availableEmails + ', ' + item.ResourceEmailId : item.ResourceEmailId;
});
}
}
var itemId = Office.context.mailbox.item.itemId;
if (itemId === null || itemId == undefined) {
Office.context.mailbox.item.saveAsync(function (asyncResultSave) {
if (asyncResultSave.status !== Office.AsyncResultStatus.Succeeded) {
console.error(`End Error:: ${asyncResultSave.error.message}`);
event.completed();
return;
}
bookingObjectAllData.ExchangeReferenceNumber = asyncResultSave.value;
createSaveBookingRequest(bookingObjectAllData, originalAppointment);
saveBooking(bookingObj);
console.log(JSON.stringify(bookingObjectAllData));
event.completed({ allowEvent: true, errorMessage: "ItemId: " + asyncResultSave.value });
});
}
else {
console.log("Item already saved");
}
});
});
});
}
I tried XMLHttpRequest and fetch. both fails.
function GetToken() {
return $.ajax({
cache: false,
type: "POST",
contentType: "application/json",
url: "https://xyz/xyz/token",
data: {
username: "abc...",
password: "r6COP...",
grant_type: "password",
},
success: function (result) {
objResourceCurrent.token = result.access_token;
},
error: function (error) {
console.log("GetToken Error ", error);
}
});
}
Update
My above issue is still not resolved however As a test, I am able to call this open weather API. It working just fine with Windows Desktop/Web Outlook's OnSend or timeChange event handlers.
function onAppointmentSendHandler(event) {
console.log("onAppointmentSendHandler");
const _contextInfo = Office.context.diagnostics;
if (_contextInfo.platform == "PC") {
var url = 'https://api.openweathermap.org/data/2.5/weather?lat=28.644800&lon=77.216721&appid=efc8b889e4d57fbcc6fb2b523d2558c8';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.send();
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
console.log(request.responseText);
const myObj = JSON.parse(request.responseText)
var _Dtext = "From Desktop: City: " + myObj.name + ", Temp: " + myObj.main.temp + "f";
Office.context.mailbox.item.subject.setAsync(_Dtext, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
event.completed({ allowEvent: false });
});
}
else {
console.log("Problem retrieving data PC");
console.log(this.responseXML);
}
}
}
}
else if (_contextInfo.platform == "OfficeOnline") {
console.log("Office Online");
var url = 'https://api.openweathermap.org/data/2.5/weather?lat=28.474388&lon=77.503990&appid=efc8b889e4d57fbcc6fb2b523d2558c8';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.send();
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
//console.log(request.responseText);
const myObj = JSON.parse(request.responseText)
var _Otext = "From Online: City: " + myObj.name + ", Temp: " + myObj.main.temp + "f";
Office.context.mailbox.item.subject.setAsync(_Otext, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
event.completed({ allowEvent: false });
});
}
else {
console.log("Problem retrieving data Office Online");
console.log(this.responseXML);
}
}
}
}
}
function onAppointmentTimeChangedHandler(event) {
console.log("onAppointmentTimeChangedHandler");
var url = 'https://api.openweathermap.org/data/2.5/weather?lat=23.669296&lon=86.151115&appid=efc8b889e4d57fbcc6fb2b523d2558c8';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.send();
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
console.log(request.responseText);
const myObj = JSON.parse(request.responseText)
var _text = "From Time Change: City: " + myObj.name + ", Temp: " + myObj.main.temp + "f";
Office.context.mailbox.item.subject.setAsync(_text, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
});
}
else {
console.log("Problem retrieving data");
console.log(this.responseXML);
}
}
}
}
Office.actions.associate("onAppointmentTimeChangedHandler", onAppointmentTimeChangedHandler);
Office.actions.associate("onAppointmentSendHandler", onAppointmentSendHandler);
Update 2 I am testing another API with 3 fields Subject, StartDate and End Date. Please note: This below code runs perfectly on Web outlook for OnSend/TimeChange events but not for Desktop Outlook OnSend /TimeChange events. And I do not get any error message or something.
Any help is much appriciated.
function onAppointmentSendHandler(event) {
console.log("onAppointmentSendHandler");
const _contextInfo = Office.context.diagnostics;
if (_contextInfo.platform == "PC") {
var obj = JSON.stringify({
Subject: "Azure Desktop 1",
StartDate: "03/02/2023",
EndDate: "03/31/2023"
});
username = "admin1";
password = "pass#123";
var url = 'https://externalwebapi.azurewebsites.net/api/save';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
request.send(obj);
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
console.log(request.responseText);
var _Dtext = "Azure Desktop 1";
Office.context.mailbox.item.subject.setAsync(_Dtext, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject1: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
event.completed({ allowEvent: false });
});
}
else {
console.log("Problem retrieving data PC");
console.log(this.responseXML);
}
}
}
}
else if (_contextInfo.platform == "OfficeOnline") {
console.log("Office Online");
var obj = JSON.stringify({
Subject: "Azure WebSite 1",
StartDate: "02/02/2023",
EndDate: "02/28/2023"
});
//console.log(obj);
username = "admin1";
password = "pass#123";
var url = 'https://externalwebapi.azurewebsites.net/api/save';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
request.send(obj);
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
console.log(request.responseText);
var _Dtext = "Azure WebSite 1";
Office.context.mailbox.item.subject.setAsync(_Dtext, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
event.completed({ allowEvent: false });
});
}
else {
console.log("Problem retrieving data Web");
console.log(this.responseXML);
}
}
}
}
}
function onAppointmentTimeChangedHandler(event) {
console.log("onAppointmentTimeChangedHandler");
var obj = JSON.stringify({
Subject: "Azure Time",
StartDate: "02/02/2023",
EndDate: "02/28/2023"
});
username = "admin1";
password = "pass#123";
var url = 'https://externalwebapi.azurewebsites.net/api/save';
var request = new XMLHttpRequest();
request.onreadystatechange = state_change;
request.open("POST", url, true);
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
request.send(obj);
function state_change() {
if (request.readyState == "4") {
if (request.status == "200") {
console.log(request.responseText);
var _Dtext = "Azure Time";
Office.context.mailbox.item.subject.setAsync(_Dtext, { "asyncContext": event }, function (asyncResultWeb) {
if (asyncResultWeb.status !== Office.AsyncResultStatus.Succeeded) {
console.error("Failed to set subject2: " + JSON.stringify(asyncResultWeb.error));
}
asyncResultWeb.asyncContext.completed();
event.completed({ allowEvent: false });
});
}
else {
console.log("Problem retrieving data Web");
console.log(this.responseXML);
}
}
}
}
Office.actions.associate("onAppointmentTimeChangedHandler", onAppointmentTimeChangedHandler);
Office.actions.associate("onAppointmentSendHandler", onAppointmentSendHandler);
REST API calls are supported and can be made from the onSend event handlers (callbacks). You just need to make sure that CORS is addressed in the add-in. The very first link in your post contains the valid answer to your case.
The same-origin policy enforced by the browser prevents a script loaded from one domain from getting or manipulating properties of a webpage from another domain. This means that, by default, the domain of a requested URL must be the same as the domain of the current webpage. For example, this policy will prevent a webpage in one domain from making XmlHttpRequest web-service calls to a domain other than the one where it is hosted.
Because Office Add-ins are hosted in a browser control, the same-origin policy applies to script running in their web pages as well.
The same-origin policy can be an unnecessary handicap in many situations, such as when a web application hosts content and APIs across multiple subdomains. There are a few common techniques for securely overcoming same-origin policy enforcement. The Addressing same-origin policy limitations in Office Add-ins article can only provide the briefest introduction to some of them.

How to play DRM content using native WebOS player

We are trying to play video content using native WebOS player and com.webos.service.drm service. The goal is to play at least some DRM content (dash+widevine or hls+widevine). Clear content works fine, but DRM content stucks completely, and no diagnostic messages appear.
The same result happens on WebOS 3.4, 4.4, and 6.0. Is there any working example of DRM content playback?
Our code is given below.
var appId = "com.zodiac.app";
// Define DRM Type
var drmType = "widevine";
function webos_request(service, params)
{
var caller = arguments.callee.caller.name;
console.log("REQ: %s: %s %s", caller, service, JSON.stringify(params))
return new Promise( function(resolve, reject) {
webOS.service.request(service, Object.assign({}, params, {
onSuccess: function (result) { console.log("REQ SUCCESS: %s: %s %s: %s", caller, service, params.method, JSON.stringify(result)); resolve(result) },
// onFailure: function (result) {
// console.log("[" + result.errorCode + "] " + result.errorText);
// reject()
// }
onFailure: function (result) { console.error("REQ ERROR: %s: %s %s: %s", caller, service, params.method, JSON.stringify(result)); reject(result) }
}))
});
}
function webos_subscribe(service, params, method)
{
var caller = arguments.callee.caller.name;
var completed = false
return new Promise( function(resolve, reject) {
params.parameters = params.parameters || {}
params.parameters.subscribe = true;
console.log("SUB: %s: %s %s", caller, service, JSON.stringify(params))
webOS.service.request("luna://com.webos.service.drm", Object.assign({}, params, {
onSuccess: function (result) { // Subscription Callback
if (!completed) {
completed = true;
if (result.subscribed) {
console.log("SUB: %s: %s: SUCCESS", caller, service)
resolve(result)
}
else {
console.error("SUB: %s: %s: FAILED", caller, service)
reject();
}
}
else
method(result)
},
onFailure: function (result) {
console.error("SUB: %s: %s: onFailure", caller, service, result)
// console.log('Player.subscribeLicensingError onFailure: ' + '[' + result.errorCode + '] ' + result.errorText);
completed = true;
reject()
}
}));
});
}
function unloadDrmClient(clientId)
{
webos_request("luna://com.webos.service.drm",
{
method:"unload",
parameters: {
"clientId": result.clientId
}
});
}
function loadDrmClient()
{
return webos_request( "luna://com.webos.service.drm", {
method:"load",
parameters: {
"drmType": drmType,
"appId": appId
}})
.then(function (result) {
console.log("DRM Client is loaded successfully. %s", JSON.stringify(result));
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
unloadDrmClient(result.clientId)
}
})
return result.clientId
})
}
function sendRightInformation(clientId, url, la_url) {
var msgId;
// Message format for widevine
var msg = [
'<?xml version="1.0" encoding="utf-8"?>',
'<WidevineCredentialsInfo xmlns="http://www.smarttv-alliance.org/DRM/widevine/2012/protocols/">',
'<ContentURL>' + url + '</ContentURL>',
'<DeviceID></DeviceID>',
'<StreamID></StreamID>',
'<ClientIP></ClientIP>',
'<DRMServerURL>' + la_url + '</DRMServerURL>',
'<DRMAckServerURL></DRMAckServerURL>',
'<DRMHeartBeatURL></DRMHeartBeatURL>',
'<DRMHeartBeatPeriod>0</DRMHeartBeatPeriod>',
'<UserData></UserData>',
'<Portal></Portal>',
'<StoreFront></StoreFront>',
'<BandwidthCheckURL></BandwidthCheckURL>',
'<BandwidthCheckInterval></BandwidthCheckInterval>',
'</WidevineCredentialsInfo>',
].join("")
// Message type for widevine
var msgType = "application/widevine+xml";
// Unique ID of DRM system
var drmSystemId = "urn:dvb:casystemid:19156";
return webos_request( "luna://com.webos.service.drm", {
method:"sendDrmMessage",
parameters: {
"clientId": clientId,
"msgType": msgType,
"msg": msg,
"drmSystemId": drmSystemId
}})
.then( function (result) {
// DRM API does not return the msgId, resultCode, resultMsg for Widevine type.
console.log("sendDrmMessage succeeded. %s", JSON.stringify(result));
return
});
}
function subscribeLicensingError(clientId, msgId)
{
return webos_subscribe("luna://com.webos.service.drm", {
method:"getRightsError",
parameters: {
"clientId": clientId
}},
function (result) { // Subscription Callback
var contentId = result.contentId;
if (contentId == msgId) {
if ( 0 == result.errorState) {
console.log("No license");
// Do something for error handling
}
else if ( 1 == result.errorState) {
console.log("Invalid license");
// Do something for error handling
}
else {
console.log("Unknown errorState: %s", JSON.stringify(result));
}
}
else {
console.log("skip notification %s", JSON.stringify(result));
}
});
}
var video = document.getElementById('myVideo');
function playback()
{
var config = {
'dash+wv': {
type: "application/dash+xml",
mediaTransportType: "WIDEVINE",
url: 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd',
la_url: 'https://widevine-proxy.appspot.com/proxy'
},
'hls+wv': {
type: "application/x-mpegURL",
mediaTransportType: "HLS",
url: 'https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine-hls/hls.m3u8',
la_url: 'https://cwip-shaka-proxy.appspot.com/no_auth'
},
'mp4': {
type: "video/mp4",
url: "https://jsoncompare.org/LearningContainer/SampleFiles/Video/MP4/Sample-MP4-Video-File-Download.mp4"
},
'hls': {
type: "application/vnd.apple.mpegurl",
url: "https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8",
},
'dash': {
type: "application/dash+xml",
url: 'https://storage.googleapis.com/shaka-demo-assets/bbb-dark-truths/dash.mpd'
}
}
var stream = config['hls+wv']
var prepare
if (stream.la_url) {
prepare = loadDrmClient()
.then( function(id) {
subscribeLicensingError(id, undefined);
document.body.addEventListener("unload", function() {
webOS.service.request("luna://com.webos.service.drm", {
method:"unload",
parameters: { "clientId": id },
onSuccess: function (result) {
console.log("DRM Client is unloaded successfully.");
},
onFailure: function (result) {
console.log("[" + result.errorCode + "] " + result.errorText);
// Do something for error handling
}
});
})
return sendRightInformation(id, stream.url, stream.la_url).then( function () { return id; })
})
}
else {
prepare = Promise.resolve()
}
return prepare.then( function (id) {
var type = stream.type
if (stream.la_url) {
var options = {
mediaTransportType: stream.mediaTransportType,
option: {
drm: {
type: drmType,
clientId: id,
}
}
};
console.log("Options: %s", JSON.stringify(options));
var mediaOption = encodeURIComponent(JSON.stringify(options));
type += ';mediaOption=' + mediaOption;
}
console.log("open url: %s", stream.url)
console.log("type : %s", type)
var source = document.createElement("source");
source.setAttribute('src', stream.url);
source.setAttribute('type', type);
video.addEventListener('loadedmetadata', function(event) {
console.log("loadedmetadata %O", event)
});
video.addEventListener('error', function(e) {
console.error('error', e);
});
video.addEventListener('stalled', function(e) {
console.log('stalled', e);
});
video.addEventListener('loadeddata', function() {
console.log('[Device_Webos_Player] loadeddata');
});
video.addEventListener('loadedmetadata', function() {
console.log('[Device_Webos_Player] loadedmetadata');
});
video.addEventListener('canplay', function () {
console.log('[Device_Webos_Player] canplay');
});
video.addEventListener('durationchange', function() {
console.log('[Device_Webos_Player] durationchange: ' + video.duration);
});
video.addEventListener('timeupdate', function() {
console.log('[Device_Webos_Player] timeupdate: ' + video.currentTime);
}, { once: true});
video.appendChild(source);
// video.load()
video.play()
})
}
playback()
Finally the idea is [see here]
MPEG-DASH streaming is officially not supported on the webOS TV.
HLS plays AES-128 DRM only in public version
HTML5 EME/MSE can use both widevine and playready
See "Streaming Protocol & DRM Combination" here

laravel set up ckeditor/ckeditor5-export-pdf

I try to set up plugin ckeditor/ckeditor5-export-pdf on my Laravel App But I cant do this. I still get issues like: Uncaught TypeError: Failed to resolve module specifier "#ckeditor/ckeditor5-export-pdf/src/exportpdf". Relative references must start with either "/", "./", or "../".
I did all steps as in docs: https://ckeditor.com/docs/ckeditor5/latest/features/export-pdf.html#configuration But when I try use import ExportPdf from '#ckeditor/ckeditor5-export-pdf/src/exportpdf'; I get the error like above. Please help. Maybe some have stuck on this issue before
import ExportPdf from '#ckeditor/ckeditor5-export-pdf/src/exportpdf';
console.log(ExportPdf);
$(document).ready(function () {
/*function ExportPdf(editor) {
editor.execute('exportPdf');
}*/
function SimpleUploadAdapter(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = function(loader) {
return {
upload: function() {
return loader.file
.then(function (file) {
return new Promise(function(resolve, reject) {
// Init request
var xhr = new XMLHttpRequest();
xhr.open('POST', '/admin/instructions/ckmedia', true);
xhr.setRequestHeader('x-csrf-token', window._token);
xhr.setRequestHeader('Accept', 'application/json');
xhr.responseType = 'json';
// Init listeners
var genericErrorText = `Couldn't upload file: ${ file.name }.`;
xhr.addEventListener('error', function() { reject(genericErrorText) });
xhr.addEventListener('abort', function() { reject() });
xhr.addEventListener('load', function() {
var response = xhr.response;
if (!response || xhr.status !== 201) {
return reject(response && response.message ? `${genericErrorText}\n${xhr.status} ${response.message}` : `${genericErrorText}\n ${xhr.status} ${xhr.statusText}`);
}
$('form').append('<input type="hidden" name="ck-media[]" value="' + response.id + '">');
resolve({ default: response.url });
});
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
loader.uploadTotal = e.total;
loader.uploaded = e.loaded;
}
});
}
// Send request
var data = new FormData();
data.append('upload', file);
data.append('crud_id', {{ $instruction->id ?? 0 }});
xhr.send(data);
});
})
}
};
}
}
var allEditors = document.querySelectorAll('.ckeditor');
for (var i = 0; i < allEditors.length; ++i) {
ClassicEditor.create(
allEditors[i], {
extraPlugins: [SimpleUploadAdapter, /*ExportPdf*/],
/*toolbar: [
'exportPdf', '|',
],
exportPdf: {
stylesheets: [
'./path/to/fonts.css',
'EDITOR_STYLES',
'./path/to/style.css'
],
fileName: 'my-file.pdf',
converterOptions: {
format: 'A4',
margin_top: '20mm',
margin_bottom: '20mm',
margin_right: '12mm',
margin_left: '12mm',
page_orientation: 'portrait'
}
}*/
}
);
}
});
</script>```
I solved my problem with https://ckeditor.com/ckeditor-5/online-builder/ Builded what I want and setup it on my App

AWS Lambda Skill Handler returns before database Get is complete

I have written my first Lambda to handle an Alexa Skill.
My problem is that the call to the database is clearly asynchronous (I can tell from the order the Console.log messages appear in the Cloud Log.
Here is my Handler.
How do I make it so the return happens after the data is got from the database?
const RemindMeHandler = {
canHandle(handlerInput) {
const request = HandlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest'
|| (request.type === 'IntentRequest'
&& request.intent.name === 'RemindMeIntent');
},
handle(handlerInput) {
console.log('Started Reminder');
var thing="Nothinbg";
/* ========== Read dB ========== */
const params =
{
TableName: 'ItemsToRecall',
Key: {
'Slot': {S: '1'}
},
};
readDynamoItem(params, myResult=>
{
console.log('Reminder Results: ' + myResult.data);
thing="Captain";
console.log('thing 1: ' + thing);
});
console.log('Ended Reminder');
function readDynamoItem(params, callback)
{
var AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-1'});
var docClient = new AWS.DynamoDB();
console.log('Reading item from DynamoDB table');
docClient.getItem(params, function (err, data)
{
if (err) {
callback(err, data);
} else {
callback('Worked', data);
}
});
}
/* ========== Read dB End ========== */
console.log('thing 2: ' + thing);
return handlerInput.responseBuilder
.speak(REMINDER_ACKNOWLEDGE_MESSAGE + thing)
.getResponse();
}
};
/* ========== Remind Handler End ========== */
You can wrap the asynchronous and return a promise and then use async/await syntax to get the data. You can check the below. Do note it's not tested.
const RemindMeHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "LaunchRequest" ||
(handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "RemindMeIntent")
);
},
async handle(handlerInput) {
console.log("Started Reminder");
let thing = "Nothinbg";
const params = {
TableName: "ItemsToRecall",
Key: {
Slot: { S: "1" }
}
};
const data = await readDynamoItem(params);
console.log("Reminder Results: ", data);
thing = "Captain";
let speechText = thing;
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
function readDynamoItem(params) {
const AWS = require("aws-sdk");
AWS.config.update({ region: "eu-west-1" });
const docClient = new AWS.DynamoDB();
console.log("Reading item from DynamoDB table");
return new Promise((resolve, reject) => {
docClient.getItem(params, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}

AJAX POST request never completes. Data posts to server

I am sending a post request via AJAX. The data successfully posts but the AJAX call never completes. Backbone on the front; Node on the back. I am including the save function from my backbone view and the express route.
save: function(event) {
event.preventDefault();
console.log( 'You signed up for ' + this.model.get('name'));
var name = this.model.get('name');
var courseDay = this.model.get('courseDay');
var time = this.model.get('time');
var location = this.model.get('location');
jQuery.post("/test/signups", {
"name" : name,
"courseDay" : courseDay,
"time" : time,
"location" : location,
}, function (data, textStatus, jqXHR) {
console.log("Post response:");
console.dir(data);
console.log(textStatus);
console.dir(jqXHR);
});
}
Route:
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err)
return done(err);
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
console.log(err);
} else {
console.log("Successfully added" + user.signup);
}
});
}
});
});
Your server side code needs to send a response. Try something like below. Note I try to cover all cases of an error, user not found, and user found.
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err) {
return res.status(500).send(err);
}
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
return res.status(500).send(err);
}
console.log("Successfully added" + user.signup);
res.send(user);
});
} else {
res.status(404).send();
}
});
});

Resources