private static async Task UpdatePrimaryTileNotificationsBlocking(AccountDataItem account, AccountDataStore data) { try { Debug.WriteLine("Updating Primary Tile"); TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication(); if (account == null || account.MainTileSettings.IsDisabled()) { ClearScheduledNotifications(tileUpdater); tileUpdater.Clear(); return; } DateTime todayInLocal = DateTime.Today; var allUpcoming = await getAllUpcomingBlocking(account, data, DateTime.SpecifyKind(todayInLocal, DateTimeKind.Utc), account.MainTileSettings); UpdateUpcomingTile(tileUpdater, allUpcoming, todayInLocal, UpcomingTileType.PrimaryTile, account.MainTileSettings); } catch (Exception ex) { if (!UWPExceptionHelper.TrackIfNotificationsIssue(ex, "Tiles")) { throw ex; } } }
private static async Task UpdateTileAsync(SecondaryTile tile, AccountDataItem account, AccountDataStore data, Guid classId) { try { DateTime todayInLocal = DateTime.Today; // Get the class tile settings ClassTileSettings settings = await account.GetClassTileSettings(classId); ClassData classData = await LoadDataAsync(data, classId, DateTime.SpecifyKind(todayInLocal, DateTimeKind.Utc), settings); // If classData was null, that means the class wasn't found, so we should delete the tile if (classData == null) { await tile.RequestDeleteAsync(); return; } bool changed = false; string desiredName = GetTrimmedClassName(classData.Class.Name); Color desiredColor; if (settings.CustomColor != null) desiredColor = ColorTools.GetColor(settings.CustomColor); else desiredColor = ColorTools.GetColor(classData.Class.Color); if (!tile.DisplayName.Equals(desiredName)) { changed = true; tile.DisplayName = desiredName; } if (!tile.VisualElements.BackgroundColor.Equals(desiredColor)) { changed = true; tile.VisualElements.BackgroundColor = desiredColor; } if (changed) await tile.UpdateAsync(); var updater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(tile.TileId); UpdateUpcomingTile(updater, classData.AllUpcoming, todayInLocal, UpcomingTileType.ClassTile, settings); } catch (Exception ex) { if (!UWPExceptionHelper.TrackIfNotificationsIssue(ex, "Tiles")) { throw ex; } } }
private static async Task UpdateScheduleTile(string tileId, AccountDataItem account, AccountDataStore data) { try { if (!SecondaryTile.Exists(tileId)) { return; } Debug.WriteLine("Updating Secondary Schedule Tile"); TileUpdater updater; try { updater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(tileId); } catch { return; } TileHelper.ClearScheduledNotifications(updater); bool sentNotification = false; var notifications = await GenerateTileNotificationContentsAsync(account); foreach (var n in notifications) { Schedule(updater, n.Content, n.DeliveryTime ?? DateTime.Now, n.ExpirationTime); sentNotification = true; } if (!sentNotification) { updater.Clear(); } } catch (Exception ex) { if (!UWPExceptionHelper.TrackIfNotificationsIssue(ex, "Tiles") && !UWPExceptionHelper.TrackIfElementNotFound(ex, "Tiles")) { throw ex; } } }
protected override Task ActuallyClearReminders(Guid localAccountId) { try { ClearReminders(localAccountId, CancellationToken.None); } catch (Exception ex) { if (UWPExceptionHelper.TrackIfNotificationsIssue(ex, nameof(ActuallyClearReminders))) { } else { TelemetryExtension.Current?.TrackException(ex); Debug.WriteLine("ClearReminders failed - " + ex.ToString()); } } return(Task.FromResult(true)); }
private static void RegisterRawPushBackgroundTask() { try { var builder = CreateBackgroundTaskBuilder("RawPushBackgroundTask"); // Trigger on raw push received builder.SetTrigger(new PushNotificationTrigger()); // Make sure internet available when triggered builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable)); builder.Register(); } catch (Exception ex) { if (!UWPExceptionHelper.TrackIfNotificationsIssue(ex, nameof(RegisterRawPushBackgroundTask))) { TelemetryExtension.Current?.TrackException(ex); } } }
/// <summary> /// Runs on a new thread /// </summary> /// <param name="account"></param> /// <param name="data"></param> protected override async Task ActuallyResetReminders(AccountDataItem account, AccountDataStore data) { try { await System.Threading.Tasks.Task.Run(async delegate { await ResetReminders(account, CancellationToken.None); }); } catch (OperationCanceledException) { } catch (Exception ex) { if (UWPExceptionHelper.TrackIfNotificationsIssue(ex, "ResetReminders")) { } else { TelemetryExtension.Current?.TrackException(ex); Debug.WriteLine("ResetReminders failed - " + ex.ToString()); } } }
/// <summary> /// /// </summary> /// <param name="updater"></param> /// <param name="allUpcoming">This list will be manipulated. Should already be sorted.</param> /// <param name="todayInLocal"></param> /// <param name="type"></param> internal static void UpdateUpcomingTile(TileUpdater updater, List <BaseViewItemHomeworkExam> allUpcoming, DateTime todayInLocal, UpcomingTileType type, BaseUpcomingTileSettings tileSettings) { try { // Clear all scheduled notifications ClearScheduledNotifications(updater); List <ItemsOnDay> groupedByDay = GroupByDay(allUpcoming); bool veryFirst = true; DateTime today = todayInLocal; const int daysInAdvance = 5; for (int i = 0; i < daysInAdvance; i++, today = today.AddDays(1)) { DateTime todayAsUtc = DateTime.SpecifyKind(today, DateTimeKind.Utc); // Remove any exams that are past "today" for (int x = 0; x < groupedByDay.Count; x++) { groupedByDay[x].Items.RemoveAll(item => item is ViewItemExam && item.Date < today); if (groupedByDay[x].Items.Count == 0) { groupedByDay.RemoveAt(x); x--; } } DateTime dateToStartFrom = tileSettings.GetDateToStartDisplayingOn(todayAsUtc); // Remove any day groups that are older than the user's chosen max date range to display while (groupedByDay.Count > 0 && groupedByDay[0].DateInUtc < dateToStartFrom) { groupedByDay.RemoveAt(0); } // If there's a today group Dictionary <Guid, DateTime> identifiersAndEndTimes = new Dictionary <Guid, DateTime>(); var todayGroup = groupedByDay.FirstOrDefault(g => g.DateInUtc == todayAsUtc); if (todayGroup != null) { // That means we'll need to check if there's exams/events, and if so, we need to update the tile // after the event is over, rather than waiting till the day is over // First we need to create a mapping of the item end times and their indexes, because we need to make sure that we're removing // in order of the earliest end times (right now items are sorted by their start times, so not necessarily correct order based on end times) // We also need to be aware that an event could potentially span multiple days... foreach (var item in todayGroup.Items) { // We ignore "all day" items which end at 11:59:59 DateTime endTime; if (item is ViewItemExam && item.TryGetEndDateWithTime(out endTime) && endTime.TimeOfDay != new TimeSpan(23, 59, 59)) { identifiersAndEndTimes[item.Identifier] = endTime; } } // Remove any events that have already expired (so that the first update doesn't include them) //if (veryFirst) //{ // while (true) // { // if (identifiersAndEndTimes.Count > 0) // { // DateTime minEndTime = identifiersAndEndTimes.Values.Min(); // // If it's already expired, we remove it // if (minEndTime < DateTime.Now) // { // Guid[] identifiersToRemove = identifiersAndEndTimes.Where(p => p.Value == minEndTime).Select(p => p.Key).ToArray(); // foreach (var id in identifiersToRemove) // { // identifiersAndEndTimes.Remove(id); // } // // Remove those events // todayGroup.Items.RemoveAll(x => identifiersToRemove.Contains(x.Identifier)); // // If we've removed all for that day // if (todayGroup.Items.Count == 0) // { // // Remove the group // groupedByDay.Remove(todayGroup); // } // } // } // break; // } //} } DateTime deliveryTime = today; do { if (deliveryTime.Date != today.Date) { // If an event ended up spanning multiple days causing delivery time to be past today, we just won't add it. // In the future when we add support for multiple day events, we'll have to actually handle this... otherwise when the // event expires, the tile won't update correctly on that future day. break; } // On all items but the last, we use the friendly date XmlDocument tile = GenerateUpcomingTileNotificationContent( groupedByDay: groupedByDay, todayAsUtc: todayAsUtc, useFriendlyDates: i != daysInAdvance - 1, type: type); if (tile == null) { if (veryFirst) { updater.Clear(); } return; } DateTime thisDeliveryTime = deliveryTime; DateTime expirationTime = today.AddDays(1); bool hasAdditionalOnThisDay = false; // Pick off earliest ending time if there are any left if (identifiersAndEndTimes.Count > 0) { DateTime minEndTime = identifiersAndEndTimes.Values.Min(); Guid[] identifiersToRemove = identifiersAndEndTimes.Where(p => p.Value == minEndTime).Select(p => p.Key).ToArray(); foreach (var id in identifiersToRemove) { identifiersAndEndTimes.Remove(id); } // Assign the expiration time and the next delivery time to be this end time if (minEndTime > deliveryTime) { expirationTime = minEndTime; deliveryTime = minEndTime; // Setting this for the NEXT notification } // Remove those events todayGroup.Items.RemoveAll(x => identifiersToRemove.Contains(x.Identifier)); // If we've removed all for that day if (todayGroup.Items.Count == 0) { // Remove the group groupedByDay.Remove(todayGroup); } // Otherwise else { // We have more on this day that we'll have to repeat the loop for hasAdditionalOnThisDay = true; } } // If we don't have additional on this day, we can remove today since we're done with it, // which will ensure we correctly set expiration time if there's nothing else left if (!hasAdditionalOnThisDay && todayGroup != null) { groupedByDay.Remove(todayGroup); } if (veryFirst || thisDeliveryTime < DateTime.Now.AddSeconds(5)) { TileNotification currNotif = new TileNotification(tile); // Only assign expiration time if we have no items left if (groupedByDay.Count == 0) { currNotif.ExpirationTime = expirationTime; } updater.Update(currNotif); veryFirst = false; } else { ScheduledTileNotification s = new ScheduledTileNotification(tile, thisDeliveryTime); // Only assign expiration time if we have no items left if (groupedByDay.Count == 0) { s.ExpirationTime = expirationTime; } updater.AddToSchedule(s); } if (!hasAdditionalOnThisDay) { break; } } while (true); } } catch (Exception ex) { if (!UWPExceptionHelper.TrackIfNotificationsIssue(ex, "Tiles")) { throw ex; } } }