Added Proton Core Login minimal needed components.

This commit is contained in:
Neil Marietta 2021-03-24 16:10:41 +01:00
parent c11663d7bf
commit 225eadc0a3
18 changed files with 517 additions and 113 deletions

View File

@ -73,7 +73,11 @@ val testUser3 = properties["TEST_USER3"] ?: privateProperties["TEST_USER3"]
val testUser4 = properties["TEST_USER4"] ?: privateProperties["TEST_USER4"]
val testUser5 = properties["TEST_USER5"] ?: privateProperties["TEST_USER5"]
android(appIdSuffix = "android") {
android(
appIdSuffix = "android",
minSdk = 23,
useDataBinding = true
) {
useLibrary("org.apache.http.legacy")
flavorDimensions("default")
@ -246,13 +250,20 @@ dependencies {
rootProject.aar(Lib.protonCore, version = `old protonCore version`),
// rootProject.aar(Lib.composer, version = `composer version`),
// `Proton-data`,
// Proton Core
`Proton-data`,
`Proton-domain`,
`Proton-presentation`,
`Proton-network`,
`Proton-kotlin-util`,
`Proton-shared-preferences`,
`Proton-work-manager`,
`Proton-crypto`,
`Proton-auth`,
`Proton-account`,
`Proton-account-manager`,
`Proton-user`,
`Proton-key`,
// Modules
project(Module.domain),

View File

@ -427,6 +427,31 @@
android:name=".api.services.ConnectivityService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Core -->
<activity
android:name="me.proton.core.auth.presentation.ui.AuthHelpActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.ChooseAddressActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.CreateAddressActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.LoginActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.TwoPassModeActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="me.proton.core.auth.presentation.ui.SecondFactorActivity"
android:theme="@style/ProtonTheme"
android:windowSoftInputMode="adjustResize" />
</application>
</manifest>

View File

@ -198,7 +198,7 @@ class ChangePasswordActivity : BaseActivity() {
private fun showTwoFactorDialog() {
val builder = AlertDialog.Builder(this)
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.layout_2fa, null)
val dialogView = inflater.inflate(R.layout.layout_2fa_old, null)
val twoFactorCode = dialogView.findViewById<EditText>(R.id.two_factor_code)
val toggleInputText = dialogView.findViewById<ToggleButton>(R.id.toggle_input_text)
toggleInputText.setOnClickListener { v ->

View File

@ -1,56 +1,57 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
*
* This file is part of ProtonMail.
*
*
* ProtonMail 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.
*
*
* ProtonMail 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 ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.activities.guest;
import android.content.Intent;
import android.os.Bundle;
package ch.protonmail.android.activities.guest
import butterknife.OnClick;
import ch.protonmail.android.R;
import ch.protonmail.android.activities.BaseActivity;
import ch.protonmail.android.utils.AppUtil;
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import butterknife.OnClick
import ch.protonmail.android.R
import ch.protonmail.android.activities.BaseActivity
import ch.protonmail.android.feature.account.AccountViewModel
import ch.protonmail.android.utils.AppUtil
/**
* Created by dkadrikj on 11/12/15.
*/
public class FirstActivity extends BaseActivity {
class FirstActivity : BaseActivity() {
@Override
protected int getLayoutId() {
return R.layout.activity_first;
}
private val accountViewModel: AccountViewModel by viewModels()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
override fun getLayoutId(): Int = R.layout.activity_first
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
accountViewModel.register(this)
}
@OnClick(R.id.sign_in)
public void onSignInClicked() {
fun onSignInClicked() {
/*
startActivity(AppUtil.decorInAppIntent(new Intent(this, LoginActivity.class)));
finish();
*/
accountViewModel.startLoginWorkflow()
}
@OnClick(R.id.create_account)
public void onCreateAccountClicked() {
Intent intent = AppUtil.decorInAppIntent(new Intent(this, CreateAccountActivity.class));
intent.putExtra(CreateAccountActivity.EXTRA_WINDOW_SIZE, getWindow().getDecorView().getHeight());
startActivity(intent);
fun onCreateAccountClicked() {
val intent = AppUtil.decorInAppIntent(Intent(this, CreateAccountActivity::class.java))
intent.putExtra(CreateAccountActivity.EXTRA_WINDOW_SIZE, window.decorView.height)
startActivity(intent)
}
}

View File

@ -103,7 +103,7 @@ public class LoginActivity extends BaseLoginActivity {
@Override
protected int getLayoutId() {
return R.layout.activity_login;
return R.layout.activity_login_old;
}
@Override

View File

@ -79,7 +79,7 @@ public class MailboxLoginActivity extends BaseLoginActivity {
@Override
protected int getLayoutId() {
return R.layout.activity_mailbox_login;
return R.layout.activity_mailbox_login_old;
}
@Override

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2020 Proton Technologies AG
*
* This file is part of ProtonMail.
*
* ProtonMail 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.
*
* ProtonMail 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 ProtonMail. If not, see https://www.gnu.org/licenses/.
*/
package ch.protonmail.android.api
import me.proton.core.domain.entity.UserId
import me.proton.core.network.domain.humanverification.HumanVerificationDetails
import me.proton.core.network.domain.session.Session
import me.proton.core.network.domain.session.SessionId
import me.proton.core.network.domain.session.SessionListener
import me.proton.core.network.domain.session.SessionProvider
import javax.inject.Inject
/**
* Provide, handle and persist any [Session] changes - based on [TokenManager].
*
* Makes the link between the Core Network module and old ProtonMail Token persistence.
*
* Note: This will be replaced by Core AccountManager in future.
*/
class TokenSessionManager @Inject constructor(
val accountManager: AccountManager
) : SessionProvider, SessionListener {
private fun getTokenManagerBySessionId(sessionId: String): TokenManager? =
// TODO: Add HashMap for O(1) access time.
accountManager.getLoggedInUsers()
.map { username -> TokenManager.getInstance(username) }
.firstOrNull { it?.uid == sessionId }
override suspend fun getSession(sessionId: SessionId): Session? =
getTokenManagerBySessionId(sessionId.id)?.session
// ProtonMail do not persist userId - only sessionId (TokenManager.uid).
// Let's assume userId === username.
override suspend fun getSessionId(userId: UserId): SessionId? =
TokenManager.getInstance(userId.id)?.uid?.let { SessionId(it) }
override suspend fun onSessionTokenRefreshed(session: Session) {
getTokenManagerBySessionId(session.sessionId.id)?.handleRefresh(session)
}
override suspend fun onSessionForceLogout(session: Session) {
getTokenManagerBySessionId(session.sessionId.id)?.clear()
// TODO: Properly logout user.
}
override suspend fun onHumanVerificationNeeded(
session: Session,
details: HumanVerificationDetails
): SessionListener.HumanVerificationResult {
TODO("Show HumanVerification UI, and block until success or failure")
}
}

View File

@ -0,0 +1,107 @@
/*
* 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 ch.protonmail.android.di
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import me.proton.core.account.data.repository.AccountRepositoryImpl
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.accountmanager.data.AccountManagerImpl
import me.proton.core.accountmanager.data.SessionManagerImpl
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.auth.domain.AccountWorkflowHandler
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.crypto.android.context.AndroidCryptoContext
import me.proton.core.crypto.android.keystore.AndroidKeyStoreCrypto
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.domain.entity.Product
import me.proton.core.network.domain.session.SessionListener
import me.proton.core.network.domain.session.SessionProvider
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AccountManagerModule {
@Provides
@Singleton
fun provideAccountManagerDatabase(@ApplicationContext context: Context): AccountManagerDatabase =
AccountManagerDatabase.buildDatabase(context)
@Provides
@Singleton
fun provideKeyStoreCrypto(): KeyStoreCrypto =
AndroidKeyStoreCrypto.default
@Provides
@Singleton
fun provideCryptoContext(
keyStoreCrypto: KeyStoreCrypto
): CryptoContext =
AndroidCryptoContext(keyStoreCrypto)
@Provides
@Singleton
fun provideAccountRepository(
product: Product,
accountManagerDatabase: AccountManagerDatabase,
keyStoreCrypto: KeyStoreCrypto
): AccountRepository =
AccountRepositoryImpl(product, accountManagerDatabase, keyStoreCrypto)
@Provides
@Singleton
fun provideAccountManagerImpl(
product: Product,
accountRepository: AccountRepository,
authRepository: AuthRepository
): AccountManagerImpl =
AccountManagerImpl(product, accountRepository, authRepository)
@Provides
@Singleton
fun provideSessionManagerImpl(
accountRepository: AccountRepository
): SessionManagerImpl =
SessionManagerImpl(accountRepository)
}
@Module
@InstallIn(SingletonComponent::class)
interface AccountManagerBindModule {
@Binds
fun bindAccountManager(accountManagerImpl: AccountManagerImpl): AccountManager
@Binds
fun bindAccountWorkflowHandler(accountManagerImpl: AccountManagerImpl): AccountWorkflowHandler
@Binds
fun bindSessionProvider(sessionManagerImpl: SessionManagerImpl): SessionProvider
@Binds
fun bindSessionListener(sessionManagerImpl: SessionManagerImpl): SessionListener
}

View File

@ -0,0 +1,35 @@
/*
* 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 ch.protonmail.android.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.domain.entity.Product
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object CoreAppModule {
@Provides
@Singleton
fun provideProduct(): Product = Product.Mail
}

View File

@ -0,0 +1,45 @@
/*
* 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 ch.protonmail.android.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.auth.data.repository.AuthRepositoryImpl
import me.proton.core.auth.domain.repository.AuthRepository
import me.proton.core.crypto.android.srp.GOpenPGPSrpCrypto
import me.proton.core.crypto.common.srp.SrpCrypto
import me.proton.core.network.data.ApiProvider
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object CoreAuthModule {
@Provides
@Singleton
fun provideAuthRepository(apiProvider: ApiProvider): AuthRepository =
AuthRepositoryImpl(apiProvider)
@Provides
@Singleton
fun provideSrpCrypto(): SrpCrypto =
GOpenPGPSrpCrypto()
}

View File

@ -2,18 +2,18 @@ package ch.protonmail.android.di
import android.content.Context
import ch.protonmail.android.api.ProtonMailApiClient
import ch.protonmail.android.api.TokenSessionManager
import ch.protonmail.android.core.Constants
import ch.protonmail.android.utils.CoreLogger
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import me.proton.core.auth.domain.ClientSecret
import me.proton.core.network.data.ApiProvider
import me.proton.core.network.data.di.ApiFactory
import me.proton.core.network.data.di.NetworkManager
@ -27,9 +27,13 @@ import me.proton.core.util.kotlin.Logger
import javax.inject.Singleton
@Module
@InstallIn(ApplicationComponent::class)
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@ClientSecret
fun provideClientSecret(): String = ""
@Provides
@Singleton
fun provideCoreLogger(): Logger = CoreLogger()
@ -72,14 +76,9 @@ object NetworkModule {
}
@Module
@InstallIn(ApplicationComponent::class)
@InstallIn(SingletonComponent::class)
abstract class NetworkBindsModule {
@Binds
abstract fun provideApiClient(apiClient: ProtonMailApiClient): ApiClient
@Binds
abstract fun provideSessionProvider(sessionManager: TokenSessionManager): SessionProvider
@Binds
abstract fun provideSessionListener(sessionManager: TokenSessionManager): SessionListener
}

View File

@ -0,0 +1,159 @@
/*
* 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 ch.protonmail.android.di
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.key.data.repository.KeySaltRepositoryImpl
import me.proton.core.key.data.repository.PrivateKeyRepositoryImpl
import me.proton.core.key.data.repository.PublicAddressRepositoryImpl
import me.proton.core.key.domain.repository.KeySaltRepository
import me.proton.core.key.domain.repository.PrivateKeyRepository
import me.proton.core.key.domain.repository.PublicAddressRepository
import me.proton.core.network.data.ApiProvider
import me.proton.core.user.data.UserAddressKeySecretProvider
import me.proton.core.user.data.UserAddressManagerImpl
import me.proton.core.user.data.UserManagerImpl
import me.proton.core.user.data.repository.DomainRepositoryImpl
import me.proton.core.user.data.repository.UserAddressRepositoryImpl
import me.proton.core.user.data.repository.UserRepositoryImpl
import me.proton.core.user.data.repository.UserSettingRepositoryImpl
import me.proton.core.user.domain.UserAddressManager
import me.proton.core.user.domain.UserManager
import me.proton.core.user.domain.repository.DomainRepository
import me.proton.core.user.domain.repository.PassphraseRepository
import me.proton.core.user.domain.repository.UserAddressRepository
import me.proton.core.user.domain.repository.UserRepository
import me.proton.core.user.domain.repository.UserSettingRepository
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object UserManagerModule {
@Provides
@Singleton
fun provideUserRepositoryImpl(
db: AccountManagerDatabase,
provider: ApiProvider
): UserRepositoryImpl = UserRepositoryImpl(db, provider)
@Provides
@Singleton
fun provideUserAddressRepository(
db: AccountManagerDatabase,
provider: ApiProvider,
userRepository: UserRepository,
userAddressKeySecretProvider: UserAddressKeySecretProvider
): UserAddressRepository =
UserAddressRepositoryImpl(db, provider, userRepository, userAddressKeySecretProvider)
@Provides
@Singleton
fun provideUserAddressKeyPassphraseProvider(
userRepository: UserRepository,
passphraseRepository: PassphraseRepository,
cryptoContext: CryptoContext
): UserAddressKeySecretProvider =
UserAddressKeySecretProvider(userRepository, passphraseRepository, cryptoContext)
@Provides
@Singleton
fun provideUserSettingRepository(
provider: ApiProvider
): UserSettingRepository = UserSettingRepositoryImpl(provider)
@Provides
@Singleton
fun provideDomainRepository(
provider: ApiProvider
): DomainRepository = DomainRepositoryImpl(provider)
@Provides
@Singleton
fun provideKeySaltRepository(
db: AccountManagerDatabase,
provider: ApiProvider
): KeySaltRepository = KeySaltRepositoryImpl(db, provider)
@Provides
@Singleton
fun providePrivateKeyRepository(
provider: ApiProvider
): PrivateKeyRepository = PrivateKeyRepositoryImpl(provider)
@Provides
@Singleton
fun providePublicAddressKeyRepository(
db: AccountManagerDatabase,
provider: ApiProvider
): PublicAddressRepository = PublicAddressRepositoryImpl(db, provider)
@Provides
@Singleton
fun provideUserManager(
userRepository: UserRepository,
userAddressRepository: UserAddressRepository,
passphraseRepository: PassphraseRepository,
keySaltRepository: KeySaltRepository,
privateKeyRepository: PrivateKeyRepository,
userAddressKeySecretProvider: UserAddressKeySecretProvider,
cryptoContext: CryptoContext
): UserManager = UserManagerImpl(
userRepository,
userAddressRepository,
passphraseRepository,
keySaltRepository,
privateKeyRepository,
userAddressKeySecretProvider,
cryptoContext
)
@Provides
@Singleton
fun provideUserAddressManager(
userRepository: UserRepository,
userAddressRepository: UserAddressRepository,
privateKeyRepository: PrivateKeyRepository,
userAddressKeySecretProvider: UserAddressKeySecretProvider,
cryptoContext: CryptoContext
): UserAddressManager = UserAddressManagerImpl(
userRepository,
userAddressRepository,
privateKeyRepository,
userAddressKeySecretProvider,
cryptoContext
)
}
@Module
@InstallIn(SingletonComponent::class)
abstract class UserManagerBindsModule {
@Binds
abstract fun provideUserRepository(userRepositoryImpl: UserRepositoryImpl): UserRepository
@Binds
abstract fun providePassphraseRepository(userRepositoryImpl: UserRepositoryImpl): PassphraseRepository
}

View File

@ -0,0 +1,86 @@
/*
* 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 ch.protonmail.android.feature.account
import androidx.activity.ComponentActivity
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import me.proton.core.account.domain.entity.Account
import me.proton.core.account.domain.entity.AccountType
import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.accountmanager.domain.getPrimaryAccount
import me.proton.core.accountmanager.presentation.observe
import me.proton.core.accountmanager.presentation.onAccountCreateAddressFailed
import me.proton.core.accountmanager.presentation.onAccountCreateAddressNeeded
import me.proton.core.accountmanager.presentation.onAccountDisabled
import me.proton.core.accountmanager.presentation.onAccountTwoPassModeFailed
import me.proton.core.accountmanager.presentation.onAccountTwoPassModeNeeded
import me.proton.core.accountmanager.presentation.onSessionHumanVerificationNeeded
import me.proton.core.accountmanager.presentation.onSessionSecondFactorNeeded
import me.proton.core.auth.presentation.AuthOrchestrator
class AccountViewModel @ViewModelInject constructor(
private val accountManager: AccountManager,
private var authOrchestrator: AuthOrchestrator
) : ViewModel() {
private val _state = MutableStateFlow(State.Processing as State)
sealed class State {
object Processing : State()
object LoginNeeded : State()
data class AccountList(val accounts: List<Account>) : State()
}
val state = _state.asStateFlow()
fun register(context: ComponentActivity) {
authOrchestrator.register(context)
// Handle Account states.
with(authOrchestrator) {
accountManager.observe(context.lifecycleScope)
.onSessionSecondFactorNeeded { startSecondFactorWorkflow(it) }
.onAccountTwoPassModeNeeded { startTwoPassModeWorkflow(it) }
.onAccountCreateAddressNeeded { startChooseAddressWorkflow(it) }
.onSessionHumanVerificationNeeded { startHumanVerificationWorkflow(it) }
.onAccountTwoPassModeFailed { accountManager.disableAccount(it.userId) }
.onAccountCreateAddressFailed { accountManager.disableAccount(it.userId) }
.onAccountDisabled { accountManager.removeAccount(it.userId) }
}
// Raise LoginNeeded on empty account list.
accountManager.getAccounts().onEach { accounts ->
if (accounts.isEmpty()) _state.tryEmit(State.LoginNeeded)
_state.tryEmit(State.AccountList(accounts))
}.launchIn(viewModelScope)
}
fun getPrimaryUserId() = accountManager.getPrimaryUserId()
fun getPrimaryAccount() = accountManager.getPrimaryAccount()
fun startLoginWorkflow() = authOrchestrator.startLoginWorkflow(AccountType.Internal)
}

View File

@ -320,7 +320,7 @@ class DialogUtils {
okListener: (String) -> Unit,
cancelListener: () -> Unit): AlertDialog {
val builder = AlertDialog.Builder(context)
val dialogView = context.layoutInflater.inflate(R.layout.layout_2fa, null)
val dialogView = context.layoutInflater.inflate(R.layout.layout_2fa_old, null)
val twoFactorCode = dialogView.findViewById(R.id.two_factor_code) as EditText
val toggleInputText = dialogView.findViewById(R.id.toggle_input_text) as ToggleButton
toggleInputText.setOnClickListener { v ->

View File

@ -37,6 +37,7 @@ fun org.gradle.api.Project.android(
version: Version? = null,
versionCode: Int = ProtonMail.versionCode,
versionName: String = ProtonMail.versionName,
useDataBinding: Boolean = false,
config: ExtraConfig = {}
) = (this as ExtensionAware).extensions.configure<TestedExtension> {
@ -82,6 +83,11 @@ fun org.gradle.api.Project.android(
}
}
// Data/View Binding turned off by default to prevent unneeded generation.
// You must turn it on if you need it in your module: android(useDataBinding = true).
buildFeatures.viewBinding = useDataBinding
dataBinding.isEnabled = useDataBinding
lintOptions {
disable("InvalidPackage")
disable("MissingTranslation")