mirror of
				https://github.com/Kopano-dev/kopano-ol-extension.git
				synced 2023-10-10 11:37:40 +00:00 
			
		
		
		
	[KOE-116] Added configuration of display names for shared folders
This commit is contained in:
		| @@ -457,6 +457,7 @@ | ||||
|     <Compile Include="Utils\TasksBackground.cs" /> | ||||
|     <Compile Include="Utils\TasksMainThread.cs" /> | ||||
|     <Compile Include="Utils\TasksSynchronous.cs" /> | ||||
|     <Compile Include="ZPush\ContactStringReplacer.cs" /> | ||||
|     <Compile Include="ZPush\Delegates.cs" /> | ||||
|     <Compile Include="ZPush\FolderRegistration.cs" /> | ||||
|     <Compile Include="ZPush\GABUser.cs" /> | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| using Acacia.Stubs; | ||||
| using Acacia.UI; | ||||
| using Acacia.UI.Outlook; | ||||
| using Acacia.Utils; | ||||
| using Acacia.ZPush; | ||||
| using Acacia.ZPush.API.SharedFolders; | ||||
| using Acacia.ZPush.Connect; | ||||
| @@ -56,6 +57,13 @@ namespace Acacia.Features.SharedFolders | ||||
|         } | ||||
|         private static readonly BoolOption OPTION_REMINDERS_KEEP_RUNNING = new BoolOption("RemindersKeepRunning", true); | ||||
|  | ||||
|         [AcaciaOption("The format for local names of shared folders. May contain contact fields and %foldername%.")] | ||||
|         public string DefaultFolderNameFormat | ||||
|         { | ||||
|             get { return RegistryUtil.GetConfigValue("SharedFolders", "DefaultFolderNameFormat", "%foldername% - %username%"); } | ||||
|             set { RegistryUtil.SetConfigValue("SharedFolders", "DefaultFolderNameFormat", value, Microsoft.Win32.RegistryValueKind.String); } | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         public override void Startup() | ||||
|   | ||||
| @@ -58,6 +58,14 @@ namespace Acacia.Features.SharedFolders | ||||
|             base.OnCheckStateChanged(); | ||||
|         } | ||||
|  | ||||
|         public string DefaultName | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _store.DefaultNameForFolder(AvailableFolder); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public AvailableFolder AvailableFolder { get { return _folder; } } | ||||
|  | ||||
|         public bool IsShared { get { return CheckState != System.Windows.Forms.CheckState.Unchecked; } } | ||||
|   | ||||
| @@ -260,7 +260,8 @@ namespace Acacia.Features.SharedFolders | ||||
|                 } | ||||
|  | ||||
|                 // Add the node | ||||
|                 node = new StoreTreeNode(_folders, user, user.DisplayName, currentShares ?? new Dictionary<BackendId, SharedFolder>()); | ||||
|                 node = new StoreTreeNode(_folders, gabLookup.GAB, | ||||
|                                          user, user.DisplayName, currentShares ?? new Dictionary<BackendId, SharedFolder>()); | ||||
|                 node.DirtyChanged += UserSharesChanged; | ||||
|                 _userFolders.Add(user, node); | ||||
|                 kTreeFolders.RootNodes.Add(node); | ||||
| @@ -524,7 +525,7 @@ namespace Acacia.Features.SharedFolders | ||||
|                 _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithName(textName.Text); | ||||
|  | ||||
|                 // If the share name matches the folder name, track update | ||||
|                 bool track = _optionNameNode.SharedFolder.Name == _optionNameNode.AvailableFolder.DefaultName; | ||||
|                 bool track = _optionNameNode.SharedFolder.Name ==  _optionNameNode.DefaultName; | ||||
|                 _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithFlagTrackShareName(track); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -41,6 +41,8 @@ namespace Acacia.Features.SharedFolders | ||||
|                 _query.Dispose(); | ||||
|         } | ||||
|  | ||||
|         public FeatureSharedFolders Feature { get { return _feature; } } | ||||
|  | ||||
|         #region API | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -26,6 +26,7 @@ using System.Threading; | ||||
| using Acacia.ZPush.API.SharedFolders; | ||||
| using Acacia.ZPush.Connect; | ||||
| using Acacia.Native; | ||||
| using Acacia.Features.GAB; | ||||
|  | ||||
| namespace Acacia.Features.SharedFolders | ||||
| { | ||||
| @@ -41,11 +42,19 @@ namespace Acacia.Features.SharedFolders | ||||
|         private readonly Dictionary<BackendId, SharedFolder> _initialShares; | ||||
|         private readonly Dictionary<BackendId, SharedFolder> _currentShares; | ||||
|  | ||||
|         public StoreTreeNode(SharedFoldersManager folders, GABUser user, string text, Dictionary<BackendId, SharedFolder> currentFolders) | ||||
|         private readonly FeatureSharedFolders _feature; | ||||
|         private readonly GABHandler _gab; | ||||
|         private readonly GABUser _user; | ||||
|  | ||||
|         public StoreTreeNode(SharedFoldersManager folders, GABHandler gab, GABUser user, string text,  | ||||
|                              Dictionary<BackendId, SharedFolder> currentFolders) | ||||
|         : | ||||
|         base(text) | ||||
|         { | ||||
|             this._initialShares = currentFolders; | ||||
|             this._feature = folders.Feature; | ||||
|             this._gab = gab; | ||||
|             this._user = user; | ||||
|  | ||||
|             // Create an empty current state. When loading the nodes, the shares will be added. This has the benefit of | ||||
|             // cleaning up automatically any obsolote shares. | ||||
| @@ -92,7 +101,7 @@ namespace Acacia.Features.SharedFolders | ||||
|  | ||||
|         private SharedFolder CreateDefaultShare(AvailableFolder folder) | ||||
|         { | ||||
|             SharedFolder share = new SharedFolder(folder); | ||||
|             SharedFolder share = new SharedFolder(folder, DefaultNameForFolder(folder)); | ||||
|              | ||||
|             // Default send as for mail folders | ||||
|             if (folder.Type.IsMail()) | ||||
| @@ -109,16 +118,44 @@ namespace Acacia.Features.SharedFolders | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         internal string DefaultNameForFolder(AvailableFolder folder) | ||||
|         { | ||||
|             // Default include the store name in root folders | ||||
|             if (folder.ParentId.IsNone) | ||||
|             { | ||||
|                 if (folder.DefaultName == null) | ||||
|                 { | ||||
|                     using (ContactStringReplacer replacer = ContactStringReplacer.FromGAB(_gab, _user)) | ||||
|                     { | ||||
|                         replacer.TokenOpen = "%"; | ||||
|                         replacer.TokenClose = "%"; | ||||
|                         replacer.UnknownReplacer = (token) => | ||||
|                         { | ||||
|                             if (token == "foldername") | ||||
|                                 return folder.Name; | ||||
|                             return ""; | ||||
|                         }; | ||||
|                         folder.DefaultName = replacer.Replace(_feature.DefaultFolderNameFormat); | ||||
|                     } | ||||
|                 } | ||||
|                 return folder.DefaultName; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return folder.Name; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private SharedFolder GetInitialShareState(AvailableFolder folder) | ||||
|         { | ||||
|             SharedFolder state; | ||||
|             if (_initialShares.TryGetValue(folder.BackendId, out state)) | ||||
|             { | ||||
|                 // If the folder has been renamed, update if we're tracing it. | ||||
|                 if (state.Name != folder.DefaultName) | ||||
|                 if (state.Name != DefaultNameForFolder(folder)) | ||||
|                 { | ||||
|                     if (state.FlagUpdateShareName) | ||||
|                         state = state.WithName(folder.DefaultName); | ||||
|                         state = state.WithName(DefaultNameForFolder(folder)); | ||||
|                 } | ||||
|                 return state; | ||||
|             } | ||||
|   | ||||
| @@ -295,27 +295,16 @@ namespace Acacia.Features.Signatures | ||||
|         } | ||||
|  | ||||
|         private void ReplacePlaceholders(GABHandler gab, params string[] signatures) | ||||
|         {  | ||||
|             IContactItem us = null; | ||||
|         { | ||||
|             ContactStringReplacer replacer = null; | ||||
|             try | ||||
|             { | ||||
|                 IAccount account = gab.ActiveAccount.Account; | ||||
|  | ||||
|                 // Look for the email address. If found, use the account associated with the GAB | ||||
|                 using (ISearch<IContactItem> search = gab.Contacts.Search<IContactItem>()) | ||||
|                 { | ||||
|                     search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, account.UserName); | ||||
|                     IItem result = search.SearchOne(); | ||||
|                     us = result as IContactItem; | ||||
|                     if (result != null && result != us) | ||||
|                         result.Dispose(); | ||||
|                 } | ||||
|  | ||||
|                 if (us != null) | ||||
|                 replacer = ContactStringReplacer.FindUs(gab); | ||||
|                 if (replacer != null) | ||||
|                 { | ||||
|                     foreach (string signatureName in signatures) | ||||
|                     { | ||||
|                         ReplacePlaceholders(gab.ActiveAccount, us, signatureName); | ||||
|                         ReplacePlaceholders(replacer, signatureName); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -325,12 +314,12 @@ namespace Acacia.Features.Signatures | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 if (us != null) | ||||
|                     us.Dispose(); | ||||
|                 if (replacer != null) | ||||
|                     replacer.Dispose(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void ReplacePlaceholders(ZPushAccount account, IContactItem us, string signatureName) | ||||
|         private void ReplacePlaceholders(ContactStringReplacer replacer, string signatureName) | ||||
|         { | ||||
|             if (string.IsNullOrEmpty(signatureName)) | ||||
|                 return; | ||||
| @@ -347,35 +336,7 @@ namespace Acacia.Features.Signatures | ||||
|                         string template = signature.GetContentTemplate(format); | ||||
|                         if (template != null) | ||||
|                         { | ||||
|                             string replaced = template.ReplaceStringTokens("{%", "}", (token) => | ||||
|                             { | ||||
|                                 // TODO: generalise this | ||||
|                                 if (token == "firstname") return us.FirstName ?? ""; | ||||
|                                 if (token == "initials") return us.Initials ?? ""; | ||||
|                                 if (token == "lastname") return us.LastName ?? ""; | ||||
|                                 if (token == "displayname") return us.FullName ?? ""; | ||||
|                                 if (token == "title") return us.JobTitle ?? ""; | ||||
|                                 if (token == "company") return us.CompanyName ?? ""; | ||||
|                                 // TODO if (token == "department") return us.; | ||||
|                                 if (token == "office") return us.OfficeLocation ?? ""; | ||||
|                                 // if (token == "assistant") return us.; | ||||
|                                 if (token == "phone") return us.BusinessTelephoneNumber ?? us.MobileTelephoneNumber ?? ""; | ||||
|                                 if (token == "primary_email") return us.Email1Address ?? ""; | ||||
|                                 if (token == "address") return us.BusinessAddress ?? ""; | ||||
|                                 if (token == "city") return us.BusinessAddressCity ?? ""; | ||||
|                                 if (token == "state") return us.BusinessAddressState ?? ""; | ||||
|                                 if (token == "zipcode") return us.BusinessAddressPostalCode ?? ""; | ||||
|                                 if (token == "country") return us.BusinessAddressState ?? ""; | ||||
|                                 if (token == "phone_business") return us.BusinessTelephoneNumber ?? ""; | ||||
|                                 // TODO if (token == "phone_business2") return us.BusinessTelephoneNumber; | ||||
|                                 if (token == "phone_fax") return us.BusinessFaxNumber ?? ""; | ||||
|                                 // TODO if (token == "phone_assistant") return us.FirstName; | ||||
|                                 if (token == "phone_home") return us.HomeTelephoneNumber ?? ""; | ||||
|                                 //if (token == "phone_home2") return us.HomeTelephoneNumber; | ||||
|                                 if (token == "phone_mobile") return us.MobileTelephoneNumber ?? ""; | ||||
|                                 if (token == "phone_pager") return us.PagerNumber ?? ""; | ||||
|                                 return ""; | ||||
|                             }); | ||||
|                             string replaced = replacer.Replace(template); | ||||
|                             signature.SetContent(replaced, format); | ||||
|                         } | ||||
|                     } | ||||
|   | ||||
| @@ -78,22 +78,15 @@ namespace Acacia.ZPush.API.SharedFolders | ||||
|  | ||||
|         public string Name { get { return _data.displayname; } } | ||||
|  | ||||
|         public string DefaultName | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 // Default include the store name in root folders | ||||
|                 if (ParentId.IsNone) | ||||
|                     return Name + " - " + Store.UserName; | ||||
|                 else | ||||
|                     return Name; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public OutlookConstants.SyncType Type { get { return _data.type; } } | ||||
|  | ||||
|         public GABUser Store { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Cache for DefaultName, used by StoreTreeNode. | ||||
|         /// </summary> | ||||
|         public string DefaultName { get; set; } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region Tree structure | ||||
|   | ||||
| @@ -95,14 +95,14 @@ namespace Acacia.ZPush.API.SharedFolders | ||||
|         /// <summary> | ||||
|         /// Creates an instances for the specified folder. | ||||
|         /// </summary> | ||||
|         public SharedFolder(AvailableFolder folder) | ||||
|         public SharedFolder(AvailableFolder folder, string name) | ||||
|         { | ||||
|             _data = new SoapData() | ||||
|             { | ||||
|                 store = folder.Store.UserName, | ||||
|                 folderid = folder.BackendId, | ||||
|                 parentid = folder.ParentIdAsBackend, | ||||
|                 name = folder.DefaultName, | ||||
|                 name = name, | ||||
|                 type = OutlookConstants.USER_SYNC_TYPES[(int)folder.Type], | ||||
|                 flags = folder.Type.IsMail() ? ShareFlags.SendAsOwner : ShareFlags.None | ||||
|             }; | ||||
|   | ||||
| @@ -0,0 +1,127 @@ | ||||
| using Acacia.Features.GAB; | ||||
| using Acacia.Stubs; | ||||
| using Acacia.Utils; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Acacia.ZPush | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Replaces placeholders in a string with information from a contact. | ||||
|     /// </summary> | ||||
|     public class ContactStringReplacer | ||||
|         : | ||||
|         IDisposable | ||||
|     { | ||||
|         private readonly IContactItem _contact; | ||||
|  | ||||
|         public string TokenOpen | ||||
|         { | ||||
|             get; | ||||
|             set; | ||||
|         } | ||||
|  | ||||
|         public string TokenClose | ||||
|         { | ||||
|             get; | ||||
|             set; | ||||
|         } | ||||
|  | ||||
|         public delegate string TokenReplacer(string token); | ||||
|  | ||||
|         public TokenReplacer UnknownReplacer | ||||
|         { | ||||
|             get; | ||||
|             set; | ||||
|         } | ||||
|  | ||||
|         public ContactStringReplacer(IContactItem contact) | ||||
|         { | ||||
|             this._contact = contact; | ||||
|             TokenOpen = "{%"; | ||||
|             TokenClose = "}"; | ||||
|         } | ||||
|  | ||||
|         public static ContactStringReplacer FindUs(GABHandler gab) | ||||
|         { | ||||
|             // Look for the email address. If found, use the account associated with the GAB | ||||
|             using (ISearch<IContactItem> search = gab.Contacts.Search<IContactItem>()) | ||||
|             { | ||||
|                 IAccount account = gab.ActiveAccount.Account; | ||||
|  | ||||
|                 search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, account.UserName); | ||||
|                 IItem result = search.SearchOne(); | ||||
|                 IContactItem us = result as IContactItem; | ||||
|                 if (result != null && result != us) | ||||
|                 { | ||||
|                     result.Dispose(); | ||||
|                     return null; | ||||
|                 } | ||||
|  | ||||
|                 if (us == null) | ||||
|                     return null; | ||||
|  | ||||
|                 return new ContactStringReplacer(us); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public static ContactStringReplacer FromGAB(GABHandler gab, GABUser user) | ||||
|         { | ||||
|             using (ISearch<IContactItem> search = gab.Contacts.Search<IContactItem>()) | ||||
|             { | ||||
|                 search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, user.UserName); | ||||
|                 IItem result = search.SearchOne(); | ||||
|                 IContactItem contact = result as IContactItem; | ||||
|                 if (result != null && result != contact) | ||||
|                     result.Dispose(); | ||||
|  | ||||
|                 return new ContactStringReplacer(contact); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|             _contact.Dispose(); | ||||
|         } | ||||
|  | ||||
|         public string Replace(string template) | ||||
|         { | ||||
|             string replaced = template.ReplaceStringTokens(TokenOpen, TokenClose, (token) => | ||||
|             { | ||||
|                 if (token == "firstname") return _contact.FirstName ?? ""; | ||||
|                 if (token == "initials") return _contact.Initials ?? ""; | ||||
|                 if (token == "lastname") return _contact.LastName ?? ""; | ||||
|                 if (token == "displayname") return _contact.FullName ?? ""; | ||||
|                 if (token == "username") return _contact.CustomerID ?? ""; | ||||
|                 if (token == "title") return _contact.JobTitle ?? ""; | ||||
|                 if (token == "company") return _contact.CompanyName ?? ""; | ||||
|                 if (token == "office") return _contact.OfficeLocation ?? ""; | ||||
|                 if (token == "phone") return _contact.BusinessTelephoneNumber ?? _contact.MobileTelephoneNumber ?? ""; | ||||
|                 if (token == "primary_email") return _contact.Email1Address ?? ""; | ||||
|                 if (token == "address") return _contact.BusinessAddress ?? ""; | ||||
|                 if (token == "city") return _contact.BusinessAddressCity ?? ""; | ||||
|                 if (token == "state") return _contact.BusinessAddressState ?? ""; | ||||
|                 if (token == "zipcode") return _contact.BusinessAddressPostalCode ?? ""; | ||||
|                 if (token == "country") return _contact.BusinessAddressState ?? ""; | ||||
|                 if (token == "phone_business") return _contact.BusinessTelephoneNumber ?? ""; | ||||
|                 if (token == "phone_fax") return _contact.BusinessFaxNumber ?? ""; | ||||
|                 if (token == "phone_home") return _contact.HomeTelephoneNumber ?? ""; | ||||
|                 if (token == "phone_mobile") return _contact.MobileTelephoneNumber ?? ""; | ||||
|                 if (token == "phone_pager") return _contact.PagerNumber ?? ""; | ||||
|                 return GetUnknownToken(token); | ||||
|             }); | ||||
|             return replaced; | ||||
|         } | ||||
|  | ||||
|         private string GetUnknownToken(string token) | ||||
|         { | ||||
|             if (UnknownReplacer != null) | ||||
|                 return UnknownReplacer(token); | ||||
|             return ""; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user