Outlook Web App add in Dialog Api messageParent not working - outlook-addin

I am developing a Outlook add in and was checking out the authentication flow (Microsoft login) for my app. I tried using the dialog api to achieve this but was not able to pass message from the dialog to the task pane after successful sign in.
index.js:
var fullUrl = 'https://localhost:3000/src/templates/auth.html'
Office.context.ui.displayDialogAsync(fullUrl,
{height: 40, width: 40}, function (result) {
console.log("Dialog has initialized. Wiring up events");
_dlg = result.value;
console.log(result.status);
_dlg.addEventHandler(Office.EventType.DialogMessageReceived, function(responseMessage){ console.log(responseMessage);});
});
Dialog box:
Office.initialize = function (reason) {
$(document).ready(function () {
Office.context.ui.messageParent("Message 1");
}
}
In the dialog console I get this,
outlook-web-16.01.debug.js:4587 Failed to execute 'postMessage' on
'DOMWindow': The target origin provided ('https://outlook.live.com')
does not match the recipient window's origin
('https://localhost:3000').
Any idea what could be the problem?

Related

Can I use Firebase's signinWithRedirect within the dialog API of a MS Powerpoint Add-In on Safari?

I'm developing authentication with firebase for a add-in for MS Powerpoint. In order to add authentication with Google I created a button which opens a dialog box:
`function openGoogleAuthDialog() {
Office.context.ui.displayDialogAsync(hostURLofDialogComponent,
{ width: 50, height: 50 }, (result) => {
if (result.status === Office.AsyncResultStatus.Succeeded) {
dialog = result.value;
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
} else {
console.log("Unable to open dialog box");
}
});
}`
The dialog opens successfully. Within the Dialog component i have another button that should redirect to google as well as a useEffect that is supposed to send back the result of the authentication to the parent.
`export function AuthDialog() {
const authFirebase = getAuth(firebaseApp);
const handleAuth = () => {
const provider = new GoogleAuthProvider();
signInWithRedirect(authFirebase, provider);
};
useEffect(() => {
getRedirectResult(authFirebase).then((result) => {
Office.context.ui.messageParent(JSON.stringify(result));
});
}, []);
return <button onClick={handleAuth}>Authenticate With Google</button>;
}`
The problem is, that if I click on the button it will leave the page and it seems like it's gonna redirect but then stops and comes back to the dialog component without showing me the google sign-in interface.
I tried this functionality within google chrome and brave browser and it shows the Google Sign-In Interface as expected. As MS Office Plugins are using Safari under the hood, and the functionality was behaving in the same faulty way in the Safari browser, I can imagine it's a problem with Safari. Has anyone experienced a similar issue? Your help would be much appreciated!

Catch FCM notification message in service worker after click_action triggered

The issue, I am facing with notification messages is, that a new tab is opened, whenever the complete URL of the defined click_action is not matching any opened tab.
Assuming click_action equals mydomain.com and there is an opened tab with the URL mydomain.com/anyroute. A new tab is opened, because the URLs do not match. But I would like the already opened tab to be focused instead of opening a new tab.
Can a notification message be catched by the service worker after a user clicks on the message or is there any other possibility?
EDIT: So far, the service worker's events like onBackgroundMessage or notificationclickare not passed, since the push notification is if type notification_message.
You can use the on like explained here.
messaging.onBackgroundMessage((payload) => {
console.log(
"[firebase-messaging-sw.js] Received background message ",
payload
);
// Customize notification here
const notificationTitle = "Background Message Title";
const notificationOptions = {
body: "Background Message body.",
icon: "/firebase-logo.png",
};
// Loop trough all clients controled by the SW
self.clients.matchAll(options).then(function (clients) {
// Let's see if we already have a chat window open:
const url = new URL(client.url);
if (url.pathname == "/custom_url/") {
// Excellent, let's use it!
client.focus();
}
// do something with your clients list
});
self.registration.showNotification(notificationTitle, notificationOptions);
});
Where you can use self.clients to loop trough all tabs/clients of your app that are controled by the SW. You can focus to a specfic client if the url/patch matches.

Office.context.mailbox.addHandlerAsync fails when reload the frame

I am implementing the pinnable taskpane in my outlook web add-in
This is my code:
Office.initialize = function (reason) {
$(document).ready(function () {
// Listen to ItemChanged event
Office.context.mailbox.addHandlerAsync(Office.EventType.ItemChanged, itemChanged, function (result) {
console.log(result)
if (result.status === Office.AsyncResultStatus.Failed) {
// here will be hit if I do a postback in the server, could also be replicated by choosing "reload frame" in the right click menu
{name: "Internal Error", message: "An internal error has occurred.", code: 5001}
}
});
gatherMailItemInfo();
});
}
Everything works fine( gatherMailItemInfo get calls when I switching between items. But as long as a do a post to the server ( can simply replicated by choosing "reload frame" in the right click menu) the handler will fail.
I am using office 365 for testing. Windows desktop client has no such issues.

Service Worker - Wait for clients.openWindow to complete before postMessage

I am using service worker to handle background notifications. When I receive a message, I'm creating a new Notification using self.registration.showNotification(title, { icon, body }). I'm watching for the click event on the notification using self.addEventListener('notificationclick', ()=>{}). On click I'm checking to see if any WindowClient is open, if it is, I'm getting one of those window clients and calling postMessage on it to send the data from the notification to the app to allow the app to process the notification. Incase there is no open window I'm calling openWindow and once that completes I'm sending the data to that window using postMessage.
event.waitUntil(
clients.matchAll({ type: 'window' }).then((windows) => {
if (windows.length > 0) {
const window = windows[0];
window.postMessage(_data);
window.focus();
return;
}
return clients.openWindow(this.origin).then((window) => {
window.postMessage(_data);
return;
});
})
);
The issue I am facing is that the postMessage call inside the openWindow is never delivered. I'm guessing this is because the postMessage call on the WindowClient happens before the page has finished loading, so the eventListener is not registered to listen for that message yet? Is that right?
How do I open a new window from the service worker and postMessage to that new window.
I stumble this issue as well, using timeout is anti pattern and also might cause delay larger then the 10 seconds limit of chrome that could fail.
what I did was checking if I need to open a new client window.
If I didn't find any match in the clients array - which this is the bottle neck, you need to wait until the page is loaded, and this can take time and postMessage will just not work.
For that case I created in the service worker a simple global object that is being populated in that specific case for example:
const messages = {};
....
// we need to open new window
messages[randomId] = pushData.message; // save the message from the push notification
await clients.openWindow(urlToOpen + '#push=' + randomId);
....
In the page that is loaded, in my case React app, I wait that my component is mounted, then I run a function that check if the URL includes a '#push=XXX' hash, extracting the random ID, then messaging back to the service worker to send us the message.
...
if (self.location.hash.contains('#push=')) {
if ('serviceWorker' in navigator && 'Notification' in window && Notification.permission === 'granted') {
const randomId = self.locaiton.hash.split('=')[1];
const swInstance = await navigator.serviceWorker.ready;
if (swInstance) {
swInstance.active.postMessage({type: 'getPushMessage', id: randomId});
}
// TODO: change URL to be without the `#push=` hash ..
}
Then finally in the service worker we add a message event listener:
self.addEventListener('message', function handler(event) {
if (event.data.type === 'getPushMessage') {
if (event.data.id && messages[event.data.id]) {
// FINALLY post message will work since page is loaded
event.source.postMessage({
type: 'clipboard',
msg: messages[event.data.id],
});
delete messages[event.data.id];
}
}
});
messages our "global" is not persistent which is good, since we just need this when the service worker is "awaken" when a push notification arrives.
The presented code is pseudo code, to point is to explain the idea, which worked for me.
clients.openWindow(event.data.url).then(function(windowClient) {
// do something with the windowClient.
});
I encountered the same problem. My error was that I registered event handler on the window. But it should be registered on service worker like this:
// next line doesn't work
window.addEventListener("message", event => { /* handler */ });
// this one works
navigator.serviceWorker.addEventListener('message', event => { /* handler */ });
See examples at these pages:
https://developer.mozilla.org/en-US/docs/Web/API/Clients
https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage
UPD: to clarify, this code goes into the freshly opened window. Checked in Chromium v.66.

titanium appcelerator cloudpush tray notification not showing

Iam developing an application that uses push notifications.
Iam using ti.cloudpush module 3.2X and titanium sdk 3.2X
When i tries to recieve notification it deos not showing on tray.
I can read message inside application but it is not creating on notification tray.
here is my sample code
var CloudPush = require('ti.cloudpush');
CloudPush.enabled = true;
CloudPush.showTrayNotificationsWhenFocused = true;
CloudPush.showTrayNotification = true;
CloudPush.focusAppOnPush = false;
CloudPush.retrieveDeviceToken({
success : function deviceTokenSuccess(e) {
alert('Device Token: ' + e.deviceToken);
deviceToken = e.deviceToken;
},
error : function deviceTokenError(e) {
alert('Failed to register for push! ' + e.error);
}
});
CloudPush.addEventListener('callback', function(evt) {
alert(evt.payload);
//alert(JSON.stringify(evt.payload));
});
CloudPush.addEventListener('trayClickLaunchedApp', function(evt) {
Ti.API.info('Tray Click Launched App (app was not running)');
});
CloudPush.addEventListener('trayClickFocusedApp', function(evt) {
Ti.API.info('Tray Click Focused App (app was already running)');
});
Thanks in advance
Assuming you have set up the PushNotifications.subscribe correctly the default properties of this module are used until you set a property for the first time.
Because the properties are persisted to the device settings (via Titanium.App.Properties), the most recent value you set will always be used.
Do a Build > Clean to make sure you have not overwritten one of these properties by accident.
Then double check what they are set to with quick logging check -
Ti.API.log(Ti.App.Properties.getString('oneofthecloudproperties');
You should then be able to see if it's an issue with the subscribe event or how you have set the push notification properties.