feat(auth): Added New SSO Login Activity.

This commit is contained in:
Neil Marietta
2023-05-23 16:03:45 +02:00
parent 2f6aa7312c
commit 92ef3964f0
12 changed files with 492 additions and 25 deletions
+138
View File
@@ -30,6 +30,10 @@ public class hilt_aggregated_deps/_me_proton_core_auth_presentation_ui_LoginActi
public fun <init> ()V
}
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_ui_LoginSsoActivity_GeneratedInjector {
public fun <init> ()V
}
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_ui_SecondFactorActivity_GeneratedInjector {
public fun <init> ()V
}
@@ -90,6 +94,14 @@ public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_Co
public fun <init> ()V
}
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_LoginSsoViewModel_HiltModules_BindsModule {
public fun <init> ()V
}
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_LoginSsoViewModel_HiltModules_KeyModule {
public fun <init> ()V
}
public class hilt_aggregated_deps/_me_proton_core_auth_presentation_viewmodel_LoginViewModel_HiltModules_BindsModule {
public fun <init> ()V
}
@@ -177,6 +189,7 @@ public final class me/proton/core/auth/presentation/AuthOrchestrator {
public final fun setOnChooseAddressResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnConfirmPasswordResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnLoginResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnLoginSsoResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnSecondFactorResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnSignUpResult (Lkotlin/jvm/functions/Function1;)V
public final fun setOnTwoPassModeResult (Lkotlin/jvm/functions/Function1;)V
@@ -184,6 +197,8 @@ public final class me/proton/core/auth/presentation/AuthOrchestrator {
public static synthetic fun startAddAccountWorkflow$default (Lme/proton/core/auth/presentation/AuthOrchestrator;Lme/proton/core/account/domain/entity/AccountType;Lme/proton/core/account/domain/entity/AccountType;Lme/proton/core/domain/entity/Product;Ljava/lang/String;ILjava/lang/Object;)V
public final fun startChooseAddressWorkflow (Lme/proton/core/account/domain/entity/Account;)V
public final fun startConfirmPasswordWorkflow (Lme/proton/core/network/domain/scopes/MissingScopeState$ScopeMissing;)V
public final fun startLoginSsoWorkflow (Ljava/lang/String;)V
public static synthetic fun startLoginSsoWorkflow$default (Lme/proton/core/auth/presentation/AuthOrchestrator;Ljava/lang/String;ILjava/lang/Object;)V
public final fun startLoginWorkflow (Lme/proton/core/account/domain/entity/AccountType;Ljava/lang/String;Ljava/lang/String;)V
public static synthetic fun startLoginWorkflow$default (Lme/proton/core/auth/presentation/AuthOrchestrator;Lme/proton/core/account/domain/entity/AccountType;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)V
public final fun startSecondFactorWorkflow (Lme/proton/core/account/domain/entity/Account;)V
@@ -198,6 +213,7 @@ public final class me/proton/core/auth/presentation/AuthOrchestratorKt {
public static final fun onChooseAddressResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onConfirmPasswordResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onLoginResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onLoginSsoResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onOnSignUpResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onSecondFactorResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
public static final fun onTwoPassModeResult (Lme/proton/core/auth/presentation/AuthOrchestrator;Lkotlin/jvm/functions/Function1;)Lme/proton/core/auth/presentation/AuthOrchestrator;
@@ -442,6 +458,21 @@ public final class me/proton/core/auth/presentation/databinding/ActivityLoginBin
public static fun inflate (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Z)Lme/proton/core/auth/presentation/databinding/ActivityLoginBinding;
}
public final class me/proton/core/auth/presentation/databinding/ActivityLoginSsoBinding : androidx/viewbinding/ViewBinding {
public final field emailInput Lme/proton/core/challenge/presentation/ProtonMetadataInput;
public final field scrollContent Landroidx/core/widget/NestedScrollView;
public final field signInButton Lme/proton/core/presentation/ui/view/ProtonProgressButton;
public final field signInWithPasswordButton Lme/proton/core/presentation/ui/view/ProtonButton;
public final field subtitleText Landroid/widget/TextView;
public final field titleText Landroid/widget/TextView;
public final field toolbar Lcom/google/android/material/appbar/MaterialToolbar;
public static fun bind (Landroid/view/View;)Lme/proton/core/auth/presentation/databinding/ActivityLoginSsoBinding;
public synthetic fun getRoot ()Landroid/view/View;
public fun getRoot ()Landroidx/coordinatorlayout/widget/CoordinatorLayout;
public static fun inflate (Landroid/view/LayoutInflater;)Lme/proton/core/auth/presentation/databinding/ActivityLoginSsoBinding;
public static fun inflate (Landroid/view/LayoutInflater;Landroid/view/ViewGroup;Z)Lme/proton/core/auth/presentation/databinding/ActivityLoginSsoBinding;
}
public final class me/proton/core/auth/presentation/databinding/ActivityMailboxLoginBinding : androidx/viewbinding/ViewBinding {
public final field forgotPasswordButton Lme/proton/core/presentation/ui/view/ProtonButton;
public final field mailboxPasswordInput Lme/proton/core/presentation/ui/view/ProtonInput;
@@ -854,6 +885,54 @@ public final class me/proton/core/auth/presentation/entity/LoginResult$Creator :
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/LoginResult;
}
public final class me/proton/core/auth/presentation/entity/LoginSsoInput : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> ()V
public fun <init> (Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lme/proton/core/auth/presentation/entity/LoginSsoInput;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/LoginSsoInput;Ljava/lang/String;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/LoginSsoInput;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getEmail ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/LoginSsoInput$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/LoginSsoInput;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/LoginSsoInput;
}
public final class me/proton/core/auth/presentation/entity/LoginSsoResult : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Lme/proton/core/auth/presentation/entity/NextStep;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Lme/proton/core/auth/presentation/entity/NextStep;
public final fun copy (Ljava/lang/String;Lme/proton/core/auth/presentation/entity/NextStep;)Lme/proton/core/auth/presentation/entity/LoginSsoResult;
public static synthetic fun copy$default (Lme/proton/core/auth/presentation/entity/LoginSsoResult;Ljava/lang/String;Lme/proton/core/auth/presentation/entity/NextStep;ILjava/lang/Object;)Lme/proton/core/auth/presentation/entity/LoginSsoResult;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getNextStep ()Lme/proton/core/auth/presentation/entity/NextStep;
public final fun getUserId ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/proton/core/auth/presentation/entity/LoginSsoResult$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun createFromParcel (Landroid/os/Parcel;)Lme/proton/core/auth/presentation/entity/LoginSsoResult;
public synthetic fun newArray (I)[Ljava/lang/Object;
public final fun newArray (I)[Lme/proton/core/auth/presentation/entity/LoginSsoResult;
}
public final class me/proton/core/auth/presentation/entity/NextStep : java/lang/Enum, android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field ChooseAddress Lme/proton/core/auth/presentation/entity/NextStep;
@@ -1370,6 +1449,15 @@ public abstract class me/proton/core/auth/presentation/ui/Hilt_LoginActivity : m
protected fun inject ()V
}
public abstract class me/proton/core/auth/presentation/ui/Hilt_LoginSsoActivity : me/proton/core/auth/presentation/ui/AuthActivity, dagger/hilt/internal/GeneratedComponentManagerHolder {
public final fun componentManager ()Ldagger/hilt/android/internal/managers/ActivityComponentManager;
public synthetic fun componentManager ()Ldagger/hilt/internal/GeneratedComponentManager;
protected fun createComponentManager ()Ldagger/hilt/android/internal/managers/ActivityComponentManager;
public final fun generatedComponent ()Ljava/lang/Object;
public fun getDefaultViewModelProviderFactory ()Landroidx/lifecycle/ViewModelProvider$Factory;
protected fun inject ()V
}
public abstract class me/proton/core/auth/presentation/ui/Hilt_SecondFactorActivity : me/proton/core/auth/presentation/ui/AuthActivity, dagger/hilt/internal/GeneratedComponentManagerHolder {
public final fun componentManager ()Ldagger/hilt/android/internal/managers/ActivityComponentManager;
public synthetic fun componentManager ()Ldagger/hilt/internal/GeneratedComponentManager;
@@ -1429,6 +1517,21 @@ public final class me/proton/core/auth/presentation/ui/LoginActivity_MembersInje
public fun injectMembers (Lme/proton/core/auth/presentation/ui/LoginActivity;)V
}
public final class me/proton/core/auth/presentation/ui/LoginSsoActivity : me/proton/core/auth/presentation/ui/AuthActivity {
public static final field ARG_INPUT Ljava/lang/String;
public static final field ARG_RESULT Ljava/lang/String;
public static final field Companion Lme/proton/core/auth/presentation/ui/LoginSsoActivity$Companion;
public fun <init> ()V
public fun showLoading (Z)V
}
public final class me/proton/core/auth/presentation/ui/LoginSsoActivity$Companion {
}
public abstract interface class me/proton/core/auth/presentation/ui/LoginSsoActivity_GeneratedInjector {
public abstract fun injectLoginSsoActivity (Lme/proton/core/auth/presentation/ui/LoginSsoActivity;)V
}
public final class me/proton/core/auth/presentation/ui/SecondFactorActivity : me/proton/core/auth/presentation/ui/AuthActivity {
public static final field ARG_INPUT Ljava/lang/String;
public static final field ARG_RESULT Ljava/lang/String;
@@ -1470,6 +1573,14 @@ public final class me/proton/core/auth/presentation/ui/StartLogin : androidx/act
public fun parseResult (ILandroid/content/Intent;)Lme/proton/core/auth/presentation/entity/LoginResult;
}
public final class me/proton/core/auth/presentation/ui/StartLoginSso : androidx/activity/result/contract/ActivityResultContract {
public fun <init> ()V
public synthetic fun createIntent (Landroid/content/Context;Ljava/lang/Object;)Landroid/content/Intent;
public fun createIntent (Landroid/content/Context;Lme/proton/core/auth/presentation/entity/LoginSsoInput;)Landroid/content/Intent;
public synthetic fun parseResult (ILandroid/content/Intent;)Ljava/lang/Object;
public fun parseResult (ILandroid/content/Intent;)Lme/proton/core/auth/presentation/entity/LoginSsoResult;
}
public final class me/proton/core/auth/presentation/ui/StartSecondFactor : androidx/activity/result/contract/ActivityResultContract {
public fun <init> ()V
public synthetic fun createIntent (Landroid/content/Context;Ljava/lang/Object;)Landroid/content/Intent;
@@ -2033,6 +2144,33 @@ public final class me/proton/core/auth/presentation/viewmodel/ConfirmPasswordDia
public static fun provide ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_Factory : dagger/internal/Factory {
public fun <init> ()V
public static fun create ()Lme/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_Factory;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Lme/proton/core/auth/presentation/viewmodel/LoginSsoViewModel;
public static fun newInstance ()Lme/proton/core/auth/presentation/viewmodel/LoginSsoViewModel;
}
public final class me/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_HiltModules {
}
public abstract class me/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_HiltModules$BindsModule {
public abstract fun binds (Lme/proton/core/auth/presentation/viewmodel/LoginSsoViewModel;)Landroidx/lifecycle/ViewModel;
}
public final class me/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_HiltModules$KeyModule {
public static fun provide ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_HiltModules_KeyModule_ProvideFactory : dagger/internal/Factory {
public fun <init> ()V
public static fun create ()Lme/proton/core/auth/presentation/viewmodel/LoginSsoViewModel_HiltModules_KeyModule_ProvideFactory;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Ljava/lang/String;
public static fun provide ()Ljava/lang/String;
}
public final class me/proton/core/auth/presentation/viewmodel/LoginViewModel_Factory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lme/proton/core/auth/presentation/viewmodel/LoginViewModel_Factory;
@@ -49,6 +49,11 @@
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.LoginSsoActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.SecondFactorActivity"
android:screenOrientation="portrait"
@@ -30,6 +30,8 @@ import me.proton.core.auth.presentation.entity.ChooseAddressInput
import me.proton.core.auth.presentation.entity.ChooseAddressResult
import me.proton.core.auth.presentation.entity.LoginInput
import me.proton.core.auth.presentation.entity.LoginResult
import me.proton.core.auth.presentation.entity.LoginSsoInput
import me.proton.core.auth.presentation.entity.LoginSsoResult
import me.proton.core.auth.presentation.entity.SecondFactorInput
import me.proton.core.auth.presentation.entity.SecondFactorResult
import me.proton.core.auth.presentation.entity.TwoPassModeInput
@@ -41,6 +43,7 @@ import me.proton.core.auth.presentation.entity.signup.SignUpResult
import me.proton.core.auth.presentation.ui.StartAddAccount
import me.proton.core.auth.presentation.ui.StartChooseAddress
import me.proton.core.auth.presentation.ui.StartLogin
import me.proton.core.auth.presentation.ui.StartLoginSso
import me.proton.core.auth.presentation.ui.StartSecondFactor
import me.proton.core.auth.presentation.ui.StartSignup
import me.proton.core.auth.presentation.ui.StartTwoPassMode
@@ -55,6 +58,7 @@ class AuthOrchestrator @Inject constructor() {
// region result launchers
private var addAccountWorkflowLauncher: ActivityResultLauncher<AddAccountInput>? = null
private var loginWorkflowLauncher: ActivityResultLauncher<LoginInput>? = null
private var loginSsoWorkflowLauncher: ActivityResultLauncher<LoginSsoInput>? = null
private var secondFactorWorkflowLauncher: ActivityResultLauncher<SecondFactorInput>? = null
private var twoPassModeWorkflowLauncher: ActivityResultLauncher<TwoPassModeInput>? = null
private var chooseAddressLauncher: ActivityResultLauncher<ChooseAddressInput>? = null
@@ -65,6 +69,7 @@ class AuthOrchestrator @Inject constructor() {
private var onAddAccountResultListener: ((result: AddAccountResult?) -> Unit)? = {}
private var onLoginResultListener: ((result: LoginResult?) -> Unit)? = {}
private var onLoginSsoResultListener: ((result: LoginSsoResult?) -> Unit)? = {}
private var onTwoPassModeResultListener: ((result: TwoPassModeResult?) -> Unit)? = {}
private var onSecondFactorResultListener: ((result: SecondFactorResult?) -> Unit)? = {}
private var onChooseAddressResultListener: ((result: ChooseAddressResult?) -> Unit)? = {}
@@ -79,6 +84,10 @@ class AuthOrchestrator @Inject constructor() {
onLoginResultListener = block
}
fun setOnLoginSsoResult(block: (result: LoginSsoResult?) -> Unit) {
onLoginSsoResultListener = block
}
fun setOnTwoPassModeResult(block: (result: TwoPassModeResult?) -> Unit) {
onTwoPassModeResultListener = block
}
@@ -120,6 +129,15 @@ class AuthOrchestrator @Inject constructor() {
onLoginResultListener?.invoke(it)
}
private fun registerLoginSsoResult(
caller: ActivityResultCaller
): ActivityResultLauncher<LoginSsoInput> =
caller.registerForActivityResult(
StartLoginSso()
) {
onLoginSsoResultListener?.invoke(it)
}
private fun registerTwoPassModeResult(
caller: ActivityResultCaller
): ActivityResultLauncher<TwoPassModeInput> =
@@ -284,6 +302,19 @@ class AuthOrchestrator @Inject constructor() {
)
}
/**
* Starts the Login SSO workflow.
*
* @see [onLoginSsoResult]
*/
fun startLoginSsoWorkflow(
email: String? = null,
) {
checkRegistered(loginSsoWorkflowLauncher).launch(
LoginSsoInput(email)
)
}
/**
* Start a Second Factor workflow.
* In case the Second Factor fails with [SecondFactorResult.UnrecoverableError],
@@ -388,6 +419,13 @@ fun AuthOrchestrator.onLoginResult(
return this
}
fun AuthOrchestrator.onLoginSsoResult(
block: (result: LoginSsoResult?) -> Unit
): AuthOrchestrator {
setOnLoginSsoResult { block(it) }
return this
}
fun AuthOrchestrator.onTwoPassModeResult(
block: (result: TwoPassModeResult?) -> Unit
): AuthOrchestrator {
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.presentation.entity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class LoginSsoInput(
val email: String? = null,
) : Parcelable
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2023 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.presentation.entity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class LoginSsoResult(
val userId: String,
val nextStep: NextStep,
) : Parcelable
@@ -28,6 +28,8 @@ import me.proton.core.auth.presentation.entity.ChooseAddressInput
import me.proton.core.auth.presentation.entity.ChooseAddressResult
import me.proton.core.auth.presentation.entity.LoginInput
import me.proton.core.auth.presentation.entity.LoginResult
import me.proton.core.auth.presentation.entity.LoginSsoInput
import me.proton.core.auth.presentation.entity.LoginSsoResult
import me.proton.core.auth.presentation.entity.SecondFactorInput
import me.proton.core.auth.presentation.entity.SecondFactorResult
import me.proton.core.auth.presentation.entity.TwoPassModeInput
@@ -64,6 +66,20 @@ class StartLogin : ActivityResultContract<LoginInput, LoginResult?>() {
}
}
class StartLoginSso : ActivityResultContract<LoginSsoInput, LoginSsoResult?>() {
override fun createIntent(context: Context, input: LoginSsoInput) =
Intent(context, LoginSsoActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
putExtra(LoginSsoActivity.ARG_INPUT, input)
}
override fun parseResult(resultCode: Int, result: Intent?): LoginSsoResult? {
if (resultCode != Activity.RESULT_OK) return null
return result?.getParcelableExtra(LoginSsoActivity.ARG_RESULT)
}
}
class StartSecondFactor : ActivityResultContract<SecondFactorInput, SecondFactorResult?>() {
override fun createIntent(context: Context, inupt: SecondFactorInput) =
@@ -18,7 +18,11 @@
package me.proton.core.auth.presentation.ui
import android.content.Intent
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import androidx.viewbinding.ViewBinding
import com.google.android.material.snackbar.Snackbar
import me.proton.core.auth.domain.usecase.PostLoginAccountSetup
@@ -34,6 +38,26 @@ abstract class AuthActivity<ViewBindingT : ViewBinding>(
bindingInflater: (LayoutInflater) -> ViewBindingT
) : ProtonSecureActivity<ViewBindingT>(bindingInflater) {
fun setActionBarAuthMenu(toolbar: Toolbar) {
setSupportActionBar(toolbar)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
supportActionBar?.setDisplayShowTitleEnabled(false)
menuInflater.inflate(R.menu.login_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.login_menu_help -> startAuthHelpActivity()
else -> super.onOptionsItemSelected(item)
}
private fun startAuthHelpActivity(): Boolean {
startActivity(Intent(this, AuthHelpActivity::class.java))
return true
}
open fun showLoading(loading: Boolean) {
// No op
}
@@ -22,8 +22,6 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.core.view.isVisible
@@ -35,7 +33,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import me.proton.core.account.domain.entity.AccountType
import me.proton.core.auth.domain.usecase.PostLoginAccountSetup
import me.proton.core.auth.presentation.R
import me.proton.core.auth.presentation.databinding.ActivityLoginBinding
@@ -76,16 +73,16 @@ class LoginActivity : AuthActivity<ActivityLoginBinding>(ActivityLoginBinding::i
requireNotNull(intent?.extras?.getParcelable(ARG_INPUT))
}
// Todo: loginSsoResultLauncher.launch(LoginSsoInput(usernameInput.text.toString()))
private val loginSsoResultLauncher = registerForActivityResult(StartLoginSso()) {
if (it != null) onSuccess(UserId(it.userId), it.nextStep)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSupportActionBar(binding.toolbar)
supportActionBar?.title = ""
binding.apply {
toolbar.setNavigationOnClickListener {
onBackPressed()
}
setActionBarAuthMenu(toolbar)
toolbar.setNavigationOnClickListener { onBackPressed() }
signInButton.onClick(::onSignInClicked)
signInWithSsoButton.isVisible = viewModel.isSSOEnabled
@@ -143,21 +140,6 @@ class LoginActivity : AuthActivity<ActivityLoginBinding>(ActivityLoginBinding::i
.launchIn(lifecycleScope)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.login_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.login_menu_help -> {
startActivity(Intent(this, AuthHelpActivity::class.java))
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun onAccountSetupResult(result: PostLoginAccountSetup.Result) {
when (result) {
is PostLoginAccountSetup.Result.Error.UnlockPrimaryKeyError -> onUnlockUserError(result.error)
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2023 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.auth.presentation.ui
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import dagger.hilt.android.AndroidEntryPoint
import me.proton.core.auth.presentation.R
import me.proton.core.auth.presentation.databinding.ActivityLoginSsoBinding
import me.proton.core.auth.presentation.entity.LoginSsoInput
import me.proton.core.auth.presentation.entity.LoginSsoResult
import me.proton.core.auth.presentation.entity.NextStep
import me.proton.core.auth.presentation.viewmodel.LoginSsoViewModel
import me.proton.core.domain.entity.UserId
import me.proton.core.presentation.utils.hideKeyboard
import me.proton.core.presentation.utils.onClick
import me.proton.core.presentation.utils.onFailure
import me.proton.core.presentation.utils.onSuccess
import me.proton.core.presentation.utils.validateEmail
@AndroidEntryPoint
class LoginSsoActivity : AuthActivity<ActivityLoginSsoBinding>(ActivityLoginSsoBinding::inflate) {
private val viewModel by viewModels<LoginSsoViewModel>()
private val input: LoginSsoInput? by lazy {
intent?.extras?.getParcelable(ARG_INPUT)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.apply {
setActionBarAuthMenu(toolbar)
toolbar.setNavigationOnClickListener { finish() }
signInButton.onClick(::onSignInClicked)
emailInput.text = input?.email
signInWithPasswordButton.onClick { finish() }
}
}
override fun showLoading(loading: Boolean) = with(binding) {
if (loading) {
signInButton.setLoading()
} else {
signInButton.setIdle()
}
emailInput.isEnabled = !loading
}
private fun onSignInClicked() {
with(binding) {
hideKeyboard()
emailInput.clearInputError()
emailInput.validateEmail()
.onFailure { emailInput.setInputError(getString(R.string.auth_login_sso_assistive_text)) }
.onSuccess { setResultAndFinish(UserId("userId")) }
}
}
private fun setResultAndFinish(userId: UserId) {
setResult(RESULT_OK, Intent().putExtra(ARG_RESULT, LoginSsoResult(userId.id, NextStep.None)))
finish()
}
companion object {
const val ARG_INPUT = "arg.loginSsoInput"
const val ARG_RESULT = "arg.loginSsoResult"
}
}
@@ -0,0 +1,8 @@
package me.proton.core.auth.presentation.viewmodel
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
internal class LoginSsoViewModel @Inject constructor() : ViewModel() {}
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2023 Proton AG
~ This file is part of Proton AG and ProtonCore.
~
~ ProtonCore is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ ProtonCore is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:navigationContentDescription="@string/presentation_close"
app:navigationIcon="@drawable/ic_proton_close"
tools:title="Title" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
style="@style/AuthContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_marginTop="@dimen/gap_large"
app:srcCompat="@drawable/ic_logo_proton" />
<TextView
android:id="@+id/titleText"
style="@style/ProtonTextView.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="@dimen/gap_large"
android:gravity="center"
android:text="@string/auth_sign_in_sso" />
<TextView
android:id="@+id/subtitleText"
style="@style/ProtonTextView.Subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="@dimen/auth_subtitle_top_margin"
android:gravity="center"
android:text="@string/auth_continue_to_proton_vpn" />
<me.proton.core.challenge.presentation.ProtonMetadataInput
android:id="@+id/emailInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/gap_large_plus"
android:focusable="true"
android:focusableInTouchMode="true"
android:inputType="text|textEmailAddress|textNoSuggestions"
app:label="@string/auth_email" />
<me.proton.core.presentation.ui.view.ProtonProgressButton
android:id="@+id/signInButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/auth_content_separator_top_margin"
android:text="@string/auth_sign_in_action" />
<me.proton.core.presentation.ui.view.ProtonButton
android:id="@+id/signInWithPasswordButton"
style="@style/ProtonButton.Borderless.Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/auth_view_items_top_margin"
android:text="@string/auth_sign_in_with_password" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -35,13 +35,18 @@
<string name="auth_current_login_password">Current login password</string>
<string name="auth_enter_six_digit_code">Enter 6-digit code</string>
<string name="auth_second_factor_code">Two-Factor code</string>
<string name="auth_email">Email</string>
<string name="auth_email_username">Username or email</string>
<string name="auth_account_details">Enter your Proton Account details.</string>
<string name="auth_sign_in">Sign in</string>
<string name="auth_sign_in_action">Sign in</string>
<string name="auth_sign_in_sso">Sign in to your organization</string>
<string name="auth_sign_in_with_password">Sign in with a password</string>
<string name="auth_continue_to_proton_vpn">to continue to Proton VPN</string>
<string name="auth_sign_in_with_sso">Sign in with SSO</string>
<string name="auth_help_label">Help</string>
<string name="auth_login_assistive_text">Please enter your Proton email or username.</string>
<string name="auth_login_sso_assistive_text">Please enter your email.</string>
<string name="auth_help_title">How can we help?</string>
<string name="auth_help_option_forgot_username">Forgot username</string>
<string name="auth_help_option_forgot_password">Forgot password</string>