Flutter with Firebase Backend Project - Full Stack Tiktok Clone App | GetX

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone my name is rivan and in this video we are going to build a full stack tick tock clone it covers ui built with flutter back end with firebase and state management with get x let me show you the demo of the app this works on ios and android so first of all you can upload videos so let me take my android device and i'll add a video you can see that we get an option of selecting an image or selecting a video from our gallery or selecting it from our camera i'm going to proceed with gallery and i'm going to select this video right here and you can see that we get the demo i hope you can hear the video as well [Music] now we can add a song name to it i'll type none for now and then we get a caption we can type and then we can click on share and you can see that our video got shared so if i come on the home screen of this uh ios simulator to show you that it's real type without refreshing i can see these videos over here and you can see my video of wait for it you can see this comes up over here and now you can see that it's showing up i'm not sure if you can hear it in the ios simulator but if i open it in the android device you can go to the bottom and you can hear it let me increase the volume [Music] and you can see that works now i can even like the image so i can even like this so if i go over here and i click on like you can see that this changed to one and if i go back to my android device and scroll down you can see that we can see a one like over here now you can even comment on any post so if i go over here and comment over here let's say and then click on send this is real time sent to to this comment section now i will go back and in the search we can search for the users as well so let me type here let's say naman and you can see this no one user showing up now this is my own profile so that's why it's uh showing this profile of sign out but if i go to another profile let's say rwandan and i'm already following this user i can unfollow this and you can see the follower count decreasing but i can follow him back again now you can see that we have this over here so we can unfollow the user or we can follow him back again these uh image posts that you can see are auto generated from the user uh videos we are going to do that and by video uploading you might have not seen but behind the scenes we are going to add a video compression so that the firebase storage can take in more videos now you can go to the profile section and you can see this profile showing up i follow two people there are zero followers and zero likes but if i go on the flooded devs you can see it has one follower and one like because we have liked on one of their videos so now i can even sign out and you can see that we have a complete authentication using firebase and get x but before starting the prerequisites for this course is to have a basic knowledge of dart flutter and firebase no knowledge of get x is required and now let's get started all right so the first thing we need to do now is go to our terminal and i want to show you the flatter version we'll be using so i can do that with using flutter dash dash version and the version is 2.8.1 which is the latest for now and then we can migrate to a desktop and here we can create a project flutter create and we can name this tick tock with an underscore don't put on hyphen else it will give you an error then we can pretend tick tock tutorial let's say and then hit enter after that we can go to our tech talk tutorial folder and then we can open it in our favorite code editor minus vs code so i can just type code and with the full stop in the folder and this will open it in vs code after that let me expand it and in the lib section in the main dot dot file i'm going to remove everything from here i removed this class from here i'll remove this theme data from here and i'm going to run i'm going to have a text which just says hello world after that we can ignore the warnings for now and we can open a simulator ios simulator which can be done using open dash a simulator this will create an ios simulator for us which will be running we can exterminate this uh terminal that we have because we'll be using the inbuilt terminal in vs code after that let me also remove this so now let's run our app and see how it's looking in the meantime what we can do is create a file named constants.dart and over here we're going to put all the constants that we're going to have and let's import material.from here and first thing we need is colors in our app so what we can do is type comment colors and you have to go to this link which will be mentioned in the description below to copy the colors there are only three colors so you can just copy that and paste it here then you can go over here and set the theme to theme data dot dot dark dot copy with and you're going to have a scaffold background color of background color make sure to import it from constants.dart file and we can save that and let's see how it's looking for now we won't see any changes in the scaffold background color because we are not using scaffold in our app till now but you can see hello world showing up which is pretty good now we need to change the title of this so let's say tick tock clone then we can remove this banner from your debug banner that we see so we can do debug show check mode banner to false then we can save it and you can see this banner has been removed so let's work on the authentication screens so uh for before starting with the authentication ui what we can do is i want to show you the structure that we're going to use so we're going to have a structure of mvc in our application which stands for models then views and then controllers so in the controller we are going to have all the logic in the views we are going to have the ui of our app and the models will contain the model data so like all the models that we create like user model post model common model all of that stuff so in the views we are going to have a widget folder and another folder called screens and in the screens folder we are going to create login screen and all the other screens that we are going to have but since we have two screens in the authentication what we can do is create a folder named authoria and in the auth we can create a file named login underscore screen dot dot now first we need to import the material package so we can import that and after that we are going to create a stateless widget which will say login screen now over here we are going to have uh we're going to return the scaffold first and then we're going to have a body which is centered let's say so that we can just see an output and we're going to put a text of login screen right now if i save it gets formatted and over here i'm going to replace this with login screen let's save that and you can see login screen showing up and the background color is black which is like the background color in our colors. file as well like constant or dart file as well right so the next thing we want is over here in a body we are going to have a container why do we need a container that's because uh we're going to have all our elements centered so we can have alignment dot center then we can have a child and a column then we need the input fields so in the children we can have a text called tick tock clone then we can have a style of text style and the style we can have font size as 35 color as button color which is in our constants or dart file and the font weight as font weight dot w 900 then we can save that and over here you can see tick-tock clone showing up it's not centered yet but it will center up when there are more elements in the column so let's work on that the next thing we want is our text another text so we can have constant text to show login and then the style over here can be similar to this so let's just copy that the font size will decrease so the font size can be you know let's say 25 we don't want any color for this like the original default color that we have it's all that we want and the weight can be 700 you can save that and you can see login showing up as well after this we need to have some spacing so we can have a size box which says height 25 then we can have a container where we are going to have a text input field and since we are going to have multiple text input fields what i am going to do is create a widget out of it so in our widgets what we can do is create a file named as text input field dot dot over here we are going to import the material package we are going to create a stateless widget and we are going to call it text input field now this will return a text for field and this text field is going to have a controller which you're going to accept from the constructor from here let's have that then in the decoration we can have input decoration firstly we want it to show some labels so what we can do is have label text then we can have a prefix icon and that will just be the icon of you know password or email or whatever we are going to have that icon from the top as well let's name it so we can have label text here and a controller here then we even need a label style how our label should look like so we can have a label style and it will definitely be of textile and it will let's just increase the size then we need to have a border so what we can do is enable border to be outline input border border radius can be border radius dot circular let's have that 5 then the border side will be a constant border side and with this we are going to give the color to our text input field so that can be color of border color then we need a focus border and then the focus border can be the same thing as this one so we can just paste that as well and finally we our text field can be obscure that means it will show the password as dot so we can have an obscure text and when will this obscure text be true whenever there is a text form field so we're going to have that from the from the constructor as well so we can have that with obscure now let's try to have those values from our constructor so the first thing we want is a text editing controller so have let's have that text editing controller which can be controller then we need a final string label text then we can have an is obscure value then we can have an icon data because this is icon and here we will have an icon data you can see it over here and then i think that's all what we want yeah and let's try to import that from this named constructor right here so let's require them here you can see i have imported i've accepted all the values from our constructor and now if we go over here and have text input field which is the widget we've created and we need to pass in some values over here the first thing we need is controller so we'll have to create that on the top so we can have a final text editing controller and we can name that email controller and we're going to mark it as private so let's have that now let's even create it for password controller since we're here so we can have that for password as well and now we'll have to remove this constraint because these are final fields also from the main dot dot we'll have to remove the login screens constant then we'll have to go down and over here we are going to have an email controller then the label text can be email then the icon over here can be icons dot email because this is icon data and the last thing we want is obscure now everything is going to be everything is not going to be obscure if it's not password field so what we can do is remove the required field from here and we're going to have a preset value for this which can be false so if we have not mentioned any value the obscure text is not going to show up but if we set it to suppose we'll do it for a password so we can have true for that now if i refresh this and go over here we can see our email showing up and if we type it you can see it's showing up which is pretty good now the email is taking up all the with and that's not how i want it so in our container what we can do is have a width and the width is going to be media query dot of context dot size dot width which will take up all the width but we are going to have a margin as well so we can have margin of const edge inserts dot only and from the left we can have 20 and from the right 20 or you can just do symmetric and set horizontal to 20. both of these approaches work and you can see the email showing up now something similar is what we want for our password so we can just copy this and paste it down here make sure to have a size box of height 25 then we can have a password controller there will be a password and the email icon is going to be lock we can save that and here we can see email and password then we need a size box again because we need to have button so let's just increase the height from here let's have 20 30 and then we are going to style our button now for this button we are not going to use the material button elevated button text button any of that we are going to create it from scratch using container so lets create a container and in the width that will be media query dot of context dot size dot width minus 40 then we can have a height of 50 a decoration of box decoration and then there can be a color of button color after that there will be a border radius and the border radius can be bord radius dot all from all the sides we want it to be five let me format this and you can see that it will create a radius.circular of five basically and you can see a button is showing up pretty well now we just need a text over here so we can have a child in our container that will be child and the text can be login and since this is going to be a plain text we can have a constant text and let's save it you can see login showing up but it's not very cool looking so we can make it cool let's have a text style and we can have a font size of 20 we can make the color i think the color is white so we don't need to change that and we can have a font weight of font weight dot w 700 you can see that it's coming up but we wanted print center so what we can do is basically wrap this with the center and you can see this shows up in the center but we'll remove this from const from the text and put it for the centered widget and the login shows up which is pretty cool looking now this won't be clickable so what i can do is wrap this centered with a widget known as inkwell you can even use gesture detector but i want splash effect so i'm going to use inkwell and we're going to have an ontap property where we'll just pass in empty function let's put in a print to see if it's working so we can say login user and we can print that so if i click over here and you can see login user showing up so after this container what we need to do is have a sized box again which will be of the height 15 we have to mark it as a constant we basically need a text at the bottom which can basically say don't have an account you can register so we can create a row and the row will have will be centered from the main axis like it should be centered from here right so we can have main access alignment as main access alignment dot center then we can have children and the first child is going to be a constant text which will say don't have and since i want an inverted comma here i can do slash which will allow me to put a inverted comma layer and then i can say don't have an account and then i can leave a space so that when the next line comes in i can have some spacing and the style can be textile and we'll just increase the signs so let's say 20. then we need another but text which will be saying register and that will have a style of text style of font size again 20 but here we are going to change the color which will be button color so we can have a button color after that what i'm going to do is for our text i'm going to wrap it with a inkwell widget again so i'm going to wrap this with the ink well widget because we are going to have an ontap functionality over here as well and over here we can just print navigating user and you can see this has a splash effect as well and we clicked on it and we got navigating user showing up which is nice and now you can see our app is fully made but we just need to center it so what we can do is go in our column and over here we can have a main access alignment property to main access alignment dot center and if we save it our app comes into shape now let's work on the sign up screen so in the auth we are going to create another file named sign up underscore screen dot dot and we are going to import the material package and we're going to name it we're going to create a stateless widget which we'll name sign up screen and for the return i'm just going to copy this scaffold from here and put it there because it's almost similar then we can resolve the errors that we are getting by importing everything so you can just just use command and full stop to see the errors and their possible solutions so in our text input field we can do that and we just need to create the two controllers i'm going to copy that as well and in the sign of screen we can go and paste them we are going to retur we are going to remove the sign up and over here we are going to return a sign up screen instead of the login screen this is the basic stuff so let's refresh and you can see that there is no change because we have to make some changes right now we are calling our sign of screen register so we can just put that then over here we can go down and just print register user we can have register and then over here we can have already have an account and here we can say login this looks pretty good now we just need to have an extra you know an extra input field and a circle avatar which shows up at the top to select images so what we can do is go to the top and we're going to copy this size box from here and paste it below and we'll have to remove this size to box from here and we'll have to paste that over here so let me copy this from here and paste it down here now i'm going to replace this with username and here we'll have username controller which we'll have to create so let's go at the top and create that we'll copy this and we'll have username controller copy this from here and paste it down and we're going to have an icon of person and if we go you can see user name showing up now the next thing we want is a circle over here which basically tells us about the image selection so let's create that now as you can refer in the image in the side we're going to have a stack over here and the stack will have children first of all a constant circle avatar which will show our image which will have a radius of 6 a4 then a background image and the background image will be a network image which will show a default image let's try to find the default image and we can paste that image link over here it's just a random image you can grab it from the net so let's put a const for the circle avatar which we have done and after that we need a background color while the you know the image is loading up so we can have a colors dot black or a color blue whatever suits your taste then we can have a position element to show an icon button which we can click and select an image so we can have a position in the bottom from -10 left 80 and a child which will be an icon button now this icon button will have an icon which will be a constant icon icons dot add underscore underscore photo and then an on press functionality where you're going to pick an image so we can just type print pick image to see you know if the icon button is working now if you go over here you can see the image and everything but we have positioned it poses position the stack wrong we have to put it above the username so we can put it down over here and now if we see we are getting that now we need to create some spacing we can create that spacing as well and we can save that now you can see that the image is showing up and it's looking pretty good but the only problem is well the size to box height so we can reduce the height by 10 pixels everywhere so we can just have 15 and if we save this this looks much better if i save you can see that it's looking much better don't worry about this image not showing up pretty good in a good way because that won't matter so now let's work on the authentication logic so what we need to do now is create a controller and the controller will be named auth underscore controller dot dot now these controllers are going to have the logic of our app because we're going to separate our logic from our ui files which is generally a good practice in flutter now the control or controller is going to extend the class known as get x controller which we'll have to import from the get x package so you can go over here in the pub.dev and type in get and you'll get the get x package so this is the package you're going to use now you can go to the popspec.yaml file and add this over here in our dependencies get and you can just take the latest version you can go in the installing tab and you can find the latest version which is this one or instead of adding multiple files what you can do is go to your extensions tab and find pub spec assist this extension allows you to do command shift and p and after that is done you can just click on possibility assist and you can add and update dependencies from here by just typing the name this will help a lot in your app so let me create a class named auth controller and we are going to extend that from get x controller now since we installed a new package we'll have to stop our app and rerun our app so we can do that but before doing that our auth controller for our auth logic we'll have to get some libraries some packages from for firebase configuration as well so you can go over here and find these packages that we are going to install firebase core so that we set up the connection between our app and the firebase console then the firebase auth package for authentication in our app cloud firestore so that we can set up a database and firebase storage to store our images so over here what we can do is we created this now we can just save this much go to our main.dart file and let's first of all add this i forgot to add them so the names are firebase core firebase auth firebase storage and lastly cloud firestore now this will add automatically to our spec.aml files with the latest version so we don't need to worry about it now in the main over here what we need to do is well let's go over here first and see why we're getting this error we can just type flutter pub get and you can see our error has gone right now in our main.dart file we can go there i did command p to open something like this to search file by the name now in the main uh function what we can do is make this asynchronous first of all then we can do widgets flutter binding dot ensure initialized so that our framework knows that the widgets have been initialized then we need to do something else await firebase dot initialize app this firebase is given by the firebase core package you can find over here and this will initialize the app for us but we need to well make a configuration in our firebase console as well we need to add this project so what we can do is click on add project enter our project name so let me type let's say tick tock tutorial and we can click on continue we can disable the analytics for this project we don't need that now in the meantime it's creating the project for us in our main.dart file we need to replace a material app with get material app don't forget to do that this is a very important step so that our whole app is with get material app and we can make changes like with get x in our app now you can see that our project is created we can go in there and well first of all for apple we need to do so we can click on ios now to find the bundle id what you can do is go on the ios folder and you can right click and you can find open in xcode and this will open the file in xcode for you after that is done we can go to the runner which is the topmost directory and over here we can copy this bundle identifier and paste it in our com. in our app bundle id we can name this let's say ios tick talk we don't need the app store id so we'll continue then we need to download the google service and 4. list file which will download and then we can just go to our downloads over here and we can take this google service info dot list file and put it in the runner the runner slash runner folder and then click on finish now you can uh exit the uh the x code and then you can click on next in the console we don't need to follow all of these steps so we can click on next and we can continue to the console our ios stuff is done but the last thing we need to do before running our app is migrate to our ios folder and here we can run pod install this will install all the necessary well platform but as you can see we have gotten an error so we can go to our so we can go to our pod file and where we need to uncomment this line and replace 9.0 with 10.0 because it needs a higher version as you can see in the error so and after that is done we can just click on pod install again and it will install the necessary dependencies for us welcome back and as you can see the pod installation is complete so we can clear this we can go back to our main uh for main folder and not the ios folder and here we can again run our app without debugging so let's wait for our app to launch to see if we have done it successfully hello everyone welcome back and our app has loaded you can see that it's loaded and we can see some messages from get x which says instance get x material control has been created and it has been initialized this is because we have returned get material app so if you're not getting this make sure to comment down below whatever you're getting or anything or just fix this with having this alright now the next thing you want to do is create is configure for the android app as well so we click on the add app and we can add the android app now we need the android package names for that we can go to our android manifest.xml and we can copy the package from here close this file and we can add that over here now i can name this android tick tock and we don't need the sha-1 certificate because we are not doing any google sign-in or phone number sign-in then we can register our app after that we need to download our google services.json file and we need to add this in our projects apps build grading so what we can do is go to our downloads and over here first of all we can go to our android then our app and over here we need to add our android google services.json file so we can add that over here make sure to add this within the app and not the src else it will not work well now after doing that we can click on next over here now we need to add the pro firebase sdk all these dependencies so what we can do is go to our build.gradle file first of all the project one which is this one in the android folder itself and over here we need to copy this line the dependencies line and paste it down here so you can click on enter and space this over here after that you can close this file and you can go to the build.gradle android app file which is this one and over here you need to copy this line from here and you need to paste it over here right this is all the configurations you need for the uh firebase console so you can continue to the console but you still have to make some changes so in the build.gradle android app over here what do you need to do is change the flutter minimum sdk version to 19 and over here we need to do minimum mini decks enabled to true it's not many decks sorry it's multi-decks so you have to turn multi-text enable to true after that you can save the file and now i'll connect my android application android phone and see if it's working welcome back our app has loaded up as you can see over here so what i'm going to do is disconnect this android app from here because it will take in all the laptops or battery from here so i'll disconnect it and what we're going to do now is again run the app so that our ios simulator can run so we can run without debugging actually it's running the chrome version so i can change that by clicking over here and changing to iphone 13 and then running it again now in the background what you want to do is when the app is initialized we need to after that is initialized we need to run something so we can do dot then and it will return a value which is not significant for us as such but after this what we need to do is get dot put and we need to put auth controller the class that we just created right now let's import the get package over here instead of route manager dot dot you can just import get dot dot so that it imports everything from the get power dependency like the get library that you have added all right now we can go to our auth controller we have everything in place so the first thing we need to do is create a method for registering the user all right so now to register the user what we can do is create a function which doesn't return anything and it will take in a username then an email a password and a file that can be null which is an image now we need to import the dot io dot io package so you can import that don't import the dart html package it imports that by default you need to import dot io then after that we need to set up a try catch block so that it can listen to any errors and since you're going to have a try like we are going to have an asynchronous process that's why we have wrapped this with a try catch block or here we can check if the username dot is not empty so we don't want any of the fields that we have accepted from the parameter to be empty if they are not empty then only we are going to follow the processes that are going to happen and the image cannot be null so we can just do images not equal to null right now if this is the case what we need to do is well we need to save our user to our authentication and to our firebase database like the firebase firestore right if we get any error what we need to do is get dot snag bar now we need to import get so you can import get and over here again you can import get dot dot package which will import everything we need in the future as well now you can remove this get instance now you can display a snack but by just doing get dot snack bar you need to pass in a title which can be error creating and account or we can just remove anand and over here to show the message we can just type e dot to string all right now let's save our database uh let's save the user to our database so now we are going to do user uh so we have so now to save to our database we have to do firebase auth dot instance but we are going to use the firebase auth dot instance quite often throughout our app so what we can do instead is go to our constant.file and and where we can create some firebase related constants so first thing is going to be let's create it as a bar and it can be firebase storage no sorry we have to name that so we can have firebase auth equal to firebase auth dot instance then we can create the same for firebase storage which can be firebase storage dot instance and lastly we can have for firebase so instead of just firebase we can do five bit store and we can have firebase firestore dot instance right now over here we can just import that firebase auth and we can have create user now we have the email and the password accepted from the parameter now this is going to be a future because we are going to fetch create a user on the net so all the processors are going to be asynchronous so we need to await this and it will return something known as user credential now this user credential is going to be user credential and you can just have that now i'm going to put some commas so that you can so that we can format the document now after that is done our user has been made now what we need to do is store this image to our firebase storage so that we can get the link to this image in our firebase storage but before that we also need to do some authentication now we can go to our auth tab and click on get started over here which i forgot to do previously and after this get started is done it will take us to the sign in method we need to enable the email or password sign in methods so you can do that and you can go to the users after that we need to do the same for firebase firestore database and storage storage will automatically open that's not a big deal we need to create a database here you can start in the test mode and click on next and the cloud firestore you can have is i can have is asia southeast because i live in southeast asia you can click according to your preference of the zone you're in in the meantime that is happening we can create a function to upload the image to our storage of firebase storage so let's create a function upload to storage and this function will uh we'll have to pass in the image that we receive from here right now over here we can create a function that will upload to firebase storage so we can just type a comment upload to firebase storage and here it will return a string so it will be of the type future string because the process is going to be asynchronous now we can upload to the storage and we'll have a file image that we are receiving from the argument uh from the param from the we are passing in as an argument now we need to do firebase storage the variable that we created in the constant.file dot ref dot child and the child will have a name of profile pics and we'll have a child of firebase auth dot current user which can be null dot uid now this will be of the type reference so we can just type reference ref equal to this now let's import the reference so basically we have to import the firebase storage file this line and we'll have to mark this process asynchronous we can save that and now we need to up upload this image so to do that what we can do is ref dot put file and what we need to put image all right now this will return an upload task to us so we can do upload task upload task equal to this and then we can do task snapshot so this will be of the type task snapshot and it will have snap equal to await upload task so this will be like a future this is like a future which we need to avoid so ah after this is done we'll get a snapshot and this snapshot will return to us our well download url so we can just do string download url which is equal to await snap dot ref dot get download url and lastly we need to return this download url which will be a string we can save this and if we go down you can see that we are not getting any error but we need this download url so we need to await this and finally get this string download url equal to this now we have that we need to uh well now finally we got the download url which basically means that we went to our storage we saved the file in the appropriate directory which is this over here and the child profile pics with the image name as this we saved a file and then we got the download url now we have to save all of those stuff with the name username all of that in our firebase firestore so what can we do well first of all we'll have to create a model which will be a user model so that our app looks pretty good i mean it it is well modeling our data and all of the code stuff is done basically we are modeling our modeling the data has its own uses which we'll see in the future now we can create a class of user now we will have a string name a profile photo then we can have an email and finally we'll have a uid which is a user id now we have to require all of this so let me do it quickly also a thing to note over here is we are saving a profile photo as a string and not as a file because we are going to save the download url right now let's see why we're getting this error that is because we need to put a semicolon over here now we'll have some functions that we'll have to create which is string which is a which will return a map called to json which will basically convert our you know whatever data that we have given over here in our model it will cover convert it into a map basically and this will return a map or an object if you're from javascript and then we can return the name so we can have name a profile photo will be profile photo then an email and finally our uid which is uid finally we'll have another function which will be static user from snap which will basically take the document snapshot that we'll pass in in the future while retrieving the values and then it will convert it into a user model so we'll have our snap equal to snap dot data and we'll have that as a map of string comma dynamic now we need to return the user so we'll return the user and the first name is going to be email so we can take the snapshot that variable that we created right now and then we can return profile photo uid and finally we will have to return a name which will be snapshot name now all the functions for our user model is done so we can go back over here and now we'll import the user now the problem is that there are two users one coming from the user model that we just created and coming an other one coming from the firebase auth to fix that that issue what we can do is import the mod user model as model and then what we can do is model dot user and then we can create our user which will be user and let me get all of those now the name is going to be username email is the email to get the uid you can just take the cred that we have over here dot user which can be null dot uid and finally the profile photo which is the download url that we have and we can save this now we basically need to put this data in the file cloud firestore but before that let me edit the rules of the cloud firestore else it will give some errors where we'll have to remove all of this and allow read and write which is by basically that everyone can read and write to our database which is an insecure tool but if you want to learn more about rules you can uh let me know i'll make a video on that as well now you can take the firebase firestore which is this one and we'll go to the collection of users dot document and the document is going to be the credential the cred dot user dot uid and we can set the user like this but now you can see that we're getting this error because it accepts a type of map string dynamic data and we are passing in the user model which is not correct so what we can do is access the dot to json method that we created and if we do this much our data should be saved but now let's avoid this as well because it is an asynchronous process you can see over here and after this we can even have an else function over here which will show a snag bar so basically if the username or any of this is empty so what we can do is show an error so what we can do is we'll add the same title but our message will change please enter all the fields and we can save this now let's rerun our app and see if it's working but before that we need to call this function so we can take the register user function and we need to go to our sign up screen and in the on tap first of all we'll have to register the user so what you can do is on tap and now to do that what we can do is auth controller dot now in order to call the auth controller dot instance we need to do something so in our auth controller we can go to the top and where we'll have to create static auth controller named instance so that we can call this and we need to do get dot fine which will basically find this auth controller for us and return to us an instance of this auth controller now you can replace this and in our constants since we are going to use auth controller quite often what you can do is well type over your controller and we'll have var auth controller equal to auth controller dot instance now we can call the instance on the auth controller we can take the source controller now and do auth controller dot register user now we need to pass in the username which is well username controller dot text then the email so we can do email controller dot text and finally the password controller dot text now we need to add an underscore because that's the name of our controller and we can format this now we need to pass in the image as well so what we can do is over here in our pic image over here what we need to do is well we need to create a pick image function over here so what we can do is pick image we need to create this sort of function and it will not return anything and will be asynchronous obviously now to pick the image from our gallery what we need to do is go to this url that i'll mention in the description below which is the image picker plugin you need to install this so i'll add this in the pop spec assist which will add in my popspec.aml file and now i can stop the app execution and we'll have to restart it all right now let's try to get the image so our picked image will be image picker now i think we need to do this so we can do image picker dot pick image and the source is going to be image source dot gallery and we can have this much now we can check if picked image is not equal to null we need to show a snag bar that we have selected a picture successfully so we can have get dot snag bar profile picture and the message can be you have success fully selected your profile picture and we can add that now we have to create a global variable which will be named let's say file of picked image and we have to make this an observable so what we can do is rx and file observable is basically uh like a stream of events uh basically we are keeping track if the picked image variable has been changed or not like the value of it has changed or not so we are doing that and now what we can do is over here we can set picked image equal to rx file which is nullable we can set this with a value which is file and it will be picked image dot path all right now we need to go over here and we need to have the on press functionality so we can have auth controller dot pick image and also we need to have this like this so we can pick the image now and after getting this picked image what we need to do is auth controller dot and we need to access the picture but we cannot access this picked image because this is a private field so what we can do is create a getter which is file get profile photo and we need to pass in the picked image dot value so whatever value is there in this picked image variable we need to return that and this is going to be a getter now this will return a value so we can do auth controller dot profile photo and we can save this much and now let's rerun our app and see if it's working also a thing i would like to note is that over in the main.dart file we put the auth controller directly because we don't want because we'll be using auth controller everywhere in our app basically to get the uid and all of that stuff that's i've put get dot put over here in our initialize app itself so that it runs uh when uh like when the first time our app is starting and also because we need to process the state of our application like if the user is signed in we need to make sure that it's signed in that's why i put it over here only so that we can access a function that will create later on all right else we would have used get builder or you know put the get dot put in every stateless widget that we created and wherever we wanted to use but since this is going to be a lot of use that's i've put it in the main.art file itself all right welcome back and you can see that our auth controller has been created and initialized which is a good sign now let me pick an image first and you can see our app crashes this is because well we haven't read the documentation for image picker the image picker documentation clearly says that we need to add something for our ios so what we can do is in our info.plist file over here we need to add some stuff so you can just copy this and put it down so we can after this key we can have two more or three more keys so this is the first one the second one and the third one then we need to copy these keys ns photo library usage so we can just say photo library needed then we can have the camera so we can have ns camera user description so we can have camera usage and finally a microphone so we can have microphone usage and now we can see this now we'll have to again run our app without debugging and let's see if it works our app has loaded again and let's try to have a file now we can see that it wants to access to all our photos so now let me select one photo and you can see profile picture has been successfully selected now we'll add a username let's say rivan and email which i'm going to badly format and then a password test123 and we can register you can see error creating a noun account this email address is badly formatted so we can have that and let me put the username field empty so that we can check if it's working and you can see please enter all the fields so let me add ranaval and we can click on register we are getting no signs of any error that means our app has been completed so we can go to our cloud firestore and in the authentication tab we should see rival namandrawan and in our cloud firestore as well we see a user's collection with our uid and all of that stuff which is pretty cool we haven't added the followers list over here uh with because it's going to be a sub collection and not a field over here so yeah now the next thing we want to do is well first of all we notice an error in our register field we forgot to mark if the password thing is obscure to true so let me do that so let me collapse all the folders so that it looks much more organized and in the sign of screen where we have our password controller we can set is obscure to true this will fix the error and now if we type anything you can see obscure text coming all right now let me create a function so that we can create a user so we'll have void login user and we can have an email and a password which will be an asynchronous process will again have a try and a catch block again we'll have a get dot snag bar so let me just copy all of this we'll again have the condition checking so we can just take these both conditions these are the conditions that we need and we can check if email is not empty and password is not empty then we need to do our task else we need a snack bar again which will be this error logging in not creating an account make sure to change that error logging in all right now let me save this and and after this we basically need to do await firebase or dot sign in with email and password we have that now we can save that and to know that we have logged in what we can do is print log success now this will only print if there is no error because we are catching the errors over here so if we're getting any error we will not get this print statement all right now we also need to show in our main dot dot file a login screen so that we can see if we're getting any so that we can basically test our app so in our email we can type namandrawan at the gmail.com i'm going to pass in a wrong password one two three four five six and we can log in we're getting the login user printed over here which means we have not added the method to our ui so let me connect it to our ui and in the on tab we can basically have auth controller dot login user the email is going to be email controller dot text and the password is going to be password controller dot text now let me even format the document that is done now we can try logging in so let me restart our app in our email let's try part two remember another gmail.com test let's put test and click on login error logging in which is a wrong format but it's fine and again in our login screen we forgot to put the is obscure so we can fix that so in our password we can set is obscure to true now this didn't change the state of our app so we don't need to restart now we can have namandrawan at the gmail.com yet again and we'll pass in the correct password and login and you can see log success showing up which is pretty cool that means we have logged in now the only thing is we need to make sure that we go to the next screen so let me first create the third screen which will be in the screens let's call that home screen dot dot let me import the material package and it will be a stateless widget so we'll have a home screen and let's keep a container for now and let's uh well now uh let's figure out how we can go to the next screen well definitely we can use make use of get dot push like get or get dot off so that we can replace everything and go to the next screen which we are going to do but instead of doing it after every success in every login user method we can do another taking we can follow another technique which i'm going to show you and with that we are also going to maintain the state of our app so if the user has logged in he doesn't need to log in again all right so now what we can do is go to the top we'll have to create a variable called late and it will be an observable yet again which will be a user and user this is not going to be the user model user but the firebase auth user right now we are going to call the on ready we are going to call the on ready function which is basically something like on in it but it's run after one frame of on in it like when the first uh first time the app loads up now over here we are going to set user to rx user and the value we are going to supply it with is firebase.auth.currentuser and we are also going to bind this user to a stream so dot bind stream and we're going to do firebase auth dot all state changes so basically we are setting the user to so a value which is the current user value and then we are binding it to a stream which is firebase dot or state changes which listens to the changes in the in our auth state and then uh binds it to our user stream which is this one so that our value constantly keeps on updating and now whenever there is a a user so whenever there is a change in the user we need to call a function which we are going to set as set initial screen over here we are going to create this function right now all right now in the on ready what now we are going to create a function known as set initial screen and it will receive a type user which will be user and we are going to check if the user is equal equal to null what we need to do is get dot of all so we need to replace everything with the login screen because we need to make sure that the user is logged in right else what we need to do is get dot off all and we need to pass in the home screen so let me run through the process we followed over here basically we are setting the user to a value which is the current user and we are also going to bind this user stream so whenever uh any odd state changes which this function will let us know the user value will also change so we have binded this to the stream and with this we have called the ever function so whenever the user for value changes we need to uh call this function which is the set initial screen which will make sure that uh we need to display like we if we need to display the login screen or the home screen now so let's save this much and run our app and now you can see the home screen showing up you can see going to route home screen removing route this this is because well our user is null not null now and now if you don't believe me actually what i'm going to do is go to the home screen so in our home screen i'm going to replace this container with a scaffold body center child text and we are just going to type in home screen so that i can make sure that it's the home screen and yes it is pretty cool right now even if i restart my app you can see that i'm going to the home screen cool now we need to work on the home screen functionality let's do that what we want to do now next is work on the bottom navigation bar so we are going to add the bottom navigation bar in our home screen itself so that's where we want it now in the bottom navigation bar we need to pass in items and the items are of the type bottom navigation item bar item and there will be an icon which we'll have to pass so we can pass in the icon as ikins dot home as the first one let's increase the size to size the 30 and then we also need to pass in a label so that we can see the text below the icons so we'll have home and we can save this much now all of the items are going to be const so we can have a constant and now let's have multiple items let's have four of them because we are going to create a custom let's create five actually now in the icons the second we want is a search icon so we can type in search the third we need is a custom icon that will create the fourth one we need is a message icon and last thing we need is a profile icon so we can just type person and we can have profile type 10. where we'll have messages typed in and where we don't need a label i think or we just need an empty label yeah and this icon is going to be a custom icon that we are going to create because we need that plus icon that you can see in the top in the right right so let's create that in our widgets so let's call it custom underscore icon dot dot it's going to be let's first of all import material package then it's going to be a stateless widget and we're going to call it custom icon now this custom icon is going to return some dimension box so let's create a size box and it will have a width of 45 and a height of 30 then we need a child and the child is going to be a stack a stack of children of container first of all with the margin of constant edge and sets dot only and from the left we need 10 then we need a width which is going to be 38 and then a decoration so we can have decoration as box decoration and the color is going to be const color dot from a rgb a is the alpha or the opacity basically then the red value then the green value and finally the blue value then we need to pass in the border radius so our body radius is going to be border radius dot circular right now let's save this much now we can take this container from here and put it again so let's pause that container as well now this is going to be from the right margin 10 it is going to have the same with 38 and the argb is going to be 32 two one one two three four right it will give us a blue effect as you can see over here in the colors finally we need a centered widget which will be a plus icon basically so we can have a center of child and we'll have the container again so i'm going to paste that now this entered will have a no margin so we can remove this margin it's going to be height double dot infinity and then it will have a color of colors dot white because we want the white background and in that we want a child as you know a color a plus icon basically so we can have a child of const const icon icons dot add which is a plus icon we want the color to be colors dot black and the size is going to be 20. let me save this much and i'm going to import custom icon from here now let me put a comma and save this much if i refresh my app you can see we are getting no errors and our bottom navigation bar looks pretty cool we just need to change the colors so let's go on the top we are going to have a background color which will be colors draw back so we can just do background color and then we can save this much now there's colors.black and we need to pass in the type so the type is going to be bottom let me have bottom navigation bar type dot fixed and let's save this and you can see this is showing up but you can see that the selected color is somewhat greenish and we don't want that so what we can do is pass the selected item color to be colors dot red or the button color whatever thing suits you i'm going to go with red and the unselected item color is going to be colors dot white you can save this and you can see that we have that now if we click over here we are not seeing any changes happening that's because we need to do some more configuration so over here we are first going to have a page index which will be zero and we need to change this page indexes value so what we can do is create this as a stateful widget because we need to change the state of this variable right here and whenever anything is tapped over here what we will get over here is an index and we need to set the state of the page index global variable to this local variable over here and we can save that much now if we do we are not seeing any changes till now because we haven't set the current index over here so we can do current index equal to page index we can save this and now we should be seeing the changes right this works but now we need to display the pages conditionally as well so if we are on the home screen we need to show the home screen if on the search screen we need to show the search screen now to make that happen we need to replace the body with something else now we are going to create a constant which is going to be constant pages which will be equal to an empty list now we're going to replace this with text values so the first thing we have is home screen and we're going to have multiple screen so let me paste text for now so we have messages screen add page screen actually this is the search screen and this is the messages screen and finally what we need is a profile screen we can save this and if we go over here we are going to take this pages let me import that and we are going to have page index so basically we are going to take the pages list from here and we are going to access that pages pa a page index element basically so if we are on the suppose we are on the home screen it will have a page index of zero so we are taking the pages list we have and we are going to grab that a particular text widget for now that we have in our well constants dot dot file and we are going to grab this text from here if you are on the second index we will get add page index and that's how we are going to display the screens and now if you see we have home screen search screen add page messages and profile which means all of our stuff works pretty well now let's work on the add post functionality so for the add screen what we need to do is go to our screens and over here we can create a new screen named add video screen dot dot now let me import the material package first and we're going to create a stateless widget again which will be add video screen this will return a scaffold and what we basically need to show is a centered button so we can have a center and child will be a button so let's wrap it with an ink right now because we know it's a button and we're not going to use the buttons like the buttons that are given to us now on the on tab we are going to do something so let's keep it empty for now and in the child we're going to create a container which will have a fixed width of 190 and height of 50. now the decoration will be box decoration and the color will be button color child will be a constant center text which says add video it will have a style of text style and the font size will be 20 color will be colors dot black and font weight will be font weight dot bold right i've formatted this now let me save it and actually we haven't added this to our list so in our constraints.art file we are going to replace this text of add page screen with an add video screen let's do that and now let's clean close all the saved files and go to our odd ad audio add video screen and this looks the way we want it to look cool now whenever this is clicked we need to show a menu dialog box as you can see in the image in the left side so what we're going to do is on tap we're going to create a function which is show options dialog and it will take in a context now this will have we will have to create the show options dialog and it will receive a build context and over here we'll have to return a show dialog so we'll have to return show dialog this requires a build context that we have passed in and a builder now the builder will receive a context and based on that it will return widget which will be known as a simple dialog now the simple dialog will have children of all the dialogues which will be the simple dialog option now the simple dialog option will have an on press property which will be a pick video functionality and a child of row which will be children and we're going to mark everything as constant because we are not going to use any dynamic value and we are going to have icons dot image we are also going to have a text which says gallery and then a style of text style and the font size will be 20. all right now let's save this much and see what we're getting if we click on add video our gallery option is showing but as you can see there's not much padding and it doesn't look that good so what we can do is wrap this text with the padding and from all the sides we can add a padding of seven now you can see it looks much better and much cleaner now we can copy the simple dialog option and paste it two more times to display a camera option and a cancel option now this camera option and the camera option is going to have icons dot camera underscore alt and the cancel option will have cancel in this cancel right now if you click on add video you can see cancel camera and gallery option so whenever we click on one of these we need to go select an image from our gallery or camera whatever option so what we're going to do is create a function over here which will be called let's say pick a video and it will be of that it will receive some image source and a build context now we need to pick and pick up video and this is very uh good uh because we are going to use the image picker plugin only that we have installed to pick the video so we're going to do pic image picker dot pick video and this is going to be asynchronous and the source is going to be src that we're going to access from the parameter now we'll check if the video is not equal to null then we need to go to the next screen so the next thing screen we are going to have is a confirm screen which confirms that there is a video and we can add captions and all sorts of stuff so we can have import material and it will be a stateless widget again confirm screen can save this and now we can type in navigator dot of context dot push material page route and we can pass in the builder for the material page route action material not material page but material page route and it will be a context and we have to pass into the confirm screen for now we ignore the warning because we know that the confirmed screen that we are going to have is not going to be a constant now over here uh we are checking the video is not equal to null so like the video can be null when the user goes in the gallery and doesn't choose any video right so now we can we have to bind this quick video to our functions over here so we can pass this pic video and it will receive two arguments the image source so over here the image source is image source dot gallery and we have to pass in the context we can copy this line and paste it over here for the camera as well so we can have image source dot camera and finally when we click on the cancel we basically need to remove this dialog so what we can do is navigator dot of context dot pop this is pretty much it now let's try to run our app so let's rerun our app and we can go over here add a video let's say gallery and we can select the image from our gallery so let me select this and you can see we can play it over here and choose it now when we choose it you can see that it's compressing the video this is the default behavior in ios and ios devices only when we are selecting it from the gallery but we are also going to compress the video on our own and now you can see we have gone to the confirm screen because we have just a container and no scaffold that means we have a video selected so now in the confirm screen let's try to display this so in our confirm screen what we want to do is return a scaffold first of all and we need to accept some stuff from our constructor so first of all we need the video files so that we can play it and we'll have to import the dart io package so let me import that and after that we also need the video path so we can do string video path so that we can basically just run the file you know so that we can save it to our database with the video path all right now what we need to return but before returning but before returning what we need to do is set up our video player so to play the videos you're going to need a package named video underscore player link will be mentioned in the description below we need to take this and add this to our pubspec assist and basically with this first of all we'll have to convert the stateless widget to a stateful widget and also accept all of this both of these construct from the you know we have to pass except this from our constructor so we will mark both of these as required so required this dot video file required this dot video path and we can then save then in the return uh in the debug console we can see that we are getting this editor but that will be fine because we have to add that in the add video screen in the image state what we need to do is after the super in it we first of all need to create a controller so we can have late video player controller controller this will be to play the videos and we need to set the state so the controller will be equal to video player controller dot file and we need to pass in widget dot video file then we need to initialize our controller then we need to play the controller we also need to set the volume for our controller so it can be anything between zero and one so you can have 0.5 as well i'm going to pass in the full volume one and then we are going to allow the controller to start looping so whenever our video stops ending it will start looping yet again after this we need to return a scaffold and in the body we are going to have a single child scroll view and it will be a column the column will have first of all a size box of height 30 let me have a high 30 then first we haven't added the children property so let me add that let me put a comma here so that i can format the document and after the size box we need to have a video player controller but we need to give some size to it so what we can have is another size box giving it some dimensions so we can have width which will be media query dot of context dot size dot width and the height is going to be media query dot of context dot size dot height divided by 1.5 then the child will be video player and we'll have to pass in the controller to the video player because that's what it accepts video player controller as you can see now we need to pass in another sized box of height 30 and there will be a single child scroll view so now this single child scroll view is going to be scroll direction axis dot vertical and the child will be a column which will be main access alignment of main access alignment dot space evenly then there will be children and the children will first of all have a container which will be having a margin like we did for you know our previous text fields as well so we can have media query dot of context dot size dot with minus 20 and let's see why we're getting this error so we need to pass in this so we can do edge in sets dot only and from the left we want 10 and from the right we want 10 and for the width we need this or you can even do symmetric like i showed it to you previously you can have symmetric horizontal 10 and you can put a const over here now we need a child and the child will be text input field and we need to pass in some stuff so this controller we want is song controller which we'll create then the label text will be a song name and the icon is going to be icons dot music underscore note let's save this much and after that we'll again need our size box refer to the image in the right and the height will be 10 you can again put const over here now you'll again need a container so we can have that and there will be now a caption so you can have caption and this will be named caption controller caption icon will be closed underscore caption and finally after that we will again have a sized box and then an elevated button and the child will be text which says share style will be textile and the font size will be 20 and color will be colors dot white right now let me put that as a const and now it works now let me go to the top and create the controllers for us so the first controller we need is a text editing controller and that will be a song controller equal to the text editing controller we also need a captions controller so we can have caption controller and after that this is pretty much it now we should be able to see our stuff happening but in the add video screen we need to pass in the parameter so that we can see the changes happening in the top what we need to pass in is a video path so our video path video file is going to be video dot path and we have to pass in a file so it will be video dot path 5 and now let me import the dot io package and we need a video path which will be video dot path and now you can see that the video is of the type x file and it can be null but you're not putting any uh null value like null check over here right this is because we have already checked if video is not equal to null so we don't have to put this but in but in case we don't put this you can see that we are getting an error if we put exclamation mark our error goes away but for now we are going to check if video is not equal to null now let me restart the app and let's see if you're getting any error no let's add a video go to my gallery and choose this file as long as it's compressing we can see that there's no error which is a good thing and now you can see our stuff happening but now we can't see our video showing up that now this is because we haven't read the rules of our video player as well which is not a good thing we have to pass in these permissions to our info.plist file so let me go to our info.plist file i've copied these rules from here and we have to paste that down over here we have to pass that we have to save that and we have to run a stop our app and we can run that app again so now let's see if we are getting any error all right our app is loaded and now if we go to the add video screen and we select from gallery let's select this and choose and we go to the next screen you can see our preview video showing up here and we can have a song name and a caption also if we go over here in our confirm video screen just to make sure that we have sound controller and commission controller yeah we do have which is a good thing now the next thing we need to work on is whenever we click on the share button our video gets shared so now let's create a upload video controller so here i'm going to type in upload video controller dot dot and first let's name this class upload video controller and we're going to make it extend the get x controller so let's type in get x controller yeah now we have our class and make sure to import get so that you know we have all the get uh classes that we can access and not just one one class else it will become this very messy imports all right now let's create a function to upload the video so we can create upload video function so let's call it upload video and here we are going to have a song name then we will need a caption then the video path which will be a string not a file because we are directly going to get the video path over here you can see we directly have a video path so why not just use that cool now we are going to have a try and catch block since this function is going to be asynchronous we'll also add that in a way we'll add the async mark over here now we need the uid of the user so first of all we will call firebase auth dot current user dot uid and now we need all the users so that you know we can access some stuff so you can have document snapshot user doc is equal to await fire store dot collection users dot document uid dot get so that we can store the user profile photo user you know uh all of that stuff user name uh all of that in the controller in the database in the video while we are saving the video we will need all of that stuff so that we can directly display them while displaying it and not you know make two to three requests while just uh displaying the videos right so now uh to get the id what we are going to do is not uh use any package like uid or anything but we are going to use a very smart way lets uh see this so to get the video id basically so it's going to be var and you're going to get all the documents which will be equal to firebase firestore it says firestore let me name it correctly firestore dot collection videos dot get with this we are getting the uh all the videos so well document snapshots query snapshot not document snapshot because we are calling it on collection and not document and then what we need is the length of all like how many documents does this video collection have so we are going to do all docs dot docs dot length so with this we are getting all the length of the all the documents available in the video collection now we need to upload the video so we need the video url but uh how are we going to do it before uploading the video to the storage we need to make sure that we are actually you know compressing the video so let's create a function upload video to storage and we're going to pass to it our id so let's have our id which is video dollar length that means video 0 video 1 video 2 like that then the video path and now i'm going to create another function which will be called upload video to storage we can have that over here and uh it will accept a string id and it will have a string video path then what we need to do is we'll create a reference so let's have a ref which is equal to firebase firestore firebase storage dot reference and the folder name is going to be videos and the child is going to be id that means the second subfolder not the second subfolder in my bag this is going to be the video id so that means this video 0 video 1 video 2 that's going to be the file name then we will have to put this so we'll have ref.put file and to before putting the file we need to make sure that we compress the video so let's create a function called compress video and we'll have to pass in the video path because it needs a video path to compress the video so let's create a function called compress video again all of these classes are marked private so that we can't access them outside of this class which will be a good thing and doesn't confuse us so here we have our video path and now we need to compress the video to compress the video we are going to use a package known as video compress the link will be mentioned in the description below so we can copy this add this to our spec assist and click on enter we can stop our app from running and then we can make the app run again so that in the background it's running and we don't have to make any extra configurations for this you can go in the installing tab and check it there is no external configurations to do right so now we can compress the video to compress the video what we need to do is call the video compress class and then call the compress video method on it and we need a path to it so we'll pass in the video path now there are a bunch of configurations you can make with it you can see that you can even crop the videos but what you uh what we are going to do is set the quality which is the video quality and we are going to keep that at medium quality you can even do other qualities like if you do full stop and find it out there's a bunch of qualities you can find out but we are going to go with medium quality so that so that it's not too bad and not you know doesn't take much space as well now if you hover over this you will find out that it's a future so to fix that we'll have to do await and then pass in async now we're going to name this final compressed video which will be equal to this and we are going to return the compressed video and you can see that the compressed video is a media info so to get the file of this we can do compressed video with an exclamation mark dot file and we should get this this is a file right now we have to take this uh compressed video which will now be a future so we need to avail this because we used async over here we have to avoid this and this will become async as well so now we will put this file in our database and then we need to get the download url so as you are familiar we will do start snapshot snap which will equal to upload tasks which will be actually a float task and we have to name this upload task so we'll name this upload task eq upload task equal to the ref.put file then we have the snapshot so we can get the download url which will be equal to await snap snap dot ref dot get download url then you can simply return the download url and this is the upload video to storage function so if you want you can just make the type future string of upload video to storage this completes the task of uploading the video to storage and also compressing the video behind the scenes so we have the upload video to storage function done so after this is done we will get a video url so we can have that and we can save this much we also need to avoid this because it will return a future string so we need to update it and then we need to upload the image to storage now what is this image this image is the thumbnail that we are going to auto generate from the video that we are watching so again we will pass in the video id which is the video dollar length then the video path then we are going to take this function and now we are going to create this function as well so we can paste this we can have string id string video path and then we can again create a reference so we can copy this line only and paste it and instead of putting videos we can put thumbnails then uh what we need to do is put the file of thumbnail so actually we can even copy these four lines because they are very pretty similar lines and instead of putting in compressed video we need to put in compress get thumbnail let's say because we don't have to compress the thumbnail we don't have a thumbnail so we need to do get thumbnail and then all of these tasks like getting the upload task awaiting that getting the download url and returning the download url and we can name this future string as well so we can take this function we will create that because we will create this get thumbnail function so let's create it here only and it's going to be string video path and it's going to be asynchronous and then we're going to get the thumbnail how do we how are we going to get the thumbnail uh because of this package video compress this allows us to do multiple stuff including getting the thumbnail automatically so we can have final thumbnail equal to await video compress dot get file thumbnail and we have to pass in the video path over here then we can basically return the thumbnail and we can save this thumbnail over here all right now we got the thumbnail as well now let's try uploading the video to our storage finally so we are we will get the thumbnail which will be equal to this and we need to await it let's see where we are getting this error okay we need to put a space over here we didn't put that now we have to upload the video to our uh firebase but as we know uh we don't upload it directly to firebase like for our collections what we do is create a model so let's create a video model so we have video dot dot and the video dot dot is going to have multiple properties but before that let's create a video class and what are the properties going to be string username string uid string id of the video then the list of likes on the video we are not storing the comments as a property on the video class but we are going to save it as sub collection so we can't have this in our you know this class then we are going to have the comment count then the share count only the count is going to be there the comments are going to be in the sub collection then we are going to have the song name then a caption let me put a comma for semicolon then a video url and a thumbnail and finally what we need is a profile photo of the user then we need to add you know this constructor over here so i'll create the constructor which will require all of this and see you later all right we have we have required all of these properties through our constructor so now let's create the from snapshot and to json function that we created in the user class so we will have a map string dynamic and we'll have to json the name of the function then we're going to return a map so let's give return a curly bracket and then we're going to have our username so we can have this username then the uid and you have to follow for all the properties so i'll do that again and see all later all right so we have a two json function here as well now let's create our from snap function so we'll have video from snap document snapshot snap then we're going to have the snap short equal to snap dot data and we're going to treat this data as map of string comma dynamic and then we're going to return this video model and we will have to pass in all the stuff so we'll have to do snapshot username and everything like this for all the fields so i'll do that and see all later alright so we have our from snap function here as well now we can create a video instance of the video class so we are an app video equal to video and then the username is going to be user doc that we created on the top here userdoc.data which can be null and we're going to treat this as map of string comma dynamic and we're going to name this name as you can see for our user class over here we have the name name now we have the uid as uid then the video id is going to be video dollar link the as we had over here and here then the likes is going to be an empty list comment count is going to be initially 0 share count is going to be 0 all of this is the same name and the profile photo finally is going to be similar to this because we are fetching it from the firebase collection so we can have this and instead of name we can have profile photo finally we just have to put a full stop and then we can go back and our video instance of the video class is created so now we basically need to save this to our collection so we can have firestore dot collection videos dot dot video dollar length dot set and we need to set this so we can have video dot to json similar to that we did in the auth controller then what we need to do is show a snack bar if there is an error so we can do get dot snag bar error uploading video and the message is going to be e.2 string then we can save this much and now when we save when we have this and we save this in our collection after it is saved we need to make sure that the user gets to know that we have successfully uploaded or instead of that we can just go back to the main screen to tell the user that we have done it so we can just use get dot back which will push us to the previous page and we can save this much we can restart our app and let's try to upload it so we can go by your add video then we can select from gallery because this has no camera then we can choose this file note that this is not compressing the video that we have done this compressing video is default by the ios simulator that ios you know gallery that has happened automatically by the ios basically i iphone operating system now let's pass in a song name so we can have the song name let's say none and we can add the caption nice trip and we can share this this will take a while so let's wait for it and only when we go back to the previous screen do we know that we have got some uh output basically in our firestore and this is not working because well we haven't connected our function of upload video anywhere to our ui so let's go to our confirm screen and first of all we will need to first initialize this controller so to do that what we can do is call upload video controller we can name this upload video controller equal to and we will put get dot put and we can put this upload video controller then we can go to the top and instead of importing instance manager we can import get a get class all right so now let's save this much and take the upload video controller and bind it on our on pressed so over here we can have upload video controller dot and we can have upload video now we need the song name so we can have song name controller dot text then the caption controller dot text and finally the video path which is the video path so we can have widget dot video path now let's see what we have named them so they are not private so we can make them private and we can fix these errors by going over here and naming them like this finally the song name controller is also going to be similar like this it's not song name it's just song controller and we can have this so let's save this much and rerun our app to see what we're getting now so let's add a video again we can choose the file then we need to pass in song name so we can have none again nice trick and then we can click on share now you can see upload video controller has been created and initialized you can ignore this error that is nothing any error but just a tip what we can do all right now let's wait for it this should happen in a while and we went back to our previous screen which is the dialog box and if we refresh our collections then we should be able to see the videos collection and the ids video cd 0 that's exactly what we wanted because the collections initially because the number of collections initially were zero because the number of collections initially were zero so there is video zero if we upload another video that will come as video one and we have this which looks pretty amazing and if we go to our storage and we have our thumbnails the thumbnail will be auto generated and it should be a street which is looking good then we have our videos the video zero as well and if we click over here we will be able to see the whole video which is compressed that's good as well so our confirm screen and all of that stuff is done now let's try to display the screen or display the videos on this home screen and then we can work on the like comment functionality so now let's create a screen named as video screen dot dot and we're going to have a stateless widget for this as well so let's first of all import the material package then create a stateless widget called video screen and it will be a scaffold which will return actually a scaffold only and then we are going to return this video screen but let's go to our constant dart file and instead of the home screen we can have the video screen we can have this and let's save this much then to return in the scaffold what we need let's decide that so over here we have our image and in the image you can see that first of all we need a a sort of page where if we scroll even a bit it goes to the next page similar to that of the tick tock then we need a video which is displaying in the background and over it we need a bunch of options like you know this image the set of icons with their icon count then this circular icon that is revolving then over here the user name the description and the song name so we need all of these components so since they're uh one upon each other so what we can do is in the body we can return first of all we'll have to return a page view controller because as i said we need a kind of layout where we just scroll a bit and it goes to the next page so we will have a page view dot builder then the item builder will have a context and an index then instead of index it will be index all right now let's see this much it will format it for us that's why so over here we have to return a stat so let's return a stack and before that we need to have an item count which we will have then a controller which will be the page controller and it will we will have to mark some options like initial page will be set to zero and the viewport fraction will be one then the scroll direction is going to be vertical and not horizontal so we can have access dot vertical because we need to scroll vertically right then in the stack we'll have children and the first child is going to be the video player right so we can have video player and this is not what we want we need to create another widget for it which will be named video player item dot dot and this is going to be a stateful widget because we have to initialize the controller and all of that stuff so we can have import material and we'll create a stateful widget which will be a video player item then we have to return a container basically which will be of the entire width so we can have first of all let's create a variable called final size which will be equal to media query dot dot of context dot size dot height not height sorry it will just be size because we need to access the width as well so we can have size rod width height can be size dot height and this watch and the decoration will be well we just want the background to be black which will be constant box decoration color as colors dot black now in the child we want a video player so we can have video player and the video player will take in a video player controller so let's create that so we will have late video player controller video player controller and then we can have an init state where we take care of this video player controller so we can have video player controller equal to video player controller dot actually we will need network because we are getting the video url through which we are going to play so we are going to have widget dot video url and we have to accept that from our constructor we will do that but as you can see this video player controller and the video player plug-in that you're using is very useful you can call the file on it dot asset on it so basically with this you are able to play any file any video file wherever it is which is a pretty good thing so on the top let's first import it from our constructor so our video url and then we are going to require this field so we're going to have required this dot video url save this much then we need to make sure that that we initialize it so we can do dot dot initialize and after that is initialized we can call then and then we'll get a value for this value we are going to have video player controller dot play and we can set the volume to video player controller dot set volume and we're not going to set the looping to true because we don't want looping we just wanted to well show it once then over here in the video player controller we can have we can pass in the video player controller and we also need another bracket over here let's save this much we also need to add a disposed functionality and as a matter of fact we didn't do that for the you know the above function like for our other class which is the confirm screen so we can do that for we can do for that as well else it will keep playing as long as we are on the screen so we can go to our confirm screen and over here we can set dispose method then we can have controller dot dispose this is a good practice because it leak it solves the memory leaks that we will be having or we can have actually right so that is done let's go so we are now in the video screen and over here instead of showing video player screen we can have video player item and we have to pass in the video url which is this and we'll have to get the video url first so let's so we'll create that logic in a while but before that let's have our ui fixed so we can have column now now why do we need this column to show this part right here and also we need to have this part over here that's why we need a column so now uh in our column we're going to have children and the first is going to leave some height so we can have const sized box height 100 then we can have an expanded with a child row then the row is going to be having children and inside the children we will need an expanded widget again which will be child of which will have child last container with some padding const edge insets dot only and from the left we want 20 so this is the ui that we're going to create so yeah after this uh padding in the child what we want is here the child that we want is a column and the column will have main access size of main access size dot minimum and a cross access alignment of cross access alignment dot start we also need a main axis alignment of main access alignment dot space evenly that's a lot of options i know but yeah and we get we are not able to format the document because we are getting errors so for now we can comment this and then we can just uncomment this for a while then the column will have children and the children will have text of well first of all the username so you can add that then the style is going to be constant textile and we can have font size of 20 and color of colors dot white and we're going to even bold it so we can have font weight dot bold all right after this text uh we need to show the description or the caption so we can have this and we can pass in caption and the font size we will just decrease for this and we'll remove the bold for from here then we need the row elements so that we can have this part over here which is an icon of music and the song name so we can have row and children is going to be constant icon icons dot music underscore note the size is going to be 15 and color is going to be colors dot white after that we are going to have a song name so we can have a text which is going to be song name and the font size again will be 15 and we are going to bold it so these are the default options that we're going to carry out now let's refresh our app and see how it's looking it's coming over here as you can see but we want it over here in the bottom so what we can do is go to the top and first of all in the row we can have main access size as main access size dot max and uh in the cross access alignment we can have cross access alignment dot end and now this comes into place in the bottom that we wanted all right now our video isn't showing up that's just because we have no video to show now over here we also need a container in the row itself so that we can have a width of 100 over here and we have to create this set of icons over here the profile photo the heart icon the comment and the share count so we can have a margin of edge in sets dot only and from the top we are going to have media query dot context dot size but we don't need that very often so we can create a size variable over here at the top so that we can reuse this so you can have media query dot of context dot size and we can make the size variable go to the bottom and we can have size dot height divided by five then we need a child of column and it will have main axis alignment of main axis alignment dot space evenly not around space evenly then we can have children and the first thing we need is a profile picture over here so what you're going to do is create a function at the top over here we're going to have a build profile function which will take in a string of profile photo and we are going to return a sized box which will have a fixed uh width and a height so it can have width 50 height 60 let's say so we can have the width also 60 and then the child is going to be stack then in the stack let's format this a bit so in our stack what we can have is children and now children is going to be positioned and from the left we will have positioned from the left we will have 30 minus 25 so we will have 5 let's say and the child is going to be container which is going to be the width 50 height 50 and then a padding of const edge inserts dot all one then we need to pass in decoration which will be box decoration color is going to be colors dot white and there is going to be a border radius so we can have border radius as border radius dot circular 25 after that uh we're going to have a child of which is an image basically so we can have image and the image is going to have a property image of network image and uh we're going to pass in the profile photo url that we'll get and the fit is going to be box fit dot cover after saving this uh we can wrap this with a clip r rect so that you know we can get some border radius so you know we can have some rounded effect so we can clip our rect the border radius is going to be border radius dot circular 25 then we can save it again we can take this build profile from now for from here and go to the bottom and in our children we are going to pass in the build profile function where we are going to pass in the url so we can have string url for now it will show us an error but that's fine then we need a column of list of these elements right here so let's create that so we can have another column and we can have children and the first children child is going to be icons dot favorite size is going to be 40 color is going to be colors dot red or colors dot white for now let's put colors dot red colors dot red so that we get to know that we need to change this else we'll forget that and also in our icon we have to wrap this with a widget known as ink well so that we get the nice on tap functionality so we can add that on tab then we can copy this ink well and before doing that we also need to space out elements so we can have a constant size box of height seven now we can copy this and we can paste it down two more times so the next uh thing we want is well but before doing that actually what we are planning to do now is not this so we have a column of inkwell and that means that we have this favorite icon over here the next thing we want over here is this text over here so what we can have is text and we can say let's say 2200 likes and style is going to be constant textile of font size 20 and color colors dot white we are ignoring all the warnings for now because we know that we are going to replace all of these values with some dynamic values now what we can do is copy this column from here and we can paste it down two more times so we will have icons comment and it will show us two actually we're just going to show the number so we can have this much two and lastly we want a share icon so what we can do is have an icon which says icons dot reply and the share count over here can be let's say two we can save this much and you can see we are getting this error but that's fine and we can have all of these icons but these all of these icons aren't looking cool because we have given the color of red we have to replace these with colors dot white now it looks good amazing so now after this column final thing that we need is a circle animation so we can have a circle animation this widget we are going to build and the child is going to be something known as a build music album and we're going to pass in the profile photo here as well so let's say pro file photo and we have to create this widget so we can go over here and in the widgets folder we can have circle animation dot dot now obviously this is going to be a stateful widget so we can have a stateful widget we're going to call it circle animation then we're going to return rotation transition widget which will keep on rotating basically and now it will have something known as turns and we will we are going to use tween animation for this which will begin from zero and at one and we we need to animate this and for that we need a controller and we are going to create that controller now so this controller will be late animation controller controller and we're going to call the init state function and now we're going to do controller equal to animation controller and vsync is going to be this this class then the duration is going to be constant duration of milliseconds five thousand let's say which is five seconds and you can see this and we're getting this error because over here we have to implement the mix in you which we can do that with the with keyword and we can have which single tick single take provider state mix in we can save this much and our error is gone now we can do controller dot forward and a controller dot repeat after this is done we can animate the controller but we don't have to forget that we even need to dispose this controller so let's do that so we can have controller dot dispose cool now uh after this turns we need to pass in a child and the child is whatever the constructor gives us so we can have that final widget child and this is going to be it required this dot widget this dot child actually not widget and this is because type animation end can't be assigned to the parameter type animation double so basically this is an end and not a double this is because we have passed in zero and one what we can do is pass in 0.0 and 1.0 so this will make it a double and not an end and the child can be widget dot child we can save this much go over here and import the circle animation and we're going to create this build music album function right now so we can go to the top of our file and let's actually build a music album it will again receive some profile pic so we can have profile photo and now we are going to return the size to box again so we can have return size box and with a width of 60 and a height of 60 we need to pass in a child which will be a column and it will have children the first child is going to be a container which has a padding of edge inserts dot all 11. then we need to pass in height 50 with 50 this is all that we've done in the upper function as well and from now this thing will change so what we need to pass in is a decoration which will be a box decoration and it will have something known as gradient which is the gradient of colors and we can have constant linear gradient of colors and the colors list is going to be colors dot gray and let's say colors dot white now we can go over here format this document and over here we have to return a semicolon we have to put a semicolon so now we have this in the decoration the next thing we want is after gradient we need to pass in a border radius so it will be border radius dot circular 25 and then there will be a child which will be clip our rec and it will have a border radius of border radius dot circular 25 then a child of image image will be the network image and we're going to pass in the profile photo and the fit is going to be box fit dot cover and we can see this much now we can take this build music album and go to the bottom and we have put that so let's try to refresh our app and let's see this is revolving which is a good thing now we only need to get the controllers right so all our logic stuff we need to get in so let's do that so now let's create our controller right here so what can we name it let's say video controller dot dot and here we are going to first let's just import the get dot package l3 will return multiple packages which we don't want then we can have video controller which can extends the extend the get x controller and then we are going to have a final rx of list of video and we have created this video class a video model in our models over here you can see that so over here we are going to make it an observable so that we can bind some stream to it and display the videos continuously real time so we are going to have this so let me just copy this and we are going to give it an initial value of empty brackets because initially there are no videos and let's create a getter as well and the getter is going to be list of video and we can create that video list and we're going to do video list dot value now make sure to make this private and this is going to get public else both of them will be public and that will be a problem you can see over here so this is going to be private so that we can access this only in this class and then if you want the value you can use this get value right here cool now let's create an on edit function we already know what init does it runs when the class first is initialized then we can do video list dot bind stream now what are we going to bind the stream to well this collection of videos right so what we can do is firestore dot collection of videos dot snapshots right now but we need to map this snapshot so that we can store this snapshot value each and every video over here in this list so what you can do is dot map so that it goes through every snapshot over here for now it's just video zero but in the future it will be video one video two as well now uh it will receive uh the event will be query snapshot which will be named let's say query and we are going to turn this arrow function to our normal lambda function anonymous function basically and now we are going to create a list of video which will be a return value and it is going to be an empty bracket now we are going to run a foreign loop so what we can do is for element in query dot docs we are going to add the element to this return value array so what we can do is video dot from snap function that it created because over here we're going to get the query snapshot and then we can pass that query snapshot over here which which is the query dot dots which will give us the document snapshot right query document snapshot which is like a sub collection or sub part of the query document snapshot after having that we need to simply return the return value array so that it gets binded to the well basically it gets mapped and all of this is converted to a stream and is saved in the video list so anytime a new video is uploaded it will get shown real time now we have that what we can do is well now we can go to the video screen so actually let's close all the saved files because it is creating a lot of mess and now we can go to the video screen and right here first of all we have to import the we have to get our video controller so what we can have is final video controller video controller is equal to get dot put and we have to pass in the video controller we're getting this error for get so what we can do is import and we are going to call get dot dot and we have to remove this constant because we are creating a final variable and now we have to and this is not going to be a pages anymore it's not going to be constant so we can have list of pages because this is not a constant now and we can add a constant for the add video screen right now in our go into our video screen what we can do is wrap this whole thing wrap this page view builder with a widget and that widget will be called something as obx this opx is a very useful feature but now now this page view builder will get trapped by a widget which will be similar to a builder so we can have wrap with stream builder and we're not going to wrap it with the stream builder but it's similar to a builder so we can have this we are going to remove this and we are going to call in obx now with this obx we are able to you know uh get the changes real time and listen to the value real time so now what we can do is remove this from here because it's not going to have any parameters or arguments passing in and we're going to return this cool now what we want to do is pass in this over here so the video url now what is the video url going to be so well it's going to be something like video controller dot video list which is the getter that we created and we want we want only one right so we are going to grab it with the index property in the item builder and then we are going to call dot video url property over it but now we will need some other properties as well like username and description and all of that stuff so instead what we can do is take this from here and create a separate variable to put it in so we can have final data and we can put this now we can do data dot video url which is a pretty good thing now if we save this we should be seeing our data coming over here now what we want to do is go to the bottom and in the username we can pass in data dot username in the caption we can have data dot caption then we can have in the song name data dot song name and this is a use of models as you can see we are not uh we there is no chance of any error because we are directly calling the data dot song name which is a property in our video class so we are getting this nice auto suggestions as well which is which is pretty nice and over here we can have data dot likes and let's see where we are getting this error this is a list so to fix that we can have dot length dot to string now we can go over here in the comment and we can have data dot comment count dot to string and finally the share so we can have data dot share count dot to string you can save this much and we need to also pass in the profile photo so what we can have is data dot profile photo and on the top instead of and here we can include the we can remove the warnings by just typing in a constant that's pretty good over here as well for the like and in the build profile we are again going to pass in data dot profile photo all right now now we're getting error over here so that is because we need to pass in the item count now the item count is going to be video controller dot video list dot length because this is an array so we can call the length function over here now let's refresh that and you can see that we are not getting any error and our video is showing up which is pretty cool so let's go to our video controller now and work on the like functionality so we'll create a function like video and it will accept the video id so we'll accept that string id and then we'll create an asynchronous function now let's update it so we'll have await firestore dot collection videos dot document id dot get and we're going to save it with the name document snapshot because it is of the type document snapshot so let's put that and now we are get we've got the user id so what we can do now is first of all check if the doc dot data which we are going to have as dynamic so that we can access any value so and also grab this with the bracket and now if that likes property contains the uid of the user and we're going to need that uid quite a bit of times so let's create that variable up here and we're going to name it auth controller dot user dot uid and i don't think we're getting that auth controller dot user and we'll have to create that user update there so let's go to our auth controller and get the user so we can have user get user and we can have let's say underscore user dot value right and now this can be non labeled and now we can have user dot uid now if the uh likes property contains the uid then what we need to do so first of all let's put this bracket right here actually over here and then a bracket over here so if uh not id if dog dot data so if dog dot data contains the uid so that means that the likes property over here contains the uid then we need to remove the uid so what we can do is await firestore dot collection videos dot doc id dot update and we have to update the likes property so we can do likes and we can have field value dot add a remove and we're going to remove the uid from here else what do we want else we basically just want the likes array well the likes property to have the add a union property so basically if the like property contains the uid that means we have already liked so we need to remove the dislike remove the like because if we click once we need to add the like and if it's already there the if and if we click we need to we need to remove the light right so uh we'll i do array dot array union over here in the else condition now we can take this like video property go to our like and what we can do is controller what was the name of our controller i forgot i think that's video controller so we can have video controller dot like video and we have to pass in the id so what is the id going to be data dot id and we can save now if we run this we should be seeing the like and if you click over here it increased to one it's real time and we didn't have to make any extra configurations for this well it's only because we have used obx right now if you again click it turn to zero but the only problem is the like color over here so what we can do is over here we can check if data dot likes dot contains the auth controller dot user dot uid so if it contains already then we want colors dot red else we want colors dot white and we can remove this constant from here because it's dynam it's now well dynamic because you're using data dot likes and now if we run our app we should be seeing so if i click on like it changed to 1 again it changed to 0 again it changed to 1 and now if i restart my app i should be stay seeing the state uh showing up and it is one now let's work on the comment functionality so now for the comment uh we'll have to create a new screen because whenever we click on the comment icon over here we should be able to see a screen something like this so let's create that so in our screens we can have comment underscore screen dot dot and we can import the material package and then we can have a stateless widget which will be called comment screen then we'll have to return a scaffold and in that scaffold we'll have a body for now let's just give it a center text which just says display comments right and now we'll have to navigate to the from the video screen so let's close all of these files and whenever we click on the comment icon over here we should be able to go to the other screen so what we can do is navigator dot of context dot push material page route and we can have the builder as the context and we can pass in the comment screen we can put comma separating over here and now we can put constant which is nice now uh whenever we uh click over here we should be able to go to that comment screen and we're going there so the first thing as you can see we want this box to show up which is the comment box so let's create that to do that we can go to our code again and in the comment screen uh what we can do is in the body we can replace this with a single child scroll view so that we don't get that render flex issue that we usually get and then in the child we can have a sized box and the sized box is going to have a width of and we'll have to create a size variable so that can be final size which is equal to media query so we can have media query let me rename it media query dot of context dot size and then we can take the size variable and call size dot width and the height can be size dot height then the child can be a column which is children and the children will be first of all we will have to wrap it with an expanded because after displaying all of these comments which will take the maximum space we need to display this comment part as well so now the child is going to be a list view so list view dot builder and we will get a context and an index and after that we can just return a list time so the list style will have a leading element of circle avatar which will be this part right here so the circle avatar will have a background color of colors dot black that means as long as it's not showing up we got any error and then it will have a background image of network image and the network image is going to be the profile photo so we can just type profile photo for now we're going to ignore the warnings like we did for the previous uh ui we are going to fix that after we put in the dynamic values then we need a row or and we'll pass in children which is the username and the disk whatever their comment is so we can have text and there will be username then the style will be a constant text style and the font size is going to be 20 we are going to have a color of colors dot red and then a font weight of font weight dot w 700 not bold then we can have another text so we can just put this and we can type in the comment description let's say and this is going to be colors dot white we will have the same font size because they shouldn't look weird with one small and one big and then we can remove the font weight or we can just reduce the font weight to w500 after that we need a subtitle so after this row element we can put a subtitle make sure that we are in the title okay we need to get out of this row and we can put in the subtitle now the subtitle will have two days ago and the number of likes on the comment so we can put that so we can have row and it will be children and first of all this will have a date and we need to get some styling so the styling is going to be textile and then the font size is going to be 12 color is going to be colors dot white we can save this and after that we will put some uh you know a bit of spacing here so we can have a constant sized box of width 10 after that we can again have a text which says 10 likes let's say and we will have a style of constant text style and the font size is going to be 12 with color as colors dot white you can save this much and let's see we are getting many comments and that is because we haven't specified the item count which we have to in our list view builder so what we can do is here we can specify the item count for now to be one we can save this much and now you can see one comment showing up which is pretty good now what we need to do is add a trailing element as well which is this part right here which is an which is a height icon so we can put your trailing and the icon can be icons dot favorite and the size is going to be 25 and the color is going to be colors dot red now we will also wrap this with an enclosed widget so that it is clickable so wrap it with a widget and call it inkwell now the ontap functionality will basically help us to like the comment so that's good and now we're getting this like functionality as well now after this expanded we need to pass in a divider and after that we need to pass in another list type now this list style will contain our text field so we can add that so in the list style we can have a title of text form field and in the controller we can pass in the comment controller which we are going to create up here so let's have that final text editing controller comment controller which is equal to text editing controller and we can have that we can remove the constraint from here go to our video screen remove a constant from here as well save this much go back to our common screen class and pass in the comment controller now we are going to have a style of constant text style and the font size is going to be 16 color is going to be colors dot white because it is a black background right and now we want a decoration of constant input decoration and the input decoration will have a label text of comment a label style of text style and then the font size is going to be 20 color is going to be colors dot white and a font weight of font weight dot w 700 after doing this much what you can do is have an enabled border as well so you can go in the input decoration again and have actually outside the input decoration we will so here we can have enabled border and enable border will have underline input border and the border side will have border side of border side color of colors dot red then we can have a focused border and again we can have an underline input border and the color will be colors dot red again so now we can save this much but before that we have not we are not complete yet so after this list tile and the title we want ascend button as well you can see over here that we have a send button so inside over here we can have a trailing option and that will be a text button and it will have a child of constant text which will just say send and the style is going to be text style font size 16 and color as colors dot white then we can even have an on pressed functionality and which is going to be an empty bracket now this end is going to be sent not misspelled and we have a send over here which is looking pretty good now let's create a comment controller and uh have our logic in there so over here we can have comment underscore controller dot dot and first of all let's again import the get package so get dot get dot dot then we'll again create a comment controller class which will extend our get x class so now the first thing we need is the list of comments so we can have again an observable so we can have rx list of comment and we'll have to create this comment class which is a model so we can go over here and create the comment dot dot model right and now the comment model will be having a class comment and it will have a string of username string comment a date published and it's going to be final because we are going to receive it as a timestamp which is given by firebase but we are going to send it as a date time and it is going to be a list of likes then we are going to have a profile photo so string profile photo string uid string id then we can create a constructor which is comment and we can have required this dot username and i'm going to require all of this again and see you after i require after creating this constructor we need again a two json function so we can create that so we can have map string dynamic to json and we can return a map and i'll see you again after i complete all of these values our two json function is ready and the last thing we want is our from snap so we can have from snap as well which will take in a document snapshot a snap and we can create a snapshot variable which will be snap dot data we have to name this snap not now and we have to take this as a map of string comma dynamic and now we have to return the comment i'll see you again after filling in all the values so now our from snapshot ready uh comment our from snapshot function is also ready now we can go in our username comment controller and we'll import the comment class and then list and we can call call this comments and then we can take this put in the default value as a list of comments and then we can create a getter and we can have comments dot value now the first thing we need is the post id so that you know we can update that posts comments so we need a post id which will be a group global variable but how do we get this post id right so we are going to call the update we are going to pass in the update post id method which will be a string which will receive the id of the post and then we are going to set the post id equal to the id and then we are going to call the get comments functionality which we are going to create right so this will update the post id with uh for us and we have to call this function as soon as the app builds so we'll call this in the build function in the stateless widget or if you want you can convert it into a stateful widget and call it in the init state so now let's create a get comment and it will be asynchronous and now uh we will get the comments for this but before getting the comments we need to make sure that we even post the comment so we'll create a post comment and we're going to call it string comment text and it is going to be asynchronous and first we are going to check if the comment text is not empty so if it's not empty then we need to well comment so we can have document snapshot which will be user doc to get the user documentation document basically and we can have firestore dot collection users dot doc and this will be the uid so we can have auth controller dot user dot uid and we can call the get functionality and then we can also get the videos doc or comments like all the comments so that we can get the post id because our post id is going to depend on the length of the com length of the like the number of comments on the video so we can have all docs let's say and you're going to have firestore dot collection videos dot dot post id dot collection comments dot get and now we are going to call the length which will be all docs dot dots dot length and now we are going to create comment which will be a common and it is going to be a user model and the username is going to be user doc dot data as dynamic and we'll wrap this with a parenthesis and it's going to be name now the comment is going to be the common text and we can trim that so we can call the trim so it will remove all the outer spaces from this text you can even use this for the email and password and all of that stuff but i showed it to you now the date published is going to be datetime.now the likes is going to be empty likes the profile photo is going to be similar to that of the username so we can copy this and have this then we can pass in the profile photo the uid is going to be again this and we can pass in the uid actually we can do it this way or we can just use authcontroller.user.uid and finally we need the comment link i like the comment id so that will be comment dollar length cool now we can save this and we have this much so now let's save it to firebase so to do that we can call await firestore dot not underscore but firestore and we can have firestore dot collection videos dot document of post id dot collection comments dot doc comment dollar link dot set and we can set the comment dot to json all right so after that is done uh we can wrap this with a try catch block which we forgot to do so let's have that and we can take this whole thing from here and even this and we can put that over here and in the catch what we can do is get dot snack bar title is going to be error while commenting the message can be e.2 string and with this we should be able to post a comment so over here in a comment screen what we can do is first of all put so we can have comment controller comment controller which is equal to get dot put and we can put comment controller and we are getting the same name so what we can do is pass this as a underscore and for the comment controller over here we can pass this then we can again go to the top and import the get dot dot package and we again have to wrap our list view builder with obx so we can wrap this with a stream builder and then wrap it with a obx so remove all of this stream and all of that stuff then we can have obx and we can have this much we can save this and now in our obx what we need to do is go to the send part and here we are going to have comment controller dot post comment and we're going to pass in the comment text which is going to be comment controller and with uh it's going to be with a underscore because that's a text controller so dot text and that is all we need to do so we can save this much and we go to our comment screen and we see that we are not getting the right thing but that's fine we need to comment so we can say this is comment and we can click on send and we can say that the path is not empty so we are getting some sort of error over here so in our comment controller so the error we were getting was that over here we didn't call the update post id method so what we can do is comment controller dot update post id and what do we need to update it with weld the id and where are we going to get the id from from the constructor so what we can have is final string id and we can have required this dot id we can save this much go over here pass in the id as data dot id right now if we say this much and go to the comment screen and again comment this and send we should be seeing the comments displaying and if we refresh we have a comments over here and we can see the comment zero showing up which is pretty cool and we can see our comment is there and so if we go in the comment zero and see we have a date publish profile photo everything looks very nice but now you can see that our comment count hasn't updated because we haven't we haven't changed the value of the comment count over here so to do that we can go to our comment controller and we'll have await fire store dot collection comments dot doc post id dot get and actually save it in a document snapshot and then what we can do is firestore dot collection videos dot dot post id and we can update the value over here so the comment count is going to be comment count and we can wrap this in a single inverted comma so we can have doc dot data which is this doc doc dot data as dynamic and we can add the comment count so we can have like this comment count and we can add one to it we can save this much and we can await it after saving it we can rerun our app and well let's see the comment so hey we can put click on send then we can see comment one now we should be seeing one comment but we got an error over here our comment count hasn't increased over here so we have faced some issue over here in this part right here so where it's not comments it's videos we made that mistake now let's delete our sub collection of comments take this print that over here click on delete and now if we rerun our app and click over here let's comment this again and we can click on send we're not receiving any issue our comment count has increased to one and if we refresh to see the sub collection and now if we go to the back screen and refresh our app we can see the comment count one showing up which is pretty good now let's try to display all the comments to do that we have to go to the comment controller and in the comment controller get comment we need to take the comments uh private comment that we had created and bind it to a stream and again we're going to do something similar to what we did for the post so we can have firestore dot collection videos dot dot post id dot collection comments dot snapshots dot map and the map will have a query snapshot and we can have that as query we can turn this arrow function to an anonymous function and we can have list of comment as named as return value then we can do for var element in query dot docs we need to add to the return value so return value dot add and we can do comment dot from snap and it will have an element now we can simply return the return value so we can have return return value put a semicolon put some commas and we can save this much now if we try to run our app we still be getting this error and that's fine because over here we need to make some configurations first our item count over here is going to be comment controller dot comments dot length then in the item builder first only we will create the comment and that will be equal to comment controller dot comments at index and the profile photo can be comment controller dot not comment controller comment because you have created that variable for this purpose to eliminate the purpose of using the this big offer word again and again then the comment dot profile photo comment dot username comment dot caption not caption i think it's comment dot comment then the date for date we are going to use a package named as time ago so let's add that link will be mentioned in the description below if you want to check it out so with this time ago package let me stop the app execution after that i can restart and in the meantime that's happening i can explain what's time ago so first of all let's import the time ago package and we'll import that that as t ago and we can run without debugging now we can go to the bottom and with this time ago package we can display in a format like this two days ago three days ago a moment ago something like that so date will be formatted according to that so what we can do is t ago dot format and we'll have to do comment dot date published and since a date published is going to return timestamp we need to convert this to a date and now we can put a constant text style now the number of likes is going to be something like comment dot likes dot length like so that will be 0 likes 2 likes 3 likes then the on tap we haven't made a method for it yet but we'll make it then what we need is down here this is actually what all we need and now we can run our app without debugging i think we figured all of it so let's do that and wait for our app to launch all right so our app has been loaded and if we go over here we see our comment showing up private this and there's not much spacing between them so what i can do is go to the comment and in the comment.username i can use string interpolation and add some spacing like this and now this is creating some space which is pretty cool so now whenever the next thing you want to do is whenever we click over here we need to update the like counter over here so in our comment controller what we can do is after the post comment method we can create a method known as like comment and that will be string id and that will be asynchronous function then we are going to call the uid because that is what we are going to need throughout the function so user.id then we can have a document snapshot of dock which will be await firestore dot collection videos dot document will be post id then we need to go to the collection of comments then the com then the post then the comment id that we'll get from the parameter then we need to get it so we can do dot get that should be named doc after this uh we need to check if doc dot data as dynamic and we'll call the likes over here so you can have this and again put over here so the likes property contains uid and this logic is pretty similar to that of the like property like the like functionality on this screen that's why i'm speeding this i'm not explaining much because i've already explained it so firestore.collection videos dot dot post id dot collection comments dot dot id dot update and we're going to update the likes property over here so we can have likes and we will do field value dot array remove and then pass in the uid to remove after that we can have an else condition and then we can take this firestore collection put it here again and instead of adding remove we can have add a union let's avoid both of these because these are asynchronous processes and this is all we need to do to like the comment so after that is done we can go over here and check if we like and go in our videos comment sub collection comment 0 there is no like that's because we haven't binded this like comment to our comment screen so what we can do is in the on tap we can do comment controller dot like comment and we can pass in the id and what is the id going to be and the id is going to be comment dot id the comment is this variable that we created up here now as a bonus before even checking we'll have confidence in ourselves and here we can check that if comment controller dot comment not comment controller but we can just use comment dot likes dot contains uh auth controller dot user dot uid then we need to show the colors dot red or we need to show colors dot white then we can remove this constant from here and put it there then we can restart our app go over here in our live and if you like this comment it changes to 1 we can again remove this 0 and now to check the state if it's working or not we can refresh our app go to our command and here we can see that the state is maintained which is pretty good i can even put another comment so let's say another and click on send or another is showing up here and that is not liked so that's working pretty well and which is a good thing and our comment is also working so our comment part is done now the next thing we want to work on is the search screen so we search on the for the users so there will be a text field in put away then we will get the list of the users then we can click on any user profile and we will be directed to the user profile screen so let's do that so now let's work on the search screen so what i'm going to do is create a screen over here search underscore screen dot dot and let's import the material package and we're going to have a stateless widget for now so let's call it search screen and in that we are going to have a scaffold first of all and then an app bar which just says can you with a search like it can have a text form field which can basically say that please search for the user so we can have a background color of colors dot red and actually to see the changes let's take this stateless widget from here put it in the constants and in the search screen we can have a search screen and let's import that and we can call this as a constant which might change in the future but let's keep that for now all right so in the title we want text form field and the text form field is going to have a decoration of const input decoration and the field will be false hint text will be search and the hints style is going to be text style and will have a font size of 18 and color of colors dot y right so now let's see how it's looking if we go in the search nothing is showing up and that's because we have gotten an error over here let's see why we're getting this all right so let's re-run our app and see so over here let's go to the search we're still getting this error over here and this has something to do with circle animation so the error is that we want to dispose the controller before calling super.dispose this has caused the error and now if we go over here we can see that we are not getting the error anymore and if we go here our search screen search bar is also showing up which is good so now we can go to our search screen again and in the body we can have a constant text which is centered which can say search for user so we can have a text which says search for users and i wanted to increase the size so we can have a text style and then we can have a font size of 25 color of colors dot white and a font weight of font weight dot bold let's save this and let's see what we're getting search for users now we want to display this text only if the user has not submitted the form so what can we do well we have to create a logic for our controller so we can type over your search underscore controller dot dot and then in our search controller first we will import the get package so we can have get and after that we will need a class search controller which extends the get controller get x controller sorry so where we are going to create a final variable which says list of user which is the user model that we created not the firebase but the user model and we're going to have a private property called search to users and it is going to be of this type and we're going to give it an initial value of a no like no users are there all right and now we also need to create a getter so we can have list of user get searched users and we are going to pass in searched users dot value and after that we are going to search the user so a search user is going to get a typed user so like whatever the user is typing so whenever the user submits the form we are going to get this typed user parameter and we can check on basis of that so to make the search functionality what we are going to use is firebase search query so over here if you come to the users tab and over here there is a filter button so if you click over here and filter by feed you can see that if we uh we can sort or do any sorts of stuff using this filter so if we click on name we can add a condition where it's less than or equal to not equal to greater than equal to less than or equal to and then you have to type in a string so let's say i type in dravan it will get users based on this condition so it just checks the ascii code and then gets us the name or something like that so we are going to implement this in code so what we can do is go over here and have searched users dot bind stream that we did before and over here we are going to bind stream to firestore dot collection users and we can put the filter with the where proper method and then we can have name and we can check if it's greater than or equal to the typed user cool and then we can get the snapshots dot map and we will get a query snapshot over here we can call that query let's say and we will again convert this to uh anonymous function and then we will again have list user return value equal to an empty black empty list then for var element in query dot docs we can add to the return value so return value dot add user dot from snap element we can save this much and then return the return value this works and we can put a semicolon here as well so this should work now we can go to our search screen and well first of all have our controller which is search controller and we'll name the search controller and we'll put that so get dot put and we can put search controller now we will import the get packet so we can have import get get dot dot now you have to remove this constant as i've mentioned previously again in our constants or dot file we'll have to go and remove this now we can get the search controller and whenever the text form field over here is clicked and pressed enter then only we need to show the users so what we can do is in our text form field we'll have a declaration and after that we will also get an on submitted and with that we'll receive a value and then we can call search controller dot and what we can type is let's say search user and we need to pass in the value that we receive over here cool now we need to even check so this is go where the conditional part is going to come in so if the field is submitted that means the fetch has been completed so the search user now has some value so search to users list has some value so what we can do is search controller dot and search users if that is empty then we need to show this so that means if the list is empty then we need to show this else we need to show the list view builder so like the list of all the elements that we like all the list tiles that we will have so what we can do is have a list view dot builder over here and item builder will have a context and an index after that we will also have an item count and item count is going to be search controller dot searched users dot link in the item builder we are going to have well a list style that will be clickable but before doing that let's wrap it with an ink well because we want it to be clickable right so we can have an ontap property and we'll just pass an empty function for now and the child will be a list tile and we're going to return the sync well and we'll remove this comma and put a semicolon instead now the list style will have a leading of circle avatar and it will have a background image of network image and the network image is going to be something related to search controller and since we don't have to use it quite often what we can do is create a user over here so user and we need to import that user model which will be search controller dot search to users and we'll grab the list elements by their index now we can take this user and we can have user dot profile photo we'll also put some commas so that we don't get any errors and now if this is done and our leading is done we can have a title and the title is going to be username so it can be user dot name it will have a style of constant text style and the font size is going to be 18 and the color is going to be colors dot y let's save this much let's reload our app and see so now if i search let's say rivan and click enter we're not seeing anything that is because well uh we are not wrapped this with a get x uh sorry with an obx so we have to wrap this with a builder and that will be called obx now this obx allows us to well listen to the changes in our app and we'll work according to them so now if we do let's say and click on enter we get one rana was showing up which is pretty cool right and now the next thing you want to do is whenever we click over here we should be seeing the profile screen so we can create another screen called profile underscore screen dot dot let's import the material package then we'll have a stateless widget called profile screen we have to return a scaffold we'll do that and over here we will also get the uid of the user so that we can make some changes over here as well and display some stuff so let's require this uid and we're going to make this uh stateless widget profile screen in such a way that this can be accessible using this over here as well so if we use the widget here it will be it will be showing all the stuff correctly so we are going to reuse this widget when we click over here and over here cool so now in the scaffold for now we can just have a body of center text which just says profile screen right now let's have this much and now if we go to the search screen and whenever there is an ink well what we need to do is navigator dot of context dot push material page route and in the builder we are going to pass the context and it is going to pass in the profile screen now we need to pass in the user id which we are going to pass in as user dot uid make sure to not use auth controller or uid else you will always show the current user's uid cool so now if we click over here you can see profile screen showing up which is nice so now what we can do is close all the saved files so that there's no confusion and in our constants.dart file as well we are going to replace this text with a constant text which just says let's say profile screen right and we're going to pass in the uid as authcontroller.user.pyd which is good now we need to remove this constant because we are passing in a dynamic value as the uid and now if we restart our app we should be seeing profile screen when we click over here that works now we will go to our profile screen so in our profile screen let's build the ui of our app first so what we need is first of all an app bar which will display the username and all the options settings that kind of icons so we can have an app bar now this app bar will have a background color of colors dot black 12 then we need a leading icon or that will be constant icon icons dot person underscore add underscore alt one outline cool after that we need an actions button which will be a constant list and actions button are this kind of stuff the icons that show up over here so over here we will have our icon called icons dot more underscore horizontal cool now let's save this much and we can see that icon as well now we need a title which will be centered by default so it will be text which just says username so we can have the username and we're going to have all the logic in our other controller that we're going to create in a while so i'm not putting any values by fetching from the internet over here so now the this will have a font weight which is bold and then a color which is colors dot y now let's save this and you can see user name showing up now the next thing we want is well if we go to our image over here you can see that we have completed the app bar section now we want a column widget where we can have this part right here which is a circle avatar then this part which is the list and then we can have a sign out button follow button accordingly and then a list of images so let's create that so in our body what we're going to have is a safe area and then in the safe area we're going to have a child which will be a column and it will have children and the first child that we need is well another column so we can add that column and inside that will be a row now this row will just have the image network over here so this part over here so we're gonna have a main access alignment of main access alignment dot center then children will be well a circle right so we will need a clip oval widget so that we can clip the oval and in the child we are going to have an image and to display the image we are going to use something known as cached network image with this cache network image you'll be able to do multiple stuff that we can see so if we click enter and install it let's stop our app and after that this pub get is completed we can run it up again so basically with this cache network image our images will load up earlier and faster because it will get saved in the map apps cache so that will be a good thing for us and our apps performance so now we can't run this because then we need to have this so a cache network and let's see why we're getting this error now that's because we didn't specify the children in the column so let's specify that property and after this row we need this column again right so now this cache network image is going to have a fit of box fit dot cover then an image url and we are going to pass in some image url over here cool and it will have a height of 100 width of 100 and when the image is not showing up we need to show a circular progress indicator so what we can do is well first of all receive context and url and and then show constant circular progress indicator after that we can have an error widget so in case there is an error what we can do is context we will get context url and an error and then we can just display an icon which says that there is an error cool after this is done we need to get out of here so before doing that we need to check if our app is showing up pretty well so let's wait for our app and let's see if we're getting the output all right so our app has loaded up and if we go to the profile screen we can see an error widget because we have not mentioned any image url but we will so that's not an issue so let's continue so if we need a sized box of height 15 over here let's say 15 and after that we need a row where we can basically tell about followers following all this stuff so for that we need a row inside of which we will need a column so we can create a row and the row will have children and before that we will need a main axis alignment of center so we can have main access alignment let's let me undo that and we can a main access alignment dot center now the children is going to have a column and the column is going to have again children the text is going to be let's say the number of followers so let's say 10 the style is going to be constant text style and we're going to pass in font size a font size like this 20 then a font weight of font weight dot the bold let me save this much and after this we will need another sized box which will have a height of 5 and then another text so let me paste that and this will be following let's increase the font size so let's decrease actually so we will have 14 and the font weight let's keep it this way only and yeah this seems good this this seemed pretty small so i just changed the value from here cool this looks good now we can just copy this column and paste it two more times so to do that we're going to have another column over here and let's save this and this looks good but we need to have some spacing over here so what we can do is before this have a container which will have a color of colors dot black 54 the width will be 1 and the height will be 15 then the margin will have a constant edge in sets dot symmetric and the symmetric is going to be horizontal 15. let me save this much and we should get some spacing this looks really really cool so now this will be for followers so we can have followers and let's say this is 10 again this looks good now i can copy this and then paste it again with the container right and now this will tell me the number of likes that i have after that is done let me say this as well and now this looks fantastic so now after that we will leave a sized box so after this row we need to work over here on this sign out button so we can have a sized box of height 15 and then we need a container now the container will have a width of 140 height 47 and the decoration will be well let me go back over here the decoration the decoration will be box decoration and we're going to add some borders so we will have border of border dot all colors dot black 12 this won't be visible much but yeah it is a border that we're going to add let's see why we're getting this error and that is because we didn't specify the color argument yeah after having that we will get out of this decoration and we'll have a child widget which will be centered and we'll have a child and the child will be a text which just says sign out and this is going to be conditionally rendered but we look at it after a while because this might even change into follow or unfollow and since this is going to be clickable we need to wrap this with an inquil widget so what we can have is wrap with a widget called inkwell and we are going to have an on tab and then we can save this much let me format this document cool now let me add some styling because over your sign out seems very out of place so style will be a constant text style and the font size will be 15 and the font weight will be font weight dot bold we can save this much and now see that is looking much more better cool now the next thing we want is now a list of images over here and that will be able to work only after we create a logic so let's put a comment over here so that you know we get that we need to work over here so we can write your video list so in our controller we will create let's say our profile controller dot dot and then we're going to import the jet package so we can have get dot dot and then we're going to have class profile controller this will extend the get a get controller so we can have genetics controller and we're going to have final rx map of string comma dynamic this will be user and we're going to have this only so this is the user data that we're going to create and we're going to use an alternative approach because we've used the snapshot method multiple times so let's try something new and i'll show you alternative approach that we're going to use so we're going to create a getter again all of that is going to remain the same we can have get user and we're going to pass in the user dot value over here cool now let's create a uid so a global variable underscore uid which is equal to this and it will be an observable you can create an observable or an rx class like this as well dot obs now similar to comment we are going to have an update user id method so that we get the user id of the profile we are in and then we can do uid dot value equal to uid so this is the private class that we are going to use and we are going to set this value to the parameter uid that we get and then we're going to run the get user data function that is now going to create so let's take this get user data and create that so it's going to be use async and now we're going to get multiple user data so first of all what we need is the thumbnail of the user so like whatever thumbnails are there so what we can do is list of string of thumbnail we'll call that thumbnail and for now it is going to be an empty list now we can do query snapshot my videos is equal to await firestore dot collection firestore.collections.org where our uid is equal to so we can do is equal to and what is it equal to this uid value that we have so is equal to uid dot value so we are finding that list of videos where the user id is similar to the uid that we get from the profile screen and then we are going to get it and then we are going to run for int i is equal to 0 i is less than my videos dot docs dot length i plus plus and then we are going to add to the thumbnails list so thumbnails dot add and we are going to add my videos dot docs at i dot data as dynamic and the data can be null so we will put an exclamation mark over here and we're going to call the thumbnail property over here because that's what we have saved for our video right so if we go to our console and in the videos tab you can see that we have saved the thumbnail with the property thumbnail now we have added to the list so thumbnail part is done the next part we want is the username the follower count and all of that stuff so what we can do is document snapshot user document which will be equal to await firestore dot collection users dot dot uid dot value dot get after that we are going to store the name and before that we are going to you call the data value so final data is equal to user doc dot data and we are going to use this as dynamic right now we can even name this user data because we are going to have more data i guess so we can leave it like this and now the name is going to be string name equal to user data name string profile photo is going to be user data profile photo now we will get the like and followers and all of those stuff so what we can do is and likes equal to 0 and follow us is equal to 0 and following is equal to zero now to get the number of likes what we're going to do is go through every video that the user has created and then add that to the likes likes property over here so what we can do is for where item we can have item and before that we need to actually use the we need to call the my videos so what we can do is for our item in and we can call this my videos dot docs and we're going to add that so likes plus equals and what we can do is item dot data likes and we're going to consider this as a list so that we can call the length method on it cool and we can even have this exclamation mark right here and to avoid this error what we can do is in the my videos we can change the query snapshot to where my videos and now there is no need of you know putting this and even over your putting this is not needed so now after this is done what we can do is where follower doc and we're going to create the follower document so we will go to the user so we will have firestore dot collection users dot dot and we're going to have uid dot value and we're going to go in the collection of followers which we haven't configured yet but we will do it soon so i told you that we're going to use sub collections and this is how we are going to use that and similarly for following doc we can do this so we can do following and we can copy this much and put that over here following now the followers end that we created that will be followers equal to follower doc dot docs dot length so whatever how many followers are there that will be the length and for following we will have following doc dot docs dot link after this we are going to have firestore dot collection users dot dot uid dot value dot collection followers dot dot auth controller dot user dot uid dot get and over here what we are checking is basically uh if the followers contains the following list so basically we are checking if the user is already following the user or not so we can do dot then and with that we can check if the value exists or not so if the value exists over there that means the following is true so what we can do is is following to true and we'll have to create that variable so let's create that so over here we can have boolean is following equal to false and over here we can set it to true so if the value exists that means we are already following else following is false and we don't need to avoid this because we are using then so basically what we're doing is going to the user's follower sub collection and then uh we are basically checking in that okay uh if the document has this uid so if the doc con consists of this auth controller.user.uid that means that we are already following them so we are setting the is following to true else we are setting the is following to false cool now let's set the user value to this so user.value is equal to and we'll pass in the followers so the followers will be followers dot tostring then following will be following dot 2 string then is following will be is following so let me have that following is following then we can have likes which will be likes dot to string then we can have profile photo we'll pass in the profile photo then we'll pass in the name that will be the name and finally the list of the thumbnails so that will be thumbnails so these are all the fields that we uh got from our net and we are sending we are setting the value to this and now we will call the update method because we are going to use something different over here all right we are not going to use obx we are going to use something known as a get x builder we will see that so in the profile screen you can scroll to the top and wrap this safe area and scaffold and everything because the app bar also needs the get builder and we can wrap that with the stream builder so that will be get builder and let's import that now the get builder will be of the type profile controller so let's have that as well and the init will be profile controller all right now the builder will over here will get a controller which we will not use generally you can use that but we are not going to use this controller over here we are going to create our own profile controller so at the top we can have final profile controller and we can mark that as profile controller and then get dot put and we can put that profile controller now we have to convert this into a stateless stateful widget and after that what we can do is in the init state we can have profile controller dot update user id and we need to pass in the uid so that will be widget dot uid let's save this much and we should be getting error for some while because our user is going to be empty so we can't call values based on that but for now let's put that now the username is going to be controller dot user name then we can just grab this and use this everywhere so we can scroll down and in the image url we can pass in control dot user profile photo then we can pass in the followers list i think this is following so let's pass in following we will have to put this as a constant text we can remove this constant from here this will be followers list so we can have followers let's put this as a constant text and remove this constant from here as well we can put this lights so we can have lights again put this as a constant and remove the constant from here cool so now let's go to our profile screen and we're getting this error for a while and that was kind of expected and you can see our image showing up which is nice and our lights is one like because we over here we gave a like so if we remove this like and go back over here we see that a like has changed to zero that means this is working even the followers and following this seems to be working because it's showing zero when we add the followers and following functionality we should see something else so now let's work on this logic over here so if it's us then it should show sign out else it should show something else so so what you can do is go to the centered inquire widget and before that let's work on this logic so what logic am i talking about is whenever we go over here you see this red screen so to fix that issue what you can do is in the controller over here we can check if the controller let me put f so if controller dot user dot is empty that means that the map is empty then we need to return a constant center child circular progress indicator that means it is loading right now we can save this and now if we restart our app and see we shouldn't be getting this issue anymore so if we go to our profile and this seems to be working perfect so now we can go down at the bottom and in the text instead of showing sign out what we can first check is over here if the widget dot uid is equal equal to auth controller dot user dot id uid that means that the that this profile is us then we will get the sign out option right else we will check if the controller dot user is following is true then we can have follow else we will have the unfollow button now we can save this so basically first we will check if the sign if the user is us then we'll put the sign out option if it's not us then we will check if it's following so that you we are following that user we will get the follow option or else we will get the unfollow option for now we will get the sign out option so let's create another user but to create another user we have to log out and to log out we need the on tab functionality so over here we can have if and we can just copy this condition from here so if widget dot uid is equal to this what we what we can do is auth controller dot sign out and this function we have to create in our auth controller so let's go to our auth controller and down here we can have a sign out option so we can have sign out which will be asynchronous and will not return anything and we can have await firebase auth dot instance so instead of doing this we can just make use of firebase auth variable that we have and then we can call sign out only this much and we won't check with the try catch block because we are expecting that it will work without an issue and we are not going to go to the other screen because if we sign out then the our state management will take care of it and process the user data accordingly so if i now click out and sign out you can see that we signed out and if i refresh my app you can see we are still on the sign login screen so now let's register our user and you can see when we click on the register we're not going to the other screen that is because we made a simple bug over here in our sign of screen when we click on the register we haven't navigated the user right so to do that what we can do is navigator dot of context dot push then we can pass in material page route and builder will have a context value and this context will and we have to go to the login screen over here we actually had to do it for the sign up screen but we haven't put that here as well we can copy this on tab and now go to the login screen and do it similarly so that we can go to the registrar's screen right and now we can type over your sign up screen cool now let's refresh and see what's happening if we go over here we can go to the register screen now that's good now let's select an image image has been successfully selected let me take this norman and we can call this with the test123 for at the gmail.com and we will add the password test123 now click on register and we can see this over here which is awesome we can go to the comments and we can see three hours ago this was when i recorded the video now if i go to the profile i see naman over here 0 likes and even if i like over here you can see that this is not incrementing so now let's work on let's see if we can search the user and when we search we get rivan ranavat this has one like and we are already following this that means that our logic is somewhere wrong over here so what we can do is go to our profile screen and we are checking if it's already following then we need to give in the unfollow button or the follow button this is where we made a mistake and now we get the follow button so now the next thing we want to do is whenever we click over here we should follow the user so over here else we can do controller dot follow user and this is a function that we are going to create in our profile controller class so here we will have follow user and this is going to be asynchronous so here we can have var dock which will be equal to await firestore dot collection users document uid dot value dot collection followers dot dot auth controller dot user dot uid dot get so we are basically getting the users followers and now we will check if the dog doesn't exist then what do we need to do well if the dog doesn't exist then we need to make sure that the user's followers is added so i can copy this and paste it over here and in the dock we can set it so that means that we have added the user to our collection wire so we have gone to the users the u the particular user that we have then we can go to the followers collection and add the user who followed that document over there and we don't need to pass in any value so i'm just going to pass in a set like this which is empty and after this followers is done we also need to make sure that we add to the following of this user over here that is the uid dot value the profile which we have tapped on so here we're going to replace the auth controller dot ui user id over here and we're going to set the uid to uid dot value and over here in the following we are going to add so basically what we did over here is added uh the you so whenever we are on this screen suppose this is the rivagnath user and i'm the naman user so whenever i click over here i click on the follow button this followers has to increase over here and for me the following has to increase so i basically set both of these values in the firestore collection and now we need to update the user value so what we can do is user dot value dot update this is how you update a map and we have to update the followers value and we need to do int dot parse which is the value so we had converted it to a string so we are basically converting it to an integer value we are adding one to it and then we are again converting it into a string cool now we are going to add an else value else condition and over here we are going to copy this paste it down and we are going to be now delete the document that we have so we can have delete and we will remove this map we are going to delete from here as well and remove this map and over here we are going to not add one but we are going to subtract one because we'll be removed one followed right now we also need to update the user's following so what we can do is user dot value dot update and we're going to follow up update the is following value so we're basically going to set the value to not so if the is following is set to false you're going to set it to true so and if it's not default and if it's false then we're going to set it to true and now we need to see the update so we can call the update method over here now let's refresh this and see how our app is looking first of all to check we can go to a profile and we don't see anything that's cool now if i type rivenware now if i go over here and type private and well follow this user we can see the update has been made one follower and if we unfollow we can see it's zero again now let me follow this and go back to our profile screen and you can see one following zero followers zero likes which is awesome now the last thing we want to do is show the list of images that we have for evandana we have some images but we can't see them so let's show the thumbnail so what we can do is go to the profile screen and when we scroll down we have our comment of video list now let's create a grid view builder so we're going to have a grid view builder to create the grid now the grid delegate is going to be a constant sliver grid delicate and let me get the auto option so with vic fixed cross access count and the cross access count is going to be two child aspect ratio will be 1 and cross access spacing will be 5. so basically cross axis spacing means that we need to leave some space over here some space over here cross access count means that there are two images that should show up in one line one row basically cool now we have our item builder and let me say this much now the item builder will have a context and an index so we are going to have a thumbnail over here so let's say thumbnail and it is going to be controller dot user thumbnails and we are going to grab the thumbnails by their index because they are a list now return a cached network image like we did and the image url is going to be a thumbnail and finally the fit will be box fit dot cover now let's save this much and let's see why we're getting this error now that's because we haven't set the item count and we will set the item count over here let's say controller dot user thumbnails dot length so whatever is the length of the list that we have and we also need to set a physics of non-scroll label that means that they're never scrollable so we can have constant never scrollable physics let's see if this much let's read on our app and see what we are getting and now you can see that our layout is totally messed up over here and this can be fixed with a very simple solution over here we can just write shrink trap and set it to true and now if we refresh our application and go to our profile screen you can see that it's coming into place and it's looking pretty good so now let's go to the ribbon user and click on enter let's go to rivan and we can see the thumbnail showing which is awesome right so now now the only thing is if you run it on a other device and there are more thumbnails then this will throw a render flex issue and that can be solved by just putting single child scroll view over here so if we wrap this with a single child scroll view then this should fix all of our problems and this is not showing any problem now but it might show that's why i'm telling it to you so now just to confirm that it works now if i click on sign out it works and all of our stuff is working pretty well so this is it for this tutorial thank you guys for watching see you in the next video
Info
Channel: Rivaan Ranawat
Views: 116,941
Rating: undefined out of 5
Keywords: flutter, dart, tiktok, getx, firebase
Id: 4E4V9F3cbp4
Channel Id: undefined
Length: 228min 48sec (13728 seconds)
Published: Fri Jan 14 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.