/// <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> /// 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> /// 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> /// 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> /// 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> /// 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(); }