Skip to content

Commit

Permalink
Merge branch 'feature/issue-1989/g-excl-warn' into release
Browse files Browse the repository at this point in the history
Closes #1989
  • Loading branch information
phw198 committed Nov 3, 2024
2 parents 6e58943 + 68a04b5 commit 652c275
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 45 deletions.
6 changes: 6 additions & 0 deletions src/OutlookGoogleCalendarSync/Console/Console.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ private void console_DocumentCompleted(object sender, WebBrowserDocumentComplete
private void console_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
if (!Forms.Main.Instance.Visible) return;

if (e.Url.Scheme != "about") {
Helper.OpenBrowser(e.Url.OriginalString);
e.Cancel = true;
return;
}

navigationStatus = NavigationStatus.navigating;
log.UltraFine("Console navigating.");
}
Expand Down
88 changes: 64 additions & 24 deletions src/OutlookGoogleCalendarSync/Google/GoogleCalendar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public Calendar() { }
public Ogcs.Google.Authenticator Authenticator;

/// <summary>Google Events excluded through user config <Event.Id, Appt.EntryId></summary>
public Dictionary<String, String> ExcludedByColour { get; private set; }
public List<String> ExcludedByConfig { get; set; }
/// <summary>Google Events excluded by colour through user config <Event.Id, Appt.EntryId></summary>
public Dictionary<String, String> ExcludedByColour { get; set; }

private Ogcs.Google.EventColour colourPalette;

Expand Down Expand Up @@ -264,9 +266,12 @@ public Event GetCalendarEntry(String eventId) {
}
}

