private static DateTime GetDayBeforeReminderTime(DateTime date, AccountDataItem account, IEnumerable <ViewItemSchedule> allSchedules) { date = DateTime.SpecifyKind(date.Date, DateTimeKind.Local); //if they're using custom end times if (account.CustomEndTimes.ContainsKey(date.DayOfWeek)) { return(date.Add(account.CustomEndTimes[date.DayOfWeek]).AddMinutes(10)); } PowerPlannerSending.Schedule.Week week = account.GetWeekOnDifferentDate(date); //otherwise get all the schedules IEnumerable <ViewItemSchedule> schedules; schedules = allSchedules.Where(i => i.DayOfWeek == date.DayOfWeek && (i.ScheduleWeek == week || i.ScheduleWeek == PowerPlannerSending.Schedule.Week.BothWeeks)); // If there aren't any schedules on that day if (!schedules.Any()) { return(date.AddHours(15)); // 3:00 PM is default time for day before reminders } return(date.Add(schedules.Max(i => i.EndTime.TimeOfDay)).AddMinutes(10)); //day before reminders show up 10 mins after last class }
protected override async Task ActuallyResetReminders(AccountDataItem account, AccountDataStore data) { try { // If reminders disabled, do nothing if (!account.RemindersDayBefore && !account.RemindersDayOf) { return; } await Task.Run(async delegate { // This gets called whenever changes are made in the account's data. AgendaViewItemsGroup agendaItems = await GetAgendaViewItemsGroup(account, DateTime.Now); // If no current semester, or no items, just clear all if (agendaItems == null || agendaItems.Items.Count == 0) { await RemoveAllNotificationsAsync(account.LocalAccountId); return; } DateTime now = DateTime.Now; await UpdateScheduledNotificationsAsync(account, agendaItems, now); }); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }
private void AccountsManager_OnAccountAdded(object sender, AccountDataItem e) { Dispatcher.Run(delegate { Accounts.Add(e); }); }
public Task ResetAllRemindersAsync(AccountDataItem account) { // If they weren't enabled, we won't do anything. The only time they get disabled is from settings, and we'll clear when that happens. if (!account.AreClassRemindersEnabled()) { return(Task.CompletedTask); } return(_workQueue.QueueOrMergeAsync(account.LocalAccountId, () => Task.Run(async delegate { try { ScheduleViewItemsGroup scheduleViewItemsGroup = null; var currSemesterId = account.CurrentSemesterId; if (currSemesterId != Guid.Empty && account.AreClassRemindersEnabled()) { // We don't need to worry about holding a lock though, if the collections change and that breaks us, that's fine, // that implies that the data has been changed anyways and another ResetReminders will come in. // Therefore we should also expect to get some exceptions here. scheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, currSemesterId, trackChanges: false, includeWeightCategories: false); } ResetAllReminders(account, scheduleViewItemsGroup); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }))); }
public static SchedulesOnDay Get(AccountDataItem account, IEnumerable <ViewItemClass> classes, DateTime date, Schedule.Week week, bool trackChanges = false) { SchedulesOnDay answer; for (int i = 0; i < _cached.Count; i++) { if (_cached[i].TryGetTarget(out answer)) { if (answer.Date == date.Date && answer.Classes == classes && object.Equals(answer.SchoolTimeZone, account.SchoolTimeZone)) { if (trackChanges) { return(answer); } else { return(new SchedulesOnDay(answer)); } } } else { _cached.RemoveAt(i); i--; } } answer = new SchedulesOnDay(classes, date, week, account.SchoolTimeZone, trackChanges); if (trackChanges) { _cached.Add(new WeakReference <SchedulesOnDay>(answer)); } return(answer); }
public static void ScheduleDayBeforeAlarm(Context context, AccountDataItem account, DateTime today, AgendaViewItemsGroup agendaItems) { if (agendaItems == null) { return; } DateTime dayBeforeReminderTime = RemindersExtension.GetDayBeforeReminderTime(today, account, agendaItems); DateTime timeToScheduleAt; // If we haven't reached that time yet for "due tomorrow" if (dayBeforeReminderTime > DateTime.Now) { timeToScheduleAt = dayBeforeReminderTime.AddMilliseconds(1); } // Otherwise we'll need to set the timer for the "due today" else { timeToScheduleAt = today.AddDays(1).AddMilliseconds(1); } AlarmManagerHelper.Schedule( context: context, receiverType: typeof(UpdateDayBeforeNotificationReceiver), wakeTime: timeToScheduleAt, uriData: "powerplanner:?localAccountId=" + account.LocalAccountId, wakeDevice: true); }
/// <summary> /// Pins and updates the secondary tile /// </summary> /// <param name="account"></param> /// <param name="data"></param> /// <returns></returns> public static async Task PinTile(AccountDataItem account, AccountDataStore data) { string args = new ViewScheduleArguments() { LocalAccountId = account.LocalAccountId }.SerializeToString(); SecondaryTile tile = new SecondaryTile(GenerateScheduleTileId(account.LocalAccountId), "Schedule", args, new Uri("ms-appx:///Assets/Square150x150Logo.png"), TileSize.Default); tile.VisualElements.Square71x71Logo = new Uri("ms-appx:///Assets/Square71x71Logo.png"); tile.VisualElements.Wide310x150Logo = new Uri("ms-appx:///Assets/Wide310x150Logo.png"); tile.VisualElements.Square310x310Logo = new Uri("ms-appx:///Assets/Square310x310Logo.png"); tile.VisualElements.Square44x44Logo = new Uri("ms-appx:///Assets/Square44x44Logo.png"); tile.LockScreenBadgeLogo = new Uri("ms-appx:///Assets/LockScreenLogo.png"); tile.LockScreenDisplayBadgeAndTileText = true; tile.VisualElements.ShowNameOnSquare150x150Logo = true; tile.VisualElements.ShowNameOnSquare310x310Logo = true; tile.VisualElements.ShowNameOnWide310x150Logo = true; if (!await tile.RequestCreateAsync()) { return; } await UpdateScheduleTile(tile.TileId, account, data); }
/// <summary> /// Finds the next date that the class occurs on. If the class already started today, returns the /// NEXT instance of that class. /// </summary> /// <param name="account"></param> /// <param name="c"></param> /// <returns></returns> public static DateTime?GetNextClassDate(AccountDataItem account, ViewItemClass c) { if (c.Schedules == null || c.Schedules.Count == 0) { return(null); } var now = DateTime.Now; DateTime date = now.Date; // Look up to 2 weeks (and one day) in advance // We include the extra one day since if the class is currently going on, we want the NEXT instance of that class, // which could possibly be 2 weeks out for (int i = 0; i < 15; i++, date = date.AddDays(1)) { var currWeek = account.GetWeekOnDifferentDate(date); // If there's a schedule on that day // (If it's not today, then we're good... otherwise if it's today, // make sure that the class hasn't started yet - if it started, we want the NEXT instance of the class) if (c.Schedules.Any(s => s.DayOfWeek == date.DayOfWeek && (s.ScheduleWeek == Schedule.Week.BothWeeks || s.ScheduleWeek == currWeek) && (date.Date != now.Date || s.StartTime.TimeOfDay > now.TimeOfDay))) { return(date); } } return(null); }
/// <summary> /// Pins and updates the secondary tile /// </summary> /// <param name="account"></param> /// <param name="data"></param> /// <returns></returns> public static async Task PinTileAsync(AccountDataItem account, AccountDataStore data, Guid classId, string className, Color classColor) { string args = new ViewClassArguments() { LocalAccountId = account.LocalAccountId, ItemId = classId }.SerializeToString(); // Display name is name of the class // Tile background is color of the class SecondaryTile tile = new SecondaryTile(GenerateTileId(account.LocalAccountId, classId), GetTrimmedClassName(className), args, new Uri("ms-appx:///Assets/Square150x150Logo.png"), TileSize.Default); tile.VisualElements.BackgroundColor = classColor; tile.VisualElements.Square71x71Logo = new Uri("ms-appx:///Assets/Square71x71Logo.png"); tile.VisualElements.Wide310x150Logo = new Uri("ms-appx:///Assets/Wide310x150Logo.png"); tile.VisualElements.Square310x310Logo = new Uri("ms-appx:///Assets/Square310x310Logo.png"); tile.VisualElements.Square44x44Logo = new Uri("ms-appx:///Assets/Square44x44Logo.png"); tile.LockScreenBadgeLogo = new Uri("ms-appx:///Assets/LockScreenLogo.png"); tile.LockScreenDisplayBadgeAndTileText = true; tile.VisualElements.ShowNameOnSquare150x150Logo = true; tile.VisualElements.ShowNameOnSquare310x310Logo = true; tile.VisualElements.ShowNameOnWide310x150Logo = true; if (!await tile.RequestCreateAsync()) { return; } await UpdateTileAsync(tile, account, data, classId); }
public static async Task<XmlDocument> GetCurrentTileNotificationContentAsync(AccountDataItem forAccount, Guid classId) { try { ClassTileSettings settings = await forAccount.GetClassTileSettings(classId); if (settings.IsDisabled()) { return null; } DateTime todayInLocal = DateTime.Today; ClassData data = await LoadDataAsync(await AccountDataStore.Get(forAccount.LocalAccountId), classId, DateTime.SpecifyKind(todayInLocal, DateTimeKind.Utc), settings); // That means the class was deleted, but we'll just return null here if (data == null) return null; List<ItemsOnDay> groupedByDay = GroupByDay(data.AllUpcoming); return GenerateUpcomingTileNotificationContent(groupedByDay, DateTime.SpecifyKind(todayInLocal, DateTimeKind.Utc), true, UpcomingTileType.ClassTile); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); return null; } }
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; } } }
public static async Task <AccountDataItem> CreateAccountLocally(string username, string localToken, string token, long accountId, int deviceId, bool needsInitialSync) { try { AccountDataItem account = account = await AccountsManager.CreateAccount(username, localToken, token, accountId, deviceId, true, true, true, needsInitialSync); return(account); } catch (AccountsManager.UsernameExistsLocallyException) { AlertUsernameExistsLocally?.Invoke(); } catch (AccountsManager.UsernameInvalidException) { AlertInvalidUsername?.Invoke(); } catch (AccountsManager.UsernameWasEmptyException) { AlertUsernameEmpty?.Invoke(); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex, "UnknownCreateAccountLocallyError"); ShowMessage("Unknown error occurred. Your error has been sent to the developer.\n\n" + ex.ToString(), "Error"); } return(null); }
private async Task UpdateScheduledNotificationsAsync(AccountDataItem account, AgendaViewItemsGroup agendaItems, DateTime now) { // Just remove all, we would be overwriting them anyways await RemoveAllScheduledNotificationsAsync(account.LocalAccountId); await AddScheduledDayBeforeNotifications(account, agendaItems, now); await AddScheduledDayOfNotifications(account, agendaItems, now); }
public async Task Initialize() { AccountDataItem account = await AccountsManager.CreateAccount("andrewbares", "andrew", null, 0, 0, true, true, true, false); LocalAccountId = account.LocalAccountId; await InitializeAfterAccount(); }
private static async Task UpdateTileNotificationsBlocking(AccountDataItem account, AccountDataStore data) { // If it's the main account, update primary tile if (account.LocalAccountId == AccountsManager.GetLastLoginLocalId()) { await UpdatePrimaryTileNotificationsBlocking(account, data); } }
public async void Handle(BackgroundActivatedEventArgs args) { var taskInstance = args.TaskInstance; taskInstance.Canceled += TaskInstance_Canceled; var deferral = taskInstance.GetDeferral(); try { RawNotification notification = (RawNotification)taskInstance.TriggerDetails; long accountId = UWPPushExtension.GetAccountIdFromRawNotification(notification); if (accountId == 0) { return; } AccountDataItem account = await AccountsManager.GetOrLoadOnlineAccount(accountId); if (account == null) { return; } var cancellationToken = _cancellationTokenSource.Token; try { cancellationToken.ThrowIfCancellationRequested(); var result = await Sync.SyncAccountAsync(account); // Need to wait for the tile/toast tasks to finish before we release the deferral if (result != null && result.SaveChangesTask != null) { await result.SaveChangesTask.WaitForAllTasksAsync(); } } catch (OperationCanceledException) { } // Wait for the calendar integration to complete await AppointmentsExtension.Current?.GetTaskForAllCompleted(); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } finally { deferral.Complete(); } }
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; } } }
public override void UpdateCurrentUser(AccountDataItem account) { base.UpdateCurrentUser(account); if (UserId != null) { AppCenter.SetUserId(UserId); } }
public ConfirmIdentityViewModel(BaseViewModel parent, AccountDataItem account) : base(parent) { _currAccount = account; if (_currAccount == null) { throw new InvalidOperationException("There's no current account."); } }
public DayPagerAdapter(AccountDataItem account, SemesterItemsViewGroup itemsSource, DateTime currentDate) { currentDate = currentDate.Date; Account = account; ItemsSource = itemsSource; CenterDate = currentDate; FirstDate = currentDate.AddDays(-1000); }
public static UpdateCredentialsViewModel Create(BaseViewModel parent, AccountDataItem account, UpdateTypes updateType) { return(new MainScreen.UpdateCredentialsViewModel(parent) { UpdateType = updateType, Account = account, Username = account.Username }); }
public static DateTime GetDayBeforeReminderTime(DateTime date, AccountDataItem account, AgendaViewItemsGroup agenda) { DateTime?classEndTime = account.GetClassEndTime(date, agenda.Classes); if (classEndTime == null) { return(date.Date.AddHours(15)); // Default time is 3:00 PM } return(classEndTime.Value.AddMinutes(10)); // Otherwise 10 mins after the class end time }
private MainScreenViewModel(BaseViewModel parent, AccountDataItem account) : base(parent) { CurrentAccount = account; AccountDataStore.DataChangedEvent += new WeakEventHandler <DataChangedEvent>(AccountDataStore_DataChangedEvent).Handler; Sync.SyncQueued += new WeakEventHandler <SyncQueuedEventArgs>(Sync_SyncQueued).Handler; Sync.UploadImageProgress += new WeakEventHandler <UploadImageProgressEventArgs>(Sync_UploadImageProgress).Handler; base.PropertyChanged += MainScreenViewModel_PropertyChanged; }
public ReminderSettingsViewModel(BaseViewModel parent) : base(parent) { _account = base.FindAncestor <MainWindowViewModel>().CurrentAccount; if (_account != null) { _remindersDayBefore = _account.RemindersDayBefore; _remindersDayOf = _account.RemindersDayOf; IsEnabled = true; } }
private DayScheduleItemsArranger(AccountDataItem account, SemesterItemsViewGroup semesterItems, ScheduleViewItemsGroup scheduleGroup, DateTime date, double heightOfHour, double spacingWhenNoAdditionalItems, double spacingWithAdditionalItems, double widthOfCollapsed, bool includeTasksAndEventsAndHolidays) { if (semesterItems.Semester == null) { throw new NullReferenceException("Semester was null"); } _semesterItems = semesterItems; semesterItems.OnItemsChanged += new WeakEventHandler <EventArgs>(SemesterGroup_OnItemsChanged).Handler; scheduleGroup.OnChangesOccurred += new WeakEventHandler <DataChangedEvent>(ScheduleViewItemsGroup_OnChangesOccurred).Handler; Date = date; _spacingWhenNoAdditionalItems = spacingWhenNoAdditionalItems; _spacingWithAdditionalItems = spacingWithAdditionalItems; _widthOfCollapsed = widthOfCollapsed; Account = account; _schoolTimeZone = account.SchoolTimeZone; HeightOfHour = heightOfHour; MinDuration = TimeSpan.FromHours(widthOfCollapsed / HeightOfHour); IsDifferentSemester = !semesterItems.Semester.IsDateDuringThisSemester(date); SchedulesOnDay schedules = null; if (!IsDifferentSemester) { schedules = SchedulesOnDay.Get(account, semesterItems.Classes, date, account.GetWeekOnDifferentDate(date), trackChanges: true); schedules.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Schedules_CollectionChanged).Handler; } _schedules = schedules; if (includeTasksAndEventsAndHolidays) { // For schedules, if tasks have a specific due time, we don't adjust the dates regardless of time zones causing them to switch to a different day, since they're displayed on the visual schedule. Therefore we set useEffectiveDatesEvenWhenItemsHaveTimes to false. _events = TasksOrEventsOnDay.Get(account, semesterItems.Items, date, today: null, activeOnly: false, useEffectiveDateEvenWhenItemsHaveTimes: false); _events.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Events_CollectionChanged).Handler; } else { _events = new MyObservableList <BaseViewItemMegaItem>(); } if (includeTasksAndEventsAndHolidays) { _holidays = HolidaysOnDay.Create(semesterItems.Items, date); _holidays.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(_holidays_CollectionChanged).Handler; } else { _holidays = new MyObservableList <ViewItemHoliday>(); } Initialize(schedules, _events, _holidays); }
private async void LocalNotFound(string username) { string password = GetPassword(); try { IsLoggingInOnline = true; OnlineLoginResponse resp; try { resp = await PowerPlannerAuth.LoginOnlineAndAddDeviceAsync(username, password); } catch { IsLoggingInOnline = false; throw; } IsLoggingInOnline = false; if (resp.Error != null) { ShowMessage(resp.Error, "Error logging in"); } else { AccountDataItem account = await CreateAccount(username, resp.LocalToken, resp.Token, resp.AccountId, resp.DeviceId); if (account != null) { TelemetryExtension.Current?.TrackEvent("LoggedInToOnlineAccount"); AccountsManager.SetLastLoginIdentifier(account.LocalAccountId); ToMainPage(account, existingAccount: false); } } } catch (Exception ex) { Debug.WriteLine("Failed logging into online account: " + ex.ToString()); ShowMessage(PowerPlannerResources.GetString("LoginPage_String_ExplanationOfflineAndNoLocalAccountFound"), PowerPlannerResources.GetString("LoginPage_String_NoAccountFoundHeader")); } finally { IsLoggingInOnline = false; } }
public static DateTime ToViewItemTime(AccountDataItem account, DateTime rawDateTime) { if (account.SchoolTimeZone == null) { return(DateTime.SpecifyKind(rawDateTime, DateTimeKind.Local)); } var currentTimeZone = TimeZoneInfo.Local; return(TimeZoneInfo.ConvertTime(DateTime.SpecifyKind(rawDateTime, DateTimeKind.Unspecified), sourceTimeZone: account.SchoolTimeZone, destinationTimeZone: currentTimeZone)); }
private static DateTime getDayOfReminderTime(BaseViewItemHomeworkExam h, AccountDataItem account, ref bool hasClassTime) { ViewItemClass c = h.GetClassOrNull(); if (c == null) { return(DateTime.MinValue); } return(h.GetDayOfReminderTime(out hasClassTime)); }
public static async Task UpdateAndScheduleDayOfNotifications(Context context, Guid localAccountId, bool fromForeground) { await InitializeChannelsAsync((NotificationManager)Application.Context.GetSystemService(Context.NotificationService)); AccountDataItem account = await AccountsManager.GetOrLoad(localAccountId); if (account != null) { await UpdateAndScheduleDayOfNotifications(context, account, fromForeground); } }
private DayScheduleItemsArranger(AccountDataItem account, SemesterItemsViewGroup semesterItems, ScheduleViewItemsGroup scheduleGroup, DateTime date, double heightOfHour, double spacingWhenNoAdditionalItems, double spacingWithAdditionalItems, double widthOfCollapsed, bool includeHomeworkAndHolidays) { if (semesterItems.Semester == null) { throw new NullReferenceException("Semester was null"); } _semesterItems = semesterItems; semesterItems.OnItemsChanged += new WeakEventHandler <EventArgs>(SemesterGroup_OnItemsChanged).Handler; scheduleGroup.OnChangesOccurred += new WeakEventHandler <DataChangedEvent>(ScheduleViewItemsGroup_OnChangesOccurred).Handler; Date = date; _spacingWhenNoAdditionalItems = spacingWhenNoAdditionalItems; _spacingWithAdditionalItems = spacingWithAdditionalItems; _widthOfCollapsed = widthOfCollapsed; Account = account; _schoolTimeZone = account.SchoolTimeZone; HeightOfHour = heightOfHour; MinDuration = TimeSpan.FromHours(widthOfCollapsed / HeightOfHour); IsDifferentSemester = !semesterItems.Semester.IsDateDuringThisSemester(date); SchedulesOnDay schedules = null; if (!IsDifferentSemester) { schedules = SchedulesOnDay.Get(semesterItems.Classes, date, account.GetWeekOnDifferentDate(date), trackChanges: true); schedules.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Schedules_CollectionChanged).Handler; } _schedules = schedules; if (includeHomeworkAndHolidays) { _events = HomeworksOnDay.Get(semesterItems.Items, date); _events.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Events_CollectionChanged).Handler; } else { _events = new MyObservableList <BaseViewItemHomeworkExamGrade>(); } if (includeHomeworkAndHolidays) { _holidays = HolidaysOnDay.Create(semesterItems.Items, date); _holidays.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(_holidays_CollectionChanged).Handler; } else { _holidays = new MyObservableList <ViewItemHoliday>(); } Initialize(schedules, _events, _holidays); }