Flutter Firebase Course | Realtime Chat App Using Firebase & Flutter Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in today's video I'm going to be showing you guys how to harness the part of flutter and Firebase to create a fully functional real-time chat application our application is going to be a mobile app that's going to be able to run on both Android and iOS and we're going to be using Firebase as our back end and taking a look at all of the core components of it to create a fully functional chat application by the end of this video you're going to be an expert not only in using Firebase but flutter as well so with this said let's actually take a look at the application that we're going to be building and all of the features that it's going to have when the user starts our application they'll have the ability to log in using an account that they had already created and if users haven't already signed up to our application then they can provide us with a picture a name an email and a password and then register on our application since I already have a user created I'm just going to quickly log in using their credentials and when we are presented with the homepage you can see that we have a list of all of the users available on our application that we can have a chat with if there is a user that we already have a conversation with in this case let's just say for example Denzel then it's going to pull up the chat history for us and we will be able to see where we had left off and then continue our conversation from there and in the case that a user we have never had a conversation with and we start a conversation with them such as Robert for example then we have an empty chat history and we'll be able to start a conversation with them so now on the other simulator I have actually done zel's account logged in and he's talking with George and here I have George logged in and he's talking with Denzel so let's send a message and see if actually George just going to get it on the other device or not so I'm like hey man how's it going long time no see and as you can see as soon as I send the message with the power of cloud fire store you can see that the message get sense to Denzel and Denzel can see what the message is now I can say that I am on vacation like so and check this out and and now using the image button here I can actually send an image message so I'm going to select an image and as soon as I click on that image it's going to send that to Denzel as you can see here and it's going to show the picture of the account that the message was received from so in this case George sent it to Denzel um as well as timestamps for all of the messages when they were sent what the dates for them was and everything like that so with this said that's pretty much all there is when it comes to the functionality of the application we're going to be taking a look at using all of the major components of Firebase so these include but are not limited to how to work with Firebase authentication how to work with the fir store database as well as how to work with Firebase storage and I'm also going to be showing you how you can work with Firebase analytics as well so with this said let's get into the video and let's start coding this application to get going with actually writing this application the first step is going to be to initialize an empty flutter project as you can see I've already done that and I have the boilerplate code that the flutter create command gives you opened up in WIS Cod code and I also have a simulator running on the right hand side of the screen where I'm going to be testing my application if you are confused as to how to get started with the flutter SDK or how you can actually create an empty flutter project or the basics of flutter then I already have tutorials for all of these topics on my channel so I'll leave links to them down in the description below and you can take a look at these videos if you want to learn about how to install the flutter SDK on your operating system or what the basics of flutter is so once you have an empty flutter project created the next thing that we are going to be doing is actually taking a look at all of the dependencies that we are going to be using throughout building our project so for that what I've done is that I've actually opened up Google Chrome and I'm going to be showing you guys each of the dependencies one by one and then I'm going to be explaining to you guys a little bit about what these dependencies are so as you know that we are going to be using Firebase as our backend then the first dependency for our project is going to be a package called Firebase core so I'll copy this dependency I'll come back to pope. file and then I'm going to browse to the section which says dependencies and then copertino icons I'm going to be pasting in the Firebase core package once this is done another package that we're going to be using from Firebase is going to be Firebase o and the name is pretty self-explanatory this is going to allow us to implement authentication abilities within our application and it's going to be crucial for us to implement features such as login and registering we're also going to be using the cloud fir store database so for that we also need the cloud fir store plugin which is going to allow us the functionality to actually interact with this database so I'm going to be adding that as well and moving forwards we're also going to be using the Firebase storage plug-in so that we can actually upload files to Firebase such as images or videos so I'll copy this come back and do the same thing as I've been doing before we're going to be using a incredible package called Dash chat 2 which is going to allow us to create a stunning chat UI with bare minimum code and this is the actual package that we're going to be using on our actual chat page to render our messages and the UI so it's an incredibly useful package and I highly recommend it so we're going to be using that as well so I'll copy this dependency come back and paste it in as well and as always links to all of the resources that I mentioned within this video as well as a link to the source code can be found in the description below so feel free to take a look at it if you're confused at any point moving onwards from Dash chat we are going to be using another Firebase plugging which is called Firebase analytics and this is basically going to allow us to implement analytics based functionality within our application and see various analytics on our application to change the font within our application we're going to be using the Google fonts package so let's copy and paste that in so you can already see that this tutorial is going to be jam-packed with a bunch of useful information to show toast within our application such as a user successfully logging in or as a user doing an operation which isn't allowed we're going to be using the delightful toast package which is an excellent package for showing toast within your flutter application and for those who don't understand what a toast it you can think of it as has a pop-up message that appears to a user when they perform a certain action as you can see here on the screen so let's copy that come back and add the delightful toast dependency as well once this is done we're going to be also using the geted package and for those of you who do not know what the geted package is Well the description here is pretty good this is a simple service locator for DOT and flutter projects with some additional goodies so it's going to allow us to basically register instances or Singleton instances of various service classes that we're going to be creating and for now it might sound a bit confusing but you'll understand more about what these classes are and what they do and what services are within an application so to achieve that functionality of registering Services we're going to be using a service locator package called get it so let's copy that come back and add this as a dependency as well and finally we're also going to be using the image picker package to actually Implement image picking functionality within our application and access our devic's gallery and the path package which is going to allow us to basically Implement some functionality of retrieving path for different files names and stuff like that so pretty much these are all of the dependencies that we require for building our application so once I've added all of these dependencies I'm going to do command save and it's automatically going to understand that I've made some changes to the pspec EML file since I have the flutter extension installed within Visual Studio code and it's automatically going to call flutter pupg which is a command that's going to go browse through my pspec DML file see all of the dependencies I have go to the appropriate sources and get the code for these dependencies and put that within my project if for any case you have this command not running automatically for example you don't have the flutter extension installed then a fix for V code is going to be that you can come to the extensions tab type in flutter here and then install the first extension that you see here which is going to be flutter that from D code.org and this is basically going to implement this functionality within your IDE as well as some other useful features that you need for FL development but if you don't want to delve into that then what you can do is basically open up a new terminal instant go to the root of your project and here what you can do is type in flutter Pub get and this is basically going to do the same thing as the command that we had run before so now that we have the packages within our actual project the next thing that we're going to be doing is changing some things on the Android side of things so that our app builds properly for Android and I believe that for iOS we don't have to change anything so to do this I will firstly come to the Android folder and and then I'll come to app build.gradle and here what I'm going to be doing is coming down to the section where I have default config and I'm trying to change the minimum SDK version to 21 and do command save once this is done before we proceed any further what I'd like to do is open the main. do file which is within my lip folder and basically give a test run to my application with all of the new dependencies that we've added and make sure that our application works as intended so I'm going to start debugging it and once the application is running on the simulator then I will resume the video welcome back everybody so as you can see that the application is running successfully on the simulator and I can see that the hot reload functionality is working as well if I come to the main do do file and then where I'm passing a title to my homepage I can change that to be XYZ if I do command save the H reload functionality is working as well so we know that our application is working as intended and we can move on to the next step which is to integrate Firebase with our flutter application to integrate Firebase with a flut application the first thing that you have to do is make sure that you have the Firebase CLI installed on your system and if you're confused with how to do this I already have a video for this on my channel as well so I'll leave a link to that in the description as well but if you're more of an advanced user then what you can do is just head on over to this website a link to this will be down in the description below as well it's firebase.com CLI and here you can basically click on the operating system which you have and then download the Firebase CLI for that so once you have the CLI installed the next thing that you can do is basically basically come to a terminal window and I'm going to be using the terminal window within Visual Studio code and make sure that you're within the root directory of your project and then type in a command which is going to be Firebase like so and then d-el and if you get an output similar to what you're seeing for my output which is basically a bunch of different commands that I can use on the Firebase CLI tool that means that the Firebase CLI was installed correctly you can also do Firebase D- version if I believe leave so and this is going to basically show to you the actual version of the Firebase CLI tools that are installed on your system then what you're going to be doing is making sure that you have logged in to a Firebase account using your Firebase CLI so for that you'll use a command called Firebase and then I'm going to do log out first so log out from my existing account and then I'm going to do Firebase login to log to an account as soon as I do this it's going to ask me do I allow Firebase to collect C an emulator Suite usage information you can do yes or no um this is just analytics information and then it's going to automatically open up on your browser a window through which you'll be able to authenticate with the Firebase CLI and here you need to select the appropriate account under which you're going to be creating your Firebase project so in my case I'll select the account and as soon as I do that there you have it let me show you the screen it's showing to me that hey signing into Firebase CA I'll be like continue and once this is done I'm going to say allow for the permissions and it's going to say woohoo Firebase CLI login successful I can close down this window and here it's giving me an output as well saying that success it was able to log in as the user that I had authenticated as so then I can do clear and I can move on to the next step so for the next step what we're going to be doing is actually activating the flutter fire CLI which is going to be the tool which is going to make it very easy for us to integrate our flut project with Firebase but before we do that let's quickly go to our Firebase console and basically create a new Firebase project here so what you're going to be doing is coming to a website called console. firebase.com and then you're going to come to the point where it says add project I'm going to click here and then I'm going to give my project a name so I'm going to give my project name of Firebase chat app tutorial let's just say and then I will click on continue I'll unable Google analytics account I'll do default account for fire base create the project and I'll let this actual process finish and then I will resume the video Welcome Back everybody so as you can see that the initialization process for our project was completed and our project is now ready so I'm going to click on continue and it's going to navigate me to the actual dashboard where I can manage my Firebase project so for now you can see that there's nothing much that is actually configured for this project so I'm going to minimize the browser window and come back to my flutter project now we can come back to the step that I had mentioned previously which was to activate our flutter fire CLI so for that basically you're going to make sure that you're within the root directory of your folder open up a new terminal window to open up terminal on Visual Studio code you can do terminal new terminal like so and it's going to open up a new terminal instance and here what you're going to be doing is typing D pub Global activate and then I'm going to do flutter fire and then underscore CLI like so and press enter as soon as I do this it's going to go ahead resolve this package for me make sure that this package is available and then activate this flutter fire CLI plug-in for me so I can move onwards to the next step now which is to use this actual flutter fire CLI and then configure my Firebase project so to do this all I'm going to be doing making sure that I'm within the root directory of my flutter project is flutter fire configure and as soon as I do this and press enter it's going to start the configuration process for the account that I had used in the previous step to log in it's going to go ahead and F the Firebase projects for me and then I can use the arrow keys to actually navigate through these projects and select the appropriate one I'm going to be using the one that I just created which is fair chat app tutorial and then I'm going to use enter to select and then we can move on to the next step which it's going to ask us which are the platforms that we're going to be supporting so in this case I just want Android and iOS so I'll use the arrow keys to go up and down and then to select and deselect I can use the space bar so I'll unselect Mac OS unselect web and once I made the appropriate selections I can press enter and continue it's going to go ahead and do everything seamlessly for me making sure that all of the registration processes are done for the Android and iOS side of things as well as all of the config files are created and everything like that and at the end it's going to let me know that the process was complete so I'll wait for this process to complete and then I will resume the video Welcome Back everybody so as you can see what's the flutter flyer CLI has done what it has to do is going to give you an output saying that the Firebase configuration file was created under lip Firebase options do dot as you can see and that it generated the following Firebase IDs for our Android app and IOS app so at this done this pretty much means that all of the configuration was done properly and we don't have to do anything else so with this done what I'm now going to be doing is doing the final step in the configuration process which is to actually just initialize the Firebase plugins and make sure that everything works as I had intended so to do that what I am going to be doing is coming to my lip folder and I'm going to be creating a new file here called utils doart once I've created this file within this I'm going to create a function which will return the future void it's going to be called setup Firebase it's going to have no parameters pass to it it will be an asnc function and I'll open up the functions body within this I will do await and then I will do Firebase Dot and then I will do initialize app but before I can do that I got to import Firebase from the Firebase core package so let's quickly do that and then initialize app and for initialize app I'm going to pass in the options property and the options are going to be default Firebase options and then current platform so it's automatically deduce what the options are going to be based upon the current platform and this information is going to come from the Firebase options. Dell that the flo fire CLI automatically generated for us so with this done let's do command save let's come back to our main doart file and in in my main do do file what I'm going to be doing is before I actually call the run app function within the main function I'm going to make sure that the setup function is called before that so to do that I am going to create a new function within main do do which again is going to return a future void it's going to be called setup like so it's also going to be an asynchronous function and within this what I'm going to do is firstly call a function called widgets flutter binding. insure initialized and then after this I'm going to do await and then we'll use the function that we have defined within u. called setup Firebase like so with this done I will do command save I'll come back to my main function and then here what I'm going to be doing is saying await setup so wait for the setup to complete and then we're going to move on to the run app function and I'm going to Mark the main function as a synchronous as well and do command save so with this done that's pretty much all we had to do the last thing that I am going to be doing is actually importing the Firebase analytics package as well at the very top so for that I'll just type in Firebase analytics press enter now the analytics package has been imported and then I can just remove that here and do command save then I will restart my application not hot reload it so once the application restarts and if you get no errors that pretty much means that the configuration process was successful we were able to successfully initialize our Firebase plug-in as well and now our flut project is communicating with Firebase so with this done that's pretty much it when it comes to configuring our project to work with Firebase and now we can move on to the next steps which is to create the login page to begin building our login page I'm going to be dividing it into two parts firstly we're going to be taking a look at everything we need to do to construct the UI for our login page and then we'll actually move onwards to actually adding logic within it so that we can authenticate our user and navigate them to our homepage so to get started you can come to the lip folder and here you can create a new folder called pages and underneath of pages I'm going to create a new file which is going to be loginor page. then I will create a stateful widget within this file and it's going to be called login page then for the build function of this login page State instead of returning a placeholder I'm going to be returning a scaffold and the actual body for this scaffold is going to be a call to a function called build UI like so so now that I've done this the next thing that I'm going to be doing is basically defining this function it's going to be called build UI like so and then I'm going to say that I will return a safe area widget and then the child for this is going to be an actual padding widget like so and then the padding for this I'm just going to copy and paste it in like so so now that this is done let's define the child for our padding widget so child is going to be a column and the reason we are using a column is because we are going to be having multiple children and these children need to be aligned in a vertical Manner and to do that we're we're going to be using a column so now that I have a column defined I'm going to leave the code as it is for now and let's actually integrate this login page within our actual main. file so that we can navigate to it so for now what we're going to do is come back to our main. file and here for the home property I'm going to be setting that to be our login page now so let's do that like so and once this is done I am also going to remove the my homepage stateful class at the corresponding State class as we're not going to be using it and now our main file should just have the actual my app class as well as our setup function and main function within it and I'll do command save now that this is done as soon as I do this the application H reloads and we can see a blank page that's actually our login page on the simulator screen so we can move onwards to The Next Step the first thing that I'm going to be doing is actually creating the widgets which are going to display our title so for that what I'm going to be doing is creating a function and I'm going to call this underscore header text and then I'm going to say that for this I am going to return a sized box and then before I do anything for the size box I'll take my header text and I'll add that as the first child within our column like so and do command save then for the size box I'll Define the width and I'll set the width to be the width of the device like so and by the way if you're confused as to what's going on right now with all of these media queries and different widgets that I'm using or how the actual widget tree is being built and you're a complete beginner to the flutter framework then I highly recommend that you take a look at my flutter and do crash course a link to that will be down in the description below and once you have actually completed that course then this is going to make much more sense to you so continuing forwards now what we can do is actually Define the child for our sized box and this time it's going to be a column like so and it's going to have a children's list and the reason we are using a column is because if I show you our actual UI we are going to have two different text one is going to be dis bolded hi welcome back and then it's going to be hello again so to do that we're going to be using a column within my column I'm just going to quickly Define the main axis size the cross AIS alignment and the main axis alignment to be the following and then after this I will copy and paste in the actual text widget like so so the first one is going to be high willcome back and then the styling on this is going to be Tex stle with phone size 20 and font weighs w800 now that this is done I'm going to add the next text as well which is going to be basically another text which is going to say hello again you've been missed but this time the phone size will be 15 font weight will be w500 and the color will be gray so now that we've defined our header text I can see that there's an issue with the actual phone that's being displayed here as opposed to what's actually being shown on our screenshots so let's quickly update the phones for our application so they look much pretty and much nicer than what's currently going on if you remember at the start of the video we had used the Google phones package and actually added that to the dependency section of our pope. yaml file so this is the package we're going to be using to basically update the phones for our flutter application to update the phone I'm going to come to my main. Dart file and I'm going to come to the section where we have our my app class and specifically where we have the build function and we're turning a material app and on the material app we have the theme property and we're basically going to be modifying some properties on the them property so that the phone gets updated and more spefic specifically we are going to be updating the textt theme property on our actual theme data and I'm going to set that equal to Google fonts and this is going to be the class that is going to come from the package which is Google fonts like so and then on this we can select a whole bunch of different text teams if you want to take a look at all of the different options that are available to you then what you can do is actually come to a website called fonts. google.com and here you can take a look at all of the different fonts that are available to you under Google fonts I already have made my selection so what I'm going to be doing is coming back and basically saying that my preferred font of choice is going to be this Monster Rat and then I am going to do text team like so and that's pretty much it that's all we had to do so with this done make sure that you invoke this function do command save and as soon as we do this after some time you're going to see that the phone gets downloaded and then the phone gets replaced for our application the last thing that I'm going to be doing is also updating the seed color for my theme data so instead of doing colors. d purple I'm going to do colors. blue and this is going to make sure that my application conforms to the color scheme that I had specified before so now that this is done we can come back to our login page and continue onwards with building our actual U so the next step in the process is going to be this text field and these are going to allow us to basically input information regarding our email and password since we are going to be using this actual widget at multiple different points within our application and The Styling for this is not going to change CH much as you can see we're using this actual text field on our login page and then we're also using them on our register page it makes sense for us to actually create this into its own reusable component and then use it at various different points within our application so to do that what we are going to be doing is actually coming through our lip folder and actually creating a folder here and I'm going to call this widgets and within this folder I'm going to create a new file called custom form field. Dart like so and then I will create a stateless class within this and I'm going to call this the same name that I had named my file which is custom form field like so and do command save then within the build function what I'm going to be doing instead of returning a placeholder I will be returning a text form field like so and before we proceed any further let's actually do command save let's come back to our login page let's actually add this custom widget that we've created to our to our login page so to do this I'll come to the very bottom of my state class I'll say that I'm going to be creating a function that returns a fidget it's going to be called login form like so and then I'll open up its body within this what I'm going to be doing firstly is making sure that I return a container with a specified height and margin so let me do that and then what I'm going to be doing is actually defining the child for this container like so and the child for this container is going to be a form widget we'll come to what a form widget is but for now just add a form widget and then we'll specify what the child for this form widget is as well so the child in this case is going to be a column widget and the reason for that is because within our form we are going to have a bunch of different elements namely we're going to have a form field for an email a form field for a password and then a login button so to arrange them in a vertical manner we'll use a column then again I'll Define the children's list here and here I'm going to say that we're going to add our custom form field like so and that that's pretty much all we had to do so with this Al do command save we won't do anything else we'll take our login form we'll come back to our build UI function to the column after the header text at the login form and there you have it we're actually able to see our input field for our form so one thing that you can actually notice is when we click on this form field we get this overflow error where it says that the bottom overflowed by 9 pixels a quick way to fix this would be to actually come to our actual scaffold and then then set the resize to aoid bottom inser property to be false like so and as soon as we do this and command save or you could actually wrap all of the UI within a single child scroll view that's also possible this is going to fix that overflow error that we were seeing before so we can now proceed to The Next Step so the next step is to actually update The Styling for this form field so it looks pretty so for that what we're going to be doing is coming back to our custom form field widget and then defining some properties on this text form field for the properties what I'm going to be doing is basically setting the decoration property we're going to Define input decoration and then on the input decoration I'm going to set the border and the border is going to be const outline input border like so and then I'll do command save and there we have it now we are seeing a text form field with an outlined border the next thing that I want to do is actually Implement some logic so that we can actually show some hint text as to what is the type of data that needs to be inputed within this field so to do this what we'll do is actually come back to our custom form field and we know that we want our custom form field to be a reusable widget so this means that when this actual custom form field gets constructed we need to pass to it what the actual hint text is going to be since we're going to be using this widget at various different places for various different use cases and not every time are we going to be just inputting emails within this form field then it makes sense that when we initialize our custom form field then we pass the hint text and then we can display that hint text so to do that on my custom form field I going to define a property which is going to be final string and it's going to be called hint text like so then on the actual Constructor I'm going to say that a named argument is going to be sent to this actual custom form field it's going to be required and it's going to be this. hint text so it's going to take the hint text that gets passed it's going to put that within this variable and then we can come back to our input decoration and I can set the hint text property here to be the hint text like so and do command save then we can come back to our login page go to the point where we are actually adding our custom form field set the hint text property here and now I can do email and do command save and there we have it now we have a field that shows us email so the power of this is let's just say that I want to show the same custom from field but this time I want to show the hint text as password all I have to do is copy and paste this and I can just change the hint text to be password and now we have another distance of the custom form field but this time it's showing us password so that's the actual beauty of doing things the way we are doing it I can see that there's some spacing issues here within our column so let's quickly fix that so I'll copy and paste these properties in I'm going to set the main access size to be main access size. Max the main AIS alignment to be main access alignment. space evenly then the cross AIS alignment to be cross Access alignment. Center and do command save and there we have it now it's looking fantastic so now I can click on these email field password field and I can add information within this and everything looks the way it's supposed to look so the next thing that I'm going to be doing is actually setting a custom size on these form Fields because right now they're taking a lot of space so to do that what I'll do is I'll come back to my custom form field and on my custom form field I'm basically going to be wrapping the text form field widget within a sized box so to do that I will basically right click on it and then I can do refactor or or I can do control shift r on Mac and I don't know the actual shortcut for Windows but it should be something similar to this um and it's going to pop up the same menu which is the refactor so either right click refactor or you can do command shift R and then I'm going to wrap this with a sized box and once this is done I'm going to set the height property here to be a height that gets passed in so to do that I'll do the same thing I'll come to the top I will Define a property it's going to be final double and I am going to say that it's going to be height and then I will say that it's also going to be a named parameter that gets passed to us called the this. height like so and then I will say that we'll set the height to be the height that gets passed to command save come back to our login page and our login page I can set the height to be 1% of the height of the screen or I should say 10% so to do that I'll set the height to be mediocre that size of context. height time 0.1 so this will be 10% of the height of the screen and and then I'll do the same again to command save and there we have it now the sizing has been fixed and everything is looking good so now we can move onwards to the next step and that is to actually create the login button so let's do that I'll create another function that returns a widget I'm going to say that this is going to be called login button and then I'll open up its body and within this what I'm going to be doing is basically saying that we're going to be returning a size box widget and that's going do have a child and then I can add the remaining bracket first and then the child here is going to be basically a material button like so then on the material button I'm going to define the onpressed call back so what basically happens when we press this button and for now that's going to be an empty function and then we can move onwards to The Styling of this but before that let's actually add this to our form so let's come to our login form form column then after after the custom form Fields let's add our login button and there we have it we can actually see that something changed but we still can't see it so we'll quickly fix that so to fix that let's quickly update the color for this so to update the color I'll set the color property to be theme do off context Dot and then I'm going to do color scheme do primary so I'm basically getting the primary color from our color scheme that's defined on on our context I should say so there we have it we can see the button now now I'm going to add some text to the button so for that I'll Define a child property I'll set this is going to be const and then I'll just paste in the text widget because it's very simple all it is is a simple text widget which says the actual text login and it has Tex stle with the color white and there we have it now we have our login button showing as well so the last thing that we have to do is actually add the link at the bottom of our page which is going to be saying don't have an account then you can sign up so let's do that to do that what I'm going to be doing is basically creating another function which is going to be called create an account link it's going to return a widget and within this I'm going to say that I'm going to return an expanded widget an expanded widget basically takes up all of the available space to it that it can within its parent and then the child here is going to be a row widget and the reason we're using a row widget is because we are going to have two different texts one is going to be this not bold one and then one is going to be a bold one which is also going to have have an actual gust detector attached on it that's going to allow us to detect clicks on it and then navigate to our signup page so for that we are going to be using a row because the row is going to allow us to put multiple children in a horizontal Manner and align them so the row is now going to have a text widget and the first one is just going to be the simple text widget that's going to say don't have an account like so but before I can add this text widget what I need to do is actually set the children's list and then add this text widget within that so so now that this is done let's actually take our create an account link go to the very top where we have our build UI and then after our login form we can add this function call and do command save and there we have it we can see don't have an account then you can sign up I can see that there are some styling issues so let's quickly fix that so to fix them what I'm going to be doing is setting the main access size on the road to be main access size. Max the main access alignment to be main Access alignment. Center and the cross access alignment to be cross access alignment. n and do command save and there we have it now it's centered and at the bottom so now what I can do is actually add the remaining text so after this what I'm going to be doing is basically adding another text and this time it's going to be a text that says sign up and it's going to have some styling applied to it where we just change the phone size to be w800 and that's pretty much it for now I can mark the actual expanded widget as a const and that's going to be pretty much it so with this we've pretty much created complete UI for our login page besides the fact that it's not functional right now so now we're going to be proceeding to the step of actually adding all of the business logic to this so that we can make this a functioning UI to begin the process of actually implementing the login logic within our application we are going to be implementing a service which is going to contain authentication related code within it which then we can reference at different points within our application to login the user or register the user and things like that so what I basically want to do is create some kind of class that is going to contain all of the logic which pertains to logging in a user registering a user and things like that and then we can use this class at multiple different points within our application whenever we want to maybe log in the user log out the user or get access to the user the way we're going to be doing this is by using the get it package and then registering a class or a service I should say within it and then we're going to be using this get it package again whenever we want to access this service and perform operations that are available in it so if it sounds a bit confusing do not worry I'm going to show you step by step what we're going to be doing and the reason I'm building the application this way is so that one I can show you good coding practices and do how to produce commercial grade applications that are written in a good manner and all of the code is broken down into separate parts each pertaining to a specific thing in our application so to get going let's do this let's actually come to a LIF folder let's create a new folder here and let's call it services and within Services I am going to be creating a new file and I'm going to call this _ service. Dart so once this is done what I'm going to be doing now is actually just creating a class within this and this class is going to be called OD service like so and then I'll open up the class definition within the class all I'm going to be doing for now is basically creating the Constructor for the class by doing odd service and then for now let's just say that it's not going to create any parameters pass to it and the body for the Constructor will also be empty now that this is done let's actually implement the login function between in our OD service class and then we're going to be taking a look at how we can use it later on so what I want to do is basically make this class reusable and composable so what I want to do is basically create some kind of universal login method that basically takes in an email and a password and then performs the login operation for us so what I'm going to do is basically say that we're going to have a function which will return a future and it's going to be a Boolean value that's going to be returned to us it's going to be called login and we're going to have two things that are going to be passed to us a email in the type of string and then a string password as well and once we have the actual email and password passed to us then we can use the actual Firebase o package to perform our login operation I'm going to be opening up a TR and clatch block just to make sure that I cat any errors in the case that our actual authentication fails and then within the tri block I am actually going to be writing our authentication code now so what I want to do is basically first get access to our Firebase Au package and the specific spefically the instance on it for Firebase o and then we can use that to actually log in our user so to do that what I will do is firstly I will come to the top of my class and here what I'm going to be doing is basically saying that we're going to have a final variable it's going to be of type Firebase o and then I'm going to say that's going to beore Firebase o like so and then I'm going to be setting this equal to Firebase Au and then I am going to do do instance like so and then it's going to give me an error saying that Firebase Au is not defined so what I can do is actually just import the package in so let me just quickly import the package and there we have it now the error should be fixed once we have access to our Firebase Au instance what I can do is come back to my login function and here I'm going to be doing Firebase off Dot and on this we have a function called sign in with and then it's going to be email and password and here we're just going to pass the email and password to this function once this is done what I'm going to be doing is basically saving the result that we get from this function within a variable so I'll do final credential equals to await Firebase Au and then sign in with password email and password and I'll mark this function as a stress once this is done the next thing that I'm going to be doing is basically saying that if the credential do user is not equal to null then we basically can be sure that the login operation was successful and what I can do is return true otherwise what we'll do is that if we reach the very end of this function then we'll return false like so and the final thing I want to do is basically save a reference on my odd service class the actual user that's currently logged in so to do that what I'll do is create a property on the OD service class which is going to be optional it's going to be of type user this class actually comes from Firebase H and it's going to be optional which means the user can be null I'll say underscore user and then within the actual login function I'm going to basically within this if statement say that we'll set the user to be equal to credential do user like so and do command save and that's pretty much it the last thing that I'm going to be doing is basically defining a getter function for our user so to do that I'll say that we'll have a getter function it's going to return a user which is going to be optional it's going to be get user and then within this I'll just say that return uncore user like so and do command save so this way now we'll be able to access our user from our odd service when we want to so now that the login function has been defined what we can do is actually come back to the Firebase side of things so open up the Firebase project within your web browser of choice and then we are basically going to come to the build section and click on authentication here what we're going to be doing is basically saying that I want to get started with authentication it's going to take some time to actually configure this and then you basically going to select the providers that you want want to enable for authentication what I want to do is basically only support email and password based authentication so I'll click on email and password and then say unable and do save once this is done the next thing that I'm going to be doing is coming to the users Tab and I'm going to be adding a new user here so to add a new user for just testing purposes let's just do Hussein test.com and then I am going to do password as test12 3 exclamation mark and add the user now that the user has been created what we can do is actually come back to our application and now we are actually ready to test the login logic so now that we have created our authentication Service we need to make this available to the different parts of our code within our application and the way we're going to be doing this is by using our get it package which is a service locator package so to do this it's going to be fairly simple the first thing that we have to do is that we need to register a new instance of this odd service class to get it and then whenever we want to access our Au service we can extract it from get it so what we have to do now is come to our u. file and here what I'm going to be doing is creating a function future void I'm going to call it register services like so it's going to take in no parameters it's going to be async and open up its body then I'll get access to our geted package by doing final get it get it like so and set it equal to get it do instance and for some reason intellisense is not working so what I will do now is actually just import the package in manually like so and it should fix the error and now that this is done I'm going to do get it dot and from here I'm going to do register and I'm going to register a Singleton instance of a class and then within the actual parentheses I need to pass in an instance of the class that I want to register so in my case it's going to be our authentication Service so I'll do authentication Service like so and that's pretty much it and the last thing that I'm going to do is that I'm going to also Define the type of the actual service that I'm registering or the single ton I should say so here I'm also going to add Au service and do command save so now that this is done we need to call this actual register service function within our actual code before we actually want to retrieve this service from get it so the best place that I found to put this code was within our main. D file where we have our setup function so once we've actually called setup we are going to be setting up Firebase so once we've set up Firebase what I can do is actually call await and here what we can do is say register services and there we have it that's pretty much all we had to do so now what's basically going to happen is setup it's going to be called we'll wait for the widget flutter bindings to be initialized then we'll set up Firebase and then we'll register our services and then our authentication Service is going to be registered um with with then get it as a Singleton and then we'll be able to reference this whenever we want to use in get it and you'll see that later on so now that this is done let's actually run our application and make sure that everything's working as intended and nothing's broken and then I will resume the video so as you can see that the application is running as intended so what we can do is move on to the next step now and that is to actually come back to our login page and start implementing the login logic within our actual page so to implement the login logic what we have to do basically is three things we first need to get some information from the user and validate it to make sure that they input some information with an email and password then we're going to be using the login function that we've defined on Art service to actually log in our user and then after that we're going to be using a service which we haven't defined yet which is going to be our navigation service which will then take us if we've successfully authenticated from the login page to our actual homepage and in the case that for some reason our actual login operation fails then we're going to be using another service which we have haven't defined yet but it's going to show a pop-up message to the user letting them know that the operation was unsuccessful so to get started let's tackle the first thing first which is to actually make sure that the user inputs something within the fields and that that information is valid so to do that what we'll do is firstly come back to our loginor page. Fel and we are going to come to the point where we have our actual form being created so let me find the function for that here we go login form if you remember previously when we had created our login form we had used a form widget and within this we had placed our form Fields so now we're going to be using the power of this form widget to actually perform validation Logic on these form Fields as well as save the values from these form Fields when we want to so let's do the logic for the validation first and then we'll come to how we can extract information from the form Fields as well which the user has entered to actually perform these operations we'll have to Define some kind of a key on our form so I'll set the key property on our form to be something and what is this going to be well we'll come to the top of my class and on the top of my login page State class I'm basically going to say that I'm going to create a final variable it's going to be of type Global key it's going to be form State like so and then it's going to be called login form key and I'll set this equal to a new instance of global key like so and then I'll take this login form key come back to my login form and I'll set the key property to be our login form key so now using this key that we've attached to our form we'll be able to perform different operations on the actual form so now what I'm going to be doing is basically coming to the point where we have our login button and on our login button we're basically going to be implementing some functionality for actually logging in our user the first step within the actual login operation once the user clicks on the login button is to validate that the user inputs valid values within our actual Fields so to do that what I'll be doing is using an if statement and I'm going to say if the login form key do current state and then on that I'm going to call the validate function and then I'm going to say that if this value is null then it's going to default to false and then I'll open up the body for this if block so what's basically going to happen now is that when the user presses on this button it's going to go to the login form key which is attached to our form and then it's going to call the validate function on it and what validate is basically going to do is that it's going to go through the forms children and see all of the children which are some type of a form field widget and then call the validate function on them and make sure that for each of these children the validate function passes before it actually turns true for the validation but you are going to ask me a question now that hey we haven't implemented any kind of validation function on our form Fields so that's what we're going to be doing right now so to imp the actual validation logic what we are going to be doing is something similar to what we had been doing before where we are going to come back to our custom form field since that's the actual widget that we are using to show these form fields and on this what I'm going to be doing is basically defining a validator function so our text form field I'm going to define the validator function and the validator function basically takes in a value and then expects us to either return nothing in the case that the validation is successful or return some kind of a string in the casee that the validation was unsuccessful so that's how it determines whether the validation was successful or not so how do we determine if the validation was successful or not well what we're going to be doing is using the power of regular Expressions to actually determine if the actual information that the user puts in within the fields conforms to what we expect the value to be for your convenience what I've done is left a link down in the description below to a place on my website where you can find some of the helper code that we're going to be using throughout this tutorial I've also left a link to download the complete source code for this application that we're building but this is going to be a paid resource and I'd really appreciate if you can actually support me and actually download the complete source code but in the case you're unable to do that I've still left some helper code for you on this actual page that we're going to be using time and time again while we're building our application so for now what we're going to be doing is basically copying in all of the stuff that you see under con. dot here and basically putting this within a con. DOT file that we're going to be creating and within this I've actually placed all of the different regular Expressions that you need for validating emails password as well as the name so let's come to our actual Visual Studio code instance let's go to our lip folder let's create a new file here and I'm going to call this cons. Dart once this is done I will actually copy the code that you see here for the con dfall come back and paste it in and that's pretty much all we have to do and command save so now that this is done you can actually minimize the Google Chrome window and we are ready to perform the next step in the validation process so to validate the values that are placed within our text form field we are going to be doing the following operation we'll check to see if the value is not equal to null that's the first thing that we're going to be doing and then then what we'll do is that we are basically going to perform an operation on the regular expression to determine if the actual value that gets inputed within this form field conforms to the regular expression that we have defined and as a quick crash Con on what regular expressions are I'm not going to go into too much detail as to what these are but they allow us to pick up patterns within text and we can use regular Expressions to extract information from actual text using certain patterns things like that so here I've defined the regular expression for an email and this basically makes sure that the email that the user puts in conforms to how an email should be so like Hussein gmail.com or something like that similar for password similar for name but since regular expressions are a tad bit more of a complicated topic I'm not going to be covering that within this video but if you want a much more detailed tutorial on this let me know I'll try to create one for you but let's come back to our custom form field and now we have a problem at our head since we are using our custom form fields for getting the email and the password and we're also going to be using this on our registration page the logic for validation depends upon what type of information this field is going to be taking so we can't hardcode the logic here so what I'm going to be doing is basically on my custom form field saying that we're going to pass in the regular expression to this actual widget and that's the regular expression against which the value is going to be checked so I'll say that there's going to be a property on the custom form field it's going to be of type final regular expression it's going to be called validation regular expression like so and that I'll say that when the custom form field gets initialized it gets a name parameter passed to it called validation regular expression like so then what I can do within my validator function is if the value is not equal to null and this validation regist that we get we try to say that does it have a match with the value that the user has inputed if that is the case that pretty much means that the validation was successful so I can return null and if that is not the case then what I'll do is basically say that we're going to return and I am basically going to use the following string which is enter a valid and then I'm going to say whatever the hint text is so enter a valid password or enter a valid email whatever the hint text is and do command save so now that this is done we can come back to our login page come back to our custom form field and now what I'm going to be doing is that on my custom form field I'm going to define the validation regular expression and for the first one it's going to be email validation magic which comes from the constant do file that we had defined and for the password it's going to be the password validation rejects like so and do command save so now we're basically going to take these regular expressions and dependent upon which type of custom form field that we are initializing we're going to pass the corresponding Reg object to the actual custom form field and then it's going to use that regular expression to determine if there is a match for the value that user inputs within these fields and if that is the case that means that the validation was successful and we just returned null otherwise we returned a string which basically means that the validation was not successful so that's pretty much all we had to do and now you can see the power of using reusable components and creating all of these reusable bits of code within our application since it's making it very easy for us to implement new function ality and also make our code less ver bothos so now that this is done let's actually test if the validation logic is working so to do that I believe everything is linked up so if I click on the login button when the user hasn't inputed any values you're going to see that the validation fails and we get the beautiful errors being displayed to us saying that we need to enter a valid password and enter a valid email if I input some kind of a bogus value that doesn't conform to the scheme of how an email should be and I press login the validation still fails but as soon as I input a value that is similar to an email and Press login you can see that the validation now for the email passes but for the password it doesn't then for the password I can do test 1 2 3 exclamation mark login and there you have it now the validations are passing and what I can do is actually print woohoo here just to show you that this actually works and if I do commands Save open up the terminal and then actually go to our debug console and if I press login you're going to see woohoo being printed so the last thing that I want to do is basically make sure that when the user inputs their password in the password field that it doesn't show that as it's showing it right now on the screen and actually obscures it so to do that what I'm going to be doing is coming back to my custom form field I'm going to be defining a property on this which is going to be final Bo and it's going to be called obscure text then what I'll do is that I'm going to say that this is going to be a named PR but it's not going to be required it's just going to be optional and by default it's going to have a value of false so by default we're not going to be obscuring our text then I'll come to my text form field and on my text form field it's going to be a property called obscure text which I'm going to set to obscure text then coming back to our login page what I'll be doing is coming to the point where we have our custom form fields and for my password one I'm going to set the obser text property to be true and do command save and there you have it now you can see that the password is actually being hidden and that we are unable to see it so that's great now our validation is actually working so the next thing that we have to do is extract information from these fields and save them within some kind of variables so how are we going to be doing that well first let's do this let's go to the top of my login page State class let's create two variables here which are going to be string optional and they're going to store the email and the password like so now that this is done then what I'm going to do is come to the bottom where I have my actual login button and here what I'm going to do is say that if the validation passes then what we're going to be doing is calling a function on our login form key and it's going to be uncore login form key do current state and then I'm going to Dove like so and do command save so now what's basically going to happen is that for the form on which this key is attached it's going to go and call the save function on of these form fields that we have we don't currently have a same function on this form field so let's actually create that so to do that I'll come back to my custom form field and I'm going to say that we are also going to be passing a function to this custom form field as a property it's going to return nothing so void it's going to have the following signature so it's going to be a function which going to get a string optional pass to it and it's going to be called on Saved like so and then I'm going to say that this is is going to be a required property so required this.on saved like so and then do command save then what I'll do is that I'll come to my text form field and I'm going to say that when on Saved is called then we call our on Saved function then we can come back to our login page come back to our login form field and here I can Define what happens when on Saved is called so basically what I want to do is that when on save this call I basically want to save the information of of this actual form field within the actual variables that I've created so to do that if you remember we are going to be creating a function and this function is going to have a string optional pass to it so we're going to call this value and then within this I will do set State and I'll set the email to the value that gets passed to us like so and then I'll copy this whole block of code I'll come back to my custom form field for my password paste this in for on Save and this time I'm going to say that we're going to set the password to be the value and do command save now we can come to the bottom where I have my actual login button and after we've saved our actual information from our form then what I'm going to be doing is just basically printing it to the console so to do that I will do print and then I'm going to say email and then after that I'm also going to add another print statement and I'm going to do password like so and do command save so now with this done let's actually open up our debug console and actually see if something gets printed to the console so let's restart our application to make sure that the actual values are not there we click on login the validation doesn't work as soon as I input valid values and the following password and then I press login you're going to see that within a debug console we can see us test.com and then test 1 2 3 exclamation mark so everything is working as intended so now we can remove these print statements and we can move on to the next step within our process which is to actually log in our user so to log in our user now that we have our email and password extracted from phont we're going to be using the authentication Service that we had created so let's get access to that within this actual widget so to do that what we're going to be doing is coming to the very top and firstly what I'll do is actually import the get it package like so and once this is done I will come back to my login page State and here what I'm going to do is Define a variable which is going to be final type get Itor get it and set it to get it. instance and then what I'll do is that I'm going to say that I'm going to Define a variable which is going to be elay it's going to be of type odd service and it's going to be called underscore OD service like so and now that this is done the next thing that I'm going to be doing is that I'm going to be defining the init State function on my login page State and then after the Super classes init State function has been called I will do all service is equal to and then we'll do get it. getet and what do I want to get well I want to get the odd service that I had registered in the previous steps so to do that I will pass the type of the actual service that I want to get so as you can see it retrieves or creates an instance of a registered type so what is the instance that I want to get well I want to get the instance of OD service like so and that's pretty much all we had to do so now this variable is going to hold a reference to our odd service that we had registered in the previous steps within get it so now I can come to the very bottom where I have my login button and here we can actually use the authentication Service to now perform the login operation so to do that I will create a variable which is going to be bu it's going to store the result it's going to be equal to await so I'm going to mark this function as a synchronous it's going to be odd service Dot and then we are going to be calling Lo in like so and passing it the email and the password and we can add exclamation mark here since we know that the email and the password are not going to be empty and that's pretty much all we had to do so now let's do this if the result is true so if result that's what basically means we'll do something else we'll also do something and for now we'll leave these blocks as empty and I will basically print the result here like so and do command save so now that this is done let's actually test this out so test it out let's open up our debug console and then let's see if we are actually able to see true being printed to the console so let's do this let's actually change the email to be something that's not valid so for example tester.com so this is a user that hasn't been registered in our application yet and if I press login um you're going to see that we get a late initialization error so this is not an error we just got to make sure that we restart our application so let's try it again Hussein tester.com so remember this email is of user that isn't registered in our application yet log in and you're going to see that it says false now let's do the following where we do test.com so this is the user that we have created and if I do login then you can see true so there we have it we're actually logging in our user correctly once the user has successfully authenticated themselves the last step in the login process is going to you take the user from the login page to our homepage so now let's take a look at how we are going to be doing that to get started the first thing that I'm going to be doing is basically creating a new navigation service within my project and this is going to contain all of the code that relates to navigation and then we're going to be using the service at various points throughout our application to implement navigation based logic so to get started what I am going to be doing now is coming to my services folder and under this I'm going to be creating a new file and this time the file is going to be called called navigation undor serviceart once this is done what I'm going to do is basically create this class like so and then I am going to open it up within this class what I'm going to be doing is basically creating a key which is going to be late it's going to be a global key and it's going to be called Navigator State and this is basically going to be a key that's going to hold the current state of our navigation stack and then I'm going to call thisor Navigator key like so and that's pretty much all we are going to be doing once this is done the next thing that I'm going to be doing is basically creating all of the roots that are available to us within our application that the user can navigate to for now we just have one root so let's create that and then we can add later on more Roots here so to do that what I'll do is I'll create a final variable it's going to be a map of type string as keys and then a widget that gets returned by a function and this function takes in a build context and then I will say that it's going to be underscore Roots like so and open it up and then create the map for now I'm just going to have one route and it's going to be for SL login so basically this route is going to take us to our login page and for the function I'll say that we'll get a context passed to us and then we'll return a instance of our login page like so and then later on we'll add more Roots here when we want to add more roots to our application now that this is done I'm going to create the actual Constructor for my nav navigation service and within this Constructor I'm going to set our Navigator key equal to a new instance of our Global key and here the type for this is going to be Navigator state so let's do that once this is done I'm also going to define a getter function so that we can actually access the Navigator key on our navigation service so to do that I'll say that we are going to have a function which is going to return a global key Navigator State and it's going to be optional I'm going to say it's going to be get Navigator key and then I'm going to say that will return underscore Navigator key like so and do command save now that this is done what I'm going to be doing is also creating another getter function that is going to allow us to get access to these roots that we've defined here so for that it's going to be pretty similar I'll say that I have a getter function that's going to return the following map like so and then it's going to be get I'm going to call this Roots like so and then I'm going to open up the function definition and say that we are going to return underscore Roots like so and do command save so now before we build our navigation service any further what I'm going to do is basically register this so to do that I am going to go to my u. dfall and here I'm just basically going to do the same thing that I've done before where I was registering a single th instance for my a service I'll copy and paste this code in but this time instead of registering a Singleton instance for our OD service I am going to do that for our navigation service and then that's pretty much all we are doing and do command save now that this is done let's give a quick restart to our application make sure that nothing's broken and then what we can do is go back to our actual navigation service file and see what other things we have to do here so now what I'm going to be doing is basically implementing a method on our navigation service that is going to allow us to push something onto our navigation stack as well as go back as well as the ability to actually push a entirely new replacement to the current screen that we're seeing on a navigation stack so these are going to be three different different functions let's implement the push function first so for that I'll say I'll have a function that won't return anything it's going to be called push named it's going to take in a parameter which will be string and this will be the actual name of the route we want to go to so route name and then I'll open up the functions body here we're going to access our Navigator key and then on the Navigator key I'm going to access the current state and then on the current state I'm going to call a function called push name and then here we can pass in the root name like so and do command save and that's pretty much all we have to do so as you can say push name you can see the definition says that it pushed a name route onto the Navigator then I'm going to copy this function and I'm going to paste it again but this time I'm going to say that instead of pushing a route we are going to push a replacement named and this way we're just going to completely replace the screen that's currently on the navigation stack with the new route that we give so this time I'm going to do current state but I'm going to do push replacement and it's going to be named and then we just pass it the root name and finally I want to also have the ability to go back so for that I am going to implement the go back function so when we call go back then we are going to go to the previous screen that we came from it's not going to take any parameters pass to it and we're going to do the same thing where we'll do Navigator key. current state and then on top of that I will do pop and what pop is basically going to do is that it's going to take us to the previous scheme that we came from it's just going to as the definition suggests pop the topmost rout of the navig ation stack so let's do command save and that's pretty much all we have to do for our navigation service so now we can actually use this and navigate to our homepage but we don't have a homepage for now so let's create that first so I'm going to come to my pages I'm going to create a new file here I'm going to call this homepage. Dart then I'm going to create a stateful widget here I'm going to call it homepage like so and that's pretty much all we have to do and do command save so for my homepage what I'm going to be doing now is basically just returning a scaffold so what I'll do is that I'll say that instead of returning a placeholder for the build function for the homepage State now we're returning a scaffold and that's pretty much all we're going to be doing for now and then what I'll do is that I am actually going to be coming back to my navigation service and here we're going to be adding a new route now so the rout is going to be for our homepage so I'll say that I'll copy this I'll paste this again as a new entry this time the actual route is going to be slome and this time the function is going to return a new instance of our homepage and do command save so now that we've defined our navigation service we've registered it let's actually link this navigation service with our material app so that it uses it and we can also use it so to do that let's come back to our main. file and we're just basically going to be implementing some functionality here so that we can link our material app with our navigation service so firstly we need access to our navigation service so to do that I'll come to my my app class I'll create a final variable here it's going to be ofp type get it it's going to beore get it and it's going to be equal to get it. instance once this is done I'm going to say that I'm going to create a variable it's going to be late it's going to be type navigation service and then what I'm going to do is call Itor navigation service now that this is done what I am going to be doing is basically within the Constructor of this class I'm going to remove the const keyword and then I'll say that when the class gets constructed we are going to basically set the navigation service equal toore get it and by now you should know if it's going to be get and here we're going to define the type which is going to be navigation service like so and do command save so now that this is done we can take our navigation service and we can actually use that so the first thing that I'm going to be doing is on my material app I'm basically going to be setting the Navigator key and I'm going to be setting that to the navigation Services Navigator key that we have available on it once this is done I am actually going to take a look at what the error at the top is and it's just saying that the my app class is not const anymore so we can just remove the con keybo and that should fix the error for us and do command save and now that this is done I also need to give the material app all of the roots that are available within my application that the user can navigate to So for that what I'll do is that I'll remove the home property and then I will set the roots property to be equal to the Navigator service and then the roots map that's available on it and do command save and finally we also need to Define what the initial root of our application is going to be so when the actual app launches what's the first page that we're going to go to so for that I'll do initial route and then I'm going to put the name of the route here so remember this needs to map with the route names that you've defined within the routes map here so it's as you can see/ login so I'm basically saying that the initial route is going to be/ login and that's pretty much all we had to do so now let's restart our application and as you can see nothing's broken and everything's working so we can now go back to our login page and implement the functionality here here so that when the login operation is successful we navigate to our homepage so to do that I'll come to the top of myor login page State here I'm going to create a new variable it's going to hold a reference to our navigation service I'm going to call this underscore navigation service that within the init State function for this class I'll do navigation service is equals to and I'm going to do get it. getet and then I am basically going to define the type of the service so it's going to be navigation service like so and then after this I can come down to where I have the actual button that's responsible for managing the logic for the actual login operation and then I'm going to say that if the result is true then what we're basically going to be doing is navigating our user to our actual homepage so to do that we have to access our navigation service so let's do navigation service Dot and then I am going to do push replacement name and the reason I'm using push replacement rain is because I completely want to remove the login page and remove the ability of the user to to go back to the login page once they've actually authenticated themselves and then here the route name is going to be slome like so and then do command save and that's pretty much all we have to do so now that this is done let's actually just give a quick restart to our application make sure that nothing's broken and then let's put in a username and a password and see if it works so for the email let's do Hussein at and then it's going to be test.com and then for the password I'm going to be doing test 1 2 3 exclamation mark and and then let's do login and there you have it we have successfully navigated once the actual authentication process was successful from our login page to our homepage and we do not have the ability to go back so now that this is done let's just quickly update The Styling on our homepage and let's just quickly add some app bar here so we can actually see that we're on our homepage so to do that I'll come to my homepage and on my homepage where I'm going to be doing is coming to my scaffold and on my scaffold I'm basically going to Define my app bar like so and I'm going to say that it's going to have a title which is going to say messages and then that's pretty much all we're going to be doing for now now that this is done the last thing that I want to do before we can call it an end or our login page is that if I restart my application you can see that we do not automatically log in and we do not take the user to the homepage even though I know that in the back end the Firebase authentication package knows that the user had previously log in and it persist exed that state and the user is currently available to us so what we can do is that we can Implement some kind of a logic so when the application starts we navigate our user from our login page to the homepage if they've already authenticated themselves so to do that what I have done is that I've basically went to the main. artfl and I've accessed the authentication Service here so let's create a variable called odd service it's going to beore odd service then what I'm going to do is when the class gets constructed I'll set our authentication Service to the following which isore getet it.get but this time we're going to get our authentication Service to command save let's restart our application make sure that nothing's broken and then what I'm going to do is that for the initial route what I'm going to be doing here is basically using a teritary operator I'm going to do the following I'll say if the odd service. user is not equal to null then what we're going to be doing is that for the initial route we'll go to slome otherwise we'll go to/ log and do command save and that's pretty much all we have to do to implement automatically logging in the user once the application starts so if I restart the application you're going to see that we are automatically going to be taken to the homepage if the user is not equal to null but for now it's not going to work and there's a very crucial reason for that and that's because if we go back to our authentication Service I can see that we only ever update the user when we call the login function for now and we are not calling the login function anywhere when the application initially starts up except for the fact when the user clicks login themselves so wouldn't it be awesome if there was some kind of a listener function that we could listen to that could update us on the authentication State changes that happen within the Firebase off package well lucky you asked there's exactly something like that that we can use and I'm going to be using that to basically update the user every time some kind of a state change happens for the authenticated user so to do this what we're basically going to be doing is firstly implementing a function within our odd service class and this function is not going to be returning everything and it's basically going to be a function that's going to be listening to a stream and I'm going to say that this function is going to be called Au State changes stream and then listener like so and now that this is then I'm going to say that this is going to take a user optional that's going to be passed to us as a parameter and then we can do whatever we want within this function so what I'm going to do that if the user that gets passed to us is not equal to null so if this is the case then I'm going to set the user equal to user otherwise what I'll do is that I'll set the user to n and I just did this to make it more easy for you guys to understand what the code is but a very short substitution to this could have been just set the user to user like so and that could have work as well but I just wanted to make the code more understandable to you guys so I did it like this so now that's pretty much all we had to do so now what I want to do is basically get notified every time some kind of a state change happens on our Firebase Au package so to do that what I'm going to be doing within the Constructor of my OD service I am basically going to be saying that I'm going to take the Firebase OD dot odd State changes stream and I'm going to attach a listener to it and this listener is going to be this function that I've created so I'll copy that put this here and that's pretty much all we have to do and do command save and this needs to be listened like so and do command save and there we have it so now when the authentication Service gets created we're going to add a listener to the off State changes stream and every time the off State changes this function is going to be called and we're going to update the user that it's available to us on our service and then when we check for the user here if the user is not n then we'll navigate to our homepage so let's do command save let's restart our application and this time hopefully fingers crossed as you can see when the application restarted we were automatically taken from our login page to the actual homepage so now that this is done the next thing that we can actually take a look at is how to implement a logo button on our actual homepage so that the user can actually log out as well otherwise we have no functionality available to actually log the user out so to do that what I'll do is I'll come back to my homepage and then I'll come to the section where we have our our app bar being defined and for the app bar what I'm going to do is basically set the actions list so on our app bar we're going to have a property called actions and it's going to be a list of widgets and then here what I'm going to be doing is basically adding an icon button and then the onpressed call back for now is going to be empty and then the icon here is just going to be icon which is going to be a log out icon like so and then I'm going to do command save and as you can see we can see that the actual log out icon is now appearing I'm also going to update the color for this so to do that I'll just Define the color property on the icon button and now it's red and now the last thing that I'm going to be doing is actually getting access to our authentication Service and our navigation service and then using them to log out the user so to do that it's going to be fairly simple let's first create a variable that's going to store a reference to our get it package and let's quickly import it like so then once this is done let's actually create two new variables which are going to store a reference to our authentication Service and a variable that's also going to store a reference to our navigation service now that this is done let's quickly import these service files and now that this is done let's actually create the init State function and then once the super classes init State function has been called then what I'm going to be doing is setting the odd service to the following and then I'm going to set the navigation service to the following so what we've doing before as well now let's restart our application make sure that nothing's broken and then we can come back to our build function to where we have our icon button within our actions list here within onpress the first thing that I'm going to do is create a variable which will store a result and this is going to be basically the output from the function on our alt service. logout and as you can see for now we don't have this function so let's go back and let's actually create a function on our authentication service that allows us to log out the user so coming back to my a service what I'm going to be doing here is basically creating a function which is going to allow me to log the user out so to do that what I'll do is I'll create a function and I'll say it'll return a future Bo and it's going to be called log out and then I will open up the functions body and I know that it's going to be a asynchronous function then I'm going to have a trash block within this function and I'm going to do the following within the cache block which is to just print the error and if we reach the end of this function then I'll return false meaning that for some reason the log out operation was not successful otherwise I'll basically do a wait and I will do Firebase off do sign out is I believe the correct function yep and once this is done we can do return true so there we have it we now have the log out function defined so coming back to my homepage I'm now going to Mark the onpressed function as a synchronous and that's pretty much all we had to do and once this is done I will basically check the result so if the result is true then what we're going to be doing is basically doing the following navigation service and then I am going to do the same thing that we have done before where we are going going to call the function push replacement named and this time we are going to go to the login page and the reason we're using push replacement named is because I want to completely remove the ability for the user to go back to the homepage once they've logged out and that's pretty much all we had to do so now that this is done let's do command save let's restart our application make sure that everything's working as intended and if I press the log out button you can see that the user was successfully logged out and now this time if I restart my application you are going to see that the user is not being automatically relogged in because the user during the last time they were running the application has actually logged themel out so with that that's pretty much all we had to do when it comes to implementing login functionality within our application and now we can actually take a look at how we can show some amazing toast messages to the user in the case that the login operation fails or that we log up to create this functionality of showing toast to the users or we can also say these alert messages what I'm going to be doing is creating a service that is going to contain all of the code that's going to allow us to show alerts so to get started what I'm going to be doing is coming to my services folder and here I'm going to be creating a new file and I'm going to call this alert service do do once this is done the next thing that I'm going to be doing is basically creating this class so alert service and then I'll open up the class definition I'm going to create a variable within this class which is going to hold a reference to our get it package so let's just quickly do that and do command save and now that this is done the next thing that I'm going to be doing is basically creating the actual alert service Constructor and with this done the only function that we're going to support on this class is going to be a function that's going to show a toast to the users so to do that I'll create a function that's going to return nothing it's going to be called show toast like so it's going to take in two named arguments the first is going to be a required argument it's going to be string text and the other one is going to be an optional argument which is going to be the icon that is displayed on the toast so it's going to be icon data and it's going to be called icon and by default the icon that we are going to use is going to be icons. info and that's pretty much all we had to do and then I'll open up the functions body within the functions body all I'm going to do is add a Ty catch block like so and within the cat block I'm just going to print the error and that's pretty much all we had to do within the tri block firstly I'm going to be creating my toast and defining how it's going to look and then I'm going to be calling a function on it that's going to show it to the user so if you remember when we were actually adding dependencies to our actual project we had used a dependency that was delightful toast so now's the time that we're going to be using that so what I'm going to do is that I'm going to construct a new delightful toast bar and this class is going to come from the delightful Post package and on this I'm going to Define some property firstly I'm going to set auto dismiss to True which basically means that after some time this actual toast is going to automatically distance then I'm going to define the position so where is it going to be shown on the screen for this I'll do delightful toast bar position. toop now that this is done I'm going to define the Builder function so this Builder function is basically going to Define how this toast looks we're going to get a context passed to us and then this function needs to return how the actual toast looks so we are going to return a toast card and this is also a class that is available to us on on delightful toast for the title what I'm going to do is basically say that the title is going to be a text widget and it's going to be equal to the text that gets passed to us like so and do all shift F command save I'm going to add some of the trailing commas just to make the code formatting a bit better and then I'm going to add some styling to the text like so and this is just changing the font weight and the font size then I'm going to to the toast card add a leading property and this is going to be an icon and the icon that we show is going to be the icon that gets passed and then the size here for the icon is going to be 28 and that's what I've concluded from my testing is a good size and that's pretty much all we have to do so the final thing we have to do once that we've constructed our delightful toast bar is to show it so to show it I'm going to call the show function on it and the show function expects us to pass it a build context so where do we get access to this build context from well what we can do is that we can access our navigation Services Navigator key and then we can can access the context on that and then pass that here so to do that we need access to our navigation service so how are we going to be doing that well to do that what I'll do is that within my alert service I'm going to open up the Constructor for it and here what I'm going to do is basically get access to our navigation service but before we can do that we need to create a variable that stores a reference to our navigation service and let's import our navigation Service as well and then I'll do navigation service is equals to and thenor getet it.get and we are going to add here the following which is navigation service like so and do command save and that's pretty much all we had have to do so now I just need to remove the type definition from here add it here and do command save and that's pretty much all we had to do so now I can take my navigation service I've come to the show method and I can do navigation service Dot and then we can do current do Navigator key. current context and that's pretty much all we have to do add exclamation mark here as well and command save so now that this is done before we can actually use our alert service we have to register it so I'm going to come back to my U tools. dfl I'm going to come to the point where we are registering our services I'm going to copy the code I'm going to paste it again and this time we're going to register our alert service and then I'm going to just copy and paste that here as well do command save and that's pretty much all we had to do let's restart application make sure that there are no errors and then we can move on to actually using it so the first place where I want to use my alert service is going to be the login page so I'm going to come back to my login page I'm going to come to the point where I've defined my login button function then do the onpressed function and here we're basically going to be displaying a toast in the case that the actual operation fails for logging the user in so we need access to our toast service so to do that what I'll do is basically go to the top of myor login page State here I'm going to create a variable that's going to store a reference to our actual alert service so let's do that then as we had been doing before we are going to within the init State function basically take the alert service and then set that equal to _ getet it.get and I'm going to set that to alert service like so once this is done I'll take my alert service and I'll come back to the very bottom where I have my actual login but button and here we're going to be using our alert service by doing alert service and then we are going to do show toast and that's pretty much all we have to do and then the text here is going to be basically the following which is fail to login please try again and then I'm also going to change the icon and I'm going to say that the icon is going to be icon icons. error and do command save so now that this is done let's restart our application make sure that nothing's broken and let's try to log in with a user that is not registered within our application for example usign at tester.com we don't have a user like this and if I do login it's going to show me a toast hopefully and there you go you can see that it's saying fail to log in please try again and I can dismiss them or they automatically dismiss after some time as well so now what I want to do is also implement this functionality on the homepage as well so let's do test.com and log the user in first and once the user is on the actual homepage when they click on the logout button I want the same functionality happening so let's come to our homepage and let's come to the homepage State classes definition and here what I'm going to be doing is creating a new variable which is going to store a reference to our actual alert service so let's do late and I'm going to say that this is going to be alert service and it's going to be called underscore alert service then I'm going to come to the NIT State function here I'm going to do alert service is equals toore get it.get and then I am going to do alert service like so and do command save then we can take out alert surface we can come back to our build function and then before we actually do navigation service. post replacement named I'm basically going to doore alert service. show host successfully logged out and then icon which is going to be icon. check so now with this let's restart our application we're automatically logged in and when we click on the logout button you can see that it automatically shows me the toing successfully logged out and now I've logged out as well so that's pretty much all we had to do when it comes to implementing our alert service and now we have a alert service that we can use within multiple different points of our application and so these beautiful alert messages we can now move onwards to creating our register page and actually implementing all of the logic within our registration page so that we can also register a brand new us user within our application to get going with our registration page what I'm going to be doing is dividing it up into two parts first we're going to be taking a look at implementing the complete UI for our registered page similar to what we did for our login page and then we can move towards actually implementing the business Logic for it so to get started the first thing that we're going to be doing is coming to our Pages folder and I'm going to close out all of the open files for now and I'm going to create a new file and I'm going to call this our register page do do once this is done I'm going to basically create a stateful widget and this is going to be called register page like so and to command save then what I'm going to be doing is for the actual build function for our register page State instead of returning a placeholder we'll be returning a scaffold and do command save now that this is done we can actually come to our navigation service and here what we can do is actually add this to our route so that we can actually navigate to our register page so to do that what I'm going to be doing is after my login brout has been defined I'm going to add slash and I'm going to do register and then it's going to be basically returning for the register page like so so now that this is done let's do CAD save that's pretty much all we had to do so the next thing I want to do now is actually implement the just detector on our signup text that we can see on our login page so that when the user clicks on it they are taken to the registration page so to do that we are going to be coming to our login page and in my login page I'm going to go and try to find the place where I have basically added the create an account link and as you can see here is the text that says sign up so now what I'm going to be doing is basically wrapping this with a gesture detector so to do that I can do control shift r on Mac like so or you can just right click on the actual widget and do refactor and then you can just say that you are going to be wrapping it with a widget in this case the widget is going to be a Jester detector so let's do that and that's pretty much all we had to do and now what you're going to do is remove the constant keyword that's here and then you can add a const keyword to the first text and const here as well and do command save then on the jest detector I am going to add the ontap function call back and for now we can set that to be an empty function within this function we are basically going to be accessing our navigation service which we already have access to on our login page and then on that I am basically going to call the push named function and the reason I'm calling push named is because I want to basically push push the registration page on top of the login page on our navigation stag and this is going to allow the user the ability to go back to the login page in the case that they maybe just came to the sign up page on accident or they want to go back so then here the route now is going to be slashed and if you remember it's going to be register and that's pretty much all we have to do so now you can see the power of composing our application using various services and breaking our code down into various different widgets that it's much easier to add additional functionality even though at the start we had to add add more boiler plate code it's much easier to maintain this as well so now if I come back to my login page I'm going to restart my application just to make sure that all of the changes do happen and now if I click on the sign up link you can see that it navigates me to the registration page and if I swipe on the left hand side I can go back as well as you can see so now we can actually begin building the UI for register page so on my register page the UI is going to be pretty similar to what we had done before first what I'm going to do is that I'm going to set the re siiz to avoid bottom instant property to be false and then the body here is going to be a call to a function called bail the UI like so which we have been doing before as well then I'll basically Define the function by doing a function which is going to return a vidget called build UI like so and within this I'm going to do the following I'll say that I'll return a safe area which is going to have some padding and then the child of that padding is going to be a column like so and now that this is done the next thing that I'm going to be doing after this is basically defining the children on the column so for now this column is going to be empty but now we're going to be adding the first child to it and do command save and make sure that we get no errors the first child that I'm going to be adding is just going to be the header text so I'll copy and paste this code in and the reason for that is because it's extremely similar to what we had done for our login page so I'll come to my login page and I am going to find where I have the function for my header text so let me just copy that like so and then I will come back and paste this in my registration page like so and then I'm going to say that the first child in this column is going to be the header text like so and do command save and then all I have to do is just change the text so now the first one is going to be let's get going instead of welcome back and then the second one is going to be register an account using the form below like so and do command save now that this is done let's actually take a look at the remaining UI for our registration page and as you can see we're going to have the ability to actually add an image and then three different form Fields plus a button for the register button and then a link at the bottom which says already have an account so you can log in so let's actually implement the ability to actually select an image and then we can move on to the form Fields so to do this what I'm going to be doing is firstly creating a w function which returns a widget it's going to be called login form like so and open it up then what I'm going to do is basically return a container which is going to have a child which is going to be a form like so and then the child within this form is going to be a column widget and that's pretty much all we had to do and then for now I'll set the children's list to be empty for our column then I can do command save and start adding the first child so what I want to do is basically add the first child which is going to be our picture selection field so I am going to create a new fun which is going to return a widget it's going to be pfp which stands for profile picture um selection field and then what I'm going to do is open it up within this I am going to basically say that I'm going to return and for now let's just do a circle Avatar as the widget like so and then I can take this pfp selection field and add that as the first child within the column of our form for our login form and I found out that I actually need to call this register form so let's do that and then I can take this register form and I can come to the top where I am adding my header text and after that I'll add my register form and there we have it we can actually see the circular Avatar so now let's just change some styling attributes on it so firstly I'm going to change the radius on this so I want the radius to be around 15% the width of the device so the way I'm going to be doing this is by doing media cy. off context Dot and then from here we can do withd do size. width and then I can multiply this 0.15 and do command save and there we have it now we've increased the size of the circular Avatar once this is done we basically need to define the background image so what's the image that this Avatar is going to display so it basically depends on whether the user has selected an image or not and then if they have then we show that image otherwise we show a placeholder so how can we do that well firstly we need to create a variable that can store a reference to the selected picture of a user so to do that I'll come to the top of my class and here I'm basically going to create a variable which is going to be file optional and it's going to be called selected image and then this class can be imported from dart. and then we can come down and come back to our pfp selection field here what I'm going to do is the following I'll say that if the selected image is not equals to null then we're going to be showing that image otherwise what we're going to do is show our placeholder so to show that image what I'm going to be doing is the following I'll do file and then selected image like so otherwise what I'm going to be doing is Network image and then we are basically going to be adding our placeholder image here so this placeholder is going to come from the con.el and remember that you can find this on my website where I have listed all of the resources so you can get that from there and I'm just basically going to be adding that here like so Place hold pfp and then what I'm going to do is cast this as image provider and that's pretty much all we had to do and here it needs to be file image I believe it doesn't need to be a file like so all shift F command save and that's pretty much all we have to do and now you can see that we are displaying a placeholder for now and then we click on it which we haven't implemented yet and we select an image then we'll show that image to implement the ability for the user to actually select an image from their Gallery that's on their device we firstly need to create a service that's going to allow us to access this functionality of picking an image from the user's device to implement the functionality of the user being able to click on this actual circular Avatar and then select an image from their Gallery we're going to be using the image picker package which we've added as a dependency to our pope.l file as you can see here so now what we're going to be doing is basically creating a service that's going to allow us to access this image picker functionality and then pick an image from the devic's gallery so to get started what I'm going to be doing is coming to my services and here I am going to create a new file this file is going to be called media uncore service do Dot and then what I'm going to be doing is basically the same thing that I've done before where I'm going to create a class called it media service and then open it up I am basically going to then Define The Constructor for this class which is just going to be empty for now and then what we can do is actually now implement the image picker functionality within this class so we can call a function on this this class and then pick an image from the device's gallery to do this I need access to my image picker so I am going to create a variable it's going to be of Type image picker this class is going to come from the image picker package and then I'm going to call this underscore picket and set that equal to an instance of image picker like so and that's pretty much all we had to do once this is done I am going to create a function which is going to basically handle all of the logic for accessing the devices gallery and then returning an image to us so let's do that this function is going to return a future file optional which basically means that we might select the file we might not it's going to be called get image from gallery like so and then it's going to be a sync and I'll open it up and then again this file class can be imported from do. iio here what I'm going to be doing is creating a variable final it's going to be of type x file I'm going to call this underscore file and set that equal to aore Picker Dot and then we are going to do pick image and we're going to do the source to be image source like so and then do gallery and that's pretty much all we had to do and command save and then what I'm going to do is the following which is if the underscore file is not equals to null then we'll return a file and it's going to be the following which is file. path like so and that's pretty much all we have to do otherwise if you reach the end of this function we'll return null and command C so there we have it that's pretty much all we had to do for our Media Services so now we got to register it and then use it within our register page so to register it what I'm going to be doing is coming to my u. artfall and within register Services I'm going to basically copy the code paste it again and this time I'm going to do that we are going to do media service like so and then the same here as well and there we have it once this is done I am going to restart my application just to make sure that nothing's broken navigate back to our register page and now we can actually use the media service so to use the media service pretty much going to be how we've been using any kind of service before where we first got to access get it so to do that I'll create a variable on register page State and this is going to hold the reference to our get it instance and after this is done I am going to create a variable which is going to store a reference to our media service so it's going to be the following late media servicecore media service like so once this is done I'll Define the init State function on this class and after the Super classes init State function has been called then all we'll do is set theore media service variable equal toore get it.get media service like so once this is done we can restart our application once more and come back to the signup page and move on over to where we have our register form and then the pfp selection field and now I'm going to basically wrap this with a fidget the circle Avatar and this is going to be a gester detector and then what I'm going to do is set the on Tab property on this and within the on Tab function I'm going to to do the following I'll say that we're going to have a variable file optional it's going to be called file it's going to be a wait so we need to Mark our function as a sync and now that this is done I'm going to do media service Dot and I can do get image from gallery like so and then I'm going to do the following where I'll do if file is not equals to null then I'll do set State and within set State I'll select the selected image equal to the file that we had gotten and do command save so now we're ready to test this functionality so let's click on this circular Avatar and there we have it our Gallery app opens up and I can select an image so let's do El Pacino and there we have it fantastic you can see that the image updates and it shows us in the circular Avatar the image that we had selected so now we can move onwards to The Next Step which is to actually Implement all of the different form Fields forgetting the user's name email as well as password so to do that what I'm going to be doing is basically coming back to my login form or I should say register form and here I'm going to be adding all of the different login form Fields so I'm going to use the same widget that created before which was our custom form field so to do that I'll come to my form and after the PSP selection field I'll add custom form field like so and then I need to define the hint text which for the first field is going to be name like so then I need to define the height on this the height is going to be 10% of the height of the device so we can do this the validation rejects is going to be the name validation rejects this is again available on our consta doall and then what happens when on Saved disc call well basically we're going to get a value passed to us that's going to be the value within this field and then we can basically do whatever we want between the unsaved function so I'll come to the very top of my undor registered page State and here I'm going to create three different variables which are going to store our email password as well as name so I'll do string email password and name there we have it then I can come back to where I have my register form come back to my custom form field and now I'm going to do set State and for this form field when on save this call that I want to do set State and I want to basically set the name equal to the value that gets passed to us and that's pretty much all we had to do now I'm going to add the trailing commas just to make sure the code formatting looks good and there we have it that's pretty much all we had to do I can see that there are some styling issues so I'm quickly going to fix them by fixing the alignment attributes on the column like so and do command save and the main access alignment actually needs to be space evenly I believe and then the cross AIS alignment is going to be Center and do command save and there we have it now these alignment issues have been resolved and all looks good so now I can add the two remaining custom form Fields so so after this we're going to have a field to get email and a field to get our password so for the email one it's going to be email as the hint text the validation reject is going to be email validation reject and on Saved is going to be the email being sent to the value and for the last one it's going to be password and it's going to be password validation re and within set State I am going to do password is equals to the value and to command save and there we have it now we have name email and password so so the last thing we have to do is just basically add a button so let's do that so I'm going to create a function which returns a widget it's going to be called register button like so and then I can open up the functions body within this I am going to say that I'm going to return a sized box which is going to have a child which is going to be a material button like so then for the actual material button I'll do the onpress property to be an empty function for now and later all we'll actually implement the logic for what happens when the user presses on the register button and then I'm going to update the color to be the color scheme's primary color and after that I'm just going to add a child to this and this child is basically going to be text which says register then I can take the register button and I can come back to my register form and after the custom form feels I can add my register button and do command save and there we have it now we can see our register button so with this done the final thing we have to do is add The Links at the bottom of the screen so that we can navigate back to our login page so to do that it's going to be fairly simple so what I'll do is firstly I'll go back to my login page and I'll come to the very bottom I will copy this function which is create an account link like so and then I will come back to my register page I'll paste this function here I'll remin this function to login account link like so and then what I'm going to be doing is basically updating the text so now it's going to say do you already have an account like so and if you do then you can just login instead of sign up and then I'm going to take this login account link and I will go back to my actual build UI and then within the column I'm going to after the register form add this login account link and to command save and that's pretty much all we had to do so the last thing that now I'm going to be doing is getting access to our actual navigation service so that we can use the push named argument so to do that I'll come to the top I'll create a variable which will store the reference to our navigation servicecore navigation service then here I'm going to do the same within the NIT state which is get it.get and then navigation service and then after this what I'm going to be doing is coming to the very bottom taking some information about the user as well as the profile picture and saving that within our fir store database so that we can have a list of all of the users that have registered within our application and that we can talk with so basically the registration process is going to be divided into these three steps so we're going to be taking each thing one step at a time and then by the end of this we'll have a fully functioning registration flow so first things first what we have to do is basically implement the validation Logic on our form to make sure that the user inputs information within the form before we begin the registration process so to get going with that what I'm going to be doing is coming to my actual register button and within the register button we are basically going to be doing the same logic that we had done before which is to basically go to our on press and basically create a TR catch block and here I'm going to do print e So within the cach block we just print the error like so within the tri block the first thing we have to do is validate our form so how are we going to be doing that well firstly I need to create a form key attach it to my form and then use that to perform validation so let's go to our actual register form and then let's add a key attribute to it and now that we have to create a key let's go to the top of our class and then create a key there so let's come to the very top where we have our undor register page State and then here what I'm going to be doing is basically creating a final Global key and I'm going to call this go register form key and set that to a new instance of global key then I can take this come back to my form set the register form key here do command save restart my application just to make sure that everything works and then go back to the register page then we can come back to our register button and within the try statement I can do the following I'll do if and then I'm going to do register form key do current state and then I'm going to do dot validate and otherwise if this returns null then we can just do false and that's pretty much all we're going to be doing and besides making sure that the form fields are validated I also want to make sure that the user selects an image so I'm going to use an and cause and say that the selected image is not equals to null so if that is the case that means that our registration form was correctly validated and now we can save the information within it so to do that I will do register form key do current state and then do save and do command save and that's pretty much all we had to do so now when we click on register you can see that the form validation logic is being rendered and as soon as I put in some information then the actual validation logic should pass for one of the fields and this means that the actual validation logic is working as intended so now before we can proceed any further what we need to do is basically go back to authentication Service and Implement some logic within it so that we can actually create create a new user so let's do that so to do that let's go back to our authentication Service and for now we have a login function we have a log out function so let's create a signup function to create a sign up function I'm going to say that we'll have a future Boolean value that's going to be returned to us this function will be called sign up it's going to take in a string email and it's going to take in a string password then I'm going to mark this function as async and open up its body let's create a TR catch block within the cat block let's just print error and then within try you can actually implement the logic for registering a user so I will do final credential is equals to and I will do await uncore Firebase o dot and then we are going to do create user with email and password and pass the email and password to this function and that's pretty much it that's all we had to do then I'll do the same that I had done before which is to check if the credential do user is not equal to null and if that is the case that means that the registration process was successful I can do user is equals to and then I can do credential do user and return true otherwise if you reach the end of this function I will return false that's pretty much all we have to do so now I can come to my register page and on my register page what I am going to be basically doing now is using the odd service to call this function on it and register an account for our user so how are are we going to be doing that well firstly we need access to our odd serice so let's come to the top of our register page State and let's basically create a variable which is going to keep a reference to our odd service like so then within the init State I can do odd service like so is equals toore get it.get and then here it's going to be a service and do command save and let's restart our application make sure that nothing's broken then I can come back to my register button and after we save our register form key so the state on our register form then we can actually call this function to sign up our user so to do this what I want to do is basically call this function and also store its result so let's do a variable bu result is equals to await and since we're using await we need to mark this function as a sync and then we're going to do OD service do and then we're going to use sign up and then we can pass the email and the password and we can add exclamation mark here since we know that email and password are not going to be empty and then once this is done I am going to do if result and then open up the if clause and besides this I'm also going to print the result to the console for now so that we can see whether creating a user was successful or not and one last thing I want to do is when the actual registration process starts I want to show a loading indicator instead of this form so to do this what I'm going to be doing is coming to the top of my class and here I'm I'm going to be creating a Boolean variable and I'm going to call this is loading like so and by default I'll set this to false so by default is loading is going to be equal to false then what I'll do is I'll come to my build UI function and I'm going to do the following I'll say that if and then here I'm going to do if not is loading then I'm going to show our register form like so I'm going to do the same for the login account link as well so if it's not Lo loading so if loading is false then we show our register form and our login account link otherwise if is loading is true then we basically return or show an expanded widget and the expanded widget has a child which is a center widget which has a child which is a circular progress indicator and that's pretty much it that's all we have to do I'm just going to add theing trailing commas and that's it now if I go to the top and ass set is loading to true you can see that now we're going to as soon as I restart the application actually see a loading indicator being appearing on our registration page and if I said is loading to false and then restart my application you are going to see that now if I come to the register page then we're seeing our form so now we can basically come to our registration logic which is in our register button so let me come down yeah there we go and then when we actually start the registration process what I'm going to be doing is the following I will do set State and then I'll set is loading to True like so and then at the very end of this function I'm going to do set is loading to false like so and that's pretty much all we had to do so now what's basically going to happen is that we are basically going to try to input some information here and try to see if you're able to register a user so to do that what I'll do is I'll basically come back to the Firebase console on Google Chrome come to the authentication bag and show you that for now we just have one user created so let's delete this user and try to create them again so let's delete now we don't have any users minimize the screen come here and now let's input some information and make sure that the registration logic works as intended so sign up and we don't need to select an image for now or we need to but it's not going to do anything thing but let's do Denzel Washington then the name is going to be denel Washington like so email could be Denzel test.com and then once this is done let's do test one 23 exclamation mark as the password I can see that there's a small issue here we need to obscure the password so let's just quickly fix that by coming to our custom form field for our password and setting the Obscure text property to be true there we have it and that's just the regist ation logic so when I click on register the loading form shows and then we are back now and if you come to Firebase go to the users tab there we go Denzel was successfully registered so one part of the equation is done we have the remaining two parts which is to upload the users image now and then we also need to figure out how we can save this user information within fir store database so let's do the first thing first which is to actually store their image so to store their image we're basically going to be storing that within Firebase storage so let's come to the storage and this is found under build storage and then click on get started you can start in test mode and then click next and do whatever location you want and then do done and this is going to create a bucket for you within which you can store these media objects and then this is going to create a bucket for you within which you can store your files welcome back everybody so now you can see that the storage bucket has been initialized properly and then we can see our bucket so we can minimize this and we can come back to coding logic within our application so that we can upload files I'm going to be doing something similar to before where now we're going to be again creating a service this service is going to be responsible for allowing us the ability to interact with Firebase storage so to get going I am going to come to my services folder and here I am going to create a new file this file is going to be called storage service. Dart once this is done the next thing that I'm going to be doing with within storage service. is create a class called storage service and then I'm going to create the Constructor for this class which is going to be empty once this is done I'm basically going to create a function which will allow us to upload a user's profile picture and it's going to return to us the download link for the actual profile picture that we can use to then display that profile picture at different places using a URL so it's basically going to return a URL to us so the fun is going to return a future string optional because the file upload might fail then I'm going to say that this is going to be called upload user pfp and then we're basically going to be taking in two arguments the first is going to be a named argument and it's going to be required it's going to be the file that needs to be uploaded it's going to be called the file and then we can import this class from iio so let's do that the next is going to be the U ID of the user so I'll do required string uid so this is the user's unique ID and that's pretty much all we had to do then I will mark this function as async and open up the functions body well then here the first thing that we need to do is get a reference to the place where within firbas storage we need to store our file so to do that firstly I need access to Firebase storage so I will create a variable and that's going to be of type Firebase storage _ Firebase storage and set it to Firebase storage. instance and this class is going to come to us from the Firebase storage package then within the upload user pfp function I need to create the reference so I'm going to do reference and then I'm going to set that equal to file ref as the name and this is going to be equal to our Firebase storage and then I'm going to do the following thing I basically want a folder at the very root level of my bucket which is going to be called users and then within that folder I want to create another folder which is going to be called pfps within which I want to basically save these users images so that's what we're going to be doing so to create this reference I'm going to do Firebase storage and then we are basically going to do ref and then the ref is basically going to be users so this is the users folder slash and then the pfps folder and then after this I'm going to have a child within this and this child is basically going to be the name of the file so the name of the file is going to be the following what I want to do is make sure that all of the file names are unique so I'm going to do the following I'll take the user's unique ID and use that as the name of the file plus whatever the extension of the file is that the user selects so let's first interpolate the user's uid within the string and then we need the extension as well so how do we get the file's extension well we're going to use the path package that we have added to our pbpe do yaml file and it's going to give us the ability to actually extract the extension from the file that gets passed to us so let's import the path package so to do that I'm going to do import package path / paath dosp and and then here within the string I'm basically going to interpolate the following value which is going to be dollar sign and then two girly brackets and within that I am going to do p Dot and it's going to be extension and here what I'm going to do is basically pass in the file. path so it's automatically going to determine the extension from the files path and that's pretty much all we had to do and do command sa so once we have the files referenced then what we can do is create an upload task so to create an upload task it's going to be upload task I'm going to call this task and this is going to be equal to the file ref that we have and that I'm going to do putut file as you can see and pass the file here and now it's going to take this file reference and it's going to upload our file to this file reference moving forward the last thing that I will do is that I will return my task like so and there we have it but right now it's going to give us an error and the error is going to be the following which is that we can't return and upload task for future string question mark so how do we fix task well what I'll basically do is that I will say when the task is complete to task. then then I will basically get a property passed to me and I will basically do the following I will check if the p. status is equal to task state. complete task state. success and if it is success then I will return the following which is going to be file ref Dot and then it's going to be get download URL and that's pretty much going to fix the issue for us and now once the upload task complete we'll return the downloaded URL and then this function is going to return that to us which then we can use later on so now that this is done we can use the storage service to now upload the users's profile picture as well but before we can do that we got to register the service so let's come to our utils and let's copy the get it. register Singleton function paste it again within register services and this time we are going to be registering our storage service like so and then I'm going to add this here as well and do command save and that's pretty much all we had to do so now let's restart our application make sure that nothing's broken and we can log out because we are automatically logged in because we had created a user in the previous step come back to sign up and then here what I'm going to be doing is coming back to our register button function but before we can do anything on the register button function we need access to our actual storage service so let's do that so let's come to the top of our actual class and then here I'm going to create a variable which will store a reference to our storage service like so and then I'm going to import this class and within the init State function I am going to do the same thing that we've been doing before where I'm going to do uncore storage service is equals toore get it.get storage service then we can come to the very bottom and then where we have our registration logic going on and now what we're basically going to doing is if the result of the actual signup call is true then we can actually take a look at uploading the file so to upload the file it's basically going to be the same process first I'm going to create a variable which is going to store a reference to the uploaded URL for the actual profile picture and I'm going to set this equal to a waitor storage service Dot and then I am going to do upload user pfp and then here we're basically going to require two things we need the file that needs to be upload it as well as the user's uid the file is going to be the selected image and we can add an exclamation mark here because we know that this image is not going to be null and then we can access the uid from our a service so I can doore a service. user and then do uid like so and do command save and now that this is done we can restart our application we can also come back to Firebase console I can go to the authentication tab I can delete the user that we had created previously come to storage show you that right now within storage there is nothing and now we can test this logic so to test it let's come to our register page let's select an image this time we can do George Clooney the name is going to be George Clooney like so email could be g o r g e George test.com and then I'm I'm going to do the password that's pretty much it let's do register and in sometime it should work and we're seeing the form again but now if I go back to storage let's come back to authentication first I can see that the user was created successfully and within storage I can see that the user's folder was created underneath which I have a pfps folder underneath of which I have used the user's uid plus the extension of the file to save their actual file and this is the actual download URL so if I click on the name it opens up the actual image and I actually downloaded but if I do copy link address and show you here this is what the download URL looks like so that's pretty much what gets return to us as you can see so with this we can conclude that not only are we registering our user properly but we're also uploading the image properly as well so the last thing is to take this information and save this within our database so that we have a list of users that have registered within our application so to do that we need to unable our fir store database so I'll come to fir store database and then I'm going to click on get started or create database and here the location is going to be whatever your preference is so I'll just let this load and then the location could be whatever your preference is and then I'm going to click on next you can start in test mode and click on Create and then it's going to provision cloudfire store for you so now that the database has been created as you can see within cloud fire store I can see that the database is now empty we can come back to our application and see the next steps that we have to take so now what I want to do is basically take the information from the actual user that's their name email and password as well as the information about the download URL for their profile picture and then save this information within Cloud fir store so how are we going to be doing that well firstly we need to have some kind of a service that's going to enable us to interact with Cloud fir store so let's create that to do that I'll come to my services folder and I'm going to create a new service here I'm going to call this database _ service do do then here what I'm going to be doing is basically creating a class and I'm going to call this database service and open up it here I'm also going to create a Constructor that for now is going to be empty then after this I'm basically going to create a variable that's going to store a reference to our Firebase fir store and this is going to come from the actual Firebase fir store package so let me just copy this and paste it in this package for some reason intellisense isn't working and now the error should be fixed so now we have access to our Firebase fir store instance once I have this done the next thing that I'm going to be doing is basically creating a variable that is going to store a reference to our users collection which is going to be within Cloud fir store for now we don't have it but what I'm basically referring to is starting a new collection and I'm going to give the name to this collection of users and under this I'm going to have documents which are going to be the profile of all of the different users so let's do cancel here and let's programmatically create it so firstly what we need to do is create a collection reference and then using that collection reference we can store documents within it to create the collection reference what I will do is basically create a variable and it's going to store a collection reference it's going to be optional and it's going to beore users collection like so now that this is done the next thing that I'm going to be doing is basically creating a function and I am going to call this underscore setup collection references like so then when the actual database service gets constructed I will call setup collection references and do command save the next thing that I'm going to do is the following which is to doore users collection is equal to and then we will basically access our Firebase fir store instance and on that I'm going to access a collection and the collection is going to be users and that's pretty much all we're going to be doing for now the next thing that I want to do is to make sure that whenever we put data into this collection and we get data out of this collection that it corresponds to a schema of a specific dot class that I've defined this is not necessary but what I want to do is ensure type safety with within my project and make sure that the information that I put within the database and get from the database conforms to a specific structure now I'm going to be doing is basically creating a model file and this model file is going to store a representation of how a user profile is going to look and then we'll use that to actually tell Firebase fir store that Hey whenever you save information to the database you need to save it in a certain Manner and whatever you retrieve it you need to retrieve it in a certain matter so it might sound confusing but I'll just become clear in just a bit so the first thing that you'll have to do is that you'll have to come back to my resources that I have left on my website and a link to this will be down in the description below and you'll basically create a user profile. file and you're going to put the following code within it so let's copy it let's come back let's come to our lib folder let's create a new folder here let's call it models open it up say new file and this is going to be user profile and then I'll paste the following code in so this basically defines a class which is user profile which has three properties on it the users uid name and pfp URL and then we have some helper functions defined on it which allow us to take in some Json and then return a representation of the user profile as well as turn the user profile into Json and that's pretty much all this class does so now I'm going to close down this class come back to my database service and I'm going to do the following so when when I set up my collection reference I'm going to use the dot with converter function and what I'm basically going to do here is Define what happens when we add information to this collection when we add information to this collection the to fire store function is going to be called and we're going to perform some data manipulation here and then whatever thing we return is the stuff that's going to be saved to the database and from fire store is going to be called every time retrieve a document from this collection it's going to perform some dat mulation and then it's going to give that to us so let's do the from fir store first and then we'll go to to fire store or let's to to fire store first because that way it'll make sense and then we'll come to from fir store so when we are saving information to fir store we're basically going to get the user profile and another parameter that I do not want to use so I'm just going to set that to underscore and what I'll do is I'll take this user profile which is going to be an object and then I will call the two Json function on it like so but for now we are going to get an error so don't worry we'll fix this error in just a bit so what's basically going to happen is that we're going to get a instance of a user profile passed to us which is this class that we've created and then we'll call the two Json function on it which will take this class and give us a Json representation of it and that is what we're going to be saving within Cloud fire store when we get information from cloudfire store then I want to do the opposite I want to take the JS set and I want to convert that to a instance of our user profile class so to do that it'll be the same we're going to get snapshots and then a second parameter that I want to ignore so I'll use it underscore and then I'll do the following I'll do user profile and then instead of using the default Constructor I'm going to do Dot from Json and here I'm going to basically pass it the snapshots. DAT like so and that's pretty much all we have to do and do command save and the last thing that I'm going to be doing is that on the with converter I'm going to define the type of the actual class so it's going to be user profile and there we have it that's pretty much it that fixes all of the issues and now we've defined a reference to our user collection with some strong type safety built in it so that we are able to send information to Cloud fir store that conforms to a certain schema and when we get information from it it also conforms to a certain schema so there we have it now we have our users collection created so we can use is to add documents to it so how can we now create a document well for that what I'll do is that I will create a function and I'm going to say this will be a function that will be future void and it's going to be called create user profile like so and it's going to take in a user profile object so I'll do required user profile and then I am going to call this user profile like so and then I'll open up the function definition and I'll mark it as a sync I can also close down the debug console and here what I'm going to be doing is the following I'll do aore users collection and then I'm going to do Dot and we are going to do document and what's the ID for the document going to be well if I don't input anything here then it's going to be automatically generated but I want the document ID here to correspond to the user's unique ID so for that what I can do is the following which is to do us profile. uid and once this is done then I'll do do set and set is going to expect us to pass it a instance of our user profile so I'll just send that here and it's automatically going to understand using the WID converter that when we save information to fir store that it needs to convert this user profile to Json so this is the part of using the width converter function so now that this is done that's pretty much all we have to do for our database service so I can come back to to my utils do.all I can register my database service like so and like so and do command save then I can restart my application and while that happens I can come back to the Firebase console within storage what I'm going to be doing is basically deleting the folder just to show you guys that we've removed everything from here and we're going to rerun all of the logic for registering a user and then I'm going to come to authentication Tab and I'll delete the user that we had created as well and then within fir store database you can see that for now we have nothing within it so now let's test if the actual registration logic works as intended so to do that what I am going to do now is come back to my register page come to my register button and here we're going to do the following once we've uploaded the actual profile picture and gotten the profile picture URL and it's not equal to null then we can move on to the next step where we're basically going to do the following we firstly going to access our database service so for that let's go to the top of our class and create a variable which is going to store a reference to our database service let's import our database service and let's take our database service and set that equal toore get it.get database service like so then I'm going to come to the very bottom and here I'm going to do the following we'll firstly access our underscore database service so let's do underscore dat service and then on that I'm going to call the create user profile function and now I need to pass it the user profile so the user profile I'm going to create a new instance of our user profile and it expects me to pass it three things it needs to be the user's name the user's pfp URL as well as the uid so the name and the pfp URL we already have so where do I get the uid from well I can do aut service. user. uid and there we have it that's pretty much all we have to do alt shift F command save and that's pretty much all we had to do the last thing that I'm going to be doing is actually using my alert service that we have created previously to show a toast to the user saying the user registered successfully so to do that it's going to be the same logic as well firstly I got to create a variable that stores a reference to our alert service so I'll come to the top of my register page State and here I'll create a variable which is going to store a reference to our aler service then what I'll do is that within the init State function I will do Al aler service is equals toore get it. alert service then I can come to the very bottom and once we've created the user profile within our firestore database then what I can do is basically use our alert service and show an alert to the user letting them know that the operation was successful so I'll just copy and paste that code in because it's very similar to what we had done before so alert service that showed host user registered successfully and an icons. check so now let's log out let's restart our application make sure that nothing's broken let's come to the sign up button let's actually select an image so this time we can do for example Leonardo DiCaprio so leonado decaprio let's do email as Leo test.com and then the password is going to be test 1 2 3 exclamation mark let's click register and fingers crossed hopefully everything should work as intended and there you go everything everything works as intended and we see the alert saying that the user registered successfully so now we can come back to Cloud fir store let's go back to fire store database and let's see we have a users collection we have a document within the users collection and that document stores information regarding the user's name pfp URL and uid so there we have it the whole registration process is now working as intended and the last thing to do is to just take the user from our registration page to the homepage so let's quickly Implement that so to navigate the user from our registration page to the homepage once we've shown the alert it's going to be fairly simple all I'm going to do is the following I'll do navigation service Dot and I'm going to do push replacement named and then here I'm going to say the following which is that we are going to go to slome like so and do command save and that's pretty much all we had to do but before I do that the first thing that I'd like to do is to go back to our login page and then from our login page go to the homepage so I'm going to do another call which is going to be navigation service. goack and then once we go back after that I want to push a replacement named slome and that's pretty much all we had to do and the last thing besides this that I want to do is that in the case that any kind of an error happens then I just want to basically show an alert to the user letting them know that the operation was unsuccessful so for that within the catch block after I print the error I'm going to do alert service. show toast fail to register please try again and that's pretty much all we are going to be doing and besides this one more thing that I'm going to be doing is the following and that is if the result that we get is not equals to true so I'll do else then we'll basically just throw an exception saying unable to register the user and one more thing that I'm going to do is that if the profile picture URL is null so else here then I'm going to throw an exception as well but this time I'm going to say unable to upload user profile picture and do command save and you're going to see how this works later on in just a bit but now all of the logic has been implemented so what I can do is basically test the complete registration flow so to do that I'll restart my application as if a new user would come in and let's log out because previously we had logged in by actually creating a user let's do sign up and let's create a new user let's do El Pacino so L Pacino um then it's going to be L test.com and then I am going to give it a password and do register and it's going to go through the whole process hopefully show us an alert in some time and it's going to take us to the actual homepage with the user being registered successfully and now if I restart my application we're automatically going to be taken to our homepage because the user had already registered and logged in the previous step and now we can log out and there we have it we've successfully logged out as well so now the whole authentication flow is working we can log in users and we can register new users so let's test one more thing and that is does the actual registration process fail if the user exists so to do that what I'll do is that I'll select George Clooney again let's just say that we create George Clooney once more and I'll say g r g test.com so I believe that this is a user that we've already created and if we haven't we can just create an account and we can test again but I believe that this user was created by S um click register let's see if we have created this user um I don't think so because we have only El Pacino and uh Leonardo Dicaprio and now we have a new user that was created which is George Looney so now we can test the actual failing logic um let's go to sign up here George cloney and then let's do g o r g George Clooney and then the email could be g g George test.com and then the password can be test 1 2 3 exclamation mark register and as you can see it says failed to register please trag in so there we have it the registration logic is working completely now we're able to register users as well and handle errors perfectly fine with the login and registration flow now completely working within our application we can move to our homepage and actually implement the logic for showing a list of users to the user with whom they can have in chat so before we can actually take a look at what we have to do on the flutter side of things let's actually go back to our database and I just quickly want to show you something if you come back to the Firebase console come to fir store database and take a look at our users collection you can see that we have for for each of a user a document created under our collection under which the documents ID is the user's unique ID and then each document contains the user's name profile URL as well as what the uid of that user is so our Logic for actually showing the list of users is going to be the following we'll come to our users collection and then we'll basically cury all of the documents except for one and the one that we're going to skipe is going to be the one whose uid that's here is going to match with the currently log Lo in users uid so this way we'll only show a list of users to the currently logged in user that are not him and that he can actually have a conversation with so hopefully that makes sense so with this done now we can go to the flutter side of things and let's see what we have to do so close down our registration page and database service page and then we can just open up our homeor page. dartel and within homeor page. is where we're basically going to be implementing all of our logic within my homepage the the first thing that I'm going to do is come to my scaffold and then within my scaffold after I've defined my ab bar the next thing that I'm going to be doing is basically setting the body property and I'm going to set that to a call to a function called build UI then underneath of this I'll create a function that returns a widget it's going to be called build UI like so and then I'll open up the functions definition within this all I'm going to do is basically return a safe area with some padding child to it and then we're basically going to add some padding here so the padding is going to be the following I'm going to do padding of 15 pixels for the horizontal and 20 on the vertical axis and do do come at save once I've defined the padding then what I'm going to do is basically add a child here and the child for this padding widget is going to be another call to a function that's going to be our chat's list like so and that's pretty much all we had to do and do command save that all will create another function which Returns the widget it's going to be called our chats list like so and for now we can just say that it returns a container just so that we can test our code and do command save with this done I'll log into my application as the users that's currently registered so at this point we have four different users within our application as you can see um so I'm going to log in as one of them let's do kadu so for that I'll come to the email and I'll do kadu test.com and then the password is going to be test one 2 3 estimation Mark and let's log in and now that we've logged in we can see our H page so now we can actually Implement how to show the actual list of users here but before we can actually start creating the UI we should actually take a look at how we can cury this information from the database and then once that part is complete then we can actually take a look at displaying the data so if you remember we are going to be basically adding this functionality between our database _ service.all because this is the class which is basically responsible for adding data to our database and getting from our database so here we're going to be basically creating a function that allow us to cury the specific information that we need from the users collection so to do that what I'll basically do is that I'll say that we are going to have a function that will return a stream and it's going to be called get user profiles like so and then I'm going to open up the functions body within this I'm going to do the following I'll say that we are basically going to access the users collection which we've already defined and this users collection I'm going to get all of the documents besides the one that has the uid which corresponds to the currently logged in users uid so how can I do that well for that I need to apply some kind of a filter so what I'm going to do is the following I'll say users collection. where and then here I'm going to basically Define the criteria for how we're going to get the documents or locate the documents that we want to get so what I basically want to do is cury over the uid field and what I want to do is make sure that it's not equal to and then we need to get the currently logged in users uid so how do we get that well we need to get access to our odd service so let's quickly do that to do that I'll come to the top of my database service and here I'm going to create a reference to a variable which is going to store a reference to our alt service then I'll import our alt service and then what I'm going to be doing is basically within the Constructor I'm going to doore a service is equals toore getet it.get and then OD service and then I also need to get the reference to our get it instance so let's do that and that's pretty much all we had to do and do command save so now that we have access to our OD service I can come back and here I can do aervice do user and then do uid and that's pretty much all we have to do and then all access to snap shots on this and that's pretty much all we have to do the reason we're using snapshots is because as you can see it return returns us a stream of cury snapshots and the benefit of this is that we'll be able to update our UI as data within the actual database changes and we'll automatically get these changes shown across our UI so that's why we're using a stream here so now that this is done the next thing that I'm going to be doing is just fixing it up a bit as you can see it tells me that we are not returning anything from the body so it might complete abnormally so I'll do return the users collection snapshot like so as also going to give me another error saying that a value of stream Cy snapshot object can't be returned for the method get user profiles because it has stream Dynamic so how do I fix it well to fix it I'm going to do the following I'm going to define the type of the stream and it's going to be of type cury snapshot and then the type of the cury snapshot if you remember is going to be user profile and then once I've done this I'll also cast the snapshot as a stream and then I'm going to do cury snapshot like so and then here I'm going to do user profile file and there we have it that should pretty much fix the issue for us so now that we have our function defined that is going to help us get the information from our database the next thing that we can do is come back to our homepage and start implementing this function so on my homepage basically what I'm going to be doing is removing this container instead of this I'm going to be using a stream Builder widget and as the name suggests the stream Builder widget basically allows us to ingest stream and then using the streams data we can build the actual widget so here what is going to be the stream well the stream basically needs to be the following we need to get access to our database service and then access the actual method on it so let's do that so to do that I am basically going to come to the top of my homepage State and here I'm going to create a variable which is going to store a reference to our database service like so once that is done I will then import the database service and once I've imported it I will come to the initate function and here I'm going to basically do underscore database is equals toore get it. get database service now that this is done I'm just going to give a quick restart to my application and then come down and now we can actually set the stream for our stream Builder so the stream here is going to be our database service and then we're going to do get user profiles and that's pretty much all we had to do and then for the Builder property we basically just Define a function that gets two parameters passed to it you can hover over it and see as well it's basically going to be a function that gets a build context and a snapshot so let's do that we're going to get the context pass to us as well as snapshot and that's pretty much all we had to do and then I can add the semicolon at the end and now we can Define how the stream Builder is basically going to build our actual widget so here what I'm going to do is basically first determine if we have information available to us that we can display to the user or if we have an error occurring or if we're currently fetching the information so to do that we're going to implement the following logic let's do the error first I'm going to do if the snapshot. has error so that is the case then what we're going to do is return the following widget which is just going to be a const center with a child which is going to text saying unable to load data and then what I'm going to do is have an other if statement and here what I'm going to do is the following I'll do if the snapshot has data if the snapshot has data and the snapshot. data is not equals to null then what we are going to be doing well then what we'll do is for now return a list View and not show anything anything else and finally the last thing that I'm going to do is as default I'm just going to return a center widget which is going to have a circular progress indicator within it so let me just quickly do that so when we're loading we'll just show this when we have data we'll show our list view if we have error then we are going to be showing the text widget which says unable to load data so let's restart our application make sure that everything works as intended and we have no errors so there we have it we can restart our application and as you can see on our homepage we are not getting any errors so now we can actually take a look at if we are getting the data so to do that all I'll do is that within the Builder function I can basically print um snapshot. data and let's see if something gets printed to the console so let's open up our console and let's go to the debug console and then let's restart our application and if you come to the actual homepage you can see that it gives me an instance off with converter cury stab shot so with this we can confirm the have access to the information so we can move forwards to actually building the UI to build the UI our UI is going to look the following we're just going to have a list View and then that list view is going to have these different chat tiles within it each corresponding to a single user so what I'm going to be doing is creating a another widget and this is going to be a reusable widget which is going to be a chat tow which is going to have the information of the user being displayed and this chat tile we're going to be using to actually then display these different tiles within our list view so let's do that so to do that what I'll do is that basically I'll come to my widgets folder and then within my widgets folder I'm going to create a new file and I'm going to call this chatore tile. Dart like so once this is done then I will open up the actual chat tile file and here I'm going to create a stateless class and I'm going to call this chat tile like so and do command save and then here instead of returning a place folder I'll return a list tile like so and what last thing that I'm going to do is basically say that this chat is going to get a user profile passed to it so I'll say we're going to have a final user profile property and it's going to be called user profile and then within the Constructor we're going to have a required named argument passed which is going to be this. user profile like so and then using this user profile we can actually populate the different properties on our list tile so firstly what i' like to do is basically set the in property on the list T to be false um and then what I'll do is that I'll set the leading property of the list tile to be a circle Avatar so the leading property on the actual list tile basically refers to the widget that's shown to the left of our actual title and subtitle so this is what the leading property is so I basically want to show the user's image here so I'll do Circle Avatar and then I'll set the background image property here to be the following which will be the network image and then we're basically going to access our user profile Dot and here we have access to our profile picture your url like so and that's pretty much all we have to do once this is done I'm also going to set the title property so after the leading one has been defined I'll do title and the title is going to be a text widget and here I'm going to do user profile Dot and then I am going to do name like so and that's pretty much all we had to do and do command save and one last thing I want to do is basically get notified every time a tab occurs on this list towel so I'll set the on Tab property here to a a function call back and then what I'll do is basically say that we're going to pass in a function which is going to be on Tab and this will be called every time the actual list T gets tapped and this is also going to be a required named parameter like so then I'll set that when the user tabs will do on tap like so and that's pretty much it and let's do a Anonymous function inline and then do on tap and that's pretty much all we have to do all shift F command save and there we have it we have our chat tile created so now we can use this within our homepage so let's close down the database service and the chat tile file let's come back to our homepage let's come to the point where we have our chats list let's come to where we return our list View and now instead of returning a list view what I am going to be doing is returning a list view. Builder and the reason we're using list view. Builder is because it's going to allow us to programmatically build our list view based upon the data that we get it expects an item Builder property this is basically a function that defines how each of the child within our list our build and it's going to get two things it's going to get a context pass to it so this is the build context as well as an index for the currently built child and that's pretty much all we have to do and once this is done I'm also going to define the item count property on our Builder so it's going to be item count so where do we get this item count from well what we can do is basically create a variable and this is going to be called users and it's going to be equal to our snapshot data and then do docs and as you can see this docs is basically going to be a list of cury document snapshots so how many documents we have corresponds to basically how many users we are going to show so I'll take this list now and for the aom count I'm going to do users. length and that's pretty much all we have to do and do command save and now we can come to our item Builder within my item Builder what I'm going to be doing is returning the chat tile so let's do that and then we need to give it the user profile as well as the ontap function call back so so let's do the following let's create a variable called user profile and I am going to say that this is going to be called user and it's going to be equal to the users list that we have and then the index that gets passed to us like so and that's pretty much all we had to do and then on this we have to call the data function like so and once this is done we can take the user profile and we can pass that here and then for the on Tab we can just set an anonymus empty function for now and then do all shift F command 6 save and there we have it we can see all of the three different users being shown to us and when we click on then we can see the tab gester happening as well so now all I like to do is just add some padding so what I'm going to do is come to my chat tile and here what I'm going to do is the following where I'll do control shift R to refactor I'm going to say that I'm going to wrap this with a padding widget and I'm going to add the following padding which is going to be to just add padding on the vertical axis and there we have it now we have some spacing within our chat tile so that's pretty much it now we've implemented the functionality for actually showing a list of users to the users with whom they can have a chat with and now the next step in the conversation is going to be how can we actually navigate to our chat page when we actually click on one of these users and start a chat with them before we can actually implement the logic for when a user clicks on one of these chat Tils and then they are navigated to a chat page we need to understand how our chats going to be represented within our database so let's take a look at what the final representation of our chats are going to be within our database by looking at an already completed project and then we can continue with building the applications logic so if I come to Cloud fir store and I see the fir store database you can see that what we're basically going to do in the final version of this application is have a chats collection and that chats collection is basically going to contain different documents within it each document is going to pertain to a chat between two users and it's going to have the following attributes a it'll have an ID and this ID is going to be unique to every chat and it's going to be generated by taking both the users uid the two users that are talking with each other and then using that to generate this ID and this ID is going to be generated by a function that we are going to create and that function will ensure that whenever two users talk with each other the generated chat ID always is the same because it's going to depend on the two users uids and we'll talk about how that is going to work besides this we're also going to have a property which is going to be participants and this is basically going to be the participants within this chat so the two users that are talking with each other and finally another property which is going to be messages within which we're basically going to have a list of all of the different messages that the user sent and each message is going to have the content of the message the type of the message the sender ID of the message to who sent the message as well as what time was the message sent at so that's basically how we're going to be structuring our database and how each chat is going to be represented and how our chats collection is going to look like so with this done I can actually minimize Cloud fire store now or the Firebase console I should say and we can move onwards to building the logic within our application so when the user actually clicks on one of these chat tiles we're going to perform the following operations firstly we are going to determine whether a chat already exists between the currently logged in user and the user that they want to talk with if the chat exists then what we'll do is that we'll skip SK the next part and the next part is going to be that if the chat doesn't exist then we'll create a chat for them and if the chat exists then we won't do this part and then finally we'll take them from our homepage to the chat page so that they can talk with the actual user and then the rest of the logic of actually pulling the messages and doing everything like that that's the chat Page's job and it's going to handle that so let's implement this functionality one by one so firstly we'll take a look at how can we determine whether a chat exists or not then will actually take a look at how we can create a chat between two users and then we'll take a look at how we can navigate the user from our homepage to the chat page when they actually click on one of these chat Tils so to begin the process you'll need access to the resources that I have mentioned within the link down in the description below and basically you're again going to come to the link that I've mentioned and come to my website and now we need access to our message. Fel which basically defines the schema of how a message is going to look within our application and then also the chat file so let's create them so let's come to our models file let's create a new file and let's do chat. DOT first so let's do chat. Dot and once this is done I'll basically copy all of this code and paste it in like so and make sure that you remove the import statement at the top we'll just fix this error in a bit then I will create a new file and this time it's going to be called message the dot and then once this is done I will basically copy all of the code that pertains to the message. file like so p paste it in to command save and that's pretty much all we had to do and then we can come to our chat. file and then basically import the model for message. and that should pretty much fix the issue for us so now we have a chat. file that creates a class called chat and this chat mimics how a chat is going to look like within our database as well as our application and the message. dfall basically shows the structure for how a message is going to be so now that this is done we can close down the ch pfile as well as the message. file and we can come back to our homeor page. file and we can actually start implementing the functionality for navigating the user when the tile actually gets clicked so first things first I'm going to come to my chat tile I'm going to come to the ont function I'm going to Mark as a sync and then I'll open up the functions body and the first thing we have to do is basically determine if a chat between these two users exists so how will we do that well the logic for this is going to be the fallowing well basically come to our database we'll come to our fir store database we'll go to our chats collection which currently we do not have so what I'll do is I'll show you the completed version of the application and then we'll take a look at the documents and we'll try to find a document which is going to have a specific ID if the document with that specific ID exists then we know that a chat exists between these users if it doesn't then we know we need to create a chat so that's pretty much what the logic is going to be so let's minimize the page and let's actually start implementing this logic what I'm going to do is put this logic within my database service. dfall so I'm going to come to my database service. dartel and actually implement the function here so how are we going to determine if a chat exists well what I'll do is basically do the following I'll say that I'll have a function which will return a future Bo and it's going to be called check chat exists then it's going to take in two parameters the first is going to be the uid of the first user and the second is going to be the uid of the second user so it doesn't matter what uids we pass for uid one or two it just needs to be the currently logged in user and the other user that the user is talking with I'll create this function body and I'll also Mark this as a sync now we need to create the actual chat ID so that we can try to find if the document with this chat ID exists and I'm going to make sure that this chat ID is going to be the same when the uid one U2 given are basically the same doesn't matter if we switch the order of them so to create this what I'm going to do is basically come to my os. function and here what I'm going to do is basically create a function which will return a string and it's going to be called generate chat ID and it's going to take two named arguments the first is going to be a required string it's going to be called uid 1 and then it's going to be required string uid 2 and then I'll open the actual function body then what I'm going to do is basically say that we're going to have a list it's going to be of U IDs and it's going to be equal to a new list which is going to have uid 1 and uuid2 within it and then what I'll do is basically the following I'll do string and then chat ID is equals to and then I'll combine all of the values within this list if to a single string and to do that I'll do uids do fold and then the fold function basically takes in an initial value it Loops over the list and to the initial value or the previous value it keeps adding the next element so we'll take the previous value which is going to be the ID and then the next value which will be the next uid in our list and I'm going to return a string where we're just going to take the ID and we're going to tag the U ID to it like so and do command save and with this done I can do return chat ID but if I just leave the function like this there's a crucial error within this function and that is that depending upon the uid 1 and the uid 2 and which order we pass these uid the actually generated chat ID can differ for example if for uid 1 I pass in the authenticated users or the currently logged in users uid then for uid 2 the actual user that they want to talk with then the actual CH ID is going to be let's just say 1 2 3 that's the uid of the first user and then 456 for the second but then if for uid 1 I actually switch the roles and I send uid 1 as the actual user that we want to talk with so it'll be 456 and then the uid 2 as the currently logged in user so it'll be 1 2 3 so you can see that the uids are going to differ so to fix this what I'm going to be doing is before I actually fold the values I'm going to do uids do sort and this will sort the actual list and this will ensure that regardless of whatever way we pass the uids for the two users the chat ID that we get is always the same if the uids are the same so let's do command save and that's pretty much all we have to do now we can come back to our database service. Dell and here I can implement this function so I'll tell the chat ID is going to be equal to generate chat ID passing the uid 1 and the uuid2 and that's pretty much all we had to do so now with this is done we can basically reference our collection and then try to determine if this document with this chat ID exists but currently we do not have access to our chat collection so let's create that so to do that what I'll do is come to the top of my database service I'll create a new variable here which will store a reference to our chats collection like so and then within my database Service setup collection references I am basically going to do the following thing I'll do chats collection is equal to and then I'll do Firebase fir store. Collections and then the collection is going to to be chats and then I'm going to do the same logic that I've done before for the users collection where I'm going to tack on a withd converter here so that we can have strong type safety and ensure that the data that gets saved within the database and retrieved from the database conforms to a specific schema so for from fir store so this basically means when we are getting data from fir store what I'm going to be doing is the following I'm basically going to get snapshots as well as a second argument that I want to ignore and then I will basically do check CH which is the model that we're going to get from our chat. file and then instead of using the default Constructor on this um I am going to do chat Dot from Json and I'm going to pass it the snapshots do data like so and that's pretty much all we had to do so now that from fire store has been defined the next thing that I'm going to be defining is two fire store for so for two fire store I'm going to do the following I'll basically get the chat given to me which is going to be this and then I'll also get a second parameter which I will ignore and then I will do the following which is that I am going to return chat. tojson like so and that's pretty much all we had to do and do command save but for now it's going to give us an error so what I'll do is on my width converter I'll Define the type which is going to be chat and with this it should pretty much fix the error for us so now that we have our chats collection defined I can I can come back to my actual check chat exist function and here I can do the following I can say final result is equals to await underscore and then I'm going to do chats collection. document and the document with the ID of chat id. getet like so that's what we're going to be doing and then what I'm going to do is basically determine if the result is not null so if the result is not equals to null then what I'll do is return result return return result. exist like so otherwise if we reach the end I will do return false and there we have it that's pretty much it and now we have our function defined so let's restart our application make sure that nothing's broken and then we can come to our homeor page. file and actually use this function so to use this function what we need to do is make sure that we have access to our data service which we do so we can come back and then we can come to our chat the ontap function and here we can implement the logic so the logic is going to be as follows I will create a variable which is going to be called chat exist is going to be equal to await and then I'll do database service Dot and then check chat exists and then we need to pass it the two different uids so one needs to be the uid of the currently logged in user which we can get by doing _ OD service do user. uid and for the second one we're basically going to be taking the the user profile and then passing that user's ID like so and that's pretty much all we had to do and do command save so now that this is done I'm going to add a print statement here and this print statement is basically going to check to ensure that we get false printed for now since we don't have any chats in the database open up our debug console and then restart our application and now on the homepage when I click on one of these chat tiles you can see that it prints false so now that this is done what we can do is actually move on to the next step which is to if the chat doesn't exist then create a chat between these two users so for that we're going to do the following first I'll add an if clause and I'm going to say if the chat doesn't exist so this is what that basically means then what I'm going to do is basically create the chat to create the chat I need to create a function that's going to allow us to create a new chat so I'm going to come to my database service. dartel and here I'm going to do the following I'll say that I have a function that's going to return a future void and it's going to be called create new chat then it's going to take the same arguments which are going to be string uid 1 and string uuid2 so I'll copy and paste them in it'll be async and I'll open up the functions body within this I'll firstly generate the chat ID so this is going to be the same logic as check chat exists and then what I'll do is that I will create a document reference and the the way we're going to do that is by following we'll access our chats collection and on that we'll get the document and this time we're going to say that we don't want to automatically generate the documents ID we want the documents ID to be chat ID then following that I am going to add the semicolon and now we have access to a document reference then what I'll do is that I'll actually create a chat object so to do that I'll do final chat is equals to a chat object and we need to give it the following parameters we need to pass it the ID so this is going to be the chat ID we need to give it a list of participants so this is going to be uid 1 and uid 2 and then for the list of messages that's just going to be an empty list for now since we're just creating a new chat and then finally once we have the chat created I will do await I will do my do ref. set and then I'm going to pass the chat here like so and that's pretty much all we had to do and we don't have to do anything else besides this and do command save the last thing that I'm going to be doing is basically changing the chats collection here to be in exclamation mark uh instead of the nare operator and now we have removed the error and everything looks good so now we have implemented the function that will allow us to create a new chat so now let's do this let's restart our application make sure that we have no errors let's come back to our homeor page. artfel and then let's do the following if the chat doesn't exist then we will do await and then I will doore database service. create new chat and we can pass it the uid 1 and two so this is going to be for the uid 1 the au. user. uid and for uuid2 the user. uid like so and that's pretty much all we had to do so let's just add the remaining semicolon add the trailing commas so that we have good chord formatting restart our application open up Cloud f store and within cloudfire store ensure that for now we don't have a chats collection so let's do the following let's restart our application and let's do the following we'll click on the chat title for Leonardo Dicaprio and I'm logged in as Keanu So currently Keanu and Le do not have a chat that exists between them so if I click on this chat tile you are going to see that the chat collection is going to appear in some time hopefully if I come too far or database and there we have it if I see I have chats within which I have a chat document and now I have the chats ID the participants as well as the messages which is currently an empty list so now if I restart the application or let's just not restart it if I click on the first chat tile again you can see that nothing's going to happen and we won't have multiple different chat documents being created since the chat ID is the same between two users then it's not going to create a new document but as soon as it click on for example George Clooney since kananu doesn't have a conversation with George Clooney you're going to see that a new document is going to appear and now it's going to have the participants listed the ID and the messages list is going to be empty so the last thing we have to do is basically navigate the user from our homepage to the chat page so that they can start chatting with the user so how we're going to be doing that well firstly we got to create a chat page so let's do that so let's come to our Pages new file chat _ page. and then what I'm going to do is do the following I'm going to create a class which is going to be stateful it's going to be called chat page and then for now let's do the following just return a scaffold instead of the placeholder and do command save and one thing I want to ensure is that when the chat page gets constructed we pass to it the user profile for the user that we are currently chatting with so to do that I'll come to my stateful widget chat page here I'm going to create a final variable which is going to be of type user profile it's going to be called chat user so the user that we are talking with and then here for the chat page I'm basically going to say that we're going to get a required named argument passed to it which will be chat user like so and do command save so now what we can do is come back to our homeor page. file and once we have basically checked if the chat exists and if it doesn't exist created the chat then we can safely navigate to our chat page and then here we're going to do the following thing we're access our navigation service and then we're going to call a function on it called push but we currently don't have that so let's create it so let's go to our actual navigation service and on my navigation service I'm basically going to create a function that will allow us to go to a route and we can give that route instead of using a named route so to do that I will create a function which is going to return void it's going to be called push and it's going to get a material page route p to it which will be called route and we'll basically navigate to this route and to navigate to this route I'll do Navigator key. current state DOT push and here we're basically going to pass the route and do command save now that this is done we can come back to our homeor page. file and on here we can call the function that is going to navigate us to the chat page so I'm going to do navigation service. push and we have to give it a route so we're going to create material page route and then we're basically Al going to define the Builder here and the reason we're using a material page route here and not a named route is because when we create our chat page we need to pass it the user profile so doing this way we'll be able to achieve that and then for the Builder function we basically have a function that gets the context passed to it and then defines how the route is going to be built and we'll basically return a chat page like so and then the chat user is basically going to be the user and that's pretty much all we had to do and we can add the trailing commas all shift F command save and we're ready to test this logic so let's click on one of these chat tis let's do Leonardo Dicaprio and there we have it we're navigated to our chat page and now we can start working on our chat page so for now all I'm going to do is just quickly add an AB bar to the chat page so that we can actually see the user that we're chatting with so to do that let's come to our chatore page. dot let's come to our scaffold let's define the ab bar property on it and set the ab bar to be app bar like so and then here what I'm going to do is set the title to be the following which is going to be text and I'm going to do widget. chat user.name and that's pretty much all we have to do Al shift F command save and there we go we can see the app bar we can see the user that we're talking with and since we're using the navigation stack we have the ability to go back as it automatically shows that button to us on the app bar so now we can add to the scaffold the body attribute which is going to be a call to function called build UI like so and then what I will do is basically here say that we will return a widget from this function the function will be called build UI let's just return a container and let's do command save and make sure that our application is working and it's working as intended and that there are no issues and then we can actually take a look at how we can build our actual ual chat UI to build the chat UI on our chat page we're going to be using a package known as Dash chat so we in the previous steps of our video had already included this package as a dependency within our pspec do yaml file so as you can see underneath the pope. yaml we have- chatore 2 and what this package is going to allow us to do as the name suggests or as the definition shows that it's the most complete chat UI for flutter so we're going to be using this to actually create the chat UI within our chat page and this is going to make it very easy for us to create a fully functional responsive chat UI so let's minimize the screen and let's actually take a look at how are we going to be implementing Das chatore 2 package so to get started I'll come to my chatore page. dfall and on the list how I'll select one of the users that I want to have a chat fit so let's do Leo and then as you can see for now we're just returning a container for the build UI function so let's remove the container and instead of this let's do CH chat and then add it it's going to expect us to test it a bunch of different parameters the first is going to be the current user so this is basically the user that's currently logged into the application and we're going to be using this to differentiate between the messages that the user sends and the messages that the other user sends so Dash Chad needs to know what the current user is so if you see it basically tells us that it needs to be a chat user and it's required so let's create it so to create it what I'll do is that I'll come to my chat page State at the top and here I'm going to create a chat user variable and I'm going to create two and they're going to be optional first will be the current user and this basically refers to the user that's currently logged in and the other one will be the other user so the user that we're talking with once this is done then what I'll do is that I will create the initstate function on this class and once the super classes in it state has been called then I'll do the following I'll set the current user to be equal to and then we'll do chat user and then we have to basically provide an ID so where do we get this ID from well the current user is the currently logged in user so we need to get access to our authentication Service so let's go to the top again and let's create a variable that will store a reference to our OD service like so and now that this is done with then in it State I am going to do get it.get but that means I also need a reference to our get it instance so let me do that quickly as well and import get it and then within init State I can doore service is equals to and then get it.get service and then using this I can do all service. user. uid and that's pretty much all we had to do but besides this I also want to tell the name for the user so I'll say first name is going to be the odd service do user and then I'm going to do do display name like so and that's pretty much all we had to do so we're creating a chat user I'm setting that to the current user and we're giving the ID and the first name for that user and this is the information that then Dash chat is going to use to display the user users's name um and that's pretty much all we had to do so now that this is done what I'm going to be doing is also creating the other users chat user so to do that I'll do other user is equals to and then we'll do chat user and then here we need to give the ID so if you remember when we create the chat page we pass the other users user profile so we can use that here by doing widget Dot and then chat user Dot and then we can do the uid similarly for the first thing name it's going to be widget and then chat user and then I'm going to do Dot and from here we can do the name and that's pretty much all we had to do now it's going to give me an error for the ID and it says that the ID is required and needs to be a string so what's the issue here well I just need to add an exclamation mark here and that should fix the issue and then finally for the other user that we're talking with within Dash chat I'd like to display the actual picture of the US user like so so the messages we send we do not show our picture but for the messages that we get from the user we want to see their picture so the other user that you're talking with so for that what I'll do is that on this chat user I'll basically set the profile picture property and I'm going to set that to our widget. chat user and then from here we can do pfp URL and that's pretty much all we had to do now I can do command save and I can come back to the dash chat and here I can set the current user to be current user and add an exclamation mark for the onent function what I'm going to do for now is basically say that nothing's going to happen when onent is called so to do that let's just add an mty anonymous function and onent is going to pass us a chat message so let's say that we're going to get a message passed to us and then for the messages list so this basically refers to the list of messages that it needs to display on the UI let's just keep that an empty list for now and then slow will build the actual logic and do command save and now we're going to get an error but it's totally expected just restart your application and then go to the chat TI click on one of them and there we go we can actually see the UI it might be a d difficult for you to see but at the very bottom you can see that now we have this text box appearing under which we can actually click and then write a message and then we can send this message but it wouldn't work for now since we haven't implemented what happens when onent is called so we'll do that but for now you can see that we can see what's going on so the next thing I'd like to do is just change some properties on the dash chat widget just to make it a bit more nicer to see so to do that I'll set the message options and I'm going to do the following I'll set that to be message options and then here what I'm going to do is basically show other user Avatar so show other user Avatar to true and then do command save besides this I also want to show the the time that the messages are sent at so let's do true on that and then finally I'll do command save and that's pretty much all we had to do and finally the last thing that I'm going to do is that I am going to set the input options and what I'm going to do is make sure that whenever the user clicks on this input that we can see the send a message button here so to do that I will come here and say input options and then I'm going to do the following which is always show send and I'm going to set that to true for now and I'll shift F command say and then we can always see the send button here so what's basically going to happen now is when we click here and we input some text within this field so hello for example and when we do send by clicking here it's basically going to run this function on send and then we can do whatever logic we need to do to persist this information within our database so hopefully that makes sense so what I am going to be doing now is firstly showing you the logic of sending text messages and then once we have some text messages in a actual chat then we'll take a logic at how to render these messages and then after that we'll take a look at sending media messages uh such as images so for now let's firstly take a look at how we can send just normal text messages so the process is going to be as follows firstly we're going to have the on send call back send us a message and this message will contain information about whatever the user types here and then we're going to perform our own operation on the database to save the information within the chat that we're currently in so hopefully that makes sense so to get started with this what I'll do is that I'll say that I'll create a function which will be future void undor send message will be the name of this actual function it's going to take a chat message as its input I'm going to call it message it will be a synchronous and then I'll open up the functions body then where it says on send on dash chat I'm basically going to set that to send message and now basically every time we click Send here it's going to run the send message function within the send message function I'll create a message and this is going to be the message class that comes from the message. fault that we've created and I'm going to say that this is going to be a variable which is going to be message and it's going to be equal to message like so and then we need to give this message a sender ID some content the message type as well as the time that the message was sent at so let's do that so what is the sender ID going to be well the sender ID is basically going to be the current user ID so I'll do current user . ID then we also need to have the content so the content will be just the message and then from there we'll have the text property on it and I can see that here I can call this chat message instead of just message and then we can do chat message. text the message type for now is going to be message type. text and this is an enum that I've created within the message. file for the different types of messages we support so we have texted image and when we we basically convert a message to Json then it takes this message type enum and it converts it to a string representation and then Returns the Json and whenever we need to construct a message from a Json object jenet takes a look at the message type that's in the Json and from that determines what the enum value should be so hopefully that makes sense and then finally we can actually add the Tim stamp at which the message was sent so to do that I'll do timestamp and then I'm going to do from date and here we're basically going to do chat message Dot and on that we're going to have a created at date time object and that's what we're going to be using so this timestamp class comes from actually Cloud fire store and we to convert the chat messages created at datetime object to a timestamp object so that we can save this timestamp within our database now before we can do anything else we actually need to create a function on a database service that is going to allow us to add new messages to an existing chat so so let's come to our database service and let's take a look at how we can do this to do this I will firstly create a function and I'll say that this function will return future void and it's going to be called send chat message once this is done I'm going to say that this function is going to take in three things it's going to take uid 1 uid 2 and it's also going to take in a message and this message class comes from message. do then I'll mark this function as async and open up its body firstly we need to generate the the chat ID so the logic for that is going to be the same so I'll just copy and paste that in and after that we basically need to get a reference to our document so for that I'll do the following which is final doc ref and then it's going to be chat collection do the document with the chat ID now what we need to do is if we look at our actual cloudfire store data store is that we have chats under which we have these documents and within each document we have a list of messages so I want to take the message that the user send and append that to this messages list so how can we do that and in fir store it's called arrays I just wanted to clarify that the way we're going to be doing this is as follows I will do a wait and then I will do dog ref and then I will do update and here we need to basically specify the data which we want to update so I basically want to append to the messages array my new message so what I'm going to do is basically say that on my messages list or array I should say I'm going to do the following operation which is going to be field value do array Union like so and then within this I am basically going to say that I'm going to send my message like so and the message is going to be message. tojson and there we have it that's pretty much all we had to do so what we're basically telling fir store is that that hey I want you to update the chat document with this chat ID and I want you to go to the messages array and I want to take the existing array and merge with it this array that I passed to this list which only contains one message within it so it's basically adding the message to the actual array and that's all we had to do so now with this done we can come back to our chat page and we can actually get access to our database provider or database service I should say and then we can use that to actually send a message so let's come to the very top of our class and let's create a variable that will store a reference to our database service and then I will say that this is going to be imported from Services database service then within init State what I'll do is basically set theore database service equals to get it.get database service then I'll restart the application just to make sure that everything's working as intended and that nothing breaks and then I can come to the very bottom to my send message function and here we can actually implement the logic for sending the message so to send the message it's going to be as follows we'll do a waitor database service. and send chat message and here we need to send the uid 1 uid 2 and message so the uid 1 will be the current users ID like so and then the uid 2 is basically going to be the other user and then their ID and then finally the message is just going to be the message that we have constructed in the previous step and that's pretty much all we had to do so now now with this done we can do command save and actually test this so I'll restart my application I'll open up the cloud fire or database browser here and let's click on one of these chats and hopefully in one of these chats a new message should appear so I'm going to say hi how's it going um and then I'm going to do send and as you can see on this chat the message appeared under the messages array and there we go we can see that the content is high how's it going the message type is text the sender ID is the following and the send at time is the following so that's great that means that we are able to now send messages so now we can actually take a look at how can we display the messages that we are sending so to do that what we basically need to do is create a function first on our database service that will allow us to read data from this document and then get notified about updates that happen on this document and then we can actually take a look at how we can display that inform information so let's come to our database service and let's see what we have to do so on my database service what basically I have to do is create a function that is going to allow me to get the chat data in the format of a stream and the reason we're going to be using a stream so that whenever the document gets updated in Cloud fire store we get updates of that through the stream and then we can consume the stream and show the messages coming in real time so what I'll be doing now is basically saying that I'll create a new function within this class it's going to to return a stream I'm going to say that it's going to be called get chat data it's going to get two parameters pass to it it's going to be string uid one string U id2 and then I will open up the function body firstly we need to determine what the chat ID is so the logic for that is going to be the same so let's do that and after that I'm going to do the following which is to return the actual chats collection. document with the ID of chat ID and then on this I can do do snapshots like so and that's pretty much all we have to do and one final thing I'll do is basically say that I'm going to cast this as a stream of document snapshot where the actual document is going to be chat like so and do command save and that's pretty much all we had to do I can also add an question mark here so there n of your access operator and then I can also update the return type for this function to be the following and do command save and now we have a function that's going to return a stream to us that we can consume to get the chat data so now we can come back to our chat page and try to implement this here so how are we going to be doing this well the Keen among you would have noticed that we are going to be using a stream Builder again because that's the widget we can use to actually consume our streams so let's do that so within build UI now what I'm going to be doing is basically copying all of this code and removing it then what I'll do is that I'll say that now we are going to return a stream builder then for the stream what I'm going to do is that I'm going to set that to database service. getet chat data and here the uid 1 is going to be the current user ID like so and then the uid to is going to be the other users ID and then for the Builder function I'm basically going to say that we're going to get a context and snapshot pass to me and then I can Define what happens or how this actual stream Builder constructs our widget within this I'm going to do the following which is to just return the same Dash chat instance we had created previously and then add the trailing commas and do command save and that's pretty much all we had to do so now the next step in this process is going to be to extract the messages from the snapshot so let's do that so to do that what I'll do is that I'll create a variable chat optional I'll call this chat and I need to basically import this model from the model / chat doile and then after this I'm going to set this variable equal to snapshot. dat and then I'm going to do the data function on that like so that's pretty much all we have to do and then what I'm going to do is basically create a list of chat message so this chat message class is basically going to come from Dash chat 2 so what we need to do is take our messages which are in the form of message class and basically transform them into chat message objects so so that Dash chat can actually display them so create a list of chat message I'll set those two messages and I'll set that to be an empty list for now and then what I'll do is that I'll set the messages list on dash chat to be this messages list now and do command save and hopefully nothing should break now so now what we need to do is that we need to access the messages on our chat and convert them into chat message objects instead of the message objects that we have so how can we do that well to do that I'll do the following firstly what I'll do is that I'll say that if the chat is not equals to null and that the chat Dot and then I will do messages are not equals to null so if that is the case if the chat isn't null and the chat. messages are not null then what I'll do is that I'll set the messages list equal to and then a return from a function which is basically going to transform our messages from message objects to chat message objects so to do that what I'll do is that I'll come to the bottom and here what I'll do is that I'll say that this function is going to return a list of chat message and it's going to be called undor generate chat messages list and it's basically going to take in a list of message which I'm going to call messages and then I'll open up the body here what I'm going to do is the following I'll create a list of chat message I'm going to call this chat message messages and I'm going to set that equal to our messages list. map so we'll basically Loop over all of the elements that are within our messages list and then convert them into chat message objects and then return that so to do that it's going to be the following I'll do messages. map and then we're going to do a message and it's basically going to then do the following within the function which is as follows we will return a chat message like so where we have to basically provide the user and the time that the message was created at and then finally once the map process has been done it's going to return an iterable so I'll cast that to a list and now we can actually take a look at how to take this message and convert that into a chat message so what is the user going to be well the user depends on the sender ID so if I take you back to the database you can see that every message is going to have a sender ID so the user here depends if the actual message ID matches with the actual ID of the currently logged in user then the user is going to be the current user otherwise they will be the other user so how do we do that well what I'll do is I'll do the following I'll say if the message. sender ID is equal to the current user and then I will do ID then what we'll do is that we'll set the user to be the current user otherwise we're going to set that to be the other user and that's pretty much all we had to do and then I will add in exclamation mark at the end and then what is the created at time going to be so it's going to be the message that we get on that we're going to have the sent at property and then it's going to be to date and that's pretty much all we had to do and now what I can do is basically all shift F command save and then what I can do is actually at the very end of this function say that we will return the chat messages like so then what I'll do is I'll take this function and I'll come to where I have the actual messages being set to something and here what I'm going to do is basically say the messages are going to be equal to the return from theore generate chat messages list function and here we need to pass our messages so that's going to be chat. messages like so that's pretty much all we have to do and do command save so now that this is done what I can do is basically add some more properties to this chat message so that they're displayed properly here you might not be able to see but we're suddenly seeing this time appearing so this pretty much tells us that some kind of data is showing up in the chat view we're just not able to see it and the reason for that is because we haven't populated our chat message with all of the information it needs so the next thing is going to be to add the text to this chat message as well so to do that I'll basically say that the text and the text is going to be M do and then it's going to be content and if I do command save as soon as I do this you're going to see that the chat message appears and it's saying hi how's it going and it's in blue because this is the message that we had sent um and that's why it's appearing like this if the other user had sent the message then it would appeared a little bit different and we'll take a look at how that looks on later on so now let's try to see if we send another message and if it works so I'll say did you hear about my new movie that's coming out like so and send it and as soon as we send you can see that the message gets shown but now you're going to see an issue and the issue is that the actual messages are not being sorted in the order of the time at which they are sent so how can we fix that well to fix it what I'll do is that I'll come toore generate chat messages list and once we've looped over all of the messages and converted them into chat messages then what I'll do is that I'll sort the chat messages list so to do that I'll do chat messages. sort and then here I'm going to do the following so the fort function fors like this it sends us two elements that it wants to compare to determine which one is bigger than the other one so A and B we call them and then we basically Define some kind of a criteria to determine if a is bigger than b or if B is bigger than a so I'm going to do return and it's going to be the following which is B do created at do compare to a do created at time and that's pretty much all we had to do so now it's automatically going going to sort the list according to time and as you can see now it is fixed so now it's saying hi how's it going which was sent at 190 and then at 1920 did you hear about my new movie that's coming out so that's great now we can see all of these messages that are being sent by the user and everything looks great so now what we can actually take a look at is how can we send media messages to the user so to send media messages we'll have to firstly Implement some kind of a button that the user can actually click on and then access their gallery from there they can select the actual image that they want to send and then we need to modify some of the functions for sending the message and retrieving the messages so that all of the logic works as intended so let's actually take a look at how we can do this so to get started the first thing that I'm going to be doing is coming back to dash chat on dash chat what I'm going to be doing is coming to the input options property and here I'm basically going to set the trailing property to be a list and this list is going to contain a widget which is going to be our media message button and this function hasn't been created yet so let's create it so I'll copy this function's name and let's do underscore and then I'll come to the very bottom and here I'm going to say that we will have a function that Returns the widget it's called underscore media message button it doesn't take anything and then I will open up its body and here I'll do the following which is just return an icon button for now where on pressed is currently an empty Anonymous function and the icon is going to be the following let me just copy and paste that in like so and that's pretty much all we had to do so the icon is going to be icons. image and the color for that is going to be the primary color of the color scheme and that's pretty much all we have to do so now let's see what the issue here is um I just need to remove the const keyword here and now we can see this actual button appearing which we can click to actually access our Gallery select an image from there and then send that to the user so how are we going to be doing that well firstly we need to get an image from the gallery so that's pretty easy we already have the function implementing on our media service so we need to get access to our media service so what I'll do is that I'll come to the top of my class and here I'll create a variable that stores a reference to our media service I'll also import the media service like so then what I'll do within init state is basically copy and paste in the code for getting the media service using get it to command save and restart our application once the application is restarted I'll just basically navigate back to the existing chat that I was having and then now we can actually implement the logic for actually sending a media message so I'll come to my media message button function and when it gets pressed I'll do the following I'll do the media service Dot and then I'm going to do get image from gallery like so and that's pretty much all we had to do besides this we just need to basically create a variable within which we'll store the file that the user selects and set that equal to the following um and then also Mark this as a sync and import the file object fromo and do command save so now we can test it let's click on the button opens up the actual gly we can select one of the images and there we have it that's done so now the next thing we have to do is upload this file to Cloud fire store and then once this file is uploaded we'll get the download URL then once we have that download URL we can send a message using that download URL so it might sound a little bit confusing but just hold on and you're going to understand everything that pertains to sending a media message so the next thing I need to do is basically check if the actual file that was selected by the user is not null so let's do file not equals to null and then within this if Clause we can actually start uploading the image so what I'm going to be doing to upload the image is firstly come back to my actual storage service and then within the storage service I'm going to create a function that's going to allow us to upload actual files that pertain to a specific chat and put them within Firebase storage so how can we do that well what I basically want to do and I'll open up the actual Firebase console for that is on my storage bucket I basically want to create a new folder which is going to be chats underneath of chats we're going to have folders for each of the different chats and these folders are going to be corresponding to those chats ID within which we're basically going to be then saving all of the files that are sent within a specific chat so to do that the logic is pretty much going to be kind of similar to what we had done before what I'm going to do is say that we are going to have the function return a future string optional and it's going to be called upload image to chat like so then I will open up the actual parameters for this and say that we're going to have some named arguments that are going to be passed the first is going to be required file file and the other one is going to be a required string and then I will do chat ID and that's pretty much all we have to do then I'll mark this function as async and open up the functions body and do command save within this firstly we need to create a file reference so I'll do reference and then I will do file bre is equals to and we will do Firebase storage Dot and here we're going to do ref and then we're going to do chats SL and then we basically want to have a folder which corresponds to the chat ID so I'll interpolate that by doing dollar sign chat ID and then within this folder we'll have a child and this child is basically going to be the name of the file that we want to save so what is the name of the file going to be well what I'll do is to make sure that all of the file names are unique is basically take the Tim stamp at which the actual message is sent at and then basically use that as the name of the file plus whatever the extension of the file is so how can we do that well to do that I will say that firstly let's create the actual Tim stamp part and then we'll take a look at the extension I'll take date time now and then I'll convert that to a ISO 8601 string and that's pretty much all we have to do and do command save and after this is done then I will tack on the actual extension of the file that the user selects so for that we'll do what we had done before where we're going to do p. extension and to this we will basically pass the file. path and that's pretty much all we had to do with this done we have now basically created a file name which is going to be a ISO 8601 string of a Tim stamp following that we'll have the extension of the file that the user has selected and this is going to be saved within chat SL whatever the folder name is which is going to correspond to the chat ID and do command save then the logic is pretty much going to be the same what we'll do is firstly create an upload task which we had done before when we were uploading the user profile pictures call it task and set it equal to file R.P put and here I'm going to do file and pass it the file and then after this the return is going to be the same as before so I'll just copy it from our upload user pfp function and paste it here because it's just going to make sure that the task state is success and then return the download URL to us and we can do command save we can come back to our chatore page. file and see what we have to do here so if the file is not equals to null then what we can do is basically access our storage service and then call the function on that to upload the image so we need access to our storage service now so let's come to the top of our class and actually create a variable that stores a reference to that so let's do late storage service is equals uncore storage service like so then we have to do the same thing that we've done like a bazillion times by now on this um video which isore getet it.get storage service let's restart our application make sure that nothing's broken and then we can come back to our media message button so if the file is not equals to null then what I want to do is basically access my storage service and on that I basically want to call the function upload image to chat and we need to pass it the file which we already have and then we also need to pass it the chat ID the chat ID logic is pretty much going to be the same we're just going to use the generate chat ID function so I'll just copy and paste that in add the semicolon here to command save and I'm also going to do await stored service. upload image to chat and then I will basically save the return value from this into a variable which is going to be string optional called download URL like so and do command save so that's pretty much all we had to do so now before we test this what we can do is actually implement the rest of the logic for sending the message just so that we can test everything at once so to do that it's going to to be the following once the file has been uploaded I'll say if the download URL is not equals to null then we can do the final step in the process what is that going to be well firstly we need to create a message and then we need to send that so let's create a chat message and we're going to take this chat message and then we're going to basically send it to the send message function which will then take care of actually doing the actual sending of the message so let's create a chat message so I'll create a chat message and I'll say this is going to be called chat message it's going to be equal to chat message like so here we basically need to define the user so who's sending the actual chat message it's going to be the current user the created at timestamp so it's going to be datetime.now like so and then after that we're going to set the media's list which is going to be a list of Chad media to include the file that we had just uploaded so so to do that what I'll do is that I'll create an empty list within which I am going to add a chat media object it requires a URL a file name and it type the file name is just going to be an empty string and the reason for that is because I don't want to display the file name the type is going to be media type. image like so and then the URL here is going to be the download URL and that's pretty much all we had to do so alt shift F command save and then the final thing we can do is basically once we've defined our chat message is to call theore send message function and pass it the chat message and that's pretty much all we had to do so now within our send message function what we're basically going to do is get that chat message and right now we're not differentiating between the messages that are text based messages and the messages that are media based messages so we need to create some kind of a mechanism that can allow us to differentiate between the chat message that we get and whether that's a media based message or a text based message so to do that it's going to be the following logic I'll do if the chat message. Medias list is not empty and if this returns null then it'll be default false then we'll do something else what we'll do is just default to assuming that it's a text message and do the logic that we were doing before within this else Clause otherwise the logic is going to change a bit we'll still create a message but this this message is going to be a little bit different it's going to be a message with a message type of image so what I'll do for now is that I'll say if the chat message. Medias and then I'll do the first. type is equal to Media type and then do image and I'm doing this check to ensure that even if the user selects a file that's not an image then we don't send a message since we don't have an ability right now to display anything else besides text and image based message so if the the chat message that we get the media's list in it the first element within it the type of that is media type. image then we're going to create a message and I'm going to call this message like so I'm going to set that equal to message and here we're basically going to set the sender ID to be the chat message Dot and then I'm going to do user. ID there we have it the content is going to be chat message do Medias and then here I'm going to take the first element and I'm going to get its URL then the message type is going to be message type. image and what's the sent at time going to be well it's just going to be Tim stamp. from dat and then it's going to be the chat message dot created ad and that's pretty much all we have to do so now we've constructed a message and this is going to be a message type of image so what we can do is do the same thing which is await database server is. send chat message and then send the message so the uid 1 is going to be the current user uid the uid 2 is going to be the other users uid and then the message is just going to be this message that we had created and that's pretty much all we had to do so let's do command save let's restart application and let's test if all of the logic is working so I'm going to come to the existing chat click on the actual image icon button select one of these and then hopefully in sometime we should see a new message appearing and there we go we can see the new message appearing but it's actually showing it to us um as a text and we can see the actual download URL being displayed here so now we basically need to update the logic within our generate chat messages list to basically differentiate between these two different message types and then generate the appropriate chat message so that's going to be fairly simple it's not going to be anything too complicated what I'm going to be doing is that I'll come back to the point where we mapping through all of our messages and here I'm going to add an if statement what I'm going to do if the m. message type is going to be equal to message type and then I'm going to do Dot and here we can do image then we're going to do something otherwise we'll just default to assuming that a message is a text message so within the else block we'll just do the same thing that we were doing before and then within this if I'm going to do return check chat message like so so now we need to define the user so the user logic is going to be the same so I'll just copy and paste that in it's basically the same logic so if the user sender ID is the same as the currently logged in users ID then that means that this chat message was sent by our user and then the created ad logic is going to be the same as well it's going to be m. sent add to date so let me copy and paste that in like so what's going to differ is the actual content that this chat message has so instead of populating the text property what we're going to be doing is populating the media property on this so I'm going to do Medias is a list and there's going to be only one enement between this list which is going to be chat media and the URL here is going to be the m. content so why is it m. content well if you go back to our Firebase console to the database you are going to see once the database actually loads that when we send a image message then the content is basically the actual download URL for the image and if you take a look at the storage you can actually see that now we have chats within which we have folders corresponding to the chat IDs within which we are storing these fils where we have the time stamp as you can see amend the actual extension of the file so everything looks great uh we building a very powerful application the file name is just going to be an empty string and the type here is going to be image so let's see what it expects it expects it to be immediate type so it'll be mediate type. image that's pretty much all we had to do alt shift F and command save and that should pretty much fix the issue for us so now text messages are being displayed at text messages and media messages are being displayed as images it's working as intended and everything seems to work great so now what I'm going to be doing is basically opening up another simulator and then trying to test if the back and forth conversations are working as we had intended because basically we've implemented all of the functionality so now that's left is to just actually test if everything works like we wanted it to so to do that what I'll do is that I'll stop running this application on this simulator but before that I'll spin up another simulator and to test out what we can do is that we can start an i simulator and then on the iOS simulator what I'm going to do is come here and select within Visual Studio code the iPhone 15 Pro Max to be the new Target where I want to run my application and then start debugging the application so now I'll wait for the application to build and then I will resume the video and if any errors occur by any chance I'll show those to you as well as well as how to fix them welcome back everybody so now that the application is running on iOS simulator as well as an instance of it is also running on an Android simulator what I can do is test the chat functionality thoroughly and see if everything works as intended on the Android side of things I've logged in as Keanu and I'm going to be talking with Leonardo DiCaprio and here's the chat history as of now and on the iOS side of things I am going to log in as Leo so Leonardo Dicaprio and then I'm going to talk with Keanu that's logged in on the Android device so here we have it there we go I'm logged in so the application crashed and that's a good thing and I believe the reason for that is because we didn't ask for the appropriate permissions when it comes to actually accessing the gallery on our actual iOS simulator on an iOS device so let's quickly fix that so to fix the issue we're going to be doing the following thing we're going to come to our image picker pub. Dev page and here we're basically going to come to the point where it says setup for iOS and as I can see it says that we need to add these three different usage descriptions to our info. pist file so let's do that so to do that I'll come to iOS Runner and then here is going to be info. P list and then I'm going to do the following I'll basically copy this key string pair I'll paste it three times and then I will set the first to be NS photo library description like so then the second one is going to be NS camera usage description like so and then finally NS microphone usage description like so and add that here and then here I'm going to change the strings to be need access to photo library like so and then I'll do the same thing here need access to camera so let me do that need access to camera and then I am going to do need access to microphone you need to make them a bit more detailed if you actually want to submit this app for review and actually get it published but for testing purposes it should suffice so now that this is done I'll stop running my application I'll minimize Google Chrome I will select the iOS simulator put this to one side select that as the target start debugging the application and hopefully this time when we try to send a media messages it should resolve and it should not crash welcome back everybody so let's test to see if this actually works if I click on the button it says me that the app wants to access the gallery I'm going to do allow full access there we go we can see the photo gallery popping up I'm going to send the following image and with this done let's see if the image actually gets sent I'm also going to open the app in the Android simulator go to the Leonardo g capio chat and as you can see it shows me that Leo has sent me this image so with that that's pretty much it this means that everything's working as intended so now one last thing I'd like to do is test the functionality of just starting a brand new chat so to do that what I'll do is that I'll log out on the Android simulator and I'll I'll try to log in as George so let's do Georg test.com and then test 123 exclamation mark So on the Android side of things now I'm logged at George Clooney and on the iOS simulator I am logged as Leonardo DiCaprio so here I'm going to select rard DiCaprio here I'll select George Clooney and let's see if I send a message does it show up so hi how's it going send the message and hopefully it should show up there we go it's showing up and now if I send a media message hopefully that gets shown as well and then here I can respond to the message as well as soon as I receive it yeah there we go we've received the message whoa looks awesome where is this place and then I can send the message and there we have it the conversation is Flowing both ways so with that that's pretty much it for today video I hope that you enjoyed this tutorial and learned a thing or two about flutter and Firebase as always if you enjoyed the video then please don't forget to leave a like on the video and subscribe to my channel so that you get notified every time I release new videos and as always stay happy stay healthy keep learning keep going and I'll see you guys in the next video bye-bye
Info
Channel: Hussain Mustafa
Views: 12,725
Rating: undefined out of 5
Keywords: flutter chat app, firebase, flutter, flutter firebase tutorial, flutter firebase full course, flutter firebase chat app, chat app flutter, chat app flutter firebase, flutter chat ui, flutter chat app with firebase, flutter chat app with firebase realtime database, chat app firebase flutter, firebase flutter tutorial, firebase_auth flutter, firebase_core, cloud firestore flutter, cloud firestore flutter tutorial, cloud firestore tutorial, flutter tutorial, flutter firebase crud
Id: 1kOMoncF4p4
Channel Id: undefined
Length: 232min 3sec (13923 seconds)
Published: Thu Mar 28 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.