Now let's go ahead and let's create the settings for our keys, right? So when I click here currently it's A404 and my URL is slash you, my username and then keys. And again you can confirm this as well by going inside of your username components. So inside of the dashboard, you username components, sidebar, navigation, and confirm that you have the same href as I do here. Great, so what we're gonna do now is we're gonna go inside of the app, browse username, and just as we created the chat folder we're now going to create the keys folder like that and inside go ahead and create page.tsx.
Let's go ahead and write keys page and let's return a div keys page And now when you go ahead and try and clicking on the keys in your sidebar you should no longer be getting a 404 instead it should say keys page like this. Now let's go ahead and style this to show our label here. So I'm going to give this div a class name of padding 6. I'm going to go ahead and open a div with a class name flex-items-center-justify-between and margin-bottom of 4. I'm going to write an h1 element, keys and urls and give it a class name of text to excel and font bold and below that I'm going to add a little button component which is just going to say generate like this and give it a variant of primary like that so you should have a screen similar to this for now this generate button isn't going to do anything we're gonna come back to that later And now below that I want to go ahead and create a div with a class name of space Y4 and inside I'm first going to render the URL card like that.
So if you save you're going to get an error because URL card does not exist. So let's go inside of keys, create a folder underscore components and inside create a new file URL-card.tsx. Let's go ahead and let's export const URL card here and let's return a div saying URLCard. So very simple like this. Let's go back inside and let's import URLCard from slash underscore components URLCard.
And now I want to go ahead back inside of my keys page and I want to turn this into an asynchronous function so that I can load my stream settings. So let's get self from await get self. So import that from the out service and let's get the stream from await get stream by user ID self dot ID like that and I'm just gonna move this to here let's go ahead and do if there is no stream throw new error stream not found alright and now we can go ahead and pass some props here so let's go ahead and pass in the value of the URL card to be stream.serverURL which is one of our properties in here. So we're gonna use this to generate the ingress ID, server URL and stream key. So these three values that's what's gonna be controlled with this page.
So now we have to enable the URL card to accept this props. So let's go inside of the URL card here and let's go ahead and create an interface URL card props to accept a value which can be a string or null. And let's go ahead and assign the props URL card props here. Let's extract the value like this and let's go ahead and give this div a class name of rounded, extra large, bg muted and padding of 6 like this. Then inside let's open up a new div with a class name space Y2 and width full.
And let's go ahead and add a new div with a class name of width full flex item center and gap x of 2 and then inside I'm gonna go ahead and render the input so make sure you import input from components UI input here. And let's give it a value of value or an empty string like that. Let's give it a property disabled. So we're going to hard code it because this is not going to be something user will be able to change. This will be generated using this generate button.
So from here they're only going to be able to see it and copy it. And let's write a placeholder server URL if user has not generated anything yet. So now this should look like this. You should have the server URL and you should have a huge input here which says server URL. So now what I want to do is create a little button here on the side which will copy whatever value is inside so we enable our users to do that more easily.
So for that what I'm going to do is go below the input and add copy button, which we don't have yet, but we're going to create in a second and pass in the value to be either a value or an empty string like this and now let's go ahead inside of this underscore components and create a new file copyButton.tsx like that, let's mark it as useClient because it's going to be interactive let's create an interface copyClientProps let's pass in the value to be an optional string and let's export const copyButton here Like this and just return a div copy button. And let's go ahead and assign the props. Copy, not copy client, my apologies, copy button props. Copy button props, right? And value.
And now go back to the URL card and you can now import this. And I'm just gonna separate the imports. All right. And now inside of here, let's go ahead and modify this a little bit. So I want this to be a button component, so Import Components UI Button.
And inside of it, I want to go ahead and render my icon, right? So this is what I'm gonna do. I'm gonna go ahead and add a state is copied and set is copied to be used state false by default so make sure you import use state from react so it's going to change the icon when we click on it, right? So it indicates to the user okay you copied this and we're going to disable the button during that time as well so they don't spam. And now let's create our dynamic icon variable.
So if it's copied, it's going to use check, check icon from Lucid React. So make sure you import check, check from Lucid React. And otherwise, it's going to use the copy icon from Lucid React. So just make sure you have both of those here. And then inside of here, we can simply render that icon constant from above and give it a class name of H4 and width of 4.
And now give this button an onClick property of onCopy. Go ahead and give it a disabled property of if there is no value of if we have copied something sorry not exclamation point here so just or if we have copied it And in here give it a variant of post and a size of small. Like this. Great. So now you should have a nice little copy button at the end here and it should be disabled because we have no value here.
Great. So now let's go back inside of our page component and below that let's go ahead and let's render the key card component which is also going to be having a Stream.StreamKey like that. So now let's go ahead inside of components and create keyCard.vsx let's go ahead and mark this as useClient and let's do an interface keyCardProps here to accept the value which can be string or null. Let's do export const keyCardProps. Let's return a div.
And let's go ahead and assign the keyCardProps value here. Extract the value. Go back inside of the keys page and then you can import the keycard from components, keycard, great. And you can see that we have no errors when passing our value. So now let's go back inside of the keycard and let's go ahead and develop this.
So inside of this div, I'm going to go ahead and give it a class name of rounded, extra large, bg muted and padding of 6. Then inside I'm going to open a div here with a class name of flex items start gap x 10. Then inside I'm going to render a paragraph which says a stream stream key and give this paragraph a class name of font semi bold and shrink 0 and then below that I'm gonna go ahead and open a div with a class name of space y2 and width of 4 and then inside open a div with a class name wFullFlexItemCenter and gapX of 2. Let's go ahead and render our input component first inside. So make sure you import this.
And inside we're going to pass in the value to be the value or an empty string. The type is for now gonna be password, right? We're gonna change it dynamically later. It's gonna be disabled and placeholder is gonna be stream key if it doesn't exist. Great, and below that, let's add our copy button, which you can import from .slashcopybutton.
So we reuse it here as well and pass in the value, the value or an empty string as well great and now outside of this div add a new button here So make sure you import the button component like this. And in here, what we're gonna do is we're gonna change this to, we're just gonna say show like that and give this a size of small and a variant of link. Like this. And now you should have this kind of a button here which can indicate to show this stream key because default is going to be hidden, right? So let's go ahead and create a little state for that.
So I'm going to import useState from React. And in here, I'm gonna go ahead and write show and setShow, useState, default value is false, like that. Let's go ahead and give this button which says show an on click to total that. So go ahead and simply call set show to do the opposite of the current value and now we can change this dynamically so if we show it the action is hide otherwise it's a show like that And then you can go ahead and try and click on this and it should trigger between hide and show. And now what we have to do is use that value to change our input type from password to text, right?
So we show that. So let's go ahead and simply use show text, otherwise password. Like that. Great. And we can try it out by going inside of our page here.
And for now, change the value to one, two, three, four for the key card. And why am I importing key card props? Whoops. My apologies. This is supposed to be keycard, right?
And then go back to the page and import keycard. Like this. Great. And now if you try it, you can see how it's hidden. When you click show, it's right here.
And you should also be able to copy that. There we go. So all of that is working great and what we have to do now is this generate button which is going to open a dialog. So before we go there let's go ahead and bring this back to stream.server.streamkey like that. And now let's go ahead and let's create our model.
In order to do that we first need to install a couple of packages from Shazam UI. So I'm going to open my terminal here. And let me shut this down. And I will just write npx shazam-ui.latest add-dialog first. After the dialog we're also gonna have to add a select component so add select and we're also going to have to add an alert component so make sure you have this three dialog select and alert And do npm run dev again and refresh your localhost.
And now what we're going to do is we're going to place this button which says generate inside of our keys folder page.tsx to instead just render the connect model. So connect model like that. And if you save, you should get an error because it doesn't exist. So let's go inside of our underscore components here and create a new file connect-model.tsx. And let's go ahead and mark this as use client let's export const connect model and just return a div connect model go back inside of the keys page and import the connect model from .slash connect model and you can remove the button import like that.
So now go back inside the connect model and let's import everything we need from our dialog so import from s slash components UI dialog So we are going to need the dialogue itself, the dialogue pose, dialogue content, dialogue header, dialogue title and dialogue trigger like this. And now let's go ahead and wrap our button inside of a dialog. So change this to be a dialog. Then inside of here, let's change this to be a dialog trigger. Let's give it an as child property and inside render a button component which you can import from add slash components UI button and in here we're gonna say generate connection and give it a variant of primary.
I like that and there we go Now you should have a button Again here and when we click on it, it's gonna open a dialog So let's go outside of the dialog trigger and let's add a dialog content here. Then let's add a dialog header then a dialog title and in here write generate connection like this and then when you go ahead and click on this button it should open that model and it should say generate connection like this. Great, what we're gonna do next is we're gonna go ahead and add a little alert here. So go outside. So first let's import everything we need from the alert, right?
So I'm going to go here and I'm going to go ahead and import everything I need from s slash components UI alert. And in here, let's import the alert, the alert description, the alert title, like that, title. Great, and now what I wanna do is go outside of the dialog header but still inside of the dialog content and render our alert here and let's add alert triangle from Lucid react so make sure you import alert triangle from lucid react I'm gonna move it here and let's give this a last name of h4 and width of 4 then let's do alert title here and let's write warning and then an alert description below which is going to say this action will reset all active streams using the current connection. So we warn the user that if they decide for any reason to reset their connection keys, we're gonna give them this warning to know that if they have an active stream going on, it's going to be shut down because the keys that they're using to connect to their streaming software are going to be reset and re-invalidated, right? Because the new ones will come in.
So that's what we're going to give this warning if anyone is playing around with this so they know what they are doing. Great and what I want to do now is add two buttons to generate or to cancel. So let's go outside of this alert, create a div with a class name of flex justify between And let's go ahead and add a dialog close here to be our button. Give it a variant of ghost. And inside render the cancel button and then outside of that another button, which is very simply going to say generate and for now let's give it an empty onClick function and let's give it a variant of primary.
Like this. And when you take a look at it now, you should be having these two buttons. Great! And now I just want to add the Select Component here. So let's...
I believe we don't have anything imported. So first let's go ahead and add everything we need from the select component here. So go ahead and import from add slash components UI select and let's import select, select content, select item, select trigger and select value. And just don't do this mistake as I did. Great.
And what we're going to do now is render that just below our header, so above the alert here. So let's add the select right here. And what I'm going to... Oh! Select like this and this one as well and then inside what I'm going to do is add a select trigger I'm going to give it a class name of PoolWidth.
I'm gonna go ahead and add a select value inside with a placeholder, ingress type, like that. And then I'm gonna add a select content here. And each of those is gonna have a select item which is going to have a value of RTMP like this and it's not going to be a self-closing tag so RTMP like this and the other one is going to be a WIP connection. So we're going to handle both protocols, RTMP and WIP, and you're going to see what they do later when we actually connect to a streaming service like that. And I believe that we should already be seeing this as our, there we go.
You can see how we can select between the two of this now. Great, so the user will select what kind of connection they want. So RTMP is often used for streaming, right? For example, OBS accepts RTMP ingress type, so it can connect to that software. And WIP connections might be used for something else.
So this way we will allow all kinds of software to connect to our Next.js application, right? So it's gonna be very modular. I believe we can even use some more popular... Actually, I think OBS is the most popular streaming software because it's free and open source. But there are some others, you know, which are maybe built into PlayStation and stuff.
And I believe that they use the exact same protocols but if they don't use this one we also have this one right so it's going to be a very very good streaming architecture for us here. Perfect so we're going to stop for here now because I want to do the actual you know ingress creation in a separate module so we have more time to talk about that and to explain it so for now we finished the UI for this and then in the next part we're gonna go ahead and actually well make this do something once we click the Generate button.