Esempio n. 1
0
        /// <summary>
        /// Guaranteed that data won't be null
        /// </summary>
        /// <param name="data"></param>
        /// <returns>Should always return an initialized list.</returns>
        private static async Task <List <BaseViewItemHomeworkExam> > getAllUpcomingBlocking(AccountDataItem account, AccountDataStore data, DateTime todayAsUtc, BaseUpcomingTileSettings tileSettings)
        {
            var currSemesterId = account.CurrentSemesterId;

            if (currSemesterId == Guid.Empty)
            {
                return(new List <BaseViewItemHomeworkExam>());
            }

            ScheduleViewItemsGroup scheduleViewGroup;

            try
            {
                scheduleViewGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, account.CurrentSemesterId, trackChanges : true, includeWeightCategories : false);
            }
            catch
            {
                // If semester not found
                return(new List <BaseViewItemHomeworkExam>());
            }

            DateTime dateToStartDisplayingFrom = DateTime.SpecifyKind(tileSettings.GetDateToStartDisplayingOn(todayAsUtc), DateTimeKind.Utc);

            var agendaViewGroup = await AgendaViewItemsGroup.LoadAsync(account.LocalAccountId, scheduleViewGroup.Semester, DateTime.SpecifyKind(todayAsUtc, DateTimeKind.Local), trackChanges : true);

            // We're not going to worry about locking changes while we enumerate, since if collection changes while we're enumerating, there'll be a
            // new incoming reset request anyways

            // Agenda view group doesn't sort, so we have to sort it
            return(agendaViewGroup.Items.Where(
                       i => i.Date.Date >= dateToStartDisplayingFrom &&
                       ((tileSettings.ShowHomework && i is ViewItemHomework) || (tileSettings.ShowExams && i is ViewItemExam))
                       ).OrderBy(i => i).ToList());
        }
Esempio n. 2
0
        private async Task OnSemesterChanged()
        {
            // Restore the default stored items
            NavigationManager.RestoreDefaultMemoryItems();

            // Disconnect the previous
            if (ScheduleViewItemsGroup != null)
            {
                Classes.EndMakeThisACopyOf(ScheduleViewItemsGroup.Classes);
                if (_scheduleChangesOccurredHandler != null)
                {
                    ScheduleViewItemsGroup.OnChangesOccurred -= _scheduleChangesOccurredHandler;
                }
                ScheduleViewItemsGroup = null;
            }

            // Clear the current classes
            Classes.Clear();

            // If there's believed to be a semester (although that semester may not exist, this simply means Guid isn't empty)
            if (!hasNoSemester())
            {
                // Load the classes/schedules
                try
                {
                    ScheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(this.CurrentLocalAccountId, this.CurrentSemesterId);
                }
                catch (SemesterNotFoundException)
                {
                    // Semester didn't actually exist
                    CurrentSemesterId = Guid.Empty;
                    return;
                }

                // Change the default date

                // If semester has already ended
                if (!PowerPlannerSending.DateValues.IsUnassigned(CurrentSemester.End) && DateTime.SpecifyKind(CurrentSemester.End, DateTimeKind.Local).Date < DateTime.Today)
                {
                    NavigationManager.SetDisplayMonth(DateTime.SpecifyKind(CurrentSemester.End, DateTimeKind.Local), preserveForever: true);
                    NavigationManager.SetSelectedDate(DateTime.SpecifyKind(CurrentSemester.End, DateTimeKind.Local), preserveForever: true);
                }

                // If semester hasn't started yet
                else if (!PowerPlannerSending.DateValues.IsUnassigned(CurrentSemester.Start) && DateTime.SpecifyKind(CurrentSemester.Start, DateTimeKind.Local).Date > DateTime.Today)
                {
                    NavigationManager.SetDisplayMonth(DateTime.SpecifyKind(CurrentSemester.Start, DateTimeKind.Local), preserveForever: true);
                    NavigationManager.SetSelectedDate(DateTime.SpecifyKind(CurrentSemester.Start, DateTimeKind.Local), preserveForever: true);
                }

                // Make this a copy of the Classes list
                Classes.MakeThisACopyOf(ScheduleViewItemsGroup.Classes);

                if (_scheduleChangesOccurredHandler == null)
                {
                    _scheduleChangesOccurredHandler = new WeakEventHandler <DataChangedEvent>(ViewModelSchedule_OnChangesOccurred).Handler;
                }
                ScheduleViewItemsGroup.OnChangesOccurred += _scheduleChangesOccurredHandler;
            }
        }
