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:
parent
72803ef3cd
commit
09f006273e
@ -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" />
|
||||||
|
@ -17,6 +17,7 @@ using Acacia.Features.SecondaryContacts;
|
|||||||
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()
|
||||||
|
@ -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; } }
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@ namespace Acacia.Features.SharedFolders
|
|||||||
_query.Dispose();
|
_query.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FeatureSharedFolders Feature { get { return _feature; } }
|
||||||
|
|
||||||
#region API
|
#region API
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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 "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user