Commit 8ed04ad5 authored by aniket's avatar aniket

deals with more edge cases

parent ac5ee24a
...@@ -303,6 +303,7 @@ class LoginPresenter @Inject constructor( ...@@ -303,6 +303,7 @@ class LoginPresenter @Inject constructor(
saveAccount(username) saveAccount(username)
saveToken(token) saveToken(token)
registerPushToken() registerPushToken()
navigator.toChatList() navigator.toChatList()
} else if (loginType == TYPE_LOGIN_OAUTH) { } else if (loginType == TYPE_LOGIN_OAUTH) {
navigator.toRegisterUsername(token.userId, token.authToken) navigator.toRegisterUsername(token.userId, token.authToken)
......
...@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.login.presentation ...@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.login.presentation
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
import com.google.android.gms.auth.api.credentials.Credential
interface LoginView : LoadingView, MessageView { interface LoginView : LoadingView, MessageView {
...@@ -223,4 +224,9 @@ interface LoginView : LoadingView, MessageView { ...@@ -223,4 +224,9 @@ interface LoginView : LoadingView, MessageView {
* Alerts the user about a wrong inputted password. * Alerts the user about a wrong inputted password.
*/ */
fun alertWrongPassword() fun alertWrongPassword()
/**
* Save credentials via google smart lock
*/
fun saveSmartLockCredentials(loginCredential: Credential)
} }
\ No newline at end of file
...@@ -2,12 +2,15 @@ package chat.rocket.android.authentication.login.ui ...@@ -2,12 +2,15 @@ package chat.rocket.android.authentication.login.ui
import DrawableHelper import DrawableHelper
import android.app.Activity import android.app.Activity
import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.content.IntentSender
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
...@@ -32,9 +35,7 @@ import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN ...@@ -32,9 +35,7 @@ import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import com.google.android.gms.auth.api.Auth import com.google.android.gms.auth.api.Auth
import com.google.android.gms.auth.api.credentials.Credential import com.google.android.gms.auth.api.credentials.*
import com.google.android.gms.auth.api.credentials.CredentialRequest
import com.google.android.gms.auth.api.credentials.IdentityProviders
import com.google.android.gms.common.api.CommonStatusCodes import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.common.api.GoogleApiClient import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.common.api.Status import com.google.android.gms.common.api.Status
...@@ -46,16 +47,9 @@ import javax.inject.Inject ...@@ -46,16 +47,9 @@ import javax.inject.Inject
internal const val REQUEST_CODE_FOR_CAS = 1 internal const val REQUEST_CODE_FOR_CAS = 1
internal const val REQUEST_CODE_FOR_OAUTH = 2 internal const val REQUEST_CODE_FOR_OAUTH = 2
internal const val MULTIPLE_CREDENTIALS_READ = 3 internal const val MULTIPLE_CREDENTIALS_READ = 3
internal const val NO_CREDENTIALS_EXIST = 4
class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks { class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks {
override fun onConnected(p0: Bundle?) {
requestCredentials()
}
override fun onConnectionSuspended(p0: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@Inject @Inject
lateinit var presenter: LoginPresenter lateinit var presenter: LoginPresenter
private var isOauthViewEnable = false private var isOauthViewEnable = false
...@@ -65,6 +59,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -65,6 +59,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
private var isGlobalLayoutListenerSetUp = false private var isGlobalLayoutListenerSetUp = false
private var deepLinkInfo: LoginDeepLinkInfo? = null private var deepLinkInfo: LoginDeepLinkInfo? = null
private var googleApiClient: GoogleApiClient? = null private var googleApiClient: GoogleApiClient? = null
private var credentialsToBeSaved: Credential? = null
companion object { companion object {
private const val DEEP_LINK_INFO = "DeepLinkInfo" private const val DEEP_LINK_INFO = "DeepLinkInfo"
...@@ -76,6 +71,14 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -76,6 +71,14 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
} }
} }
override fun onConnected(p0: Bundle?) {
//add call to the save credentials function here just like in sign up fragment
}
override fun onConnectionSuspended(p0: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this) AndroidSupportInjection.inject(this)
...@@ -128,17 +131,55 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -128,17 +131,55 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
} else if (requestCode == MULTIPLE_CREDENTIALS_READ) { } else if (requestCode == MULTIPLE_CREDENTIALS_READ) {
var loginCredentials: Credential = data!!.getParcelableExtra(Credential.EXTRA_KEY) var loginCredentials: Credential = data!!.getParcelableExtra(Credential.EXTRA_KEY)
handleCredential(loginCredentials) handleCredential(loginCredentials)
} else if (requestCode == NO_CREDENTIALS_EXIST) {
//use the hints to autofill some info in the sign up or sign in forms
var loginCredentials: Credential = data!!.getParcelableExtra(Credential.EXTRA_KEY)
//pass these info to sign up view to autofill forms
var name = loginCredentials.name
var email = loginCredentials.id
var password = loginCredentials.password
text_username_or_email.setText(email)
text_password.setText(password)
} }
} }
//cancelled
else if (resultCode == Activity.RESULT_CANCELED) {
}
//create new account to use it as login account (deal with this case carefully, many edge cases)
else if (resultCode == CredentialsApi.ACTIVITY_RESULT_ADD_ACCOUNT) {
//save credentials in this case after user signs up as well as in that case when user signs in
// with a new account other than those saved by smart lock. Also delete and disableAutoSignIn
// need to be implemented. Refer docs.
}
//no hints for user id's exist
else if (resultCode == CredentialsApi.ACTIVITY_RESULT_NO_HINTS_AVAILABLE) {
}
}
override fun onDestroy() {
super.onDestroy()
googleApiClient!!.stopAutoManage(activity!!)
googleApiClient!!.disconnect()
} }
private fun buildGoogleApiClient() { private fun buildGoogleApiClient() {
googleApiClient = GoogleApiClient.Builder(context!!) googleApiClient = GoogleApiClient.Builder(context!!)
.enableAutoManage(activity!!, {
Log.d("STATUS", "ERROR: connection to client failed")
})
.addConnectionCallbacks(this) .addConnectionCallbacks(this)
.addApi(Auth.CREDENTIALS_API) .addApi(Auth.CREDENTIALS_API)
.build() .build()
} }
override fun onStart() {
super.onStart()
requestCredentials()
}
private fun requestCredentials() { private fun requestCredentials() {
var request: CredentialRequest = CredentialRequest.Builder() var request: CredentialRequest = CredentialRequest.Builder()
.setPasswordLoginSupported(true) .setPasswordLoginSupported(true)
...@@ -148,19 +189,39 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -148,19 +189,39 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
Auth.CredentialsApi.request(googleApiClient, request).setResultCallback { credentialRequestResult -> Auth.CredentialsApi.request(googleApiClient, request).setResultCallback { credentialRequestResult ->
//hideProgress() //hideProgress()
val status = credentialRequestResult.getStatus() val status = credentialRequestResult.status
if (status.isSuccess) { if (status.isSuccess) {
// Auto sign-in success // Auto sign-in success
handleCredential(credentialRequestResult.getCredential()) handleCredential(credentialRequestResult.credential)
} else if (status.statusCode == CommonStatusCodes.RESOLUTION_REQUIRED) { } else if (status.statusCode == CommonStatusCodes.RESOLUTION_REQUIRED) {
// Getting credential needs to show some UI, start resolution // Getting credential needs to show some UI, start resolution
resolveResult(status, MULTIPLE_CREDENTIALS_READ) resolveResult(status, MULTIPLE_CREDENTIALS_READ)
} else if (status.statusCode == CommonStatusCodes.SIGN_IN_REQUIRED) {
//resolveResult(status, NO_CREDENTIALS_EXIST)
//build a dialog for possible account hints
var hintRequest: HintRequest = HintRequest.Builder()
.setHintPickerConfig(CredentialPickerConfig.Builder()
.setShowCancelButton(true)
.build())
.setEmailAddressIdentifierSupported(true)
.setAccountTypes(IdentityProviders.GOOGLE)
.build()
var intent: PendingIntent = Auth.CredentialsApi.getHintPickerIntent(googleApiClient, hintRequest)
try {
startIntentSenderForResult(intent.intentSender, NO_CREDENTIALS_EXIST, null, 0, 0, 0, null)
} catch (e: IntentSender.SendIntentException) {
Log.e("STATUS", "ERROR: Could not start hint picker Intent", e);
}
} else {
Log.d("STATUS", "ERROR: nothing happening")
} }
} }
} }
private fun handleCredential(loginCredentials: Credential) { private fun handleCredential(loginCredentials: Credential) {
if (loginCredentials.accountType == IdentityProviders.GOOGLE) { if (loginCredentials.accountType == null) {
presenter.authenticateWithUserAndPassword(loginCredentials.id, loginCredentials.password!!)
} else if (loginCredentials.accountType == IdentityProviders.GOOGLE) {
//TODO add SL code for google as custom login method //TODO add SL code for google as custom login method
} else if (loginCredentials.accountType == IdentityProviders.FACEBOOK) { } else if (loginCredentials.accountType == IdentityProviders.FACEBOOK) {
//TODO add SL code for facebook as custom login method //TODO add SL code for facebook as custom login method
...@@ -168,8 +229,6 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -168,8 +229,6 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
//TODO add SL code for twitter as custom login method //TODO add SL code for twitter as custom login method
} else if (loginCredentials.accountType == IdentityProviders.LINKEDIN) { } else if (loginCredentials.accountType == IdentityProviders.LINKEDIN) {
//TODO add SL code for linkedin as custom login method //TODO add SL code for linkedin as custom login method
} else {
presenter.authenticateWithUserAndPassword(loginCredentials.id, loginCredentials.password!!)
} }
} }
......
...@@ -20,6 +20,7 @@ import chat.rocket.core.internal.rest.login ...@@ -20,6 +20,7 @@ import chat.rocket.core.internal.rest.login
import chat.rocket.core.internal.rest.me import chat.rocket.core.internal.rest.me
import chat.rocket.core.internal.rest.signup import chat.rocket.core.internal.rest.signup
import chat.rocket.core.model.Myself import chat.rocket.core.model.Myself
import com.google.android.gms.auth.api.credentials.Credential
import javax.inject.Inject import javax.inject.Inject
class SignupPresenter @Inject constructor(private val view: SignupView, class SignupPresenter @Inject constructor(private val view: SignupView,
...@@ -66,6 +67,10 @@ class SignupPresenter @Inject constructor(private val view: SignupView, ...@@ -66,6 +67,10 @@ class SignupPresenter @Inject constructor(private val view: SignupView,
localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, me.username) localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, me.username)
saveAccount(me) saveAccount(me)
registerPushToken() registerPushToken()
var loginCredentials: Credential = Credential.Builder(email)
.setPassword(password)
.build()
view.saveSmartLockCredentials(loginCredentials)
navigator.toChatList() navigator.toChatList()
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
......
...@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.signup.presentation ...@@ -2,6 +2,7 @@ package chat.rocket.android.authentication.signup.presentation
import chat.rocket.android.core.behaviours.LoadingView import chat.rocket.android.core.behaviours.LoadingView
import chat.rocket.android.core.behaviours.MessageView import chat.rocket.android.core.behaviours.MessageView
import com.google.android.gms.auth.api.credentials.Credential
interface SignupView : LoadingView, MessageView { interface SignupView : LoadingView, MessageView {
...@@ -24,4 +25,9 @@ interface SignupView : LoadingView, MessageView { ...@@ -24,4 +25,9 @@ interface SignupView : LoadingView, MessageView {
* Alerts the user about a blank email. * Alerts the user about a blank email.
*/ */
fun alertBlankEmail() fun alertBlankEmail()
/**
* Save credentials via google smart lock
*/
fun saveSmartLockCredentials(loginCredential: Credential)
} }
\ No newline at end of file
package chat.rocket.android.authentication.signup.ui package chat.rocket.android.authentication.signup.ui
import DrawableHelper import DrawableHelper
import android.app.Activity.RESULT_OK
import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import android.util.Log
import android.view.* import android.view.*
import android.widget.Toast import android.widget.Toast
import chat.rocket.android.R import chat.rocket.android.R
...@@ -13,12 +16,30 @@ import chat.rocket.android.authentication.signup.presentation.SignupView ...@@ -13,12 +16,30 @@ import chat.rocket.android.authentication.signup.presentation.SignupView
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.TextHelper import chat.rocket.android.helper.TextHelper
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import com.google.android.gms.auth.api.Auth
import com.google.android.gms.auth.api.credentials.Credential
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.common.api.ResolvingResultCallbacks
import com.google.android.gms.common.api.Status
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_sign_up.* import kotlinx.android.synthetic.main.fragment_authentication_sign_up.*
import javax.inject.Inject import javax.inject.Inject
class SignupFragment : Fragment(), SignupView { internal const val SAVE_CREDENTIALS = 1
@Inject lateinit var presenter: SignupPresenter
class SignupFragment : Fragment(), SignupView, GoogleApiClient.ConnectionCallbacks {
override fun onConnected(p0: Bundle?) {
saveCredentials()
}
override fun onConnectionSuspended(p0: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@Inject
lateinit var presenter: SignupPresenter
private var googleApiClient: GoogleApiClient? = null
private var credentialsToBeSaved: Credential? = null
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener { private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
if (KeyboardHelper.isSoftKeyboardShown(relative_layout.rootView)) { if (KeyboardHelper.isSoftKeyboardShown(relative_layout.rootView)) {
bottom_container.setVisible(false) bottom_container.setVisible(false)
...@@ -58,6 +79,12 @@ class SignupFragment : Fragment(), SignupView { ...@@ -58,6 +79,12 @@ class SignupFragment : Fragment(), SignupView {
} }
} }
override fun onDestroy() {
super.onDestroy()
googleApiClient!!.stopAutoManage(activity!!)
googleApiClient!!.disconnect()
}
override fun onDestroyView() { override fun onDestroyView() {
relative_layout.viewTreeObserver.removeOnGlobalLayoutListener(layoutListener) relative_layout.viewTreeObserver.removeOnGlobalLayoutListener(layoutListener)
super.onDestroyView() super.onDestroyView()
...@@ -95,6 +122,50 @@ class SignupFragment : Fragment(), SignupView { ...@@ -95,6 +122,50 @@ class SignupFragment : Fragment(), SignupView {
} }
} }
override fun saveSmartLockCredentials(loginCredential: Credential) {
credentialsToBeSaved = loginCredential
googleApiClient = GoogleApiClient.Builder(context!!)
.enableAutoManage(activity!!, {
Log.d("STATUS", "ERROR: connection to client failed")
})
.addConnectionCallbacks(this)
.addApi(Auth.CREDENTIALS_API)
.build()
}
override fun onStart() {
super.onStart()
saveCredentials()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == SAVE_CREDENTIALS) {
if (resultCode == RESULT_OK) {
Toast.makeText(context, "Credentials saved successfully", Toast.LENGTH_SHORT).show()
} else {
Log.e("STATUS", "ERROR: Cancelled by user")
}
}
}
private fun saveCredentials() {
if (credentialsToBeSaved == null) {
return
}
Auth.CredentialsApi.save(googleApiClient, credentialsToBeSaved).setResultCallback(
object : ResolvingResultCallbacks<Status>(activity!!, SAVE_CREDENTIALS) {
override fun onSuccess(status: Status) {
Log.d("STATUS", "save:SUCCESS:$status")
credentialsToBeSaved = null
}
override fun onUnresolvableFailure(status: Status) {
Log.w("STATUS", "save:FAILURE:$status")
credentialsToBeSaved = null
}
})
}
override fun showLoading() { override fun showLoading() {
ui { ui {
enableUserInput(false) enableUserInput(false)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment