Build a ChatGPT Clone with React Native (Expo, SQLite, RevenueCat, Clerk, OpenAI)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up Galactic friends and welcome back to the next big clone here on this channel today we are building a Chad GPT clone application and you have been waiting for this so after the Airbnb clone the WhatsApp clone the fintech Clone we are doing a clone of the cad gbt application and this is going to be really really exciting there are so many small and big things included in this build that it's once again a completely new thing even if you've taken one of the previous clones this one will share new things so we're going to use some cool animations we're going to have actually a draw menu which we will really really customize to our needs there a lot of small things we're going to include we're going to use zego library for context menus drop- down menus we're going to have an image viewer component we are of course incorporating the open AI API using streaming and so much more and on top of all of that we have two sponsors in this video so the first one is clerk just like before we are using clerk for authentication of our users you can check it out at clerk.com you can get started completely for free clerk is an amazing solution for managing authentication and especially users in your application and today we're using email authentication but previously in the Clones we've also used social authentication or even phone authentication so check it out clerk.com thanks for sponsoring this video and on top of that we have a second sponsor today which is revenue cat so you might already noticed that if we're using Revenue kit we're going to integrate in a purchases and that's what we're going to do at the end of our clone so definitely make sure you stick around until then and get started with Revenue kit completely for free up until I think 2 and a half th000 monthly transactions which is quite a lot of money to make I never made made that much from an application but if you can make this after that it's like 1% of your transactions but again get started completely for free with Revenue C at Revenue c.com and thank you Revenue C for sponsoring and making this clone happen because this is once again quite a huge application I've provided all the code linked below to GitHub so make sure you open that repository check it out we might bring in some color some util or some functionalities from time to time and if you want to follow along this clone I highly recommend you get the code from GitHub and of course also subscribe to this channel for more clones and react native videos coming in the future before we know dive into the code let me quickly walk you through all the different chapters of this video and what you can expect from our build in the first part of the Clone we will as always quickly talk about how we set up our application with Expo and how we enable a pre-build so we will be able to create our own development client and later use every custom native module in our application in the second part we're going to talk about creating this animated intro screen which features this epic animation and I'm pretty sure you're going to love that component in the third part we will get closer to our login and registration we're going to create this bottom sheet which is just our own component and then we're going to talk about how we can create a model and navigate to that page part four will be all about authentication we're going to integrate clerk into our application for registration and login and we will also see how we can protect pages with Expo router and Clark authentication in part five we're going to talk about creating a draw component and especially customizing it exactly to our needs which means custom icons sizes colors how far we can open it custom icons and everything with a custom draw content in part six we're going to use the zgo library the first time to create this cool drop- down component which allows us to select between different versions which also works on other screens of our applications later in part seven we're talking about the input component down here which will feature a nice little animation that opens and closes automatically once we start typing or go back in part eight we will then talk about how to create the general chat UI how we can have these scrollable cards and how text messages on our screen could look like within a chat in part nine we will Implement data storing with react native mm KV so users are able to provide their own API keys under the settings which will be then stored with the key value of mm KV in part 10 we will then finally build our own streaming using a library and this will be so epic we're going to connect to open Ai and will be able to achieve something like this where the result from the API is directly streamed in our application and used within our view to render this epic view which we've built up up until this point in part 11 we're going to tackle the next menu item which is do so we will be able to generate images based on The Prompt in the screen and change our chat messages so it will be able to see something is working and display an image in our view in part 12 we're going to use a context menu which on iOS allows us to press long on this and then include different elements down here and we're going to also work on the functionality to actually copy this photo save this to our media library or share it from our app in part 13 we dive into another functionality which is the image viewer component in which we will be able to zoom into images use a blur view uh have a drop- down down up here again and also finally use another bottom sheet from gorom in chapter 14 we're going to dive into the explore page for which we will first of all build this cool header component with scroll and blur effect that we will then use in The Following part in part 15 we will then implement this list down here and also a logic to switch between the different pages and include a nice enter and exit animation for our elements in part 16 we going to include sqlite so we will be able to actually load previous chats get all the chat messages and debug our SQL light files locally in chapter 17 we're going to add the logic to then actually load these so previously we only prepare them then we have the ability to load previous chats and dive again into them and finally in the last chapter we going to include Revenue C in our application we're going to go through the whole process of setting up Revenue C creating a product uh creating projects and then buying something within our application to unlock the dly features which we've then put behind a pay wall all right I think that's a lot for one clone but we can do it you can do it and I'm excited to dive into it all righty then let's kick off our clone so we can get started with npx create Expo app using the Expo CLI the name of our I will also add add latest because I want to use the SDK 51 and I will use the template so minus t default then should be the TS template and I will also use the beta version of that in your case most likely when this video goes live the SDK 51 or whatever it is in the future is already released so you can emit both at latest and at beta so just go ahead with npx create Expo app chat GPT DT default in fact- t default doesn't make sense sense I think uh probably in the future the default is the default I don't have to SP I don't know maybe it's not using a template if you don't say minus uh t t so minus t is for- template of course okay so this is setting up our Expo application and we're going to install a few dependencies right in the beginning because there're just some packages that you just always use and these are reanimated and the gesture Handlock and we will also use the dev client so after the last video uh some of you commented that I should use code minus r dot to open in the current instance yeah almost oh yeah okay I think it was actually correct but I should open in that folder okay so now my folder is called C gbt at latest that certainly wasn't my idea with at latest here let's check out our dependencies okay we got Expo 51 um so we should be fine uh our application also looks good we have routing in place and as I said we're going to install some dependencies right here and now so these are the dependencies I wanted to use the Expo def client reanimated package for animations and the gesture Handler to handle some gestures later now why are we using the Expo def client well we are doing a custom build of our app now usually you can do Expo go and that is cool for testing and uh quick quickly spinning up something but I don't really recommend it in this case so um we want to do a pre-build now let's just run this right here um or maybe let's quickly include reanimated in our um okay this looks interesting um let's see do I have to like spin up npx expo at least one time uh because this is not giving me we do have our app Json but what I wanted is the Babel config why is there no more Babel config that is interesting um I think there was a command to generate that Babel config uh so let's quickly kill this do I have something regarding Babel in my nope of course not so let's just do this manually touch B.C config.js or you can just create a file whatever suits you we're going to input the following so this is the input for our Babel config and this makes sure that the reanimated plug-in is included correctly in our application I don't know why we didn't have a bable config but let's go ahead with our pre-build npx Expo pre-build this will build our native IOS and Android folders what would you like your Android package name to be um usually this gives me like the default something like com. Simon do uh C GPT GPT I don't know yeah let's just use this for IOS as well and then this will create native Android okay let's see where is it come on uh Android and iOS folder here this is important because later along this build we're going to use a many Native modules and those will require us to have our own pre-build of this application as I said Expo go is cool for quickly testing something but uh ultim if you're developing an app you usually go for pre-build and then continuous native generation of your project using Expo and that just makes things a lot easier so this is what we're doing we do have our folders now and if we want to build our app we can now simply run why do I get all this stuff today uh npx Expo run iOS ah I have no completion here so far that's interesting um I think I need like what is it called code whisper or something did I uninstall this H I will have to check soon anyway uh npx Expo run iOS will bring up my simulator here we go here's the simulator and it's deploying the application uh within it we can put this to this side do I want to keep it on the right hand side or the left where did we have it in the past I honestly don't know where we had it before um does anyone still remember let's check out I will check out my last okay it was on on that side as well so here we go we're going to put it here this is now our own build and now we can also uh make sense of the one dependency we installed a minute ago which was called the Expo def client uh where's my dependency we have reanimated we have the gesture Handler and we have where's the def client okay here it is Expo def client so the Expo def client helps us to get the same experience of basically using the Expo Go app but within our custom build um this is not unbelievable important but it still helps you're going to see if we're open the debugging Tools in a second here uh it just looks exactly like the um the standard Expo Go app and you can't really see a difference anymore by the way this might take some time in the beginning uh if you do it the first time for iOS what I'm currently doing is only possible if if you're on a Mac so if you're on Windows you can't use npx run iOS because there's no iOS simulator um and if you want to build the same for Android that of course works as well you can spin up a virtual device uh make sure you have something configured or you can also directly um deploy this to a connected device doesn't really matter too much in my case we're going to go with the simulator and while this loads we can maybe quickly take a look which is reset project what is this I'm not entirely sure uh I also didn't really have this before this res set the project to a blank state it moves the app directory to example uh it moves the app directory to app example and creates a new with an index and layout file you can move uh safely delete this file after running this is interesting I I honestly don't know why it exists but I like it I want to do this I want to just test this out I don't know if you got this in your project um uh how did we call this npm run reset project okay so this moves all the boiler plate stuff that was initially in here um I don't know where it moves it moves this to to something else maybe it just removes the stuff uh it renames the stuff it moves the stuff with wres file I don't know but now we got like a clean index file and a clean layout file this is cool I always wanted to have this nice thank you so much um okay that is good news really on every build that we do I learn something else um so here we go um our app is still loading so we can quickly take a look if you don't have this reset project script uh and by the way we can now get rid of that script folder because we really just need to run this once uh we can check out the rest of our application so in terms of the color we're going to go with some colors for our cat GPT clone you can grab all of this from the GitHub repository linked below this video and we're going to also put in another file into the constants folder which I will call styles. TS so here we're going to put in some styles that we reuse across our application we're importing the colors from our constants folder and the stylesheet and then we just generate a button a loading overlay and everything in my IDE looks completely different today I don't know what's going on um but anyway these are things that you might reuse across multiple Pages views in your application so it makes sense to put them here um this is now done so this interesting because it's still loading let's see if I can like open on iOS again um I feel like my iOS simulator here does have some some issue so I will kill it and I will press I again to open iOS probably I've have no messed things up no it's coming up again so maybe we're going to Lucky be lucky yeah um you see this kind of looks the same like if you run npx uh Expo run it gives you this QR code um but notice this we're now using a development build so this is the difference that means I should now be able to see this so open in chat GPT latest I want to open my app and this will hopefully open now our client we see it's loading our resources and at this point we should have the same experience like if we were in the Expo Go app so you see we actually also get this which is exactly why we install the Expo def client this is the debugging view uh that you used to from the Expo go Application you only get this if you install the Expo def client which we did and we see our first screen and we can of course change something and we see we got life reload as well so at this point we're not using Expo go we're using our custom def CLI if we now install new native modules we have to spin this up again with npx Expo run iOS um I could at the same time deploy this here and we're still using the local development server so this is the first step and I wanted to do this right in the beginning because this sets us up on the right trajectory so we don't have to like interfere with Expo go and then later at some point opt out and um switch to the def client so we're now uh immediately right where we want to be we can remove everything from the components we can also remove the app example stuff if we want to and then we're ready to get started with the actual code of the cat GPT CP okay now we want to do this cool animated intro screen from the cat GPT application and you see this uh right here on the GitHub repository basically this animation that's going on here is what we want to create now we won't do this in full detail because that would probably take us about one and a half hour um instead I got the support from Gary talkman uh Gary was a guest on the rocket ship podcast I highly recommend that episode was really really epic Gary is working at Kendall um Kendall is doing some uh sort of finance fintech application it's really interesting and they did really really cool stuff and he shared that animation with me and I um remodeled it to our needs let's say it like that okay let's get started by creating all of this in a component so if you're not interested in this you can basically completely skip this part because it's really not essential uh but if you're interested uh I will just go over the different steps included and try to explain them as good as possible so let's create an animated intro component here in my components folder and I will do react native functional export animated intro um then we can go ahead to my app folder and actually uh I don't really want the uh I don't really want the react native IDE stuff in here enable preview [Music] editors uh how can I remove the height run or debug height G view hide uh okay the rest is fine uh let's go back here to the index this will will keep Flex one I don't want to Center the stuff and then I want to just include my animated animated intro component okay so here we go uh additionally I would like to remove the header so let's go to the layout where we have the STC layout navigation we're using expor router in this video if I haven't said this before uh we're going to get more into what this means uh in the next uh lessons here so header shown fals and we don't need a TI so this get rid of the header now we have the whole page available for our animated inro key and we actually need some dependencies so what we need is let's see where do I got this we want to install uh react native redash so what is react native redash I think I opened it up before it's a package from William cillan um to basically animate some text and to change the text element this just doesn't work really well with the builtin text component so we are using redash for that uh beyond that do we need anything else I don't think uh we have reanimated already so that's cool uh do we need to make a new build I'm not entirely sure that could be the case let's see if we import retext from redash still fine still fine so let's try if I put in something here but let's start by giving this here uh some Style in react native stylesheet we're going to call this rapper and the microphone is in a perfect position right above my keyboard today uh great okay so stylesheet goes up here and then we're going to say this one has styles. rapper all right with flex one now if I use retext in here oops uh retext yeah let's use it like this uh string is not time to share date that is correct uh because we now need an actual shared text that we can use um so let's do this we can do this uh but first of all as I said we don't want to do all the things in here one by one so I will bring in the different blocks and you can get an understanding for what's going on so first of all I do have this array here uh of content and color so these are the text like let's create let's brainstorm and then we have a front uh and the background color attached to them then for our text we should actually be able to use this at a specific position um so let's see const text equals use derived value so we are now getting into reanimated uh I want to get the index from a value called current index so let's start with a current index of zero we use a shared value for that and then we can get this let's first of all close this so our whole page isn't red uh index equals yeah almost uh content at current index. value and once I got this I can return content uh no actually this is the whole thing I just want the current index value and oh it's still early morning got some typing issues I want to return content index. title good um we also need the dependencies array which is holy moly what is this um this is interesting uh of course the current index so at this point we should be able to use the text for this retext text field and we see it up here there's already a tiny let's create so I think this requires some styling as well so let's put in a style and for this we're going to use the title actually let me bring in the rest of the styling as I said uh we don't want to do too much in here so we do have now a title style down here uh which is an absolute position and we can attach this here styles. tile so just showing you the beginnings of how that stuff came together uh we have now the title up here and we can animate that and at the same time we will also animate some views around that title so basically the title changes and the background changes and the color changes and then there's also a ball that should be above this so if we look again at our uh animation on the Clone page me zoom in a bit uh we see this ball okay thank you this ball here is basically moving above the text so all of things come together and as I said we could do a whole tutorial on this probably let me know in the comments if you're interested in like seeing how we can build this step by step but I think for this clone we should really stick to some Basics and not do everything so now as I've shown you retext now let's put in the rest first of all let's bring in a bunch of values up here again if I highly recommend you check out the GitHub repository there's the code for this animated intro and as well you can also skip over this if you're not interested so we do have some shared values like a start label with can go next did play and we already have my derived value um however we now need a lot of styling um next to the text we're going to have a new color index which is also a derived value and then comes a bunch of use animated style so maybe let's do a comment here styles um and end Styles okay I can't even type correctly and we're going to put it in here so let's see what's going on we have a text style and these are using of course use animated style and interpolation for colors uh let's add all the Imports so the text style of course is the text and it's doing some transition as I said coming up with all of this right now would require a lot of time then we have the Bal style which is the bald style and all of these are usually using like the new color index which is the the current index from the array of the contents at the top then we have a little mask which is going over the content and we do have style one actually I'm not entirely sure where style one uh comes into play H this goes to our repper okay uh finally we're going to do the rest later for now let's put in all the views that we need for this so instead of just having this one view we're going to have a bunch of animated views which is required if you want to animate this stuff we have one animated view surrounding everything with this style one which is basically the background then we have our content view so inside of the content view we have the ball as I said which is moving across the text and we have a little mask on that and the retext which is now using the text and as we already seen the text is a derive value which changes over time and on layout we will also change the label width of this if I now hit save we have an interesting view so we can see the ball we could see the background um somewhere here is probably the text it's hidden behind the mask now nothing moves so far and this is where we add uh reactions okay and end reactions okay so the first animated reaction is this one this one we'll use the label with can we just uh okay I will just add all add all the missing stuff okay uh this probably is already doing something so this is as we've seen revealing this once however we also need to go to the next index so this is where we have our next reaction uh that looks like this if we have le of can go to next we will go to next with a little delay and then at some point change our current index value when the current index changes uh this one will be triggered again most likely um so let's hit save again and then we should already see that is exactly what we wanted to see so now at the same time with nice timings the background changes the the ball color changes the text color changes and the ball moves across the text and uses the mask to hide the rest of the text now as I said this is not a whole uh tutorial about how we create this animated intro component and I'm pretty sure there are things that could be improved about this however I'm really grateful for Gary for providing this he shared this on Twitter um Kendall actually has some heptic as well they have some interesting packages we might get back into this I don't know um and I think actually in his example he used Kendall heptic because with kendle heptic you can have a heptic pattern so I excluded this because I can't really share this heptic stuff with you he used this in his example so if you're interested in this you can get like a typing uh animation or heptic pattern to play on iOS um check this out at kendle Finance heptic if you are interested but so so far we're going to leave it like this I think this is a pretty cool result of our animated intro screen and we can do the real uh loog in and registration now all right now we want to move closer to the lockin but first we actually need to prepare some components for that uh so we should probably create a new bottom uh let's call this bottom loin sheet. TX okay bottom lockin sheet and then we can put this right here below our intro now why are we using our own bottom sheet and not the gor home bottom sheet this time well um that's a good question uh I usually recommend the gon bottom sheet but in this case what we really want to do is uh can we zoom in here no that was the wrong oh where's the zoom uh where's the bottom sheet from the lock in this is one and this is kind of static in that application it's just that we have this animation playing up here and this part here is kind of AES static so we only need this bottom sheet with rounded Corners um and we can do this without any external package and usually that's a good thing if we don't need an external package also if you are uh or if you don't like this playing animation the whole time uh you should be able to Simply comment out one of our animated reactions uh and then it stops or you can also just get rid of the whole animated intro screen if you don't want to see it so now let's see how we can place our bottom lockin sheet in the right place and also make it look good therefore we're going to start here in the bottom loin sheet and what we want to do is uh we want to first of all wrap this in some container styling which will allow us to position this in an absolute fashion uh we're going to add Here style I will make this an array actually um styles. container first of all so container will have as I said position absolute it will be completely at the bottom um then we're going to have a width of 100% And I want to set the background color of this to Black okay so let's see it comes up at the bottom already uh but of course this does not have the right he it will have it pretty soon um maybe we're going to do this next so let's add a touchable opacity because it just has like a few buttons touchable opacity um NOP not from react native gesture handle I just want this from react native that should be fine and the style here is actually using our default Styles so we can do again Styles or in this case default Styles default styles. button um and then we're going to also have some styling because this is a light button so let's call this button light and place this down here I already hear everyone screaming Simon not that fast please slow down I will I will try my best okay so we're going to use the not logo Google here we're going to use logo Apple first of all with a size of 14 um and this one will also have its own styling so style equals Styles Dot button icon so let's place this down here and then we have our view okay you see it's coming up but there's not really anything included let's also add a text here um for The Styling we should be able to use styles do let's call this button light text okay we need some styling and we're going to work on that in a second um and we're just going to put in continue continue with Apple so once we have this for like one button we can uh mostly copy this stuff over so let's see the button light should have of course a white background color uh we don't really need anything beyond that uh we already see it's filling up the whole view that's not bad then for the button light text uh we're going to use a font size of 20 maybe okay that looks good and for the button icon do we really need this can we not use like uh the button icon yeah let's just use pedding right of like I don't know six okay um this is okay but we see a problem now this is way too close to the bottom and if we're not respecting the inser areas we have a problem so in order to do this we can either surround our view with a save area view or we can manually do this by extracting bottom or destructuring the use Save area insets hook here okay this gives us access to the right distance at the bottom and we're going to attach this here to our surrounding View and simply say okay for petting bottom use my bottom value and we see it moves out everything from this area and keeps it safe and then our stuff happens above that okay uh but I think our container could need some uh more petting so we'll give this one a petting of like 26 as well okay yeah that looks somewhat better uh I also want to have gap between the elements we won't see that yet and I want to have uh border radius so we can simply say border top left radius and Border top right radius and now we have these little edges so this looks exactly like a bottom sheet it's just not really a bottom sheet okay but I think for our case this should be fine um next to our light button we will also have dark buttons um so my button dark should have a dark gray background color using my constants uh and the button dark text should look like this and finally we want to have a button outline which has just a border width and a border color so this should set us up for the remaining buttons we can now copy this one over we could just have it like this but of course I don't want to I want to use this one to use button dark uh logo will be Google I think this is a bit smaller so we might have to use 16 here and button icon should be fine but we're going to have to yeah I assume we should set the color of this icon to be uh White okay then continue with Google and this should be button dark text okay so our second button is in place as well now we have two more buttons so we actually in this tutorial won't use Google or Apple login with claric we're going to use the regular email sign up check out the other clones for something like OTP um authentication with SMS stuff really cool in I think the fintech Clone or the Airbnb clone check out the other clones with clerk now what we want is something that now triggers the actual lockin page therefore I will create a login. TSX here uh we'll call this just page this should also be available within my layout so I will add another St screen oops stack. screen in here the name of this one is yes Lo in and we could close it but what I want for my login is to have a certain presentation so I will add the options block here and then I will add presentation model for now so now we can go back and we can use the Expo link component so the Expo router link component allows us to set an AG ref here and we should actually get code completion usually uh why are we not getting code completion on my routes that is a pretty good question um a question I I currently can't answer at this moment uh let's see let's see uh for the moment we're just going to put in whatever just something that co-pilot gives us uh sign up with email this does not trigger my lockin maybe I did not hit save on the lock in Let's see we have my St screen name loog in do we have uh type routes enabled I think uh this should be plugins experiments type routes should be enabled so what is the problem here today with our type routes maybe it it's working by now uh nope completely not working at all this is uh interesting because this should definitely work I will have to fix that in a minute for now let's just keep it like it is um but those buttons should also be pretty easy so the first one will just be sign up with email okay the problem if your styling does not apply within the Expo router link component is usually that you need to use S child so that will allow you to use the right styling um uh however this doesn't look right yet so we should also give this one some styling uh how about default Styles button and styles. button dark yeah that's the one we wanted and we're going to copy this over and the second one will just say block in uh we probably don't even need an ion in this case Okay so this is our bottom sheet I think this looks pretty cool uh as I said we can't really drag this but we also don't need this in this case um but what we need is the actual routing so this is not routing to slash login or something is going on usually that happens uh unexpected token view usually that stuff happens okay here's my lock in yeah now it seems to work I don't know why my um my typings here are incorrect like this is completely not correct um but we're going to fix this so there are two scenarios we can go to our login page either using sign up or login I want to pass that information to that page so we can display like a little bit of different text there therefore what we're going to do is we will not just set an HEV U we're basically attaching query parms but I kind of like to do this in a bit different fashion so if you want to make this more explicit you can do it like this you can set the path name um the path name in this case is still /login um and then we have params and then we can just include whatever we want so I will include type register here okay type register and then I'm going to copy that block over to my second one down here um and this one will have the type login now let's see how we can extract this if we go into our login page we should be able at the top to extract this using cons type so we're going to get the type from use local search perams that's the hook to access our perams and we can also strongly type this so we can say the what we expect here is type string okay and now if I add a little lock here I should be able to go to that page probably I should hit save and we see type register if if I go on Lo in we see type lockin and that should be enough for our case to see um if we want to use like the login or the registration on that page cool um do we want to continue a bit um we do have the stuff down here um I think why not why not why not continue a bit um so for my lock in we have only set the presentation model I will set the title now to nothing because that kind of looks ugly um but I want to set the header left value so for header left we want to supply our own component that should just be a touchable opacity again from react native and on press we're going to do something on press um well let's do a void function for the moment and just place ionicon inside name should be close outline size of 28 and that's it so if we now open this we see my button up here but of course it's not yet closing the stuff so what we need in this case is access to the router we could also have used the link component but I kind of want to mix things up so let's add use router from Expo router and then onpress we will simply call router. back uh we could also check Cano go back but I think router back should be fine so test come on something something is messed up here I don't know exactly what it is I will figure it out uh but we will get there uh so I should Ed it like this no yes perfect okay we are able to trigger the login and registration and we're getting the information correctly which kind of page we are on before we get into uh our clerk authentication maybe let's provide the according view here already so we're going to start with react native stylesheet again to create our login and registration experience uh as always we're going to have some sort of container here that's using Flex one and perhaps some sort of petting like 20 we can then use this and I want to surround this page with a keyboard avoiding view to make sure um that we can input stuff correctly in our text Fields uh do we add I think I use the keyboard I mean there's discussion from like what's the best keyboard avoiding view there different approaches I usually went okay with this if you have problems try to investigate this more uh there are different solutions out there just so you know this uh but usually what you see in examples is a platform check check checking if this is IOS then we want to use the behavior padding uh on Android we want to use hate okay this is the usual behavior on top of that I will also set the keyboard vertical offset or maybe we're going to do this in a second let's just set it to one for testing and then we're going to add our Styles here so styles. container good now let's put in some stuff we probably have some sort of loading State as well so we can say con loading loading set loading use State fults that's a good start um let me check if we are loading we will display a little loading overlay so in case of loading we can use the Expression end end as a shortcut and then render something so I want to render a little view which is using our default styles again so we have configured something in the default Styles I think default Styles dot uh loading overlay exactly and close that and then close it here and let's try to set this to true so this turns the page dark um that loading overlay why is it not above the header stylesheet absolute fill sometimes you want with a couple tweaks Comm okay mostly fine we should probably we might have to set like the header transparent well it's a minor thing we can keep it we just want to have like some overlay over our app uh while it's loading so I think we're we're fine we could probably do this in a better way but should be okay so now I want to add a activity indicator I want to make this white and then we have our loading okay we'll set this to fault because otherwise we can't use our app then uh I would like to use a a little logo maybe here so let's call this one logo and then an image component I think I haven't added the image actually so we're going to come back to that in a second so image from react native and then I want to use the logo dark I haven't added any kind of esset yet you should probably do this as well check out the GitHub repository these assets don't belong to me um did I use anything else I think I just use logo dark uh and Logo white and maybe DOL um yeah something like this and for fonts we can use space mono should be fine so now we have the logo but of course that sizing is totally off so let's change this to be uh width of 60 uh hate 60 as well please and then want to make sure that this aligns itself in the center and has some margin vertical of let's say 80 okay here we go we got the nice CET GPT logo now after that let's Place some text element in here uh style styles. probably title and then this is the interesting part so if our type is Lo in we're going to say uh welcome back and otherwise we can say create your account we're not really using this stuff in any other place so um wasn't too important to get the type in here but you see create your account if I come from sign up and if I go from login we got welcome back it's just a nice thing to have the right titles and texts in your views and it's such an easy win in this cas case now let's place the remaining inputs into a little view here I will just directly give this uh some margin bottom in here uh and let's close this View and then we have our text input components text input from no that was the wrong input from react native okay um autoc capitalize nope none then we can add a placeholder let's say yeah email whatever I'll also close this to get rid of the error messages uh okay we see this is like the input field not great not great so let's add an input field styling this is like a default styling I like to use uh we could probably have put this under default Styles but I don't know if we're going to reuse this maybe maybe not for the moment let's keep this styling so then we can attach this to our input field uh styles. input field okay makes it already look way nicer uh we have autoc capitalized none we have the placeholder email we now of course need to catch the email and password so let's add a state we can also use react hook form but I was kind of too lazy because this is just too easy but in real case you could probably use react hook form for this uh value should be email address and on change text we can set my email address that's correct um I think this is also everything we really need in here um so let's just copy this over can you just generate this for input field autoc caliz none placeholder password secure text entry I think this is actually accurate yeah this looks good it looks good okay so we can wrap this now up with two buttons uh let's add some styling here so we're going to have like a primary button and the primary button text styling and again we going to reuse uh our type so if the type is now equal to loin we going to render something and otherwise we're going to render something else so if we are in the lockin case we're going to make a touchable opacity here using my default button and styles button primary that is pretty accurate um and then we're going to have the primary button text saying Lo in why are you so mad about me this is pretty good and then we can use this exactly again in here but this time we're going to say create account okay let's see I go to sign up I got create account I go to loog in I got lockin now if we just create the write functions we are set up perfectly for cler so let's use const uh on sign up or sign up press should be like an async function at some point and then we're going to have the same for on login oh come on copilot can you figure this out right so on sign up press goes to our create account so on press we're going to just call my on signup press and here comes the on come on on lock in press cool um I think or I want to call this on sign in I don't know why I just want to call it sign in on sign in press okay with that in place we should be fine let's check it out um actually this is a problem here if we are using the keyboard avoiding view you see the offset doesn't really match this so I will set my vertical offset to 70 uh let's see I think I might have to reload my app go in here uh oh this is ah it's probably I think the problem is that within a modal overlay uh the keyboard avoiding view is not respecting it correctly so this is one of these things we might have to tweak it more or use something else um do we are we using the bottom offset correctly could be many things uh could be many things let's see yeah models and navigation usually have a bit of an issue let's let's just try this one thing uh if we follow the same approach we used before to get the bottom offset I don't think that the inset is a problem here here but we can at least give it a try okay and let's see if I now also attach to like pading bottom our bottom value would it make any change n not really and if I use margin bottom probably not as well so let's see this no not really making a difference uh how can we solve this I assume there something wrong with a keyboard avoiding view um within the model we should probably use it not in the case of a model uh which also makes this kind of obsolete in here uh if we use RN save that won't change anything so we can also get rid of this but for the moment we're going to leave it like this uh we're not here to perfectly optimize this clone we have a whole lot more to do and these are like just these these minor things on which you then like the 802 rule these I like the things where you spend a lot of time on just getting this little tiny thing right uh and while it's important definitely I agree uh it's not something we want to do right now we now have our bottom sheet model we can trigger these models on Android that might look different that might uh span across the whole view but that's not really a problem I think but we are now ready to finally Implement our clerk authentication all right time to connect our application to some real authentication and we're going to use clerk the sponsor of this video or actually one of the sponsors next to revenue kit so we've used clerk a couple of times in the past and I really like how easy it is to get started I will walk you through the different steps um we're going to use email authentication in this clone check out the other clones we've done with coloric to also see passport authentication or how social authentication with Google and apple could work but they are all super similar and super easy uh here we go you can by the way get started completely for free um I will create a new application here let's maybe zoom in a bit I will call this chat GPT D video we will only use email so I will disable the other stuff if you're in a web context you can also use this nice Uh custom component I think this is not yet working inside a Native application but this won't be a problem at all so we need to install a few things now um we need to install actually two things uh so let's kill this because we need to refresh this anyway and let's install the clerk clerk Expo package and then also the Expo secure store package this is required because then we can store the key that we get the JWT from clerk in a secure way in our application um I want to actually use this in my Expo project so I can now copy this over and and create a EnV file okay let's do this right here at the root of the project EnV and I will put in my Expo public is this correct I wonder yeah this is actually completely correct nice I think they updated documentation uh which now gives me this key um with that in place I think we can uh npx Expo run iOS again and we can close this and that will sue come up now in my application do I have to configure something that is a pretty good question uh a question I'm not sure about yet so users can use an email um uh allow sign in verify require use your verify sign in I actually will disable this right now uh verify by clicking a link um or do I want to allow this I don't know if I want to or not I honestly don't know um yeah authentication strategies users can sign in with a password um shouldn't that be enabled I don't want to reload that page I feel like I made a mistake somewhere along the way uh yeah it was enabled all the time and it was emailing a verification code let me quickly check out my cat GPT video yes password nope email verification so I disabled this verification link and verify at signup that's what I thought um would be cool to to like just copy my settings um email verification code I will hit save now okay uh is this blurring the bottom this was interest it was an interesting effect no I don't think there's anything else we have to configure right now and we should be able to use this so right now I have no users but we have my environment key set up and so we now need to touch our layout to include um the right stuff we will restructure this now a tiny bit so I will actually call this one up here const initial layout okay initial layout no typo today good and then we down here I will have my root layout navigation uh the naming is not important you can name this whatever you want but you need to make sure that you export default yeah exactly root layout n and within my Ro now now I will simply return the right order of providers so I will now put a clerk provider around my application this needs some more settings and I will also place the gesture Handler root view here with a style of Flex one and all of this WPS my initial layout so then we have all the providers around the app cool now I want to grab my key so we can grab my cler publisher key using process. EnV Expo public clerk publish key uh and we can use this in our clerk provider because this expects the publishable key which is in our case now the CL publishable key uh on top of that we want to supply a custom token cache and for this you usually find a little snippet to use the Expo secure store so let's add Expo secure store in here we can just import Star as secure store and then we Supply our own custom token cash on the web you don't really have to do this on Native as a react native app we want to supply this to clerk which is pretty cool because this is basically like overriding or giving clerk this cach which is then using secure store to get an item or to set an item and now we can just put this token cache here into our app now this still complains about my key so you can just say as string which should get rid of that warning as well cool now we should have clerk in our application and we're going to use a few things that are usually included in um the setup of the default Expo application so I kind of I Ran this reset script in the beginning I might have not done this maybe we we shouldn't have done this um but anyway uh we now going to use Splash screen. prevent autohide this means our splash screen won't be hidden until we tell it to be hidden um and usually what you see is that Expo is using this use fonts hook to load the custom font and then there are two more use effect included so I will just place them in the right place here if there's an error uh we're going to throw that error and otherwise if we are loaded so if loaded from use Font is true we can hide the splash screen but that's not everything um that's not everything thing because we will now also check if we are loaded and if clerk is ready and therefore we can D structure is loaded and is signed in using use o from clerk Expo that's pretty cool so now we can before we actually return our view we can check if we're not loaded or not is loaded we'll just return like a slot we could also just return an activity indicator or something um that should pretty much render nothing we could also just render a view at this point I think but sometimes Expo or Expo router is mad about if you're not rendering anything at the root level uh by the way is that the case right now uh not a valid base 64 encoded string length um yeah I love I I really love react native errors okay let's see this is my clerk publishable key is this the same name we used in the EnV yes Expo publisher key the key looks maybe there was something wrong with that key maybe uh and if that was the case we might have to do it again I might have pasted the key in the wrong way with like a uh something okay uh but we do have everything set up so far what we also want is access to the segments so this is going to be interesting this is now combining Expo router and clerk authentication okay so we're getting use segments from Expo router uh let me show you up here so use router use segments and all that stuff with that information we are now able to create our authentication stuff and the app is not loading which is scaring the out of me okay um we're going to have another block here this one is dependent on is signed in and if we are not loaded so if uh clerk is not yet ready I will just return otherwise I will check the segments um let's just do it as a test like this so we can have something to lock out but fail to commit transaction is located in the CL provider not bot base 64 encoded string um well that was a tough one I actually had to completely set up the project again I'm not using the beta right now although when you are using this the Expo SDK 51 should just work fine I have absolutely no idea what costed this something in hers um I don't I honestly don't know I just hope it's not coming back at all so let's do this uh we were here so uh we wanted to sign up uh we have our clerk provider wrapped our app around the app and now we want to implement the authentication so the whole idea is that you usually have some sort of authenticated area and we can group that stuff together by creating a new o group just like this you could also name this differently the brackets only help to like put things together that belong together with Expo router you could also just call this folder off without the brackets would work as well in this case I will just place an index TSX in here here um for testing so this would be our inside Area eventually uh that one will look different so for now this is it uh should we place a layout here that's a good question I actually think we should have our own St layout in here uh so let's do another layout. TSX okay there was not correct I think I M TS X right retive functional export let's call this layout and let's just call this one here a stack we don't even have to supply anything if we don't want to we could just use it like this so the whole idea is that our index page or whatever is inside the O group should be protected and we can do this through our topmost layout file and we're checking here is loaded uh and we're checking the segment so what we want to do next is we actually don't want to use segments at index X zero we want to use this in a different way we want to check if that person is trying to access a page in the or group and we can check this by using segments at the index zero um is equal equal to O So if that part of the URL basically of the routing is in there um we have a match so now we can check if the user is signed in and we are not yet in that off Group which basically means we're in the outside area that means we should actually bring the user bring the user inside okay another case is let's check it with an else if if we are not assigned in and we are in an or group we want to kick the user out nice copilot that was a nice code completion okay so this is the whole idea IDE and the protection of our app and now we can just use the expor router to fill in the blanks so kicking the user out is simply uh router push or in this case I would kind of like to use replace instead um and then we want to just go back to our initial page do we get H now we also get this completion I don't know something with the other project was just off uh maybe it was the Ed in the file name okay so in this case we want to kick the user out if we want to bring the user inside we can bring the user to let's say we get code completion here as well SL off we will just leave it like this for the moment um let's just do some locks in here so in O group and let's also loog is signed in so right now we're not in the O group and we are also not signed in so let's see how we can actually sign in for that we go back to the lockin and on our Lo in page we now need to add clerk um so let's add first of all const uh sign up is loaded um and set active from and now I can use use sign up I think use sign up from clerk okay uh is loaded we also need something pretty similar uh from use sign in so this is going to be a bit challenging if we have both on one page uh we have sign in and we have um uh yeah we do have is loaded and set active here as well um let's just give them different names sign up loaded and set active gets sign up set active Okay this is how we can give them uh a different name with typescript okay now we got both of them and we can Implement our functions so on sign up press uh we should first of all check if for whatever reason the sign up is not ready we just going to return otherwise we're going to set our loading overlay to true and then let's wrap this in a TR catch block so what I want to get uh is uh result from the signup function and to sign up uh no we actually need to call sign up do create so this is how we create a new user with email and password um and once we got this um we could check but I think we don't actually have to so let's just call sign up set active with the result afterwards um or probably not with the result I think this expects a session so let's set the session to result dot oh what was that uh result. create session ID so by setting the user active we're basically doing what we do on a login um and we can catch any errors if there's a problem and I would also like to finally set my loading to false in this case you could also alert out uh error. error and what is it called it's called error okay error do errors at the index0 do message uh that's what we could log out okay let's do it like this good I think this should actually work for our sign up we could try this out but I think let's just copy this um because we need pretty much the same thing here on sign in or maybe copilot is able to figure this out so let's check if it's not loaded we return we then set our loading to true we then use uh our sign in create but this time we're going to use uh or we have to use identifier email address and password uh on sign in press result and then we want to call just set active that's true and the session is the result. created session ID um that sounds pretty good actually I want to use the alert overlay here from react native uh should work just fine okay I don't see a problem let's try and do a sign up so sign up with email s at galaxies um I think I can't use my fake password Here Yeah password must be eight characters or more Ah that's Such a Pity but it actually gave us a chance to check out the login uh the sign up and here couldn't find your account so error messages on point now let's sign up with email I don't know let's um col is just too good and is figuring out all the passwords that I shouldn't use so let's use something else uh maybe this one works oh yeah I finally got this one so we are signed in or at least it looks like we're signed in um what do we see we see we have two headers up here so this is a problem of Expo router and stacking uh navigations we can easily overcome this pretty quickly by going to our top layout and adding a new entry for well it's it's called St screen but it's actually more like a group so in this case the name would be our o group and for the whole o group I want to set the header shown to false so that would remove the uh header that came from this outer stack navigation we only want to have it from this inside stack navigation at this point um we should also be able able to um let's see we need a way to sign out right uh if we need a way to sign out where could we do this um where could we place the fake sign well let's place it just here on the index page we're going to quickly change this or soon change this anyway um so let's add a button from react native title uh title sign out on press I want to call something which we can get from clerk as well uh is it called use sign out no I don't think so uh what was the name it's I think in the use off hook from Clerk and then we can just call sign out here or maybe we have to do it with an error [Music] function okay uh button title sign in onpress sign out anything wrong wrong uh has no closing tick yeah that's a problem all right but what we see is that if I press refresh I'm also immediately brought back to the inside area we quickly see uh the login we could probably hide that as well if we wanted to um in fact we should be able to hide this by not returning a slot and instead returning like a view if we in our top layout return a view style uh Flex one and then maybe place like an activity indicator in there um oh come on just close it and put RIT okay react native reanimated could not be found oh no oh no oh no why are you doing this to me just the import from react native it's not that hard really like when did I ever wanted to use a view that way I don't know so now we wouldn't see the index we actually see the loading at the top for a brief moment uh we could of course change this by saying align item Center and justify content Center so then we would just briefly see uh a loading indicator let's do this okay loading indicator and then we signed in cool that is probably even better so so we are automatically brought in uh this inside area is protected here by all logic and if I know sign out I hopefully brought back here and I'm now back on my lockin and if I refresh Yep this happens and also at the same time I should be able to sign in here uh so let's do this if I do another lock in voila we are signed in cool cool um honestly again I don't know what happened in the beginning uh what went wrong but this code definitely worked I tried it uh it wasn't the code the problem was something in my react native project setup so now we should be fine we are able to create our user account in Clerk and we can verify this by checking out the users and here we go my Simon user is in here ah great that feels so good okay but but honestly we just like at the very beginning of our app we have secured our cat GPT colog with clor which was pretty easy um only the problem with react native was kind of boring um but now the inside Area comes and I think before we get into all the functionalities let's build a cool side draw navigation and customize it really to our needs we now want to create a draw navigation in our cat gpg clone the goal is that it should look like this so at the top we're going to have a text input field for like searching stuff then we would have uh three menu items bring us to different pages of the app and later we're going to also have a history uh we won't do that for now but we're going to keep that in mind also at the bottom we want to have something fixed like a footer uh with our logo that should open some settings page and we pretty much fill up the whole view so you see it right here uh if you check out the gbt app this is what it looks like so this is the goal for this section and it's actually it's not too hard but it takes some time so let's get started first of all we need the react navigation draw package this is required to uh in general Implement a draw navigation with Expo router and then we can follow this up again with NP Expo run iOS to bring up our views now let's talk about how we want to structure our we do have this off group in or under this o group I want to have different things so I want to have for example a folder later where we can have some models for example inside the model there might be something like a settings TSX file let's call this reate function page and let's call this settings okay this is going to be a model in our application um that also means for the models uh we don't really need a layout but we have that layout file up here and I want to put another folder draw in here and that draw folder will have its own layout file which then defines the actual draw content now again bear with me this is a bit more complicated but we have to set this up once and then uh everything will eventually work fine so we have draw folder we have modal folder both are protected because they're part of the O group and we have a top level index and layout file um that top level index file is actually something I don't really want to use anymore um so maybe we can put this under the draw um and then we're going to place okay so the first will be uh the chat group and I will do another folder this time this will make sense later we could also have just a chat TSX but this is going to be interesting so we're keeping it like this uh next to the chat as we've seen we have a page for do and explore so let's just add these files let's call this explore. TSX uh let's call this page explore and then I we'll copy this and call this DOL this is the dolly page okay so under the draw we have the chat folder we have the layout D explore and we have the top layout file I think this is enough for the moment so the top layout file in our authentication folder defines the stack so that will help us to display the models later for the moment there's not really a whole lot this page or this layout has to do but we can be pretty sure that we're going to have a problem if we later or in a second use a draw we're going to have a duplicate um header so as always we go ahead for our group which is the draw group we're going to put in options header uh what is it header shown fault exactly so now the header here will disappear that's fine because in a second we going to get that back let's now talk about the draw layout so the layout file here in the draw this is the one that now actually defines our draw and I do have another resource on Galaxies on uh creating a custom drawer uh which is definitely helpful as well if if you're interested in this so let's begin the basic stuff is just putting a draw uh around our app we can import the draw uh we cannot import it than so this actually I feel like this might change so from Expo router SL draw I feel like this might change in the future um but the cool thing about file based routing is that you see this immediately everything works we can go to explore we can go to do and we can go back here this is like unbelievable we just place the files here and use a draw component and we have a fully functional react native draw component this is again and again really impressive to me but we see there's so much we have to do um you can try and style these items in some way and like make this a bit custom but it's going to be really really challenging um so we're going to have a problem here and we're going to later use our own implementation or our own Uh custom draw content but for the moment let's just affect these views a bit because we can actually do some things our own here so let's do the same like we did uh for the other screens we can set up the drawer for a certain page so let's call for chat um I think it's is it chat new how did I call this let's call this one new so this is if I want to like start a new chat in that case okay for chat new uh we want to supply some options and these options could be title new chat and I would already change the title up here I also want to give this a draw icon so draw icon and the draw icon is going to be a logo so this is a bit challenging but as I said it's not going to be really easy our draw so we're going to place a view in here uh maybe let's just do this for the second and what we see is that we now have this new chat put in uh in front of new chat that's of course not what we wanted uh we wanted to display an image so let's add a stylesheet down here in which we can in a second style that stuff and I want to use the item um so item put it in here and then we're going to place my image component in here from react native and for the string uh we're going to use our local asset in fact uh at least I hope there's a local asset called logo white let's see uh assets images logo white yeah seems to exist and for the style uh do we need some styling here I don't know let's close it for the moment so this gives us a gigantic image I forgot to attach The Styling here so styles. item uh and we didn't really gave that one any kind of value right yeah that makes sense uh so that item should probably have rounded border so let's use a border radius of 15 and I want to set the Overflow to hidden um okay yeah that was actually a good start but the button image needs also some styling do we already have this no styles. button image and then let's generate this one down here so button image uh let's give it a margin of I don't know six and then a specific width of 16 and a he of 16 as well so now this turns up as a little white icon up here the positioning is fine uh the only problem is that our item needs a dark background so let's set the background color I might reuse the item so I directly set the background color here and then we have it like this I think this is a good start actually okay um do we need anything else in here um we might at later Point have some something up here in the header right slot so header right let's implement this as well and you see this is not yet the custom menu we're going to get to the custom menu eventually uh but for the moment we just work with the default uh draw navigation because that is actually sometimes enough okay this is an expo link component we're directly passing in push because we want to push a new page so on the new chat page there's always an icon up here to like start a new chat um and this will bring us there so let's include a touchable opacity and then just add an ionicon name should be create outline size uh 24 color probably uh our own color so colors. gr and then we might need some style here because it's attached to the right right hand side let's use margin right of 16 no that's 17 the six yep that looks quite good to me we're already on that page so this is not working um there was a little fix like if you want to push a page again and again it should be possible by um adding get ID to a screen um however this never really worked for me I don't know if Expo router is still working on something or if I'm using this incorrectly because not this is the fix that you see in the documentation uh maybe I just need to reload uh uh what did I uh okay yeah we have the automatic sign in that should probably Now take us to SL draws SL CH new yeah okay that is fixed um and our drawer Works somewhat now let's copy that block here because we have two more uh elements in the menu that we should talk about by the way I will call this one the first one not new chat but chat GPT because that's what we are working on so the second one will be um Deli we don't need to use the group it's just right here we also don't really need the ID uh for the title I actually copied out this dot somewhere so it now looks like Del um the draw icon will be DOL instead um and for the header RI we don't want to supply anything yet okay the Del image is a bit different so for the do image we need to create our own styling um this will have a bit different width and hate and the resize mode set to cover so then it will cover this whole area let's use this instead on our Dolly image so then it fills up this it's just like playing around with a few things here and there then we have that explore thing going on um so let's add another screen for explore this will get the title explore gpts um draw icon in this case is the item and now not an image but only the ionicons name app apps outline uh apps outline size could be something like 18 colors I actually want to use in this case I want to use the black color um and we don't need a margin okay so this gives us nothing really helpful so far um why are we not where why is it so small uh I think uh the item stuff here is not working in our advantage also Yep this is better with a white background so let's overwrite this and use our own custom with and hate we probably probably we don't need item at all yeah border radius 15 I mean we could probably just copy this block out and call it something different uh let's call this item explore sometimes you you you know you try to reuse as much as possible but sometimes it just doesn't make sense uh and this is one of those cases where the explore item is just too different uh we have a white background color in this case we might have a border radius as well uh if we want to we want to align the items in the center and justify content Center yeah I think this is what I wanted if we would add this would it help anything not really it's not really making any difference I kind of feel like I want to keep the Border radius um but also I feel like this is not aligned I don't know exactly why it's not aligned but it's it's definitely not aligned um oh maybe because we're not using it yet the explore item um yep no here we go now everything is aligned we can go to Dolly we see the dolly header we see Explorer and we see Chad GPT with that custom icon good so this is almost as far as we can get but as you see we're not yet there we're not yet there uh we don't have our custom footer component and we don't have the header I think we might be able to work a bit more on this by setting some general options for the draw so if you want some general options for the draw you can do it in screen options up here first of all I would like to set my header style and use the background color light um additionally I thought I had something about the general kind but I can't find it anywhere I also want to use a different icon up there so this is not a problem but again one of these things you have to work on so I wanted to have this um dark icon up here and currently we have this icon so we have to change that we have to change that I really want to have an eye here on the details so touchable opacity uh and the touchable opacity on press will do something can we keep this like it is yeah oh no what did I oh what was that that was an interesting one did I click here I don't know where I clicked it turned my whole view dark that was scary uh anyway uh this time I actually want to use Font awesome six I couldn't find this icon anywhere else in this it is called grip lines and it comes as close as possible to what I wanted to use normally you can also of course use um a custom SVG if you want to okay just uh but in this case what is your problem here okay now everyone's happy okay now we have our custom icon up here we just need uh some styling more so I don't know why I don't get code completion for size here on this so let's use 28 and for the color let's use colors. gray okay this is my icon up there not perfect yet we probably need some margin left uh margin left of about 16 okay now the icon is somewhat in the right place this is just too big 20 looks better to me good um what else can we do um okay yeah we we use our custom icon but we completely messed up the uh the draw if we now want to manually get this back let's see how we can manually control the uh the draw that's anyway quite interesting we can first of all use use navigation from Expo router and with that we can now attach the function here in on press I want to call navigation and I will call dispatch and I want to dispatch an action and we can import this there are nice typings called Draw actions and then draw actions close draw jump to open or in this case I will just use toggle so now this dispatches an event and I'm able to open my draw again fun fun fun that was really fun okay uh we have the header style um now we just going to do a few more things for styling so I will set the header Shadow visible to fults I will set the draw active background color um so this is the color here okay if I disable this you see it's this blue now we got this nice gray then I want to set the drawer active and inactive tint colors which are the colors of these item and you know you see we're getting there we're getting closer to what we want to see now I also wanted to change this overlay stuff and turns out you can do this so I can supply my own custom draw overlay color if this was um too light then for these icons I can also Supply a custom draw item Style with a bigger border radius as you can hopefully see in these areas here so we now have pre- rounded borders I want to bring my label closer to the left so something like this and finally I want to have the draw open a bit more so I can later see more of my text in here and we can change that as well by simply adding draw style and using the window dimensions so let's add the hook for use window dimensions from react native and then we can set this to whatever width we want so you see this is open pretty far and gives us plenty of real estate later to show our stuff now the question remains why do we actually have to customize more well let we check this out we haven't talked about the footer and we haven't talked about this area up here and we also haven't talked about these custom stuff links that will come in later we have so far only Built the general draw and customized the default items that are included so if we want to take things another step further which we eventually now have to do we can create create our own custom draw content let's just do it in this file I tried to do it in a different file it just makes things a bit more different um maybe if you're done you can like put this in a different file but during development I had some issues if I didn't do it like this so uh we got this I'll actually put in props any here I don't know exactly the typing right now um and what we want to do is we want to return a custom view okay this one will have styling of Flex one for the moment um and maybe some margin top using once again uh our cool use safe area insets Hook from react native save area context so then I can use instead of margin top with a fixed value I can use this one all right uh this didn't change anything so far but we can now go down to my draw and specify that we want to use a custom drawer content okay custom draw content and that will use our custom drawer content this first of all replaces everything in the drawer with that custom component but don't fear we will get back our stuff in a second so we will not do the header yet let's just focus on getting back the previous stuff and we can do this by using a draw content uh scroll view why is there no import uh that already scares me normally we should be able to get the draw scroll view from react navigation draw do we actually add react navigation draw so far we haven't done okay so here we go we can import the draw content scroll view from react navigation draw that's the actual package that supp app this we will then pass any props to it so any props that were given to the custom drawer now go to the draw content scroll View and to render the previous list we can use another component called the drawer item list and once again we pass in all the props so at this point we have pretty much the same draw but we have more control we can use it just like before we have all the customizations we used before but now we have the ability to add more to this okay and that is the cool thing so with that in place I should be able to bring in another view up here um for the moment I will give it a background color of red so the classic debugging and then we're going to place yeah some header in here okay here we go we have our nice distance here with the safe area inser and then the header starts that's good um also why is the draw content scroll view starting uh such a big difference here that shouldn't be the case let's try and set the content container style and I will set the petting top uh petting top to zero yeah that brings it way closer maybe we could set it to something or maybe on this view we could set like pading bottom I think that makes more sense because later we will be able to like scroll this part below the header so in the header we have this search box and this makes more sense so now we can just give this white background and then we have our sticky header up there okay cool um let's Place do we need another view in there uh not really so we want to make this a search section now um can we just do it in one I'm curious not really let's do another one let's do another view and give this one uh styles. search section because we want to have an input view with an icon and text and usually you have to do this in a custom view because you can't place the item correctly in that text input field that you need up there let's put that text input field right in there so uh in the search section we go with a text input uh do we need to put in anything here well let's put in a placeholder for the moment search and I think underline Android color should be set to transparent but I don't want the style that you gave me here although I'm appreciated okay we see we got a search input not really working with the background stuffs but we're going going to get to that in a second additionally let's also add an ionicon so here we go we now need to implement some stuff um let's also put this here so styles. input and then we have search icon and input and we have three things that we can style search icon and then we had input okay for the search section let's begin with that uh let's give it some margin horizontal about 16 so this is it the search icon is pretty simple let's just get some padding and then we're going to make sure that everything inside the search search section is aligned correctly that means Flex Direction row justify content Center Aline item Center I will also set the background color in this case to um colors dot input and that already do a lot so we see looks like this um also might want to do some border radius uh border radius let's set this one to about 10 gives it a nice rounded View and let's also Define the he with 34 okay cool now the only problem is we're typing here in the middle that's certainly not what I want so I will now give this field a flex one that already changes pretty much everything because now this field is taking up as much space as available with flex one um and the icon will just have the rest um for the input we can now also customize this this is just more like really small stuff adding a bit of padding here and there U aligning the items and then also changing the color of the text as we type cool um that was actually a lot so we got this point that means later on we will be able to reuse this so right here uh below the draw item list we could render everything that we wanted to and that in the end means uh the chats we have created before that we've stored using sqlite will be rendered here right below that list um there's one last thing that was the bottom part of this so let's attach one more view in here um I will just do it in here uh I we give this one pading of 16 um exactly and then petting bottom using the bottom value of our safe area insets um let's for the moment yeah let's let's just go with this so we see what's going on good point okay we see the version down here that's of course not what we want what we want is uh something like looks like this a row with an image name something and we can actually click on this so if we want something we can click on you know that we need a link component atev oh I think that was actually correct off modal settings yeah that's that's true we don't really need push but we need as child as we're wrapping something so we got my cool touchable opacity in here again and that touchable opacity probably gets some Styles as well so I mean the problem here is that we have to jump quite a lot in this file between our stylesheet and now the new component again maybe later put this somewhere else at least that's my recommendation okay the first thing we're going to use in here is an image uh does that still exist yeah it still exists at least today um using the Avatar styling let's put this in here as well okay and for the footer we already know that we we need to align our items uh with a row and then align items in the center and maybe Place some Gap in here why am I not seeing any Avatar probably because I haven't given any size to this so let's use a width of 40 he of 40 and a border radius of H just 10 I don't want to make this completely rounded okay here we go we got that down there um additionally I wanted to include a little text but all of this is now just like playing around uh nothing too critical so I want to use like M Marat um the mascot of galaxies and then finally a little ellipses horizontal icon and we just need to wrap this up with the right styling so username should probably take up most of the space just like we had before with the input field username and for the styling of the username we just going to make sure it's taking up everything and has a bit bigger font size good again that stuff is still working that header stuff is fixed this is a whole scroll view here and then we have our MAA down here which pushes the settings page now that should actually come up as a model um do we want to customize this right now um actually no actually I don't want to do it right now we're going to get to that anyway in a second but for the moment let's appreciate what we've done we've created this whole draw navigation uh with a custom styling of item with a custom draw content so we can create our own Hera and footer area uh we've changed the whole appearance of the draw component as well with the screen options and I think now we're closely getting to actually working with CAD gbt but before that let's Implement some more cool stuff with react native I bet you're going to love this part because this is something that you might not see very often and it gives our app a really really epic feeling so we now want to use a drop-down menu I actually don't really have a good screenshot of that um no don't think so the idea is that up here I want to click on this and I want to have this like little context menu appear this drop down menu actually we're going to get into context menus later they not really any kind of screenshot here how this later looks uh but anyway it's a great library and we're going to use a drop- down menu from zego created by Fernando Rojo maybe there's something on GitHub no no example here anyway doesn't make a difference let's get started so what we need is to install a bunch of things uh let's just go ahead and go back to our code and most likely we going to have to kill this for now so npm installed zego that's the main library react native iOS context menu that's for the iOS context menus react native iOS utilities and react native menu SL menu on top of that we also need Expo build properties because we need to change something in our app Json all right so before we continue and I wonder if we have to do a clean rebu soon we will figure it out we will figure it out so uh oh if you're using an older version there some I might not need this um but I think we do uh I think I ran into a problem and then I I used these values so you can add a custom block with Expo build properties to your app Json and that's what we're going to do so let's bring that up uh app Json and instead of having just Expo build properties I want to use this block here so I want to set for Android A Min SDK Target compile SDK and for IOS as well a deployment Target of 15 I just noticed that yeah maybe it's not required anymore with latest uh Expo versions I think this was also a problem of the initial screen with a kendle heptic uh plug-in which doesn't exist but anyway it's a good exercise so if for example some of your plugins require a specific version a specific SDK you can use the Expo build properties and then everything would be set accordingly okay back to NP Expo run iOS let's close this and do we need anything else I don't think for the moment I think for the moment we are good um I want to reuse this in two places so whenever I have a case like that I know I want to do this as a component so let's call this header dropd down. TSX okay this is my header drop-down component and I want to use use this both on the DOL page and on the chat page uh since we're on the chat page maybe let's start with that one um so I will go here and we currently have that page I will give this some stylings so we should have default styles. page container uh that's the first part and then I want to directly change the header in here because this will also call some functions of that page so I don't want to use it in the layout um and you can change the header and everything that you see also on this screen so I can now simply say stack from explorator screen on this page I don't need the name because well we are already on that page but I can Define some options here and for the options what I want to change is I want to change the header title uh Herer title to well we can change it to chat for the moment that would be interesting oh one error uh react native menu Swift okay maybe we should do a pre-build maybe we should do a clean of our pre-build um and maybe also the Expo build properties were really required in the first place or at least I hope so I had enough of problems with some random issues today that were not my fault so I really hope this is not one of those again and I hope the war play nicely together um at least I think they should they should now okay uh installing pots so this should be finished soon and then we can run iOS again and we hope for the best please work okay um what we want to do on this page is for uh the header we want to actually Supply our custom component for the title title okay you could set that just to Chad H now we're getting confused uh we could set the heter title simply to Chad or we can supply our own component and in this case I want to supply the header drop-down component for that we haven't defined any props so far so we can just go ahead with this meanwhile let's talk about how we can implement the header dropdown first of all we need to add everything from the drop-down menu from zego then I want to Define some uh some type here so let's call these header drop-down props and what I want is of course I want a title okay title um is going to be a string and then we're going to have something that is what is going on here selected that should be a string as well which kind of um title is selected then I want a call back function so on select let's call this key string I want to call something and then I want an array of items uh I'm glad this this is still building I'll just keep it open and hope it works out so items can be passed to my header drop down as well these are of the type it's going to be an array and everyone will have a key a title and an icon all right now we can use the header drop down props here and I want to actually destructure this into uh all of this so HRA drop down props and then we can use title so in this case C GPT should really see what I want so I want of course selected items and on select good um I really hope this build is working if it's not working it will be so painful to debug again no why why all right it looks like there's actually a problem with the react native men so I uninstalled this this was only required for Android so if you're using Android I wonder if this is working for you if you also got problems with the latest version let me know in the comments um maybe we're going to have to talk about that for the moment however this seems to work now how does a drop- down menu work um a drop- down menu basically looks like this we have a rout we have a trigger and then we have content with label and items it's actually pretty straightforward and that's now exactly what we want to imp Implement in our header dropdown so we already see the component gets displayed up there um so what I want to return is dropdown menu. root that surrounds everything then we do have drop-down menu. trigger that's the first thing um inside drop down menu trigger uh we have a little view in which we could just render the title uh that also means I should pass the title through so uh let's call this one test here uh yep that seems to work for the moment uh we're still missing a few properties but we can get them in a second additionally this text title should be of course a bit bigger so let's change this to have some font weight and it looks actually like a title now this is only the trigger what's more important is probably the dropdown menu. content so this is where we actually see the drop down menu now I want to iterate through all the items that are passed to this component and create a drop- down menu item for each of them using key on select will call of course uh my on select with a key uh we don't really need selected but we should use the icon um the icon shouldn't be set like this uh also the drop-down item should use dropdown menu do uh item title I think um let's give this item do title uh cannot read map of undefined yeah that makes sense uh we should probably spend a moment to pass the right params to that page okay header drop down the title should be Chad GPT just like the title of that page was before then we have the array of items um I want to have two in here uh the key will be 3.4 and this will be four so this is only like about using the different versions this is GPT minus 3.5 this is GPT minus 4 and for the icons it's quite interesting uh zego is using native icons so if you're on a Mech you can use the app SF symbols and then use uh the included icon so this is an icon set that is included with iOS um so I want to use these I want to use the bolt icon and the Sparkles here um then we need to pass in some more so and we need to pass in on uh select oh did I use lowercase I definitely want to use on no un select on select that's fine uh oh I'm still in the array I'm sorry on select uh come on on select um so whenever we select something I will just lock that out for the moment and select it um is well we could just set this to something uh maybe we going to use a GPT version we're going to use a state up here we will later use something better uh let's call this GP GPT version with a use state of 3.5 uh then selected will be our GPT version um in this one should be closed okay so here we go we see our context menu appear let's just refresh once I thought that was an issue okay uh we don't see the icon yet but we see the header and we see the different menu elements that's good so now we can find you in this a bit more in my header drop- down so I want to include the icon here so let's use drop-down menu. item icon um and we can use a specific setup for iOS so for iOS I want to use the name item icon uh I don't want that I want to use the point size is there no point size uh item icon iOS I think why is there no point size um there definitely was a value called Point size and there still is you see now the icons turn up I don't know something's off here today and also if I click on something we see 3.5 and we see four so this will help us to change the GPT versions we're going to connect this to mm KV in a step later for the moment this is pretty cool um but I also want to include the selected so if we do have a selected value in that case I want to include a little text blob here which has the selected version um and greater than so we see up here my version appears because we're actually passing it in this also shows us that this view should probably have a flex layout row um Flex Direction set to row uh and also align the items in the center okay uh we got the title now we probably should give this select block it's own styling let's see probably something like margin left um what is this let's just see uh I want to give this a bit more margin left I want to use font size that's bigger I also want to use where's the 60 my own color so colors dot gray light okay that's getting there maybe a bit bigger font weight of about 500 yeah I think that's good I think I can live with that um now the only problem is that it's not changing I think for debugging we can actually do this so let's just call set gp2 version with the key and voila we have a nice drop down which changes our state in the future we're going to persist that and uh use mm KV but for the moment that should be fine and I really like this you can reuse this in so many places zego is such a fantastic Library uh I don't know why I encountered the issues and we're also going to use the context menu later so this is my header dropdown and because we created it in a component uh and we were very smart about that I will now go ahead copy this block go over to the dolly page and on the DOL page we're going to do the same stuff that we just did um I will give this one the default Styles Dot Page container so we have the right background color and then I paste this in um let's see add all missing Imports if it's getting this right um header title will be DOL okay um on select I actually don't really care about this uh in this case so I will pass in this I will not pass in selected because that is optional and now instead of these items I will pass in three other icons if we now go to DOL check it out voila we have the same great drop down we can share a GPT we can see the details and we can keep in a sidebar whatever we want um we could also easily attach uh functions to that but we don't really want to we just wanted to have this pretty epic UI effect and thanks to zego we got this okay there was just a small or short example of what's possible and now back to the actual topic of making progress towards getting completions from cat GPT now it's time to talk about the message view so on our cat GPT page this is basically what we want to see uh we're going to have this logo up here and later we're going to of course have the chat here then we have this area which are like some recommendation cards and then we have this bottom um text input that text input has something unique to it and that is let's see open link a new tab put it here that this stuff is actually animated so when this comes up let's see this animation once again in a second maybe just focus on this part so you see the icons on the left hand side can be expanded or closed okay you see that is what we want to achieve and it's a small thing but I also think it's quite cool um this is a good example of using reanimated and like some small micro animations so therefore we will go for it okay we will create a new component I will call this message message input. TSX okay this is my message input uh the props here are export type uh message input props um yeah probably to do uh but we want to have something like on should send and then we have a message that should be sent okay good um we will use this on our new chat page uh we will later rework uh many parts of the application again this is probably one of those for the moment what I would like to do is I will just put in something that has Flex one in here um we're going to have like dummy content we're going to have the button in there so this is or will take up most of the view and then we will have our message input here at the bottom okay message input there we go um this should already render down there um I can probably yeah put my head up in in the corner of our view while we're doing this uh so then you can see everything uh regarding that area good on the message input component what do we need we of course need state with the actual message so use state from react we want to have access to the bottom uh safe area so again let's import bottom and then we will also prepare a bit regarding our uh anim I will call this expanded and use a shared value which has a value of zero I don't want to use false and true I didn't really have a lot of success with that um then we can probably begin with the view and also installing a bunch of packages so there are exactly three packages I would like to install we will not really completely use them but I anyway want them so Expo blur the Expo document picker and the Expo image picker uh the letter two will just be like indicating what's possible with Expo and uh we're not really using them uh but I wanted to include them but we will actually make heavily use of the blur view especially in later parts of this course so I want to put a blur view around this whole thing in fact uh did the import work no of course not why should it uh and this blur view uh will have a certain intensity we can already set that uh the app should come up pretty soon uh and what we can set as well is what we did before so we are usually setting the padding bottom to our bottom inser uh and maybe also some pading top but I don't know about that one yet um then we will have okay let's revisit what did it look like uh can we just open then view again okay here we go open link a new tab okay this is again what it o no this is not what I wanted okay we have a row with three icons a text input and another icon that is the basic idea of this view we see already in the background it is a blur view this will only become really important once we got some text that can be scrolled behind the uh bar so right now we probably won't notice that blur View at all uh because there's nothing we can scroll behind it um but I'll already give this The Tint extra light that's what we want to have later on okay so instead of message input I will wrap that stuff in a view now style styles. row oh I don't have styles yet reate to sty sheet um I'm jumping around I just want to fix that Stu stuff okay stylesheet probably still need text and then the row styling Crow pilot you know what row means exactly Flex Direction row uh align the items in the center and some petting horizontal of let's say 20 and I don't need a background color but thank you nonetheless okay so that row has three uh Parts as I said we have that first area with either one or three icons right here then we have the text input and then we have the third area let's implement this um should we do it directly yeah I think we should do it in the right way um because we will animate that stuff very soon uh we're going to use touchable opacities for the buttons and these are usually not animated we have to create our own animated components so let's call this animated touchable touchable opacity equal animated and again we're using the re native reanimated API to create an animated component and then pass in touchable opacity so now we have our a touchable opacity component and we will reuse this in the view um first of all let's see what do we need uh now co-pilot I don't want what you're giving me here uh definitely not I will write this my own so onpress something will happen uh I will probably call the function expand items okay yeah let's put this into to do okay on press I will expand the other items um the style here should be something yeah good question what the styling is uh and then I will have the ionicons name at size 24 and um colors do gray no not green gray good okay we got that icon and on press when I click this this would expand to the other three icons this is uh what we usually see inside do I still have yeah we could uh open link a new view so by default it would look something like this this also means we need some styling for that button so probably we should have a button round button styling let's use this one so withd 30 big border radius a light background color and aligning the items and now we can use styles. round button uh but additionally yeah we will later have a different styling for that but we don't have to worry about that too much also I noticed that I can already see that we need more petting towards the top so I don't know if you can see this in the video but definitely in your own view we should have some petting here in that view otherwise this is not working out uh let's next add our text input component we will skip the three buttons and get back to that in a second um we will actually autofocus this once we enter the page uh we will have a placeholder which is message then we will have a certain styling uh so let's call this styles do message input okay we should place this in here as well we're going to implement that later we can already close this to make everyone happy okay and then we have our text input um okay what else do we need this could be a multi-line input so we're going to set multi-line true the value is didn't we have like a state for that didn't we already have something like message yeah we did have so we can also have unchange text set message um I also want to have something on Focus so when we click this I actually want to collapse the three items again to this one plus item so besides expand items we're going to have uh collapse collapse items and that collapse does it do you spell collapse like that I don't know it's it's wrong it's like this okay on Focus I want to collapse my items right now this won't do something uh I can just type it's getting bigger and bigger um also my row uh should the row have now I will give this to the message input so my message input will take up most of the space so again Flex one um and then we're going to add some more styling to it so some margin horizontal uh super thin hairline with border width then we have the radius of 20 we have some pedding and we have the border and background color okay this looks pretty good so far on the right side of that message we should also have uh another button so that one will depend on whether my message. length is greater than zero so if it's greater than zero this should be the pr the scent button and otherwise it will be this headphones button okay so in the case of the headphones button we can use something like this uh from font awesome I get something wrong here uh no I don't think so I think it's just mad that we don't have the import yet so font awesome five from Expo Vector icons um if I just put it in here as well are you happy then yeah it's always the same okay so this is my uh headphones icon but in the other case I want to have Arrow up uh Arrow up Circle that's not how you spell it Circle uh oh and that one's also from ionicons good so we see no okay uh if it's empty then it changes to the icon uh do I really want an icon that looks like this uh size 24 colors gray well on press I definitely want to call on sent as well uh so let's call function on sent that will do something uh let's just call this on sent and put it down here so if we press that one it will send um Arrow up Circle maybe outline or is it like this I don't know I kind of like outline more I'm I'm right now not exactly sure how it looks in the uh official uh app yeah I honestly don't know okay um we got the basic stuff uh we still have a problem once again with a keyboard avoiding view now the problem here is that I want to use a blur view that means this message input has to stay above what's coming on this page if this would just be the footer component and like uh content and here and here is my input stuff then we wouldn't have the problem we're talking about right now normally I would just put the keyboard avoiding view in here and everyone would be happy however because we got the blur view stuff going on this is not working exactly like that so instead I will go into my chat page here where we're using the message input component uh and by the way we should be able to use on oh we're not using the props yet uh on should send message from message input props by the way we can then call this one with my message and set the message back to an empty string and then we can implement this here on should send message uh we will call something like get completions get completions or get completion get completion uh for a moment I will just put a lock in here that we want to get the completion for that message good okay get completion cool um but the problem was regarding the keyboard so we will place the keyboard avoiding view in here again keyboard avoiding view from react native uh the behavior we're going to use the same stuff we had before um can you just do this if the platform is IOS then pading otherwise hate for The Styling I honestly don't know yet um but we're going to wrap this around here okay so far this is probably not yet working because we still need to set my keyboard vertical offset I think 70 should be a fine value again um let's see yeah that I that actually worked pretty well um I wonder the only thing I wonder about is that in my test I had an absolute position um I don't know if we need this still or if this was maybe a relic of the past so I had something like this what would change if I do it like this we don't have the content yet so I will leave it in here I think this will be required once we have something that we can scroll behind maybe maybe we can scroll something behind already um we do have the flex one here uh what have I just put in a lot of items um what if I just had like a scroll view in here of dummy items um can I just like map yeah array from yeah this is good copilot you're doing right you're doing EX exactly yes this is what I wanted okay so this is going behind this right now um I don't really see something through [Music] um let's give this one a red backround yeah this is definitely working I think it's working um let's not use that background color let's use it like this so the view is definitely behind Maybe my intensity here is a bit too big what if I set this to 30 yeah then we can see that stuff is definitely looking through so uh play around with the intensity or the tint here but our blur view stuff is now working as expected that's good okay also text input and keyboard seems to work with that setup and also if I now remove that part uh and do a Reload I assume that probably the blur isn't working as expected um oh I need to test this do you know this feeling like you just can't unest it you just have to do this one test yeah you see now it's not going behind this if I add the absolute position it goes behind this okay finally confirmed all of this is required for our app to work we'll commment out the scroll view because we don't really need this and we will get to the actual animation now so we have prepared most of of that already uh what we need is once we expand our items we will set the expanded do value um to something like withd timing um withd timing is another function from reanimated so I will set the value to one and for the duration I will use 400 so we actually get something from this same now for collapsing that stuff but in this case I will do it uh by setting the expanded value to zero now the important part happens here um oh by the way I want to use something unchange text I want to set uh I want to use a custom function so unchange text what I want to do is uh I will actually set my message but I will also collapse the item so you see this in the official app as well once you start typing it will collapse the stuff again okay so there's a little trick here um okay now the important part is how we animated and therefore we create two stylings we create the uh expand expanded button style using use animated style from reanimated and this one will give us the chance to return uh specific value [Music] whatever this is this is not yet what I want but anyway we're going to use it for the moment and this goes right in our component and because this is an animated component we can now make use of that stuff so right now the expanded value is zero and therefore my opacity is also zero um if I would change these to one that should actually make make this stuff appear again yeah then it would be here but probably because we're focusing it it would immediately go back to zero anyway uh we are still missing our second View and also this is not completely finished this is just an indication of what we want to do we want to have another button view style that will work something similar okay so we're not seeing that button at the moment anymore let's do another animated view that one will have uh something like button View and button view style from up here actually I will pass the opacity one for the moment so we can develop this in isolation that button view uh has just pretty much the same setup like our row so Flex Direction row align item Center and just a bit of gap between those elements uh and the elements should be pretty much like above but these can be normal touchable opacities so for example this one the first one could use is a camera outline and the image picker from re uh from Expo we can also bring in the document picker as I said before we are installing these and kind of using them but not in a really functional way I will just indicate that functionality here so for the second one we could then uh use instead of launch camera we could launch the library and for the third one we could call get document async which actually would open up this document View and the second one would open up the library here we go so all of this is really really easy with Expo and react native you could go ahead and then really work with these results and upload an image we will not do this today I just wanted to indicate that okay so far we don't really have any kind of Animation going on because we are not really using um the button view style or the expanded button style in the correct way let's do this now so in the default way um the opacity of the button should be one um but we want to uh interpolate that value um so the problem here is that let's do it let's let's write some code because this is actually kind of uh challenging for me I have some problems with interpolation uh I try my best okay so interpolate from react native reanimated that basically Maps values like you have a value of between zero and one and you can map that to something between zero and 100 so you have many more steps and it's automatically mapped okay the number is here the expanded value and the expanded value the range goes from 0 to one these are the values if expanded is zero the opacity for my button okay for this plus button should be one so this zero is now mapped to one if the value is one which means uh it should be collapsed it is mapped to zero so you see this this is kind of a bit like a bit challenging but it should work also we want to pass in extrapolation do clamp uh if we're using clamp it will not use any values outside I think it's the like an clamp clamps the value to the edge of the output range so it can't go beyond anything like this however the opacity in this case is not uh everything uh additionally I would also like to use this for the width so I will call this width interpolation again the input value ranges from 0 to one and the output ranges from by default this has a width of 30 the button and then it goes to zero because then it's not taking up any space anymore okay and then we can return this in our Styles here opacity and width okay button is here you see that works actually pretty good already good uh now we need to do pretty much the same for the button view style only mentally switch this around so if the expanded value is zero then my three buttons shouldn't be visible so that means um this should go to zero then it should go to one and in terms of the width it should go from zero to let's say 100 uh and then I can return the width and the opacity okay I just noticed that for the opacity interpolation I'm not really mapping anything I'm mapping Zer to zero and one to one uh which means this line can be removed and instead I can just use expanded uh [Music] expanded do value uh that's completely the same all right here we go um let's see um I can do something okay this is let's refresh maybe we're wrong here okay let's see um the expanded button style is now set to a width of 100 uh which does sound quite good to me however let's see the button view is down here animated uh we have that row we have the round button and the expand and button button view style button view I feel like it's some point we are missing something but I'm not entirely sure where that's the case uh the message input is taking up this um this is the touch level opacity at the end that one's not really important this one has the right styling as well on Focus I want to collapse the items well that shouldn't be a problem so we see something is actually going on but it's also not entirely correct what's going on uh we can also remove autofocus for the moment um should expand it start with one that's a good question I don't think so um did I got that one wrong so expanded value goes from 0 to one um the expanded buttons style goes [Music] from uhoh uh I think I just removed something I think I trolled myself somewhere along the way right here um let's see I want to go back in history um yeah right I don't want to remove that one I want to keep the opacity up here uh the expanded button style should actually go from one to zero that is correct but for the button view style the opacity should be like this okay we're starting at expanded value zero that means my opacity for the expanded button style should be one where is my buttton uh uh okay I don't know why exactly this happens right now um pretty nice good really good catch uh right here from Expo so if you're using media library and stuff you usually need to request permissions I didn't do that and so my app got really mad now so we're going to add the no I'm actually not using the Expo media library um I don't know I'm not even using the Expo media library uh what is this um app is missing either uh either sure both I mean yeah they are kind of missing but it's not really important so this is about the iOS permissions and I don't really care about them right now it should work all the same I don't know okay so again my WID interpolation is fine um maybe maybe just maybe um we're doing something wrong somewhere uh yeah the button view I don't know where I completely messed up the stuff like this should be the expanded button style and this should be at the bottom I don't know how I mix that up so uh the expanded button style honestly I said this before I said I'm going to troll my myself so the expanded button I will just copy this from my existing code then not messing myself up okay the expanded button style up here uh maps from zero to one one and the width of 30 and this one just goes for the button view Style Just changes the width so uh this should work finally okay here we go uh let's also open this up the default State button is here I click it it reveals that stuff I start typ typing it hides the stuff was that so hard I don't know um I click this button it appears and it hats I really like these micro animations and I also hope that you enjoy them I made this more complicated than it is I think these are just the most important pieces and up here we have our width timing function maybe we should put that together so you know what's going on uh all the reanimated stuff is now here it's just like it fits on almost one screen uh everything that we need to animate from one button to three and I think this is a pretty cool animation um for our app we also did a lot in terms of making progress so I can type um and I can send this and if I check the logs we get getting completion for something so that means the text from my message input is already reaching this page here and that's is a good sign because that means we can now continue with that chat page to implement the chat UI and then very soon make request to the open AI API all right so before we actually make request to the API we're going to prepare the whole chat View and we're going to do two things now the first one is that we want to build this General view which means we want to have this as a component and this as well so it should be reused basically a message in the chat which has an image and some text and it can expand that is Task number one task number two is that I would like to have these sort of recommendation cards here above our input um this is a scroll view so I can scroll this to the side and once we have a chat you've seen it in the previous image these will disappear and when I click them I should also of course send that message later to the chat and we also probably have a little logo up there so you see all of this is preparation for later just attaching the API and then displaying the stuff of course that is exciting but we're going to get to that trust me so uh where do we want to start do we want to start with the chat message or should we start with the message ideas huh that's a good question I feel like we we we can start with a chat message idea uh for that let's get to our components and let's do a new one and call this message ideas. TSX okay here's it then I will start with an actual array of some predefined messages okay these were the ones you just saw in the uh picture you can of course use something else as well we also want to make sure that we can um uh that we can click on these and uh the parent component can work with like the text send that text to the API so we're going to have a type props up here why is this not getting me code completion usually I get like night something okay so let's say on select message um well I want to call this on select card because it's like a card here okay but that's a card and then I'm we for this okay then we can get that in here so unselect card this is like the the most like thing I hate it already knows in this place that I want to use these props all the time so it could definitely autocomplete in that spot anyway uh rank native Styles sheet goes down there and making sure we see something let's put the message ideas into our chat view I will actually put this into the keyboard avoiding view because if we're not doing that it might be covered by something else yeah I think we should put it in there so let's put it into that place and um do we have a messages array no we don't we probably should uh messages set messages okay this is not entirely accurate I will give it any right now um but for the moment that should be okay so if messages. length is equal to zero then we're going to use the message ideas component and on select card I want to call my get compl comption okay so now message ideas should show up at the bottom of course not styled or anything by the way I just noticed we have the messages array and I feel like we could need some interfaces for that uh let's probably do we have a utils folder or something let's do this let's do utils SL interfaces. TS uh I will put my interfaces all in this one file simply because I will just have three of them if you're having a big application with tons of interfaces probably have one file per interface like there you know the react ecosystem there's not really a rule for this uh but in my case I will just keep it in here of course that is convenient so you just have that one interfaces file and everything's included okay so a message can have a role role is an enum with either from the user or bot I could also call this system but I don't know I just like the wordbot um the message has a role so who sent this the actual content it might later have a image URL and there might also be a prompt inside of it uh just keeping track of that and finally later we will also have chats once we store them so they will have an ID and a title that also means once we have that file we can change any here to message and use our interface uh won't really change anything right now uh but should be fine for the moment uh we can remove that we can also remove the dummy content um as we're just working on the message ideas for the moment uh we got the predefined messages so let's get into this now what we want is of course a scroll view component that we can scroll horizontal so horizontal scroll uh let's see what copilot made here um I'm honestly not sure I just don't want that like this uh do we have the col closing Tech no we don't here we go so for every predefined message we have the message and the index and we're going to use a touchable opacity touchable opacity from react native key will be the index of course uh and on press I want to call on select card actually I want to use more than just that uh I will not only send the message text I would like to send both the title and because this reads like explain react native like I'm 5 years old so we want to send that whole sentence to open AI That's why you do uh string letter Ral here we're doing two uh objects in there and we got item. title no it's message right yeah message. tile and then probably space and message message. tile and message. text is what I wanted to say before I thought I hit a shortcut to stop the video but in fact I had just one gigabyte of space left on my hard drive so I was kind of lucky that my computer still works and now I got a terabyte free after removing all the videos I did in the past so here we go I feel so much lighter now uh and we should have our touchable opacity ready with our key and onpress now what I want to put into this is pretty simple I just want to have two text Fields the first one will have message. tile and the second one will have the text okay so message title message text and of course this touchable opacity should have some styling I will call this styles. card uh so let's put this down here in our stylesheet and for the card I just want to set the background color to something like um colors so importing our colors and then I think input should work here for the color some pading of 14 we don't need margin border radius yeah that's a good idea okay so I think this is not too bad for first draft um what's the problem here uh the problem is why do we see the scroll bar I don't want to see that at all uh let's get into the scroll view so if you want to disable that go with shows horizontal scroll indicator fault okay that feels more natural not like a browser and then if you want to style the insides here we can go with a Content container styling uh we probably want to have some petting horizontal of like 20 okay so that moves it to the side I want to have gap between the items I think 16 is a nice number we had and then I want to also have some petting vertical uh let's put this here petting vertical of 10 yeah that looks good okay cool nice we can click that stuff um we probably should see a lock for that so let's see yeah we already get there because we connected that correctly uh we're clicking here we're having on select card and on select card is triggering uh get completion cool now the only thing missing is that I want to make the title a bit bigger here so let's go with another style uh let's say font size 16 so making it a bit bigger and font weight of about 500 uh feels about right uh what What's the [Music] problem um what is the problem um font weight is oh it must be like this yeah of course of course uh for the other element I would just like to set the font size to 14 so making it a bit smaller and then eventually also changing its colors to colors. gray so it's like a bit more passive color okay I think this is cool uh this is a nice thing also this should yep because we put it inside of the um keyboard avoiding view it stays on top here okay we're good with the message ideas now let's talk about the chat message for that we should also do another components I really like to do a lot of components in in this cologne simply because um we can reuse them in many places and we don't want to keep all the code in our files here uh that's going to be a lot cleaner um okay what is the chat message getting the chat message is most likely um getting a message so we can destructure this how could I do this like in a good I mean I could do it like this um so then I would have to access all everything from message I don't really like this I want to do this couldn't you do this automat ially you know the interface like why you know that it's content it's Ro it's no it's completely wrong what's what's your problem co-pilot I don't know sometimes you're really really good at what's going on and sometimes you're just horrible I don't know okay so this is my chat message um I just noticed that I should like I need some some dummy messages is right uh I don't think I have a reply somewhere uh let me see if I can dig something up in my previous code but I think I did not hit save on there um that would have been so good such a good idea to just save that nope no why should Simon hit save when he has a good idea no not okay so in my new chat uh we want to see the chat because it's going to be really hard to develop the component in like isolation I mean it's working with a react native ID we could probably do that but I'm a bit scared to do it honestly so let's come up with a little array of like cons dummy messages now let's do this dummy messages exactly they're going to be of the type message so maybe copilot is no helpful um this looks somewhat okay only that we have to use the right enum here so we have to use the enam roll dobot uh and ID is not required okay we also don't really need the image URL and the prompt is um I don't care about the prompt okay so let's simplify this a bit and this one should be roll do user uh user and then we probably we're already good like with two prompts uh we don't need anything else because this should help us to develop our component we're going to put this here for the time being and we also going to remove our sign out button we don't really need that one right now what I want to use now is I actually don't want to use I just don't want to map the messages or something I want to use fles list this is usually the most or the fastest way to use uh of a scroll view or flat list or something in react native so let's install the flash list that is done pretty easily and PX Expo install at Shopify flash list the only problem is I think we have to kill our server for a second um then bring it back up again but we going to make use of that okay uh the good thing is that this usually or I think it right does it still require a custom build uh maybe it's also included in Expo go I don't know exactly but we're in a uh we're using pre-build and we're using Expo run so uh we don't have any problems regarding native modules so let's put the flesh list to use uh we're going to do this in our view here um this one should actually have some styling as well so we're on the chat page uh let's put stylesheet to the top in the right import here and then let's do a styling for yeah like the the page styling is just Flex one that's okay um I want to have something as well like if messages. length is equal to zero we wanted to render our logo as well so let's do end end and do another view style uh let's see let's call this styles. logo container we don't have that yet but we're going to have that in a second hey I copied logo container not stylesheet here we go okay let's see if we can close this and make everyone happy for the moment yes we can um this is going to be somewhat challenging let's try and put in the image here uh why am I not seeing anything uh shouldn't I at least see that text okay because mes that's where the trolling starts because messages length wasn't zero okay now the length is back to to Z uh let's quickly get in our image I will actually use this so this is the essay we can use require right in here not the coolest way uh but usually that works and we're going to put an image down here so uh property image does not exist yeah then just edit come on we're living in the year 2024 if something doesn't exist just import it it's not that hard I don't know okay let's use a really small width of like uh 30 and a he of 30 as well and I want to use the resize mode no this is not the resize mode where is it where is my the logo container does seem to have a problem um where are you align yourself in the center and uh let's say let's give this a specific width as well uh and heit okay where is it where is the logo container and where is my image the image should definitely exist and the logo container does have some hate I want to give this a background color let's give this a background color oh I know the problem T it was a white icon on a white background I don't know we're all making these mistakes I at least I hope I hope we're all making them it's not just me okay let's align this and justify content should be Center as well so then it looks correct we could of course also just have the right icon then we wouldn't have to create this logo container in the first place but that would be too boring right you're not getting the right assets from your designer so you got to make work what you get uh and we'll also put this to cover uh doesn't really make a big difference here now what I want is I want this uh to have the right offset from the top um let's see we can do this if I can use margin top and I want to set margin top to the he of my page divided by something um the hate of the page is changing sometimes because if we use this it would change so I want to try if we can get that I don't know if it still works in one version it did work in my tests but later it didn't so you can also use the window hate but as I said it might change here now would like to keep it always in the center just not sure if it will work okay um we can get the hate um and we can get this with a little trick here so let's add something in here we're going to call this const on layout okay we're getting an event uh let's say any I don't have really any typings here and we can now get the hate from event native layout so I will lock this out uh and then I'm going to set my Hate to this okay now we can for every view actually use that on layout so I want to use this for this one box here and say on layout please call my on layout function uh we'll just give this margin 10 for the moment and we see now it's 750 something yeah apparently the absolute layout here does not trigger another on layout that is sort of a Pity uh but honestly we will make that work uh nonetheless so let's use hate divided by two so we got like we should be here but we also have a he of 100 so let's use minor 100 that should most likely be the center we could now probably listen to the on keyboard Show event and then trigger that as as well um they like react native on keyboard show um let's see here we go keyboard uh we could have a listen that keyboard did show uh and put this into a use effect let's see if that works uh I haven't done that before okay so use effect from react uh show subscription we have to import the keyboard and then I just want to like lock this um or maybe I just want to call like my on layout here that would Ah that's probably yeah oh yeah it's problematic that's not going to work exactly as I plan to so keyboard hidden keyboard hidden uh keyboard shown yeah we do have keyboard shown in keyboard hidden events however we don't have the hate of of the view at that point are we getting like an event here or something uh let's try let's just try it let's try like we don't know if it's going to work um let's just do this okay probably breaking every every rule there is yeah uh okay we shouldn't do that like this um so how can we like get the hate at this point I would love to call on layout but I don't know how we could get the exact view hate at this point native event layout hate EV and coordinates hate okay this is interesting copal gave us an idea here um why not why not test it we we can't do more we can't fail anymore yeah okay on layout hate minus 33 th [Music] um yeah we might now have a problem with use effect and States here um so yeah this is probably an idea for you to improve this I don't really want to do it right now we could have done the on layout stuff if our stuff wasn't in in an absolute position here so if I would commment that out this stuff would probably work better so now we should see that yeah in that case we actually trigger the on layout again uh we're just not triggering it if our styl is absolute which we wanted to use because we have a blur view so you see sometimes there are trade-offs you have to make uh in applications okay back to the topic at hand uh which was displaying our messages let's use the dummy messages array here so we have some messages in our view and then we want to render The Flash list so let's put the FL flesh list in here flesh list uh we want to render the data Let's see we got some some stuff going on here already it's not completely true okay the data is our messages array that is definitely true for render item we want to use our chat message component and we want to put in all the properties of our item uh usually for Flash list they also require an estimated item set size that's kind of hard because chat messages are different but let's use 400 as an estimate uh and then we have a key extractor I don't think we need that one um let's just keep it like this for the moment okay we see two chat messages that is actually a good starting point so now in our chat message we can do our stylesheet here we go uh the only style we need is like a row styling because you know we got a flex Direction uh Row for the items in the view so let's say this one has styles. row and then we have the image so let's check for the role first um could we yeah we could probably if we had the right icons we could do this if the roll is equal to roll let's use our interface dobot in that case I want to render a view for uh the bot image otherwise we're going to render an image which is my own mirat image okay this is like the user image it also means we need image up here and we need the Avatar styling which I haven't defined yet so the Avatar styling should be something like uh with 30 he 30 border radius 15 and maybe a background color I don't know if we need a background color okay this is here do we need a background color was just wondering does it show up anywhere not really not really H I don't know looks quite okay to me by the way the roll should also have some margin included um let's do uh let's see now let's let's create the stuff first and see what works um we don't have the the bot yet so for the bot image uh I want to use uh the white logo so we have the same Danse again um I will use styling button image which I will Define in a second because we had the button image styling before in our app which was like this uh the only problem here is that our view now requires a background color again if we had the right icon which I should probably have just created that would have been a good idea uh let's call this styles. item I will put this in here and the item should just have like a border radius of 10 and um overflow hidden because otherwise we can see the difference in a second so can we finally see our background stuff now that would be really really cool um let's probably also give this the background color black and then we see at least the logo up here okay that's a good starting point we should also put in our text so text Styles uh. text and then we have the content this is actually the easiest part and then we just need to align the stuff correctly um I will give this like a pading of four and for the moment keep it like it is okay not too bad we should probably have a bit longer message as well so I want to make this one here uh no um okay okay we got the longer message so now it becomes better let's see uh we also see a few problems here if your text is Flowing out of the bounds of your view uh then what you want to do is you first of all you want to set the font size this is not changing this uh but what you want to do is you want to set the flex VP to VP and then you set Flex to one and you see how this aligned our stuff and make sure we're just using the available space here until the end of the view and then we're wrapping the content okay we also need some uh petting margin stuff between our items so let's say for the row I first of all want to uh align the items actually not in the center that would align my item here here I want to do this with flex start so then would always be at the top then we got some petting horizontal can't hurt to give this some space I want to have some gap between my items okay and I want to have some margin vertical let's use something like 12 so we got like the margin vertical is here between these items we could also have done this in the list but yeah should work as well in here okay the item uh let's actually use a bigger border radius yeah that makes it round then we have the button image we have the avatar for which we actually don't really need a background color that doesn't make a whole lot of sense um and I actually think this is pretty good like we're going to come back to this later once we have image URL prompt and also uh like a loading thing going on but for the moment I think we can leave these messages as they are um also in our chat view just want to check the flash list one last time so if we would have more stuff in the view uh let's put more in so if we would have some long text we can already see that our blur is finally working in our bottom message input but I still feel we should have like an intensity of 90 I think 80 is not enough this already gives us a nice blur effect so 90 should be fine we already see that at the bottom we do have a problem because we have our input there so let's go back to the flash list and attach some content container styling here um I want to use a pading bottom of50 so that should render everything correctly and I also kind of feel like at the top we should have a bit of pading uh pading top maybe yeah maybe 30 okay I think that looks pretty good we have the blur working we got our messages so once we start render something real this should actually look pretty good now there's one more thing I wanted to show you and that is um if you have this open in iOS applications you will usually notice that if you do like a little gesture you little fling down here it usually closes the keyboard if you want that behavior it is so unbelievable easy you sometimes just have to know what you're looking for like find the right words so on flash list and also on flat list there is something called keyboard dismiss mode and you can set this to on drag if you set the keyboard dismiss mode to Onre you can do this and this feels just so good to have this thing working with one line of code sometimes react native is just blowing my mind and like in terms of the stuff they implemented and thought about um I would have thought that oh I need to gesture head and catch some events no it is just keyboard dismiss mode on drag I actually don't know what is the other on drag interactive what is interactive keyboard is dismissed interactively with a drag and moves in synchrony with a touch dragging upwards cancels the the missive that sounds interesting as well let's give this just a try because we're we're curious um yeah well um interesting but we do have a problem with our message input and the absolute position in that case so let's go back to Onre I think that's fine for the moment uh to close our view all right with all of that preparation done let's take The Next Step uh and moving closer to getting API results I swear we're soon making request to the open a API but in order to do that you need a key and usually you don't want to provide your own key in these sorts of applications so what we want to build is a simple input on the settings page where the user can input the key and I think you also need an organization by now to do this we of course also need to store that key and for that want to use another great package which is react native mm KV by micro saavy uh react native mm KV is like the fastest way or fastest key value storage um for react native you see the The Benchmark here between the different solutions um for small things mm KV is the best there are some downsides and we actually later going to use SQL light as well but for the moment let's just not talk about that and instead kills run npx Expo install react native mm M KV and once it's installed we can quickly bring up our application again so with that imp Place uh let's see how we set up mm KV for that let's create a new file and call this storage. TS and in that storage file I want to import mm KV from react native mm KV and I want to export a con storage using new mm KV and then you can put in some configuration if you want to uh like an ID or an can you do an encryption key by now oh that's pretty cool I don't really do I want to do that uh M encrypt by default store all key text r on to make sure file is encrypted should you worry about information leaking you choose to encrypt mm KV um you can choose to I don't want to do it today uh so keep the idea to what you want and if you feel fancy try the encryption as well however I will not do this right now but what I want to do is on the chat page I want to implement mechanisms so if the user comes to the chat page and does not have a valid key yet and I want to make this array a bit shorter because this is kind of annoying um also we could get rid of the dummy messages honestly we don't need them right now anymore um if the user comes here and does not have a valid key we want to to guide the user somewhere else so let's do this and for that we can actually use hooks which is pretty cool so I can use key and set key uh equals use mm KV string uh I don't know why the import is not yet working uh should usually work uh let's see where's the good mm KV from react native mm KV here we go there few other hooks like get a used number probably uh but we're going to use it like this so I want to just call this API key uh and we're going to use the storage that we just defined uh a minute ago when we use uppercase or lowercase storage it doesn't really matter that much okay so this is my API key then I also want to have the organization set organization uh this will use like or from our storage and while we're here we can also persist what we initially did up here with that selection of the GPT version so let's also bring in GPT version and set GPT version Oh we actually have that already but we're going to replace this now with the mm KV string from our storage cool we see this is right now not selecting anything that means we should in in our header drop down where we have this function right here replace this and set actually we should not actually we should just select it once and then we should be fine yeah now it's stored with mm KV and it stores this so if I select this two4 and refresh it will now actually stay on GPT version 4 uh also this autofocus of the input field is kind of messing up with my logo a bit but as I said before let's a story for another day so in this view what we can do now is uh it's probably not the smartest the nicest thing to do but you can like have a hardcoded if there's no key um or let's do a little check or key is equal to an empty string or you have no organization or organization is empty in one of those cases is true I want to directly return I don't want to return this view I want to return a redirect from Expo router and use the hre to go to my settings page as hard as that so you see we're coming there we don't have these values and I'm immediately brought to the settings page also that settings page should be displayed as a model so it is in the model folder uh we just need to go into into the right uh layout file here and Define for the name okay what's the name that should be like uh model slash settings uh I want to Define some options here so of course header title settings thank you this is not required okay yep but most importantly I want to have the presentation model so if I now refresh the app and and that's not entirely what I want to [Music] see why is this not coming up as I wanted to um maybe let's get rid of that redirect for a second uh and let's just go to the usual page and if I then select this it comes up as a model so maybe it was like sort of a caching issue okay let's let's hope this is it uh for that model I want to affect a bit how this looks like so let's make the header Shadow invisible and let's use a different header background color okay so now it's like one thing if you remove the header Shadow you get rid of that little border and then we probably need a button to close this because I also want to make this work on Android uh where this is going to be full screen so let's use a touchable opacity from react native on press I want to use the router do we have the router nope so let's add the router use router okay so on press we do what we did before router do back okay and then we also should add um something like an ionicon uh name close yeah well probably not name close I'm like close outline more um size white is also not the right color for something on a white background as we have learned previously so let's use gray and then let's see if I open this up uh it's not opening up anymore that's that's good that means okay yeah we do have it up here um size 16 should be enough actually that is very small that's a very small thing m maybe we going to use what we had before what did we have before 24 um but we also want to give the touchable opacity a slight background color so let's use some styling here and let's set the background color to um colors. graylight so we have this little background that's also yeah I want to make the button smaller and I want to give this a border radius of like 20 I want to make this a rounded button yeah okay we're getting there some petting okay yeah that looks somewhat like it should be maybe we could petting like six to make it even bigger yeah I think that should be fine okay that is the general setup for the settings page now on the settings page where is it actually here there's nothing that's great okay so we need some styling here and I want to make this a bit quicker because this is a super boring page this is also not really a page of the official um C GPT app that you're going to have some sort of O outflow with the open AI API and then you're connected um this is more sort of like all the other clones out there which make use of the AI and make the user usually put in their key so really I want to go through this as quick as possible it's just about like putting up a field here now on this page or two fields and a button to SA save that key that saving might actually be the most interesting thing so I highly recommend you check out the explore or the settings page not the Explorer page on the GitHub repository okay so in that view what we want to do is um we're going to use our mm KV storage once again so let's already bring that in because we know co-pilot is not doing it for us and then we should use our key and organization stuff again in here using the storage we defined a second ago so this comes storage from utils Storage cool uh view will first of all get styles. container so we're getting a bit of petting here um and now we need to check if we do have a key um and the key is not an empty string so I just want to really make that sure in that case we can render a button to like with a text um you are all set okay and we're going to use the style style. label is just some label styling we don't see that text yet of course because we are not yet set if on the other hand uh we don't have a key or the key is equal to an empty string in that case what we want to render is the input um so I want to have a text on top of that so I will use an empty fragment and then we have the text so API key and organization and then two text input Fields okay these text input fields are simply uh connected to my API key okay I called this key let's call this key and set key and or uh organization and set organization okay why are we not seeing anything it looks like we haven't loaded the according values or what are these values like oops what was there that was interesting as well certainly not what I wanted to do um can we just lock this uh an organization maybe maybe my app already knows this no it's undefined um okay undefined is not great great uh but it should be caught by our stuff if we don't have a key or this is definitely the wrong place uh we don't have a key or key equals to long do I really have to put this stuff here in Brackets to make it work uh and this then we got this uh one too many yeah that's better okay so I just had the brackets in the wrong place we make sure that this is put in the right brackets okay so now I can enter my API key and my organization in here and we also of course need a little touchable opacity after those input Fields again this is not super interesting so let's add all missing uh Fields here and Define our const save API key function okay okay uh we're using our default Styles I feel like we got the button wrong no everything is just fine copilot really figured that one out and this is also the place where I want to use the on sign out so I can now remove the locks and instead bring in uh the sign out once again from clerk so sign out using use off and now we can use the button we had before to sign that out of course button from react native so finally getting the sign out button back now the cool thing is in uh what oh sing out yeah we don't want to sing out in Here sign out it's what we want to do oh my okay so if you want to save your API key up here what we need is simply to call the according functions so I want to call set key with a key and I going to call set organization um in fact aren't we doing this no we we actually do this we kind of store them as we type um these might actually be saved already so we might not need these lines so maybe you can get rid of those lines uh but anyway what we need is the router so we can like manually route the user back again uh once this is done so probably these are obsolete but the next line is definitely not so router. navigate once we've finished we want to navigate to uh where do I want to navigate and why am I not getting code completion two questions in here uh I want to navigate to or and the draw stuff so that should be draw rest should be figured out automatically in where we want to go cool uh we also might want to supply something in case the user wants to remove the API key so cons remove API key comes in here and this uh comes right into my view here if we do have a key so after the text I'm want to put in another touchable opacity which also means I need to wrap this in an empty fragment because otherwise R native will complain so here we go now we have the text and the touchable opacity to remove the API key which would then simply call set key and set organization back to empty good with that in place let's see uh yeah usually we're not seeing it like this so let's see we're opening why is this opening why is the redirect here from expore router uh triggering like not really triggering the model uh it's not triggering it as it should be I don't really like that uh HEV o modal settings this does look right to me uh what is wrong here I mean we kind of we we kind of shouldn't close this I think it's actually okay to have it like this and just not I just don't completely understand what's going on um why is this redirect not showing a model we do have the presentation type model set in here um presentation we have the draw we have a stack we have modal settings is this correct do I need like no modal settings settings uh presentation I honestly I'm I'm a bit puzzled I don't know exactly um we could definitely also attach something in here so that we only see this um so if router dot uh can go back something like this oh come on yeah if I mess up this stuff here it's going to be horrible um okay let's place the touchable opacity in here if the router I think I can't access it like this right Uh something's getting mad about this if I just put a fragment around this it's probably working out better so if router can go back then we want to okay so you see what's going on now it will show that page and we can't go back because we also shouldn't we should just simply insert our key in this page so let me insert some testing key that I have um okay yeah that's certainly not what I want um okay let's check again the settings page what do we do wrong uh if we have a key and the key is unequal to this okay yep I see automatically setting the key with unchanged text set key is probably in this case not the best bet and we should only do it once we are really done um so let's remove our API key let's do a refresh and check again if I now enter something okay now it's not okay okay yeah I understand let's use another um that is why I had in my initial code another state the problem is that if we attach these to our input field we will immediately write them to mm KV because it's just so fast um so let's just use a regular State for the moment and we're going to attach uh the API key in here so API key and unchange text unchange text we want to call uh set API key and down here we're going to change this to or and onchange text to set or so now we're just setting the state in our component we're just setting this and once we hit save we will finally call set key with the API key and with the orc okay that should get rid of all the problems so now let's try and do it again I will paste in my stuff here and I will also put in an organization uh here we go and let's hit save okay this does not know where the draw stuff is um do we actually use the right router because it didn't have code completion that made me kind of kind of kind of scary router dot now it should actually be fine we got navigate we got push um by the way with push it's working that's interesting so may we just do it like this okay now we're also allowed to insert that page let's check again here we are you're all set uh we got the buttons so that looks good that looks good to me um and we have our API key ready now with that API key in mm KV storage uh and also with the GPT version we are finally ready to make some real requests all right it is is finally time to use the open AI API so you got to create an account here uh if you want to test this you can use an API key and test this for free I think uh up until a certain amount of requests uh or like like some requests are pretty cheap to make usually what you do is you install the open AI uh note library and then you make requests like get completion uh create something this is pretty easy you can do this and yes we could do this however I wanted to add a little like a little touch to this and make this a bit different and therefore I will come back to good uh kendle Finance really great stuff they put out here from Gary they have an open AI package that allows to stream the result uh it's not like everything included only chat and images so far but still it should be enough for our case so let's install this uhhuh npm uh or npx Expo install just to make sure it works with our current version uh we're installing this and the usage looks like this we import open AI so let's do this and let's also bring up the reload here we're doing this now on our chat page of course so we're adding open AI then we creating an open AI instance uh we can actually use memo for that so let's put it in here here uhhuh okay can probably tweak this a bit so let's tweak this uh con open AI equals use memo and then uh is that correct uhuh equals new open AI key actually we should say API key is the key uh and organization should be fine we don't need any dependencies here uh and this should be an object uh cannot find name No it should be fine like this okay so with use memo we're putting this and memorizing the stuff and now we can use open AI to stream result uh you can use your own backa not hardc okay yeah that's something different the way it works is that we should set up um a listener okay we should listen for messages and then attach them uh and we like stream the different content results and store them uh it makes more sense once we do it probably let's start by closing this here um and then setting or starting with get completion So within get completion we can check if the message uh do length or if messages. length is equal to zero in that case I want to add a new chat later okay we just going to keep a note uh create chat later store to DB so we can keep track of that um in the time until then what we need is okay for getting a completion we should push that first thing that we've wrote most likely to our messages so we can say set messages and we want to reuse everything that we have currently in messages and then we have content uh that is the actual message that is correct and the role is user I also want to directly push another message which has the uh rooll roll dobot and the content is empty why why are we doing this we are doing this second message so we can then catch in our streaming event and just fill the last message in the array okay so it will look like this we have a use effect block here now we're going to do this and this will have open AI as a dependency here that means whenever that changes we're going to see something um this is not yet working so we're just setting our local array okay there's something still missing um then what did this what is this I had a line for messages push I don't know I just hope we don't need this because it's empty okay and now we can use the code actually Gary had on this so open ai. chat. stream this will allow us to stream the result and this requires an input a certain input so the first value here is an array of messages what we want to send there is of course my RO user um I'm going to have to do it like this roll user so you can now use assistant system or user this is also how you could Prime the system while like specific inputs you are a Storyteller please reply with this and that you know all the AI prompt hacking stuff uh the content is the message here after that we also have to supply the model so the model in our case is is that string correct um it might be but it also might complain so let's do it manually so if my GPT version is equal to four actually this is a string in our case then we want to use GPT 4 um and otherwise we want to use gpt3 turbo okay this is everything to trigger a reply and to stream the stuff from from uh open AI now we just need to correctly manage that in our use effect where we get that data and this is going to be uh somewhat challenging so we can create a function cons let's call this handle message we're getting a payload here okay there we go with this we're going to do something now we can tell open ai. chat. at listener so whenever we receive a message this is not the right type um can we get this on message received nice we get typings we use our handle message all right and to clean up after ourself you know that in use effect you should return that subscription in the a uh end so open AI chat remove listener on chat message received we don't have to use that again so this is the basic way of catching this maybe let's put a lock in here received message if we now send something like explain react native like I'm 5 years old we expect a ton of locks here because we're streaming the results so we're triggering this uh we're pushing something to our array and then we're streaming the result we're just not adding it to our array yet let's try it out uh or maybe let's open the debugger because this might be a lot of messages and that might look actually pretty cool in here um okay can I zoom into this no I will be too fancy all right explain okay we added that message we also added that empty message for the bot user here um we're not really getting any replies I would expect something here now which certainly didn't happen um could have multiple reasons could be that my key is wrong or that it just took a moment so here we go tons of messages and they all have choices array and there's content okay if we know go somewhere else like here you see there are like words in the content really so that is what the streaming is doing it's just giving us some chunks of content we check out different ones here and we have like use here's in comma okay and we're going to piece together all of that to give the T sort of typing effect that you're used to so we're going to make that the text appears here while we get it back from this streamed result now this is somewhat tricky um the problem is that we need to update our messages array in the right way and we're using a call back here I encountered some problems with that in the past uh we shall see how good that works I I think I had a a problem before but let's just try it out so we're getting back a lot of messages and we're going to update our messages now not directly to an array but we're actually going to use the previous messages that we had and then return a function I think that will make sure that all of these updates are executed in the right order so the new message is now equal to payload do choices add the index zero. Delta do Delta I don't know could we get uh let's see can we bring up the debugging again nope we can't apparently what is what are they doing uh we got a message they don't add any sort of um typing here what is the payload type has implicit type any what should it be is the question uh question of AD listener is chat models stream output okay I might use chat [Music] message uh that's not working really great that's not working our favor um I don't know if this is exposed this type I assume it's not uh but we can try to get chat models here from yeah it's not exposed yeah we can't do it like this we could set this up for the moment we're going to have to do with any and to fix the problem here we will just return messages for the moment this is going to change so we're updating our state that's the whole idea now if we do have a new message so if there's something in that message I want to change the messages at the last index so remember how we added that empty block here for the bot this is now the place we want to stream in the content so length minus one will Target exactly this block here and we'll set the content here to plus equal new message so we want to add the message at the end and then we want to return um everything inside of messages using the spread operator uh I feel like if we here this should have a closing bracket and open okay why is it here okay now additionally one more thing is that if the streaming has finished so if payload do choices at index z uh has a finish reason then then uh let's put this it has a finish reason in that case we want to uh save the message this is important once we got our DB up and running for now we're just going to put in a lock um let's just say um stream ended okay this is just for ourselves in the other case uh whatever if there's nothing we're just going to return the messages down here good I think that's it so far let's hit save and let's see I want to reload that page and then we're going to do suggest fun activities going to hit that and we should see nice everything's coming in streamed to our application ah that feels so rewarding we've been building up ours to have this working we could have probably done this in like the first thing but I wanted to keep up the the excitement and now we finally got this one uh working in our favor I feel so good let's grab a coffee and you know sometimes you just got to appreciate these moments when stuff works because as a developer so many times things are not working you're frustrated you're debugging you got to also cherish these moments when things work so this is cool good [Music] job also thanks again to Kendall um for providing this open AI package I think there are probably more packages this is relying on some native technology to stream that and I really like that approach um for us that was a thing uh a lot of things are now coming together and that page looks really really cool I think um we can also get back to a new page later as I said we will have the option to store that stuff but for the moment that's pretty much it U we can't get back to that page that's by Des design don't worry about this we're going to come back later to the storing and the whole mechanism of selecting a previous chat until we get there we're going to take a little side side step because there are two more things we want to do we want to have our Deli view which works sort of the same so we can reuse a lot of the code and we have the explore gpts page on which we want to do some cool loading stuff and eventually we also want to add some purchases with Revenue C the other sponsor of this video so there's still a lot ahead and I think for the moment play a bit around with our chat but then let's get back on track with do getting completions from DOL meaning getting images from open air is pretty much exactly like almost entirely exactly the same we just need a few tweaks for our Deli page so what I would like to do is I would actually like to just bring in everything that that we have in our chat um so we will start with the Styles uh putting them down here we can also add pretty much all the same Imports we had uh before uh and then also use most of the stuff we had in our new chat page in terms of this logic in terms of getting the completion in terms of handling the messages and on layout and actually also the view like I will wait with a view for a moment uh because I don't want to mess up everything so that should be fine for Dolly um for the dolly page we have the page container we are setting our uh yeah we're setting a bit different header drop down basically but we also do have this uh logic here with a view we do have a flesh list and we have that bottom stuff so let's bring that in as well to our Del page and then we are pretty I think we should have a really easy time um we don't need the stuff with the message ideas in this case so we can close that um and also for the image um I also would like to display a little label below that um so let's put below that or let's maybe go to the dolly page we should already see that let's put in a label let me turn your imagination into imagery and that label will just have like a little gray color but beyond that we're pretty much reusing everything we had before okay uh and we should also add text of course because we always need text yeah where is it here we go text okay this is the chat GPT page this is Del uh this is not entirely correct so let's maybe check out the logo container uh align self Center Center maybe let give this a bit bigger withd and and ah okay yeah we also probably uh want to use a different image here so we want to of course use the uh Del image in this case from our settings um also this container here needs a little bit of gap between the elements otherwise our text will be included in that one uh also um yep we need to split this up this is not working we need another view uh we'll put that view around this here this view up there will have the uh margin top stuff and this one will have only this one okay view style equals uh margin top and probably align items in the center and then we have the logo component further down uh let's go back there Del okay yep we still need the Gap stuff and then the text shouldn't be in the logo container okay that's getting better now we just need to fix our logo container so the logo container so far had 8080 border radius 50 um for the image I don't want to make this so small I just want to have like uh like this size mode cover and then we set the Overflow here to Hidden which should limit it and then we set a nice little border color and then uh we once again fixed everything that got wrong with the image that we got from our designer okay Gray light uh and probably a border width of something border withd of let's say one okay here we go let me turn your imagination into imagery we can do the same stuff because we still have our input down here which is pretty cool a reusable component that really helps and now we just need to tweak our uh get completions and how we handle the completions so getting completions let's say we have a mode where um the page is working so let's use a state working and set working this should like give us a little activity indicator if if we try to get a completion I want to first of all call set working true then um yeah want to get the completion for a message we can get rid of that and I also don't really want to do the saving here we're going to later just do this for the chat then we're going to do the same we are adding the user message uh but we're not really adding the bot message yet um instead uh we're going to try and um get the result yeah we're going to actually not stream it this time so what we do is cons result equals await open AI do image. create and then we need to put in our image stuff I think there's only the prompt expected um and then we can already lock the result if we we want to um for testing I would also like to use some dummy messages on this page so let's put up a dummy message up here rollbot no content just the image URL and a prompt so we're going to have to handle this in a slightly different way let's use the dummy messages here and now we need to get back to uh our chat message rendering function so where's the chat message we have the flash list we have our chat message render item estimated size uh keyboard on drag all of that is still fine I think we can just go to the chat message inside of this I would not also like to have a loading prop included um we can do this by saying okay this is a bit of typescript fun so bit ugly Maybe uh loading Boolean so making loading optional and not messing up anything else okay so now we have a loading value included here as well um if we are loading and we're rendering a message with loading that should just like display this little uh loading indicator we're going to do this probably here if we are loading um I want to render a simple view with style styles. loading I think we don't have that yet but that's not a problem and then just an activity indicator size small and for the color I want to use my own colors so colors dot let's use primary we haven't used primary a lot yet and then we close that view um as I said we don't have the loading yet we're going to fix that in a second just make making sure that if we're not loading we're displaying this text uh I think I need a m up yeah that's better okay let's see loading putting loading somewhere here so if we're loading I want to just like justify the counter in the center and give it a bit of hate and margin this is just like a loading State maybe we can actually do this in Del if we have another message uh robot and loading true could this work let's see let's see where's Deli yeah this is it so we're basically having our own message at the top in that case and then we have a loading spinner here in the chat message which indicates that um something is going on right now cool um so we don't really need the dummy messages I think we have figured out that view already so let's go back to the empty array and now let's implement the final piece here um as I said we're getting the result already we're doing a lot here um maybe we're going to try this okay so Santa on the beach and how can I send this like this okay this puts my message up here um and then at some point we might might get a reply okay we've got a reply which has an object which I can't click on here in the debugging tools because that will be too easy uh created data and it has a data URL so that means uh I want to say if um we got result. data and um result. data do length is greater than zero if that is the case I want to grab the image URL which is at result data index z. URL and I want to uh let's fix this image URL and then I want to set my messages to all the previous messages uh and the new one however I had some issues with that in the past so let's also do it in a slightly different way way let's call it with the previous function and then I want to return everything that we had previously in there and then rollbot no content image URL and I also want to have the prompt included uh which was the message so that might be helpful later on uh and once we're done here we can also set working back to faults um does all of this make sense is the question mostly this makes sense so if I now send something I will set working to true I will attach the user message like we already did I try to get the result if I get the result I will attach the stuff with the image URL we're actually not rendering the image yet in the chat message I assume um so we probably need uh something in here um we should check this let's do an empty fragment up here and then if content is equal to an empty string and we do have an image URL in that case I want to render something else or uh like this okay so in that case I just want to render image uh where did I go wrong with my brackets here I felt pretty good about them uh image source sty uh maybe just putting a question mark up here okay that makes more sense so if we do have an image I want to use that image URL but I want to use a different styling so let's call this preview image and we're going to style that in a second uh or maybe we should do it already here so let's give this a fixed width and height of 240 in a bitboard radius okay good I actually think now we could make use of my stuff up here so the whole idea of loading is probably not yet clear to you you might ask yourself why did we include this loading prop I will come back to that in a second so for the moment this is how a result image would look like if we do have an image URL it would look like this um where do we actually use the prompt I don't know uh we probably don't really need it right now um we're going to later pass that prompt on so why are we using loading if we're not really using it yet well the trick is that we now um attach something by the way we can get rid of the whole use effect because we're not streaming on the Del page okay that simplifies the page a lot what we want is in the flesh list we want a component at the bottom if we are working so if we are working we're going to render a list footer component here list footer component and this one we'll check um if we are working so if that state is set I want to render a chat message and I want to pass in some props to that chat message I know I get really careful with all the brackets here okay so what I want to is this correct I think it is um I want to manually create something here I want to set the role to bot user I want to set the content to empty so we're not rendering any string and I want to render loading true okay uh yeah I think I missed something [Music] true this does mostly look good to me but at the same time we still have a problem here um what is the problem here uh unexpected token yeah I see that uh if work okay working and and chat message yeah that's it that's the syntax so if we're working we're now rendering this list footer component and I can just try this out I can set my working state to true in the beginning and then we would see it would always render this stuff so now everything comes together and we can give it a final try um I think the view is ready we are ready let's say I want to have on the Del page an image generated for uh mirat in a space suit flying around in uh the Galaxy okay we see my prompt we see the list photo component rendering this loading stuff we could probably also disable the uh footer and now we do get our result back the footer is not rendered anymore but we rendered the new message including an image and this is the worst image I've seen of a mircat in space uh I don't know mid journey is usually so much better probably I need to put in better stuff here to get better images from Del I know it's better by now but this is just yeah sometimes the result is really really awful but what's not awful is that we have finished another view we have reused so much code from our previous page from the chat page we could reuse all the logic for the API key for creating the open AI instance uh and also most of the stuff that we have in our view including the flash list just changing a few things here and there to build a completely new view so with that in place um I think we're ready to take some more steps because we can make this page even better uh we're going to go back because we've seen that the API works and we now going to go back to my dummy images and when we have that dummy image with a prompt there are some really fancy things that we can do our next step is to implement something really really cool and that is a context menu so we are already using zego and zego does not only have drop downs but also this sort of context menu this doesn't really exist on Android uh but on iOS you usually get this with a force touch on something and that is exactly what we want to do and we will actually also Implement these functionalities so we want to save this image we want to copy the image or share the image so really getting some functionalities done as well to get started as I said we do already have zego so we don't have to set that up but we do need some Expo plugins we need the media library the file system sharing and clipboard so let's install all of these in our application and once we got that we can also heat over to the app Json and where's the app Json should be here and then check out the app Json because we want a new entry for our Expo media library I think I kind of did this in the beginning um now we we just installed Expo media library I don't know what you're complaining about plug in not found Expo media library doesn't really make sense to me at this moment because we need to give some permissions here to allow access to our photos now uh let me just quickly check the package Jason before we do something so media library is definitely installed uh we should be fine so let's just run our usual command again to bring up the live reload and then we can start um before we get to the functionality we also need a context menu on our image for that we can change our Chad message so we already know the case where we um show the image and we will now just change this to use a context menu I think to use a context menu we first of all uh just like the drop down need to import Star as context menu from zigo Context menu and then we can wrap the context menu. root around what we want to do okay so I will comment this out for the moment we're going to get back to that what we need is of course a context menu trigger first of all um that trigger is actually our item I think we might need a pressible here uh although I'm not 100% sure about that so let's put this in here and put the context menu trigger here are we fine here with the app build I hope so I really hope mhm yeah that looks good um we are using the dummy image here right now so if we go back to the dolly screen we had open before uh we're using this dummy message however there's no real difference if we get back a reply from cat GPT uh from from open AI we would get the same kind of image URL so we're cool also while we're doing this and working on all of that stuff I want to change in my top place here um the default routing so by default I want to go to the do page um oh yeah that's not under chat that's just here good uh so by default now when the app crashes or something goes wrong we are coming back to the do page cool um the image is still here and we can actually you see the context menu is already kind of working so let's continue with that I feel good about this okay so content menu content follows now the content menu content is of course these items and what we want to do with them so let's create an array for these items and call these like context items uh and they will have a title like copy uh they're going to have a system icon so this one I'm again using something from the SF symbols uh from Apple and then we do have an action which would do something yeah let's let's just do a console or copy for now okay so with these context items we can go back to our cont here and then we can iterate them so uh context Items Map item and index uh and for every item we want to create a context menu. item the key is our uh should we use the index uh should work actually and then we have an on select of that item and that should simply Trigger item. action of course um it's not happy about index yet yeah we can also use item. title or something uh context menu item is not happy yet uh I think the this item requires uh some children maybe let's see we should put in a context menu. item Title Here which is the oh come on you had it item. tile okay now it's already getting better I think uh do we just need another one oh come on we have the closing bracket one two okay this is it so now at this point we see this feels so rewarding like this is a force touch I'm doing here so good just so good um next to the title I also want to place that icon so I really like that the the setup here is pretty much the same like we've seen before uh for the drop down menu because it's both from Fernando Rojo so let's use an iOS icon in this case name item. system icon and then again Point size I don't know why there's no point size in here there is definitely a point size if you go into this um oh there's not a point size well it's the image symbol configuration something H interesting does the point size make any difference that's a question it does it does so let's use the point size okay this is our dialog so far and I think this is pretty amazing how easy you can get stuff like this in your react native application now let's do a few more of these um and then we're going to connect them to some actions so we're going to do two more um the say next one is save to photos uh we're going to use arrow down to line arrow down to line I like how apple called these things and then finally we're going to have share this is uh square and arrow up okay square and arrow up let's see okay they're all working that's good anyway all of them we should be able to see a lock so mhm mhm save uh this did okay we all we're loging copy for all of them that's of course a problem but nothing we can fix so we installed a bunch of Expo packages um a few minutes ago now let's create a new file in our utils folder I will call this one um image uh yeah that's probably the worst name I could have picked but uh what I want is I want to bring in all these things that we just installed and I want to create the functionality in here so um I actually found this first part here on STC overflow which was kind of uh nice maybe we start with the easiest one so the easiest one is share an image for that we can just use the sharing plugin and call share asung with an image URL okay super easy um to copy something to the clipboard it's a bit more challenging so to copy to the clipboard what we're going to do is we're going to first of all create a file URI using our file system plugin and the document directory is basically the directory of our application so this is uh something something and then at the end we have the date whatever one 12 point jpeg okay this is like the worst drawing okay so we have a file URI then we download this our image URL to the file URI okay so it is locally saved once we got it locally we can finally read that local string a sync using the URI and the encoding and then we can copy that base 64 string to the clipboard right here using set image Asing on the clipboard plugin this feels a bit I don't know not right but this simply accepts a Bas 64 image that's the problem of the clipboard so if we want to do it it it looks like this um now the third function is what I took from St overflow I think I found it here I want to download an image with react native image so here uh was something I think I made slight changes to this so let me walk you through what's going on if we call the download and save image function with our image URL which is an https URL we do the same thing like we did before file URI trying to download the file from the URL to that URI once we got that we will actually save it so uh in this case here we are already saving it I think um I just wonder what's the difference here um yeah so in this case we don't want to save it internally that was the difference if we just copy it to the clipboard we're kind of saving it internally in our app but in this case what we're doing is we're actually using the media library so you see a media library all over the place here we first try to request permissions if they are granted we will create an ESS um esset using that file URI and try to get an album this is the difference so we're trying to really save that image into our photos so um I can go to the photos application and you will see I actually did this a few times so uh let me probably this is by the way the same effect like in our app it's exactly the same uh I want to delete this and I want to delete that So you you're not saying like oh Simon that photo is already in there no so now we only have these photos albums I do have the Download album here I'll also remove that one just for testing so now what we're doing here to save that file is we're trying to get this album or it will be created on Android we actually have to pass in an asset uh mobile s oh yeah I don't care um so in Android we actually have to pass in an Ed here otherwise the album wouldn't be created okay uh otherwise if that album already exists we're coming down here we're adding the asset to the album so an array with that new asset and the album name uh and then we alert that it's saved okay it's it's no rocket signs um it might look a bit ugly actually it looks quite cool and I think the whole setup should be pretty clear at this point um it's a nice combination of using Media Library file system um and also here the clipboard so really great uh you can find again that file as well in GitHub in the U folder and with that in place we can heit over back to our chat message and we can now attach the right actions so for copy I want to use copy image to clipboard from my utils uh using the uh image URL let's use with an exclamation mark because that's going to be set in that case if we want to share this I will use um share image with the image URL and in the other case down here I want to call download and save image with the image URL okay back to our app now we do got this we've seen the context menu before let's try to share it and okay yeah what's going on app has crashed because it attempted to access privacy sensitive data without use appps must contain NS photo library usage description so that's the whole point why I did the app Json change in the beginning um what NS photo library okay yeah I think we need to do another pre-build with clean once we change our app Json um that's a Pity because that's taking like 5 minutes and I don't want to wait but apparently that's the reality and I still don't know why it's saying that this Expo media library plug-in was not found because it was definitely uh found I can go to all the other plugins I just can't go to the Expo media library plugin that's so strange um I don't know if this is happening for you as well maybe it is like some new version um because it's definitely installed uh it's R oh this could really be the case that's something okay that's Expo secure store that's some it's a different story H that is really strange uh probably if I reload my IDE maybe that stuff would just turn out fine but again reminder uh if you don't set the right permissions your app might completely crash uh because especially on iOS but also on Android you need to ask for the right permissions otherwise the stuff won't work especially working with a file system getting images or in this case also um sharing stuff so let's wait until the build has finished all right and we are back and we can finally test our functionality so let's try to um share this share should hopefully open the share dialogue and I want to uh let's say allow full access the image oh I think I accessed yeah okay I just intend call download instead of share because I connected them in the wrong kind of way well that happens so let's do it again I want to share this and it hopefully brings up the share dialogue nice here we go we see that we are now sharing this image I can also hopefully save these two photos and this will alert image saved to photos and we can check this out we have a new download folder with two images included I can remove this now okay I remove this as well then I could go back hit again save to photos and it would hopefully be saved in that array so this is by the way how you save images to the media library of the user so these clones are not just about UI we also have some functionality here finally I also have this copy um so after copying my uh image to the clipboard um let's try where can we paste this uh probably if I just open up the messages here these are like fake numers and if I do a long press paste yes it works so if you got the base 64 in the clipboard usually applications know what to do with that and we have our image here as well so um this is everything I wanted to show you about that context menu thing uh I think it's a pretty cool thing from zego this is not the last time we're using the context menu today I at least I hope um but for the next part we're going to do something probably even more epic with the image viewer we might have developed a lot of interesting things in this clone already with the menu the navigation and all the styling we got going on but I think what's coming next is probably my favorite page of this whole clone so we want to build an image viewer component that means when I click on this image here I don't want to only see that context menu just clicking on it should open this image viewer component that component has many different aspects so we have a whole Zoom view here that's like the main part as you can see this should go beyond both the uh Tap bar at the bottom and the header which are blur views we have some uh buttons up here this one will actually trigger another drop down menu so we're going to create our own drop- down menu we have these buttons we won't have the add the edit functionality and select however save and share can work in our case as well and finally if we want to share this we also want to add like a bottom sheet this is actually a real bottom sheet uh for our app so as I said this is probably my favorite view of this whole clone um for this we will need three different things we will use the react native image Zoom component which allows us to easily zoom into an image like this we will use the react native bottom sheet from gorom once again epic package you can find more tutorials on using this as well on the channel and the third one is just a react native toast because I wanted a toast message if you copy like the prompt um so these are the main three packages we will use let's install them first of all so I'm going to kill this and what we need here is first of all the react native image Zoom package uh by the way there should be a file like um like I don't know commands. sh uh in the repository on GitHub where find all these commands uh second package is gor home bottom sheet at version 4 and then we have react native toes which also needs the react native root siblings at version uh at version 4.0.0 at least I hope that works okay with these three packages we got a lot of work to do uh where do we start I have no idea actually um let's start by bringing up our our live reload again um so if we click on an image we want to route to a new page so we need a new page and I will put this under the model and I will include the URL in the page name like this okay um just like we did before we should be able to extract the URL and I will actually also get the prompt using use local search params if we include this we can do it like this The Prompt will be well let's say this is optional okay so this is my page um in that one I will most likely also use the uh save area insets at the bottom if we want to fix something at the bottom I'm going to talk probably about the uh bottom sheet a bit later let's prepare something for on copy prompt already so we got that in place uh we can just use something like this and then do a lock in here copy prompt okay that's fine so far um where do I want to start next maybe we go back to our chat message because on the chat message we now need to integrate that um so where we currently have the pressable in our context menu we need to wrap the pressable now with the link component from Expo router and set the H to something that's not included in here that's bad uh pretty much this but not exactly this um o model and then we have the URL I will just include it in here to be honest so let's use a string letter Ral and then I will attach let's do encode Yuri component image URL and as a query parum I will also attach prompt equals um another one and code Yuri component with the uh prompt we need to use something special or can we just use prompt okay um let's see unexpected token yeah I was pretty sure that I was messing this one up uh link should be close as well I think then we're pretty good maybe the link needs to have as child as well and then nice this is already routing forward okay that's good by the way the context menu should still work so we having like two different functionalities on this image cool um let's go back to the layout here we do have an entry for the settings page and the entry for the model page is probably similar so this one has URL here in the name um the header title for that page should be Mt and then we're going to make this a full screen model so it's just filling up the full screen um let's see can we just get this okay yeah here we go um I want to have this here in the header left field um I also don't really want to have it like this uh we probably need to change the touchable opacity so now we can't see it but the header is Bec a bit darker in a second so we can now apply some styling um for the header Shadow visible fults that's correct header Style I want to set the background color to uh something with an opacity so I'll set this to a value like this uh and then I want to make the header blur effect so yes this is actually something we can use I want to use dark here and then we have the header style and hopefully uh stuff behind that will be visible um to achieve that maybe we need to quickly go to the page and already add our image Zoom component so um this page let's do a bit of style here uh let's do some container styling Flex one justify content Center align item Center and I will also give it a background color of black okay here we go add the stylesheet to the import and then we can add our style here styles. container and then we can quickly bring in uh the image Zoom can we already get that ah we can of course but we did install this so I'm I'm pretty confident that at some point uh we should have the image Zoom the import should look like this I don't know why we were not able to figure this out automatically but nonetheless um we can now pass in the URI here and use our URL that was passed to this page stylesheet doesn't exist nice error okay let's see um I click on this I get to the page um I don't see anything yet probably because we need to give this some styling um let's use a width of 100% And for the hate the same and I will give this styling in here so nice this is a nice starting point and you notice something at the top um oh we can't uh you see it's actually already a blur View at the top that's pretty nice nice I like that um but there are certain things that are not yet working so we're going to get to that in a second uh but I think this is pretty much done I also feel like the header should be transparent but let's see header transparent true does this change anything yeah that makes it even lighter um that was an interesting command to hide all editors yeah now the is even I think I like this even more because we still got the blur effect uh I don't know if this is like still applying this yeah it's it's all it's all coming together we need everything we need all of that okay let's see how we can change change the image Zoom component because that's the uh the most important part here we have set the URI uh I also want to set a few more things so I want to set for example the Min scale I want to set this to 0.5 I will set the maximum scale that we can zoom into five I will send the Min penp pointers to one and the double tap scale to two so now it should already work that I double click this I would probably have to reload this uh not yet uh yeah we need to say is single tab enabled and is double tap enabled uh now I should be able to yes zoom in and I can also with a single tab move this image around nice um I think I might also need a resize mode uh resize mode I will set this to contain will this change something this should definitely yeah render my image full screen and then I can zoom this in uh I don't want to move the simulator sorry okay that's a pretty cool component so far I don't know why my container okay now the container does have a dark background as well um and we also now want to have this Bottom bar so we've seen before there are different area uh this Bottom bar with a blur View and then we have the header bar on which we might have to work as well uh for the moment let's do the bottom thing so this is a simple blur view just like we had before uh I want to set the intensity to 95 because this is quite dark uh tint dark and for the style I will set up some Styles um styles dot did I get that right yeah I got uh blur View so let's add this down here this should probably have like a width of 100% uh yes like this 100% WID and should be at the bottom so we'll say bottom zero uh let's close the blur view as well so within that blur view actually we need to not self close this but close it later in that blur view we're going to have a view which has now our items so I don't really think we need another uh row setup and developing these button items I think this is going to be pretty boring so let's just bring in the row and the button styling um so here's the row Flex Direction row we're now justifying content space between which will evenly align the four items and we have some pading and aligning the items and then the button text and then we can just replace The View that we had in the blur view with a view that has some touchable opacities and ionicons it's actually nothing really fancy the only cool thing is that this is a blur View and now above this only thing I noticed is that we have a problem with a petting bottom so that's why I wanted to have this as an array so I can now add petting bottom my bottom inser and then we can slightly move this area up from the blur view okay um I think this already looks pretty dope uh we should be able to close it get there it looks really like a nice image viewer component um by the way notice we can use share image the functionality we previously had uh in our utils and also download and save image all of this still works because we're still exporting that now there are two more things there's uh the drop down component that we need and also the bottom sheet I think we're going to do the drop down first because that's going to be somewhat easy um let's do a new component and let's call this one drop down menu. TSX okay react native functional drop down in how far is it different from the header drop down that's a pretty good question indeed uh it's going to be a bit different um do we have a preview of what we want to do with that button uh I don't think so I don't think we have uh something um but what it will do it will actually trigger our model so the idea is that this should finally present our model um so if there there's no let me see uh I got so many examples of this uh here it is this one it's it's this one okay this is what we want uh we go to that page we click on the three dots up here and that should open a drop- down menu and then it opens up the bottom sheet which we can dismiss and we can copy the prompt to the clipboard that's the whole story here so in order to make that drop down menu we just need to use the usual stuff that we are used to from previously so let's replace this with dropdown menu. root um drop down uh we need to be a bit careful here so so uh I'm reusing the names so now it's drop down menu yeah yeah that's better okay then we got our trigger as always which in this case is simply an icon and that is already enough to place it in my image um in the image viewer component so what I want to do is I want to use stack again from Expo router to configure the stack screen right here on that page options and then I will use uh header right to provide my custom component and in here I want to use the dropdown menu component we will later or in a second also add some items to this uh for the moment I need to make sure I close this and then um let's see okay here we go okay this is not triggering any anything so far um but we're going to get there in a second so our drop down menu we have the button now we just need the content so let's go ahead with drop-down menu do content and Implement a simple drop-down content I will actually use some props here as well just like before we have an array of items with key title and icon and the on select function and I can just attach this in here in my drop down menu so I can get the it items and on select and then it becomes pretty easy so items. map for every item I want to create uh dropdown menu do item key should be item. key on select I want to call the on select uh and now copal is able to figure out most of this so drop- down menu item title is my title and for iOS I want to use the item icon and again I want to use a Point size of 80 here uh what is something I did not close probably here NOP sorry about that one probably here yeah that should be fine okay I think this is our whole drop- down menu you really get this stuff from zego so easily and it just looks so so good uh we just need to pass in the right items here now that should be fairly easy so it items could be something okay to make sure I got the right syntax in here um key let's just use one and that's going to be view prompt icon will be an info. Circle second item will be key2 uh let's should say something else like learn more and then we got question mark. Circle uh on select is missing that's a good point so on select what I want to do is I want to have a function uh to like handle the model let's call this one handle present uh modal press this is going to be a function pretty soon so let's just put it in here okay if we click this we see the menu we click view prompt and the bottom sheet should appear also it's going to be appear in both cases we don't really care too much about that um so let's just do it like this this page I really love it I really love that page honestly let me know in the comments if you also like this page this is definitely my this is definitely my favorite page I just like it uh so many things are coming together here on this page it's it just feels good okay not getting too overly excited before we do the handle model and integrate the model let's quickly do something uh regarding the toast so I don't know why but I just wanted to give the user a little feedback when we click uh copy prompt uh which by the way doesn't make sense [Music] yet H let's do it anyway I think it's good because the other part is going to be harder so in order to use the uh react native toast package that I've shown you before we're going to have to wrap this root sibling parent around our stuff and because we're soon using model component we actually got to wrap this uh around the stuff in here so let's by the way also bring in the model sheet stuff from gorom and then we can restructure the whole view so around everything I want to put the root sibling parent what we just added root sibling parent so this one goes all the way down here this shouldn't change a whole lot yet the only thing it changes is that um on copy Pro we should now be able to call the right functionality so I could now use the uh clipboard do set string async uh did it get the import right can we just like get the clipboard from Expo clipboard oh why not why do I have to do all of this myself clipboard. set string async and that's going to be our prompt so so this is copying The Prompt and once you got this uh we got the prompt we should be able to call toast. show and say something like promp copied duration whatever I will do this like with a short duration position at the bottom that's okay Shadow true animation true hide on press true delay zero so now we can already try this out by adding it in our handle model press so I click this and it shows prompt copied to clipboard um if you don't see this I can also do top for a minute and do view prompt and then it appears up here cool okay so we know that functionality and that part works now we just need to present the actual gorom bottom sheet um in many cases it's like hard included in a page where you can drag it up from the bottom we want to have it a bit different way so in our case what we are using we are using a bottom sheet model provider around our app here or around our view let's get that in the right place um and then we can and or add a bottom sheet at the bottom that makes sense right so bottom sheet uh model goes in here uh within that model we can then have a view with our stuff let's just place a text in here test we don't see anything yet because we need still uh we need to configure this a bit uh to configure our bottom sheet correctly what we need is usually a reference so a bottom sheet model ref using use ref and we can use the bottom sheet model type here then we need the snap points these are the points where you can like Snap this bottom sheet too uh it's not going to be super important here as we won't really snap them very far but usually you're going to see a setup with useed memo uh in different values to which you can like Snap this bottom sheet in our case I will only allow one value of like 40% and then I want to implement the uh handle model press let's bring this up here so in this function we will actually make use of use callback to store the result of this call okay here we go and then call bottom sheet modal ref current. presentes uh use call back we're good we still need the empty dependencies and now just like this we can have a function that doing exactly the opposite so const uh handle close model press pretty much exactly the same setup just like this and with these lines we can now control our model completely from code so if I now click on this uh handle present model it should bring up the model from from the bottom let's see view prompt and okay my model is is not exciting to be honest I don't know if it even works yet yeah we're not seeing any kind of model yet uh bottom sheet model yeah we haven't even attached like the ref this can't work at all so let's quickly fix this ref is the bottom sheet model ref um sorry uh butt sheet model where did I go wrong this time uh okay should be just fine okay snap points not provided yet we should do the whole setup so uh the initial index will be zero in my case snap points are my snap points and then we should already be able to see it yeah now we finally see it here it is uh I will actually set a bit of styling so let's use a background style using um background and my own colors so colors do gray okay this is the general background and I want to make the indicator at the top a bit lighter so handle indicator style should be colors gray light okay now this works a lot better okay cool um honestly that view as I've shown you before just consists of a lot of styling at the bottom and the text in between I don't think there's anything really excited about building that view right now so we have the whole logic working with the like the drop down here and then opening the modal sheet with the ref I think that was more of the interesting part here so let me just fill in the blanks with the rest the rest means we have some styling which affects the model container uh the title text which is a bit bigger The Prompt text which is a bit smaller the button text and the close button styling nothing really wild going on then we can have all of that inside of our bottom sheet model instead of just having this text we now put in a whole view only thing missing is the pressable and our default Styles if we do this we're filling it out like this so you see um I highly recommend that you use the bottom sheet scroll view because the text here might actually be a bit longer and I've structured it in this way and we do have the bottom sheet uh scroll view up here in the view of the model and then we have the touchable uh which is the copy button down here so this relates to the part up here and we can scroll this and the button is fixed all the time and we can actually scroll inside that bottom sheet if I click the button we use using again the uh ref and handle close model press like we uh prepared up there uh for share we can still use share no no I'm in the wrong place uh let's see it again here we go this is the prompt and yeah I think there's nothing else to this but we've done a tremendous job with this page so in the previous step we did the context menu and I was really proud about that one and both also the functionality but this page this coming up this this blur of you everywhere the buttons down there um the drop down menu and then also in combination with the bottom sheet this is certainly my favorite view of this whole app and I think this is something you can reuse in many of your application both the functionality we did before with the um with the assets with the uh media library and with the what it's called albums uh and now the whole image viewer component the blur views the drop downs and the bottom sheets and how to easily like combine all these things and like just from a buffet mix together these things and pick them for your application so you see I'm getting already too excited about what we just did uh there's still a few things ahead of us so once you're done playing around with this component let's continue there's one page we haven't talked about yet and that's the explore page so on that page what we basically want to do is we want to show a you like this uh where people could explore different gpts but before we get to that part which will actually involve something like a loading animation we will focus on the part up here because this is once again like these buttons here is something we can scroll and at the same time if we scroll this here the part up here has a blurry background and that was actually quite challenging to implement so I wanted to take a minute to um just focus on on creating that blur view with a draw which was somewhat challenging so let's do this I'm here on the explore page and I want to first start by defining these sections so these are the different sections that we will be able to scroll through now let's also do re native stylesheet here because we're going to have a lot of styles on that page and then we can start uh probably want to set our container styling first so container uh of that page will be Flex one and background color colors importing my own colors. light good we got that page going on uh now let's use these so styles. container and then we have the same color across our page cool uh we might need a scroll view with some random data so let's add some scroll View [Music] I want to have fake data can we have fake data array from length something just do some whatever random stuff please can't you just like do random things uh text test uh okay that looks awful anyway I want to have 20 of these items so then we can later test this uh maybe I'm just giving them yeah I don't care okay this is only for testing now we want to focus on the header and because we are here in a draw scenario we can't use stack. screen to style something we have to use now draw do screen instead shouldn't be a huge problem for us anyway um the draw screen can be configured in mostly the same way so we're going to start uh with some easy easy stuff so for example in the header right slot we want to have a touchable opacity like we had in other places with this icon um we also as I said want to have a blurry background so if we scroll this we want to see the stuff here going beyond that header in order to achieve this we have to make our header transparent so header transparent true we see this now looks awful but we can now set our header background and the header background will be set to a custom blur view so on the other page Pages you saw that we could actually use a property here in options which doesn't exist as least as I as far as I know within the draw header so we're going to do it ourselves no big deal we know how to work with a blur view we're going to set the tint here just to light today and then we might have some styling um we're going to check out that styling in a second let's close this for now uh here we go okay we don't really see the blur view yet um the reason is because we don't have the right styling we need a background color uh and I want to use the following with opacity so this is my background color now this is still not working because we need to fill that whole Space of that header and we can achieve this simply by using stylesheet do absolute fill as a result we see that stuff going behind this is now getting this little overlay um however I don't really see this I think it is it might be a bit too hard why am I not seeing this correctly uh we do have the tint light can I use light like this in the intensity uh heter transparent true uh the scroll View you might have an issue [Music] here actually it shouldn't um but what is this okay border bottom color I don't want this anyway uh could we give them like a red background color and then check again okay they're definitely going Beyond this by the way you see if you set the header to transparent um you you got a problem because now your page start pretty much here at the top you need to take that in consideration and add some padding to your uh scroll view so I could add something like content container style uh pading top uh pading top and I think I can actually get the header hate so we don't have to like use a fixed value we can use header hate uh with a custom hook called use header hate it's usually hidden you won't find this you see I'm not getting code completion on that um however we can get that stuff from the react navigation elements package so there's also get header title and header which we're going to use in a second and now with the value of header height here from our hook we can set this in here and you see I can still do this but now my list has some petting at the top and I can scroll it behind this now this is of course not everything we also want to have our um horizontal scroll view in there so probably I will turn off the background color here because we see that the stuff seems to work um and now I want to focus on getting the the scroll view thing in there the horizontal scroll to do this we actually have to create our own header I couldn't find a better way but it turns out it's pretty easy so I think this is a nice learning again these clones are really not just about cloning these are about like learning in different scenarios different pieces so if you go back to the fintech Clone to the Airbnb clone to the WhatsApp clone you're going to notice like at least 5 to 10 of these small helpful nuggets across these videos because it's not just about the UI and like doing a lot of styling it's also about making things work and understanding what you can do with react native and these packages so we can create our own header if we want to we could do this by using the header component that we just added from react navigation elements and then you would pretty much have the same experience so you see no chains this because this is the actual header component however we're going to restructure this I will place a view in here we could also have a fragment I guess uh which first of all has the header using get header title the options and what n but then also has a scroll view with horizontal scrolling uh can we get the closing stuff as well I think we need to close the view as well so with that in place we see we already get this one if we map through our sections with a horizontal scroll view no indicator and probably some content container styling included so let's include something like a gap of eight between these these touchable opacities key index that's fine um styling we have to talk about that and on press we're going to have to uh use some state so let's keep track of that of like the selected element uh I don't want to use react I just want to use use State and the sections at index zero will be selected if I click on any of these elements I want to set uh set selected to the current section the iteration that also means we need an error function here okay now with that in place we can use some conditional styling so we need the uh button selected uh we need a label we need a title we need a section we need a lot of styling I guess uh styling yeah we need section button section button selected section button text section button yeah a whole lot of styling let's let's go down here and add this so section button has one sort of uh color what is that color that's a pretty light color if it is selected it's a bit darker then we set change between like black text and white text and with these four states we can now create uh the effect that we were looking for so going back to the styling here of the touchable opacity I can start and say if selected is equal to section of the iteration in that case I want to use styles. section button selected and otherwise I want to use most likely just the section button uh oh so many red lines um it should be like this oh come on where did I go wrong um Style on press section uh if selected oh yeah we need to have just one of these better okay so if the selected is the current section I will use section button selected if I now reload we should see that this most likely already works I can click these and works just fine I just noticed that our content could also need some pading horizontal of like 16 okay moving it there and then some pading vertical of let's say uh 10 so we got a bit more space in here nice okay cool um if I click something I should also change my text so for the text it's the same thing let's just do this if the selected is equal to the section we're using the section button selected otherwise we're using the section button text and with that if I now reload we should have the right State and and I can switch between them quite nicely and we can also scroll this behind this again if I use the background color like green we see we're starting here we have the right padding from top but then we're using or making use of that blur view at the top still using a draw navigation but now having our own custom header implemented which is a combination of custom scroll view so many people also have like a text input there and the actual element which is the exact element you would get by default if you command this out so I think this is a good starting point for our page uh of course we don't want to render a bunch of test elements in here what we want is something real so let's talk about how we can make that explore screen including a cool loading Shimmer all right so we want to continue on the explore page and now after building that header area let's talk about this so on the page in general what we want to display looks like this um we do have like a little uh title text up here and then we have different cards I think we're going to have like five cards usually if I would switch between the categories here this view would reload however we're going to keep that stuff mostly the same and just change like the text up here but we want to have transitions between the pages so if we skip from one to the next we still want to mimic what's going on and we want to do this with like loading animations or a loading Shimmer and also if we like come to that page initially we want to see something like this for that what we're going to use is a package called react native Shimmer placeholder I found this to be quite helpful this is exactly what I want to do so we can install both the U package for the react native Shimmer placeholder uh we might have to kill our app once again and we also want to install the Expo linear gradient because that is usually used in here so the linear gradient will help us to create that nice background in our app good once we got that once again bring up the app and now let's see so I highly recommend you know go to GitHub uh link below this video if you're joining now for whatever reason uh and check out the explore page because we're going to have some dummy data up here so this is what I want to use we like title description author and image they're like one two three four uh five different apps that we want to display on that page this is just some dummy information I actually got that information by using C GPT and asking cat GPT for Json formatted current apps so uh a real Inception going on here let's also put in a little loading State here we pretty sure need that at some point going to start with a loading State fault and I will use a use effect because in reality you're probably making an API call uh there you will somehow set loading to true and then after when the request is finished you would set loading to false in our case I will just mimic this with a 2 second timeout that should be enough for us um now what we do need is the Shimmer placeholder and we're going to import two things so let's import the create Shimmer placeholder and the linear gradient and then we can create our own uh Shimmer placeholder so I I was I was under the impression that it's just called like loading skeleton but it seems like this is also called Shimmer I don't know um I kind of prefer the word loading skeleton but well here we go so this creates our Shimmer placeholder now in my scroll view somewhere down the page uh we can get started we first of all want to map through all the sections we have now as I said in reality every section here would have different data so if we go to writing to productivity we would see different results this is not going to happen in our case I don't want to have like 25 different apps and dummy data in here so we will just like use the stuff again I would normally wrap my view now with an empty fragment because I want to like have um another um if something like if selected equals section uh and and then I want to do something but since we're already mapping something we should use up here react. fragment so we can actually add a key and the key will be our index because if you have an iteration you always need the key in there uh okay so once we got that out of the box let's see we're going to wrap everything here with an animated view so animated from react native why animated view well because we're going to animate that view at some point uh for the moment what I would like to use is let's see um I want to put in some text here for that we're going to need uh some styling for uh both the title and probably also a label okay so a bigger font size and a bit smaller font size so let's see uh we got our label we got the text and we also got the label let's for now see how we can fix this uh brackets here then we got the react fragment which has this and then we need more of these right here we go this is what we want to see um we also probably want to have some sort of section styling for the whole section uh we can place this on the animated view so let's use styles. section I would like to like can I just create this now in my stylesheet that would be a really helpful thing huh H that would be a cool addition if somebody has an idea about that please let me know in the comments okay we're going to use some petting here and then our section uh excuse me where's my section um then we got this okay that looks fine we also got the blur working in our favor cool but this is not really animating yet um what we want to animate is the appearance and disappearance of uh that text so therefore we made this an animated View and now we can use simply an entering animation we can use something like fade in we can specify uh duration let's say we make a bit longer duration of 600 and we will actually delay this by 400 this is going to be important to make the whole thing work because we're going to also have an exiting animation which is using a duration of 400 so basically what we have when we switch between them is the existing view here will disappear it will fade out and the next one will fade in okay but it won't fade in to the side it will actually fade in here okay but we're waiting with this fade in here for The Disappearance of the other things so that gives us a nice little effect here that means if I go to top picks and then to DOL well this is not yet exactly working as I expected to work it's I don't know why there's like a little delay when I press this uh on press I set my selected section um maybe maybe we should do like smaller values uhuh it fades out and it has the okay yeah this shouldn't do Fade Out okay my bad so of course for exiting this should be fade Fade Out instead let's see yeah that makes a lot more sense so the one thing is fading out the other one is fading in after a delay now additionally I wanted to use this Shimmer placeholder as I said and that one is quite interesting because we can actually have this Shimmer placeholder which is visible until something is ready and then it displays uh the content so we kind of wrap this around our components usually I'm used to like creating the whole View and then I have a completely other view in which I check okay if loading then we're going to display all of these skeleton views but the loading Shimmer Works a bit different so let's see we can now put our Shimmer placeholder um around our label and I will just do it around one label for the moment okay so you see this is now actually displaying the loading Shimmer you can affect how that looks so you can say like I want to use a width of let's say 160 and a he of 20 okay so we have like a nice Shimmer up here additionally we can place the same thing now around the other text but first of all we're going to check this will only be visible when we are not uh loading okay so okay initially this won't happen again now only if I reload this page so it only happens when the page enters it loads and then it goes to the top picks and now we're going to replicate this around the label um so around the second label here we're going to give that one a with of like something like 280 ha 80 uh and we can also put in a shimmer style here for that I will just specify margin vertical hello um am I good here I think I I hope so margin vertical of 10 okay so now let's reload that page I don't know why it's jumping from the top do we have something that changes the top uh uh we don't have any sort of on layout I mean we have the use header hate going on [Music] here uh is that a problem I mean it shouldn't be but if I don't use it I have another problem because my stuff is going to be hidden behind that so I will use it in here okay but we've seen the idea of that Shimmer it shows up in the beginning uh until we are ready okay so 2 seconds in my case with the use effect and then the rest of the view becomes visible and we can now do this again below it so we have the uh where am I I'm in the wrong place okay here we are here's the animated view these are like the first two text elements now we got an array uh we're going to say just array. from um actually we don't why are we using array from in here we we don't need it like that I just noticed we can just iterate my sections right or the apps right uh so let's iterate all the apps uh for every app I want to create one view key will be index uh style that we're going to Define ourselves so styles. card let's put this already down here card uh and then let's see I will close it and I always have one missing bracket okay no problem okay this is our card then we're going to put in an image so this is the react native image source will be Yuri app. image that should be fine uh then we probably going to use styles. card image here and we close of that image and then we're going to create this ourselves card Cent image I don't know if this is going to be the current image let's see uh this is probably not going to be the card image uh eventually we should also Define our card so let's give this one a background color of colors. input we're going to have a border radius yeah let's use eight let's use a margin bottom of eight and overflow I don't know if I need overflow I don't think so okay so these are more or less the cards the card image with should just be 60 UH 60 and Border radius 40 something I don't know why this is disappearing all the time um if I use use State up here with the first section why is this changing like the selected should always be the same that's so strange it's really strange anyway okay this is a bit better uh nonetheless the card should have some petting as well so petting 16 we going to add uh Flex direction of row here so Flex Direction row align items in the center and a gap of 16 so this is between the image here and then the text that follows here uh we have some margin button we have some petting I think that looks pretty good uh let me just quickly bring in three more stylings that we need for our card so we need a card title card description and author these are like the uh where is it like this three things you're going to see so title description and author down here uh nothing really too fancy okay and for all of these we're going to place a shimmer placeholder around them because that will allow us to reuse that view and we're actually going to place the Shimmer placeholder also around that image so we can use SE it in here we know that this should have a width of 60 a he of 60 it should only be visible while we're not loading and then we also do have the Shimmer style in here so the Shimmer style in this case should be a border radius of 30 for that image so reloading and this looks pretty good already and as I said we just need to bring in the final view now uh which is also part of the card this is quite boring this is just the title the description and the author here actually we don't need to do it like this we can just do app. tile app. description and app. author uh or not app. author okay so now let's do reload and see what's going on we got a nice loading Shimmer here for all the things and if I know switch to another view the whole view Fades out because we have the uh topmost animated view here with the fade out and fade in so this is like a really smooth and gentle switch between the categories we could probably make like yeah the Fade Out 300 300 and maybe this 400 do it however you like uh so now it would be a bit faster yeah that maybe feels even better because it still looks good good uh but I guess something going on and this is probably not the most exciting view of our application but you see with this blurry header and the scroll view in here the selected stuff and changing of the views this is really helpful you need this in a lot of application where you just display stuff and it just shows this could have been a pretty boring view but with a blur view with the stuff here in the header and with the loading shimmers and transitions it becomes way way better view but just like really easy things that we included in our page okay so that's everything I think actually everything in terms or most of the things in terms of UI now there are two big big things I still want to show you so one thing is how we can persist our chat data to sqlite and the other one is how we could now easily integrate payments into our app using Revenue C so if you're ready let's take on those two challenges all right after all the UI things we have implemented we now want to get a bit more functional in the end again and we want to implement something that is using the sqi database of the device so we will be able to store when we start a new chat and also the messages that we send in that chat I'm well aware that we can kind of get this if you're authenticated with open Ai and user accounts and getting your history but um we're doing a clone here and we want to learn something so we're going to use the Expo SQL light package which was actually updated recently so let's go ahead let's kill this and let's install this and usually this is pretty interesting because it's not that obvious how you get the data from SQL light um so let's bring up Expo run iOS again and then we can get started so if we check out the documentation there's a pretty great example here um of all the basic things that you can call uh especially let's scroll down a bit um so maybe we should scroll in um the idea is that we're going to wrap this sqlite provider around our application and then we have a function here on init which which calls migrate database if needed and if we expand this uh we see that at least somewhere here is this migrate database if needed function which basically checks database version checks the current version if we are already on the latest version there's nothing we should do otherwise we're going to basically create our tables and in this case they're also inserting some data so then is the first step and the general logic that we want to follow so here we go uh let's import the start is it like this I thought it was actually the import was different but anyway we're going to do this in the inside Area um so in the inside layout I feel this is a good place um I also want to kind of can we directly get the SQL light provider why can't we get the SQL light provider [Music] um uh I'm pretty sure this did exist before uh no provider in here that's interesting okay so how did they do this in the example then um if I want to use the provider let's check out secr light provid it's exactly like this didn't I type it like that let's see uh okay uh module expose equal light has no that's so much fun so much fun uh because I think they updated this uh um which version did we install that's a good question uh we should probably check that out and you should also check this out Expo SQL Expo sqlite 13 um in my previous example I did use 13.4 okay so this is definitely not the latest version uh are we using the latest version of Expo no we're not so in your case you are most likely on Expo 41 which means you should be fine with exactly this Import in my case I have to use Expo sqlite next to get the right stuff because I'm still on version 13 of the Expo sqlite plugin and in your case most likely it is 14 okay this just to clarify a few things now we're going to wrap the SQL light provider just as they did around the app which will later give us the ability um to use a hook and then directly access SQL light from our components in a lot easier way uh we're going to call the database like um whatever chats. DB um and this is still missing uh has no responding closing Tech yeah that's a good point we should rep this here okay uh there we go by the way we can start on the chats page again so for debugging I changed this to the Explorer page in my topmost layout file uh now we're going to go back to this here okay uh as they said we should have this migrate database if needed we're going to put this in our utils folder so let's create a new file database. TS and within the database TS we're going to export asnc function migrate can we just use it from them uh from the export documentation let's just copy this for the moment and put this to the side we don't need it right now anymore and call it okay so we can now add the import uh from sqlite next as I said in your case this should be just fine um in my case there are a few things that I want to change here so first of all I also would like to lock the path to my database this is going to be important for debugging later on so right here in the beginning I will put a simple lock statement which locks the file system the document directory this is um really helpful as you will see if you want to open the file uh because usually there will be some problems you're not sure what's going on so we can now get um the user version in fact this line didn't work for me so I had to change this to something else maybe we should do a bit more space while we develop our database provider so this first line is just getting the user version of our DB um to get the actual current database version we have to then call result user version as I said the destructuring statement of Expo did not work well for me uh if the user has the stuff there's nothing else we need to do but if we are in a new database here we need to create our tables so this is what we want to do now um we want to create a table I will call this one chats um and the chats table consists of uh let's see an ID and a title of the chat okay nothing nothing really fancy besides that I want to create a second table called messages so every message also has an ID we can put this so you see this a bit better um every message has an ID a related chat ID so we can reference this this is also marked as the foreign key uh of the message then we have a prompt Roll image all content you know all the fields that we already had in our typescript interface um for a chat I'm well aware that not everyone in the front end worldall likes to write um SQL code there are other Solutions you could probably also use drizzle cusell um I'm also working on a another video about offline first worlde with power sync which is another great mode to have this synced to your data base and also still uh local First Data different approaches for today we will go with this simple approach and I'm also aware that we're not respecting the user account so probably for every chat we should store which user created that so if you like lock out on a device and lock in again you don't want to see the chats from the previous user so you could easily put in like a user ID here and then um make the select call dependent on that for the moment let's just keep it like it is but what we want is uh we definitely don't want to insert some dummy data um and I also want to let's say I want to get the this as a result equals a weight so then I can later do a little lock statement here for the result so far we should not see any result because I'm um not calling the provider yet uh or I'm not calling that so let's change this let's go back to our layouting function and the line we wanted to add here is what was the line uh on inid on in it of this provider I want to call migrate uh album if needed no uh migrate database if needed make I should put in an export here um migrate database if needed cool now with that in place we expect that if we save uh yeah that's actually good that's an error from SQL light um calling the exact Asing function uh has failed caused by create syntax error okay um create table chats um is it not happy about like the okay we need a semicolon here maybe it's just this yep okay so right now um let's put a lock in here already on latest DB so if we see this now we got to look we should have initialized the sqlite database correctly so even if I do a Reload you see it's logging out uh the path to the database and then already on latest database so this is actually good news um looking at the database right now should be pretty boring because there's no data included so let's add a couple of functions that will help us to um insert and read data so export con at chat uh that's going to be an async function and we always need to pass in the sqlite database but we can access that through the according hook uh and then we simply call await database uh I want to run run a sync in this case insert into chats I want to add a new chat with a title and then we got the values in fact this doesn't have to be an array I think um I think this is fine as it is okay cool let's prepare another one to get all the chats nice co-pilot exactly get all async is the call in this case I want to select all the results from chat um on top of that we of course want to get my messages and we want to add a message so let's see export const add message okay this is interesting let's see if this is actually correct here uh let's go can you just format this correctly thank you okay add message we got the database um we have a chat ID the actual content um maybe we could just structure this like from a message okay so this part here could actually look a bit better if we just did it like this uh from my interface and then in here we would have like this okay and then we would run Asing insert into messages the table um chat ID content Roll image URL prompt chat ID content Roll image URL prompt and these other values 1 2 3 4 5 1 2 3 4 5 okay we got chat ID we got content we got uh Ro by the way should be checked so if roll is equal to rooll do uh bot we're going to say bot because we're going to have to convert this to a string we can't really store an enim type the image URL is optional so let's otherwise store an empty string and the prompt uh is the same actually so if the prompt is empty we will also use an empty string good our databases provider is coming together really really really great um now we need another function to get all the messages for a specific chat ID uh this will return get all Asing select star from messages where chat ID equals chat ID yes this is correct um the only problem I see here is that um the result of this call it's by the way a promise unknown this is not so cool uh let's say this is um um get messages should actually be like an array of messages um so let's await the result and then map every result so for every yeah message I want to take all the values that we have in message and then check the role so that's again if message. roll doesn't exist on type message um okay now it thinks it's an array uh is it better like this should be better yeah only the comparison here okay now now we got some typescript issues because message role is expected to be of the role enam but in this case it's actually a string uh we can overcome this with like uh message rooll as a string com equals to bot yeah then we convert this and set the role to an actual role I think this makes sense hope this is clear uh we just want to make sure that we return an actual message type here from our get messages okay um what else do we need we finally um maybe two more things let me quickly bring them in so two things to delete a chat which would run a delete command delete from chats where ID is equal to chat ID or renaming a chat which would be an update statement so with all of that in place we have a perfect provider around our sqlite database we've wrapped it with a sqlite provider here around it so let's actually use it we're going to use it on the new chat page um I'm going to restructure this pretty soon for the moment what we want to do is uh I want to get rid of the dummy messages here this is only confusing me at this point um and we can now get the database we can say cons DB equals use sqlite context and again uh I'm using it with uh the es with a SQL light next package here in your case it's just going to be Expo SQL light this gives me access to the database and with the database I should be able to perform something so we already left a lock here that was probably like two or three hours ago at this point uh create the chat when we call the get completion function and our current messages array uh length is zero that means we have no message which means this is the start of a new chat so in that case I want to create a new chat so let's actually do this by calling add chat from my database um I will pass in my DB which I got from the context and the title for that uh chat should be um let's just use the the the message let's just use message uh message is a string yeah so the prompt from the user is basically title you see this when you open cat GPT it usually shows like the first message you can also later rename this which we implemented so here we go um let's say I get a result at this point uh we are in ASN context so that's fine okay we got a result which is white um this is not so cool so probably um at chat should actually return something okay then at chat returns a SQL light run result that sounds better okay with a sqlite run result we should be able to get like the created chat ID which was automatically created so result. last insert row ID sounds good to me with that in place um I want to make sure uh that I set this locally so let's also add some State here um const chat ID set chat ID this is going to be um is it going to be a number um I wonder no it's more likely going to be a string actually um string or null let's just set it to an empty string for the moment oh no okay here we go okay um and once we got this we can say set chat ID chat ID uh two string and finally because this is a message we are sending we now want to use that chat ID to also add a message and adding a message message calls for the sqlite database which we got from the context uh then for the actual IDE of that chat and then the message so content is message and role is user cool um we should actually be able to now send this message um are there other cases when we want to yes there are so if we get a completion we also want to store that and this is probably going to be a problem so we left this comment here as well uh as I said about 2 hours ago and the problem here is now the following I will I will put in a lock um save uh bot message to uh and then I want to make uh show you something so at this point we would use my State uh the chat ID okay no big deal so let's give this a try uh I will put this up here let's do a refresh and then check this out okay we already on the latest database so let's just try explain react native like I'm 5 years old I will hit this okay um okay I should have probably had released that lock but uh up here we see getting completion uh getting completion has a result do we like save that file um stream ended okay didn't we like put up a message once here if messages length equal uh okay yeah I got the result uh I'm a bit confused so the result up here should be the SQL light result right yeah I think it is uh it's just not helpful what I locked up here I should have locked the chat ID that would have been way more helpful anyway um what we notice is that most most likely we got a chat ID up here but once the stream ended we see down here save bot message too and there's no chat ID here so the problem is we are using our state and let's maybe do it uh once again so I can also show you this that we do have a chat ID and we do set this chat ID up here so here we go there was the lock um get completion that's the result and chat ID is two so previously we had chat ID one now we have chat ID to but once again when this completion here finishes uh is it finished already no it's probably not we're still getting some chunks but once this is finished and we try to save the butt message we are not getting the right chat ID why is that the problem is that we're creating this handle message function here uh in use effect and then calling it uh or attaching it to our ad listener so it's like created in the beginning and does not get the changes of our state so when we try to save the message it's like still acting on that Old State and it's not having the chat ID correctly so if we want to also change or save the message here we need a better way to access the state correctly and there's actually something I found on of course stack over over flow so react use hook event handler using initial state so we are using the initial state with the event handler and not getting the latest State how can we fix this we can actually overcome this by using use ref uh so where's the example we want to create a ref so we're changing the set function of our state a bit here then we're using uh ref to it and having our own set function so you see instead of having the US set we will now have this set function and once uh we want to use it we can use the ref. current to get the value and if we want to update this thing we can just call set active just like we would usually do okay I hope this makes sense and I hope you notice what the problem uh was here so I wanted to really run into this upfront okay let's change it the way we're going to change this to underscore set chat ID and we're going to create our own function uh set chat ID with a value could be ID string uh let's call this ID string and then what we need as well is the ref so const chat ID ref equals use ref with the current chat ID State and then in my custom set chat ID I will set the chat ID ref current to that ID and I will also call the underscore chat ID to correctly update my state all right if I now want to set my chat ID I actually don't have to change anything I can still use it but it's now calling this function instead uh which will update my ref and if I now go to my use effect and the block here where we had the problem I can now change this to um this should be chat ID rev. current all right let's give this a try um when I open this up I will do explain react native once again so it's logging a bunch of things and at the end once this is completed we hope to see the right chat ID being locked because we're now using the chat ID rev. current and here we go save bot message to three this is the new chat ID that we wanted to see okay um let's actually save it now um so that's the place we just call add message and co-pilot is probably able to figure this one out so Pars in chat ID ref. Curren this will give us the right chat ID and then for the content we're using the last message that was added because that is the one that's currently being created and the role is the bot cool um so we can remove our loock statements I will also remove this one which is spamming everything and then we can also remove a bunch of things in here great um let's do it one more time uh because then we can actually uh see like a real result let's do um I don't know recommended dish we haven't done that before um you are now probably interested also in understanding how we can debug this and I'm interested as well and I found this always to be somewhat challenging okay um I'm going to show you two things uh or indicate how you could debug your SQL light database because it's not that easy um if you deploy your application through excode um to an iOS device not to the simulator you can usually go to like window uh devices and then pull out from the package of your application the database um it should be a sealite database if you are like we do here run this in an emulator simulator there is a file with a path and I will now take that path and open the path okay it does not exist that is always great um but this one should exist and there we see we see a bunch of images which are stored in our application and we see also mm KV storage and we see SQL light with my Chads DB if we now want to check this out we can use a tool like DB browser for SQL light or you can use any other SQL light tool and then I want to uh open a database I will drag in my chats DB and open it up and we we can see I assume I can't zoom into this thing okay so that's not a gigantic tool but um we can see the tables and we should be able to browse the data and here we go these are the four Chads that we just created you can it's probably really really okay hard to see but you see this is the text recommend Edition that was the last thing we added this is the chats table um so they have the ID and the title if we go to the messages we see that they have the column for chat ID and we can see for the last one where it finally worked we have two items recommended dish uh which was from a user and then we have the next row which is the result from cat GPT with the rollbot so this confirms that our database is working and if you got problems this is the way for iOS at least how you can debug it on a uh simulator again for the device you might have to go through xode devices uh select the package that you installed on your device and from there you should be able to find the file and bring to your computer um if you're interested in learning more about this there's also a SQL light course here on galaxies and in this chapter we talk about debugging um for Android this is what you can do you can run ad shell to create a shell and then execute the command ADB pull with the path to the file which you got from the file system previously or Lo and then a local path so that basically pulls out the sqlite database from your emulator or device to your local hard drive and then you can follow up by using a tool to inspect the SQL light database okay um we are confident that our logic is working uh we have the migrate statement we have the context so now the next thing is to actually load that data and see if we can navigate to different chats from the history loading our chat message should be fairly straightforward but there's still a few things we need to be aware of so let's do this um we first of all want to probably change a bit the appearance of our app because we want to now be able to navigate to a chat with a certain ID which means I have to use a new file here like id. TSX now what I don't want to is like copy all the content of this file into that file so I have like a duplicate code that means I will actually extract all the code that we have in New and put this under a component so I will put this under uh chat page. TSX uh and I will now call this chat page and Export default chat page down here good once we got that we can go back to like both the ID and the new file and we simply insert one thing we insert export default from and then add components chat page and this goes to both ID and new what is the result of this change well first of all our app still works and the general change is simply the both of these are now pointing on using the same component but still for Expo router we do have two files in our router in now as you can see this will also make up this new ID page appear here automatically because it's automatically picking up files we're going to talk about that in a second so for the moment this is our new setup and all the changes we do will be now inside the chat page so that means in the chat page I should be able to get the ID uh let's maybe put this here it's related to the DB anyway so const ID and you know what follows equals use local search params from Expo router uh and again we can use ID string and with that ID we can put this uh into our state here so this is the initial State value of my chat ID and then I will also if we do have an open AI key of course uh add a use effect Block in which we're going to load my data and this should have ID in the depend array so this should be called when ID changes and if we have an ID so we could still enter that page without an ID we want to load my transactions so let's say um load for chat ID and then we can simply call the according function uh get messages from our utils with the database we're paing the uh ID and then we should get some messages which we can then set to our state that should hope hopefully be everything okay uh messages yeah that's actually working nice but our types here okay sounds good um let's put a look in here uh got messages and fine now this won't change anything so far for the default page because this does not have an ID this only happens if we navigate to that page with an existing chat ID which we could actually fake but well we're going to get to that anyway in a second um um so let's bring up our layout uh not this one now we're all actually talking about the draw layout okay now it's getting a bit more complicated by the way there's one thing I noticed if we pull up the keyboard and then open the side menu it looks kind of ugly if you also notice this and want to prevent this there's something called is draw open that you can use so you can use cons uh is draw open and then use use draw status and check if the status is equal to open so that will indicate if the draw is open or not and then you can use a simple use effect block use effect um let's close this accordingly which will be triggered when the draw is open so when they basically changes and in that case I want to call keyboard. dismiss okay super simple trick here you see keyboard open I open drawer keyboard closed keyboard is open I open drawer keyboard is closed cool um just another of these little tiny nuggets that I think are really really helpful from these clones now next thing we need a load chats function going to be an Asing function and this will be called here when we open the draw as well maybe we could actually do this like if um is draw open only in that case I want to load my chats uh let's see if this works before I do it loading chats okay I close I open loading chats I close nothing I open Lo y That's good okay so whenever we open the drawer it will try to load my current chats we can get the result Again by the uh statement we prepared before so let's call await get chats um there's actually nothing we need to pass in here um and then we can call uh let's call this history or something like const history set history it's going to be an array of chat okay empty array and use state from react um this one expects okay this actually this expects our data base so we can actually get this using use SQL light context and pass pass it in here so it's accessing the right thing and then we should be able to call set history with my result uh type unknown is not assign what to type okay so get Chets should return an array of chat okay this is this um uh this is again the stuff that this function already makes it an array yeah that's better okay so now it should work correctly let's see should I we Q This is likely a bucket react okay whatever uh let's open the menu we expect yes to get some chats we're getting the chat B data remember we've seen this in the seq light browser which I have not opened anymore um but these are the chats I want to display um let's just try and display them in the right place so we want to put them below our draw so here we got the draw content scroll view this is basically these items I want to place them below this but still in the scrollable area so I just want to do it uh down here um and I I'll say history. map so for every chat I want to create a new drawer item uh the item key is going to be chat. ID uh and then we have the actual uh drawer uh no we can we can directly do this I think we can directly attach a label here yeah uh item dot no chat chat. title uh and then we do need an onpress so onpress should navigate to that new chat which means we should use the router yeah uh cons router equals use router from Expo router uh and then when we press this new item I want to call router. push and now it's going to be an interesting path uh all check new nope not new but uh chat. ID um and then we still missing one of the brackets in here this should look fine I think cannot read property length of undefined uh how do we initialize history uh like this mhm okay okay here we go this looks promising this looks promising we got my chat history and we've created draw items for all of the chats they usually have like the the first prompt or we will soon be able to also rename them and we can also change the inactive tint color to be something like black so then it fits more nicely into this cool um I also want to get rid of this year uh but maybe let's try what happen if I oh it just works it just works it just works we did an awesome job if you made this work you can be really proud of you because we store the stuff through SQL light which is usually not easy we read the stuff and we're using the idea for the navigation and also use this H with with a shared component here that's loading the ID I'm it's just this is good this is good stuff I know I'm kind of raving about the con over wrot on my own but but I still think it's good and it's it's a good moment to appreciate what we've created and this was definitely not easy I was kind of scared to do the the SQL ey chapters of this course uh because that's always really scary to do okay um that means we can go to the different chats as you see we are loading the history wherever we go and if I go to this one it's still calls for the new page good this feels so rewarding but there are still a few more things that we want to do so if we check out the menu we should see a problem and that is this here as I said Expo router is automatically using all the files to generate a route and we're passing this to the drawer and the drawer is usually uh using all the props it gets to create the default draw item list that means we need to prevent our ID page from showing up here we can do this so let's simply copy the draw chat new screen thing here and do it here and we're going to set this up for my uh page chat ID um we don't really need the uh this part for the title we also don't need this one um we actually also don't need a draw icon because the whole idea is that we don't want this to show up in the menu and the easy fix is to use the draw item style and set display to none this should prevent the item from appearing in the menu but we still have um the configuration for that page so if I go into a page we now see that we get this button which is the the header right we defined here for the specific chat ID okay hope that makes sense we have an entry which defines the settings but it's not simply not showing up in the menu because we St the display style here to none cool um there just two things actually left and that is how we can now finally remove a chat and how we can rename the chat um maybe we start by creating the functions uh so there's like the const on delete chat uh which gets an ID and then we can remove this and then we have const on rename chat also getting an ID um and then we're going to open up something to rename it cool to trigger these functions we're going to soon add a context menu because it's just too easy um but let's quickly Implement them so to rename a chat we're going to use the react native alert view with a prompt uh rename chat enter a new name for the chat and then we do have um an async function here which gets the new name so if we do have a new name at this point and let's see if we get the brackets right probably here one more um if we do have a new name we're going to call rename chat from our yoube file passing in the database passing in the ID of that chat and the new name and then we're going to reload our chats okay that should work uh if we want to delete something I want to call the alert as well uh alert. alert delete chat are you sure you want to do this uh and then we're going to show some buttons so the first one will be text cancel and style cancel and the second one will be delete which then calls our delete chat with a database ID and finally load chat okay that was pretty easy nice now let's see how we can connect these functions to the chats so um in the chat GPT app there is uh I was just confused okay it's in the right place um there is also the context menu which you can use on iOS and we're going to just do it ourselves for the history items in here so for all the draw items so we can just wrap this draw item in a context menu therefore I will say context menu okay we probably need to bring in the context menu first uh up here import context menu from zego and then dive into this so context menu first of all needs a root let's close it uh key is chat ID so I can also remove it here from the draw item now and then we need the trigger so context menu. trigger the trigger will actually be my draw item so I we just copy this by the way we should be able to just autoc close this okay draw item goes into the trigger and then we need the context menu. content um that's interesting is this correct uh on press type ch uh probably not correct um these also need a key by the way so let's give this one the key uh rename and the other one gets the key delete but the context menu item requires a bit more I think it requires not just a string uh but actually a context menu dot item title this is going to be rename name and then a context menu icon can you figure this one out that would be cool nope we can't uh do item subtitle indicator let's use an icon here um we can use iOS equals name uh pencil no not pencil Circle let's just use pencil and once again my favorite property that does not exist Point size and then we close this and we should have an icon cool now let's put the same stuff into our delete function this one's going to say delete then we have a trash icon and why are you not happy um oh it's because on select is the name not on press let's hit save and see so good so rewarding let's see I want to rename this to Simon's rename and this is just good it's just good if you can Implement that sort of like functionality in your application people going to love it people will not notice that this is a react native app it's just it's just good um if you want to release or remove something yes I want to delete this and of course it works because our database provider is in perfect shape to handle all of that stuff this is like I will love to play around with this for a minute and I recommend you do as well so we can just like rename stuff it shows up you can still go into this you can still go into a new page um we've done really a lot in this one uh there's one more thing if you check out the cat GPT app you're going to notice that this here sometimes shows like the whole prompt I don't really have the data right here to show The Prompt but I will just give you an idea of how you could do this so in the context menu content you can also o Define the context menu. preview this is the preview you see up here um and then M and this needs to return a function so it looks a bit weird but this is the way it goes and then we could have some sort of view in here I will just use the chat title and I will use like let's give this for example a hate of 200 so maybe you want to display like the last image or any kind of image that was found and also I want to have the background color white because right now it's not really white okay so if I hit save now and do a little refresh oh I should have closed this before yeah that was oh pretty sure that was going to crash okay let's wait a second until this is up and then we should be able to see my preview uh unless I now completely destroyed this no here we go we can still load my chat and here is the preview so he of 200 uh maybe should set like a bit bigger width of oh what was that uh width of something like 80 or so um this actually pretty small oh 80 is really small what if I do like 150 it's so good it's automatically changing in here that feels so good what is the size of the box below it seems to be 250 so 250 seems to be a good size here and then you have a nice preview you can even Center your text you could have like align items uh Center I don't know if this is going to work but let's see um yeah can we also justify content Center yeah and we have everything aligned uh in that box so this is how you could also change that preview window again love zego I love the context menu uh I love the drop- down stuff it is such a great Library by Fernando Rojo can't recommend this enough but uh what I can recommend is the next part of this clone because we are adding even though we're in this like three four five hours I don't know we're taking one last Act of amazing things because we are now also integrating payments into our clone with Revenue kit we have come to the last but certainly not least part of our course now we want to add in a purchase to our C GPT clone the idea is simple we want to let's say prevent a certain thing like DL access only to users who enabled that features so we're going to go through the whole flow of setting up Ina purchases through our app and using Revenue cat for that so Revenue cat is also the co-sponsor of this video uh I've worked with Revenue cat in the past there's another video which you can find and this part here is basically this could be its tutorial on its own own because it will take us a moment to set this up because in a purchases are usually not that easy but with Revenue C we can make this work in a crossplatform way really really easy I think there's no like easier way to get started uh and you can actually do this completely for free with Revenue C up to 2.5k in MTR I thought it's called mrr monthly TR Revenue okay that's a different thing so if you earn 2 and 1/2k from your in app purchases I highly congratulate I never did this before uh and it usually means your application is already pretty successful and I think in that case you will be able uh to pay that 1% on uh additional income so you can create an account get started for free whatever you prefer and then let's see how we can do this um maybe we actually start by integrating um the package first of all so what we need is we simply need to install the direct native purchases package and because we're not using Expo go we don't have any problem this usually wouldn't work with Expo go as far as I know so we need a real app what we also need to make a purchase is I think a device this does to my knowledge not work great with a simulator especially on iOS there was a post uh on iOS 14 plus you can test on a simulator you can test Revenue kit with a simulator however I went through the dox here and was like at a store kit configuration file in xcode create a new scheme for testing do this setting up the configuration file uploading a certificate and then you can test this and I didn't want to put you through this as well uh just want to let you know that if you want to test this on a simulator it should be possible at this point however in our case what we do we can simply do um where is it npx Expo run iOS D- device or of course you can also do this on Android by the way this is also finding my device I will dive directly into Simon's iPhone and just give this a try so I hope this will deploy uh to my iPhone we're going to see because we actually also thank you reflector yeah um we have to do a bunch of configuration within Revenue cat first so maybe let's expand this a bit and then try to get started so I will walk you through what's required at least for iOS and then also indicate what's necessary for Android let's start by creating a new project in Revenue cat and I will call this cat GPT video all right uh inside my new project I now have to add the App Store so I will get started with iOS and then we have the app name and the bundle name so this is like chat GPT video app my bundle ID is what we have inside our app. Json so somewhere at the top we should find this com super Simon chat GPT now it gets a bit more challenging as we need the uh App Store Connect app specific shared secret so how do we get this well let's take a look we can have to log into App Store connect navigate to my apps under app information General select manage in the app specific shared secret okay that's a good point but I actually haven't created the app yet so let's also do this let's fun uh let's go to App Store connect let's create a new app uh platform iOS I will call this chat um video app primary language is English uh I don't care UK US my bundle ID uh oh can I is the problem the problem is that I actually created this chat AI clone previously and I used the bundle ID or exactly the same bundle ID in this one so this is anyway the view you should see after creating your app um and we are still on the hunt for our app store Connect app specific shared secret we should be able to find this under app information and manage okay so let's go to app information uh uh uhuh here's here's the app specific shared secret I can manage this uh I can regenerate this I can copy this over and put it uh in here how can I put it in here uh generate and copy enter the share Secret in Revenue C App Store enter Revenue C dashboard why am I not allowed to use it um okay okay I have to click this and then set okay this is good now the next section is also required so the inm purchase configuration here is required this is a bit more complicated uh but again Revenue cat is usually walking you through how you can get that so generating an in a purchase key happens as well in app store connect so under users uh and access we have Integrations and I already did this before so I will do this again let's call this chat GPT video I will generate this one uh then I can download the inapp purchase key so I got this up here uh also this is the key ID I don't think I need the key ID but I need the issuer ID so issuer ID is copied now let's see um I think I just need to drop that file here why is it a subscription key that sounds strange to me but maybe Apple just change the names um so let's see chat GPT video we got the key ID key ID was obtained correctly from there maybe you put this to the side here this is actually not the one you see it's quite complicated you can go wrong many times but uh I created my key ID here and revenue Cat found that key ID and the issue ID went here and I uploaded the file as the p8 key file from App Store connect so let's hit save here and the app is created successfully um you can then also set up Apple server notifications in here if you want to uh you don't have to do this right now you can also configure the App Store connect API should we do this uh I think it is usually a good idea to also configure this uh how do we do this uh create an app store connect API key so where is the window I had before up here uh we're going to have to go to Integrations again and then App Store connect API I actually have this one uh but I'm probably going to do another one so let's add one more so RC video uh then we have App Manager role we generate that uh then we can download the file I can only download it once yes I'm a very well aware of that uh and then we're going to have to upload this to revenue cat again so let's drop the file into Revenue cat we need the issuer ID again okay so issuer ID and the vendor number uh the wender number the wendor number is I think your uh yeah this is visible once you go into the payments and financial reports page so let's hit save with all of this information here and then our integration with Apple for this should be configured now you can do the same in here if you want to add another store you can just go the same for Google Play App name package name in that case you need to create a service account credentials that is not too hard it can just take like really long to get that and you go through the Google API console you enable this and you create a service account through the um account settings it's really pretty much the it's maybe even easier and then you can download that file uh and then you should be fine with all of that okay we will just stick to this for the moment um what else do we need well we now need to configure our products in Revenue kit uh so let's see usually under products we should be a I don't know if we can actually like obtain our products that would be so cool let's try oh I haven't created products uh uh yeah okay okay okay yeah yeah yeah good I understand what's going on so let me explain uh this is the Chad AI clone and I previously set up an Ina subscription here called CET GPT Pro that is what Revenue C found I actually don't want to use that so let's go through how we can set up a simple consumable an Ina purchase together um right now I don't have any in a purchases so this is going to be uh consumable reference name uh what's the reference name that's a good point um let's say enable D in the app and the product ID is usually you want to make this a combination of the product uh and the price so let's call this Del um I don't know $3.99 and this is going to be a consumable okay let's hit create okay I have a typo there but this shouldn't show up in uh in the user area Okay um let's set up the availability it's going to be everywhere let's set up the pricing this should probably be$ 3.99 if I call give it the name 3.99 um hit next hit confirm then we have the pricing set up uh then we have the App Store localization uh display name let's call this enable Del features um use di for image generation create okay um App Store promotion optional optional things are things I don't want to do right now so let's hit save and then we should see our Ina purchase in the list uh of the items here cool if I now go back in here in Revenue kit and select this because I added the App Store connect API key I am able to import products and this makes it so easy so I se here's no do I can hit import and it directly Imports my product into Revenue C I really love this about Revenue C and like how easy these things work so now you can just go ahead um you could by the way now add your products here from Google from the play console no problem then you usually heat over into the next thing so they're like three things you need to configure products are like the things we do in uh Play Store in app store connect like the real items people purchase then we have entitlements which are like the user entitled to use something and then we can also create groups of offerings but let's do an entitlement first uh I will call this um use do this is the entitlement or let's use this as a description and the identifier is just DOL okay I hit caps no problem in that or in that entitlement I want to now attach the product that we just created before and here is also where you could like attach multiple products from different platforms and that would all share the same entitlement good let's go back we have the entitlement we have the product now let's finally create the offering an offering is a selection of products that are offered to a customer on your pay wall so this is cool for like testing stuff and experimenting uh we're just going to create like a default offering like standard app features you can include some metadata we won't do this right now um we can now go into our default offering and add a package um monthly no actually this is going to be like a custom package I assume um let's see where we go uh description do we actually need this I wonder yeah I think we need this um so how do we get this product in here uh let's call this uh custom I identify I don't know DOL and then unlock DOL I don't know how many times I know said unlock DOL okay but this is the one package and I will attach my product again in here so here we go this is my final package that will hopefully be available inside the app as an offering so offering can be used to test different pricing combinations um is just a really great instrument but you can also use entitlements this should be everything in terms of the configuration in Revenue C and this took us about I don't know 15 minutes um including the app stores which is really really fast you know we we created a native app and App Store connect and got the the inapp stuff to work with Revenue kit and it also feels good so in the past many times I had to like use these IDs use prices and put them in somewhere and it always felt like there's a disconnect between IOS and Android and the platform and the tool you're using for purchases but here with this import functionality for the products I feel so much better I feel like Revenue cat is actually Revenue Cat knows what's going on they will be informed about pricing changes I do in or connect in other platforms so this feels a lot it feels a bit like using typescript basically like you maybe in the past you also knew your code was working but now I can kind of see this and get a validation for it okay so um I do have the app now up and running on my device I just don't see it right now I probably have to like sign in let me just log in with my device in our custom Expo def client I do um do we have a preview of that so here's my application right now uh if I hit refresh I should see cat GPT on Simon's MacBook Pro um and then of course it messes up everything for a minute but here we go we are inside the app now in the meantime I will have to uh lock in again I don't know what kind of password I used um probably this one or at least I hope so um let's see if I'm able to get there yeah the problem is always if I use this Dame reflector application I can't see any alert that's going on in my application and this is so unbelievable conf confusing okay app is finally up and running I'm signed in and now let's see what we have to do so we install the package and I usually like to put the revenue c um logic into its own provider so let's create a new folder providers and then call it revenuecat provider. TSX that's actually a great post uh I don't know I will put this to the side for the moment so we can focus on creating that provider um there was somewhere a great post about creating this so here it is um in a purchase tutorial from Josh love that uh it's really great and easy way to get set up in his case I think he had some code somewhere uh uh uh in a purchase somewhere somewhere somewhere here's the react native app so what he used was I actually used this directly he did not create a provider in my Galaxy tutorial I did create a provider and I really like that so maybe let's just do it on our own what we need in our Revenue cat provider is first of all an API key so our API keys will be under Expo public RC apple key and RC Google key so let's put these uh into our EnV file and no I just noticed I have to do a build again why did I do this to me no okay anyway um let's see we need to find my uh Chad gptv video key from revenue CIT so this should be under API Keys um public app specific API key is it this one um Apple yeah because I have only configured for App Store we only have the apple key um for the Google key that would look something like Google goo and then uh a different key we don't have that right now okay uh that also means I can already kill this again and then run this command once again to deploy it to my device such a fun anyway um back to our provider So within the provider we want to set up a few things um I want to first of all set up a little interface with some information uh let's see we can use customer information from react native purchases and we can also import uh purchase package which which is usually the name of a package that you want to import uh that you want to purchase user state is something I included myself so the user state of our provider will include the information if the user has access to Deli or not okay this is the basic setup and then once we've wrap the provider around our app we will be able to get purchase package restore package get the user State and also get the packages so we set up the whole Logic for like loading the information from revenue C in this provider um in order to do this we going to use the Lo uh the usual logic to create a context I'm going to add the import this is going to be a partial of the revenue cat props and then we make an hook so we can use this more easily in our application and then we finally come to the actual provider so export const export con Revenue cat provider uh is this correct correct I don't know we can add the typing by the way we can use children and then react react note in here uh export cons Revenue we don't have the export correct yet uh so the export would look like return Revenue cat provider um no Revenue cat context actually Revenue cat context do provider and then the children okay that would already make this somewhat happy do we need this part here no but now it works okay this is our basic provider and in fact we're cool let's just put this right around our app uh probably where we did the the SQL stuff because this is the inside area so I will wrap this around my inside area around the SQL light provider and just say import Revenue cat provider cool this shouldn't break my application and in fact my application is still showing up which is a good sign so now we can continue with the provider what are we going to do in that provider that's a good question um first of all we want to keep track of some state so we have our user and we have set user which is using our user State and we'll set the Del purchase to fults then we will have some packages these are the packages users can purchase Cas and we will get that information from revenue cat and then I will use something like is ready um set is ready and use fult so this should be ready once our Revenue C provider is initialized correctly this also means before we return we can check if this is not um is ready then we will just return empty fragment okay now we can get started and load our information so let's put in a use effect that's executed once when uh the provider is loaded so empty dependencies array and then we put in a simple init function which is going to be an async function can close this and then we can call the init function and now we get started so we first of all check if the platform. is equal to iOS uh then I want to do this I don't know if I want to do this this sounds interesting but I don't want to do it um I want to call purchases. configure and pass in my apple key but we have to pass it in as API key so API key API keys. apple and of course we could do the same now for Android come on just take that line it's exactly there it's not too hard okay uh this should be Google okay that would be the Google key case um additionally after that I want to await these call because the configure should return a promise I'm not too sure if this is a promise actually maybe it's not a promise um I don't know but we're going to keep play it safe here once this is done we can already set uh is ready to true because then our app is basically initialized for debugging I will also call purchases. set log level and I will set this to log level do uh debug This is highly recommend while you work with this um and then we can dive more into what Revenue C actually offers so let's create a function load offerings and this function will load guess what all the offerings we will then also create a function uh let's call this update customer uh information uh information let's do also an async function let's do another one Con purchase package um this will get a purchase package that's correct and then we probably also have something like restore permissions now all of these things need to be implemented but we can already follow this up down here and create an object uh which we can then pass to our provider so it could look like this uh yeah let's call this const uh value and then down here for Value we Supply our object uh what are you mad about what is missing here user packages uh purchase package restore permissions what is missing uh only I mean the implementation of the packages is missing of course but what is this typ prom not assignable type yeah okay uh um which one is that actually let restore permission yeah these should return something so we need to implement them no problem um loading the offerings is going to be pretty easy and we're going to do this right in here so I will call load offerings right in the beginning because as it says it will load the offerings from revenue kit additionally I want to configure purchases to um listen so whenever the at customer info update listener is called uh we get back some information and I want to pass this to my update customer information function so this is basically uh when something about the customer changes in Revenue CIT uh our app would be updated so let's call customer info uh type customer info here and then we should be able in here to call our own function let's see um update customer info with the customer information okay let's put in a lock as well log customer info and now let's focus on load offerings because that's the first thing we want to do and by the way we should pretty soon see some locks about this um again make sure you run your app on a device or actually in a simulator you might be able to like receive the uh initial offerings and stuff you can just not purchase them so getting the offerings from revenue c is now pretty easy we can call purchases get offerings um and then I want to check if uh offerings. current uh so if there's something included I want to set the available packages here to my current packages let's put in a look as well because this is quite interesting uh to see how the data looks and if we're lucky we are now getting an offerings object and that offering objects includes all and default um so remember uh or maybe not remember maybe I should show you this um we configured our offerings here and we now check this out we have an identifier default included here uh we have standard app features which exactly maps to the text here in Revenue cat and the default maps to default and then we have available packages included and if I dive into this uh we have this one package up here which is called identifier Del um package type is custom then we have the type uh enable do features this is the actual product included so if I would go into this uh I would see this um I wonder this is I think the product here use deli I wonder where use deli for image generation where this is coming from but you see this is also getting the right the correct price and a Del features I actually think and this is just uh an assumption I don't know if this is correct but I think this information is coming straight from exco from App Store connect let's verify this because this is quite interesting so if we go to iner chases yeah that's uh what I thought so my reference name in app store connect is enable Del in the app uh and this is exactly here in the information from revenue cat Okay so through the API Revenue cat got all of that information um the pricing also here display name uh and description so enable do features again that's here and use d for image generation that text appears up here in the result so this is what I meant before I I am not working on some like identifier string I really got the confidence with Revenue cat that the products are mapping to the right things and I can then include them here with my entitlements or uh with my offerings um cool this means we do now have something uh I oops I shouldn't have closed the debugging can I just get that one back um I'm not getting this back uh but we are setting my offerings to offerings. current uh yeah in offerings. current we have available packages so at that point we should have packages okay I will also do another lock of this up here maybe let's do it here and then we do a refresh and then I can confirm that I have now one package that our users can consume or that they can purchase good um let's see let's continue to purchase uh our package we want to try this uh we want to try to await purchases dot um purchases dot uh purchase package and I want to purchase my peeg now this is pretty much enough to trigger like the whole flow of purchasing something in the app um usually you're going to have like multiple identifiers you're going to have like the chaos crystals and the gems and whatever you can unlock or unlock no ads uh and then you want to check what kind of identifier was used so in my case I hope or I think the identifier of the product uh should be just Dolly let's see if I go back here yeah the ENT identifier here should really be DOL okay so if my identifier at this point is Del of the PEC let's put in a lock here lock purchasing pc. identifier if Del is true I want to update my user data and I I honestly want to do like an alert here uh usually uh or or some other view I will comment this out for one reason and will just put in a look if whenever I do alert my iOS device and the reflector app I use here like Drive crazy and everything crashes so that's why we'll just add a lock in your case I recommend you just put in an alert um then we probably going to add a little catch block so something like purchase error uh by the way you can now test um if uh not let's see if not error dot uh there is is a field called user cancelled so if the user cancelled you pretty much don't want to display an error but if there's an actual error you can display it um so if it's not user cancel in that case you probably want to do an alert uh alert. alert with the error message okay cool that is the purchase function uh restore is pretty easy you can just uh get the information from the customer so you can say customer equals await purchases. restore permissions and revenue kit will handle the rest and then we can just return the customer here I actually don't know if we're going to use this I just want to include this because usually you have to supply um a button with restore purchases now the only thing missing is update customer information as I said this should come in right in the beginning when the uh Revenue C loads this should be triggered and this is the point when your app starts and you check what kind of entitlements the user has so let's try and get like the the user uh and setting the user state to DOL and then user. D all right and close this the whole idea here is to just simply update our state so what we do next now is to check if this customer information that was supplied if the custom information do entitlements do active Has a Field uh DOL uh although I'm not sure if it's DOL or something else um then we want to set the new user Del to true and update my state with that user but again I'm not entirely sure uh if let's try to reload again uh already here's the customer information object um would be really helpful if I could like zoom into this oh finally it works oh I'm so sorry that I found this after five hours in the video okay um here's our update customer information object and we want to check the entitlements that are active so under active there are no entitlements uh under all there's also nothing so again I'm not exactly sure what the uh entitlement looks like but we're going to figure that out so we are at a point now where we can check if the user has the DOL feature enabled and we can use this now to our advantage okay that sounds kind of bad but uh we can use this let's say in our draw layout in the draw layout I want to prevent access to DOL so somewhere down here we have the draw screen DOL and if you want to prevent users from getting to that page by the way can I reload you as well you should work you should at least work for displaying the stuff that would be cool during development wouldn't it yeah nice here we go we got our epic um if I want to prevent that click event from happening then what we can do is uh we can go into Del and add outside of the options a new object called listeners so that took me quite some time to figure this out uh but nonetheless it's super interesting and you can access the draw item press prop uh here which gets an event and then we can check in here so uh let's prevent the default I don't want to do any navigation I just want to put in a little lock here so Dolly let's see if I go here and press Dolly you see nothing's happening we have successfully prevented The Click event here now let's see how we can get our user that's why we created the provider in the first place so I should be able to get the user from the use Revenue cat uh hook here and within that press event I will now simply check if user. D is enabled in that case we can navigate to The Dol page uh this should just be [Music] under uh all uh DOL is not a folder so because we're using brackets this should actually work I don't know why it's not yet uh what is navigation here is this use navigation uh I kind of want to use the router I feel more comfortable using the router to be honest cons router equals use router uh oh oh oh oh is this the right router I feel like this added a oh we're good we're good okay back to this and then let's use router. navigate to cannot find router didn't I just edit like a second ago okay bear with me I've been a long time in this clone now as well just like you okay so uh I'm not user so if I had Dolly I could go there I can't so let's create our own model to purchase this this now uh I swear this is the last page you have to do so purchase. TSX goes in here react native functional export let's call this a page and then we can tell this in this case we want to go to all slm model SLP purchase um we also probably want to include this now in the upper navigation so the remember the models are part of this layout file here so we have the draw we have model settings this is somewhat similar to modal settings so I will copy that block um put it here this is going to be modal SL purchase uh I want to have no header title I want to make this a full screen model uh header Shadow visible fult I don't really need a background style uh and then for header left I want to have if I can go back I will have the router back with close outline um let's not give this a background color let's just use a border radius and pading and maybe gray light here okay let's see and we see nice modal coming up actually that size should be way bigger in this case um yeah okay so we have no Deli features so we are guided now directly to this purchase screen and of course you can now do whatever you fancy on this screen but most importantly we're going to get the packages and the purchase package from our use Revenue cat hook all right here we go additionally we might have to respect once again the bottom area so use Save area insets you should really get used to all of this by now now uh then we have the router which we probably need for some sort of navigation use router from Expo router and then I want to find the right P because in my case I don't want to display like all the different packages I just want to find the right P so let's use uh packages. find and we're checking if the identifier is equal to DOL okay that's not how you spell Del this is it and then I'm going to put in a little lock here and if we're lucky yep we see on this page it shows my uh I can also do it here again so you can see it in a bit better way uh um um am I already on that page this does not seem to work correctly uh oh yeah I'm attached to the wrong thing I need to attach this to my iPhone 15 uh let's close this again and go to Del so here it is this is the pack that I want to purchase we got all the pricing and the information included so now we can just create a view based on that information because we're like 5 hours probably into this build let's hurry this a bit up so we got a Styles sheet with some header image description and button text this is really nothing new for you um and again the final not is that you can find all the code available on GitHub now I want to use the view the surrounding view including my cool default Styles uh and then on the page I want to first of all have a little text which says unlock more power then I want to present an image which is using a revenue C image that I found quite fitting for this case um so I I was kind of like the initial page on the lending page but look look how this works within this screen this is really getting a nice screen um and then we can have a text like get access to more features by unlocking for just and here we got the product price string which will then resolve to the currency of the user or whatever is uh which store the user is using so no fixed values in here I now want to put a touchable opacity uh below this uh so let's add all the missing Imports and this will allow us then to finally purchase DOL okay let's do this again uh and I want to place this button at the bottom so let's put in a view style um Flex one so this will spin uh or take up the rest the remaining uh hate here cool so our logic works now if I want to use do I'm guided to this screen and on this screen I can finally purchase Del and this is the final missing piece these are my friends the last lines of the chat GPT clone that we are writing together if you haven't hit the Subscribe button now would be a pretty good time because there's more coming in the future and I'm very excited that you managed to stay with me for such a long time okay I expect that PEC is set at this point so I can just call the purchase package function from our Revenue CIT um provider and then once this is done I will simply call router dismiss to dismiss this view um I want to also add a little catch block so in case something goes wrong we can catch this now I expect that this is not working because I can't purchase something here in the simulator okay I it actually shows the stuff but once you click through this it will never trigger the final event uh for the purchase so this is where I have to bring up my iPhone uh and actually use a real device for that purchase uh so let's put this up here okay uh is everything saved I think everything is Sav I will attach a debugger so we see what's going on um honestly I it might just I'm just I just wonder what happens uh once we purchase but we're going to figure that out so let's try I can't click I know need to reuse the actual device okay um where is it I want to purchase Del okay I will click buy now uh yes I want to purchase that funny thing uh what is my password I have no idea all right I'm done that was the done dialogue with purchasing D your purchase was successful in the sandbox environment the screen should soonish be dismissed um we got a lock from the customer info object and we see under entitlements DOL is now active yes it is active and if I'm lucky I get to the page oh this feels so good so good oh I really hope you also get this wow it just works now a moment um what happened well I used my uh App Store connect user uh I would love to show you the right place where I have this open under App Store connect you can find your uh sendbox users this is the user I used this was not a real user and by the way you can also click edit uh select a user and then clear purchase history that's really helpful during testing just as a quick information um what else did I want to show you now uh I probably want to show you what's going on in Revenue cat if I can find my instance of Revenue cat somewhere on the screen I got way too many views open at this point uh so let's see if I can still find this somewhere uh here's the C GPT video okay and we should see a customer um I want to see the scentbox data are we seeing the scentbox data no not really but to minutes ago that looks good cat gbt video project purchase my device whatever made a purchase ah and this is the entitlement this user now has the Del entitlement um this user is also seeing the default offerings so I can see all of that uh let's quickly check out our provider one last time I just want to confirm that we used the right stuff so customer information is chatting um if the entire Del is active now this is somewhat interesting this might not work I think this needs to check for uppercase do because that is the entitlement name and I want to I think I need to check if this is like unequal to undefined uh I think this is the actual check we need so now if this app reloads and I go back yeah I'm still able to go there and also from the locks somewhere um didn't I have like a lock view somewhere uh I wonder if your your screen looks the same you got like 10 different views open so this is my lock screen I will hit refresh okay running file already custom information entitlements yeah under active we definitely see that there's the key d now under entitlements uh which is is active it's also in sandbox mode purchase data and more information can be found here so this was a really challenging end for our colog but I think it was really worth it um because in many cases you're not doing this in the beginning you have to integrate this at a later point and we followed the whole process of setting up the revenue account creating your app adding an uh iOS item for purchase um configured the connection imported the products and entitlements and then built out our uh Revenue cat provider and all the functionalities to load the offerings load the customer information and finally make the purchase in a somewhat beautiful view I have to admit this view was pretty nice um if I wanted to use uh or make the purchase again uh I was just thinking yeah I can probably hit delete custom customer uh this action please type confirm so I will hit confirm here uh at the same time I might have to delete this uh let's see if I can just if I do a Reload it's probably maybe it's disabled um let's see yeah now it's disabled I could make that purchase again um finally because we just stepped through this on iOS I just want to mention uh again that on Android uh I used this before in our tutorial it's under monetized that you can set up your inapp products you can give them names and things you need to supply some more information sometimes but then you get like these ideas uh IDs and these other things that you can then use in Revenue cat to map to your products so if you then go to your uh you need to of course connect uh the Play Store here but then you should be able to add them under products and finally group them under entitlements so thank you once again Revenue cat for sponsoring this I really enjoyed working with this it was such a breeze again to see the latest features working and to everyone else this marks the end of our CET GPT clone I really hope you enjoyed this and learned a bunch of things and now have a cool project that you can continue to Tinker on all right and that's it for the Chad GPT clone I really hope you enjoyed this build I definitely had a lot of fun especially like the All the Small Things that came together the customization of the drawer that intro screen where we got the animation from Gary from Kendall um of course authentication from clerk uh Revenue kit in air purchases the image viewer component the context menus so many small things and I really hope you like these builds if you want to see more leave a comment below and of course support the sponsors of this video which are once again Clerk clerk.com for authentication and revenuecat revenue cat.com for Ina purchases the best way to manage your apps transactions subscriptions consumables and whatever you might have for different platforms thanks for watching this stay subscribed and I will catch you in the next one so until then Happy coding Simon [Music]
Info
Channel: Simon Grimm
Views: 13,808
Rating: undefined out of 5
Keywords: javascript, mobile app development, reactjs, html, react js, app development, ionic framework tutorial, learn react, react course, app developer, react native, ios development, ionic app review, react, reactjs projects, react tutorial, react native tutorial, react native app, full course react native, clerk, reanimated, expo router, whatsapp clone, fintech clone, fintech, finance, programmieren lernen, galaxiesdev, galaxies dev
Id: 8ztx68SUOQo
Channel Id: undefined
Length: 408min 31sec (24511 seconds)
Published: Tue May 21 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.