if (request != null)
return request;
else
if (request != null) {
SettingsStore.Calendar profile = Settings.Profile.InPlay();
List<Event> evList = new List<Event>() { request };
applyExclusions(ref evList, profile);
return evList.FirstOrDefault();
} else
throw new System.Exception("Returned null");
} catch (System.Exception ex) {
if (ex is ApplicationException) throw;
Expand All @@ -280,9 +285,8 @@ public List<Event> GetCalendarEntriesInRange() {
return GetCalendarEntriesInRange(profile.SyncStart, profile.SyncEnd);
}

public List<Event> GetCalendarEntriesInRange(System.DateTime from, System.DateTime to) {
public List<Event> GetCalendarEntriesInRange(System.DateTime from, System.DateTime to, Boolean suppressAdvisories = false) {
List<Event> result = new List<Event>();
ExcludedByColour = new Dictionary<String, String>();
Events request = null;
String pageToken = null;
Int16 pageNum = 1;
Expand Down Expand Up @@ -354,13 +358,51 @@ public List<Event> GetCalendarEntriesInRange(System.DateTime from, System.DateTi
result = result.Except(endsOnSyncStart).ToList();
}

List<Event> allExcluded = applyExclusions(ref result, profile);
if (allExcluded.Count > 0) {
if (!suppressAdvisories) {
String filterWarning = "Due to your OGCS Google settings, " + (result.Count == 0 ? "all" : allExcluded.Count) + " Google items have been filtered out" + (result.Count == 0 ? "!" : ".");
Forms.Main.Instance.Console.Update(filterWarning, Console.Markup.config, newLine: false, notifyBubble: (result.Count == 0));

filterWarning = "";
if (profile.SyncDirection.Id != Sync.Direction.OutlookToGoogle.Id && ExcludedByColour.Count > 0 && profile.DeleteWhenColourExcluded) {
filterWarning = "If they exist in Outlook, they may get deleted. To avoid deletion, uncheck \"Delete synced items if excluded\".";
if (!profile.DisableDelete) {
filterWarning += " Recover unintentional deletions from the Outlook 'Deleted Items' folder.";
if (profile.ConfirmOnDelete)
filterWarning += "<p style='margin-top: 8px;'>If prompted to confirm deletion and you opt <i>not</i> to delete them, this will reoccur every sync. " +
"Consider assigning an excluded category to those items in Outlook.</p>" +
"<p style='margin-top: 8px;'>See the wiki for tips if needing to <a href='https://github.com/phw198/OutlookGoogleCalendarSync/wiki/FAQs#duplicates-due-to-colourcategory-exclusion'>resolve duplicates</a>.</p>";
}
}
if (!String.IsNullOrEmpty(filterWarning))
Forms.Main.Instance.Console.Update(filterWarning, Console.Markup.warning, newLine: false);
}
if (profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id) {
for (int g = 0; g < allExcluded.Count; g++) {
Event ev = allExcluded[g];
if (CustomProperty.ExistAnyOutlookIDs(ev)) {
log.Debug("Previously synced Google item is now excluded. Removing Outlook metadata.");
//We don't want them getting automatically deleted if brought back in scope; better to create possible duplicate
CustomProperty.RemoveOutlookIDs(ref ev);
UpdateCalendarEntry_save(ref ev);
}
}
}
}

log.Fine("Filtered down to " + result.Count);
return result;
}

private List<Event> applyExclusions(ref List<Event> result, SettingsStore.Calendar profile) {
List<Event> colour = new();
List<Event> availability = new();
List<Event> allDays = new();
List<Event> privacy = new();
List<Event> declined = new();
List<Event> subject = new();
List<Event> declined = new();
List<Event> goals = new();
List<Event> colour = new();

//Colours
if (profile.ColoursRestrictBy == SettingsStore.Calendar.RestrictBy.Include) {
Expand All @@ -380,11 +422,12 @@ public List<Event> GetCalendarEntriesInRange(System.DateTime from, System.DateTi
log.Debug(colour.Count + " Google items contain a colour that is filtered out.");
}
foreach (Event ev in colour) {
ExcludedByColour.Add(ev.Id, CustomProperty.Get(ev, CustomProperty.MetadataId.oEntryId));
if (!ExcludedByColour.ContainsKey(ev.Id))
ExcludedByColour.Add(ev.Id, CustomProperty.Get(ev, CustomProperty.MetadataId.oEntryId));
}
result = result.Except(colour).ToList();

//Availability, Privacy
//Availability, All-Days, Privacy, Subject
if (profile.SyncDirection.Id != Sync.Direction.OutlookToGoogle.Id) { //Sync direction means G->O will delete previously synced all-days
if (profile.ExcludeFree) {
availability = result.Where(ev => String.IsNullOrEmpty(ev.RecurringEventId) && ev.Transparency == "transparent").ToList();
Expand Down Expand Up @@ -437,19 +480,12 @@ public List<Event> GetCalendarEntriesInRange(System.DateTime from, System.DateTi
}
}

if (profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id) {
List<Event> allExcluded = colour.Concat(availability).Concat(allDays).Concat(privacy).Concat(subject).Concat(declined).Concat(goals).ToList();
for (int g = 0; g < allExcluded.Count(); g++) {
Event ev = allExcluded[g];
if (CustomProperty.ExistAnyOutlookIDs(ev)) {
log.Debug("Previously synced Google item is now excluded. Removing Outlook metadata.");
CustomProperty.RemoveOutlookIDs(ref ev);
UpdateCalendarEntry_save(ref ev);
}
}
List<Event> allExcluded = colour.Concat(availability).Concat(allDays).Concat(privacy).Concat(subject).Concat(declined).Concat(goals).ToList();
foreach (Event ev in allExcluded) {
if (!ExcludedByConfig.Contains(ev.Id))
ExcludedByConfig.Add(ev.Id);
}

return result;
return allExcluded;
}

/// <summary>
Expand Down Expand Up @@ -1200,8 +1236,12 @@ private Boolean deleteCalendarEntry(Event ev) {
MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) {
doDelete = false;
if (Sync.Engine.Calendar.Instance.Profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id && CustomProperty.ExistAnyOutlookIDs(ev)) {
CustomProperty.RemoveOutlookIDs(ref ev);
UpdateCalendarEntry_save(ref ev);
if (Ogcs.Outlook.Calendar.Instance.ExcludedByCategory.ContainsKey(CustomProperty.Get(ev, CustomProperty.MetadataId.oEntryId))) {
log.Fine("Refrained from removing Outlook metadata from Event; avoids duplication back into Outlook.");
} else {
CustomProperty.RemoveOutlookIDs(ref ev);
UpdateCalendarEntry_save(ref ev);
}
}
Forms.Main.Instance.Console.Update("Not deleted: " + eventSummary, anonSummary?.Prepend("Not deleted: "), Console.Markup.calendar);
} else {
Expand Down
50 changes: 32 additions & 18 deletions src/OutlookGoogleCalendarSync/Outlook/OutlookCalendar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public enum Service {
public Outlook.EphemeralProperties EphemeralProperties = new EphemeralProperties();

/// <summary>Outlook Appointment excluded through user config <Appt.EntryId, Event.Id></Appt.EntryId></summary>
public Dictionary<String, String> ExcludedByCategory { get; private set; }
public Dictionary<String, String> ExcludedByCategory { get; set; }

public Calendar() {
InstanceConnect = true;
Expand Down Expand Up @@ -119,7 +119,7 @@ public List<AppointmentItem> GetCalendarEntriesInRange(SettingsStore.Calendar pr
Ogcs.Exception.LogAsFail(ref ex);
String wikiURL = "https://github.com/phw198/OutlookGoogleCalendarSync/wiki/Resolving-Outlook-Error-Messages#one-or-more-items-in-the-folder-you-synchronized-do-not-match";
ex.Data.Add("OGCS", ex.Message + "<br/>Please view the wiki for suggestions on " +
"<a href='" + wikiURL + "' target='_blank'>how to resolve conflicts</a> within your Outlook account.");
"<a href='" + wikiURL + "'>how to resolve conflicts</a> within your Outlook account.");
if (!suppressAdvisories && Ogcs.Extensions.MessageBox.Show("Your Outlook calendar contains conflicts that need resolving in order to sync successfully.\r\nView the wiki for advice?",
"Outlook conflicts exist", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
Helper.OpenBrowser(wikiURL);
Expand All @@ -144,7 +144,6 @@ public List<AppointmentItem> FilterCalendarEntries(SettingsStore.Calendar profil

List<AppointmentItem> result = new List<AppointmentItem>();
Items OutlookItems = null;
ExcludedByCategory = new();

if (profile is null)
profile = Settings.Profile.InPlay();
Expand Down Expand Up @@ -274,6 +273,7 @@ public List<AppointmentItem> FilterCalendarEntries(SettingsStore.Calendar profil
} finally {
if (filtered && profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id && CustomProperty.ExistAnyGoogleIDs(ai)) {
log.Debug("Previously synced Outlook item is now excluded. Removing Google metadata.");
//We don't want them getting automatically deleted if brought back in scope; better to create possible duplicate
CustomProperty.RemoveGoogleIDs(ref ai);
ai.Save();
}
Expand All @@ -282,20 +282,30 @@ public List<AppointmentItem> FilterCalendarEntries(SettingsStore.Calendar profil
result.Add(ai);
}
}
if (!suppressAdvisories) {
if (availabilityFiltered > 0) log.Info(availabilityFiltered + " Outlook items excluded due to availability.");
if (allDayFiltered > 0) log.Info(allDayFiltered + " Outlook all day items excluded.");
if (ExcludedByCategory.Count > 0) log.Info(ExcludedByCategory.Count + " Outlook items contain a category that is filtered out.");
if (subjectFiltered > 0) log.Info(subjectFiltered + " Outlook items with subject containing '" + profile.ExcludeSubjectText + "' filtered out.");
if (responseFiltered > 0) log.Info(responseFiltered + " Outlook items are invites not yet responded to.");

if ((availabilityFiltered + allDayFiltered + ExcludedByCategory.Count + subjectFiltered + responseFiltered) > 0) {
if (result.Count == 0)
Forms.Main.Instance.Console.Update("Due to your OGCS Outlook settings, all Outlook items have been filtered out!", Console.Markup.config, notifyBubble: true);
else if (profile.SyncDirection.Id == Sync.Direction.GoogleToOutlook.Id)
Forms.Main.Instance.Console.Update("Due to your OGCS Outlook settings, Outlook items have been filtered out. " +
"If they exist in Google, they may be synced and appear as \"duplicates\".", Console.Markup.config);
if (availabilityFiltered > 0) log.Info(availabilityFiltered + " Outlook items excluded due to availability.");
if (allDayFiltered > 0) log.Info(allDayFiltered + " Outlook all day items excluded.");
if (ExcludedByCategory.Count > 0) log.Info(ExcludedByCategory.Count + " Outlook items contain a category that is filtered out.");
if (subjectFiltered > 0) log.Info(subjectFiltered + " Outlook items with subject containing '" + profile.ExcludeSubjectText + "' filtered out.");
if (responseFiltered > 0) log.Info(responseFiltered + " Outlook items are invites not yet responded to.");

Int32 allExcluded = availabilityFiltered + allDayFiltered + ExcludedByCategory.Count + subjectFiltered + responseFiltered;
if (allExcluded > 0 && !suppressAdvisories) {
String filterWarning = "Due to your OGCS Outlook settings, " + (result.Count == 0 ? "all" : allExcluded) + " Outlook items have been filtered out" + (result.Count == 0 ? "!" : ".");
Forms.Main.Instance.Console.Update(filterWarning, Console.Markup.config, newLine: false, notifyBubble: (result.Count == 0));

filterWarning = "";
if (profile.SyncDirection.Id != Sync.Direction.GoogleToOutlook.Id && ExcludedByCategory.Count > 0 && profile.DeleteWhenCategoryExcluded) {
filterWarning = "If they exist in Google, they may get deleted. To avoid deletion, uncheck \"Delete synced items if excluded\".";
if (!profile.DisableDelete) {
filterWarning += " Recover unintentional deletions from the <a href='https://calendar.google.com/calendar/u/0/r/trash'>Google 'Bin'</a>.";
if (profile.ConfirmOnDelete)
filterWarning += "<p style='margin-top: 8px;'>If prompted to confirm deletion and you opt <i>not</i> to delete them, this will reoccur every sync. " +
"Consider assigning an excluded colour to those items in Google.</p>" +
"<p style='margin-top: 8px;'>See the wiki for tips if needing to <a href='https://github.com/phw198/OutlookGoogleCalendarSync/wiki/FAQs#duplicates-due-to-colourcategory-exclusion'>resolve duplicates</a>.</p>";
}
}
if (!String.IsNullOrEmpty(filterWarning))
Forms.Main.Instance.Console.Update(filterWarning, Console.Markup.warning, newLine: false);
}
}
log.Fine("Filtered down to " + result.Count);
Expand Down Expand Up @@ -853,8 +863,12 @@ private Boolean deleteCalendarEntry(AppointmentItem ai) {
MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) {
doDelete = false;
if (Sync.Engine.Calendar.Instance.Profile.SyncDirection.Id == Sync.Direction.Bidirectional.Id && CustomProperty.ExistAnyGoogleIDs(ai)) {
CustomProperty.RemoveGoogleIDs(ref ai);
ai.Save();
if (Ogcs.Google.Calendar.Instance.ExcludedByColour.ContainsKey(CustomProperty.Get(ai, CustomProperty.MetadataId.gEventID))) {
log.Fine("Refrained from removing Google metadata from Appointment; avoids duplication back into Google.");
} else {
CustomProperty.RemoveGoogleIDs(ref ai);
ai.Save();
}
}
Forms.Main.Instance.Console.Update("Not deleted: " + eventSummary, anonSummary?.Prepend("Not deleted: "), Console.Markup.calendar);
} else {
Expand Down
5 changes: 4 additions & 1 deletion src/OutlookGoogleCalendarSync/Recurrence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,14 @@ public Event GetGoogleMasterEvent(AppointmentItem ai) {
events.Add(ev);
haveMatchingEv = true;
log.Fine("Found single hard-matched Event.");
} else if (Ogcs.Google.Calendar.Instance.ExcludedByConfig.Contains(googleIdValue)) {
log.Debug("The master Google Event has been excluded by config.");
return null;
}
}
}
if (!haveMatchingEv) {
events = Ogcs.Google.Calendar.Instance.GetCalendarEntriesInRange(ai.Start.Date, ai.Start.Date.AddDays(1));
events = Ogcs.Google.Calendar.Instance.GetCalendarEntriesInRange(ai.Start.Date, ai.Start.Date.AddDays(1), true);
if (Sync.Engine.Calendar.Instance.Profile.SyncDirection.Id != Sync.Direction.GoogleToOutlook.Id) {
List<AppointmentItem> ais = new List<AppointmentItem>();
ais.Add(ai);
Expand Down
Loading

0 comments on commit 652c275

Please sign in to comment.