Coder Social home page Coder Social logo

Comments (16)

rbays avatar rbays commented on August 10, 2024 1

Hi @Swathy-Mothilal I have invited you as a collaborator to the private repo, is there anyone else I need to add too?

from office-js.

kumarshrey-msft avatar kumarshrey-msft commented on August 10, 2024 1

@rbays Thanks for reporting this issue, we have been able to reproduce it and it has been put on our backlog. We unfortunately have no timelines to share at this point.

Internal tracking id: Office: [4694943]

from office-js.

isabela-dominguez avatar isabela-dominguez commented on August 10, 2024

Thank you for sharing this issue @rbays! Connecting you @exextoc with who may be able to help.

from office-js.

Swathy-Mothilal avatar Swathy-Mothilal commented on August 10, 2024

@rbays We are unable to repro the issue locally. Can you please host your repro video and the har logs to a private repo, and grant permission to access it?

from office-js.

Swathy-Mothilal avatar Swathy-Mothilal commented on August 10, 2024

@rbays Thanks for sharing the repo. Could you please provide a video demonstrating the issue and logs? We need to understand the flow to be able to reproduce it.

from office-js.

Swathy-Mothilal avatar Swathy-Mothilal commented on August 10, 2024

@rbays Please provide a working manifest link also where you are able to repro the issue.

from office-js.

rbays avatar rbays commented on August 10, 2024

Hi, I don't have a manifest available to share, but I believe I have managed to isolate the issue. The below code will cause the issue on New Outlook for windows (there is no issue on old outlook or web)

the processMessageComposeEvent event is in the manifest as a launch event as follows
<LaunchEvent FunctionName="processMessageComposeEvent" Type="OnNewMessageCompose"/>

Office.initialize = () => { };

type MailboxItem = Office.Item & Office.ItemCompose & Office.ItemRead &
Office.Message & Office.MessageCompose & Office.MessageRead &
Office.Appointment & Office.AppointmentCompose & Office.AppointmentRead;
function getContext() : Office.Context {
	if (Office.context) {
		return Office.context;
	}
	throw new Error();
}
function getMailbox() : Office.Mailbox {
	const result = getContext().mailbox;
	if (result) {
		return Office.context.mailbox;
	}
	throw new Error();
}

function getMailboxItem() : MailboxItem {
	const result = getMailbox().item;
	if (result) {
		return result;
	}
	throw new Error();
}
async function saveCustomProperties(customProps: Office.CustomProperties) : Promise<void> {
	return new Promise((resolve, reject) => {
		customProps.saveAsync((asyncResult) => {
			if (asyncResult.status === Office.AsyncResultStatus.Failed) {
				reject(asyncResult.error);
			} else {
				resolve();
			}
		});
	});
}
function getItemCustomPropertiesAsync(): Promise<Office.CustomProperties> {
	return new Promise((resolve, reject) => {
		getMailboxItem().loadCustomPropertiesAsync((asyncResult) => {
			if (asyncResult.status === Office.AsyncResultStatus.Failed) {
				reject(asyncResult.error);
			} else {
				resolve(asyncResult.value);
			}
		});
	});
}
async function setItemCustomPropertyAsync(key: string, value: string): Promise<void> {
	const customProps = await getItemCustomPropertiesAsync();
	customProps.set(key, value);

	return saveCustomProperties(customProps);
}

async function processMessageComposeEvent(): Promise<void> {
	let x = 0;
	const intervalID = setInterval(() => {
		x += 1;
		if (x >= 40) {
			window.clearInterval(intervalID);
		} else {
			setItemCustomPropertyAsync('test_key_iterator', x.toString());
		}
	}, 500);
}

export default processMessageComposeEvent;

The issue seems to be some kind of race condition between customProps.SaveAsync and whatever is happening with the attachment being saved in office.

The code above just calls that method every half a second for the first 20 seconds when you start composing a new email.