Esempio n. 3
0
        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);
                }
            })));
        }
        private static async Task <AgendaViewItemsGroup> GetAgendaViewItemsGroup(AccountDataItem account, DateTime today)
        {
            try
            {
                // We're getting cached versions which might change as we're using the app, but that's fine, since if items change, another
                // ResetReminders will be incoming anyways
                var scheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, account.CurrentSemesterId, trackChanges : true, includeWeightCategories : false);

                return(await AgendaViewItemsGroup.LoadAsync(account.LocalAccountId, scheduleViewItemsGroup.Semester, today, trackChanges : true));
            }

            // If semester didn't exist, it throws null reference exception
            catch { return(null); }
        }
Esempio n. 5
0
        private static async Task <ClassData> LoadDataBlocking(AccountDataStore data, Guid classId, DateTime todayAsUtc, ClassTileSettings settings)
        {
            DateTime dateToStartDisplayingFrom = DateTime.SpecifyKind(settings.GetDateToStartDisplayingOn(todayAsUtc), DateTimeKind.Local);

            Guid semesterId = Guid.Empty;

            // We lock the outside, since we are allowing trackChanges on the view items groups (so we have a chance of loading a cached one)... and since we're on a background thread, the lists inside the
            // view items groups could change while we're enumerating, hence throwing an exception. So we lock it to ensure this won't happen, and then we return a copy of the items that we need.
            using (await Locks.LockDataForReadAsync())
            {
                // First we need to obtain the semester id
                var c = data.TableClasses.FirstOrDefault(i => i.Identifier == classId);

                if (c == null)
                {
                    return(null);
                }

                semesterId = c.UpperIdentifier;
            }

            // We need all classes loaded, to know what time the end of day is
            var scheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(data.LocalAccountId, semesterId, trackChanges : true, includeWeightCategories : false);

            var classViewItemsGroup = await ClassViewItemsGroup.LoadAsync(
                localAccountId : data.LocalAccountId,
                classId : classId,
                today : DateTime.SpecifyKind(todayAsUtc, DateTimeKind.Local),
                viewItemSemester : scheduleViewItemsGroup.Semester,
                includeWeights : false);

            classViewItemsGroup.LoadTasksAndEvents();
            await classViewItemsGroup.LoadTasksAndEventsTask;

            List <ViewItemTaskOrEvent> copied;

            using (await classViewItemsGroup.DataChangeLock.LockForReadAsync())
            {
                // Class view group sorts the items, so no need to sort
                copied = classViewItemsGroup.Class.TasksAndEvents.Where(i => i.Date.Date >= dateToStartDisplayingFrom).ToList();
            }

            return(new ClassData()
            {
                Class = classViewItemsGroup.Class,
                AllUpcoming = copied
            });
        }
Esempio n. 6
0
        protected override async Task LoadAsyncOverride()
        {
            await base.LoadAsyncOverride();

            if (Account.CurrentSemesterId == Guid.Empty)
            {
                return;
            }

            try
            {
                var viewItems = await ScheduleViewItemsGroup.LoadAsync(Account.LocalAccountId, Account.CurrentSemesterId, trackChanges : true, includeWeightCategories : false);

                HasSemester = true;

                // We lock since we're tracking changes, and can't let the list change while enumerating it initially
                using (await viewItems.DataChangeLock.LockForReadAsync())
                {
                    if (viewItems.Classes.Count == 0)
                    {
                        return;
                    }

                    HasClasses = true;

                    var classes = new List <ClassAndPinnedStatus>();

                    foreach (var c in viewItems.Classes)
                    {
                        classes.Add(new ClassAndPinnedStatus()
                        {
                            Class    = c,
                            IsPinned = ClassTileHelper.IsPinned(Account.LocalAccountId, c.Identifier)
                        });
                    }

                    Classes = classes;
                }
            }
            catch (SemesterNotFoundException) { }
        }
