diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs index 4eeebf7..bcbfbed 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/FeatureSharedFolders.cs @@ -88,7 +88,7 @@ namespace Acacia.Features.SharedFolders private bool CanManageFolder(MenuItem b, IFolder folder) { - return folder.SyncId?.IsShared == true; + return folder.SyncId?.IsCustom == true; } private void ManageFolder(IFolder folder) @@ -151,7 +151,7 @@ namespace Acacia.Features.SharedFolders // Check that we can get the id SyncId folderId = folder.SyncId; Logger.Instance.Trace(this, "GetSharedFolder1: {0}", folderId); - if (folderId == null || !folderId.IsShared) + if (folderId == null || !folderId.IsCustom) return null; // Get the ZPush account @@ -310,7 +310,7 @@ namespace Acacia.Features.SharedFolders public override bool IsApplicable(IFolder folder) { - if (folder.SyncId != null && folder.SyncId.IsShared) + if (folder.SyncId != null && folder.SyncId.IsCustom) return true; using (IFolder parent = folder.Parent) @@ -354,7 +354,7 @@ namespace Acacia.Features.SharedFolders private void OnSharedFolderDiscovered(IFolder folder) { Logger.Instance.Trace(this, "Shared folder discovered: {0} - {1}", folder.Name, folder.SyncId); - if (folder.SyncId == null || !folder.SyncId.IsShared) + if (folder.SyncId == null || !folder.SyncId.IsCustom) { Logger.Instance.Warning(this, "Local folder created in shared folder, deleting: {0} - {1}", folder.Name, folder.SyncId); // This is a new, locally created folder. Warn and remove @@ -376,7 +376,7 @@ namespace Acacia.Features.SharedFolders private void Folder_BeforeFolderMove(IFolder src, IFolder moveTo, ref bool cancel) { - if (src.SyncId?.IsShared == true || moveTo.SyncId?.IsShared == true) + if (src.SyncId?.IsCustom == true || moveTo.SyncId?.IsCustom == true) { // Suppress any move of or into a shared folder Logger.Instance.Warning(this, "Shared folder move: {0} - {1}", src.Name, moveTo.Name); @@ -399,7 +399,7 @@ namespace Acacia.Features.SharedFolders private void CheckSharedFolderRename(IFolder folder) { - if (folder.SyncId != null && folder.SyncId.IsShared) + if (folder.SyncId != null && folder.SyncId.IsCustom) { string originalName = (string)folder.GetProperty(OutlookConstants.PR_ZPUSH_NAME); // The folder.name property is sometimes cached, check against the MAPI property diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/RemindersQuery.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/RemindersQuery.cs index dce9cf5..f6d4966 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/RemindersQuery.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/RemindersQuery.cs @@ -17,7 +17,8 @@ namespace Acacia.Features.SharedFolders private readonly FeatureSharedFolders _feature; private readonly IFolder _folder; private SearchQuery _queryRoot; - private SearchQuery.Or _queryCustom; + private SearchQuery.Or _queryCustomShared; + private SearchQuery.Or _queryCustomConfigured; private bool _queryCustomModified; public RemindersQuery(FeatureSharedFolders feature, IStore store) @@ -28,7 +29,7 @@ namespace Acacia.Features.SharedFolders public bool Open() { - if (_queryCustom != null) + if (_queryCustomShared != null && _queryCustomConfigured != null) return true; try { @@ -39,30 +40,34 @@ namespace Acacia.Features.SharedFolders SearchQuery.And root = (SearchQuery.And)_queryRoot; // TODO: more strict checking of query - if (root.Operands.Count == 3) + if (root.Operands.Count == 5) { - this._queryCustom = root.Operands.ElementAt(2) as SearchQuery.Or; - if (this._queryCustom != null) + this._queryCustomShared = root.Operands.ElementAt(2) as SearchQuery.Or; + this._queryCustomConfigured = root.Operands.ElementAt(3) as SearchQuery.Or; + if (this._queryCustomShared != null) { // TODO: check property test return true; } } + else if (root.Operands.Count == 3) + { + // KOE-98 introduced also checking of G and C prefixes, which are not yet present + _queryCustomShared = root.Operands.ElementAt(2) as SearchQuery.Or; + } // We have the root, but not the custom query. Create it. Logger.Instance.Debug(this, "Creating custom query"); - _queryCustom = new SearchQuery.Or(); - - // Add the prefix exclusion for shared folders - _queryCustom.Add( - new SearchQuery.Not( - new SearchQuery.PropertyContent( - PROP_FOLDER, SearchQuery.ContentMatchOperation.Prefix, SearchQuery.ContentMatchModifiers.None, "S" - ) + if (_queryCustomShared == null) + _queryCustomShared = AddCustomQuery(root, "S"); + _queryCustomConfigured = AddCustomQuery(root, "C"); + // Add the G (GAB) exclusion. Folders will never have a flag with this prefix, so it's simpler + root.Operands.Add(new SearchQuery.Not( + new SearchQuery.PropertyContent( + PROP_FOLDER, SearchQuery.ContentMatchOperation.Prefix, SearchQuery.ContentMatchModifiers.None, "G" ) - ); + )); - root.Operands.Add(_queryCustom); Logger.Instance.Debug(this, "Modified query:\n{0}", root.ToString()); // Store it FolderQuery = root; @@ -72,7 +77,24 @@ namespace Acacia.Features.SharedFolders { Logger.Instance.Error(this, "Exception in Open: {0}", e); } - return _queryCustom != null; + return _queryCustomShared != null && _queryCustomConfigured != null; + } + + private SearchQuery.Or AddCustomQuery(SearchQuery.And root, string prefix) + { + SearchQuery.Or custom = new SearchQuery.Or(); + + // Add the prefix exclusion + custom.Add( + new SearchQuery.Not( + new SearchQuery.PropertyContent( + PROP_FOLDER, SearchQuery.ContentMatchOperation.Prefix, SearchQuery.ContentMatchModifiers.None, prefix + ) + ) + ); + + root.Operands.Add(custom); + return custom; } public string LogContextId @@ -117,15 +139,28 @@ namespace Acacia.Features.SharedFolders public void UpdateReminders(SyncId folderId, bool wantReminders) { - Logger.Instance.Trace(this, "Setting reminders for folder {0}: {1}", wantReminders, folderId); + Logger.Instance.Trace(this, "Setting reminders for folder {0}: {1} ({2})", wantReminders, folderId, folderId?.Kind); + switch(folderId.Kind) + { + case SyncKind.Configured: + UpdateReminders(_queryCustomConfigured, folderId, wantReminders); + break; + case SyncKind.Shared: + UpdateReminders(_queryCustomShared, folderId, wantReminders); + break; + } + } + + private void UpdateReminders(SearchQuery.Or query, SyncId folderId, bool wantReminders) + { string prefix = MakeFolderPrefix(folderId); if (prefix == null) return; // Find existing - for (int i = 0; i < _queryCustom.Operands.Count;) + for (int i = 0; i < query.Operands.Count;) { - SearchQuery.PropertyContent element = _queryCustom.Operands[i] as SearchQuery.PropertyContent; + SearchQuery.PropertyContent element = query.Operands[i] as SearchQuery.PropertyContent; if (element != null && prefix == (string)element.Content) { Logger.Instance.Trace(this, "Found at {0}: {1}", i, folderId); @@ -134,7 +169,8 @@ namespace Acacia.Features.SharedFolders return; // Otherwise remove it. Still continue looking for others, just in case of duplicates - _queryCustom.Operands.RemoveAt(i); + query.Operands.RemoveAt(i); + _queryCustomModified = true; } else ++i; } @@ -143,7 +179,7 @@ namespace Acacia.Features.SharedFolders if (wantReminders) { Logger.Instance.Trace(this, "Adding reminders for {0}", folderId); - _queryCustom.Operands.Add(new SearchQuery.PropertyContent( + query.Operands.Add(new SearchQuery.PropertyContent( PROP_FOLDER, SearchQuery.ContentMatchOperation.Prefix, SearchQuery.ContentMatchModifiers.None, prefix )); _queryCustomModified = true; @@ -152,19 +188,37 @@ namespace Acacia.Features.SharedFolders public void RemoveStaleReminders(IEnumerable wanted) { - // Collect the valid prefixes - HashSet prefixes = new HashSet(); + // Group the valid prefixes on type + HashSet prefixesS = new HashSet(); + HashSet prefixesC = new HashSet(); foreach (SyncId id in wanted) { string prefix = MakeFolderPrefix(id); if (prefix != null) - prefixes.Add(prefix); + { + switch (id.Kind) + { + case SyncKind.Configured: + prefixesC.Add(prefix); + break; + case SyncKind.Shared: + prefixesS.Add(prefix); + break; + } + } } + // Update the queries + RemoveStaleReminders(prefixesS, _queryCustomShared); + RemoveStaleReminders(prefixesC, _queryCustomConfigured); + } + + private void RemoveStaleReminders(ISet prefixes, SearchQuery.Or query) + { // Remove all operands for which we do not want the prefix - for (int i = 0; i < _queryCustom.Operands.Count;) + for (int i = 0; i < query.Operands.Count;) { - SearchQuery.PropertyContent element = _queryCustom.Operands[i] as SearchQuery.PropertyContent; + SearchQuery.PropertyContent element = query.Operands[i] as SearchQuery.PropertyContent; if (element != null) { string prefix = (string)element.Content; @@ -175,7 +229,7 @@ namespace Acacia.Features.SharedFolders } Logger.Instance.Trace(this, "Unwanted prefix at {0}: {1}", i, prefix); - _queryCustom.Operands.RemoveAt(i); + query.Operands.RemoveAt(i); _queryCustomModified = true; } else ++i; @@ -186,7 +240,7 @@ namespace Acacia.Features.SharedFolders { // Sanity check. The check for shared folders also excludes any weird ids; e.g. if permissions are wrong, // this will not be a sync id, but a backend id. - if (folderId == null || !folderId.IsShared) + if (folderId == null || !folderId.IsCustom) return null; return folderId.ToString() + ":"; } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushTypes.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushTypes.cs index fbbeadc..a5bd0ad 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushTypes.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushTypes.cs @@ -69,6 +69,14 @@ namespace Acacia.ZPush #endregion } + public enum SyncKind + { + Normal, + Shared, + Configured, + GAB + } + public class SyncId : ZPushId { public static readonly SyncId NONE = new SyncId("0"); @@ -76,10 +84,24 @@ namespace Acacia.ZPush public SyncId(string id) : base(id) { } public SyncId(int id) : base(id) { } + + public SyncKind Kind + { + get + { + if (_id.StartsWith("S")) + return SyncKind.Shared; + if (_id.StartsWith("C")) + return SyncKind.Configured; + if (_id.StartsWith("G")) + return SyncKind.GAB; + return SyncKind.Normal; + } + } /// /// Checks if this is a SyncId for a shared folders /// - public bool IsShared { get { return _id.StartsWith("S") || _id.StartsWith("C") || _id.StartsWith("G"); } } + public bool IsCustom { get { return Kind != SyncKind.Normal; } } #region Standard overrides