//Gets recent posts via backend methods and displays them in a ListView //it is setup in a way so that if there is no changes, it won't bother with an API call private async void DisplayList() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IRecentPostsBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { if (app.PostsMod.Count != 0) { lblSubTitle.IsVisible = false; lstRecentPosts.ItemsSource = app.PostsMod; //ListView itemsource set to collection from backend } else { lblSubTitle.IsVisible = true; //If no items, display an "empty" message } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to display recent posts", "Ok"); } }
//Gets the post associated with the comment selected in the ListView via backend methods, API call is made containing the postId stored within the comment private async void GetPost(Comments commentInfo) { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ICommentHistoryBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var post = await app.GetPost(commentInfo.PostId); await Navigation.PushAsync(new ViewPostPage(post)); //ViewPostPage is pushed onto the stack, takes in the post info } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to retrieve post info", "Ok"); } }
//Begins the update process, uses dependency injection via lifetimescope to access methods from the backend private async void BeginUpdate() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IAccountBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var validation = app.CheckInfo(txtUsername.Text, txtEmail.Text, txtName.Text, txtOldPassword.Text, txtNewPassword.Text); //New info sent to backend for validation if (validation == null) { var user = await app.Update(txtUsername.Text, txtEmail.Text, txtName.Text, txtNewPassword.Text); //New info sent to backend for API call to update user in db await DisplayAlert("Update Successful", "Successfully updated, please log back in again", "Ok"); BeginLogout(); } else { await DisplayAlert("Invalid or Empty Field(s)", $"{validation}", "Ok"); } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to update info", "Ok"); } }
//Begins the login process, uses dependency injection via lifetimescope to access methods from the backend private async void BeginLogin() { try //Try the following code below { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ILoginBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var validation = app.CheckInfo(txtUsername.Text, txtPassword.Text); //Uname and pword sent to backend for validation if (validation == null) { var user = await app.Login(txtUsername.Text, txtPassword.Text); //Uname and pword sent to backend for API call to get the user out of the db if (user != null) { if (swtchRememberLogin.IsToggled == true) //If "Remember Me" button is toggled, store uname and pword for auto login { await Storage.LocalStorage.WriteTextFileAsync("username.txt", user.Uname); await Storage.LocalStorage.WriteTextFileAsync("password.txt", user.Pword); } btnSignin.IsEnabled = false; actIndicator.IsRunning = true; App.user = user; //Stores the user info into a public static IUser to use "globally" throughout the app //These three lines of code are for pushing a new instance of a page ontop of the nav stack then removing the previous page in the stack var previousPage = Navigation.NavigationStack.LastOrDefault(); await Navigation.PushAsync(new MainPage()); //Navigates to the MainPage Navigation.RemovePage(previousPage); actIndicator.IsRunning = false; } else { await DisplayAlert("Login Details Incorrect", "Login details are incorrect, please try again", "Ok"); //Displays alert for incorrect login info } } else { await DisplayAlert("Invalid or Empty Field(s)", $"{validation}", "Ok"); } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to login", "Ok"); } //If an exception is thrown, catch it and display an alert (Try Catches prevent the app from crashing when an exception is thrown) }
private async void RemoveFromList(object sender, EventArgs e) { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IDetailedPageBackend>(); // Creating an object of the sender ( In this case its a button ) var btn = (Button)sender; // Resets variables string choice = string.Empty; bool success = false; // By checking the senders ID i can see which button sent the click event if (btn.Id == btnRemoveComp.Id) { // Changes choice to "Played" // Since my DeleteFromWishlistPlayed is generic it needs to know which table to delete data from choice = "Played"; success = await app.DeleteFromWishlistPlayed(_errorHandling, choice, playedID); // Changes the buttons to no longer remove from played it will now be add to played if (success) { btnCompleted.IsVisible = true; btnRemoveComp.IsVisible = false; } } else if (btn.Id == btnRemoveWish.Id) { // Changes choice to "Wishlist" // Since my DeleteFromWishlistPlayed is generic it needs to know which table to delete data from choice = "Wishlist"; success = await app.DeleteFromWishlistPlayed(_errorHandling, choice, wishlistID); // Changes the buttons to no longer remove from played it will now be add to played if (success) { btnWishlist.IsVisible = true; btnRemoveWish.IsVisible = false; } } // Displays an alert showing that the item has been added if (success) { await DisplayAlert("Item Removed", $"Removed {game.name} from {choice}", "Ok"); } } } catch (Exception ex) { _errorHandling(ex.Message); } }
//Gets all comments by user via backend methods and displays them in a ListView private async void DisplayList() { try { actIndicator.IsRunning = true; container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ICommentHistoryBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { if (app.CommentsMod.Count != 0) { lblSubTitle.IsVisible = false; Comments = app.CommentsMod; //List is set to collection from the backend if (Comments.Count >= 10) //If Else statements which limit how much items are displayed, if more than 10, limit to 10, if not then put them into collection { for (int i = minItems; i < maxItems; i++) //For loop allows adding items to a limit of 10 { CommentsMod.Add(app.CommentsMod[i]); } } else { foreach (var item in app.CommentsMod) //If less than or equal to 10, it'll just put the items into the collection { CommentsMod.Add(item); } } lstCommentHistory.ItemsSource = CommentsMod; //ListView itemsource set to collection } else { lblSubTitle.IsVisible = true; //If no items, display an "empty" message } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } actIndicator.IsRunning = false; } } catch { await DisplayAlert("Error", "Something went wrong, unable to display user post history", "Ok"); } }
// This method manages logging in public async void LoginFunction() { // Validation check if (string.IsNullOrEmpty(txtUsername.Text)) { _errorHandling("Please enter a username"); } else if (string.IsNullOrEmpty(txtPassword.Text)) { _errorHandling("Please enter a password"); } else { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { // If the user wants to be remember then the option is saved to their local storage var option = chkRemember.IsChecked ? "true" : "false"; await Storage.WriteTextFileAsync(App.detailsLocation, option, _errorHandling); var app = scope.Resolve <ILoginBackend>(); var user = await app.GetUser(txtUsername.Text, txtPassword.Text, _errorHandling); // This is a shorthand version of an if else statement i had in my program, This way is less code and also works faster // Technically it is the same as the if else statement commented out below but is much faster var temp = user != null ? (App.isLoggedIn = true, App.user = user) : (App.isLoggedIn = false, App.user = new User()); // if the user is logged in then it will push the main page // If not then there will be an error message if (temp.Item1) { await Navigation.PushAsync(new MainPage()); } // Below is an expanded version of the code above //if (user != null) //{ // App.isLoggedIn = true; // App.user = user; // await Navigation.PushAsync(new MainPage()); //} //else //{ // App.isLoggedIn = false; // App.user = new User(); //} } } }
// Linked to the submitChanges button private async void ChangeUserInfo() { // Validates info entered if it isnt empty // If it is then it will display a appropriete error if (string.IsNullOrEmpty(txtUname.Text)) { _displayError("Please enter a username"); } else if (string.IsNullOrEmpty(txtFName.Text)) { _displayError("Please enter your first name"); } else if (string.IsNullOrEmpty(txtLName.Text)) { _displayError("Please enter your last name"); } else if (string.IsNullOrEmpty(txtEmail.Text)) { _displayError("Please enter your email"); } else if (string.IsNullOrEmpty(txtPwrd.Text)) { _displayError("Please enter a password"); } else { // Informs the user their account is being updated await DisplayAlert("Progress", "Updating Account Now", "Ok"); container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ISettingsBackend>(); var success = await app.UpdateUser(new User { Id = App.user.Id, UName = txtUname.Text, Email = txtEmail.Text, FName = txtFName.Text, LName = txtLName.Text, Pwrd = txtPwrd.Text }, _displayError); // If they user was updated successfully if (success) { await DisplayAlert("Updated!", "Your details have been updated!", "Ok"); } } } }
//Event handler method which updates the post upon clicking either UpVote or DownVote button via backend methods, returns the updated post private async void UpdatePost(object sender, EventArgs e) { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IViewPostBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var btn = (Button)sender; //Stores the button info into the var //If Else statements which determine what code to do based on which button was pressed if (btn == btnUpVote) { btnUpVote.IsEnabled = false; var updatedPost = await app.UpVote(post); //Post is sent to backend, API call made to update post in db, returns the updated post //These three lines of code are for pushing a new instance of a page ontop of the nav stack then removing the previous page in the stack var previousPage = Navigation.NavigationStack.LastOrDefault(); await Navigation.PushAsync(new ViewPostPage((Posts)updatedPost)); //Re-navigates to ViewPostPage with the updatedPost (Converted from an IPost to a Post) Navigation.RemovePage(previousPage); } else if (btn == btnDownVote) { btnDownVote.IsEnabled = false; var updatedPost = await app.DownVote(post); //Post is sent to the backend, API call made to update post in db, returns the updated post //These three lines of code are for pushing a new instance of a page ontop of the nav stack then removing the previous page in the stack var previousPage = Navigation.NavigationStack.LastOrDefault(); await Navigation.PushAsync(new ViewPostPage((Posts)updatedPost)); //Re-navigates to ViewPostPage with the updatedPost (Converted from an IPost to a Post) Navigation.RemovePage(previousPage); } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to upvote or downvote", "Ok"); } }
//Gets post and the comments for this specific post via backend methods and displays them in a ListView private async void DisplayList() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IViewPostBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { post = await app.GetPost(post.Id); //API call made from backend to get the post from the db via postId //Binds the post info to frontend labels for display lblPageTitle.Text = "Post By: " + post.Uname; lblTopic.Text = post.Topic; lblPostTitle.Text = post.Title; lblPostContent.Text = post.Content; btnUpVote.Text = "+" + post.UpVote.Count().ToString(); btnDownVote.Text = "-" + post.DownVote.Count().ToString(); app.GetCommentsInfo(post.Id); //Gets the comments for the post by taking in the post id and making API call to the db lstComments.ItemsSource = app.CommentsList; //Populates ListView itemsource with backend collection //If Else statements which display the amount of comments on the post if (app.CommentsList.Count == 0) { lblCommentCounter.Text = "No Comments Have Been Posted Yet"; } else if (app.CommentsList.Count == 1) { lblCommentCounter.Text = app.CommentsList.Count.ToString() + " Comment on Post"; } else { lblCommentCounter.Text = app.CommentsList.Count.ToString() + " Comments on Post"; } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to display comments", "Ok"); } }
// Gets the information from the Played table private async void PopulateInfo() { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve<IWishlistPlayedBackend>(); if (App.isLoggedIn) // If the user isnt logged in there wouldnt be anything to display (They shouldnt be able to enter this page anyway but better safe then sorry) { var items = await app.GetPlayed(_errorHandling, App.user.Id); if (items != null) lstGames.ItemsSource = items; } else _errorHandling("Please log in to view this"); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Rhinodoor_backend", Version = "v1" }); c.CustomSchemaIds(type => type.ToString()); }); DependancyInjection.Inject(ref services); services.AddDbContext <DatabaseContextAbstract>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); }
protected void Application_Start() { DependancyInjection.Setup(); AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); Mapper.CreateMap <Image, ImageModel>(); Mapper.CreateMap <Album, AlbumModel>(); Mapper.CreateMap <GalleryItem, BaseGalleryModel>() .Include <GalleryItemImage, GalleryImageModel>() .Include <GalleryItemAlbum, GalleryAlbumModel>(); Mapper.CreateMap <GalleryItemImage, GalleryImageModel>(); Mapper.CreateMap <GalleryItemAlbum, GalleryAlbumModel>(); }
//Begins the post creation process, post is created via backend methods private async void BeginPost() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ICreatePostBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var validation = app.CheckInfo(txtTopic.SelectedItem.ToString(), txtTitle.Text, txtMessage.Text); //Post sent to backend for validation if (validation == null) { btnPost.IsEnabled = false; var createdPost = await app.CreatePost(txtTopic.SelectedItem.ToString(), txtTitle.Text, txtMessage.Text); //Post sent to backend for API call to post in db, returns post var post = (Posts)createdPost; //Converts post from IPost (Interface of a model) to a Post (Post model) var previousPage = Navigation.NavigationStack.LastOrDefault(); await Navigation.PushAsync(new ViewPostPage(post)); //ViewPostPage is pushed onto the stack, takes in the post info Navigation.RemovePage(previousPage); } else { await DisplayAlert("Invalid or Empty Field(s)", $"{validation}", "Ok"); } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to create post, please try again", "Ok"); } }
//Begins the registration process, uses dependency injection via lifetimescope to access methods from the backend private async void BeginRegistration() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IRegisterBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { var validation = app.CheckInfo(txtUsername.Text, txtEmail.Text, txtName.Text, txtPassword1.Text, txtPassword2.Text); //Info sent to backend for validation if (validation == null) { btnSignup.IsEnabled = false; await app.Register(txtUsername.Text, txtEmail.Text, txtName.Text, txtPassword2.Text); //Info is sent to backend for API call to register user in the db await DisplayAlert("Registration Successful", "Account successfully registered, please login", "Ok"); //These three lines of code are for pushing a new instance of a page ontop of the nav stack then removing the previous page in the stack var previousPage = Navigation.NavigationStack.LastOrDefault(); await Navigation.PushAsync(new LoginPage()); //Navigates back to the LoginPage Navigation.RemovePage(previousPage); } else { await DisplayAlert("Invalid or Empty Field(s)", $"{validation}", "Ok"); } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to register", "Ok"); } }
//Begins the process of sending a comment, API call is made to post the comment to the db private async void BeginComment() { try { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IViewPostBackend>(); var network = scope.Resolve <IConnectionBackend>(); if (network.HasConnection()) //If Else statements which determine if you have internet connection, if you do then continue, if you don't then display an alert { if (!String.IsNullOrWhiteSpace(txtComment.Text)) { btnSend.IsEnabled = false; await app.PostComment(txtComment.Text, post.Id); //Comment is sent to the backend (contains postId to get post when needed), API call made to post comment in db lstComments.BeginRefresh(); //Refreshes ListView when new comment has been sent and added txtComment.Text = ""; btnSend.IsEnabled = true; } else { return; } } else { await DisplayAlert("No Internet Access", "Connection to network not found, please try again", "Ok"); } } } catch { await DisplayAlert("Error", "Something went wrong, unable to send comment", "Ok"); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); DependancyInjection.Register(services); }
private async void InsertInfo(string id) { container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <IDetailedPageBackend>(); // If the app is using the custom API then it makes different calls if (App.useCustomAPI) { game = await app.GetCustomGame(id, _errorHandling); if (game != null) // No need for an else, if its null DisplayError will handle the error on its own { if (App.isLoggedIn) { var isWishlist = await app.IsOnWishlist(_errorHandling, (Game)game, App.user.Id); // This will change the visibility of buttons, so if the game is on the wishlist it will change the button being displayed to Remove From Wishlist as opposed to Add To Wishlist btnRemoveWish.IsVisible = isWishlist; // If the isWishlist is true then set the button visibility to false ? means (Condition ? If its true do this : if its false do this) btnWishlist.IsVisible = isWishlist ? false : true; var isPlayed = await app.IsOnPlayed(_errorHandling, (Game)game, App.user.Id); btnRemoveComp.IsVisible = isPlayed; btnCompleted.IsVisible = isPlayed ? false : true; } // Below just fills the xaml with text, Binding wouldnt work here as i need to filter through lists lblGameName.Text = game.name; lblGenre.Text = game.Genre; lblDeveloper.Text = game.Developer; // This filters through each platform in the list then concatenates it to the lblPlatforms.Text to be displayed foreach (var item in game.Platform) { lblPlatforms.Text += $"{item}, "; } lblRating.Text = game.Rating.ToString(); // Gets the image from a URI (Does not display (Unknown reason, no error given)) imgGamePhoto = new Image() { Aspect = Aspect.AspectFit, Source = ImageSource.FromUri(new Uri(game.background_image)) // This gets the image from the webpage and displays it }; lblSummary.Text = game.Summary; } } else // Uses Rawg API { var game = await app.GetGame(id, _errorHandling); // Changes button visibility since you can not add Rawg API items to the db btnCompleted.IsVisible = false; btnRemoveComp.IsVisible = false; btnWishlist.IsVisible = false; btnRemoveWish.IsVisible = false; if (game != null) { // Assigns variables to be displayed lblGameName.Text = game.name; lblGenre.Text = game.genres.First().name; lblDeveloper.Text = game.publishers.First().name; // Concatonates the platform name to the string to be displayed foreach (var item in game.platforms) { lblPlatforms.Text += $"{item.platform.name}, "; } lblRating.Text = game.rating.ToString(); // Gets the image from a URI (Does not display (Unknown reason, no error given)) imgGamePhoto = new Image() { Aspect = Aspect.AspectFit, Source = ImageSource.FromUri(new Uri(game.background_image)) }; lblSummary.Text = game.description; } } } }
// Used to search for items // Searches through different databases depending on what option is chosen private async void ItemSearch(string search) { if (!activityIndicator.IsRunning) { activityIndicator.IsRunning = true; container = DependancyInjection.Configure(); using (var scope = container.BeginLifetimeScope()) { var app = scope.Resolve <ISearchBackend>(); if (App.useCustomAPI) { // gets all games that match the search allGames = await app.GetCustomGames(search, _errorHandling); if (allGames != null) { // Limits how many items are displayed at a time so the user can load more by scrolling down if (allGames.Count >= 10) { // If their is more than 10 items then it will scroll through all items and add them to the Observeable collection // Grabing them out based on index for (int i = minItems; i < maxItems; i++) { games.Add(allGames[i]); } } else { // If there is less than 10 items in the list it will grab all items // As 10 is the minimum amount of items to be shown it would crash if their was less than 10 items // This will handle it in the case of less than 10 items foreach (var item in allGames) { games.Add(item); } } // Sets the item source of the ListView to display the info lstGames.ItemsSource = games; } } else { // Rawg Api returns an IGameRootObject var temp = await app.GetGames(search, _errorHandling); allResults = temp.results; if (allResults != null) { // Limits how many items are displayed at a time so the user can load more by scrolling down if (allResults.Count >= 10) { // If their is more than 10 items then it will scroll through all items and add them to the Observeable collection // Grabing them out based on index for (int i = minItems; i < maxItems; i++) { results.Add(allResults[i]); } } else { // If there is less than 10 items in the list it will grab all items // As 10 is the minimum amount of items to be shown it would crash if their was less than 10 items // This will handle it in the case of less than 10 items foreach (var item in allResults) { results.Add(item); } } lstGames.ItemsSource = results; } } activityIndicator.IsRunning = false; } } }