Esempio n. 7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="account"></param>
        /// <param name="today">As local time</param>
        /// <param name="daysIncludingToday"></param>
        /// <returns></returns>
        public static async Task <ScheduleTileDataHelper> LoadAsync(AccountDataItem account, DateTime today, int daysIncludingToday)
        {
            var answer = new ScheduleTileDataHelper()
            {
                Account            = account,
                DaysIncludingToday = daysIncludingToday,
                Today = today.Date
            };

            var currSemesterId = account.CurrentSemesterId;

            if (currSemesterId != Guid.Empty)
            {
                try
                {
                    answer.ScheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, currSemesterId, trackChanges : true, includeWeightCategories : false);

                    answer.HasSemester = true;
                }
                catch
                {
                    // If semester not found
                    return(answer);
                }

                try
                {
                    answer.HolidayViewItemsGroup = await HolidayViewItemsGroup.LoadAsync(account.LocalAccountId, answer.ScheduleViewItemsGroup.Semester, today, today.AddDays(daysIncludingToday - 1), trackChanges : false);
                }
                catch (Exception ex)
                {
                    TelemetryExtension.Current?.TrackException(ex);
                }
            }

            // TODO: Genericize the logic between UWP and Android

            return(answer);
        }
Esempio n. 8
0
        public static DayScheduleItemsArranger Create(AccountDataItem account, SemesterItemsViewGroup semesterItems, ScheduleViewItemsGroup scheduleGroup, DateTime date, double heightOfHour, double spacingWhenNoAdditionalItems, double spacingWithAdditionalItems, double widthOfCollapsed, bool includeHomeworkAndHolidays)
        {
            if (account == null)
            {
                throw new ArgumentNullException(nameof(account));
            }

            if (semesterItems == null)
            {
                throw new ArgumentNullException(nameof(semesterItems));
            }

            if (scheduleGroup == null)
            {
                throw new ArgumentNullException(nameof(scheduleGroup));
            }

            date = date.Date;

            foreach (var cachedAnswer in _cached)
            {
                if (cachedAnswer.Date == date.Date &&
                    cachedAnswer._semesterItems == semesterItems &&
                    cachedAnswer.HeightOfHour == heightOfHour &&
                    cachedAnswer._spacingWhenNoAdditionalItems == spacingWhenNoAdditionalItems &&
                    cachedAnswer._spacingWithAdditionalItems == spacingWithAdditionalItems &&
                    cachedAnswer._widthOfCollapsed == widthOfCollapsed)
                {
                    return(cachedAnswer);
                }
            }

            DayScheduleItemsArranger answer = new DayScheduleItemsArranger(account, semesterItems, scheduleGroup, date, heightOfHour, spacingWhenNoAdditionalItems, spacingWithAdditionalItems, widthOfCollapsed, includeHomeworkAndHolidays);

            _cached.Add(answer);
            return(answer);
        }
Esempio n. 9
0
        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;
            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);
        }
