Unverified Commit 2625c52c authored by Hussein El Feky's avatar Hussein El Feky Committed by GitHub

Added animation when expanding/collapsing login options

parent acb0f6f3
package chat.rocket.android.authentication.loginoptions.ui
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Intent
import android.graphics.PorterDuff
......@@ -7,10 +10,13 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.widget.Button
import android.widget.LinearLayout
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isVisible
import androidx.core.view.marginTop
import androidx.fragment.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager
......@@ -62,32 +68,32 @@ internal const val REQUEST_CODE_FOR_CAS = 2
internal const val REQUEST_CODE_FOR_SAML = 3
fun newInstance(
serverName: String,
state: String? = null,
facebookOauthUrl: String? = null,
githubOauthUrl: String? = null,
googleOauthUrl: String? = null,
linkedinOauthUrl: String? = null,
gitlabOauthUrl: String? = null,
wordpressOauthUrl: String? = null,
casLoginUrl: String? = null,
casToken: String? = null,
casServiceName: String? = null,
casServiceNameTextColor: Int = 0,
casServiceButtonColor: Int = 0,
customOauthUrl: String? = null,
customOauthServiceName: String? = null,
customOauthServiceNameTextColor: Int = 0,
customOauthServiceButtonColor: Int = 0,
samlUrl: String? = null,
samlToken: String? = null,
samlServiceName: String? = null,
samlServiceNameTextColor: Int = 0,
samlServiceButtonColor: Int = 0,
totalSocialAccountsEnabled: Int = 0,
isLoginFormEnabled: Boolean,
isNewAccountCreationEnabled: Boolean,
deepLinkInfo: LoginDeepLinkInfo? = null
serverName: String,
state: String? = null,
facebookOauthUrl: String? = null,
githubOauthUrl: String? = null,
googleOauthUrl: String? = null,
linkedinOauthUrl: String? = null,
gitlabOauthUrl: String? = null,
wordpressOauthUrl: String? = null,
casLoginUrl: String? = null,
casToken: String? = null,
casServiceName: String? = null,
casServiceNameTextColor: Int = 0,
casServiceButtonColor: Int = 0,
customOauthUrl: String? = null,
customOauthServiceName: String? = null,
customOauthServiceNameTextColor: Int = 0,
customOauthServiceButtonColor: Int = 0,
samlUrl: String? = null,
samlToken: String? = null,
samlServiceName: String? = null,
samlServiceNameTextColor: Int = 0,
samlServiceButtonColor: Int = 0,
totalSocialAccountsEnabled: Int = 0,
isLoginFormEnabled: Boolean,
isNewAccountCreationEnabled: Boolean,
deepLinkInfo: LoginDeepLinkInfo? = null
): Fragment = LoginOptionsFragment().apply {
arguments = Bundle(23).apply {
putString(SERVER_NAME, serverName)
......@@ -186,9 +192,9 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = container?.inflate(R.layout.fragment_authentication_login_options)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
......@@ -253,11 +259,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
private fun setupCas() {
if (casLoginUrl != null && casToken != null && casServiceName != null) {
addCasButton(
casLoginUrl.toString(),
casToken.toString(),
casServiceName.toString(),
casServiceNameTextColor,
casServiceButtonColor
casLoginUrl.toString(),
casToken.toString(),
casServiceName.toString(),
casServiceNameTextColor,
casServiceButtonColor
)
}
}
......@@ -265,11 +271,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
private fun setupCustomOauth() {
if (customOauthUrl != null && state != null && customOauthServiceName != null) {
addCustomOauthButton(
customOauthUrl.toString(),
state.toString(),
customOauthServiceName.toString(),
customOauthServiceTextColor,
customOauthServiceButtonColor
customOauthUrl.toString(),
state.toString(),
customOauthServiceName.toString(),
customOauthServiceTextColor,
customOauthServiceButtonColor
)
}
}
......@@ -277,11 +283,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
private fun setupSaml() {
if (samlUrl != null && samlToken != null && samlServiceName != null) {
addSamlButton(
samlUrl.toString(),
samlToken.toString(),
samlServiceName.toString(),
samlServiceTextColor,
samlServiceButtonColor
samlUrl.toString(),
samlToken.toString(),
samlServiceName.toString(),
samlServiceTextColor,
samlServiceButtonColor
)
}
}
......@@ -311,40 +317,40 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
override fun enableLoginByFacebook() = enableAccountButton(button_facebook)
override fun setupFacebookButtonListener(facebookOauthUrl: String, state: String) =
setupButtonListener(button_facebook, facebookOauthUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_facebook, facebookOauthUrl, state, REQUEST_CODE_FOR_OAUTH)
override fun enableLoginByGithub() = enableAccountButton(button_github)
override fun setupGithubButtonListener(githubUrl: String, state: String) =
setupButtonListener(button_github, githubUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_github, githubUrl, state, REQUEST_CODE_FOR_OAUTH)
override fun enableLoginByGoogle() = enableAccountButton(button_google)
override fun setupGoogleButtonListener(googleUrl: String, state: String) =
setupButtonListener(button_google, googleUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_google, googleUrl, state, REQUEST_CODE_FOR_OAUTH)
override fun enableLoginByLinkedin() = enableAccountButton(button_linkedin)
override fun setupLinkedinButtonListener(linkedinUrl: String, state: String) =
setupButtonListener(button_linkedin, linkedinUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_linkedin, linkedinUrl, state, REQUEST_CODE_FOR_OAUTH)
override fun enableLoginByGitlab() = enableAccountButton(button_gitlab)
override fun setupGitlabButtonListener(gitlabUrl: String, state: String) =
setupButtonListener(button_gitlab, gitlabUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_gitlab, gitlabUrl, state, REQUEST_CODE_FOR_OAUTH)
override fun enableLoginByWordpress() = enableAccountButton(button_wordpress)
override fun setupWordpressButtonListener(wordpressUrl: String, state: String) =
setupButtonListener(button_wordpress, wordpressUrl, state, REQUEST_CODE_FOR_OAUTH)
setupButtonListener(button_wordpress, wordpressUrl, state, REQUEST_CODE_FOR_OAUTH)
// CAS service account.
override fun addCasButton(
caslUrl: String,
casToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
caslUrl: String,
casToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
) {
val button = getCustomServiceButton(serviceName, serviceNameColor, buttonColor)
setupButtonListener(button, caslUrl, casToken, REQUEST_CODE_FOR_CAS)
......@@ -353,11 +359,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
// Custom OAuth account.
override fun addCustomOauthButton(
customOauthUrl: String,
state: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
customOauthUrl: String,
state: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
) {
val button = getCustomServiceButton(serviceName, serviceNameColor, buttonColor)
setupButtonListener(button, customOauthUrl, state, REQUEST_CODE_FOR_OAUTH)
......@@ -366,11 +372,11 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
// SAML account.
override fun addSamlButton(
samlUrl: String,
samlToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
samlUrl: String,
samlToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
) {
val button = getCustomServiceButton(serviceName, serviceNameColor, buttonColor)
setupButtonListener(button, samlUrl, samlToken, REQUEST_CODE_FOR_SAML)
......@@ -421,12 +427,12 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
when (requestCode) {
REQUEST_CODE_FOR_OAUTH -> {
presenter.authenticateWithOauth(
data.getStringExtra(INTENT_OAUTH_CREDENTIAL_TOKEN),
data.getStringExtra(INTENT_OAUTH_CREDENTIAL_SECRET)
data.getStringExtra(INTENT_OAUTH_CREDENTIAL_TOKEN),
data.getStringExtra(INTENT_OAUTH_CREDENTIAL_SECRET)
)
}
REQUEST_CODE_FOR_CAS -> presenter.authenticateWithCas(
data.getStringExtra(INTENT_SSO_TOKEN)
data.getStringExtra(INTENT_SSO_TOKEN)
)
REQUEST_CODE_FOR_SAML -> data.apply {
presenter.authenticateWithSaml(getStringExtra(INTENT_SSO_TOKEN))
......@@ -470,22 +476,22 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
}
private fun setupButtonListener(
button: Button,
accountUrl: String,
argument: String,
requestCode: Int
button: Button,
accountUrl: String,
argument: String,
requestCode: Int
) {
ui { activity ->
button.setOnClickListener {
when (requestCode) {
REQUEST_CODE_FOR_OAUTH -> startActivityForResult(
activity.oauthWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_OAUTH
activity.oauthWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_OAUTH
)
REQUEST_CODE_FOR_CAS -> startActivityForResult(
activity.ssoWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_CAS
activity.ssoWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_CAS
)
REQUEST_CODE_FOR_SAML -> startActivityForResult(
activity.ssoWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_SAML
activity.ssoWebViewIntent(accountUrl, argument), REQUEST_CODE_FOR_SAML
)
}
......@@ -498,22 +504,22 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
* Gets a stylized custom service button.
*/
private fun getCustomServiceButton(
buttonText: String,
buttonTextColor: Int,
buttonBgColor: Int
buttonText: String,
buttonTextColor: Int,
buttonBgColor: Int
): Button {
val params: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
val marginTop = resources.getDimensionPixelSize(R.dimen.button_account_margin_top)
params.setMargins(0, marginTop, 0, 0)
val button = Button(
ContextThemeWrapper(context, R.style.Authentication_Button),
null,
R.style.Authentication_Button
ContextThemeWrapper(context, R.style.Authentication_Button),
null,
R.style.Authentication_Button
)
button.layoutParams = params
button.text = buttonText
......@@ -525,24 +531,87 @@ class LoginOptionsFragment : Fragment(), LoginOptionsView {
private fun showThreeAccountsMethods() {
(0..accounts_container.childCount)
.mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable }
.take(3)
.forEach { it.isVisible = true }
.mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable }
.take(3)
.forEach { it.isVisible = true }
}
private fun expandAccountsView() {
(0..accounts_container.childCount)
.mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable && !it.isVisible }
.forEach { it.isVisible = true }
val collapsedHeight = accounts_container.height
var expandedHeight = collapsedHeight
val optionHeight = accounts_container.getChildAt(1).height +
accounts_container.getChildAt(1).marginTop
for (i in 0 until accounts_container.childCount) {
val bt = accounts_container.getChildAt(i) as Button
if (bt.isClickable && !bt.isVisible) {
expandedHeight += optionHeight
}
}
val animation = ValueAnimator.ofInt(collapsedHeight, expandedHeight)
animation.addUpdateListener {
val params = accounts_container.layoutParams
params.height = animation.animatedValue as Int
accounts_container.layoutParams = params
}
animation.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animator: Animator) {
for (i in 0 until accounts_container.childCount) {
val bt = accounts_container.getChildAt(i) as Button
if (!bt.isVisible) {
bt.isVisible = true
val anim = AlphaAnimation(0.0f, 1.0f)
anim.duration = 400
bt.startAnimation(anim)
}
}
}
})
animation.setDuration(400).start()
}
private fun collapseAccountsView() {
(0..accounts_container.childCount)
.mapNotNull { accounts_container.getChildAt(it) as? Button }
.filter { it.isClickable && it.isVisible }
.drop(3)
.forEach { it.isVisible = false }
val expandedHeight = accounts_container.height
var collapsedHeight = expandedHeight
val optionHeight = accounts_container.getChildAt(1).height +
accounts_container.getChildAt(1).marginTop
for (i in 3 until accounts_container.childCount) {
val bt = accounts_container.getChildAt(i) as Button
if (bt.isClickable && bt.isVisible) {
collapsedHeight -= optionHeight
}
}
val animation = ValueAnimator.ofInt(expandedHeight, collapsedHeight)
animation.addUpdateListener {
val params = accounts_container.layoutParams
params.height = animation.animatedValue as Int
accounts_container.layoutParams = params
}
animation.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animator: Animator) {
for (i in 3 until accounts_container.childCount) {
val bt = accounts_container.getChildAt(i) as Button
if (bt.isVisible) {
val anim = AlphaAnimation(1.0f, 0.0f)
anim.duration = 400
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
bt.isVisible = false
}
override fun onAnimationRepeat(animation: Animation) {
}
})
bt.startAnimation(anim)
}
}
}
})
animation.setDuration(400).start()
}
}
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