1
0
mirror of https://github.com/Kopano-dev/kopano-ol-extension.git synced 2023-10-10 13:37:40 +02:00

[KOE-116] Added configuration of display names for shared folders

This commit is contained in:
Patrick Simpson 2017-09-26 16:01:53 +02:00
parent 3b2c6dde64
commit 20ebda3e8c
10 changed files with 206 additions and 68 deletions

View File

@ -457,6 +457,7 @@
<Compile Include="Utils\TasksBackground.cs" /> <Compile Include="Utils\TasksBackground.cs" />
<Compile Include="Utils\TasksMainThread.cs" /> <Compile Include="Utils\TasksMainThread.cs" />
<Compile Include="Utils\TasksSynchronous.cs" /> <Compile Include="Utils\TasksSynchronous.cs" />
<Compile Include="ZPush\ContactStringReplacer.cs" />
<Compile Include="ZPush\Delegates.cs" /> <Compile Include="ZPush\Delegates.cs" />
<Compile Include="ZPush\FolderRegistration.cs" /> <Compile Include="ZPush\FolderRegistration.cs" />
<Compile Include="ZPush\GABUser.cs" /> <Compile Include="ZPush\GABUser.cs" />

View File

@ -17,6 +17,7 @@
using Acacia.Stubs; using Acacia.Stubs;
using Acacia.UI; using Acacia.UI;
using Acacia.UI.Outlook; using Acacia.UI.Outlook;
using Acacia.Utils;
using Acacia.ZPush; using Acacia.ZPush;
using Acacia.ZPush.API.SharedFolders; using Acacia.ZPush.API.SharedFolders;
using Acacia.ZPush.Connect; using Acacia.ZPush.Connect;
@ -56,6 +57,13 @@ namespace Acacia.Features.SharedFolders
} }
private static readonly BoolOption OPTION_REMINDERS_KEEP_RUNNING = new BoolOption("RemindersKeepRunning", true); 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 #endregion
public override void Startup() public override void Startup()

View File

@ -58,6 +58,14 @@ namespace Acacia.Features.SharedFolders
base.OnCheckStateChanged(); base.OnCheckStateChanged();
} }
public string DefaultName
{
get
{
return _store.DefaultNameForFolder(AvailableFolder);
}
}
public AvailableFolder AvailableFolder { get { return _folder; } } public AvailableFolder AvailableFolder { get { return _folder; } }
public bool IsShared { get { return CheckState != System.Windows.Forms.CheckState.Unchecked; } } public bool IsShared { get { return CheckState != System.Windows.Forms.CheckState.Unchecked; } }

View File

@ -260,7 +260,8 @@ namespace Acacia.Features.SharedFolders
} }
// Add the node // 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; node.DirtyChanged += UserSharesChanged;
_userFolders.Add(user, node); _userFolders.Add(user, node);
kTreeFolders.RootNodes.Add(node); kTreeFolders.RootNodes.Add(node);
@ -524,7 +525,7 @@ namespace Acacia.Features.SharedFolders
_optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithName(textName.Text); _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithName(textName.Text);
// If the share name matches the folder name, track update // 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); _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithFlagTrackShareName(track);
} }
} }

View File

@ -41,6 +41,8 @@ namespace Acacia.Features.SharedFolders
_query.Dispose(); _query.Dispose();
} }
public FeatureSharedFolders Feature { get { return _feature; } }
#region API #region API
/// <summary> /// <summary>

View File

