OUT-527: Implement Last used folder and update its items if used OUT-497
authorThomas
Fri, 07 Dec 2018 12:58:32 +0100
branchOUT-497
changeset 2492d584f9a38d31
parent 2491 6caad4507bc1
child 2493 3d8606f06546
OUT-527: Implement Last used folder and update its items if used
Extensions/FolderExtensions.cs
PEPIdentity.cs
Properties/Resources.Designer.cs
Properties/Resources.de.resx
Properties/Resources.es.resx
Properties/Resources.resx
Wrappers/WatchedExplorer.cs
pEpForOutlook.csproj
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Extensions/FolderExtensions.cs	Fri Dec 07 12:58:32 2018 +0100
     1.3 @@ -0,0 +1,62 @@
     1.4 +using System;
     1.5 +using Outlook = Microsoft.Office.Interop.Outlook;
     1.6 +
     1.7 +
     1.8 +namespace pEp.Extensions
     1.9 +{
    1.10 +    internal static class FolderExtensions
    1.11 +    {
    1.12 +        /// <summary>
    1.13 +        /// Gets the Last Used folder. Creates it if it doesn't exist.
    1.14 +        /// </summary>
    1.15 +        /// <returns>The Last Used folder or null if an error occured.</returns>
    1.16 +        public static Outlook.Folder GetLastUsedFolder()
    1.17 +        {
    1.18 +            Outlook.Application application = null;
    1.19 +            Outlook.Folder defaultFolder = null;
    1.20 +            Outlook.Folder lastUsed = null;
    1.21 +            Outlook.Folders folders = null;
    1.22 +            Outlook.NameSpace session = null;
    1.23 +
    1.24 +            try
    1.25 +            {
    1.26 +                // Get default folder folders
    1.27 +                application = Globals.ThisAddIn.Application;
    1.28 +                session = application.Session;
    1.29 +                defaultFolder = session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts) as Outlook.Folder;
    1.30 +                folders = defaultFolder.Folders;
    1.31 +
    1.32 +                // Try to get Last Used folder
    1.33 +                try
    1.34 +                {
    1.35 +                    lastUsed = folders[Properties.Resources.LastUsedFolderName] as Outlook.Folder;
    1.36 +                }
    1.37 +                catch (Exception ex)
    1.38 +                {
    1.39 +                    Log.Warning("GetlastUsedFolder: Error getting Last Used list. " + ex.ToString());
    1.40 +                    lastUsed = null;
    1.41 +                }
    1.42 +
    1.43 +                // If folder doesn't exist, create it
    1.44 +                if (lastUsed == null)
    1.45 +                {
    1.46 +                    lastUsed = folders.Add(Properties.Resources.LastUsedFolderName, Outlook.OlDefaultFolders.olFolderContacts) as Outlook.Folder;
    1.47 +                }
    1.48 +            }
    1.49 +            catch (Exception ex)
    1.50 +            {
    1.51 +                Log.Error("GetlastUsedFolder: Error getting Last Used list. " + ex.ToString());
    1.52 +                lastUsed = null;
    1.53 +            }
    1.54 +            finally
    1.55 +            {
    1.56 +                application = null;
    1.57 +                defaultFolder = null;
    1.58 +                folders = null;
    1.59 +                session = null;
    1.60 +            }
    1.61 +
    1.62 +            return lastUsed;
    1.63 +        }
    1.64 +    }
    1.65 +}
     2.1 --- a/PEPIdentity.cs	Fri Nov 30 16:28:52 2018 +0100
     2.2 +++ b/PEPIdentity.cs	Fri Dec 07 12:58:32 2018 +0100
     2.3 @@ -1,4 +1,5 @@
     2.4 -using pEpCOMServerAdapterLib;
     2.5 +using pEp.Extensions;
     2.6 +using pEpCOMServerAdapterLib;
     2.7  using System;
     2.8  using System.Collections.Generic;
     2.9  using System.ComponentModel;
    2.10 @@ -1619,12 +1620,8 @@
    2.11          /// <returns>The created contact or null if an error occured.</returns>
    2.12          private static Outlook.ContactItem CreateContact(string address, string userName, string addressType = null)
    2.13          {
    2.14 -            Outlook.Application application = null;
    2.15              Outlook.ContactItem contact = null;
    2.16 -            Outlook.Folder defaultFolder = null;
    2.17 -            Outlook.Folder lastContacted = null;
    2.18 -            Outlook.Folders folders = null;
    2.19 -            Outlook.NameSpace session = null;
    2.20 +            Outlook.Folder lastUsed = null;
    2.21  
    2.22              // Doublecheck if contact already exists
    2.23              contact = PEPIdentity.GetContact(address);
    2.24 @@ -1636,35 +1633,18 @@
    2.25              {
    2.26                  try
    2.27                  {
    2.28 -                    application = Globals.ThisAddIn.Application;
    2.29 -                    session = application.Session;
    2.30 -                    defaultFolder = session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts) as Outlook.Folder;
    2.31 -                    folders = defaultFolder.Folders;
    2.32 +                    lastUsed = FolderExtensions.GetLastUsedFolder();
    2.33  
    2.34 -                    // Get Last Contacted folder
    2.35 -                    try
    2.36 +                    if (lastUsed != null)
    2.37                      {
    2.38 -                        lastContacted = folders[Properties.Resources.LastContactedFolderName] as Outlook.Folder;
    2.39 +                        // Create contact and move it to Last Used folder
    2.40 +                        contact = Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olContactItem);
    2.41 +                        contact.Email1Address = address;
    2.42 +                        contact.FullName = userName;
    2.43 +                        contact.Email1AddressType = addressType;
    2.44 +                        contact.Save();
    2.45 +                        contact.Move(lastUsed);
    2.46                      }
    2.47 -                    catch (Exception ex)
    2.48 -                    {
    2.49 -                        Log.Warning("CreateContact: Error getting last contacted list. " + ex.ToString());
    2.50 -                        lastContacted = null;
    2.51 -                    }
    2.52 -
    2.53 -                    // If folder doesn't exist, create it
    2.54 -                    if (lastContacted == null)
    2.55 -                    {
    2.56 -                        lastContacted = folders.Add(Properties.Resources.LastContactedFolderName, Outlook.OlDefaultFolders.olFolderContacts) as Outlook.Folder;
    2.57 -                    }
    2.58 -
    2.59 -                    // Create contact and move it to Last Contacted folder
    2.60 -                    contact = application.CreateItem(Outlook.OlItemType.olContactItem);
    2.61 -                    contact.Email1Address = address;
    2.62 -                    contact.FullName = userName;
    2.63 -                    contact.Email1AddressType = addressType;
    2.64 -                    contact.Save();
    2.65 -                    contact.Move(lastContacted);
    2.66                  }
    2.67                  catch (Exception ex)
    2.68                  {
    2.69 @@ -1672,13 +1652,9 @@
    2.70                      Log.Error("CreateContact: Error creating contact. " + ex.ToString());
    2.71                  }
    2.72                  finally
    2.73 -                {
    2.74 -                    application = null;
    2.75 +                {                    
    2.76                      contact = null;
    2.77 -                    defaultFolder = null;
    2.78 -                    lastContacted = null;
    2.79 -                    folders = null;
    2.80 -                    session = null;
    2.81 +                    lastUsed = null;                    
    2.82                  }
    2.83              }
    2.84  
    2.85 @@ -1756,7 +1732,7 @@
    2.86              Outlook.NameSpace session = null;
    2.87              Outlook.Folder defaultFolder = null;
    2.88              Outlook.Folders folders = null;
    2.89 -            Outlook.Folder lastContactedFolder = null;
    2.90 +            Outlook.Folder lastUsedFolder = null;
    2.91  
    2.92              try
    2.93              {
    2.94 @@ -1768,22 +1744,33 @@
    2.95                  // Search in default folder
    2.96                  contact = PEPIdentity.GetContact(defaultFolder, address);
    2.97  
    2.98 -                // If not found in default folder, search in Last Contacted folder
    2.99 +                // If not found in default folder, search in Last Used folder
   2.100                  if (contact == null)
   2.101                  {
   2.102                      folders = defaultFolder.Folders;
   2.103  
   2.104                      try
   2.105                      {
   2.106 -                        // Get Last Contacted folder
   2.107 -                        lastContactedFolder = folders[Properties.Resources.LastContactedFolderName] as Outlook.Folder;
   2.108 +                        // Get Last Used folder
   2.109 +                        lastUsedFolder = folders[Properties.Resources.LastUsedFolderName] as Outlook.Folder;
   2.110  
   2.111 -                        // Try to get contact from Last Contacted folder
   2.112 -                        contact = PEPIdentity.GetContact(lastContactedFolder, address);
   2.113 +                        // Try to get contact from Last Used folder
   2.114 +                        contact = PEPIdentity.GetContact(lastUsedFolder, address);
   2.115 +
   2.116 +                        // If contact is already there, update its "Last Modified" value
   2.117 +                        if (contact != null)
   2.118 +                        {
   2.119 +                            // Another workaround...
   2.120 +                            string yomiCompanyName = contact.YomiCompanyName;
   2.121 +                            contact.YomiCompanyName = "123";
   2.122 +                            contact.Save();
   2.123 +                            contact.YomiCompanyName = yomiCompanyName;
   2.124 +                            contact.Save();
   2.125 +                        }
   2.126                      }
   2.127                      catch (Exception ex)
   2.128                      {
   2.129 -                        Log.Warning("CreateContact: Error getting last contacted list. " + ex.ToString());
   2.130 +                        Log.Warning("CreateContact: Error getting Last Used list. " + ex.ToString());
   2.131                      }
   2.132                  }
   2.133              }
   2.134 @@ -1798,7 +1785,7 @@
   2.135                  session = null;
   2.136                  defaultFolder = null;
   2.137                  folders = null;
   2.138 -                lastContactedFolder = null;
   2.139 +                lastUsedFolder = null;
   2.140              }
   2.141  
   2.142              return contact;
     3.1 --- a/Properties/Resources.Designer.cs	Fri Nov 30 16:28:52 2018 +0100
     3.2 +++ b/Properties/Resources.Designer.cs	Fri Dec 07 12:58:32 2018 +0100
     3.3 @@ -1177,11 +1177,11 @@
     3.4          }
     3.5          
     3.6          /// <summary>
     3.7 -        ///   Looks up a localized string similar to Last contacted.
     3.8 +        ///   Looks up a localized string similar to Last Used.
     3.9          /// </summary>
    3.10 -        public static string LastContactedFolderName {
    3.11 +        public static string LastUsedFolderName {
    3.12              get {
    3.13 -                return ResourceManager.GetString("LastContactedFolderName", resourceCulture);
    3.14 +                return ResourceManager.GetString("LastUsedFolderName", resourceCulture);
    3.15              }
    3.16          }
    3.17          
     4.1 --- a/Properties/Resources.de.resx	Fri Nov 30 16:28:52 2018 +0100
     4.2 +++ b/Properties/Resources.de.resx	Fri Dec 07 12:58:32 2018 +0100
     4.3 @@ -828,7 +828,7 @@
     4.4    <data name="Options_HideInternalMessagesText" xml:space="preserve">
     4.5      <value>Interne Nachrichten verbergen</value>
     4.6    </data>
     4.7 -  <data name="LastContactedFolderName" xml:space="preserve">
     4.8 -    <value>Zuletzt kontaktiert</value>
     4.9 +  <data name="LastUsedFolderName" xml:space="preserve">
    4.10 +    <value>Zuletzt verwendet</value>
    4.11    </data>
    4.12  </root>
    4.13 \ No newline at end of file
     5.1 --- a/Properties/Resources.es.resx	Fri Nov 30 16:28:52 2018 +0100
     5.2 +++ b/Properties/Resources.es.resx	Fri Dec 07 12:58:32 2018 +0100
     5.3 @@ -828,7 +828,7 @@
     5.4    <data name="Options_HideInternalMessagesText" xml:space="preserve">
     5.5      <value>Esconder mensajes internos</value>
     5.6    </data>
     5.7 -  <data name="LastContactedFolderName" xml:space="preserve">
     5.8 -    <value>Contactados recientemente</value>
     5.9 +  <data name="LastUsedFolderName" xml:space="preserve">
    5.10 +    <value>Usados recientemente</value>
    5.11    </data>
    5.12  </root>
    5.13 \ No newline at end of file
     6.1 --- a/Properties/Resources.resx	Fri Nov 30 16:28:52 2018 +0100
     6.2 +++ b/Properties/Resources.resx	Fri Dec 07 12:58:32 2018 +0100
     6.3 @@ -946,7 +946,7 @@
     6.4    <data name="Options_HideInternalMessagesText" xml:space="preserve">
     6.5      <value>Hide internal messages</value>
     6.6    </data>
     6.7 -  <data name="LastContactedFolderName" xml:space="preserve">
     6.8 -    <value>Last contacted</value>
     6.9 +  <data name="LastUsedFolderName" xml:space="preserve">
    6.10 +    <value>Last used</value>
    6.11    </data>
    6.12  </root>
    6.13 \ No newline at end of file
     7.1 --- a/Wrappers/WatchedExplorer.cs	Fri Nov 30 16:28:52 2018 +0100
     7.2 +++ b/Wrappers/WatchedExplorer.cs	Fri Dec 07 12:58:32 2018 +0100
     7.3 @@ -1,4 +1,6 @@
     7.4  using System;
     7.5 +using System.Linq;
     7.6 +using System.Xml;
     7.7  using Outlook = Microsoft.Office.Interop.Outlook;
     7.8  
     7.9  namespace pEp
    7.10 @@ -101,12 +103,14 @@
    7.11                  if (connect)
    7.12                  {
    7.13                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).Close += Explorer_Close;
    7.14 +                    ((Outlook.ExplorerEvents_10_Event)this.Explorer).FolderSwitch += Explorer_FolderSwitch;
    7.15                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).InlineResponseClose += Explorer_InlineResponseClose;
    7.16                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).SelectionChange += Explorer_SelectionChange;
    7.17                  }
    7.18                  else
    7.19                  {
    7.20                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).Close -= Explorer_Close;
    7.21 +                    ((Outlook.ExplorerEvents_10_Event)this.Explorer).FolderSwitch -= Explorer_FolderSwitch;
    7.22                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).InlineResponseClose -= Explorer_InlineResponseClose;
    7.23                      ((Outlook.ExplorerEvents_10_Event)this.Explorer).SelectionChange -= Explorer_SelectionChange;
    7.24                  }
    7.25 @@ -135,6 +139,122 @@
    7.26          }
    7.27  
    7.28          /// <summary>
    7.29 +        /// Event handler for when a different folder is being selected.
    7.30 +        /// </summary>
    7.31 +        private void Explorer_FolderSwitch()
    7.32 +        {
    7.33 +            Outlook.Folder folder = null;
    7.34 +            Outlook.TableView customView = null;
    7.35 +            Outlook.View view = null;
    7.36 +            Outlook.Views views = null;
    7.37 +
    7.38 +            try
    7.39 +            {
    7.40 +                folder = this.Explorer?.CurrentFolder as Outlook.Folder;
    7.41 +
    7.42 +                // If the "Last Used" contacts folder is selected, make sure the correct view is applied
    7.43 +                if ((folder?.DefaultMessageClass?.Equals(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Contact) == true) &&
    7.44 +                    (folder?.Name?.Equals(Properties.Resources.LastUsedFolderName) == true))
    7.45 +                {
    7.46 +                    view = this.Explorer.CurrentView;
    7.47 +
    7.48 +                    // If the current view isn't the custom one, create it if necessary
    7.49 +                    if (view?.Name?.Equals(Properties.Resources.LastUsedFolderName) != true)
    7.50 +                    {
    7.51 +                        views = this.Explorer.CurrentFolder.Views as Outlook.Views;
    7.52 +
    7.53 +                        try
    7.54 +                        {
    7.55 +                            customView = views[Properties.Resources.LastUsedFolderName] as Outlook.TableView;
    7.56 +                        }
    7.57 +                        catch (Exception ex)
    7.58 +                        {
    7.59 +                            customView = null;
    7.60 +                            Log.Info("Explorer_SelectionChange: Error getting Last Used folder view. " + ex.ToString());
    7.61 +                        }
    7.62 +
    7.63 +                        /* If the custom view doesn't exist, create and apply it.
    7.64 +                         * If it already exists, don't apply it.
    7.65 +                         * Caveat: If the creation of the view went wrong at some point, it will never be set correctly. The alternative
    7.66 +                         *         here would be to set it each time it's not set. This is another problem, however, as we don't know if
    7.67 +                         *         the view of this folder is not the custom one because it has never been set correctly or if the user 
    7.68 +                         *         selects another one. So, in the latter case, we would basically override a user decision.
    7.69 +                         * Note: This whole procedure is a workaround because we can only set the Explorer's current view and not the folder's
    7.70 +                         *       current view directly.
    7.71 +                         */                           
    7.72 +                        if (customView == null)
    7.73 +                        {
    7.74 +                            customView = views.Add(Properties.Resources.LastUsedFolderName, Outlook.OlViewType.olTableView, Outlook.OlViewSaveOption.olViewSaveOptionThisFolderEveryone) as Outlook.TableView;
    7.75 +                            XmlDocument xmlDoc = new XmlDocument();
    7.76 +                            xmlDoc.LoadXml(customView.XML);
    7.77 +                            XmlNodeList childNodes = xmlDoc.LastChild.ChildNodes;
    7.78 +
    7.79 +                            // Create and/or set up Order By property
    7.80 +                            XmlNode orderByNode = childNodes.OfType<XmlNode>().First(a => a.Name == "orderby");
    7.81 +                            if (orderByNode == null)
    7.82 +                            {
    7.83 +                                orderByNode = xmlDoc.CreateNode(XmlNodeType.Element, "orderby", string.Empty);
    7.84 +                                xmlDoc.LastChild.AppendChild(orderByNode);
    7.85 +                            }
    7.86 +                            orderByNode.InnerXml = "<order><heading>Modified</heading><prop>DAV:getlastmodified</prop><type>datetime</type><sort>desc</sort></order>";
    7.87 +
    7.88 +                            // Create and/or set up Modified column
    7.89 +                            XmlNode modifiedNode = childNodes.OfType<XmlNode>().FirstOrDefault(a => (a.ChildNodes.OfType<XmlNode>().FirstOrDefault(b => b.Value == "Modified") != null));
    7.90 +
    7.91 +                            if (modifiedNode == null)
    7.92 +                            {
    7.93 +                                modifiedNode = xmlDoc.CreateNode(XmlNodeType.Element, "column", string.Empty);
    7.94 +
    7.95 +                                // Get first column
    7.96 +                                XmlNode fullNameColumn = null;
    7.97 +                                foreach (var node in childNodes)
    7.98 +                                {
    7.99 +                                    if ((node is XmlNode xmlNode) &&
   7.100 +                                        (xmlNode.Name == "column") &&
   7.101 +                                        (xmlNode.FirstChild.InnerText == "Full Name"))
   7.102 +                                    {
   7.103 +                                        fullNameColumn = node as XmlNode;
   7.104 +                                        break;
   7.105 +                                    }
   7.106 +                                }
   7.107 +
   7.108 +                                // If not found, just insert after the 4th column
   7.109 +                                if (fullNameColumn == null)
   7.110 +                                {
   7.111 +                                    fullNameColumn = childNodes[4];
   7.112 +                                }
   7.113 +
   7.114 +                                if (fullNameColumn != null)
   7.115 +                                {
   7.116 +                                    xmlDoc.LastChild.InsertAfter(modifiedNode, fullNameColumn);
   7.117 +                                }
   7.118 +                            }
   7.119 +                            modifiedNode.InnerXml = "<heading>Modified</heading><prop>DAV:getlastmodified</prop><type>datetime</type><width>50</width><style>padding-left:3px;;text-align:left</style><editable>0</editable><format>M/d/yyyy||h:mm tt</format><displayformat>2</displayformat>";
   7.120 +
   7.121 +                            // Set modified XML
   7.122 +                            customView.XML = xmlDoc.OuterXml;
   7.123 +                            customView.Save();
   7.124 +
   7.125 +                            // Apply as current view
   7.126 +                            this.Explorer.CurrentView = customView;
   7.127 +                        }
   7.128 +                    }
   7.129 +                }
   7.130 +            }
   7.131 +            catch (Exception ex)
   7.132 +            {
   7.133 +                Log.Error("Explorer_FolderSwitch: Error setting Last Used folder view. " + ex.ToString());
   7.134 +            }
   7.135 +            finally
   7.136 +            {
   7.137 +                customView = null;
   7.138 +                folder = null;
   7.139 +                view = null;
   7.140 +                views = null;
   7.141 +            }
   7.142 +        }
   7.143 +
   7.144 +        /// <summary>
   7.145          /// Event handler for when an inline response is being closed.
   7.146          /// </summary>
   7.147          private void Explorer_InlineResponseClose()
   7.148 @@ -232,10 +352,10 @@
   7.149  
   7.150                          // Initialize mail item
   7.151                          this.InitializeWindow(isInlineResponse);
   7.152 -                    }
   7.153 +                    }                    
   7.154                      else
   7.155                      {
   7.156 -                        Log.Error("Explorer_SelectionChange: Error getting current mail item.");
   7.157 +                        Log.Error("Explorer_SelectionChange: Error getting current selection.");
   7.158                      }
   7.159                  }
   7.160              }
     8.1 --- a/pEpForOutlook.csproj	Fri Nov 30 16:28:52 2018 +0100
     8.2 +++ b/pEpForOutlook.csproj	Fri Dec 07 12:58:32 2018 +0100
     8.3 @@ -333,6 +333,7 @@
     8.4      <Compile Include="DecryptionStack.cs" />
     8.5      <Compile Include="Extensions\AccountExtensions.cs" />
     8.6      <Compile Include="Extensions\ContactItemExtensions.cs" />
     8.7 +    <Compile Include="Extensions\FolderExtensions.cs" />
     8.8      <Compile Include="Extensions\StoreExtensions.cs" />
     8.9      <Compile Include="FPPMessage.cs" />
    8.10      <Compile Include="Globals.cs" />