/// <summary> /// Handle event when user clicks delete quiz button. /// </summary> /// <param name="e"></param> private async void ButtonDelete_Clicked(string deleteType, string DBId) { if (CredentialManager.IsLoggedIn) { bool unsubscribe = deleteType == "Unsubscribe"; string question; string message; if (unsubscribe) { question = "Are you sure you want to unsubscribe?"; message = "This will remove the copy from your device"; } else { question = "Are you sure you want to delete this quiz?"; message = "This will delete the copy on your device and in the cloud. This is not reversable."; } bool answer = await this.DisplayAlert(question, message, "Yes", "No"); if (answer) { // Acquire QuizInfo from roster QuizInfo rosterInfo = QuizRosterDatabase.GetQuizInfo(DBId); // Author string path = rosterInfo.RelativePath; // tell the roster that the quiz is deleted QuizInfo rosterInfoUpdated = new QuizInfo(rosterInfo) { IsDeletedLocally = true, LastModifiedDate = DateTime.Now.ToString() }; QuizRosterDatabase.EditQuizInfo(rosterInfoUpdated); // If connected, tell server to delete this quiz If not, it will tell server to delete next time it is connected in QuizRosterDatabase.UpdateLocalDatabase() if (CrossConnectivity.Current.IsConnected) { OperationReturnMessage returnMessage; if (unsubscribe) { returnMessage = await SubscribeUtils.UnsubscribeFromQuizAsync(DBId); } else { returnMessage = await ServerOperations.DeleteQuiz(DBId); } if (System.IO.Directory.Exists(path)) { Directory.Delete(path, true); } this.Setup(); } } } else { await this.DisplayAlert("Hold on!", "You must be create an account or log in before you can unsubscribe", "OK"); } }
/// <summary> /// Unsubscribe from a quiz /// </summary> /// <param name="dbId">ID to unsub from</param> /// <returns>If the unsub was successful</returns> public static async Task <OperationReturnMessage> UnsubscribeFromQuizAsync(string dbId) { QuizInfo info = QuizRosterDatabase.GetQuizInfo(dbId); if (info.SyncStatus != (int)SyncStatusEnum.NotDownloadedAndNeedDownload) { string location = App.UserPath + "/" + info.Category + "/" + info.QuizName + "`" + info.AuthorName; if (Directory.Exists(location)) { Directory.Delete(location, true); } } OperationReturnMessage returnMessage = await Task.Run(async() => await ServerOperations.UnsubscribeToQuizAsync(dbId)); if (returnMessage == OperationReturnMessage.True) { QuizRosterDatabase.DeleteQuizInfo(dbId); return(returnMessage); } else if (returnMessage == OperationReturnMessage.FalseInvalidCredentials) { CredentialManager.IsLoggedIn = false; return(returnMessage); } else { return(returnMessage); } }
/// <summary> /// Handle when user clicks edit button /// </summary> private async void ButtonEdit_Clicked(string DBId) { QuizInfo info = QuizRosterDatabase.GetQuizInfo(DBId); if (!CredentialManager.IsLoggedIn) { await this.DisplayAlert("Hold on!", "Before you can edit any quizzes, you have to login.", "Ok"); } else if (info.SyncStatus == (int)SyncStatusEnum.NotDownloadedAndNeedDownload) { await this.DisplayAlert("Hold on!", "This quiz isn't on your device, download it before you try to edit it", "Ok"); } else { CreateNewQuizPage quizPage = new CreateNewQuizPage(info); //Create the quizPage quizPage.SetQuizName(info.QuizName); Quiz quizDB = new Quiz(info.DBId); foreach (Question question in quizDB.GetQuestions()) { quizPage.AddNewQuestion(question); } await this.Navigation.PushAsync(quizPage); } }
/// <summary> /// Sets up the page with quizzes the user has subscribed to from the category of the page /// </summary> public void Setup() { if (!this.IsLoading) { this.IsLoading = true; this.StackLayoutButtonStack.Children.Clear(); List <QuizInfo> quizzes = QuizRosterDatabase.GetRoster(this.category); if (quizzes.Count == 0) { Device.BeginInvokeOnMainThread(() => { StackLayout stack = new StackLayout(); stack.Children.Add(new Label { Text = "You don't have any quizzes in this category yet!", HorizontalTextAlignment = TextAlignment.Center, FontSize = 38 }); if (CredentialManager.IsLoggedIn) { stack.Children.Add(new Button { Text = "Make a quiz now", CornerRadius = 25, BackgroundColor = Color.Accent, TextColor = Color.White, FontSize = 26 }); (stack.Children[1] as Button).Clicked += (object sender, EventArgs e) => this.Navigation.PushAsync(new CreateNewQuizPage()); stack.Children.Add(new Button { Text = "Search for quizzes", CornerRadius = 25, BackgroundColor = Color.Accent, TextColor = Color.White, FontSize = 26 }); (stack.Children[2] as Button).Clicked += (object sender, EventArgs e) => this.Navigation.PushAsync(new SearchPage()); } Frame frame = new Frame() { CornerRadius = 10, HorizontalOptions = LayoutOptions.CenterAndExpand, Content = stack }; this.StackLayoutButtonStack.Children.Add(frame); }); } foreach (QuizInfo quiz in quizzes) { Frame frame = GenerateFrame(quiz); this.StackLayoutButtonStack.Children.Add(frame); } this.IsLoading = false; } }
/// <summary> /// Send a quiz to the server with the current user credentials. /// </summary> /// <param name="relativeQuizPath">The path to the quiz on the current device.</param> /// <returns>A bool wrapped in a task representing whether the quiz successfully sent or not.</returns> public async static Task <bool> SendQuiz(string relativeQuizPath) { try { string realmFilePath = Directory.GetFiles(App.UserPath + relativeQuizPath, "*.realm").First(); Realm realm = Realm.GetInstance(App.realmConfiguration(realmFilePath)); QuizInfo info = realm.All <QuizInfo>().First(); if (await SendRealmFile(realmFilePath) != OperationReturnMessage.True) { throw new Exception(); } string[] imageFilePaths = Directory.GetFiles(App.UserPath + relativeQuizPath, "*.jpg"); for (int i = 0; i < imageFilePaths.Length; i++) { //[0] = path, [1] = fileName, [2] = dBId string fileName = imageFilePaths[i].Split('/').Last().Split('.').First(); string dbID = info.DBId; OperationReturnMessage message = await SendImageFile(imageFilePaths[i], fileName, dbID); if (message == OperationReturnMessage.False) { throw new Exception(); } } // When finished, confirm with server that quiz send has completed OperationReturnMessage finalizationMessage = (OperationReturnMessage)SendStringData( $"{info.DBId}`{info.LastModifiedDate}`{imageFilePaths.Length + 1}`" + $"{CredentialManager.Username}`{await SecureStorage.GetAsync("password")}`-", ServerRequestTypes.FinalizeQuizSend); if (finalizationMessage == OperationReturnMessage.True) { QuizInfo infoCopy = new QuizInfo(info) { SyncStatus = (int)SyncStatusEnum.Synced }; QuizRosterDatabase.EditQuizInfo(infoCopy); return(true); } else { throw new Exception(); } } catch (Exception ex) { string test = ex.ToString(); // Alert server that quiz send failed Delete records return(false); } }
/// <summary> /// When a user wants to unsubscribe from a quiz /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void ImageButtonUnsubscribe_Clicked(object sender, EventArgs e) { if (CredentialManager.IsLoggedIn) { ImageButton button = (sender as ImageButton); string dbId = button.StyleId; bool answer = await this.DisplayAlert("Are you sure you want to unsubscribe?", "You will no longer get updates of this quiz", "Yes", "No"); if (answer) { ActivityIndicator indicatorSyncing = (button.Parent as StackLayout).Children[(int)SubscribeUtils.SubscribeType.Syncing] as ActivityIndicator; button.IsVisible = false; indicatorSyncing.IsVisible = true; indicatorSyncing.IsRunning = true; // get rosterInfo QuizInfo rosterInfo = QuizRosterDatabase.GetQuizInfo(dbId); // tell the roster that the quiz is deleted QuizInfo rosterInfoUpdated = new QuizInfo(rosterInfo) { IsDeletedLocally = true, LastModifiedDate = DateTime.Now.ToString() }; QuizRosterDatabase.EditQuizInfo(rosterInfoUpdated); OperationReturnMessage returnMessage = await SubscribeUtils.UnsubscribeFromQuizAsync(dbId); if (returnMessage == OperationReturnMessage.True) { (button.Parent as StackLayout).Children[(int)SubscribeUtils.SubscribeType.Subscribe].IsVisible = true; // add in subscribe button QuizRosterDatabase.DeleteQuizInfo(dbId); } else if (returnMessage == OperationReturnMessage.FalseInvalidCredentials) { button.IsVisible = true; await this.DisplayAlert("Invalid Credentials", "Your current login credentials are invalid. Please log in and try again.", "OK"); } else { button.IsVisible = true; await this.DisplayAlert("Unsubscribe Failed", "The unsubscription request could not be completed. Please try again.", "OK"); } indicatorSyncing.IsVisible = false; indicatorSyncing.IsRunning = false; } } else { await this.DisplayAlert("Hold on!", "Before you can subscribe to any quizzes, you have to login.", "Ok"); } }
/// <summary> /// Deletes the quiz from the roster /// </summary> private async Task ButtonDelete_Clicked(string DBId) { bool answer = await this.DisplayAlert("Are you sure you want to delete this quiz?", "This will delete the copy on your device and in the cloud. This is not reversable.", "Yes", "No"); if (answer) { // Acquire QuizInfo from roster QuizInfo rosterInfo = QuizRosterDatabase.GetQuizInfo(DBId); string path = rosterInfo.RelativePath; if (rosterInfo != null) { string dbId = rosterInfo.DBId; // tell the roster that the quiz is deleted QuizInfo rosterInfoUpdated = new QuizInfo(rosterInfo) { IsDeletedLocally = true, LastModifiedDate = DateTime.Now.ToString() }; QuizRosterDatabase.EditQuizInfo(rosterInfoUpdated); // If connected, tell server to delete this quiz If not, it will tell server to delete next time it is connected in QuizRosterDatabase.UpdateLocalDatabase() OperationReturnMessage returnMessage = await ServerOperations.DeleteQuiz(dbId); if (returnMessage == OperationReturnMessage.True) { QuizRosterDatabase.DeleteQuizInfo(dbId); } if (System.IO.Directory.Exists(path)) { Directory.Delete(path, true); } this.QuizNumber.Text = "You have published a total of " + await Task.Run(() => ServerOperations.GetNumberOfQuizzesByAuthorName(CredentialManager.Username)) + " quizzes!"; } else { await DisplayAlert("Could not delete quiz", "This quiz could not be deleted at this time. Please try again later", "OK"); } // Setup Page again after deletion await this.UpdateProfilePageAsync(); } }
/// <summary> /// Saves updates to a quizInfo /// </summary> /// <param name="editedQuizInfo">the new version of the quizinfo to save</param> public void EditQuizInfo(QuizInfo editedQuizInfo) { Realm realmDB = Realm.GetInstance(App.realmConfiguration(this.dbPath)); realmDB.Write(() => { realmDB.Add(editedQuizInfo, update: true); }); QuizInfo rosterCopy = new QuizInfo(editedQuizInfo) { SyncStatus = (int)SyncStatusEnum.NeedUpload // Default to 1, meaning "needs upload" in roster }; QuizRosterDatabase.EditQuizInfo(rosterCopy); }
/// <summary> /// Show an activity indicator and refresh the page in the background. /// </summary> /// <returns></returns> public async Task RefreshPageAsync() { await this.StackLayoutButtonStack.FadeTo(0, 1); this.ActivityIndicator.IsVisible = true; this.ActivityIndicator.IsRunning = true; this.isSetup = false; await Task.Run(() => QuizRosterDatabase.UpdateLocalDatabaseAsync()); this.CheckSetup(); this.ActivityIndicator.IsVisible = false; this.ActivityIndicator.IsRunning = false; await this.StackLayoutButtonStack.FadeTo(1, 1); }
/// <summary> /// Called when the user tries to download a quiz /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void SyncDownload_Clicked(object sender, EventArgs e) { // this.serverConnected = true; ImageButton button = sender as ImageButton; string dbId = button.ClassId; QuizInfo quizInfo = QuizRosterDatabase.GetQuizInfo(dbId); // DOES THIS WORK? while (quizInfo == null && Plugin.Connectivity.CrossConnectivity.Current.IsConnected) { await QuizRosterDatabase.UpdateLocalDatabaseAsync(); quizInfo = QuizRosterDatabase.GetQuizInfo(dbId); } string authorName = quizInfo.AuthorName; string quizName = quizInfo.QuizName; string category = quizInfo.Category; ActivityIndicator indicatorSyncing = (button.Parent as StackLayout).Children[(int)UISyncStatus.Syncing] as ActivityIndicator; string quizPath = button.ClassId; button.IsVisible = false; indicatorSyncing.IsVisible = true; indicatorSyncing.IsRunning = true; if (await Task.Run(() => ServerOperations.GetQuiz(dbId, category))) { ImageButton buttonSyncNoChange = (button.Parent as StackLayout).Children[(int)UISyncStatus.NoChange] as ImageButton; indicatorSyncing.IsVisible = false; buttonSyncNoChange.IsVisible = true; (((button.Parent as StackLayout).Parent as StackLayout).Parent as Frame).StyleId = "Local"; } else // If it failed to download { indicatorSyncing.IsVisible = false; button.IsVisible = true; await this.DisplayAlert("Quiz Download Failed", "This quiz could not be downloaded from the server. Please try again.", "OK"); } indicatorSyncing.IsRunning = false; await this.UpdateProfileContentAsync( this.SelectedCategory); }
/// <summary> /// Subscribes to a quiz given the ID /// </summary> /// <param name="dbId">the ID of the quiz to sub to</param> /// <param name="quizzesSearched">the quizzes currently displayed (used to get info about the quiz from the dbid)</param> /// <returns>If the subscription was successful</returns> public static async Task <OperationReturnMessage> SubscribeToQuizAsync(string dbId, List <QuizInfo> quizzesSearched) { if (QuizRosterDatabase.GetQuizInfo(dbId) == null) // make sure it isn't in yet { OperationReturnMessage returnMessage = await Task.Run(async() => await ServerOperations.SubscribeToQuiz(dbId)); if (returnMessage == OperationReturnMessage.True) { QuizInfo quiz = quizzesSearched.Where(quizInfo => quizInfo.DBId == dbId).First(); string lastModifiedDate = await Task.Run(() => ServerOperations.GetLastModifiedDate(dbId)); QuizInfo newInfo = new QuizInfo { DBId = quiz.DBId, AuthorName = quiz.AuthorName, QuizName = quiz.QuizName, Category = quiz.Category, LastModifiedDate = lastModifiedDate, SyncStatus = (int)SyncStatusEnum.NotDownloadedAndNeedDownload // 4 to represent not present in local directory and need download }; QuizRosterDatabase.SaveQuizInfo(newInfo); return(returnMessage); } else if (returnMessage == OperationReturnMessage.FalseInvalidCredentials) { CredentialManager.IsLoggedIn = false; return(returnMessage); } else { return(returnMessage); } } else { return(OperationReturnMessage.False); } }
/// <summary> /// Sets up the quizzes owned by this user as cards /// </summary> private async Task SetupQuizzes(string category) { await QuizRosterDatabase.UpdateLocalDatabaseAsync(); // A single LINQ statement to get all quizzes by the current // user that is logged in, and of the specified category, // taking the top 20 of the current chunk ordered by // the subscriber count of the quizzes List <QuizInfo> rosterCopy = QuizRosterDatabase.GetRoster(); List <QuizInfo> quizzes = rosterCopy. Where( quizInfo => (quizInfo.AuthorName == CredentialManager.Username && (quizInfo.Category == category || category == "All"))). OrderBy(quizInfo => quizInfo.SubscriberCount). Take(20 * this.currentChunk).ToList(); this.AddQuizzes(quizzes, false); }
/// <summary> /// Create a new quizinfo and adds it to the Quiz DB. /// A copy is stored in the device quiz roster. /// </summary> /// <param name="authorName">Author</param> /// <param name="quizName">Quiz name</param> /// <param name="category">Category</param> public void NewQuizInfo(string authorName, string quizName, string category) { QuizInfo newQuizInfo = new QuizInfo(authorName, quizName, category) { // Sync status is irrelevant in a Quiz Database's copy of the QuizInfo SyncStatus = -1 }; this.QuizInfo = newQuizInfo; Realm realmDB = Realm.GetInstance(App.realmConfiguration(this.dbPath)); realmDB.Write(() => { realmDB.Add(newQuizInfo); }); QuizInfo rosterCopy = new QuizInfo(newQuizInfo) { SyncStatus = (int)SyncStatusEnum.NeedUpload // Default to 1, meaning "needs upload" in roster }; QuizRosterDatabase.SaveQuizInfo(rosterCopy); }
/// <summary> /// Handle when user presses "three dot" icon on the quiz tab /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void ImageButtonMenu_Clicked(object sender, EventArgs e) { string DBId = ((ImageButton)sender).ClassId; QuizInfo quizInfo = QuizRosterDatabase.GetQuizInfo(DBId); string quizName = quizInfo.QuizName; string author = quizInfo.AuthorName; string deleteText = "Delete"; if (author != CredentialManager.Username) { deleteText = "Unsubscribe"; } string action = await this.DisplayActionSheet(quizName, "Back", null, deleteText, "Edit"); if (action == deleteText) { this.ButtonDelete_Clicked(((ImageButton)sender).StyleId, ((ImageButton)sender).ClassId); } else if (action == "Edit") { this.ButtonEdit_Clicked(DBId); } }
/// <summary> /// Update local data through synchronzing data with server. /// Runs on a timed background task and repeats a synchronization every two minutes. /// </summary> /// <returns></returns> public static async Task RunServerChecksAsync() { await CredentialManager.CheckLoginStatusAsync(); await Task.Run(async() => await QuizRosterDatabase.UpdateLocalDatabaseAsync()); var minutes = TimeSpan.FromMinutes(2); Device.StartTimer(minutes, () => { Task task = Task.Run(async() => { if (CredentialManager.IsLoggedIn) { await CredentialManager.CheckLoginStatusAsync(); } await QuizRosterDatabase.UpdateLocalDatabaseAsync(); BugReportHandler.SubmitSavedReports(); }); // Return true to continue the timer return(true); }); }
/// <summary> /// Download a quiz from the server. /// </summary> /// <param name="dBId">The DBId of the quiz to download</param> /// <param name="category">The category the quiz belongs in.</param> /// <returns></returns> public static bool GetQuiz(string dBId, string category) { // TO DO: CHECK IF quizName or category changed and save accordingly string tempPath = App.UserPath + "/" + "temp" + "/" + dBId + "/"; string tempFilePath = tempPath + "/" + realmFileExtension; // Store the realm file into a temporary directory in order the retrieve information from it // (Information regarding the images in order to retrieve them from the server) Directory.CreateDirectory(tempPath); byte[] realmFile = (byte[])SendStringData($"{dBId}/-", ServerRequestTypes.GetRealmFile); if (realmFile.Length > 0) { File.WriteAllBytes(tempFilePath, realmFile); } else { return(false); } // Retrieve info regarding the images from the realm file from its temporary location Realm realmDB = Realm.GetInstance(App.realmConfiguration(tempFilePath)); IQueryable <Question> questionsWithPictures = realmDB.All <Question>().Where(question => question.NeedsPicture); foreach (Question question in questionsWithPictures) { byte[] jpegFile = (byte[])SendStringData($"{question.QuestionId}/{dBId}/-", ServerRequestTypes.GetJPEGImage); string jpegFilePath = tempPath + "/" + question.QuestionId + jpegFileExtension; if (jpegFile.Length > 0) { File.WriteAllBytes(jpegFilePath, jpegFile); } else { return(false); } } QuizInfo info = realmDB.All <QuizInfo>().First(); string newQuizName = info.QuizName; string newCategory = info.Category; string newLastModfiedDate = info.LastModifiedDate; string quizPath = info.RelativePath; string realmFilePath = quizPath + "/" + info.DBId + realmFileExtension; Directory.CreateDirectory(quizPath); string[] imageFilePaths = Directory.GetFiles(tempPath, "*.jpg"); string[] realmFilePaths = Directory.GetFiles(tempPath, "*.realm"); foreach (string path in realmFilePaths) { File.Copy(path, quizPath + "/" + info.DBId + realmFileExtension, true); } foreach (string path in imageFilePaths) { string imageName = path.Split('/').Last(); File.Copy(path, quizPath + "/" + imageName, true); } if (category != newCategory) { DeleteDirectory(info.RelativePath, true); } DeleteDirectory(tempPath, true); QuizInfo infoCopy = new QuizInfo(QuizRosterDatabase.GetQuizInfo(dBId)) { SyncStatus = (int)SyncStatusEnum.Synced, QuizName = newQuizName, Category = newCategory, LastModifiedDate = newLastModfiedDate }; QuizRosterDatabase.EditQuizInfo(infoCopy); return(true); }
/// <summary> /// Select database file for the current game/topic, Load the questions from file /// </summary> public Quiz(string DBId) { this.QuizInfo = QuizRosterDatabase.GetQuizInfo(DBId); this.LoadQuestions(); }
/// <summary> /// Adds a quiz to the search stack given a QuizInfo /// </summary> /// <param name="quizzes"></param> private void AddQuizzes(List <QuizInfo> quizzes) { List <QuizInfo> currentlySubscribed = QuizRosterDatabase.GetRoster(); foreach (QuizInfo quiz in quizzes) {// Only add quiz if the category is what user picked (we are asking the server for more then we need so this could be changed) if (this.category == "All" || quiz.Category == this.category) { Frame quizFrame = new Frame { VerticalOptions = LayoutOptions.Start, HorizontalOptions = LayoutOptions.FillAndExpand, CornerRadius = 10 }; StackLayout frameStack = new StackLayout { FlowDirection = FlowDirection.LeftToRight, Orientation = StackOrientation.Vertical }; StackLayout topStack = new StackLayout { FlowDirection = FlowDirection.LeftToRight, Orientation = StackOrientation.Horizontal }; Label quizName = new Label // 0 { Text = quiz.QuizName, FontAttributes = FontAttributes.Bold, FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), HorizontalOptions = LayoutOptions.StartAndExpand }; topStack.Children.Add(quizName); ImageButton ImageButtonSubscribe = new ImageButton // 1 { IsVisible = false, Source = "ic_playlist_add_black_48dp.png", StyleId = quiz.DBId, HeightRequest = 30, BackgroundColor = Color.White, HorizontalOptions = LayoutOptions.End }; ImageButtonSubscribe.Clicked += this.ImageButtonSubscribe_Clicked; topStack.Children.Add(ImageButtonSubscribe); ImageButton ImageButtonUnsubscribe = new ImageButton // 2 { IsVisible = false, Source = "ic_playlist_add_check_black_48dp.png", StyleId = quiz.DBId, HeightRequest = 30, BackgroundColor = Color.White, HorizontalOptions = LayoutOptions.End }; ImageButtonUnsubscribe.Clicked += this.ImageButtonUnsubscribe_Clicked; topStack.Children.Add(ImageButtonUnsubscribe); ActivityIndicator Syncing = new ActivityIndicator // 3 { IsVisible = false, Color = Color.Accent, HeightRequest = 25, WidthRequest = 25, VerticalOptions = LayoutOptions.StartAndExpand, HorizontalOptions = LayoutOptions.End, }; topStack.Children.Add(Syncing); if (quiz.AuthorName != CredentialManager.Username) { // If already subscribed if (!(currentlySubscribed.Where(quizInfo => quizInfo.DBId == quiz.DBId && !quizInfo.IsDeletedLocally).Count() > 0)) { ImageButtonSubscribe.IsVisible = true; } else { ImageButtonUnsubscribe.IsVisible = true; } } frameStack.Children.Add(topStack); Label quizAuthor = new Label { Text = "Created by: " + quiz.AuthorName, }; frameStack.Children.Add(quizAuthor); Label quizCategory = new Label { Text = "Category: " + quiz.Category, }; frameStack.Children.Add(quizCategory); quizFrame.Content = frameStack; this.quizzesSearched.Add(quiz); Device.BeginInvokeOnMainThread(() => this.SearchedStack.Children.Add(quizFrame)); } } }
/// <summary> /// Loads the profile content if the user is logged in. /// </summary> /// <returns> </returns> private async Task UpdateProfileContentAsync(string category) { if (!this.IsContentLoading) { this.IsContentLoading = true; this.QuizNumber.IsVisible = true; this.PickerCategory.IsVisible = false; this.PickerCategory.IsEnabled = false; this.StackLayoutQuizStack.Children.Clear(); this.StackLayoutQuizStack.IsEnabled = false; this.ActivityIndicator.IsVisible = true; this.ActivityIndicator.IsRunning = true; await Task.Run(async() => { await this.SetupQuizzes(category); int createdCountFromServer = ServerOperations.GetNumberOfQuizzesByAuthorName(CredentialManager.Username); string frameMessage = ""; if (createdCountFromServer >= 0) // Returns -1 if can't connect to server { if (createdCountFromServer == 0 && !QuizRosterDatabase.GetRoster() .Any(quizInfo => quizInfo.AuthorName == CredentialManager.Username)) { frameMessage = "You haven't made any quizzes yet!"; Device.BeginInvokeOnMainThread(() => { this.PickerCategory.IsVisible = false; this.QuizNumber.IsVisible = false; }); } else { Device.BeginInvokeOnMainThread(() => { this.QuizNumber.Text = "You have published a total of " + createdCountFromServer + " quizzes!"; this.PickerCategory.IsVisible = true; this.PickerCategory.IsEnabled = true; }); } } else { frameMessage = "Could not connect to BizQuiz servers. Please try again later."; Device.BeginInvokeOnMainThread(() => { this.PickerCategory.IsVisible = true; this.PickerCategory.IsEnabled = true; }); } if (frameMessage != "") { Frame frame = new Frame() { CornerRadius = 10, HorizontalOptions = LayoutOptions.CenterAndExpand, Content = new Label { Text = frameMessage, HorizontalTextAlignment = TextAlignment.Center, FontSize = 38 } }; Device.BeginInvokeOnMainThread(() => this.StackLayoutQuizStack.Children.Add(frame)); } }); if (this.ToolbarItems.Count <= 0) { ToolbarItem accountSettingsButton = new ToolbarItem(); accountSettingsButton.Clicked += this.ToolbarItemAccountSettings_Clicked; accountSettingsButton.Icon = ImageSource.FromFile("ic_settings_white_48dp.png") as FileImageSource; this.ToolbarItems.Add(accountSettingsButton); } this.IsOnLoginPage = false; this.ActivityIndicator.IsRunning = false; this.ActivityIndicator.IsVisible = false; this.StackLayoutQuizStack.IsEnabled = true; this.IsContentLoading = false; } }