Determine if new inspector is the result of a popout

Add-in Express™ Support Service
That's what is more important than anything else

Determine if new inspector is the result of a popout
 
Bert Sinnema




Posts: 55
Joined: 2015-04-16
Hi Team ADX,


Thanks for releasing version 9. It works really well and feels very stable! Based on ADX 9 we are building a brand new version of our Outlook add-in. Because we had a lot of issues with state management I'm doing a lab on using the Redux pattern in an ADX add-in. So far it seems to be going really well.

Situation:
I have an ADXolFromsCollectionItem which obviously contains a form. This item is showed in the explorer and in any inspector. In my state object I have a list of inspectors with a corresponding model which I call MailState and a single property which holds a MailState object for the ADXolFromsCollectionItem instance in the explorer.


    public class ApplicationState
    {
        // State held by individual inspectors
        // 
        public Dictionary<string, MailState> MailStates { get; set; }

        // State that is held for the Explorer instance of
        // MailSecurityTopPane
        public MailState ExplorerMailState { get; set; }


        // constructor
        public ApplicationState()
        {
            MailStates = new Dictionary<string, MailState>();
        }
    }


In my ADXOlForm I use the Load event to determine if the host of the instance is an Inspector or the Explorer. Based on that I set up a subscription to the application state and update my form. For now it is simply a button that regenerates a Guid shown in a label:


        private void MailSecurityTopPane_Load(object sender, EventArgs e)
        {
            // Subscribe to application state updates
            // We put the subscription in an IDisposable so we can release the update pipe
            // Before we close the form

            // When we are dealing with inspectors
            if (CurrentInspector?.CurrentItem is Outlook.MailItem)
            {
                ConversationID = CurrentInspector.CurrentItem.GetHashCode().ToString();

                StoreSubscription = Store.Subscribe(state =>
                {
                    state.MailStates.TryGetValue(ConversationID, out MailState mailState);
                    UpdateValues(mailState);
                });
            }

            // When we are dealing with an explorer instance of the form
            // The Conversation ID comes from the ExplorerConversation state

            if (CurrentExplorer != null)
            {
                StoreSubscription = Store.Subscribe(state =>
                {
                    ConversationID = Constants.ExplorerConversation;
                    UpdateValues(state.ExplorerMailState);
                });
            }


        }


Based on Redux actions the ApplicationState changes and forms are updated. This works really well for every inspector and it also works when I do an inline response.

Challenge:
Now the challenge is as follows: When I am in an inline response and I do a pop-out. I need find out that the new Inspector that is created is actually created by a pop-out so I can copy the state that was set in the explorer to the state of the new inspector.


        private void outlookAppEvents_NewInspector(object sender, object inspector, string folderName)
        {
            var insp = inspector as Outlook.Inspector;
           
            // TODO: Determine if this new inspector is the result of a popout or not
            // so we can decide to add a new viewmodel for the MailSecurityTopPane
            // or if we need to copy the viewmodel used in the Explorer instance of MailSecurityTopPane
            if (insp.CurrentItem is Outlook.MailItem)
            {
                OutlookItemEvents.ConnectTo(insp.CurrentItem, true);
                
                Store.Dispatch(new InspectorActivatedAction() { ItemId = insp.CurrentItem.GetHashCode().ToString() });
            }

        }


My Question:
Is there a best practice to determine if a new Inspector is the result of a popout? And is outlookAppEvents_NewInspector the best place to do this?

*Since this is a Lab project I could easily share my code if required.

Thanks!
Posted 22 May, 2018 04:46:59 Top
Andrei Smolin


Add-in Express team


Posts: 15284
Joined: 2006-05-11
Hello Bert,

There's no such way. I see two variants:
- a quick and dirty approach: add a UserProperty to the mail item to identify it
- a thorough search for a supposed difference in the flow of events/property values that show itself if you pop out an inline response or open an inspector by double-clicking an email or by pressing Ctrl+N (or similar shortcuts).

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 22 May, 2018 06:00:20 Top
Bert Sinnema




Posts: 55
Joined: 2015-04-16
Hi Andrei,

There are so many use cases for this. Hopefully someday the Outlook API will support this.

This quick and dirty way works pretty well, not saying I'd recommend it for any developer but for my use case it works:


        // Whenever we have an inline response
        private void outlookAppEvents_ExplorerInlineResponse(object sender, object itemObject)
        {
            if (itemObject is Outlook.MailItem)
            {
                //Get the mail item
                var item = itemObject as Outlook.MailItem;
                
                // add a userprop without saving it to keep things clean
                // the userprop is still there when we catch the MailItem in New_Inspector
                var prop = item.UserProperties.Add("InlineResponded", Outlook.OlUserPropertyType.olNumber, false);
                prop.Value = 1;


                Marshal.ReleaseComObject(item);
            }
        }




        private void outlookAppEvents_NewInspector(object sender, object inspector, string folderName)
        {
            var insp = inspector as Outlook.Inspector;
           

            if (insp.CurrentItem is Outlook.MailItem)
            {

                //try to find prop
                var item = insp.CurrentItem as Outlook.MailItem;

                if ( item.UserProperties["InlineResponded"] != null )
                {
                    // New inspector is based on a MailItem that comes
                    // from an inline response
                    
                    // remove the property as we don't need it anymore
                    item.UserProperties["InlineResponded"].Delete();
                }
                else
                {
                    // The new Inspector does not come from a popout

                }


                Marshal.ReleaseComObject(item);
            }

        }


Do you have any concerns I need to consider with this approach?

Thanks
Posted 22 May, 2018 09:06:33 Top
Andrei Smolin


Add-in Express team


Posts: 15284
Joined: 2006-05-11
Hello Bert,

Your code produces a number of unreleased COM objects. Every item.UserProperties, UserProperties.Add() and UserProperties[index] call produces a separate COM object. You should also foresee the scenario in which the user property exists when the ExplorerInlineResponse event occurs.

You should also delete the user property when you send the email.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 22 May, 2018 09:51:46 Top
Bert Sinnema




Posts: 55
Joined: 2015-04-16
Hi Andrei,

Ah, so even if I don't put certain objects in variables COM objects are unreleased. I always thought when nog cast to an interface or put into a variable it's there is nothing to release.

Thanks so much!
Posted 22 May, 2018 10:03:09 Top
Andrei Smolin


Add-in Express team


Posts: 15284
Joined: 2006-05-11
Welcome!

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 22 May, 2018 10:05:28 Top