By opening a new email, and then attaching some small attachments withing the first 5-10 seconds of having the message open I have been able to consistently reproduce the issue.

Please let me know if you need any more help to replicate the issue

from office-js.

Swathy-Mothilal avatar Swathy-Mothilal commented on August 10, 2024

@rbays , Thanks for sharing the code snippet. In your code, the processMessageComposeEvent function sets custom properties in a loop with a 500ms interval. If the attachments are being saved at the same time, there might be a conflict or timing issue that causes the attachments not to be removed properly. To avoid this race condition, could you please wait for Attachments to be Saved. Ensure that the attachments are fully saved before starting the custom property setting operations.

Here is a code snippet, that can help you.
async function waitForAttachmentsToBeSaved(): Promise {
return new Promise((resolve) => {
const checkAttachments = () => {
const attachments = getMailboxItem().attachments;
if (attachments.every(attachment => attachment.isInline || attachment.isSaved)) {
resolve();
} else {
setTimeout(checkAttachments, 100);
}
};
checkAttachments();
});
}

Please let me know if you have any queries.

from office-js.

rbays avatar rbays commented on August 10, 2024

Hi @Swathy-Mothilal ,

I don't have the isSaved property available to me, I have upgraded the package https://www.npmjs.com/package/@types/office-js to 1.0.401 (which is currently the latest) and only have the following props available on the AttachmentDetails interface that is returned.

image

Could you please advise if I should be using a different package to access this property?

Further, even if this does fix my issue, I believe that this will cause issues for others in the future, this is only an issue on New outlook (not OWA or old outlook) and means that every time someone saves a custom prop, they run the risk of breaking attachments. My example runs on a loop to ensure I can recreate the issue consistently, but when I initially encountered the issue, it was happening sporadically during the normal course of usage. As such I believe that this is a bug that should be fixed by the office-JS team

from office-js.

rkpathak avatar rkpathak commented on August 10, 2024

@rbays Few observations for your handler function in the code that you shared.

  1. event.completed() is not being called in the handler, without that function will not work properly.
  2. The handler code is returning a promise that platform can't wait for. The handler function should follow the rules mentioned at https://learn.microsoft.com/en-us/office/dev/add-ins/outlook/autolaunch#event-based-activation-behavior-and-limitations

Can you create a repro script in script lab, to help repro this.

from office-js.

rbays avatar rbays commented on August 10, 2024

Hi @rkpathak ,

  1. I have amended the process event to call the event.completed method below, though it doesn't make a difference and still has issues in the same way
  2. I cannot see anything relevant in the section you linked, but do you mean that the function should not be asynchronous?
async function processMessageComposeEvent(event: any): Promise<void> {
	let x = 0;
	const intervalID = setInterval(() => {
		x += 1;
		if (x >= 40) {
			window.clearInterval(intervalID);
		} else {
			setItemCustomPropertyAsync('test_key_iterator', x.toString());
			if (x === 39) {
				event.completed();
			}
		}
	}, 500);
}

from office-js.

rkpathak avatar rkpathak commented on August 10, 2024

@rbays Can you create a repro script in script lab and share the link, to help repro this.

from office-js.

rbays avatar rbays commented on August 10, 2024

@rkpathak I have created a script in script lab, however I have not been able to repro the issue this way because as far as I can tell, script lab does not run on new outlook.

I took an existing template and replaced the main function with the exact code from the example that I provided earlier.

I hope this helps.

Here are the segments of the script:

Script

$("#wreck-it").on("click", processMessageComposeEvent);

type MailboxItem = Office.Item &
  Office.ItemCompose &
  Office.ItemRead &
  Office.Message &
  Office.MessageCompose &
  Office.MessageRead &
  Office.Appointment &
  Office.AppointmentCompose &
  Office.AppointmentRead;

function getContext(): Office.Context {
  if (Office.context) {
    return Office.context;
  }
  throw new Error();
}
function getMailbox(): Office.Mailbox {
  const result = getContext().mailbox;
  if (result) {
    return Office.context.mailbox;
  }
  throw new Error();
}

