mirror of
https://github.com/Kopano-dev/kopano-ol-extension.git
synced 2023-10-10 13:37:40 +02:00
[KOE-24] Added per-account GAB resync and synchronous GAB resync.
This commit is contained in:
parent
c5fcf62e35
commit
edf48b595d
@ -361,7 +361,7 @@ namespace Acacia.Features.GAB
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsGABContactsFolder(folder))
|
||||
if (IsGABContactsFolder(folder, accounts))
|
||||
{
|
||||
Logger.Instance.Debug(this, "FullResync: Deleting contacts folder: {0}", folder.Name);
|
||||
folder.Delete();
|
||||
@ -378,16 +378,27 @@ namespace Acacia.Features.GAB
|
||||
}
|
||||
|
||||
// Do the resync
|
||||
int remaining = _gabsByDomainName.Count;
|
||||
foreach (GABHandler gab in _gabsByDomainName.Values)
|
||||
using (completion.Begin())
|
||||
{
|
||||
CompletionTracker partCompletion = new CompletionTracker(() => OnGabSyncFinished(gab));
|
||||
// TODO: merge partCompletion into total completion
|
||||
Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName);
|
||||
Tasks.Task(partCompletion, this, "FullResync", () =>
|
||||
foreach (GABHandler gab in _gabsByDomainName.Values)
|
||||
{
|
||||
gab.FullResync(partCompletion);
|
||||
});
|
||||
// Check if the gab is appropriate for the accounts
|
||||
if (accounts == null || accounts.Contains(gab.ActiveAccount))
|
||||
{
|
||||
completion.Begin();
|
||||
CompletionTracker partCompletion = new CompletionTracker(() =>
|
||||
{
|
||||
OnGabSyncFinished(gab);
|
||||
completion.End();
|
||||
});
|
||||
|
||||
Logger.Instance.Debug(this, "FullResync: Starting resync: {0}", gab.DisplayName);
|
||||
Tasks.Task(partCompletion, this, "FullResync", () =>
|
||||
{
|
||||
gab.FullResync(partCompletion);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
@ -499,9 +510,30 @@ namespace Acacia.Features.GAB
|
||||
return GABInfo.Get(folder);
|
||||
}
|
||||
|
||||
public static bool IsGABContactsFolder(IFolder folder)
|
||||
/// <summary>
|
||||
/// Checks if the folder is a relevant GAB contacts folder.
|
||||
/// </summary>
|
||||
/// <param name="folder">The folder.</param>
|
||||
/// <param name="accounts">If specified, the folder is considered relevant only if it is the GAB for one of the specified
|
||||
/// accounts. Otherwise, any GAB folder is considered relevant.</param>
|
||||
public static bool IsGABContactsFolder(IFolder folder, ZPushAccount[] accounts)
|
||||
{
|
||||
return GetGABContactsFolderInfo(folder) != null;
|
||||
// Check if this is a GAB folder at all
|
||||
GABInfo gab = GetGABContactsFolderInfo(folder);
|
||||
if (gab == null)
|
||||
return false;
|
||||
|
||||
// If we don't have a list of accounts, it is what we're looking for
|
||||
if (accounts == null)
|
||||
return true;
|
||||
|
||||
// Check if the domain is specified
|
||||
foreach(ZPushAccount account in accounts)
|
||||
{
|
||||
if (account.Account.DomainName == gab.Domain)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AccountDiscovered(ZPushAccount zpush)
|
||||
|
@ -41,6 +41,39 @@ namespace Acacia.Features.SyncState
|
||||
|
||||
public class FeatureSyncState : FeatureDisabled, FeatureWithRibbon
|
||||
{
|
||||
|
||||
#region Sync configuration
|
||||
|
||||
[AcaciaOption("Sets the period to check synchronisation state if a sync is in progress.")]
|
||||
public TimeSpan CheckPeriod
|
||||
{
|
||||
get { return GetOption(OPTION_CHECK_PERIOD); }
|
||||
set { SetOption(OPTION_CHECK_PERIOD, value); }
|
||||
}
|
||||
private static readonly TimeSpanOption OPTION_CHECK_PERIOD = new TimeSpanOption("CheckPeriod", new TimeSpan(0, 5, 0));
|
||||
|
||||
[AcaciaOption("Sets the period to check synchronisation state if a sync is in progress and the dialog is open.")]
|
||||
public TimeSpan CheckPeriodDialog
|
||||
{
|
||||
get { return GetOption(OPTION_CHECK_PERIOD_DIALOG); }
|
||||
set { SetOption(OPTION_CHECK_PERIOD_DIALOG, value); }
|
||||
}
|
||||
private static readonly TimeSpanOption OPTION_CHECK_PERIOD_DIALOG = new TimeSpanOption("CheckPeriodDialog", new TimeSpan(0, 1, 0));
|
||||
|
||||
private TimeSpan DelayTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dialogOpen)
|
||||
return CheckPeriodDialog;
|
||||
else
|
||||
return CheckPeriod;
|
||||
}
|
||||
}
|
||||
private bool _dialogOpen;
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: this is largely about progress bars, separate that?
|
||||
private class SyncStateData : DataProvider
|
||||
{
|
||||
@ -152,7 +185,7 @@ namespace Acacia.Features.SyncState
|
||||
public override void Startup()
|
||||
{
|
||||
_state = new SyncStateData(this);
|
||||
_button = RegisterButton(this, "Progress", true, ShowSyncState, ZPushBehaviour.Disable);
|
||||
_button = RegisterButton(this, "Progress", true, ShowSyncState, ZPushBehaviour.None);
|
||||
_button.DataProvider = _state;
|
||||
// Add a sync task to start checking. If this finds it's not fully synchronised, it will check more often
|
||||
Watcher.Sync.AddTask(this, Name, CheckSyncState);
|
||||
@ -306,10 +339,14 @@ namespace Acacia.Features.SyncState
|
||||
DeviceDetails details = deviceService.Execute(new GetDeviceDetailsRequest());
|
||||
|
||||
// Determine the totals
|
||||
details.Calculate();
|
||||
details?.Calculate();
|
||||
|
||||
// And store with the account
|
||||
account.SetFeatureData(this, null, details);
|
||||
|
||||
// If syncing, check again soon.
|
||||
if (details?.IsSyncing == true)
|
||||
Util.Delayed(this, (int)DelayTime.TotalMilliseconds, () => CheckSyncState(account));
|
||||
}
|
||||
|
||||
// Update the total for all accounts
|
||||
@ -340,7 +377,15 @@ namespace Acacia.Features.SyncState
|
||||
|
||||
private void ShowSyncState()
|
||||
{
|
||||
new SyncStateDialog(this).ShowDialog();
|
||||
_dialogOpen = true;
|
||||
try
|
||||
{
|
||||
new SyncStateDialog(this).ShowDialog();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_dialogOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class SyncStateImpl : SyncState
|
||||
@ -362,7 +407,6 @@ namespace Acacia.Features.SyncState
|
||||
_canResync[(int)ResyncOption.Signatures] = _featureSignatures != null;
|
||||
_canResync[(int)ResyncOption.ServerData] = ThisAddIn.Instance.Watcher.Sync.Enabled;
|
||||
_canResync[(int)ResyncOption.Full] = true;
|
||||
Update();
|
||||
}
|
||||
|
||||
public long Done
|
||||
@ -399,14 +443,29 @@ namespace Acacia.Features.SyncState
|
||||
{
|
||||
if (!CanResync(option))
|
||||
return true;
|
||||
_canResync [(int)option] = false;
|
||||
|
||||
switch(option)
|
||||
{
|
||||
case ResyncOption.GAB:
|
||||
// TODO: use completion tracker if not synching
|
||||
_featureGAB.FullResync(null, _accounts);
|
||||
return false;
|
||||
if (IsSyncing)
|
||||
{
|
||||
// Already syncing, resync GAB asynchronously
|
||||
_featureGAB.FullResync(null, _accounts);
|
||||
// Cannot resync again until the dialog is reopened
|
||||
_canResync[(int)ResyncOption.GAB] = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProgressDialog.Execute("GABSync",
|
||||
(ct, tracker) =>
|
||||
{
|
||||
_featureGAB.FullResync(tracker, _accounts);
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
case ResyncOption.Signatures:
|
||||
ProgressDialog.Execute("SignaturesSync",
|
||||
(ct) =>
|
||||
|
@ -50,6 +50,15 @@ namespace Acacia.Features.SyncState
|
||||
// Add the accounts
|
||||
foreach (ZPushAccount account in ThisAddIn.Instance.Watcher.Accounts.GetAccounts())
|
||||
comboAccounts.Items.Add(account);
|
||||
|
||||
// Add a timer to update the UI
|
||||
Timer timer = new Timer();
|
||||
timer.Interval = 2500;
|
||||
timer.Tick += (o, args) =>
|
||||
{
|
||||
UpdateUI();
|
||||
};
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private void ShowHint(object sender, KHintButton.HintEventArgs e)
|
||||
@ -119,6 +128,8 @@ namespace Acacia.Features.SyncState
|
||||
|
||||
private void UpdateUI()
|
||||
{
|
||||
_syncState.Update();
|
||||
|
||||
// Set up the UI
|
||||
foreach (ResyncOption option in Enum.GetValues(typeof(ResyncOption)))
|
||||
{
|
||||
@ -127,7 +138,7 @@ namespace Acacia.Features.SyncState
|
||||
|
||||
if (_syncState.IsSyncing)
|
||||
{
|
||||
textRemaining.Text = _syncState.Remaining.ToString();
|
||||
textRemaining.Text = _syncState.Remaining.ToString() + " / " + _syncState.Total.ToString();
|
||||
progress.Value = (int)(_syncState.Done * 100.0 / _syncState.Total);
|
||||
}
|
||||
else
|
||||
|
@ -168,6 +168,24 @@ namespace Acacia.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The global address book is being synchronised..
|
||||
/// </summary>
|
||||
internal static string GABSync_Label {
|
||||
get {
|
||||
return ResourceManager.GetString("GABSync_Label", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Global Address Book.
|
||||
/// </summary>
|
||||
internal static string GABSync_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("GABSync_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
|
@ -494,4 +494,10 @@
|
||||
<data name="ServerSync_Title" xml:space="preserve">
|
||||
<value>Server data</value>
|
||||
</data>
|
||||
<data name="GABSync_Label" xml:space="preserve">
|
||||
<value>The global address book is being synchronised.</value>
|
||||
</data>
|
||||
<data name="GABSync_Title" xml:space="preserve">
|
||||
<value>Global Address Book</value>
|
||||
</data>
|
||||
</root>
|
@ -89,6 +89,61 @@ namespace Acacia.UI
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
public static ResultType Execute<ResultType>(string resourcePrefix, Func<CancellationToken, CompletionTracker, ResultType> action)
|
||||
{
|
||||
// TODO: merge with above
|
||||
|
||||
Logger.Instance.Info(typeof(ProgressDialog), "Opening");
|
||||
// Determine the UI context, creating a new one if required
|
||||
if (SynchronizationContext.Current == null)
|
||||
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
|
||||
var context = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
|
||||
// Create the dialog, so it is available for the task
|
||||
ProgressDialog dlg = new ProgressDialog();
|
||||
// Set the strings
|
||||
dlg.Text = StringUtil.GetResourceString(resourcePrefix + "_Title");
|
||||
dlg.labelMessage.Text = StringUtil.GetResourceString(resourcePrefix + "_Label");
|
||||
|
||||
// Start the task
|
||||
Exception caught = null;
|
||||
Task<ResultType> task = null;
|
||||
// And close the dialog when done
|
||||
CompletionTracker tracker = new CompletionTracker(() =>
|
||||
{
|
||||
// This extra step is needed to go back into the thread context
|
||||
task.ContinueWith(_ => { dlg._isComplete = true; dlg.DialogResult = DialogResult.OK; }, context);
|
||||
});
|
||||
|
||||
task = Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return action(dlg.cancel.Token, tracker);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
caught = e;
|
||||
return default(ResultType);
|
||||
}
|
||||
},
|
||||
dlg.cancel.Token);
|
||||
dlg.task = task;
|
||||
|
||||
// Show the dialog
|
||||
if (dlg.ShowDialog() != DialogResult.OK)
|
||||
return default(ResultType);
|
||||
|
||||
// Rethrow any exception.
|
||||
// The framework already handles this, but that causes breaks into the debugger
|
||||
if (caught != null)
|
||||
throw caught;
|
||||
|
||||
// Result the result
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
private void ProgressDialog_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (!_isComplete)
|
||||
|
@ -125,7 +125,7 @@ namespace Acacia.ZPush
|
||||
|
||||
private static bool IsCustomFolder(IFolder folder)
|
||||
{
|
||||
return Features.GAB.FeatureGAB.IsGABContactsFolder(folder);
|
||||
return Features.GAB.FeatureGAB.IsGABContactsFolder(folder, null);
|
||||
}
|
||||
|
||||
private static void HideAllFolders(IStore store)
|
||||
|
Loading…
Reference in New Issue
Block a user