Skip to content

feat: Change authentication process and remove navigation (#1749) #1763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class SmartAuthViewModel : ViewModel() {
val progress: LiveData<Boolean> = mutableProgress
private val mutableApiExceptionRequestCodePair = MutableLiveData<Pair<Any, Any>>()
val apiExceptionCodePair: LiveData<Pair<Any, Any>> = mutableApiExceptionRequestCodePair
private val mutableStatus = MutableLiveData<Boolean>()
val isCredentialStored: LiveData<Boolean> = mutableStatus

fun requestCredentials(any: Any) {
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI.setupWithNavController
import kotlinx.android.synthetic.main.activity_main.navigation
import kotlinx.android.synthetic.main.activity_main.navigationAuth
import kotlinx.android.synthetic.main.activity_main.mainFragmentCoordinatorLayout
import org.fossasia.openevent.general.auth.EditProfileFragment
import org.fossasia.openevent.general.auth.RC_CREDENTIALS_READ
Expand Down Expand Up @@ -44,7 +43,6 @@ class MainActivity : AppCompatActivity() {

private fun setupBottomNavigationMenu(navController: NavController) {
setupWithNavController(navigation, navController)
setupWithNavController(navigationAuth, navController)

navigation.setOnNavigationItemReselectedListener {
val hostFragment = supportFragmentManager.findFragmentById(R.id.frameContainer)
Expand All @@ -64,17 +62,11 @@ class MainActivity : AppCompatActivity() {
R.id.favoriteFragment -> navAnimVisible(navigation, this@MainActivity)
else -> navAnimGone(navigation, this@MainActivity)
}
when (id) {
R.id.loginFragment,
R.id.signUpFragment -> navAnimVisible(navigationAuth, this@MainActivity)
else -> navAnimGone(navigationAuth, this@MainActivity)
}
}

override fun onBackPressed() {
when (currentFragmentId) {
R.id.loginFragment,
R.id.signUpFragment -> {
R.id.authFragment -> {
navController.popBackStack(R.id.eventsFragment, false)
Copy link
Contributor

@anhanh11001 anhanh11001 May 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small problem: this will always pop back to EventsFragment -> So if the user navigate from other fragments like Order or Ticket to log in and somehow they press back button, they will not return to the correct one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have not removed it because imo it make scene. User is redirected to auth fragment where authentication requires, if user cancel the authentication then it should redirect to home screen.
If you want I will remove the condition from auth fragment and navigation flow will work in it's natural way?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think that popping back to EventsFragment is fine in most case, except when a user is booking tickets in AttendeeFragment, canceling logging in will not return them to the current event/ticket detail that they're searching for.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so It will make complex to apply different conditions for different fragments. I will remove it. 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any other changes you want to suggest?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't. I think the rest is good

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got a problem in that case. If the user goes to tickets, redirected to auth fragment. After pressing the back button, the user must redirect to events fragment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iamareebjamal Can we use fragment's navArgs() in Main activity?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would it be a problem?

mainFragmentCoordinatorLayout.snackbar(R.string.sign_in_canceled)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.fossasia.openevent.general.auth
import io.reactivex.Single
import org.fossasia.openevent.general.auth.change.ChangeRequestToken
import org.fossasia.openevent.general.auth.change.ChangeRequestTokenResponse
import org.fossasia.openevent.general.auth.forgot.Email
import org.fossasia.openevent.general.auth.forgot.RequestToken
import org.fossasia.openevent.general.auth.forgot.RequestTokenResponse
import retrofit2.http.Body
Expand Down Expand Up @@ -33,4 +34,7 @@ interface AuthApi {

@POST("upload/image")
fun uploadImage(@Body uploadImage: UploadImage): Single<ImageResponse>

@POST("users/checkEmail")
fun checkEmail(@Body email: Email): Single<CheckEmailResponse>
}
116 changes: 116 additions & 0 deletions app/src/main/java/org/fossasia/openevent/general/auth/AuthFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package org.fossasia.openevent.general.auth

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.navigation.Navigation
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_auth.view.getStartedButton
import kotlinx.android.synthetic.main.fragment_auth.view.email
import kotlinx.android.synthetic.main.fragment_auth.view.rootLayout
import org.fossasia.openevent.general.BuildConfig
import org.fossasia.openevent.general.PLAY_STORE_BUILD_FLAVOR
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.utils.Utils
import org.fossasia.openevent.general.utils.Utils.hideSoftKeyboard
import org.fossasia.openevent.general.utils.Utils.show
import org.fossasia.openevent.general.utils.Utils.progressDialog
import org.fossasia.openevent.general.utils.extensions.nonNull
import org.jetbrains.anko.design.longSnackbar
import org.jetbrains.anko.design.snackbar
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel

class AuthFragment : Fragment() {
private lateinit var rootView: View
private val authViewModel by viewModel<AuthViewModel>()
private val safeArgs: AuthFragmentArgs by navArgs()
private val smartAuthViewModel by sharedViewModel<SmartAuthViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (BuildConfig.FLAVOR == PLAY_STORE_BUILD_FLAVOR) {
smartAuthViewModel.requestCredentials(SmartAuthUtil.getCredentialsClient(requireActivity()))
smartAuthViewModel.isCredentialStored
.nonNull()
.observe(this, Observer {
if (it) redirectToLogin()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikit19 Here no email address is passing, so set its default value to an empty string.

})
}
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.fragment_auth, container, false)

Utils.setToolbar(activity, "", true)
setHasOptionsMenu(true)

val progressDialog = progressDialog(context)

val snackbarMessage = safeArgs.snackbarMessage
if (!snackbarMessage.isNullOrEmpty()) rootView.snackbar(snackbarMessage)

rootView.getStartedButton.setOnClickListener {
hideSoftKeyboard(context, rootView)
authViewModel.checkUser(rootView.email.text.toString())
}

authViewModel.isUserExists
.nonNull()
.observe(viewLifecycleOwner, Observer {
if (it)
redirectToLogin(rootView.email.text.toString())
else
redirectToSignUp()
authViewModel.mutableStatus.postValue(null)
})

authViewModel.progress
.nonNull()
.observe(viewLifecycleOwner, Observer {
progressDialog.show(it)
})

smartAuthViewModel.progress
.nonNull()
.observe(viewLifecycleOwner, Observer {
progressDialog.show(it)
})

authViewModel.error
.nonNull()
.observe(viewLifecycleOwner, Observer {
rootView.rootLayout.longSnackbar(it)
})

return rootView
}

private fun redirectToLogin(email: String = "") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this default value?

Navigation.findNavController(rootView)
.navigate(AuthFragmentDirections
.actionAuthToLogIn(email, safeArgs.redirectedFrom)
)
}

private fun redirectToSignUp() {
Navigation.findNavController(rootView)
.navigate(AuthFragmentDirections
.actionAuthToSignUp(rootView.email.text.toString(), safeArgs.redirectedFrom)
)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
activity?.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ class AuthService(
val changeRequestToken = ChangeRequestToken(Password(oldPassword, newPassword))
return authApi.changeRequestToken(changeRequestToken)
}

fun checkEmail(email: String): Single<CheckEmailResponse> {
return authApi.checkEmail(Email(email))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.fossasia.openevent.general.auth

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.fossasia.openevent.general.R
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.fossasia.openevent.general.data.Network
import org.fossasia.openevent.general.data.Resource
import org.fossasia.openevent.general.utils.extensions.withDefaultSchedulers
import timber.log.Timber

class AuthViewModel(
private val authService: AuthService,
private val network: Network,
private val resource: Resource
) : ViewModel() {

private val compositeDisposable = CompositeDisposable()
private val mutableProgress = MutableLiveData<Boolean>()
val progress: LiveData<Boolean> = mutableProgress
val mutableStatus = MutableLiveData<Boolean>()
val isUserExists: LiveData<Boolean> = mutableStatus
private val mutableError = MutableLiveData<String>()
val error: LiveData<String> = mutableError

fun checkUser(email: String) {
if (!network.isNetworkConnected()) {
mutableError.value = resource.getString(R.string.no_internet_message)
return
}
compositeDisposable += authService.checkEmail(email)
.withDefaultSchedulers()
.doOnSubscribe {
mutableProgress.value = true
}.doFinally {
mutableProgress.value = false
}.subscribe({
mutableStatus.value = !it.result
Timber.d("Success!")
}, {
mutableError.value = resource.getString(R.string.error)
Timber.d(it, "Failed")
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.fossasia.openevent.general.auth

class CheckEmailResponse(
val result: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.navigation.Navigation.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.activity_main.navigationAuth
import kotlinx.android.synthetic.main.fragment_login.email
import kotlinx.android.synthetic.main.fragment_login.password
import kotlinx.android.synthetic.main.fragment_login.loginButton
Expand All @@ -28,6 +27,10 @@ import kotlinx.android.synthetic.main.fragment_login.view.tick
import org.fossasia.openevent.general.BuildConfig
import org.fossasia.openevent.general.PLAY_STORE_BUILD_FLAVOR
import org.fossasia.openevent.general.R
import org.fossasia.openevent.general.event.EVENT_DETAIL_FRAGMENT
import org.fossasia.openevent.general.notification.NOTIFICATION_FRAGMENT
import org.fossasia.openevent.general.order.ORDERS_FRAGMENT
import org.fossasia.openevent.general.ticket.TICKETS_FRAGMNET
import org.fossasia.openevent.general.utils.Utils
import org.fossasia.openevent.general.utils.Utils.show
import org.fossasia.openevent.general.utils.Utils.hideSoftKeyboard
Expand Down Expand Up @@ -55,7 +58,6 @@ class LoginFragment : Fragment() {
val progressDialog = progressDialog(context)
Utils.setToolbar(activity, getString(R.string.login))
setHasOptionsMenu(true)
showSnackbar()

if (loginViewModel.isLoggedIn())
popBackStack()
Expand All @@ -65,7 +67,9 @@ class LoginFragment : Fragment() {
hideSoftKeyboard(context, rootView)
}

if (BuildConfig.FLAVOR == PLAY_STORE_BUILD_FLAVOR) {
if (safeArgs.email.isNotEmpty()) {
rootView.email.text = SpannableStringBuilder(safeArgs.email)
} else if (BuildConfig.FLAVOR == PLAY_STORE_BUILD_FLAVOR) {

smartAuthViewModel.requestCredentials(SmartAuthUtil.getCredentialsClient(requireActivity()))

Expand All @@ -82,8 +86,8 @@ class LoginFragment : Fragment() {
})

smartAuthViewModel.apiExceptionCodePair.nonNull().observe(viewLifecycleOwner, Observer {
SmartAuthUtil.handleResolvableApiException(
it.first, requireActivity(), it.second)
SmartAuthUtil.handleResolvableApiException(
it.first, requireActivity(), it.second)
})

smartAuthViewModel.progress
Expand All @@ -92,6 +96,7 @@ class LoginFragment : Fragment() {
progressDialog.show(it)
})
}

loginViewModel.progress
.nonNull()
.observe(viewLifecycleOwner, Observer {
Expand Down Expand Up @@ -143,10 +148,8 @@ class LoginFragment : Fragment() {
rootView.sentEmailLayout.visibility = View.VISIBLE
rootView.loginLayout.visibility = View.GONE
Utils.setToolbar(activity, show = false)
Utils.navAnimGone(activity?.navigationAuth, requireContext())
} else {
Utils.setToolbar(activity, getString(R.string.login))
Utils.navAnimVisible(activity?.navigationAuth, requireContext())
}
})

Expand All @@ -165,7 +168,6 @@ class LoginFragment : Fragment() {
rootView.tick.setOnClickListener {
rootView.sentEmailLayout.visibility = View.GONE
Utils.setToolbar(activity, getString(R.string.login))
Utils.navAnimVisible(activity?.navigationAuth, requireContext())
rootView.loginLayout.visibility = View.VISIBLE
}

Expand All @@ -189,7 +191,16 @@ class LoginFragment : Fragment() {
}

private fun popBackStack() {
findNavController(rootView).popBackStack()
val destinationId =
when (safeArgs.redirectedFrom) {
PROFILE_FRAGMENT -> R.id.profileFragment
EVENT_DETAIL_FRAGMENT -> R.id.eventDetailsFragment
ORDERS_FRAGMENT -> R.id.orderUnderUserFragment
TICKETS_FRAGMNET -> R.id.ticketsFragment
NOTIFICATION_FRAGMENT -> R.id.notificationFragment
else -> R.id.eventsFragment
}
findNavController(rootView).popBackStack(destinationId, false)
rootView.snackbar(R.string.welcome_back)
}

Expand All @@ -200,17 +211,10 @@ class LoginFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
findNavController(rootView).popBackStack(R.id.eventsFragment, false)
rootView.snackbar(R.string.sign_in_canceled)
activity?.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}

private fun showSnackbar() {
safeArgs.snackbarMessage?.let { textSnackbar ->
rootView.loginCoordinatorLayout.snackbar(textSnackbar)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
import org.fossasia.openevent.general.utils.Utils.setToolbar
import org.jetbrains.anko.design.snackbar

const val PROFILE_FRAGMENT = "profileFragment"

class ProfileFragment : Fragment() {
private val profileViewModel by viewModel<ProfileViewModel>()

private lateinit var rootView: View
private var emailSettings: String? = null

private fun redirectToLogin() {
findNavController(rootView).navigate(ProfileFragmentDirections
.actionProfileToLogin()
)
findNavController(rootView).navigate(ProfileFragmentDirections.actionProfileToAuth(null, PROFILE_FRAGMENT))
}

private fun redirectToEventsFragment() {
Expand Down
Loading