Refactor AccountManagerActivity.kt to use User Id instead of username
MAILAND-1100 #comment Affected: AccountManagerActivity.kt
This commit is contained in:
parent
c8a199ead0
commit
0af7f1ef01
|
@ -96,6 +96,8 @@ public abstract class BaseActivity extends AppCompatActivity implements INetwork
|
|||
@Inject
|
||||
protected NetworkConfigurator networkConfigurator;
|
||||
@Inject
|
||||
@Deprecated // TODO this should not be used by sub-classes, they should get it injected
|
||||
// directly, as are aiming to remove this base class
|
||||
protected UserManager mUserManager;
|
||||
@Inject
|
||||
protected JobManager mJobManager;
|
||||
|
|
|
@ -20,34 +20,37 @@ package ch.protonmail.android.activities.multiuser
|
|||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.core.view.postDelayed
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import ch.protonmail.android.R
|
||||
import ch.protonmail.android.activities.BaseActivity
|
||||
import ch.protonmail.android.activities.multiuser.viewModel.AccountManagerViewModel
|
||||
import ch.protonmail.android.adapters.AccountsAdapter
|
||||
import ch.protonmail.android.api.AccountManager
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.core.ProtonMailApplication
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.domain.entity.user.User
|
||||
import ch.protonmail.android.events.LogoutEvent
|
||||
import ch.protonmail.android.uiModel.DrawerUserModel
|
||||
import ch.protonmail.android.utils.extensions.app
|
||||
import ch.protonmail.android.utils.extensions.setBarColors
|
||||
import ch.protonmail.android.utils.extensions.showToast
|
||||
import ch.protonmail.android.utils.moveToMailbox
|
||||
import ch.protonmail.android.utils.moveToMailboxLogout
|
||||
import ch.protonmail.android.utils.ui.dialogs.DialogUtils
|
||||
import ch.protonmail.android.utils.ui.dialogs.DialogUtils.Companion.showTwoButtonInfoDialog
|
||||
import com.squareup.otto.Subscribe
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.android.synthetic.main.activity_account_manager.*
|
||||
import kotlinx.android.synthetic.main.toolbar_white.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class AccountManagerActivity : BaseActivity() {
|
||||
|
||||
|
||||
private var movingToMailbox = false
|
||||
|
||||
private val viewModel by viewModels<AccountManagerViewModel>()
|
||||
|
@ -57,45 +60,59 @@ class AccountManagerActivity : BaseActivity() {
|
|||
* to display the users (logged in and recently logged out) of the application.
|
||||
*/
|
||||
private val accountsAdapter by lazy { AccountsAdapter() }
|
||||
|
||||
override fun getLayoutId() = R.layout.activity_account_manager
|
||||
|
||||
@Inject
|
||||
lateinit var accountManager: AccountManager
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
toolbar.setNavigationIcon(R.drawable.ic_close)
|
||||
setSupportActionBar(toolbar)
|
||||
val actionBar = supportActionBar
|
||||
actionBar?.apply {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
window?.apply {
|
||||
setBarColors(resources.getColor(R.color.new_purple_dark))
|
||||
}
|
||||
actionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
window?.setBarColors(getColor(R.color.new_purple_dark))
|
||||
|
||||
val nextLoggedInAccount = mUserManager.nextLoggedInAccountOtherThanCurrent
|
||||
val currentActiveAccount = mUserManager.username
|
||||
accountsAdapter.apply {
|
||||
onLogoutAccount = { username ->
|
||||
DialogUtils.showInfoDialogWithTwoButtons(this@AccountManagerActivity,
|
||||
if (nextLoggedInAccount != null && username == currentActiveAccount) getString(R.string.logout) else String.format(getString(R.string.log_out), username),
|
||||
if (nextLoggedInAccount != null && username == currentActiveAccount) String.format(getString(R.string.logout_question_next_account), nextLoggedInAccount) else getString(R.string.logout_question),
|
||||
getString(R.string.cancel),
|
||||
getString(R.string.okay), {
|
||||
viewModel.logoutAccountResult.observe(this@AccountManagerActivity, Observer(::closeActivity))
|
||||
viewModel.logoutAccount(username)
|
||||
}, false)
|
||||
}
|
||||
onRemoveAccount = { username ->
|
||||
DialogUtils.showInfoDialogWithTwoButtons(this@AccountManagerActivity,
|
||||
getString(R.string.logout), String.format(getString(R.string.remove_account_question), username), getString(R.string.cancel),
|
||||
getString(R.string.okay), {
|
||||
viewModel.removedAccountResult.observe(this@AccountManagerActivity, Observer(::closeActivity))
|
||||
viewModel.removeAccount(username)
|
||||
}, false)
|
||||
}
|
||||
}
|
||||
|
||||
onLogoutAccount = { userId ->
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val nextLoggedInUserId = userManager.getNextLoggedInUser()
|
||||
val (title, message) = if (nextLoggedInUserId != null) {
|
||||
val next = userManager.getUser(nextLoggedInUserId)
|
||||
getString(R.string.logout) to getString(R.string.logout_question_next_account, next.name.s)
|
||||
} else {
|
||||
val current = checkNotNull(userManager.getCurrentUser())
|
||||
getString(R.string.log_out, current.name.s) to getString(R.string.logout_question)
|
||||
}
|
||||
|
||||
showTwoButtonInfoDialog(this@AccountManagerActivity, title, message) {
|
||||
viewModel.logoutAccountResult.observe(this@AccountManagerActivity, ::closeActivity)
|
||||
viewModel.logout(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onRemoveAccount = { userId ->
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val username = checkNotNull(userManager.getUser(userId)).name.s
|
||||
showTwoButtonInfoDialog(
|
||||
context = this@AccountManagerActivity,
|
||||
title = getString(R.string.logout),
|
||||
message = getString(R.string.remove_account_question, username)
|
||||
) {
|
||||
viewModel.removedAccountResult.observe(this@AccountManagerActivity, ::closeActivity)
|
||||
viewModel.remove(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
accountsRecyclerView.layoutManager = LinearLayoutManager(this)
|
||||
}
|
||||
|
||||
|
@ -103,9 +120,7 @@ class AccountManagerActivity : BaseActivity() {
|
|||
private fun closeAndMoveToLogin(result: Boolean) {
|
||||
if (result && !movingToMailbox) {
|
||||
movingToMailbox = true
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
moveToMailboxLogout()
|
||||
}, 500)
|
||||
window.decorView.postDelayed(500, ::moveToMailboxLogout)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +141,7 @@ class AccountManagerActivity : BaseActivity() {
|
|||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
ProtonMailApplication.getApplication().bus.register(this)
|
||||
app.bus.register(this)
|
||||
loadData()
|
||||
}
|
||||
|
||||
|
@ -137,7 +152,7 @@ class AccountManagerActivity : BaseActivity() {
|
|||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
ProtonMailApplication.getApplication().bus.unregister(this)
|
||||
app.bus.unregister(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
|
@ -154,9 +169,8 @@ class AccountManagerActivity : BaseActivity() {
|
|||
}
|
||||
R.id.action_remove_all -> {
|
||||
showToast(R.string.account_manager_remove_all_accounts)
|
||||
val accountManager = AccountManager.getInstance(this)
|
||||
viewModel.removedAllAccountsResult.observe(this@AccountManagerActivity, Observer(::closeAndMoveToLogin))
|
||||
viewModel.removeAllAccounts(accountManager.getLoggedInUsers())
|
||||
viewModel.removedAllAccountsResult.observe(this@AccountManagerActivity, ::closeAndMoveToLogin)
|
||||
viewModel.removeAllLoggedIn()
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
|
@ -166,31 +180,45 @@ class AccountManagerActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun loadData() {
|
||||
val currentPrimaryAccount = mUserManager.username
|
||||
if (!mUserManager.accessTokenExists() || mUserManager.getUser(currentPrimaryAccount).addresses.isEmpty()) {
|
||||
mUserManager.logoutOffline(currentPrimaryAccount)
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val hasAccessToken = userManager.accessTokenExists()
|
||||
val hasAddresses = userManager.getCurrentUser()?.addresses?.hasAddresses ?: false
|
||||
if (hasAccessToken.not() || hasAddresses.not()) {
|
||||
userManager.logoutOffline(checkNotNull(userManager.currentUserId))
|
||||
}
|
||||
|
||||
val currentUser = userManager.currentUserId
|
||||
lifecycleScope.launchWhenCreated {
|
||||
|
||||
val allUsers = accountManager.allLoggedIn().map { it to true } +
|
||||
accountManager.allLoggedOut().map { it to false }
|
||||
|
||||
val accounts = allUsers
|
||||
// Current user as first position, then logged in first
|
||||
.sortedByDescending { it.first == currentUser && it.second }
|
||||
.map { (id, loggedIn) ->
|
||||
val user = userManager.getUser(id)
|
||||
user.toUiModel(loggedIn, id == currentUser)
|
||||
}
|
||||
|
||||
accountsAdapter.items = accounts + DrawerUserModel.Footer
|
||||
accountsRecyclerView.adapter = accountsAdapter
|
||||
}
|
||||
}
|
||||
val accountManager = AccountManager.getInstance(this)
|
||||
val accounts = accountManager.getLoggedInUsers().map {
|
||||
val userAddresses = mUserManager.getUser(it).addresses
|
||||
val primaryAddress = userAddresses.find { address ->
|
||||
address.type == Constants.ADDRESS_TYPE_PRIMARY
|
||||
}
|
||||
val displayName = primaryAddress?.displayName ?: ""
|
||||
val primaryAddressEmail = if (primaryAddress == null) {
|
||||
it
|
||||
} else {
|
||||
primaryAddress.email
|
||||
}
|
||||
DrawerUserModel.BaseUser.AccountUser(it, primaryAddressEmail, true, it == currentPrimaryAccount, if (displayName.isNotEmpty()) displayName else it)
|
||||
}.sortedByDescending {
|
||||
it.primary
|
||||
}.plus(accountManager.getSavedUsers().map {
|
||||
DrawerUserModel.BaseUser.AccountUser(name = it, loggedIn = false, emailAddress = "", primary = false, displayName = it)
|
||||
}) as MutableList<DrawerUserModel>
|
||||
accounts.add(DrawerUserModel.AccFooter)
|
||||
accountsAdapter.items = accounts
|
||||
accountsRecyclerView.adapter = accountsAdapter
|
||||
}
|
||||
|
||||
private fun User.toUiModel(loggedIn: Boolean, currentPrimary: Boolean): DrawerUserModel.BaseUser.AccountUser {
|
||||
val primaryAddress = addresses.primary
|
||||
val username = name.s
|
||||
val displayName = primaryAddress?.displayName?.s
|
||||
return DrawerUserModel.BaseUser.AccountUser(
|
||||
id = id,
|
||||
name = displayName ?: username,
|
||||
emailAddress = primaryAddress?.email?.s ?: username,
|
||||
loggedIn = loggedIn,
|
||||
primary = currentPrimary,
|
||||
displayName = displayName ?: username
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
|
|
|
@ -27,7 +27,6 @@ import ch.protonmail.android.api.AccountManager
|
|||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.domain.entity.Id
|
||||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.util.kotlin.unsupported
|
||||
|
||||
class AccountManagerViewModel @ViewModelInject constructor(
|
||||
private val userManager: UserManager,
|
||||
|
@ -52,11 +51,6 @@ class AccountManagerViewModel @ViewModelInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use with user id", ReplaceWith("logout(userId)"), DeprecationLevel.ERROR)
|
||||
fun logoutAccount(username: String) {
|
||||
unsupported
|
||||
}
|
||||
|
||||
fun remove(userId: Id, notify: Boolean = true) {
|
||||
viewModelScope.launch {
|
||||
|
||||
|
@ -69,14 +63,9 @@ class AccountManagerViewModel @ViewModelInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use with user id", ReplaceWith("remove(userId, notify)"), DeprecationLevel.ERROR)
|
||||
fun removeAccount(username: String, notify: Boolean = true) {
|
||||
unsupported
|
||||
}
|
||||
|
||||
fun removeAll(usersIds: Collection<Id>) {
|
||||
fun removeAllLoggedIn() {
|
||||
viewModelScope.launch {
|
||||
val otherUsersIds = (usersIds - userManager.currentUserId).filterNotNull()
|
||||
val otherUsersIds = (accountManager.allLoggedIn() - userManager.currentUserId).filterNotNull()
|
||||
for (userId in otherUsersIds) {
|
||||
remove(userId, notify = false)
|
||||
}
|
||||
|
@ -86,9 +75,4 @@ class AccountManagerViewModel @ViewModelInject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use with user id", ReplaceWith("removeAll(usersIds)"), DeprecationLevel.ERROR)
|
||||
fun removeAllAccounts(listUsername: List<String>) {
|
||||
unsupported
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,30 +53,16 @@ internal sealed class DrawerUserModel {
|
|||
*/
|
||||
open val notificationsSnoozed: Boolean = false
|
||||
|
||||
data class AccountUser @JvmOverloads constructor(
|
||||
data class AccountUser(
|
||||
override val id: Id,
|
||||
override val name: String = EMPTY_STRING,
|
||||
override val emailAddress: String = EMPTY_STRING,
|
||||
override val loggedIn: Boolean = false,
|
||||
val primary: Boolean = false,
|
||||
val displayName: String = EMPTY_STRING
|
||||
) : BaseUser() {
|
||||
override val name: String,
|
||||
override val emailAddress: String,
|
||||
override val loggedIn: Boolean,
|
||||
val primary: Boolean,
|
||||
val displayName: String
|
||||
) : BaseUser()
|
||||
|
||||
@Deprecated(
|
||||
"Use constructor with id",
|
||||
ReplaceWith("AccountUser(id, name, emailAddress, loggedIn, primary, displayName"),
|
||||
DeprecationLevel.ERROR
|
||||
)
|
||||
constructor(
|
||||
name: String = EMPTY_STRING,
|
||||
emailAddress: String = EMPTY_STRING,
|
||||
loggedIn: Boolean = false,
|
||||
primary: Boolean = false,
|
||||
displayName: String = EMPTY_STRING
|
||||
): this(TODO(), name, emailAddress, loggedIn, primary, displayName)
|
||||
}
|
||||
|
||||
data class DrawerUser @JvmOverloads constructor(
|
||||
data class DrawerUser(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
override val emailAddress: String,
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@ import android.widget.CheckBox
|
|||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import android.widget.ToggleButton
|
||||
import androidx.annotation.StringRes
|
||||
import ch.protonmail.android.R
|
||||
import ch.protonmail.android.views.CustomFontButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
@ -107,6 +108,44 @@ class DialogUtils {
|
|||
return dialog
|
||||
}
|
||||
|
||||
inline fun showTwoButtonInfoDialog(
|
||||
context: Context,
|
||||
title: CharSequence,
|
||||
message: CharSequence,
|
||||
@StringRes positiveStringId: Int = R.string.okay,
|
||||
@StringRes negativeStringId: Int = R.string.cancel,
|
||||
cancelable: Boolean = false,
|
||||
crossinline onPositive: () -> Unit
|
||||
) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setNegativeButton(negativeStringId) { dialog, _ -> dialog.dismiss() }
|
||||
.setPositiveButton(positiveStringId) { dialog, _ ->
|
||||
run {
|
||||
onPositive()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
.setCancelable(cancelable)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Use 'showTwoButtonInfoDialog'",
|
||||
ReplaceWith(
|
||||
"showTwoButtonInfoDialog(\n" +
|
||||
" context,\n" +
|
||||
" title,\n" +
|
||||
" message,\n" +
|
||||
" positiveStringId,\n" +
|
||||
" negativeStringId,\n" +
|
||||
" cancelable,\n" +
|
||||
" okListener\n" +
|
||||
")"
|
||||
)
|
||||
)
|
||||
fun showInfoDialogWithTwoButtons(context: Context, title: String, message: String,
|
||||
negativeBtnText: String, positiveBtnText: String,
|
||||
okListener: ((Unit) -> Unit)?, cancelable: Boolean) {
|
||||
|
|
Loading…
Reference in New Issue