diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
index 4e8901d..fb76988 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
@@ -326,6 +326,7 @@
+
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
index 97d58be..da5fa9c 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/DebugSupport/DebugDialog.cs
@@ -97,9 +97,10 @@ namespace Acacia.Features.DebugSupport
private void DebugCycle()
{
- Tasks.Task(gab, "DebugCycle", () =>
+ // TODO: use completiontracker
+ Tasks.Task(null, gab, "DebugCycle", () =>
{
- gab.FullResync();
+ gab.FullResync(null);
});
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/FreeBusy/FeatureFreeBusy.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/FreeBusy/FeatureFreeBusy.cs
index 6855ad6..3601e42 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/FreeBusy/FeatureFreeBusy.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/FreeBusy/FeatureFreeBusy.cs
@@ -147,7 +147,7 @@ namespace Acacia.Features.FreeBusy
TcpClient client = listener.AcceptTcpClient();
Interlocked.Increment(ref _requestCount);
// And handle it in the UI thread to allow GAB access
- Tasks.Task(this, "FreeBusyHandler", () => server.HandleRequest(client));
+ Tasks.Task(null, this, "FreeBusyHandler", () => server.HandleRequest(client));
}
}
catch (Exception e)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
index 8d3375c..c2358c7 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/FeatureGAB.cs
@@ -45,6 +45,14 @@ namespace Acacia.Features.GAB
{
}
+ public delegate void GABSyncFinishedHandler(GABHandler gab);
+ public event GABSyncFinishedHandler SyncFinished;
+
+ public void OnGabSyncFinished(GABHandler gab)
+ {
+ SyncFinished?.Invoke(gab);
+ }
+
public static GABHandler FindGABForAccount(ZPushAccount account)
{
FeatureGAB gab = ThisAddIn.Instance.GetFeature();
@@ -305,7 +313,7 @@ namespace Acacia.Features.GAB
#region Resync
- internal void FullResync()
+ internal void FullResync(CompletionTracker completion)
{
try
{
@@ -345,10 +353,12 @@ namespace Acacia.Features.GAB
int remaining = _gabsByDomainName.Count;
foreach (GABHandler gab in _gabsByDomainName.Values)
{
+ CompletionTracker partCompletion = new CompletionTracker(() => OnGabSyncFinished(gab));
+ // TODO: merge partCompletion into total completion
Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName);
- Tasks.Task(this, "FullResync", () =>
+ Tasks.Task(partCompletion, this, "FullResync", () =>
{
- gab.FullResync();
+ gab.FullResync(partCompletion);
});
}
}
@@ -662,15 +672,20 @@ namespace Acacia.Features.GAB
++_processing;
Logger.Instance.Trace(this, "Processing GAB message: {0} - {1}", account, _processing);
- try
+ CompletionTracker completion = new CompletionTracker(() => OnGabSyncFinished(gab));
+ using (completion.Begin())
{
- gab.Process(item);
- DoEmptyDeletedItems();
- }
- finally
- {
- Logger.Instance.Trace(this, "Processed GAB message: {0} - {1}", account, _processing);
- --_processing;
+ try
+ {
+ gab.Process(completion, item);
+ // TODO: this will probably run while still processing, use completion tracker
+ DoEmptyDeletedItems();
+ }
+ finally
+ {
+ Logger.Instance.Trace(this, "Processed GAB message: {0} - {1}", account, _processing);
+ --_processing;
+ }
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs
index ddcbae0..c6092c9 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABHandler.cs
@@ -128,10 +128,10 @@ namespace Acacia.Features.GAB
#region Processing
- public void FullResync()
+ public void FullResync(CompletionTracker completion)
{
ClearContacts();
- Process(null);
+ Process(completion, null);
}
private void ClearContacts()
@@ -167,27 +167,30 @@ namespace Acacia.Features.GAB
/// Processes the GAB message(s).
///
/// If specified, this item has changed. If null, means a global check should be performed
- public void Process(IZPushItem item)
+ public void Process(CompletionTracker completion, IZPushItem item)
{
- try
+ using (CompletionTracker.Step step = completion?.Begin())
{
- if (item == null)
+ try
{
- if (Folder != null)
- ProcessMessages();
+ if (item == null)
+ {
+ if (Folder != null)
+ ProcessMessages(completion);
+ }
+ else
+ {
+ ProcessMessage(completion, item);
+ }
}
- else
+ catch (Exception e)
{
- ProcessMessage(item);
+ Logger.Instance.Error(this, "Exception in GAB.Process: {0}", e);
}
}
- catch(Exception e)
- {
- Logger.Instance.Error(this, "Exception in GAB.Process: {0}", e);
- }
}
- private void ProcessMessages()
+ private void ProcessMessages(CompletionTracker completion)
{
if (!_feature.ProcessFolder)
return;
@@ -207,12 +210,12 @@ namespace Acacia.Features.GAB
Logger.Instance.Trace(this, "Checking chunk: {0}", item.Subject);
if (_feature.ProcessItems2)
{
- Tasks.Task(_feature, "ProcessChunk", () =>
+ Tasks.Task(completion, _feature, "ProcessChunk", () =>
{
using (IItem item2 = Folder.GetItemById(entryId))
{
if (item2 != null)
- ProcessMessage((IZPushItem)item2);
+ ProcessMessage(completion, (IZPushItem)item2);
}
});
}
@@ -225,7 +228,7 @@ namespace Acacia.Features.GAB
public const string PROP_GAB_ID = "ZPushId";
public const string PROP_CURRENT_SEQUENCE = "ZPushCurrentSequence";
- private void ProcessMessage(IZPushItem item)
+ private void ProcessMessage(CompletionTracker completion, IZPushItem item)
{
if (!_feature.ProcessMessage)
return;
@@ -281,7 +284,7 @@ namespace Acacia.Features.GAB
}
// Create the new contacts
- ProcessChunkBody(item, index);
+ ProcessChunkBody(completion, item, index);
// Update the state
SetChunkStateString(index, item.Location);
@@ -460,14 +463,14 @@ namespace Acacia.Features.GAB
return value as ValueType;
}
- private void ProcessChunkBody(IZPushItem item, ChunkIndex index)
+ private void ProcessChunkBody(CompletionTracker completion, IZPushItem item, ChunkIndex index)
{
// Process the body
foreach (var entry in JSONUtils.Deserialise(item.Body))
{
string id = entry.Key;
Dictionary value = (Dictionary)entry.Value;
- Tasks.Task(_feature, "CreateItem", () => CreateObject(index, id, value));
+ Tasks.Task(completion, _feature, "CreateItem", () => CreateObject(index, id, value));
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABSettings.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABSettings.cs
index 3d2f9cd..52094e0 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABSettings.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/GAB/GABSettings.cs
@@ -50,7 +50,7 @@ namespace Acacia.Features.GAB
// Allow null feature for designer
if (_feature != null)
{
- _feature.FullResync();
+ _feature.FullResync(null);
}
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
index 51f34cb..8229828 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
@@ -1,4 +1,6 @@
-/// Copyright 2017 Kopano b.v.
+
+using Acacia.Features.GAB;
+/// Copyright 2017 Kopano b.v.
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License, version 3,
@@ -13,7 +15,6 @@
/// along with this program.If not, see.
///
/// Consult LICENSE file for details
-
using Acacia.Stubs;
using Acacia.Stubs.OutlookWrappers;
using Acacia.Utils;
@@ -48,9 +49,16 @@ namespace Acacia.Features.Signatures
#endregion
+ private FeatureGAB _gab;
+
public override void Startup()
{
Watcher.AccountDiscovered += Watcher_AccountDiscovered;
+ _gab = ThisAddIn.Instance.GetFeature();
+ if (_gab != null)
+ {
+ _gab.SyncFinished += GAB_SyncFinished;
+ }
}
private void Watcher_AccountDiscovered(ZPushAccount account)
@@ -146,11 +154,7 @@ namespace Acacia.Features.Signatures
private string StoreSignature(ISignatures signatures, ZPushAccount account, Signature signatureInfo)
{
- string name = SignatureLocalName.ReplacePercentStrings(new Dictionary
- {
- { "account", account.DisplayName },
- { "name", signatureInfo.name }
- });
+ string name = GetSignatureName(signatures, account, signatureInfo.name);
// Remove any existing signature
try
@@ -176,11 +180,129 @@ namespace Acacia.Features.Signatures
// Create the new signature
using (ISignature signature = signatures.Add(name))
{
- signature.SetContent(signatureInfo.content, signatureInfo.isHTML ? ISignatureFormat.HTML : ISignatureFormat.Text);
- // TODO: generate text version if we get an HTML?
+ if (!HasPlaceholders(signatureInfo))
+ {
+ // Simple, set signature straight away
+ signature.SetContent(signatureInfo.content, signatureInfo.isHTML ? ISignatureFormat.HTML : ISignatureFormat.Text);
+ }
+ else
+ {
+ // There are placeholders. Create a template and hook into the GAB for patching
+ signature.SetContentTemplate(signatureInfo.content, signatureInfo.isHTML ? ISignatureFormat.HTML : ISignatureFormat.Text);
+
+ // Try replacing straight away
+ GABHandler gab = FeatureGAB.FindGABForAccount(account);
+ if (gab != null)
+ ReplacePlaceholders(gab, name);
+ }
}
return name;
}
+
+ private string GetSignatureName(ISignatures signatures, ZPushAccount account, string name)
+ {
+ return SignatureLocalName.ReplaceStringTokens("%", "%", new Dictionary
+ {
+ { "account", account.DisplayName },
+ { "name", name }
+ });
+ }
+
+ private bool HasPlaceholders(Signature signature)
+ {
+ return signature.content.IndexOf("{%") >= 0;
+ }
+
+ private void GAB_SyncFinished(GABHandler gab)
+ {
+ ReplacePlaceholders(gab, gab.ActiveAccount.Account.SignatureNewMessage, gab.ActiveAccount.Account.SignatureNewMessage);
+ }
+
+ private void ReplacePlaceholders(GABHandler gab, params string[] signatures)
+ {
+ IContactItem us = null;
+ try
+ {
+ IAccount account = gab.ActiveAccount.Account;
+
+ // Look for the email address. If found, use the account associated with the GAB
+ using (ISearch search = gab.Contacts.Search())
+ {
+ search.AddField("urn:schemas:contacts:email1").SetOperation(SearchOperation.Equal, account.SmtpAddress);
+ IItem result = search.SearchOne();
+ us = result as IContactItem;
+ if (result != null && result != us)
+ result.Dispose();
+ }
+
+ foreach (string signatureName in signatures)
+ {
+ ReplacePlaceholders(gab.ActiveAccount, us, signatureName);
+ }
+ }
+ catch(Exception e)
+ {
+ Logger.Instance.Error(this, "Exception in ReplacePlaceholders: {0}", e);
+ }
+ finally
+ {
+ if (us != null)
+ us.Dispose();
+ }
+ }
+
+ private void ReplacePlaceholders(ZPushAccount account, IContactItem us, string signatureName)
+ {
+ if (string.IsNullOrEmpty(signatureName))
+ return;
+
+ using (ISignatures signatures = ThisAddIn.Instance.GetSignatures())
+ {
+ using (ISignature signature = signatures.Get(signatureName))
+ {
+ if (signature == null)
+ return;
+
+ foreach (ISignatureFormat format in Enum.GetValues(typeof(ISignatureFormat)))
+ {
+ 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.Title ?? "";
+ 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);
+ }
+ }
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOlkAccount.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOlkAccount.cs
index de66aa6..9b504a3 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOlkAccount.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOlkAccount.cs
@@ -8,16 +8,11 @@ using System.Threading.Tasks;
namespace Acacia.Native
{
- [StructLayout(LayoutKind.Explicit)]
+ [StructLayout(LayoutKind.Sequential)]
unsafe public struct ACCT_VARIANT
{
- [FieldOffset(0)]
public uint dwType;
- [FieldOffset(4)]
- public uint dwAlignPad;
-
- [FieldOffset(8)]
public char* lpszW;
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
index c8ac761..6c48a3b 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/MAPI/Restriction.cs
@@ -200,6 +200,7 @@ namespace Acacia.Native.MAPI
}
}
+ // TODO: check this on 32 bit machines
[StructLayout(LayoutKind.Explicit)]
unsafe public struct SRestriction
{
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignature.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignature.cs
index 0ad250e..9e8e5ac 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignature.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignature.cs
@@ -16,5 +16,7 @@ namespace Acacia.Stubs
{
void Delete();
void SetContent(string content, ISignatureFormat format);
+ void SetContentTemplate(string content, ISignatureFormat format);
+ string GetContentTemplate(ISignatureFormat format);
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs
index 14fb794..15279b0 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs
@@ -12,7 +12,9 @@ namespace Acacia.Stubs.OutlookWrappers
{
private static readonly string[] SUFFIXES =
{
- "htm", "html", "rtf", "txt"
+ "htm", "html", "rtf", "txt",
+ "htm.template", "html.template", "rtf.template", "txt.template",
+
};
private static string BasePath
@@ -63,18 +65,44 @@ namespace Acacia.Stubs.OutlookWrappers
// TODO: additional files folder? We never create it
}
- public void SetContent(string content, ISignatureFormat format)
+ private string GetPath(ISignatureFormat format, bool template)
{
// Determine suffix
string suffix = "txt";
- switch(format)
+ switch (format)
{
case ISignatureFormat.HTML: suffix = "htm"; break;
}
- // Write
- string path = GetPath(_name, suffix);
+ if (template)
+ suffix += ".template";
+
+ return GetPath(_name, suffix);
+ }
+
+ public void SetContent(string content, ISignatureFormat format)
+ {
+ string path = GetPath(format, false);
File.WriteAllText(path, content);
}
+
+ public void SetContentTemplate(string content, ISignatureFormat format)
+ {
+ string path = GetPath(format, true);
+ File.WriteAllText(path, content);
+ }
+
+ public string GetContentTemplate(ISignatureFormat format)
+ {
+ string path = GetPath(format, true);
+ try
+ {
+ return File.ReadAllText(path);
+ }
+ catch(Exception)
+ {
+ return null;
+ }
+ }
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoresWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoresWrapper.cs
index 4d167b4..9dd430c 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoresWrapper.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/StoresWrapper.cs
@@ -67,7 +67,7 @@ namespace Acacia.Stubs.OutlookWrappers
// Check existing stores
foreach(NSOutlook.Store store in _item)
{
- Tasks.Task(null, "AddStore", () =>
+ Tasks.Task(null, null, "AddStore", () =>
{
StoreAdded(store);
});
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/CompletionTracker.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/CompletionTracker.cs
new file mode 100644
index 0000000..2a139f9
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/CompletionTracker.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Acacia.Utils
+{
+ public class CompletionTracker
+ {
+ public class Step : IDisposable
+ {
+ private readonly CompletionTracker _tracker;
+
+ public Step(CompletionTracker tracker)
+ {
+ this._tracker = tracker;
+ }
+
+ public void Dispose()
+ {
+ _tracker.End();
+ }
+ }
+
+ private readonly Action _completion;
+ private int steps = 0;
+
+ public CompletionTracker(Action completion)
+ {
+ this._completion = completion;
+ }
+
+ ///
+ /// Begins a sub-step.
+ ///
+ /// A step. This may be disposed, or End may be used
+ public Step Begin()
+ {
+ Interlocked.Increment(ref steps);
+ return new Step(this);
+ }
+
+ public void End()
+ {
+ if (Interlocked.Decrement(ref steps) == 0)
+ {
+ // Done
+ _completion();
+ }
+ }
+ }
+}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/StringUtil.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/StringUtil.cs
index 997c91d..6d990c0 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/StringUtil.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/StringUtil.cs
@@ -108,20 +108,32 @@ namespace Acacia.Utils
#region Formatting / Replacement
- public static string ReplacePercentStrings(this string s, Dictionary replacements)
+ public delegate string TokenReplacer(string token);
+
+ public static string ReplaceStringTokens(this string s, string open, string close, TokenReplacer replacer)
{
- return Regex.Replace(s, @"%(\w+)%", (m) =>
+ return Regex.Replace(s, Regex.Escape(open) + @"(\w+)" + Regex.Escape(close), (m) =>
{
- string replacement;
var key = m.Groups[1].Value;
- if (replacements.TryGetValue(key, out replacement))
- {
- return Convert.ToString(replacement);
- }
- else
+ string replacement = replacer(key);
+ if (replacement == null)
{
return m.Groups[0].Value;
}
+ else
+ {
+ return replacement;
+ }
+ });
+ }
+
+ public static string ReplaceStringTokens(this string s, string open, string close, Dictionary replacements)
+ {
+ return s.ReplaceStringTokens(open, close, (token) =>
+ {
+ string replacement = null;
+ replacements.TryGetValue(token, out replacement);
+ return replacement;
});
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
index 9169b04..cc7a45e 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/Tasks.cs
@@ -26,12 +26,15 @@ namespace Acacia.Utils
{
public class AcaciaTask
{
+ private readonly CompletionTracker _completion;
public readonly Feature Owner;
public readonly string Name;
public readonly Action Action;
- public AcaciaTask(Feature owner, string name, Action action)
+ public AcaciaTask(CompletionTracker completion, Feature owner, string name, Action action)
{
+ this._completion = completion;
+ completion?.Begin();
Owner = owner;
Name = name;
Action = action;
@@ -62,6 +65,10 @@ namespace Acacia.Utils
Logger.Instance.Error(Owner, "Exception in task {0}: {1}", Name, e);
return false;
}
+ finally
+ {
+ _completion?.End();
+ }
}
}
@@ -122,9 +129,9 @@ namespace Acacia.Utils
}
}
- public static void Task(Feature owner, string name, Action action)
+ public static void Task(CompletionTracker completion, Feature owner, string name, Action action)
{
- Task(new AcaciaTask(owner, name, action));
+ Task(new AcaciaTask(completion, owner, name, action));
}
public static void Task(AcaciaTask task)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs
index 164b8a9..eebfabf 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccounts.cs
@@ -68,13 +68,13 @@ namespace Acacia.ZPush
// Process existing accounts
foreach (IAccount account in _stores.Accounts)
{
- Tasks.Task(null, "AccountCheck", () =>
+ Tasks.Task(null, null, "AccountCheck", () =>
{
AccountAdded(account);
});
}
- Tasks.Task(null, "AccountCheckDone", () =>
+ Tasks.Task(null, null, "AccountCheckDone", () =>
{
_watcher.OnAccountsScanned();
});
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushChannel.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushChannel.cs
index f78a25f..1e64aa5 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushChannel.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushChannel.cs
@@ -85,7 +85,7 @@ namespace Acacia.ZPush
// Notify any listeners
if (Available != null)
{
- Tasks.Task(null, "Watcher_WatchingFolder", () => Available(folder));
+ Tasks.Task(null, null, "Watcher_WatchingFolder", () => Available(folder));
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs
index 77f20c5..6540a65 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushFolder.cs
@@ -85,7 +85,7 @@ namespace Acacia.ZPush
// Recurse the children
foreach (IFolder subfolder in _folder.SubFolders)
{
- Tasks.Task(null, "WatchChild", () => WatchChild(subfolder, true));
+ Tasks.Task(null, null, "WatchChild", () => WatchChild(subfolder, true));
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushSync.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushSync.cs
index c521519..e05b37b 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushSync.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushSync.cs
@@ -57,7 +57,7 @@ namespace Acacia.ZPush
{
if (_actionConnection != null)
{
- return new AcaciaTask(_owner, _name, () =>
+ return new AcaciaTask(null, _owner, _name, () =>
{
// TODO: reuse connections
using (ZPushConnection con = account.Connect())
@@ -68,7 +68,7 @@ namespace Acacia.ZPush
}
else
{
- return new AcaciaTask(_owner, _name, () => _action(account));
+ return new AcaciaTask(null, _owner, _name, () => _action(account));
}
}
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs
index c8afd5b..3801d7b 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs
@@ -111,7 +111,7 @@ namespace Acacia.ZPush
if (account.Account.HasPassword)
{
// Send an OOF request to get the OOF state and capabilities
- Tasks.Task(null, "ZPushCheck: " + account.DisplayName, () =>
+ Tasks.Task(null, null, "ZPushCheck: " + account.DisplayName, () =>
{
// TODO: if this fails, retry?
ActiveSync.SettingsOOF oof;