Esempio n. 10
0
 /// <summary>
 /// Reset the class reminders. scheduleViewItemsGroup may be null (indicating no semester or reminders disabled).
 /// </summary>
 /// <param name="account"></param>
 /// <param name="scheduleViewItemsGroup"></param>
 protected abstract void ResetAllReminders(AccountDataItem account, ScheduleViewItemsGroup scheduleViewItemsGroup);
        private async Task ResetReminders(AccountDataItem account, CancellationToken token)
        {
            if (account == null)
            {
                return;
            }

            ClearReminders(account.LocalAccountId, token);

            token.ThrowIfCancellationRequested();

            var semesterId = account.CurrentSemesterId;

            if (semesterId == Guid.Empty)
            {
                return;
            }

            DateTime todayAsUtc = DateTime.SpecifyKind(DateTime.Today, DateTimeKind.Utc);

            ViewItemTaskOrEvent[] itemsDueTodayOrGreater;
            ViewItemSchedule[]    allSchedules;

            try
            {
                ScheduleViewItemsGroup viewModelSchedule = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, semesterId, trackChanges : true, includeWeightCategories : false);

                AgendaViewItemsGroup viewModel = await AgendaViewItemsGroup.LoadAsync(account.LocalAccountId, viewModelSchedule.Semester, DateTime.SpecifyKind(todayAsUtc, DateTimeKind.Local), trackChanges : true);

                // Data we need to load and hold are...
                // - Items due today or greater
                // - All schedules
                // 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.

                allSchedules           = viewModelSchedule.Classes.SelectMany(i => i.Schedules).ToArray();
                itemsDueTodayOrGreater = viewModel.Items.Where(i => i.Date.Date >= DateTime.SpecifyKind(todayAsUtc, DateTimeKind.Local)).ToArray();
            }
            catch
            {
                // Semester wasn't found or other misc error
                return;
            }

            // Since we're no longer inside the lock and we're using a view group that tracks changes, any properties we access on the view items could change at any time.
            // Therefore we need to take that into consideration and be careful about what we do.

            if (account.RemindersDayBefore)
            {
                Dictionary <DateTime, List <ViewItemTaskOrEvent> > groupedByDay = new Dictionary <DateTime, List <ViewItemTaskOrEvent> >();

                DateTime tomorrow = DateTime.SpecifyKind(todayAsUtc.AddDays(1), DateTimeKind.Local);

                //select all incomplete tasks/events that is due on tomorrow or later
                foreach (ViewItemTaskOrEvent h in itemsDueTodayOrGreater.Where(i => i.Date.Date >= tomorrow))
                {
                    token.ThrowIfCancellationRequested();

                    var hDate = h.Date.Date;

                    if (!groupedByDay.TryGetValue(hDate, out List <ViewItemTaskOrEvent> group))
                    {
                        group = new List <ViewItemTaskOrEvent>();
                        groupedByDay[hDate] = group;
                    }

                    group.Add(h);
                }

                foreach (var pair in groupedByDay)
                {
                    token.ThrowIfCancellationRequested();

                    DateTime dueOn = pair.Key;
                    List <ViewItemTaskOrEvent> items = pair.Value;

                    DateTime reminderTime = GetDayBeforeReminderTime(dueOn.AddDays(-1), account, allSchedules);

                    if (!IsTimeOkay(reminderTime))
                    {
                        continue;
                    }


                    ViewItemTaskOrEvent[] tasks  = items.Where(i => i.Type == TaskOrEventType.Task).ToArray();
                    ViewItemTaskOrEvent[] events = items.Where(i => i.Type == TaskOrEventType.Event).ToArray();


                    if (tasks.Length > 0)
                    {
                        XmlDocument xml = GenerateToastReminder(
                            tasks.Length == 1 ? "You have 1 item due tomorrow" : "You have " + tasks.Length + " items due tomorrow",
                            GetItemLineText(tasks[0]),
                            tasks.Length >= 2 ? GetItemLineText(tasks[1]) : null,
#pragma warning disable 0612
                            new QueryStringHelper()
#pragma warning restore 0612
                            .SetLocalAccountId(account.LocalAccountId)
                            .SetAction("DayBeforeHomeworkReminder")
                            .ToString()
                            );

                        string remoteId = null;
                        if (account.IsOnlineAccount)
                        {
                            int hashedItems = string.Join(";", tasks.Select(i => i.Identifier)).GetHashCode();
                            remoteId = $"PP_DayBeforeHomeworks_{account.AccountId}_{hashedItems}";
                        }

                        Schedule(
                            GenerateScheduledToastNotification(
                                xml,
                                reminderTime,
                                GetId(account), //id's don't need to be unique
                                remoteId)
                            );
                    }

                    if (events.Length > 0)
                    {
                        XmlDocument xml = GenerateToastReminder(
                            events.Length == 1 ? "You have 1 event tomorrow" : "You have " + events.Length + " events tomorrow",
                            GetItemLineText(events[0]),
                            events.Length >= 2 ? GetItemLineText(events[1]) : null,
#pragma warning disable 0612
                            new QueryStringHelper()
#pragma warning restore 0612
                            .SetLocalAccountId(account.LocalAccountId)
                            .SetAction("DayBeforeExamReminder")
                            .ToString()
                            );

                        string remoteId = null;
                        if (account.IsOnlineAccount)
                        {
                            int hashedItems = string.Join(";", events.Select(i => i.Identifier)).GetHashCode();
                            remoteId = $"PP_DayBeforeExams_{account.AccountId}_{hashedItems}";
                        }

                        Schedule(
                            GenerateScheduledToastNotification(
                                xml,
                                reminderTime,
                                GetId(account),
                                remoteId));
                    }
                }
            }

            if (account.RemindersDayOf)
            {
                foreach (ViewItemTaskOrEvent h in itemsDueTodayOrGreater)
                {
                    token.ThrowIfCancellationRequested();
                    bool hasClassTime = false;

                    DateTime reminderTime = GetDayOfReminderTime(h, ref hasClassTime);

                    if (!IsTimeOkay(reminderTime))
                    {
                        continue;
                    }

                    string subtitle = GetClassName(h) + " - ";

                    if (h.Type == TaskOrEventType.Task)
                    {
                        subtitle += "due ";
                    }

                    if (hasClassTime)
                    {
                        subtitle += "in one hour";
                    }

                    else
                    {
                        subtitle += "today";
                    }

                    XmlDocument xml = GenerateToastReminder(
                        TrimString(h.Name, 200),
                        subtitle,
                        TrimString(h.Details, 200),
                        ArgumentsHelper.CreateArgumentsForView(h, account.LocalAccountId).SerializeToString()
                        );

                    string remoteId = null;
                    if (account.IsOnlineAccount)
                    {
                        remoteId = $"PP_DayOf_{account.AccountId}_{h.Identifier}";
                    }

                    Schedule(
                        GenerateScheduledToastNotification(
                            xml,
                            reminderTime,
                            GetId(account),
                            remoteId));
                }
            }
        }
            private async System.Threading.Tasks.Task InitializeDataAsync()
            {
                List <object> items = null;
                List <BaseViewItemHomeworkExam> tasks = null;

                _now = DateTime.Now;
                bool hasAccount           = false;
                bool isDisabledInSettings = false;
                bool hasSemester          = false;

                try
                {
                    await System.Threading.Tasks.Task.Run(async delegate
                    {
                        var account = await AccountsManager.GetLastLogin();

                        AccountDataStore data = null;

                        if (account != null)
                        {
                            data = await AccountDataStore.Get(account.LocalAccountId);
                        }

                        if (data != null)
                        {
                            hasAccount = true;

                            isDisabledInSettings = account.MainTileSettings.IsDisabled();

                            if (!isDisabledInSettings)
                            {
                                _localAccountId    = account.LocalAccountId;
                                var currSemesterId = account.CurrentSemesterId;
                                if (currSemesterId != Guid.Empty)
                                {
                                    ScheduleViewItemsGroup scheduleViewGroup;
                                    try
                                    {
                                        scheduleViewGroup = await ScheduleViewItemsGroup.LoadAsync(account.LocalAccountId, account.CurrentSemesterId, trackChanges: true, includeWeightCategories: false);
                                    }
                                    catch
                                    {
                                        // If semester not found
                                        scheduleViewGroup = null;
                                    }

                                    if (scheduleViewGroup != null)
                                    {
                                        DateTime dateToStartDisplayingFrom = DateTime.SpecifyKind(account.MainTileSettings.GetDateToStartDisplayingOn(_now.Date), DateTimeKind.Utc);

                                        // We don't track changes since we need a fresh version that has been filtered right now.
                                        // Otherwise when we update for an event expiring, if we have a cached version, that event wouldn't have expired!
                                        var agendaViewGroup = await AgendaViewItemsGroup.LoadAsync(account.LocalAccountId, scheduleViewGroup.Semester, _now.Date, trackChanges: false);
                                        hasSemester         = true;

                                        // We lock the outside, since we are allowing trackChanges on the view items groups (so we have a chance of loading a cached one)... and since we're on a background thread, the lists inside the
                                        // view items groups could change while we're enumerating, hence throwing an exception. So we lock it to ensure this won't happen, and then we return a copy of the items that we need.
                                        using (await agendaViewGroup.DataChangeLock.LockForReadAsync())
                                        {
                                            var filtered = agendaViewGroup.Items
                                                           .Where(i => i.Date.Date >= dateToStartDisplayingFrom);

                                            if (!account.MainTileSettings.ShowHomework)
                                            {
                                                filtered = filtered.Where(i => !(i is ViewItemHomework));
                                            }

                                            if (!account.MainTileSettings.ShowExams)
                                            {
                                                filtered = filtered.Where(i => !(i is ViewItemExam));
                                            }

                                            // Agenda view group doesn't sort, so we have to sort it
                                            tasks = filtered
                                                    .OrderBy(i => i)
                                                    .Take(20)
                                                    .ToList();

                                            // Add date headers
                                            items = new List <object>();
                                            DateTime lastHeader = DateTime.MinValue;
                                            foreach (var t in tasks)
                                            {
                                                if (lastHeader != t.Date.Date)
                                                {
                                                    items.Add(t.Date.Date);
                                                    lastHeader = t.Date.Date;
                                                }

                                                items.Add(t);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    });

                    if (items == null || items.Count == 0)
                    {
                        if (hasSemester)
                        {
                            items = new List <object>()
                            {
                                PowerPlannerResources.GetString("String_NothingDue")
                            };
                        }
                        else if (isDisabledInSettings)
                        {
                            items = new List <object>()
                            {
                                PowerPlannerResources.GetString("String_WidgetDisabled")
                            };
                        }
                        else if (hasAccount)
                        {
                            items = new List <object>()
                            {
                                PowerPlannerResources.GetString("String_NoSemester")
                            };
                        }
                        else
                        {
                            items = new List <object>()
                            {
                                PowerPlannerResources.GetString("String_NoAccount")
                            };
                        }
                    }

                    _items = items;
                }
                catch (Exception ex)
                {
                    TelemetryExtension.Current?.TrackException(ex);
                }

                // Schedule next
                try
                {
                    if (tasks != null && tasks.Count > 0)
                    {
                        DateTime?nextChangeTime = GetNextAgendaChangeTime(tasks, _now);
                        if (nextChangeTime != null)
                        {
                            AlarmManagerHelper.Schedule(
                                context: _context,
                                receiverType: typeof(UpdateWidgetAgendaReceiver),
                                wakeTime: nextChangeTime.Value);
                        }
                    }
                }
                catch (Exception ex)
                {
                    TelemetryExtension.Current?.TrackException(ex);
                }
            }
        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);
        }
Esempio n. 14
0
        protected override void ResetAllReminders(AccountDataItem account, ScheduleViewItemsGroup scheduleViewItemsGroup)
        {
            var notifier = ToastNotificationManager.CreateToastNotifier();
            var group    = ClassRemindersGroupPrefix + "." + UWPRemindersExtension.GetId(account);

            // Clear current scheduled notifications
            try
            {
                var scheduled = notifier.GetScheduledToastNotifications();
                foreach (var s in scheduled)
                {
                    try
                    {
                        if (s.Group == group)
                        {
                            notifier.RemoveFromSchedule(s);
                        }
                    }
                    catch { }
                }
            }
            catch { }

            if (scheduleViewItemsGroup == null)
            {
                return;
            }

            // This will be initialized
            var beforeTime = account.ClassRemindersTimeSpan.GetValueOrDefault();

            // Added in 17134
            bool isExpirationTimeSupported = ApiInformation.IsPropertyPresent(typeof(ScheduledToastNotification).FullName, "ExpirationTime");

            var today = DateTime.Today;
            var end   = today.AddDays(8); // Schedule out for 8 days

            Dictionary <ViewItemSchedule, XmlDocument> generatedPayloads = new Dictionary <ViewItemSchedule, XmlDocument>();

            for (; today.Date < end.Date; today = today.AddDays(1).Date)
            {
                // No need to lock changes, if changes occur an exception might occur, but that's fine, reminders would be reset once again anyways
                var schedulesOnDay = SchedulesOnDay.Get(account, scheduleViewItemsGroup.Classes, today, account.GetWeekOnDifferentDate(today), trackChanges: false);

                foreach (var s in schedulesOnDay)
                {
                    var reminderTime = today.Add(s.StartTime.TimeOfDay).Subtract(beforeTime);
                    if (reminderTime >= DateTime.Now.AddSeconds(5))
                    {
                        XmlDocument payload;

                        if (!generatedPayloads.TryGetValue(s, out payload))
                        {
                            payload = GeneratePayload(account, s);
                            generatedPayloads[s] = payload;
                        }

                        var notif = new ScheduledToastNotification(payload, reminderTime)
                        {
                            Group = group,
                            Tag   = s.Identifier.ToString() + "." + today.ToString("yy-dd-MM")
                        };

                        if (isExpirationTimeSupported)
                        {
                            notif.ExpirationTime = today.Add(s.EndTime.TimeOfDay);
                        }

                        try
                        {
                            notifier.AddToSchedule(notif);
                        }
                        catch (Exception ex)
                        {
                            // If OS is in a bad state, we'll just stop
                            TelemetryExtension.Current?.TrackException(new Exception("Adding toast to schedule failed: " + ex.Message, ex));
                            return;
                        }
                    }
                }
            }
        }