@ -26,6 +26,7 @@ using System.Threading;
using Acacia.ZPush.API.SharedFolders; using Acacia.ZPush.API.SharedFolders;
using Acacia.ZPush.Connect; using Acacia.ZPush.Connect;
using Acacia.Native; using Acacia.Native;
using Acacia.Features.GAB;
namespace Acacia.Features.SharedFolders namespace Acacia.Features.SharedFolders
{ {
@ -41,11 +42,19 @@ namespace Acacia.Features.SharedFolders
private readonly Dictionary<BackendId, SharedFolder> _initialShares; private readonly Dictionary<BackendId, SharedFolder> _initialShares;
private readonly Dictionary<BackendId, SharedFolder> _currentShares; 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) base(text)
{ {
this._initialShares = currentFolders; 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 // 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. // cleaning up automatically any obsolote shares.
@ -92,7 +101,7 @@ namespace Acacia.Features.SharedFolders
private SharedFolder CreateDefaultShare(AvailableFolder folder) private SharedFolder CreateDefaultShare(AvailableFolder folder)
{ {
SharedFolder share = new SharedFolder(folder); SharedFolder share = new SharedFolder(folder, DefaultNameForFolder(folder));
// Default send as for mail folders // Default send as for mail folders
if (folder.Type.IsMail()) 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) private SharedFolder GetInitialShareState(AvailableFolder folder)
{ {
SharedFolder state; SharedFolder state;
if (_initialShares.TryGetValue(folder.BackendId, out state)) if (_initialShares.TryGetValue(folder.BackendId, out state))
{ {
// If the folder has been renamed, update if we're tracing it. // 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) if (state.FlagUpdateShareName)
state = state.WithName(folder.DefaultName); state = state.WithName(DefaultNameForFolder(folder));
} }
return state; return state;
} }

View File

@ -296,26 +296,15 @@ namespace Acacia.Features.Signatures
private void ReplacePlaceholders(GABHandler gab, params string[] signatures) private void ReplacePlaceholders(GABHandler gab, params string[] signatures)
{ {
IContactItem us = null; ContactStringReplacer replacer = null;
try try
{ {
IAccount account = gab.ActiveAccount.Account; replacer = ContactStringReplacer.FindUs(gab);
if (replacer != null)
// 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)
{ {
foreach (string signatureName in signatures) foreach (string signatureName in signatures)
{ {
ReplacePlaceholders(gab.ActiveAccount, us, signatureName); ReplacePlaceholders(replacer, signatureName);
} }
} }
} }
@ -325,12 +314,12 @@ namespace Acacia.Features.Signatures
} }
finally finally
{ {
if (us != null) if (replacer != null)
us.Dispose(); replacer.Dispose();
} }
} }
private void ReplacePlaceholders(ZPushAccount account, IContactItem us, string signatureName) private void ReplacePlaceholders(ContactStringReplacer replacer, string signatureName)
{ {
if (string.IsNullOrEmpty(signatureName)) if (string.IsNullOrEmpty(signatureName))
return; return;
@ -347,35 +336,7 @@ namespace Acacia.Features.Signatures
string template = signature.GetContentTemplate(format); string template = signature.GetContentTemplate(format);
if (template != null) if (template != null)
{ {
string replaced = template.ReplaceStringTokens("{%", "}", (token) => string replaced = replacer.Replace(template);
{
// 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 "";
});
signature.SetContent(replaced, format); signature.SetContent(replaced, format);
} }
} }

View File

@ -78,22 +78,15 @@ namespace Acacia.ZPush.API.SharedFolders
public string Name { get { return _data.displayname; } } 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 OutlookConstants.SyncType Type { get { return _data.type; } }
public GABUser Store { get; private set; } public GABUser Store { get; private set; }
/// <summary>
/// Cache for DefaultName, used by StoreTreeNode.
/// </summary>
public string DefaultName { get; set; }
#endregion #endregion
#region Tree structure #region Tree structure

View File

@ -95,14 +95,14 @@ namespace Acacia.ZPush.API.SharedFolders
/// <summary> /// <summary>
/// Creates an instances for the specified folder. /// Creates an instances for the specified folder.
/// </summary> /// </summary>
public SharedFolder(AvailableFolder folder) public SharedFolder(AvailableFolder folder, string name)
{ {
_data = new SoapData() _data = new SoapData()
{ {
store = folder.Store.UserName, store = folder.Store.UserName,
folderid = folder.BackendId, folderid = folder.BackendId,
parentid = folder.ParentIdAsBackend, parentid = folder.ParentIdAsBackend,
name = folder.DefaultName, name = name,
type = OutlookConstants.USER_SYNC_TYPES[(int)folder.Type], type = OutlookConstants.USER_SYNC_TYPES[(int)folder.Type],
flags = folder.Type.IsMail() ? ShareFlags.SendAsOwner : ShareFlags.None flags = folder.Type.IsMail() ? ShareFlags.SendAsOwner : ShareFlags.None
}; };

View File

@ -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 "";
}
}
}