Hi everyone. I want to build authentication system...
# compose
e
Hi everyone. I want to build authentication system for my app, and still a bit confuse on how to handle the flow. I always implement the A flow before, but the problem is I always see my Login Screen first, even it is only a glimpse. Which do you prefer between these flows? Is doing the B approach even possible?
t
B is how I implemented it in the Aetna Attain project. I did it as the chunk of logic that needs to run before dismissing the splash screen. Roughly 1- read state from disk and determine start destination 2- setup the nav graphs 3- callback at the end of first composition pass to dismiss
be warned if you go the splash screen route that you cant put critical logic in the exit anim listener. https://issuetracker.google.com/issues/216136037
c
Going off of the android nav docs (not even the compose specific docs) they tell you to use your "main" screen as your start destination. So then basically on that "main" screen you should check the state to see if you're logged in. If so, then you send the user to the login screen. When login completes, then you call pop back stack and the user is now back where they came from. This is super handy for cases where the user hasn't logged in yet, but maybe clicks on a deep link that takes them deep into the app somewhere. Login check occurs, then takes you to login screen if the check fails. User logs in. Pop backstack. Bam, you're taken right to the deep link.
Doing the login check per screen (or per destination) can sometimes eem a little backwards, but there are legit use cases for it. Ian taught me this. SO like if you're building twitter. There are a bunch of screens where login is optional. For example. You can install twitter, not use it. Then in an email click on a link to twitter. the twitter app opens to show you the tweet but it doesn't require you to be logged in. Once you click "like" tweet, then at that point your login screen might show. For apps that are like "I ALWAYS NEED MY USER TO BE LOGGED IN" I would still follow the idea that the home screen is the start destination but I'd maybe try to come up with some single helper to call everywhere.
z
The best thing to do in a fully declarative/compose app is have some top-level thing in your UI determine whether there's a session or not, and then show the correct screen directly. Introducing the indirection of “imperative” navigation doesn't mean bugs like this are inevitable, but it's a lot easier to introduce them.
c
@ Zach does that still hold true for like the twitter scenario though? In that case wouldn't you want to handle it per destination? (e.g. viewing a tweet you can do while being logged out, but viewing a timeline requires you to be logged in)
z
Absolutely. The screens requiring login can be wrapped in a composable that does the check and shows the login UI.
2
c
Thanks. I'm still learning but this login stuff legit makes my head hurt. It's like. It either works or it doesn't. But I'm also secretly scared that I'm introducing some sort of security hole by potentially doing this the wrong way. I.e what if the person can somehow get around the login screen and see the content underneath? I'm sure most of my worries are unjustified, but it's just something that always kind of lingers over my head
e
I think I'll go with MAIN screen as my start destination, and wrap some features that require the user to be logged with conditional check. I guess it will make a better user experience as the user can see what are inside our app at the first launch and not forced to login. Thank you so much! @trevjones @Zach Klippenstein (he/him) [MOD] @Colton Idle
K 3
c
@Zach Klippenstein (he/him) [MOD] kinda come back to this late in the game... but I was thinking about what you said last night
The best thing to do in a fully declarative/compose app is have some top-level thing in your UI determine whether there's a session or not, and then show the correct screen directly. Introducing the indirection of “imperative” navigation doesn't mean bugs like this are inevitable, but it's a lot easier to introduce them.
So. That makes sense to me. Like total sense. (this is actually like week 1 of me being an android dev in 2012 and just swapping out R.layout.signin and R.layout.homescreen based on an if statement). BUT since this makes a ton of sense for me in the compose world... why do we even need compose-navigation? Wouldn't I want to modify that navigation stack directly instead of using this "event" based technique where the event callback bubbles up to the NavHost and the navhost calls
.navigate(OtherScreen)
?
z
why do we even need compose-navigation
Short answer: Exactly! We don’t! 🙂 Longer answer: There are some navigation-related things that are pretty boilerplaty and helpful to factor out (e.g. state saving/restoration, maybe some common transition animations). I think an ideal navigation library for Compose would help solve those problems, but not try to manage its own source of truth for actual navigation. There are already a few libraries out there that do exactly that. I think (my personal opinion, not my employer’s) the only reason compose-navigation really exists is because it already existed for fragments, it’s been the “official” recommendation for navigation for some time, and it can be helpful when migrating a large app incrementally. It’s a lot easier to answer 100 “how do we do navigation” questions with “the same as before” than trying to get everyone to reconceptualize what “navigation” even is, and there are a limited number of devrels 😅
👍 1
This was the whole motivation behind compose-backstack, although that’s not maintained anymore and i think there are other, better, KMP, etc libraries out there at this point.
c
Thanks. Yeah I guess that's kinda my big light bulb moment a few months ago where it was like... wait... life is easier if i manage the state of my app. and then Adam gave great guidance on state vs events and stuff. but then it was like. wait. why dont i just have a NavBackStackState or something.
t
Same thinking applies to DI IMO. Why don't my DI scopes model my domain lifecycles instead of platform lifecycles? It's hard to do well. but quite nice when you get things all setup
🤯 1
1