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.
Related
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!
I use Browserstack to do the E2E testing, now I met a problem when I try to run the mobile automate script in safari on Browserstack, there will have a pop-up dialogue show when I click a button which will result in opening a new tab, the dialogue show message like this: 'this site is attempting to open a popup window', I must close it and the script can continue executing.
Now the problem is:
1. When I click the button which will trigger this pop-up dialogue, there will always show an exception in the log: 'Error while running .clickElement() protocol action: Appium error: An unknown server-side error occurred while processing the command. Original error: Did not get any response after 20s'.
2. I can use the XPath to locate the button on the pop-up dialogue and click it to close the dialogue, but it takes serval minutes, is there another way to do this operation more efficient?
const { client } = require('nightwatch-api')
const { Given, Then, When} = require('cucumber')
Given('open mobile 163 news', async function () {
await client.url('https://3g.163.com/news/article/EJN99AOF000189FH.html?clickfrom=index2018_news_newslist#offset=0')
})
When('choose share by QQ', async function () {
await client.waitForElementVisible('.sharelogo')
await client.click('.sharelogo')
})
Then('the popup should show', async function () {
await client.waitForElementVisible('.qzone')
await client.click('.qzone')
await client.setContext('NATIVE_APP')
await client.source(function(res){
console.log(res.value)
})
await client.useXpath()
await client.click('//*[#name="Allow"]')
await client.contexts(function(result) {
client.setContext(result.value[result.value.length - 1])
client.useCss()
})
})
Have you tried adding the capability 'nativeWebTap' and setting it to the value 'true' in the test scripts?
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?
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.
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.