private async Task LoadBlocking() { var dataStore = await GetDataStore(); DataItemMegaItem[] dataItems; using (await Locks.LockDataForReadAsync("SemesterItemsViewGroup.LoadBlocking")) { Guid semesterIdentifier = Semester.Identifier; Guid[] classIdentifiers = Semester.Classes.Select(i => i.Identifier).ToArray(); dataItems = dataStore.TableMegaItems.Where(ShouldIncludeItemFunction(semesterIdentifier, classIdentifiers)).ToArray(); } await Dispatcher.RunAsync(delegate { foreach (var i in dataItems) { Add(i); } if (dataItems.Length > 0) { OnItemsChanged?.Invoke(this, new EventArgs()); } }); }
private async void TryAskingForRatingIfNeeded() { try { // If we haven't asked for rating yet if (!ApplicationData.Current.RoamingSettings.Values.ContainsKey("HasAskedForRating")) { if (ViewModel.CurrentAccount != null) { var dataStore = await AccountDataStore.Get(ViewModel.CurrentLocalAccountId); // If they actually have a decent amount of tasks/events if (await System.Threading.Tasks.Task.Run(async delegate { using (await Locks.LockDataForReadAsync()) { return(dataStore.TableMegaItems.Count() > 15); } })) { CustomMessageBox mb = new CustomMessageBox("Thanks for using Power Planner! If you love the app, please leave a rating in the Store! If you have any suggestions or issues, please email me!", "★ Review App ★", "Review", "Email Dev", "Close"); mb.Response += mbAskForReview_Response; mb.Show(); ApplicationData.Current.RoamingSettings.Values["HasAskedForRating"] = true; } } } } catch { } }
private async Task LoadBlocking() { var dataStore = await GetDataStore(); DataItemYear[] dataYears; DataItemSemester[] dataSemesters; DataItemClass[] dataClasses; DataItemWeightCategory[] dataWeightCategories; DataItemMegaItem[] dataMegaItems; DataItemGrade[] dataGrades; // Need to lock the whole thing so that if something is added while we're constructing, it'll be added after we've constructed using (await Locks.LockDataForReadAsync("YearsViewItemsGroup.LoadBlocking")) { dataYears = dataStore.TableYears.ToArray(); dataSemesters = dataStore.TableSemesters.ToArray(); dataClasses = dataStore.TableClasses.ToArray(); dataWeightCategories = dataStore.TableWeightCategories.ToArray(); dataGrades = dataStore.TableGrades.ToArray(); dataMegaItems = dataStore.TableMegaItems.Where(i => (i.MegaItemType == PowerPlannerSending.MegaItemType.Homework || i.MegaItemType == PowerPlannerSending.MegaItemType.Exam) && i.WeightCategoryIdentifier != PowerPlannerSending.BaseHomeworkExam.WEIGHT_CATEGORY_EXCLUDED).ToArray(); var school = new ViewItemSchool(CreateYear); school.FilterAndAddChildren(dataYears); foreach (var year in school.Years) { year.FilterAndAddChildren(dataSemesters); foreach (var semester in year.Semesters) { semester.FilterAndAddChildren(dataClasses); foreach (var classItem in semester.Classes) { classItem.FilterAndAddChildren(dataWeightCategories); foreach (var weight in classItem.WeightCategories) { weight.FilterAndAddChildren <BaseDataItemHomeworkExamGrade>(dataGrades); weight.FilterAndAddChildren <BaseDataItemHomeworkExamGrade>(dataMegaItems); } } } } // Sort the years here, since when initially inserting they can't be sorted, since they // sort based on their start dates, but their start dates are calculated based on their // semesters, and their semesters hadn't been added when the years are inserted school.Years.Sort(); this.School = school; } School.CalculateEverything(); }
private static async Task <bool> CheckThatSemesterIsValidBlocking(Guid localAccountId, Guid semesterId) { var dataStore = await AccountDataStore.Get(localAccountId); using (await Locks.LockDataForReadAsync()) { return(dataStore.TableSemesters.Count(i => i.Identifier == semesterId) > 0); } }
private async Task LoadBlocking() { var dataStore = await GetDataStore(); DataItemClass[] dataClasses; DataItemSchedule[] dataSchedules; DataItemWeightCategory[] dataWeights = null; // Weights are now needed for adding tasks/events DataItemSemester dataSemester; using (await Locks.LockDataForReadAsync("ScheduleViewItemsGroup.LoadBlocking")) { var timeTracker = TimeTracker.Start(); dataSemester = dataStore.TableSemesters.FirstOrDefault(i => i.Identifier == SemesterId); if (dataSemester == null) { throw new SemesterNotFoundException(); } dataClasses = dataStore.TableClasses.Where(i => i.UpperIdentifier == SemesterId).ToArray(); Guid[] classIdentifiers = dataClasses.Select(i => i.Identifier).ToArray(); dataSchedules = dataStore.TableSchedules.Where(i => classIdentifiers.Contains(i.UpperIdentifier)).ToArray(); if (_includeWeightCategories) { dataWeights = dataStore.TableWeightCategories.Where(i => classIdentifiers.Contains(i.UpperIdentifier)).ToArray(); } timeTracker.End(3, "ScheduleViewItemsGroup.LoadBlocking loading items from database"); timeTracker = TimeTracker.Start(); var semester = new ViewItemSemester(dataSemester, CreateClass); semester.FilterAndAddChildren(dataClasses); foreach (var c in semester.Classes) { c.FilterAndAddChildren(dataSchedules); if (_includeWeightCategories) { c.FilterAndAddChildren(dataWeights); } } this.Semester = semester; timeTracker.End(3, "ScheduleViewItemsGroup.LoadBlocking constructing view items"); } }
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 }); }
public override async Task <bool> ShouldShowAsync(AccountDataItem account) { // Don't show for offline accounts or for devices that aren't Desktop if (account == null || !account.IsOnlineAccount || InterfacesUWP.DeviceInfo.DeviceFamily != InterfacesUWP.DeviceFamily.Desktop) { return(false); } if (ApplicationData.Current.RoamingSettings.Values.ContainsKey(SETTING_HAS_PROMOTED_ANDROID_AND_IOS)) { return(false); } var dataStore = await AccountDataStore.Get(account.LocalAccountId); // If they actually have some classes bool hasContent; using (await Locks.LockDataForReadAsync()) { hasContent = dataStore.TableClasses.Count() > 1; } if (hasContent) { // Try downloading and then show ShouldSuggestOtherPlatformsResponse response = await account.PostAuthenticatedAsync <ShouldSuggestOtherPlatformsRequest, ShouldSuggestOtherPlatformsResponse>( Website.URL + "shouldsuggestotherplatforms", new ShouldSuggestOtherPlatformsRequest() { CurrentPlatform = "Windows 10" }); if (response.ShouldSuggest) { return(true); } // No need to suggest in the future nor show now MarkShown(account); return(false); } else { // Not enough content to show right now return(false); } }
public override async Task <bool> ShouldShowAsync(AccountDataItem account) { if (account == null) { return(false); } // If we've already shown if (Helpers.Settings.HasShownPromoContribute) { return(false); } var dataStore = await AccountDataStore.Get(account.LocalAccountId); // If they actually have lots of tasks using (await Locks.LockDataForReadAsync()) { return(dataStore.ActualTableMegaItems.Count() > 60); } }
private async Task LoadBlocking() { var dataStore = await GetDataStore(); Guid semesterId = Semester.Identifier; DateTime startAsUtc = DateTime.SpecifyKind(StartDate, DateTimeKind.Utc); DateTime endAsUtc = DateTime.SpecifyKind(EndDate, DateTimeKind.Utc); DataItemMegaItem[] dataItemHolidays; using (await Locks.LockDataForReadAsync("HolidayViewItemsGroup.LoadBlocking")) { dataItemHolidays = dataStore.TableMegaItems.Where(i => i.MegaItemType == PowerPlannerSending.MegaItemType.Holiday && i.UpperIdentifier == semesterId && ((i.Date <= startAsUtc && i.EndTime >= startAsUtc) || (i.Date >= startAsUtc && i.Date <= endAsUtc))).ToArray(); } Holidays = new MyObservableList <ViewItemHoliday>(dataItemHolidays.Select(i => new ViewItemHoliday(i))); }
private async Task LoadBlocking() { var dataStore = await GetDataStore(); DataItemMegaItem[] dataItems; using (await Locks.LockDataForReadAsync("AgendaViewItemsGroup.LoadBlocking")) { Guid[] classIdentifiers = _semester.Classes.Select(i => i.Identifier).ToArray(); DateTime todayAsUtc = DateTime.SpecifyKind(Today, DateTimeKind.Utc); dataItems = dataStore.TableMegaItems.Where(ShouldIncludeItemFunction(classIdentifiers, todayAsUtc)).ToArray(); this.Items = new MyObservableList <ViewItemTaskOrEvent>(); foreach (var i in dataItems) { Add(i); } } }
private async void TryAskingForRatingIfNeeded() { try { // If we haven't asked for rating yet if (!PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating) { if (ViewModel.CurrentAccount != null) { var dataStore = await AccountDataStore.Get(ViewModel.CurrentLocalAccountId); // If they actually have a decent amount of homework if (await System.Threading.Tasks.Task.Run(async delegate { using (await Locks.LockDataForReadAsync()) { return(dataStore.TableMegaItems.Count() > 30 && dataStore.TableMegaItems.Any(i => i.DateCreated < DateTime.Today.AddDays(-60))); } })) { var builder = new Android.App.AlertDialog.Builder(Context); builder .SetTitle("★ Review App ★") .SetMessage("Thanks for using Power Planner! If you love the app, please leave a rating in the Store! If you have any suggestions or issues, please email me!") .SetNeutralButton("Review", delegate { OpenReview(); }) // Neutral is displayed more prominently .SetPositiveButton("Email Dev", delegate { AboutView.EmailDeveloper(Context, base.ViewModel); }) .SetNegativeButton("Close", delegate { }); builder.Create().Show(); PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating = true; } } } } catch { } }
private async void LoadPastCompletedHomeworkAndExams() { if (_hasLoadedPastCompletedHomeworkAndExams) { return; } _hasLoadedPastCompletedHomeworkAndExams = true; try { var dataStore = await GetDataStore(); DataItemMegaItem[] additionalHomeworkAndExams; using (await Locks.LockDataForReadAsync()) { // Get the data items that we haven't loaded yet additionalHomeworkAndExams = dataStore.TableMegaItems.Where(IsPastCompletedHomeworkOrExamFunction(_classId, TodayAsUtc)).ToArray(); // Exclude any that are already loaded (due to the events being complicated to calculate whether they're incomplete, we end up double loading items that are on today) additionalHomeworkAndExams = additionalHomeworkAndExams.Where(a => !this.Class.HomeworkAndExams.Any(i => i.Identifier == a.Identifier)).ToArray(); // And then update the child function so that we include all homework for the class, and inject the new items this.Class.UpdateIsChildMethod <DataItemMegaItem, BaseViewItemHomeworkExam>(i => i.UpperIdentifier == _classId && i.MegaItemType == PowerPlannerSending.MegaItemType.Homework || i.MegaItemType == PowerPlannerSending.MegaItemType.Exam, additionalHomeworkAndExams); } // Include the opposite of the other function PastCompletedHomework = new PastCompletedHomeworkList(this.Class.HomeworkAndExams.OfTypeObservable <ViewItemHomework>(), TodayAsUtc); PastCompletedExams = new PastCompletedExamsList(this.Class.HomeworkAndExams.OfTypeObservable <ViewItemExam>(), TodayAsUtc); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }
public async Task HandleViewHolidayActivation(Guid localAccountId, Guid holidayId) { DataItemMegaItem holiday = await Task.Run(async delegate { using (await Locks.LockDataForReadAsync("HandleViewHolidayActivation")) { var dataStore = await AccountDataStore.Get(localAccountId); if (dataStore == null) { return(null); } return(dataStore.TableMegaItems.FirstOrDefault(i => i.MegaItemType == PowerPlannerSending.MegaItemType.Holiday && i.Identifier == holidayId)); } }); if (holiday != null) { var holidayDate = DateTime.SpecifyKind(holiday.Date, DateTimeKind.Local); var desiredDisplayMonth = holidayDate; var mainScreen = GetMainScreenViewModel(); if (mainScreen != null && mainScreen.CurrentAccount != null && mainScreen.CurrentAccount.LocalAccountId == localAccountId && mainScreen.Content is CalendarViewModel) { (mainScreen.Content as CalendarViewModel).DisplayMonth = desiredDisplayMonth; (mainScreen.Content as CalendarViewModel).SelectedDate = holidayDate; } else { NavigationManager.SetDisplayMonth(desiredDisplayMonth); NavigationManager.SetSelectedDate(holidayDate); await HandleSelectMenuItemActivation(localAccountId, NavigationManager.MainMenuSelections.Calendar); } } }
private async void TryAskingForRatingIfNeeded() { try { // If we haven't asked for rating yet if (!PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating) { if (ViewModel.CurrentAccount != null) { var dataStore = await AccountDataStore.Get(ViewModel.CurrentLocalAccountId); // If they actually have a decent amount of tasks if (await System.Threading.Tasks.Task.Run(async delegate { using (await Locks.LockDataForReadAsync()) { return(dataStore.TableMegaItems.Count() > 30 && dataStore.TableMegaItems.Any(i => i.DateCreated < DateTime.Today.AddDays(-60))); } })) { var alert = UIAlertController.Create( title: "★ Review App ★", message: "Thanks for using Power Planner! If you love the app, please leave a rating in the Store! If you have any suggestions or issues, please email me!", preferredStyle: UIAlertControllerStyle.Alert); alert.AddAction(UIAlertAction.Create("Review", UIAlertActionStyle.Default, delegate { PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating = true; PowerPlannerAppDataLibrary.Helpers.Settings.HasReviewedOrEmailedDev = true; TelemetryExtension.Current?.TrackEvent("PromptReviewApp_ClickedReview"); OpenStoreReview(); })); alert.AddAction(UIAlertAction.Create("Email dev", UIAlertActionStyle.Default, delegate { PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating = true; PowerPlannerAppDataLibrary.Helpers.Settings.HasReviewedOrEmailedDev = true; TelemetryExtension.Current?.TrackEvent("PromptReviewApp_ClickedEmailDev"); Settings.AboutViewController.EmailDeveloper(); })); alert.AddAction(UIAlertAction.Create("No thanks", UIAlertActionStyle.Cancel, delegate { PowerPlannerAppDataLibrary.Helpers.Settings.HasAskedForRating = true; TelemetryExtension.Current?.TrackEvent("PromptReviewApp_ClickedNoThanks"); })); PresentViewController(alert, true, null); } } } // If the user previously clicked No thanks, we'll try the new in-app review dialog else if (!PowerPlannerAppDataLibrary.Helpers.Settings.HasReviewedOrEmailedDev) { if (UIDevice.CurrentDevice.CheckSystemVersion(10, 3)) { // This will only sometimes show a dialog, at most 3 times a year // It will still display if they already rated, meaning users who previously clicked // No thanks on my own dialog will persistently get this dialog, but that should be ok StoreKit.SKStoreReviewController.RequestReview(); } } } catch { } }
public async void LoadHomeworkAndExams() { try { if (_hasHomeworkAndExamsBeenRequested) { return; } _hasHomeworkAndExamsBeenRequested = true; bool hasPastCompletedHomework = false; bool hasPastCompletedExams = false; SemesterItemsViewGroup cached = null; if (this.Class.Semester != null) { cached = SemesterItemsViewGroup.GetCached(this.Class.Semester.Identifier); } if (cached != null) { await cached.LoadingTask; DataItemMegaItem[] dataMegaItems = cached.Items .OfType <BaseViewItemHomeworkExam>() .Select(i => i.DataItem) .OfType <DataItemMegaItem>() .ToArray(); this.Class.AddHomeworkAndExamChildrenHelper(CreateHomeworkOrExam, ShouldIncludeHomeworkOrExamFunction(_classId, TodayAsUtc)); this.Class.FilterAndAddChildren(dataMegaItems); hasPastCompletedHomework = dataMegaItems.Any(IsPastCompletedHomeworkFunction(_classId, TodayAsUtc)); hasPastCompletedExams = dataMegaItems.Any(IsPastCompletedExamFunction(_classId, TodayAsUtc)); } else { await Task.Run(async delegate { var dataStore = await GetDataStore(); DataItemMegaItem[] dataHomeworks; using (await Locks.LockDataForReadAsync()) { dataHomeworks = dataStore.TableMegaItems.Where(ShouldIncludeHomeworkOrExamFunction(_classId, TodayAsUtc)).ToArray(); this.Class.AddHomeworkAndExamChildrenHelper(CreateHomeworkOrExam, ShouldIncludeHomeworkOrExamFunction(_classId, TodayAsUtc)); this.Class.FilterAndAddChildren(dataHomeworks); hasPastCompletedHomework = dataStore.TableMegaItems.Any(IsPastCompletedHomeworkFunction(_classId, TodayAsUtc)); hasPastCompletedExams = dataStore.TableMegaItems.Any(IsPastCompletedExamFunction(_classId, TodayAsUtc)); } }); } HasPastCompletedHomework = hasPastCompletedHomework; HasPastCompletedExams = hasPastCompletedExams; Homework = this.Class.HomeworkAndExams.Sublist(ShouldIncludeInNormalHomeworkFunction(TodayAsUtc)).Cast <ViewItemHomework>(); Exams = new MyObservableList <ViewItemExam>(); (Exams as MyObservableList <ViewItemExam>).InsertSorted( this.Class.HomeworkAndExams.Sublist(ShouldIncludeInNormalExamsFunction()).Cast <ViewItemExam>()); OnPropertyChanged(nameof(Homework)); OnPropertyChanged(nameof(Exams)); _loadHomeworkAndExamsCompletionSource.SetResult(true); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }
public async void LoadGrades() { try { if (_hasGradesBeenRequested) { return; } _hasGradesBeenRequested = true; await Task.Run(async delegate { try { var dataStore = await GetDataStore(); DataItemGrade[] dataGrades; DataItemMegaItem[] dataItems; using (await Locks.LockDataForReadAsync()) { Guid[] weightIds = this.Class.WeightCategories.Select(i => i.Identifier).ToArray(); dataGrades = dataStore.TableGrades.Where(i => weightIds.Contains(i.UpperIdentifier)).ToArray(); dataItems = dataStore.TableMegaItems.Where(i => (i.MegaItemType == PowerPlannerSending.MegaItemType.Exam || i.MegaItemType == PowerPlannerSending.MegaItemType.Homework) && i.UpperIdentifier == _classId && i.WeightCategoryIdentifier != PowerPlannerSending.BaseHomeworkExam.WEIGHT_CATEGORY_EXCLUDED) .ToArray(); var unassignedItems = new MyObservableList <BaseViewItemHomeworkExam>(); unassignedItems.InsertSorted(dataItems .Where(i => IsUnassignedChild(i)) .Select(i => i.MegaItemType == PowerPlannerSending.MegaItemType.Homework ? new ViewItemHomework(i) { Class = this.Class, WeightCategory = ViewItemWeightCategory.UNASSIGNED } as BaseViewItemHomeworkExam : new ViewItemExam(i) { Class = this.Class, WeightCategory = ViewItemWeightCategory.UNASSIGNED })); PortableDispatcher.GetCurrentDispatcher().Run(delegate { try { foreach (var weight in this.Class.WeightCategories) { weight.AddGradesHelper(ViewItemWeightCategory.CreateGradeHelper); weight.FilterAndAddChildren <BaseDataItemHomeworkExamGrade>(dataGrades); weight.FilterAndAddChildren <BaseDataItemHomeworkExamGrade>(dataItems); } Class.CalculateEverything(); UnassignedItems = unassignedItems; HasUnassignedItems = unassignedItems.Count > 0; _loadGradesTaskSource.SetResult(true); IsGradesLoaded = true; } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }); } } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } }
private async Task LoadBlocking(ViewItemSemester viewItemSemester, bool includeWeights) { var dataStore = await GetDataStore(); DataItemClass dataClass; DataItemClass[] dataClasses; DataItemSchedule[] dataSchedules; DataItemWeightCategory[] dataWeights; using (await Locks.LockDataForReadAsync("ClassViewItemsGroup.LoadBlocking")) { dataClasses = viewItemSemester.Classes.Select(i => i.DataItem).OfType <DataItemClass>().ToArray(); var viewClassRef = viewItemSemester.Classes.FirstOrDefault(i => i.Identifier == _classId); dataClass = viewClassRef?.DataItem as DataItemClass; if (dataClass == null) { throw new ClassNotFoundExcetion(); } dataSchedules = viewClassRef.Schedules.Select(i => i.DataItem).OfType <DataItemSchedule>().ToArray(); if (includeWeights) { // Get weights for ALL classes, since we need them for editing purposes when editing item to different class dataWeights = viewItemSemester.Classes.SelectMany(i => i.WeightCategories).Select(i => i.DataItem).OfType <DataItemWeightCategory>().ToArray(); } else { dataWeights = null; } Func <DataItemWeightCategory, ViewItemWeightCategory> createWeight = null; if (includeWeights) { createWeight = CreateWeight; } var classItem = new ViewItemClass( dataClass, createScheduleMethod: CreateSchedule, createWeightMethod: createWeight); classItem.FilterAndAddChildren(dataSchedules); if (includeWeights) { classItem.FilterAndAddChildren(dataWeights); } this.Class = classItem; _semester = new ViewItemSemester(dataClass.UpperIdentifier, createClassMethod: CreateClass); dataClasses = dataStore.TableClasses.Where(i => i.UpperIdentifier == _semester.Identifier).ToArray(); _semester.FilterAndAddChildren(dataClasses); // Add the weights for the other classes if (includeWeights) { foreach (var c in _semester.Classes.Where(i => i.Identifier != this.Class.Identifier)) { c.FilterAndAddChildren(dataWeights); } } } // If there were no weights in the class, we need to create and add a weight if (this.Class.WeightCategories != null && this.Class.WeightCategories.Count == 0) { TelemetryExtension.Current?.TrackEvent("Error_ClassMissingWeightCategoryAddingDefault"); DataChanges changes = new DataLayer.DataChanges(); changes.Add(AccountDataStore.CreateDefaultWeightCategory(this.Class.Identifier)); await PowerPlannerApp.Current.SaveChanges(changes); } }
private async Task ApplyFilterBlocking(DateTime prevStart, DateTime prevEnd, DateRange filterRequest) { DateTime newStart = filterRequest.Start; DateTime newEnd = filterRequest.End; DateTime notLoadedStart; DateTime notLoadedEnd; // We're only supporting where the date range shifts in one direction. // We're not supporting where the date range expands in both directions. if (newEnd > prevEnd) { notLoadedEnd = newEnd; if (newStart < prevEnd) { notLoadedStart = prevEnd.AddTicks(1); } else { notLoadedStart = newStart; } } else if (newStart < prevStart) { notLoadedStart = newStart; if (newEnd > prevStart) { notLoadedEnd = prevStart.AddTicks(-1); } else { notLoadedEnd = newEnd; } } else { return; } var dataStore = await GetDataStore(); using (await Locks.LockDataForReadAsync()) { // If the pending filter request has changed, do nothing if (_pendingFilterRequest != filterRequest) { return; } Guid[] classIdentifiers = Semester.Classes.Select(i => i.Identifier).ToArray(); DataItemMegaItem[] dataItems = dataStore.TableMegaItems.Where(ShouldIncludeItemFunction(classIdentifiers, notLoadedStart, notLoadedEnd)).ToArray(); // We need to dispatch to UI thread to actually change the collection try { Dispatcher.Run(delegate { // If the pending filter request has changed, do nothing if (_pendingFilterRequest != filterRequest) { return; } // Remove all that are no longer in the date range (don't worry about class changing since data didn't change here) Items.RemoveWhere(i => !ShouldIncludeItem(i, newStart, newEnd)); // Then add the new items foreach (var h in dataItems) { Add(h); } Start = newStart; End = newEnd; }); } catch (Exception ex) { TelemetryExtension.Current?.TrackException(ex); } } }
protected async Task LoadBlocking(Guid examId) { var dataStore = await GetDataStore(); if (dataStore == null) { throw new NullReferenceException("Account doesn't exist"); } DataItemMegaItem dataItem; // We need ALL classes loaded, including their schedules, and their weight categories. // Might as well just use ScheduleViewItemsGroup therefore. Guid semesterId; Guid classId = Guid.Empty; using (await Locks.LockDataForReadAsync("BaseSingleItemViewItemsGroup.LoadBlocking")) { dataItem = dataStore.TableMegaItems.FirstOrDefault(i => i.Identifier == examId); if (dataItem == null) { TelemetryExtension.Current?.TrackEvent("Error_LoadSingleItem_CouldNotFind", new Dictionary <string, string>() { { "ItemId", examId.ToString() } }); // Leave the Item set to null return; } if (dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Task || dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Event) { semesterId = dataItem.UpperIdentifier; classId = dataItem.UpperIdentifier; } else { var dataClass = dataStore.TableClasses.FirstOrDefault(i => i.Identifier == dataItem.UpperIdentifier); if (dataClass == null) { throw new NullReferenceException("Class not found. Item id " + examId); } semesterId = dataClass.UpperIdentifier; classId = dataClass.Identifier; } } _scheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(LocalAccountId, semesterId : semesterId, trackChanges : trackChanges, includeWeightCategories : true); // Grab the class for the item ViewItemClass viewClass; if (dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Task || dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Event) { viewClass = _scheduleViewItemsGroup.Semester.NoClassClass; } else { viewClass = _scheduleViewItemsGroup.Semester.Classes.FirstOrDefault(i => i.Identifier == classId); if (viewClass == null) { throw new NullReferenceException("ViewItemClass not found. Item id " + examId); } } // And create the item Item = CreateItem(dataItem, viewClass); }