function getMailboxItem(): MailboxItem {
  const result = getMailbox().item;
  if (result) {
    return result;
  }
  throw new Error();
}
async function saveCustomProperties(customProps: Office.CustomProperties): Promise<void> {
  return new Promise((resolve, reject) => {
    customProps.saveAsync((asyncResult) => {
      if (asyncResult.status === Office.AsyncResultStatus.Failed) {
        reject(asyncResult.error);
      } else {
        resolve();
      }
    });
  });
}
function getItemCustomPropertiesAsync(): Promise<Office.CustomProperties> {
  return new Promise((resolve, reject) => {
    getMailboxItem().loadCustomPropertiesAsync((asyncResult) => {
      if (asyncResult.status === Office.AsyncResultStatus.Failed) {
        reject(asyncResult.error);
      } else {
        resolve(asyncResult.value);
      }
    });
  });
}
async function setItemCustomPropertyAsync(key: string, value: string): Promise<void> {
  const customProps = await getItemCustomPropertiesAsync();
  customProps.set(key, value);

  return saveCustomProperties(customProps);
}

async function processMessageComposeEvent(): Promise<void> {
  let x = 0;
  const intervalID = setInterval(() => {
    x += 1;
    if (x >= 40) {
      window.clearInterval(intervalID);
    } else {
      setItemCustomPropertyAsync("test_key_iterator", x.toString());
      console.log(x);
    }
  }, 500);
}

HTML

<section class="ms-font-m">
	<p class="ms-font-m">This sample saves custom props a bunch to try to break attachments</p>
	<p><b>Required mode</b>: Compose</p>
</section>

<section class="samples ms-font-m">
	<h3>Try it out</h3>
	<ol>
		<li>click the button</li>
		<br>
		<li>add some attachments within 20 seconds</li>
		<br>
		<li>watch them break</li>
	</ol>
	<div class="ms-TextField">

		<button id="wreck-it" class="ms-Button">
        <span class="ms-Button-label">I'm gonna wreck it!</span>
    </button>
</section>

CSS

section.samples {
    margin-top: 20px;
}

section.samples .ms-Button, section.setup .ms-Button {
    display: block;
    margin-bottom: 5px;
    margin-left: 20px;
    min-width: 80px;
}

Libraries

https://appsforoffice.microsoft.com/lib/1/hosted/office.js
@types/office-js

[email protected]/dist/css/fabric.min.css
[email protected]/dist/css/fabric.components.min.css

[email protected]/client/core.min.js
@types/core-js

[email protected]
@types/[email protected]

from office-js.

rbays avatar rbays commented on August 10, 2024

@rkpathak is there any update or timeline on this?

from office-js.

kumarshrey-msft avatar kumarshrey-msft commented on August 10, 2024

Hi @rbays, apologies for the delay. I was able to reproduce this issue on the New Outlook, however as you mentioned this is very intermittent. Can you briefly elaborate the use case you are trying to address? If your add-in depending on attachments being saved or removed so that you can subsequently save the custom properties, you can consider listening to the OnMessageAttachmentsChanged event instead of doing so after intervals of 500ms?

from office-js.

rbays avatar rbays commented on August 10, 2024

Hi @kumarshrey-msft, the example I gave here isn't my actual use case, it's an example I created to help to hit the problem with more consistency to help you debug the problem.

In our actual usage we are storing a custom property on the message customProps when the user clicks a button in our taskpane to signify how the message should be processed on send, and also we are saving another custom prop during the messagecompose event to keep reference to the message.

The problem we have is that if the user happens to add an attachment to the email close to either of these events happening, there is a chance of the attachments breaking, which our QA team found, and managed to replicate about 1/10 times when trying.

As far as I can tell at the moment in new outlook, if you ever want to save message customProps, and the user wants to add an attachment, there is a chance that these 2 actions will clash and break the attachments for the user.

from office-js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.