TOA Part 6: Using Sealed Classes For View States

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let us think well one thing to think about here is let's have another debate about naming conventions or not naming conventions but about coding conventions and specifically around um hold on it's in here somewhere yeah login view state so we've got a data class here that's our email our password now the question there's a debate oftentimes about view states being data classes or sealed classes um because here if we consider all the information i would need right well we've got an email we've got a password we've got like show progress bar is something we're gonna need um we're gonna need to know if there's an error message um right uh in theory we're gonna have like if we have an issue with a particular input we could have like an email input error message um we could have a password input error message you know and some people would say well now we're kind of encapsulating a lot of different view states inside one single data class um and i guess that's bad but on the other hand do i really want like 10 million sale classes that could define what the login view state looks like i don't know um what do you think chat in my mind i want to stick with um this i like data classes but um just carry it out to people like i think i'm gonna stick with data classes until it bothers me um let's show a loading indicator on the screen faults otherwise if sublime error message about trying to log in or an error message um explaining why a user could not log in um it supplied an error message explaining a problem with the female field it supplied an error message explaining a problem with the password yeah i like data classes too for this example as well because of the fact that you could have like a hybrid approach so um one thing people would say like uh let's say you are pulling data right and like someone say that you can only show the loader or you can show your data but what if you're refreshing so then it makes sense to have a data class where you have like a list of items and a separate property that says show loading but the alternative that some people suggest is well that's a third ui state called refreshing and i'm like i guess i get it there but how many sealed classes are you going to end up with because how many different combinations of what's right here are we gonna have you know um all the different parameters of this could be pretty long so i think we should go with this um i'm actually also going to give these default values even though i typically don't like to do that i'm going to do that here but in addition to these so there's a little more that i would do here um namely like okay um let's consider error message um i got lots catch up right so tim brings up a valid point which is the consequence of my decision is that by putting everything in the data class i am opening myself up for a data class that represents a view state that should not be possible so the question is well do we just solve that with very thorough testing or do we take advantage of sealed classes which don't allow us to do that in the first place and i think that that's kind of a personal decision um yeah so like wild dog is right um like that is the point of sale classes but um everyone's vote with tim tonight okay i just i don't i don't like it i don't know why let's okay humor me i'm gonna keep the state of class up here at the top humor me and help me think about um do data classes break single responsibility principle i'm not sure they do in this case because it still has one responsibility which is tell me what the view state is right we're not really breaking responsibility here but it's just not as strict so yep we're still here we're still here we're we're keeping it long today um so okay let's consider both let's write out a few sealed classes um for the different states we could be so i want to put it inside something i'm going to call it login state uh i prefer login view state but this is just because i'm inside the same file here and it's worth asking like um ah gotta hydrate cheers ah okay you guys are right we can break it down okay so then let's talk through how we could define it in a sealed class way well the first question i would have is is there any information that i think would be shared across every possible login state and i actually think the answer to that is a guess because the username and the email and password fields are always visible and their text is part of my view state whether i am in the initial state whether i am logging in whether i have an error i care about what that text is so i might regret this as we go but i'm going to start by saying that you know email and password or email and password should be or to be more specific credentials um are always here that sounds interesting i i think that it's generics and retro like with networking are really helpful but yeah they definitely make um love these they are not there initially are they not they're just empty yes you can get a quick recap on the ui um that is a great great suggestion matt out here with the big brain questions it would make sense to look at the ui while defining the ui state wouldn't it um that would have been uh really great also just saw matt's dm that's fantastic okay um so you should know not to represent no data with an empty string but it's it is data in this case like you just have chosen not to enter anything or well you just for reasons you have not entered anything but okay so all right so let's let's talk about it some more okay i will once again humor tim and start typing it out even though he will probably be right so what do we want to call this initialized initial um empty what do we call what we're looking at login state that empty initial okay now pretend i type in which doesn't work because we haven't hooked up the ui i've entered some information i'm not clicking i'm not logging in right um what do we call this inputting i don't know if we don't want to make it a verb we call like input that feels weird login state that input um active ah okay love it act it okay we're going to use our credentials sealed class here as well well do we want to use credentials or do we want to split it up to email and password let's keep credentials we keep one one entity there okay so we've got um then let's consider i've pressed the button and i'm logging in let's call that submitting now here's where it gets interesting when i am submitting i still care about what your email and password are so it's almost like i'm gonna have the same thing in submitting i'm also gonna have credentials and to me this starts to feel like i'm duplicating information but you could also argue that i'm duplicating it necessarily but i'm going to want to know your credentials in other cases but let's keep going so one that's different from we've got two error states um it is not explicitly mvi backed no um maybe something we could modify in the future but not something i did now um so we've got two error states we've got a [Laughter] we've got a login error um oh all right well we got more contentious stuff um and display the message as soon as the input field is updated focus and actually makes sense oh my god there's so there's so much going on here hold on um so web shark i think that uh to your point like sealed classes as far as i'm understanding them they can work for all of these um but yeah it just means you're going to have a lot of instances of that sealed class to represent everything uh the the point now whether or not i agree with this is different the point is that it's like type safety it's like you have this extra layer of confirmation that you are expecting this specific state and you're not allowing it to be like dirtied with any other flags or information um okay let me keep typing out some other things so we've got um we're going to have what i'm going to call this submission error so this still has our credentials in it but then we're also going to have an error message which will be a string this will be a login statement and then we could have an input error which i'm not going to split we'll say we'll have credentials we could have email input error message which will be a string and a password input error message and actually let's make these nullable because we could have one input errored and not the other i really think that like i don't want to have email input air and password and put her as separate view states because then i'm saying that there should really be three um uh so we'll have one for input um okay but chat sealed classes versus theta classes aside here's another question how do i what's the proper way to then handle something about the login ui that is based on this state for example let's say i want to okay i mean that's right this has come up a lot this stream that sealed classes have scalability benefits for sure because you just need to add a new entry to the field class and then all of your like when statements throughout the app and stuff um will like yell at you and you'll know exactly what needs to update but so here's my question let's say we have something about the ui that is um specific to a spec say like okay how do i explain this consider our two buttons when we are in the submitting state i don't want those to be enabled so the question is where does that logic live because we could put it one could say that it could go in log in content right and then like we could say you know is enabled equals view state equal is submitting or something and like that's fine but isn't that logic inside the composable that shouldn't be there um if that makes sense like so i'm just wondering if um like i'm gonna have the same problem with credentials that i explained to tim earlier let me show you let's try to use our sale class that we made so okay so email input it needs text every time i compose the screen i need text how do i get this right that's why i was going to make this thing with every state no matter what it needs to have the credential information because otherwise i'm basically saying like if view state do you state that initial or something like well you know what i mean like i have this if statement here i don't like that i think that um i do want to put credentials on the base sealed class but let's ignore that for now even because what i really want to work through is this idea um so we don't have an enabled state on the button now but let's let's say we want to do this so we could have buttons enabled right this is a boolean and we're saying this is equal to um login state equals login state that whoops rather this is viewstate is submitting so this is how i would check if buttons were enabled and i don't like this because i've kind of got this like domain logic inside um okay but we're thinking of but so i'm expecting the way i typically design things i'm expecting my view model to emit this it's going to emit this login state so where is that logic actually going to live then right because my view model emits this the login content consumes that i expect this to tell me whether or not the buttons are enabled now i suppose maybe breaking single responsibility principle you know if i do like if i do it here um this technically works and my uh looks nicer but now we're we're um oh that makes a lot more sense raphael that makes a lot more sense you're right um and then i can actually see how let me revert this class by the way um i can actually see how that would be really nice especially if i move credentials up so you're saying the same thing i was saying about credentials is that words it's information that is always there no matter what state we're in so we could have um so we've got our credentials here but then we've got buttons enabled and so actually this and then in each place we define it we can specify that there so here uh we'll give default credentials um and buttons enabled will be true and let's so active consumes credentials we'll say credentials um now i'm looking at this and i'm starting to think that um initial and okay so i need okay i need override there why can't i do this credentials and login state is final and cannot be overridden then i guess i just can't okay i i'm gonna make it open because i want those to be data classes um ah i'm glad you all are catching me up i also know this is yelling at me i'll fix this later okay add override mutuals buttons enabled will be false can i do [Music] do default parameters work in data classes or in two classes oh they do great okay so we can actually just not have to put the um what we call it the button thing in all of them except for the one that we care about changing it so um i'm not saving them in both well okay it's because when i create this this is the constructor right this needs to consume some credentials so um this needs to consume some credentials and then it's just getting passed into the pair constructor maybe this will make it a little more clear if i do this let's say active doesn't care about credentials right i can do this i can just create a constructor for active that takes in credentials yeah okay you that's a great point let me give you the answer when i do this i've created a constructor that takes some credentials and passes them to the super constructor and that's great now let me ask you a question if i want to write a unit test down the line that's expecting a certain view state and i take and i create my own instance of an active state and i compare it to what the view model says will that test pass and the answer like this is not out of the box because this is not a data class so i would need to override the equals function myself and that's fine that's an option but i would prefer that this be a data class so that i can get that equals function out of the box and now because i'm using a data class this is yelling at me because data classes must have at least one property or actually even more specific their primary constructor must only have properties so okay we make this a property but now i am shadowing the parent version of this so the last step is that i need to add the override to this whoops and so that's why we got where we did so make logins say a sealed interface wouldn't that result in almost the same code i actually don't know much about sealed interfaces because i know they're new to kotlin and i've actually never written one um so i have no idea if it's better here i want to fix this real quick i'm going to make credentials and i'm going to give this default arguments but i actually think okay we've added a lot but i think that we've got something going here so let's let's try to roll with it some further um we're going to delete this i mean that's that's valid but i don't know if there's any other um so sealed class defining all possible states of our login screen and also now i can rename this to login view state uh property credentials the current credentials entered by the user and we've got buttons enabled if true the buttons on the login screen can't accept clicks false otherwise um let's okay so actually initial and active are the same and i mean they're not but they are right like their signature is the same so do i combine them into one do i drop initial or i guess they're not because like initial is easier to create let's keep them separate um the initial state of the screen with nothing input um state of the screen as the user entering email information and it's dated the screen as the user is attempting to log in and state of the screen when there is an error logging in and lastly we've got the state of the screen when the user tries to submit with invalid inputs okay so we did all that let's go to our login content this is all going to have to change now um well really this will just be credentials.email value this will be credentials that password that value and down here um this actually becomes one thing i will say that helps us in the compose world tim is that uh you know when i've got sealed classes my previews become a lot nicer because when you have data classes to get a preview for a different state um that's just like that's a lot of lines that are repeated in every preview um but the sealed class makes this preview a little nicer so like if we do a split let's remove this then we see this preview and actually previews can do some cool stuff there's a thing in compose called a preview parameter provider where you can pass a list of items and i suppose you could do this with data classes too but we could create a preview function that takes in a list of login view states and then generates a preview for each one maybe something cool we could look at not something that's specific to sealed classes definitely also possible with data classes but one could argue like you get a little more readability with that sealed class version um but i don't know i'm just thinking out loud um yeah i guess it's not like i said it's not specific to sealed classes which is why someone will call me out on that what i just described you can also do with yeah uh do you guys want to see it let's do it um let me run this make sure this preview works and then i'll show you how you can uh do this yourself um i just need to look up um the example i get that for the screen that makes sense the hashtags and classbooks transparent data may be updated from multiple sources having to check the type or switch on the state it's cumbersome i i think that's valid um i think that it falls into what we uh talk about often is like a lot of uh what did i say on twitter recently best practices is just a fancy word for someone's opinion right like you don't have to do things the same way every time um that makes sense i don't need that anymore i'm not sure why my previews that rendering this is classic compose happening right now is it scaling at me for something else i've got a render problem what is the render problem array index out of bounds exception where is it trying to reference an array all right we're going to do a clean bill and we're going to get this previous job matt brings up a good point two yeah so i want this to rebuild you definitely could right like it's it's complicated and there's no i don't think there is a right or wrong answer to it um why is this yelling at me what is this stack trace okay so this is not my fault this is definitely a weird compose thing going on um yeah i think that that's something i struggle with when it comes to like clean architecture as someone who just released a video on nbvm and mbi it's like they always feel like over engineering until you are bit by the problems they're solving you don't understand how helpful they are and it's like it's over engineering today that saves you time tomorrow and that's really hard to conceptualize until you've like really been burned by it you know um i used to think like a lot of the things that i preach on this channel i used to like not enjoy doing um okay can't figure out why the preview isn't showing up let's thank you matt let's um let me show off the preview parameter provider thing and hopefully it works or i don't know what i need to do do i want to go as far as like trying to restart android studio here um why is the preview working this index out of bound things is definitely not my fault it's definitely like a compose issue um i don't know why um i don't know how to fix it unless i try to do like an invalid caches and restart or something um i did a clean right let's try that one more time oh that's different oh my god i'm not gonna enjoy this um goodnight tim i'm not gonna enjoy this uh the promoter thing it's gonna get to me it truly is i just want my previews to work am i asking for so much clearly i am aha the preview worked okay so here's like our mode so all of that said oh my god how do i disable this how do i turn it off no pop-up i don't care i'll deal with it later i don't have time to learn today okay yeah but i kept saying disable for this alert and i was like i want to disable it for everything it's a preview parameter provider okay let's throw that in at the bottom maybe we could put in some class so we can have a login view state provider it's something we can create and this will be a preview parameter provider and the type will be login view state i'm going to close this window for now okay and this has two things that we nope hold on uh or one thing that we need to move i thought we need to override count two did they change that oh they did change it nice okay we don't need to care about count so this values it's a sequence of states that we want to show so let's give an example um well or we can just kind of yeah okay hold on um i'm just thinking of that i'm going to create this helper i'm going to create like active credentials um which will be credentials with email that's the test face and the password um because this will be helpful tim suggestion of the abstract vowel in the sealed class as a member's variable is actually really cool example okay i totally missed some side conversations so let me pull that up in a second um let's look at this um okay so abstract value test interesting um so why is this better than um having it in the parent i'm not really sure i see a difference um maybe there's a use case in this particular case i don't find it necessary but it's really good to me you don't have to open it interesting i think i would still need it for the credentials part the way i want to do it but you're right um i would lose would i lose the hmm interface version we can look at that real quick i see so it's actually the interface is actually pretty much the same thing as what matt just showed let me think on it let me finish showing y'all the multi-previews in jetpack compose and then um we can go back to considering refactoring this um because i want to show you all how cool this is so let me recap we create a preview parameter provider of some type right we override values which is a sequence of that type i created some test credentials but now what we're going to do is we're going to return if i can type a sequence of so first we're going to have login due state dot initial we're also going to show log viewstate.active with the active credentials um we might want to show submitting right which will have the active credentials we're going to want to show um submission error so this would be like active credentials something went wrong and then we could have our login do state of the input errors which would be actually let me add names to these ones because this one is helpful uh you know how it would go matt it would go fantastic because we have the copy method that's how it would go by reading the copy method but you're right i wouldn't know what state i'm trying to so one funny thing about me doing all this work actually is the fact that half of these states aren't covered by our login ui yet so we're just gonna see several previews that look identical but then we can look update the ui and see them change or something okay so how do we use what i just showed you well we add an argument in here that uh consumes the provider um so we want to take a login view state but then we need to annotate this with preview parameter and then we give it login view state provider class um you can punch out between the two concepts don't make a code review or cry oh god you guys are all so mean um okay all this teasing about naming conventions and you're not ready to have your mind blown about what i just showed you right so we created that sequence we pass in the preview parameter provider let's do a split we need to wait for this to rebuild and all of a sudden we have tons of previews that uh have words um all of our different states so here we've got empty login and now we see okay well this one is active here um and then they're all going to look active but wait why is there two oh there's not i'm just at the bottom but that's because none of the error stuff is actually there actually something interesting is um yeah i'm surprised none of these buttons show as disabled that i would have expected to have been covered i wonder if i can rename this do they provide a way of you know the name no it doesn't look like they do um cheers um that's a good crest question winothan i think there's no right answer to it um i'd kind of suggest like picking something that you're passionate about um if you knew native android like um going to like native ios or a hybrid is probably like going to be the easiest jump for you but uh yeah you can mix and match that or you could pick whatever works well cool so after making that preview i know we talked about um what did we talk about we talked about wanting this to be the view model pr but i'm actually thinking of like renaming this uh to like log in view states and now that we have like our other states on this uh why don't we reconfigure the content to show us that so i think it will be a little easier to do the error states um uh well let's talk about let's talk about error states because we've got something interesting here so let's say um [Music] above the email input is that where i would put it or would i put it after password where would you put an error message on this screen if you had a problem logging in would you put it below these two inputs or would you put it right above them maybe above them right so we do like uh under password okay i lied we're doing it under password okay um let's do some text text will be so okay well so this is my question so would we do if view state is login view state dot submission error then we could do some text here we would do view state that error message and the color here would be ah but i'm not using material text field unless like there is for compose um but i think for compose we would need to add ourselves but i'm not talking about like an error entering your password i'm talking about like an error signing in um that color is that error um and let's also we're gonna throw in this error message let's give it a modifier um let's put some spacing it let's do 12 dips let's build and refresh one of these view states should have an error for us for us to see how that looks aha look at that so this one whoops i zoomed in too far this one shows the text that i just added this will show some text that gives the error message um when something goes wrong trying to log in let's actually i wonder can i this is actually really cool if this works that i can it generates all those previews and then i could run a very specific one um that would be cool if that works yeah really fascinating i'm glad everyone's loving it um also holy crap in two minutes we're going to hit the four hour mark this will be one of my longest streams ever and which i am grateful for that means people and i hope that means people are enjoying this and having a good time um okay it still doesn't look great but like it works um and actually i like that it shifts all of this up so okay i like the way that looks um so what was the other thing ah well we talked about wanting to be able to show errors on our text fields as well so that's actually a custom thing we would have to build ourselves so we have this toa text field that we made the short if we close it all up it's an outline text field um what i think i would do is this could consume an error message and actually what we would do then is we could take this and we could wrap it in a column right and then below the text field we could put some text which will be error message um color will be whoops whoops okay color will be material theme that colors that air there's a couple other ways we can clean this up a little more though um actually well the first thing is if error message is not equal to null i don't really like doing null checks inside my composable functions but i don't hate it here because the option is to pass in the error message and a boolean and do i really need both if i could just suck it up and write the null check um i don't know i think so um but the other thing is outline text field should have in its error property where we can say um if error message is not equal to null we want to show that which means it will show a highlight on the input as well and we can demonstrate that we've got some previews in here let's copy our filled one and let's make an error to a text field preview so we'll call this error error oh i know why this unused private member was there i think because it yells that function but um anyways so here we'll say error message please answer this so now if we do a little split here we'll have to wait for this preview to build but i think it will show our input with um an error message yeah we just need to build and refresh real quick sorry just sending a message um this should be ready so here's what the error version looks like maybe we could add some padding there let's add just like a tiny amount let's just add like more dips so we have a little bit of spacing but we don't want to create a ton so we see the preview here um let's actually go back to login content and let's refresh those previews and let's see what that input error yeah it's not so much a fear of using null but like the if not null check just feels like there's probably a better way i could have done it oh i know what i did wrong here um so we've got this email input right oh i just remembered like 10 other things about why my previews aren't doing what i thought they were so the first one is we've got this email input um and this one is actually going to be interesting so we're saying that email input should be able to consume an error message which will be a string um and then we'll pass that through it'll be a nullable string so now the question is like well what's the best way to get the error message because again that's only available in one specific case of my sealed class here is how i would do it we're going to do view state as type safecast login view state input error and then try to reference email input error message so this is kind of long but um yeah i agree i agree um i think that i'd just be right sometimes i just hesitate uh this is kind of long but what we're basically doing is we're saying if we are this type then get this property but if at any point if this doesn't exist or if it's not this type this will return null so and then we're going to want to do the same thing on password error message will be view state as login due state that input error that password and player message and then of course we have to update this as well so now that we've added it to this code if we refresh um then we should see an input error message in some of these hopefully oh look at that please enter an email please enter a password um i'm actually looking at this and i think that we would it make more sense for this to be aligned with um like where the end of the radius starts like where the text starts um or at least like where the end of the radius is uh that might be a good idea because i don't like this yeah no it needs to move okay let's figure out how to do that so this is actually hard because i don't know what is our text field shape it's rounded corner shape i don't know what this padding is it seems like it's a system thing um oh yeah i've seen that post as soon as i read the author i was like oh i've definitely seen that um i'm not sure how much space is being given here how much padding is inside of this um i don't know if we can dig into the source code to find out what it is because we basically put something here but we need to figure out what this magic number is supposed to be so there's got to be a value because the text of the label add up so let's dig into the source code yeah let's let's dig in so we're probably going to go down a bit of a rabbit hole here um because we're going to go into this outline text field and i'm just going to scroll really fast you don't have to be confused what i'm doing is i am scrolling until my brain sees a dimension resource that i think is relevant and i have not yet seen one until here we're close okay well there's some top padding there's some min with min height that's not what we need there's a decoration box which is only if we're showing a placeholder got a basic text field all right i think i actually missed it i think that it would have been earlier on um where'd we go where did we go where did we find this um okay maybe there was something in here so we get the text color we get some transform text we do get the input state there's this transition which is for the label um why can't i see is this the decoration does the decoration have padding it does not okay oh god where do we go um wait what is this oh it's the modifiers where they set the error message all right raphael have a good night thank you for coming by um ah command bracket i knew there was a thing um okay so then i think it's in here um like this is where we have like shape and all this stuff so outline text field layout feels like where i need to look um yeah that's not it um oh wait here we go we've gotten icons with text field layout um there's calculating the label i and stuff um this has like our border and stuff let's go in here aha we're about to get somewhere i can see it this is the content that's the border the got come on paddington icon there is a text field padding and it's 16 dips i could have guessed that but i wanted to know for sure so let's make this 16 and let's refresh this and see how this looks i think it'll be a little weird uh because oh my god why is it so jumpy we can see that the text starts before the arrow ends but um there is something supported actually and that's uh the trailer there's something called a leading icon um so here we could do like icons that default that search for example um if you add a leading there's leading icon there's trailing icon and then where those get used is they basically show up before the text uh let me just run this to show you i'll remove this in a second but just like that that's all we hit oh my god why is this so jumpy i don't know what's wrong with my android studio today it's like possessed um yeah just like that that's all we have to do to add an icon at the start or end of a text field and compose it's really nice that that kind of comes out of the box like that yeah no problem um but okay so we've got the padding let's go back here let's refresh this oh that already oh god yeah let's refresh this um i find it interesting i had to change this at my current job because um okay i'm glad i'm not alone uh i had to change this at my current job for something because uh the text color the text color doesn't turn red maybe material suggests that you don't do that um i know but uh i'm actually thinking ahead at another weird scenario of our login viewstate but i don't know if i want to get ahead of myself or not let's keep going with things that are relevant which the only thing we changed before we want to build the view model i guess is um the enabled state on the buttons so let's do that real quick so enabled equals viewstate that button's enabled um enabled because we stay that button is enabled um enabled boolean oh my god i'm going to need to update a few pieces of code because we're passing into our own thing here but let's fix one function at a time secondary button enabled boolean we're gonna default to true um enabled equals enabled we'll also probably want to update a preview for like um i don't know i'll leave it um because it'll be here we should probably update these previews you know what i'm going to do it um i'm just going to update the previews real quick while we're here so i'm going to take this and because disabled uh enabled equals false and so here we can actually before we update our login ui we can make sure that this button when disabled looks reasonable um i'm not sure what reasonable is uh okay so this i wonder what this i think it looks fine i actually think this is using like our background color so i'm a little worried about what this will mean um when we see it on that screen but let's worry about that when we get to it let's do the same thing for this one dude disabled secondary button um i also learned about an interesting preview trick from sebastiano last time i watched coding with the italians is that you can have groups of previews in compose let me show you what that means um okay this works the way i expect them to so right now we have all of these previews there's two preview functions but each of them is generating two and we've got them in uh all in the same file what if i wanted to only see like the enabled version we can go here we can call this group enabled um and then we just copy that we give it whatever string we want and then for these two we can paste them in here but we can call them disabled and then what we can do is when we refresh um once they're done in this drop down i have to wait till it's done but now we'll have a drop down that shows the different groups so i could filter to just only see the enabled buttons or i can only see the disabled buttons um so something cool you can do if you find this helpful i'm not sure everyone will see it a little differently um but all that said now we can see the cool stuff in here um we need to find our submitting state oh this actually looks really good now the submitting state is missing the progress bar is missing the progress bar but we can add that um and adding that will be an interesting challenge um why do i say that well our entire screen here is in a column now i want my progress bar to be smack in the center of the screen and in order to do that i will need a box composable and that's fine but i don't like my composables to be super nested so what i think i might do is take all of this stuff and throw it in a new function interesting perspective there a progress bar within the submit button itself and no i absolutely think you're right wild dog there are some things that we didn't have to do that we now have to do like error handling and text fields like a lot of stuff with text fields i'm really composed text fields are very powerful yes i don't like how much responsibility it puts on us as the developers to do um it puts a lot more responsibility at us and there's benefits to that right like we have the same problem when recyclerview was released recyclerview required more work on our part than listview did but that came with having a much more powerful component recyclerview um so but i definitely feel that like i think that it's it's a valid uh piece of feedback there but okay interesting the idea of putting it on the buttons i was thinking about putting it right in the middle of the screen because that's what i'm used to seeing um i don't know if i would put it left of the text i could see myself putting it like over the text or something i don't i think middle of the screen makes sense or i'm wondering if there's other another way we could simulate loading the reason i'm stressing out is because like i if i want to make it a box i want to like put this out to its own function call it like logo inputs column or something let's go down that rabbit hole first and then maybe we could refactor like the loading indication in the future if we have a better way so let's pull this out um let's call it logo inputs column we're just gonna i know that's not like super clear but let's roll with it so and then what we're going to do is we're going to put this inside of a box siblings in a box i don't think i need animated visibility for what i want to do here um well maybe if i want the progress bar to like animate in but um but so here so we've got a box we've got this so now we're going to do is we're going to add a circular progress indicator um on top of everything but uh because i've been bit by this in the past one thing i know is um we want this to be wrap content size and then we also want to do a line alignment.center so let's build and refresh this all right there's a there's our circular progress indicator even though that's not the real one a box is it's most than a uh comparable to a frame layout it's just a composable that you can put everything in and it draws the lower items first but it allows you to align things not to each other but within the box so you can align to the center of the box the top left right of the box and stuff like that so in this case where i have two things that i want layered on top of each other and i want to align one in the center of the entire screen box is really good for that oh matt out here decompiling code and we can see even though the preview doesn't really show it like we can see the circular progress indicator is there uh we could run this on our emulator if we want to see what our loading state actually looks like but uh it's working holy crap it's 11 o'clock um all of you staying up late but this has been like one of the best streams we've done so much stuff today i love it um maybe we can do just a little bit more um we'll see yeah look at that so it's not great right like it's not it looks weird with the logo being right there but it's something i think that a future stream we could definitely change this but what i like is that we have something that works here today um i think that's really good so let's push all of this up um updating is this where we changed everything to field class yeah login view state to sealed class and updating the ui that uh accordingly uh no actually i should fix that like right now um that's something we're going to need to do eventually let's add that because that's actually pretty quick so um i'm gonna wait for everything to commit everything's going slow because i have so many previews now uh maybe that was not the best idea um but our outline text field can consume something called a visibility transformation so i think that's what it's called what is it called visual transformation oh my god i can't cite so we're going to consume a visual transformation we're going to default to visual transformation.none but we'll proxy this through uh with everything else and so what this allows us to do is in our login content where we create the password input we can give this a visual transformation of password visual transformation and what this will do is this will replace why that fail i don't know we'll worry about it with the next commit um this will replace everywhere that we have text with dots oh super easy and you can write your own so i read a really great post on like how you could write your own visual transformation to do like phone number masking or uh like hiding a credit card with hyphens instead of dots or something um hot and there we go there are our dots um actually with our urban response style that's not i don't like that well why are they so small i have been so close together uh maybe we'll play with typography um look at those little dots you have to zoom in like so far just to see that why is it doing that i don't i don't know if it would actually show up like that this feels like a preview thing your password must be 0.5 characters lost my brother's inside of me later so as much as i would love to keep streaming i guess we'll see where we're at wow it really is small okay i'm gonna ignore that for today uh that will be uh a future future concern uh but let's quit this code then adding password visual transformation um and then i don't know if we'll hook up the screen to a view model but um you can you can replace them with every with whatever you want and that's working uh i think it's a issue with the typography um i can show you how it works real quick um actually before i show you how it works let me figure out why um this didn't push last time it looks like we had some static analysis issues oh my god right this yells at me i removed this that was my fault i should just turn off that check ah asherah thank you for the follow and visual transformation yes um okay once this pushes i will show you how it works which i think it's trying to do um oh my god yeah everything's just a little slow right now i don't know if it's all of the previews or what uh those other tabs that's what i wanted okay so where were we we were in password input password visual transformation uh its functionality is as easy as it sounds so it takes in a mask which is um basically what you want to replace it with so this is the unicode character for like an asterisk and then this filter function says okay give me the text that you already have and i will return you the transform text so it creates this transform text and all it does is it takes that mask character and it repeats it for the length of our string so if our password is 10 characters this is just going to give us 10 asterisks so uh what someone said web shark yeah this is basically just replacing it with unicode um now it's like the transform text right so it knows what was there underneath you don't have to worry about that but this is what it's going to show up as to the user so the fact that it's so small tells me that i could probably do something with a better font size or maybe even letter spacing or something with my typography could be improved upon for the asterisk at least that's my thought process or maybe i want to try a different mask you know like i'm i think that's an asterisk so what's bullet aspie um how do i find this bullet point happy i know this is a thing i can't find what the i can copy it here but it won't tell me oh this is read only maybe that might work um let's see if that's any better than what we already had wait did that fail to push again or was that an old message it failed to push again we'll figure out why after yeah okay it's still super small so it's definitely a typography thing we'll worry about that on another stream um let's send this back real quick um why why did it fail i just want to talk why are you failing long parameter list um that's fair but i can't make this any smaller so guess what we're gonna do we're gonna suppress for this case because i think for this case it's okay um or actually what i might do differently so detect we've mentioned is highly configurable right and the long parameter lists option gives me a chance to say ignore default parameters and i think for that i'm gonna say okay um this is opinionated of course but i'm gonna say like look if i've got a lot of default parameters i don't really care how long the list is but if i've got a lot that aren't defaults then maybe i'm doing something wrong so let's go with that detect environment
Info
Channel: Adam McNeilly
Views: 52
Rating: 0 out of 5
Keywords: Android
Id: 3UNa6l0KlcU
Channel Id: undefined
Length: 82min 48sec (4968 seconds)
Published: Mon Oct 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.