Removed SplashActivity.
MailboxActivity is now the main launcher Activity, and support null current userId.
This commit is contained in:
parent
57553dceca
commit
e3550fd8a8
|
@ -140,11 +140,15 @@
|
|||
<activity android:name=".util.HiltViewTestActivity"/>
|
||||
|
||||
<!-- Begin - Root Activities -->
|
||||
<activity
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity"
|
||||
android:targetActivity=".mailbox.presentation.MailboxActivity"/>
|
||||
<activity
|
||||
android:name=".mailbox.presentation.MailboxActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:launchMode="singleInstance"
|
||||
android:launchMode="standard"
|
||||
android:maxRecents="1"
|
||||
android:theme="@style/ProtonTheme.Splash.Mail.Light">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -154,12 +158,6 @@
|
|||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcuts" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".mailbox.presentation.MailboxActivity"
|
||||
android:exported="false"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:maxRecents="1"
|
||||
android:theme="@style/ProtonTheme.Splash.Mail.Light" />
|
||||
<!-- End - Root Activities -->
|
||||
<activity
|
||||
android:name=".settings.presentation.AttachmentStorageActivity"
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.details.presentation.MessageDetailsActivity
|
||||
import ch.protonmail.android.utils.AppUtil
|
||||
|
||||
class StartMessageDetails : ActivityResultContract<StartMessageDetails.Input, Unit?>() {
|
||||
|
||||
data class Input(
|
||||
val messageId: String,
|
||||
val locationType: Constants.MessageLocationType,
|
||||
val labelId: String?,
|
||||
val messageSubject: String
|
||||
)
|
||||
|
||||
override fun createIntent(context: Context, input: Input): Intent =
|
||||
AppUtil.decorInAppIntent(Intent(context, MessageDetailsActivity::class.java)).apply {
|
||||
putExtra(MessageDetailsActivity.EXTRA_MESSAGE_OR_CONVERSATION_ID, input.messageId)
|
||||
putExtra(MessageDetailsActivity.EXTRA_MESSAGE_LOCATION_ID, input.locationType.messageLocationTypeValue)
|
||||
putExtra(MessageDetailsActivity.EXTRA_MAILBOX_LABEL_ID, input.labelId)
|
||||
putExtra(MessageDetailsActivity.EXTRA_MESSAGE_SUBJECT, input.messageSubject)
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, result: Intent?): Unit? {
|
||||
if (resultCode != Activity.RESULT_OK) return null
|
||||
return Unit
|
||||
}
|
||||
}
|
|
@ -205,7 +205,7 @@ public abstract class BaseActivity extends AppCompatActivity implements INetwork
|
|||
|
||||
humanVerificationOrchestrator.register(this, false);
|
||||
accountStateManager.setHumanVerificationOrchestrator(humanVerificationOrchestrator);
|
||||
accountStateManager.observeHumanVerificationStateWithExternalLifecycle(getLifecycle());
|
||||
accountStateManager.observeHVStateWithExternalLifecycle(getLifecycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,7 +38,6 @@ import ch.protonmail.android.R
|
|||
import ch.protonmail.android.activities.settings.EXTRA_CURRENT_MAILBOX_LABEL_ID
|
||||
import ch.protonmail.android.activities.settings.EXTRA_CURRENT_MAILBOX_LOCATION
|
||||
import ch.protonmail.android.api.AccountManager
|
||||
import ch.protonmail.android.api.local.SnoozeSettings
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.segments.event.AlarmReceiver
|
||||
import ch.protonmail.android.contacts.ContactsActivity
|
||||
|
@ -54,7 +53,6 @@ import ch.protonmail.android.feature.account.AccountStateManager
|
|||
import ch.protonmail.android.labels.domain.model.LabelType
|
||||
import ch.protonmail.android.labels.presentation.EXTRA_MANAGE_FOLDERS
|
||||
import ch.protonmail.android.labels.presentation.LabelsManagerActivity
|
||||
import ch.protonmail.android.prefs.SecureSharedPreferences
|
||||
import ch.protonmail.android.servers.notification.EXTRA_USER_ID
|
||||
import ch.protonmail.android.settings.pin.EXTRA_FRAGMENT_TITLE
|
||||
import ch.protonmail.android.settings.pin.ValidatePinActivity
|
||||
|
@ -62,21 +60,18 @@ import ch.protonmail.android.utils.AppUtil
|
|||
import ch.protonmail.android.utils.UiUtil
|
||||
import ch.protonmail.android.utils.extensions.app
|
||||
import ch.protonmail.android.utils.extensions.setDrawBehindSystemBars
|
||||
import ch.protonmail.android.utils.resettableManager
|
||||
import ch.protonmail.android.utils.startSplashActivity
|
||||
import ch.protonmail.android.utils.ui.dialogs.DialogUtils.Companion.showTwoButtonInfoDialog
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import me.proton.core.accountmanager.presentation.view.AccountPrimaryView
|
||||
import me.proton.core.accountmanager.presentation.viewmodel.AccountSwitcherViewModel
|
||||
import me.proton.core.auth.presentation.AuthOrchestrator
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.presentation.utils.setDarkStatusBar
|
||||
import me.proton.core.presentation.utils.setLightStatusBar
|
||||
import java.util.Calendar
|
||||
import javax.inject.Inject
|
||||
|
||||
// region constants
|
||||
|
@ -109,14 +104,9 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
private lateinit var drawerToggle: ActionBarDrawerToggle
|
||||
// endregion
|
||||
|
||||
val lazyManager = resettableManager()
|
||||
|
||||
@Inject
|
||||
lateinit var accountManager: AccountManager
|
||||
|
||||
@Inject
|
||||
lateinit var authOrchestrator: AuthOrchestrator
|
||||
|
||||
@Inject
|
||||
lateinit var databaseProvider: DatabaseProvider
|
||||
|
||||
|
@ -129,7 +119,6 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
private val accountSwitcherViewModel by viewModels<AccountSwitcherViewModel>()
|
||||
|
||||
protected abstract val currentMailboxLocation: Constants.MessageLocationType
|
||||
|
||||
protected abstract val currentLabelId: String?
|
||||
|
||||
/**
|
||||
|
@ -152,6 +141,13 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun onPrimaryUserId(userId: UserId) {
|
||||
app.startJobManager()
|
||||
mJobManager.addJobInBackground(FetchUpdatesJob())
|
||||
val alarmReceiver = AlarmReceiver()
|
||||
alarmReceiver.setAlarm(this)
|
||||
}
|
||||
|
||||
protected abstract fun onInbox(type: Constants.DrawerOptionType)
|
||||
|
||||
protected abstract fun onOtherMailBox(type: Constants.DrawerOptionType)
|
||||
|
@ -174,30 +170,36 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
authOrchestrator.register(this)
|
||||
|
||||
with(accountStateManager) {
|
||||
setAuthOrchestrator(authOrchestrator)
|
||||
observeAccountStateWithExternalLifecycle(lifecycle)
|
||||
register(this@NavigationActivity)
|
||||
|
||||
// Start Splash on AccountNeeded.
|
||||
state
|
||||
.flowWithLifecycle(lifecycle, Lifecycle.State.CREATED)
|
||||
.onEach {
|
||||
when (it) {
|
||||
AccountStateManager.State.Processing,
|
||||
AccountStateManager.State.PrimaryExist ->
|
||||
Unit
|
||||
AccountStateManager.State.AccountNeeded -> {
|
||||
startSplashActivity()
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
AccountStateManager.State.PrimaryExist -> Unit
|
||||
AccountStateManager.State.AccountNeeded -> addAccount()
|
||||
}
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
onAddAccountClosed {
|
||||
if (userManager.currentUserId == null) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
onAccountSwitched()
|
||||
.flowWithLifecycle(lifecycle, Lifecycle.State.CREATED)
|
||||
.onEach { switch -> onAccountSwitched(switch) }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
getPrimaryUserId().filterNotNull()
|
||||
.flowWithLifecycle(lifecycle, Lifecycle.State.CREATED)
|
||||
.onEach { userId -> onPrimaryUserId(userId) }
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
accountPrimaryView.setViewModel(accountSwitcherViewModel)
|
||||
|
@ -269,18 +271,12 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
setUpDrawer()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
authOrchestrator.unregister()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
accountStateManager.setAuthOrchestrator(authOrchestrator)
|
||||
super.onResume()
|
||||
if (SHOULD_DRAW_DRAWER_BEHIND_SYSTEM_BARS)
|
||||
if (resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES) {
|
||||
|
@ -290,10 +286,6 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
checkUserId()
|
||||
app.startJobManager()
|
||||
val alarmReceiver = AlarmReceiver()
|
||||
alarmReceiver.setAlarm(this)
|
||||
|
||||
closeDrawerAndDialog()
|
||||
}
|
||||
|
||||
|
@ -311,11 +303,11 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
private fun checkUserId() {
|
||||
// Requested UserId match the current ?
|
||||
intent.extras?.getString(EXTRA_USER_ID)?.let { extraUserId ->
|
||||
intent.extras?.remove(EXTRA_USER_ID)
|
||||
val requestedUserId = UserId(extraUserId)
|
||||
if (requestedUserId != accountStateManager.getPrimaryUserId().value) {
|
||||
accountStateManager.switch(requestedUserId)
|
||||
}
|
||||
intent.extras?.remove(EXTRA_USER_ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,16 +364,6 @@ internal abstract class NavigationActivity : BaseActivity() {
|
|||
})
|
||||
}
|
||||
|
||||
private suspend fun areNotificationsSnoozed(userId: UserId): Boolean {
|
||||
val userPreferences = SecureSharedPreferences.getPrefsForUser(this, userId)
|
||||
with(SnoozeSettings.load(userPreferences)) {
|
||||
val shouldShowNotification = !shouldSuppressNotification(Calendar.getInstance())
|
||||
val isQuickSnoozeEnabled = snoozeQuick
|
||||
val isScheduledSnoozeEnabled = getScheduledSnooze(userPreferences)
|
||||
return isQuickSnoozeEnabled || (isScheduledSnoozeEnabled && !shouldShowNotification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpInitialDrawerItems(isPinEnabled: Boolean) {
|
||||
val hasPin = isPinEnabled && userManager.getMailboxPin() != null
|
||||
|
||||
|
|
|
@ -1,87 +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.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.flowWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import ch.protonmail.android.R
|
||||
import ch.protonmail.android.feature.account.AccountStateManager
|
||||
import ch.protonmail.android.utils.startMailboxActivity
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import me.proton.core.auth.presentation.AuthOrchestrator
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class SplashActivity : AppCompatActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var accountStateManager: AccountStateManager
|
||||
|
||||
@Inject
|
||||
lateinit var authOrchestrator: AuthOrchestrator
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
authOrchestrator.register(this)
|
||||
|
||||
with(accountStateManager) {
|
||||
setAuthOrchestrator(authOrchestrator)
|
||||
observeAccountStateWithExternalLifecycle(lifecycle, isSplashActivity = true)
|
||||
// Start Login or MailboxActivity.
|
||||
state
|
||||
.flowWithLifecycle(lifecycle, Lifecycle.State.CREATED)
|
||||
.onEach {
|
||||
when (it) {
|
||||
AccountStateManager.State.Processing ->
|
||||
Unit
|
||||
AccountStateManager.State.AccountNeeded ->
|
||||
addAccount()
|
||||
AccountStateManager.State.PrimaryExist -> {
|
||||
delay(resources.getInteger(R.integer.splash_transition_millis).toLong())
|
||||
startMailboxActivity()
|
||||
overridePendingTransition(0, 0)
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
||||
}.launchIn(lifecycleScope)
|
||||
|
||||
// Finish if AddAccount closed.
|
||||
onAddAccountClosed {
|
||||
finishAndRemoveTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
accountStateManager.setAuthOrchestrator(authOrchestrator)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
authOrchestrator.unregister()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
|
@ -47,6 +47,9 @@ class DatabaseProvider @Inject constructor(
|
|||
AttachmentMetadataDatabase.getInstance(context, userId).getDao()
|
||||
|
||||
// Contact
|
||||
fun provideContactDatabase(userId: UserId): ContactDatabase =
|
||||
ContactDatabase.getInstance(context, userId)
|
||||
|
||||
fun provideContactDao(userId: UserId): ContactDao =
|
||||
ContactDatabase.getInstance(context, userId).getDao()
|
||||
|
||||
|
|
|
@ -102,7 +102,6 @@ internal class EventHandler @AssistedInject constructor(
|
|||
|
||||
@AssistedInject.Factory
|
||||
interface AssistedFactory {
|
||||
|
||||
fun create(userId: UserId): EventHandler
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ class ComposeMessageRepository @Inject constructor(
|
|||
val jobManager: JobManager,
|
||||
val api: ProtonMailApiManager,
|
||||
val databaseProvider: DatabaseProvider,
|
||||
private var messageDao: MessageDao,
|
||||
private val messageDetailsRepository: MessageDetailsRepository,
|
||||
private val accountManager: AccountManager,
|
||||
private val userManager: UserManager,
|
||||
|
@ -68,9 +67,11 @@ class ComposeMessageRepository @Inject constructor(
|
|||
|
||||
val lazyManager = resettableManager()
|
||||
|
||||
private val contactDao by resettableLazy(lazyManager) {
|
||||
databaseProvider.provideContactDao(userManager.requireCurrentUserId())
|
||||
}
|
||||
private val messageDao: MessageDao
|
||||
get() = databaseProvider.provideMessageDao(userManager.requireCurrentUserId())
|
||||
|
||||
private val contactDao: ContactDao
|
||||
get() = databaseProvider.provideContactDao(userManager.requireCurrentUserId())
|
||||
|
||||
private val contactDaos: HashMap<UserId, ContactDao> by resettableLazy(lazyManager) {
|
||||
val userIds = accountManager.allLoggedInBlocking()
|
||||
|
@ -81,13 +82,6 @@ class ComposeMessageRepository @Inject constructor(
|
|||
listOfDaos
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads all statically required dependencies when currently active user changes.
|
||||
*/
|
||||
fun reloadDependenciesForUser(userId: UserId) {
|
||||
messageDao = databaseProvider.provideMessageDao(userId)
|
||||
}
|
||||
|
||||
fun getContactGroupsFromDB(userId: UserId, combinedContacts: Boolean): Flow<List<ContactLabelUiModel>> {
|
||||
return labelRepository.observeContactGroups(userId)
|
||||
.map { list ->
|
||||
|
|
|
@ -259,7 +259,6 @@ class ComposeMessageViewModel @Inject constructor(
|
|||
fun init(processor: HtmlProcessor) {
|
||||
htmlProcessor = processor
|
||||
composeMessageRepository.lazyManager.reset()
|
||||
composeMessageRepository.reloadDependenciesForUser(userId)
|
||||
getSenderEmailAddresses()
|
||||
// if the user is free user, then we do not fetch contact groups and announce the setup is complete
|
||||
if (!user.isPaidUser) {
|
||||
|
|
|
@ -89,7 +89,6 @@ import java.util.concurrent.atomic.AtomicReference
|
|||
import javax.inject.Inject
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
private const val TITLE_ANIMATION_THRESHOLD = 0.9
|
||||
private const val TITLE_ANIMATION_DURATION = 200L
|
||||
private const val ONE_HUNDRED_PERCENT = 1.0
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
package ch.protonmail.android.di
|
||||
|
||||
import android.content.Context
|
||||
import ch.protonmail.android.feature.account.SetupAccountUserCheck
|
||||
import ch.protonmail.android.prefs.SecureSharedPreferences
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -29,7 +31,6 @@ import me.proton.core.auth.data.repository.AuthRepositoryImpl
|
|||
import me.proton.core.auth.domain.repository.AuthRepository
|
||||
import me.proton.core.auth.domain.usecase.SetupAccountCheck
|
||||
import me.proton.core.auth.presentation.AuthOrchestrator
|
||||
import me.proton.core.auth.presentation.DefaultUserCheck
|
||||
import me.proton.core.crypto.android.srp.GOpenPGPSrpCrypto
|
||||
import me.proton.core.crypto.common.srp.SrpCrypto
|
||||
import me.proton.core.network.data.ApiProvider
|
||||
|
@ -59,6 +60,7 @@ object CoreAuthModule {
|
|||
fun provideUserCheck(
|
||||
@ApplicationContext context: Context,
|
||||
accountManager: AccountManager,
|
||||
userManager: UserManager
|
||||
): SetupAccountCheck.UserCheck = DefaultUserCheck(context, accountManager, userManager)
|
||||
userManager: UserManager,
|
||||
factory: SecureSharedPreferences.Factory
|
||||
): SetupAccountCheck.UserCheck = SetupAccountUserCheck(context, accountManager, userManager, factory)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package ch.protonmail.android.feature.account
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.core.content.edit
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
|
@ -87,6 +88,7 @@ internal class AccountStateManager @Inject constructor(
|
|||
private val userManager: UserManager,
|
||||
private val eventManager: EventManager,
|
||||
private val jobManager: JobManager,
|
||||
private val authOrchestrator: AuthOrchestrator,
|
||||
private val humanVerificationManager: HumanVerificationManager,
|
||||
private val oldUserManager: ch.protonmail.android.core.UserManager,
|
||||
private val launchInitialDataFetch: LaunchInitialDataFetch,
|
||||
|
@ -101,7 +103,6 @@ internal class AccountStateManager @Inject constructor(
|
|||
private val scope = lifecycleOwner.lifecycleScope
|
||||
private val lifecycle = lifecycleOwner.lifecycle
|
||||
|
||||
private lateinit var currentAuthOrchestrator: AuthOrchestrator
|
||||
private lateinit var currentHumanVerificationOrchestrator: HumanVerificationOrchestrator
|
||||
|
||||
private val mutableStateFlow = MutableStateFlow(State.Processing)
|
||||
|
@ -129,6 +130,8 @@ internal class AccountStateManager @Inject constructor(
|
|||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
private suspend fun getAccountOrNull(userId: UserId) = getAccount(userId).firstOrNull()
|
||||
|
||||
private fun observeAccountManager(lifecycle: Lifecycle): AccountManagerObserver =
|
||||
accountManager.observe(lifecycle, Lifecycle.State.CREATED)
|
||||
|
||||
|
@ -154,44 +157,36 @@ internal class AccountStateManager @Inject constructor(
|
|||
*
|
||||
* For example, SecondFactor Workflow, TwoPassMode Workflow or ChooseAddress Workflow.
|
||||
*/
|
||||
fun observeAccountStateWithExternalLifecycle(
|
||||
lifecycle: Lifecycle,
|
||||
isSplashActivity: Boolean = false
|
||||
) {
|
||||
// Don't start workflow if MailboxActivity will do it later.
|
||||
fun shouldStart() = !isSplashActivity || state.value != State.PrimaryExist
|
||||
private fun observeAccountStateWithExternalLifecycle(lifecycle: Lifecycle) {
|
||||
observeAccountManager(lifecycle)
|
||||
.onSessionSecondFactorNeeded { if (shouldStart()) currentAuthOrchestrator.startSecondFactorWorkflow(it) }
|
||||
.onAccountTwoPassModeNeeded { if (shouldStart()) currentAuthOrchestrator.startTwoPassModeWorkflow(it) }
|
||||
.onAccountCreateAddressNeeded { if (shouldStart()) currentAuthOrchestrator.startChooseAddressWorkflow(it) }
|
||||
.onSessionSecondFactorNeeded { authOrchestrator.startSecondFactorWorkflow(it) }
|
||||
.onAccountTwoPassModeNeeded { authOrchestrator.startTwoPassModeWorkflow(it) }
|
||||
.onAccountCreateAddressNeeded { authOrchestrator.startChooseAddressWorkflow(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe all human verification states that can be solved with [HumanVerificationOrchestrator].
|
||||
*/
|
||||
fun observeHumanVerificationStateWithExternalLifecycle(lifecycle: Lifecycle) {
|
||||
fun observeHVStateWithExternalLifecycle(lifecycle: Lifecycle) {
|
||||
observeHumanVerificationManager(lifecycle)
|
||||
.onHumanVerificationNeeded { currentHumanVerificationOrchestrator.startHumanVerificationWorkflow(it) }
|
||||
}
|
||||
|
||||
fun setAuthOrchestrator(authOrchestrator: AuthOrchestrator) {
|
||||
currentAuthOrchestrator = authOrchestrator
|
||||
}
|
||||
|
||||
fun setHumanVerificationOrchestrator(
|
||||
humanVerificationOrchestrator: HumanVerificationOrchestrator
|
||||
) {
|
||||
fun setHumanVerificationOrchestrator(humanVerificationOrchestrator: HumanVerificationOrchestrator) {
|
||||
currentHumanVerificationOrchestrator = humanVerificationOrchestrator
|
||||
}
|
||||
|
||||
fun register(context: ComponentActivity) {
|
||||
authOrchestrator.register(context)
|
||||
observeAccountStateWithExternalLifecycle(context.lifecycle)
|
||||
}
|
||||
|
||||
fun onAddAccountClosed(block: () -> Unit) {
|
||||
currentAuthOrchestrator.onAddAccountResult { result -> if (result == null) block() }
|
||||
authOrchestrator.onAddAccountResult { result -> if (result == null) block() }
|
||||
}
|
||||
|
||||
fun getAccount(userId: UserId) = accountManager.getAccount(userId)
|
||||
|
||||
suspend fun getAccountOrNull(userId: UserId) = getAccount(userId).firstOrNull()
|
||||
|
||||
fun signOut(userId: UserId) = scope.launch {
|
||||
accountManager.disableAccount(userId)
|
||||
}
|
||||
|
@ -202,14 +197,14 @@ internal class AccountStateManager @Inject constructor(
|
|||
|
||||
fun signIn(userId: UserId? = null) = scope.launch {
|
||||
val account = userId?.let { getAccountOrNull(it) }
|
||||
currentAuthOrchestrator.startLoginWorkflow(
|
||||
authOrchestrator.startLoginWorkflow(
|
||||
requiredAccountType = requiredAccountType,
|
||||
username = account?.username
|
||||
)
|
||||
}
|
||||
|
||||
fun addAccount() = scope.launch {
|
||||
currentAuthOrchestrator.startAddAccountWorkflow(
|
||||
authOrchestrator.startAddAccountWorkflow(
|
||||
requiredAccountType = requiredAccountType,
|
||||
product = product
|
||||
)
|
||||
|
@ -218,7 +213,7 @@ internal class AccountStateManager @Inject constructor(
|
|||
fun switch(userId: UserId) = scope.launch {
|
||||
val account = getAccountOrNull(userId) ?: return@launch
|
||||
when {
|
||||
account.isDisabled() -> currentAuthOrchestrator.startLoginWorkflow(
|
||||
account.isDisabled() -> authOrchestrator.startLoginWorkflow(
|
||||
requiredAccountType = AccountType.Internal,
|
||||
username = account.username
|
||||
)
|
||||
|
@ -259,11 +254,7 @@ internal class AccountStateManager @Inject constructor(
|
|||
val prefs = oldUserManager.preferencesFor(userId)
|
||||
val initialized = prefs.getBoolean(Constants.Prefs.PREF_USER_INITIALIZED, false)
|
||||
if (!initialized) {
|
||||
oldUserManager.preferencesFor(userId).edit {
|
||||
putBoolean(Constants.Prefs.PREF_USER_INITIALIZED, true)
|
||||
// See DatabaseFactory.usernameForUserId.
|
||||
putString(Constants.Prefs.PREF_USER_NAME, account.username)
|
||||
}
|
||||
prefs.edit { putBoolean(Constants.Prefs.PREF_USER_INITIALIZED, true) }
|
||||
// Workaround: Wait the primary key passphrase before proceeding.
|
||||
userManager.waitPrimaryKeyPassphraseAvailable(account.userId)
|
||||
// Workaround: Make sure this uninitialized User is fresh.
|
||||
|
@ -290,9 +281,7 @@ internal class AccountStateManager @Inject constructor(
|
|||
// Clear Data/State.
|
||||
clearUserData.invoke(userId)
|
||||
eventManager.clearState(userId)
|
||||
oldUserManager.preferencesFor(UserId(account.userId.id)).clearAll(
|
||||
/*excludedKeys*/ PREF_PIN, Constants.Prefs.PREF_USER_NAME
|
||||
)
|
||||
prefs.clearAll(/*excludedKeys*/ PREF_PIN, Constants.Prefs.PREF_USER_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.feature.account
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.prefs.SecureSharedPreferences
|
||||
import me.proton.core.accountmanager.domain.AccountManager
|
||||
import me.proton.core.auth.domain.usecase.SetupAccountCheck
|
||||
import me.proton.core.auth.presentation.DefaultUserCheck
|
||||
import me.proton.core.user.domain.UserManager
|
||||
import me.proton.core.user.domain.entity.User
|
||||
|
||||
class SetupAccountUserCheck(
|
||||
context: Context,
|
||||
accountManager: AccountManager,
|
||||
userManager: UserManager,
|
||||
private val secureSharedPreferencesFactory: SecureSharedPreferences.Factory
|
||||
) : DefaultUserCheck(context, accountManager, userManager) {
|
||||
|
||||
override suspend fun invoke(user: User): SetupAccountCheck.UserCheckResult {
|
||||
// Workaround: Make sure we have the preference user name by userId.
|
||||
// See DatabaseFactory.usernameForUserId.
|
||||
secureSharedPreferencesFactory.userPreferences(user.userId).edit(commit = true) {
|
||||
putString(Constants.Prefs.PREF_USER_NAME, user.name)
|
||||
}
|
||||
return super.invoke(user)
|
||||
}
|
||||
}
|
|
@ -32,13 +32,11 @@ import androidx.work.WorkerParameters
|
|||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.ProtonMailApi
|
||||
import ch.protonmail.android.api.models.IDList
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.local.CounterRepository
|
||||
import ch.protonmail.android.worker.KEY_WORKER_ERROR_DESCRIPTION
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import me.proton.core.accountmanager.domain.AccountManager
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.CancellationException
|
||||
import javax.inject.Inject
|
||||
|
@ -47,17 +45,17 @@ import javax.inject.Inject
|
|||
internal class RemoveMessageLabelWorker @AssistedInject constructor(
|
||||
@Assisted context: Context,
|
||||
@Assisted params: WorkerParameters,
|
||||
private val accountManager: AccountManager,
|
||||
private val userManager: UserManager,
|
||||
private val counterRepository: CounterRepository,
|
||||
private val protonMailApi: ProtonMailApi
|
||||
) : CoroutineWorker(context, params) {
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val userId = requireNotNull(userManager.currentUserId)
|
||||
val messageIds = requireNotNull(inputData.getStringArray(KEY_INPUT_DATA_MESSAGES_IDS)) {
|
||||
"Cannot continue without message ids!"
|
||||
}
|
||||
val labelId = inputData.getString(KEY_INPUT_DATA_LABEL_ID)
|
||||
val userId = accountManager.getPrimaryUserId().filterNotNull().first()
|
||||
Timber.v("Remove label $labelId for messages: $messageIds")
|
||||
|
||||
if (messageIds.isEmpty() || labelId == null) {
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
package ch.protonmail.android.mailbox.data
|
||||
|
||||
import ch.protonmail.android.api.ProtonMailApiManager
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.messages.receive.MessageFactory
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.core.NetworkConnectivityManager
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.ProtonStore
|
||||
import ch.protonmail.android.data.local.MessageDao
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
|
@ -88,10 +90,9 @@ private const val MAX_LOCATION_ID_LENGTH = 2
|
|||
|
||||
@Suppress("LongParameterList") // Every new parameter adds a new issue and breaks the build
|
||||
internal class ConversationsRepositoryImpl @Inject constructor(
|
||||
private val conversationDao: ConversationDao,
|
||||
private val messageDao: MessageDao,
|
||||
private val userManager: UserManager,
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val labelsRepository: LabelRepository,
|
||||
private val unreadCounterDao: UnreadCounterDao,
|
||||
private val api: ProtonMailApiManager,
|
||||
responseToConversationsMapper: ConversationsResponseToConversationsMapper,
|
||||
private val databaseToConversationMapper: ConversationDatabaseModelToConversationMapper,
|
||||
|
@ -109,6 +110,15 @@ internal class ConversationsRepositoryImpl @Inject constructor(
|
|||
connectivityManager: NetworkConnectivityManager
|
||||
) : ConversationsRepository {
|
||||
|
||||
private val conversationDao: ConversationDao
|
||||
get() = databaseProvider.provideConversationDao(userManager.requireCurrentUserId())
|
||||
|
||||
private val messageDao: MessageDao
|
||||
get() = databaseProvider.provideMessageDao(userManager.requireCurrentUserId())
|
||||
|
||||
private val unreadCounterDao: UnreadCounterDao
|
||||
get() = databaseProvider.provideUnreadCounterDao(userManager.requireCurrentUserId())
|
||||
|
||||
private val refreshUnreadCountersTrigger = MutableSharedFlow<Unit>(replay = 1)
|
||||
|
||||
private val allConversationsStore by lazy {
|
||||
|
|
|
@ -63,6 +63,7 @@ import ch.protonmail.android.activities.EngagementActivity
|
|||
import ch.protonmail.android.activities.NavigationActivity
|
||||
import ch.protonmail.android.activities.SearchActivity
|
||||
import ch.protonmail.android.activities.SettingsItem
|
||||
import ch.protonmail.android.activities.StartMessageDetails
|
||||
import ch.protonmail.android.activities.composeMessage.ComposeMessageActivity
|
||||
import ch.protonmail.android.activities.messageDetails.repository.MessageDetailsRepository
|
||||
import ch.protonmail.android.activities.settings.SettingsEnum
|
||||
|
@ -89,7 +90,6 @@ import ch.protonmail.android.data.local.CounterDatabase
|
|||
import ch.protonmail.android.data.local.PendingActionDao
|
||||
import ch.protonmail.android.data.local.PendingActionDatabase
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.details.presentation.MessageDetailsActivity
|
||||
import ch.protonmail.android.di.DefaultSharedPreferences
|
||||
import ch.protonmail.android.events.FetchLabelsEvent
|
||||
import ch.protonmail.android.events.MailboxLoadedEvent
|
||||
|
@ -99,7 +99,6 @@ import ch.protonmail.android.events.Status
|
|||
import ch.protonmail.android.fcm.MultiUserFcmTokenManager
|
||||
import ch.protonmail.android.fcm.RegisterDeviceWorker
|
||||
import ch.protonmail.android.fcm.model.FirebaseToken
|
||||
import ch.protonmail.android.feature.account.AccountStateManager
|
||||
import ch.protonmail.android.jobs.EmptyFolderJob
|
||||
import ch.protonmail.android.labels.domain.model.Label
|
||||
import ch.protonmail.android.labels.domain.model.LabelType
|
||||
|
@ -133,6 +132,7 @@ import kotlinx.android.synthetic.main.activity_mailbox.screenShotPreventerView
|
|||
import kotlinx.android.synthetic.main.activity_message_details.*
|
||||
import kotlinx.android.synthetic.main.navigation_drawer.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -172,7 +172,6 @@ internal class MailboxActivity :
|
|||
|
||||
@Inject
|
||||
lateinit var messageDetailsRepositoryFactory: MessageDetailsRepository.AssistedFactory
|
||||
lateinit var messageDetailsRepository: MessageDetailsRepository
|
||||
|
||||
@Inject
|
||||
lateinit var networkSnackBarUtil: NetworkSnackBarUtil
|
||||
|
@ -213,6 +212,8 @@ internal class MailboxActivity :
|
|||
private var storageLimitApproachingAlertDialog: AlertDialog? = null
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
private val startMessageDetailsLauncher = registerForActivityResult(StartMessageDetails()) {}
|
||||
|
||||
override val currentLabelId get() = mailboxLabelId
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.activity_mailbox
|
||||
|
@ -221,12 +222,6 @@ internal class MailboxActivity :
|
|||
setTheme(R.style.ProtonTheme_Mail)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val userId = userManager.currentUserId ?: return
|
||||
|
||||
messageDetailsRepository = messageDetailsRepositoryFactory.create(userId)
|
||||
counterDao = CounterDatabase.getInstance(this, userId).getDao()
|
||||
pendingActionDao = PendingActionDatabase.getInstance(this, userId).getDao()
|
||||
|
||||
// TODO if we decide to use special flag for switching (and not login), change this
|
||||
if (intent.getBooleanExtra(EXTRA_FIRST_LOGIN, false)) {
|
||||
multiUserFcmTokenManager.setTokenUnsentForAllSavedUsersBlocking() // force FCM to re-register
|
||||
|
@ -245,7 +240,11 @@ internal class MailboxActivity :
|
|||
if (extras != null && extras.containsKey(EXTRA_MAILBOX_LOCATION)) {
|
||||
switchToMailboxLocation(extras.getInt(EXTRA_MAILBOX_LOCATION))
|
||||
}
|
||||
|
||||
startObserving()
|
||||
startObservingPendingActions()
|
||||
startObservingUsedSpace()
|
||||
|
||||
mailboxViewModel.toastMessageMaxLabelsReached.observe(this) { event: Event<MaxLabelsReached?> ->
|
||||
val maxLabelsReached = event.getContentIfNotHandled()
|
||||
if (maxLabelsReached != null) {
|
||||
|
@ -260,8 +259,6 @@ internal class MailboxActivity :
|
|||
|
||||
mailboxViewModel.hasConnectivity.observe(this, ::onConnectivityEvent)
|
||||
|
||||
startObservingUsedSpace()
|
||||
|
||||
var actionModeAux: ActionMode? = null
|
||||
mailboxAdapter = MailboxRecyclerViewAdapter(this) { selectionModeEvent ->
|
||||
when (selectionModeEvent) {
|
||||
|
@ -312,10 +309,11 @@ internal class MailboxActivity :
|
|||
mailboxAdapter.setItemClick { mailboxUiItem: MailboxUiItem ->
|
||||
OnMessageClickTask(
|
||||
WeakReference(this@MailboxActivity),
|
||||
messageDetailsRepository,
|
||||
messageDetailsRepositoryFactory,
|
||||
mailboxUiItem.itemId,
|
||||
mailboxUiItem.subject,
|
||||
currentMailboxLocation.messageLocationTypeValue
|
||||
currentMailboxLocation,
|
||||
userManager.requireCurrentUserId()
|
||||
).execute()
|
||||
}
|
||||
|
||||
|
@ -403,9 +401,22 @@ internal class MailboxActivity :
|
|||
}
|
||||
}
|
||||
|
||||
private fun startObservingPendingActions() {
|
||||
val owner = this
|
||||
mailboxViewModel.run {
|
||||
pendingSendsLiveData.removeObservers(owner)
|
||||
pendingUploadsLiveData.removeObservers(owner)
|
||||
pendingSendsLiveData.observe(owner) { mailboxAdapter.setPendingForSendingList(it) }
|
||||
pendingUploadsLiveData.observe(owner) { mailboxAdapter.setPendingUploadsList(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun startObservingUsedSpace() {
|
||||
val preferences = SecureSharedPreferences.getPrefsForUser(this, userManager.requireCurrentUserId())
|
||||
preferences.observe<Long>(PREF_USED_SPACE)
|
||||
mailboxViewModel.primaryUserId
|
||||
.flatMapLatest { primaryUserId ->
|
||||
val preferences = SecureSharedPreferences.getPrefsForUser(this, primaryUserId)
|
||||
preferences.observe<Long>(PREF_USED_SPACE)
|
||||
}
|
||||
.onEach { mailboxViewModel.usedSpaceActionEvent(FLOW_USED_SPACE_CHANGED) }
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
@ -513,39 +524,17 @@ internal class MailboxActivity :
|
|||
|
||||
private var firstLogin: Boolean? = null
|
||||
|
||||
private fun startObservingPendingActions() {
|
||||
val owner = this
|
||||
mailboxViewModel.run {
|
||||
pendingSendsLiveData.removeObservers(owner)
|
||||
pendingUploadsLiveData.removeObservers(owner)
|
||||
reloadDependenciesForUser()
|
||||
pendingSendsLiveData.observe(owner) { mailboxAdapter.setPendingForSendingList(it) }
|
||||
pendingUploadsLiveData.observe(owner) { mailboxAdapter.setPendingUploadsList(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAccountSwitched(switch: AccountStateManager.AccountSwitch) {
|
||||
super.onAccountSwitched(switch)
|
||||
|
||||
val currentUserId = userManager.currentUserId ?: return
|
||||
Timber.v("onAccountSwitched, new userId: $currentUserId")
|
||||
override fun onPrimaryUserId(userId: UserId) {
|
||||
super.onPrimaryUserId(userId)
|
||||
|
||||
mJobManager.start()
|
||||
counterDao = CounterDatabase.getInstance(this, currentUserId).getDao()
|
||||
pendingActionDao = PendingActionDatabase.getInstance(this, currentUserId).getDao()
|
||||
counterDao = CounterDatabase.getInstance(this, userId).getDao()
|
||||
pendingActionDao = PendingActionDatabase.getInstance(this, userId).getDao()
|
||||
|
||||
startObservingPendingActions()
|
||||
AppUtil.clearNotifications(this, currentUserId)
|
||||
lazyManager.reset()
|
||||
setUpDrawer()
|
||||
checkRegistration()
|
||||
switchToMailboxLocation(DrawerOptionType.INBOX.drawerOptionTypeValue)
|
||||
|
||||
// Account has been switched, so used space changed as well
|
||||
mailboxViewModel.usedSpaceActionEvent(FLOW_USED_SPACE_CHANGED)
|
||||
// Observe used space for current account
|
||||
startObservingUsedSpace()
|
||||
|
||||
// manually update the flags for preventing screenshots
|
||||
if (isPreventingScreenshots || userManager.currentLegacyUser?.isPreventTakingScreenshots == true) {
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
|
@ -759,7 +748,7 @@ internal class MailboxActivity :
|
|||
mailboxViewModel.checkConnectivity()
|
||||
val mailboxLocation = mailboxViewModel.mailboxLocation.value
|
||||
if (mailboxLocation == MessageLocationType.INBOX) {
|
||||
AppUtil.clearNotifications(this, userManager.requireCurrentUserId())
|
||||
userManager.currentUserId?.let { AppUtil.clearNotifications(this, it) }
|
||||
}
|
||||
|
||||
if (shouldShowSwipeGesturesChangedDialog()) {
|
||||
|
@ -1202,7 +1191,7 @@ internal class MailboxActivity :
|
|||
) {
|
||||
SetUpNewMessageLocationTask(
|
||||
WeakReference(this),
|
||||
messageDetailsRepository,
|
||||
messageDetailsRepositoryFactory,
|
||||
labelId,
|
||||
isFolder,
|
||||
newLocation,
|
||||
|
@ -1273,12 +1262,15 @@ internal class MailboxActivity :
|
|||
|
||||
private class OnMessageClickTask internal constructor(
|
||||
private val mailboxActivity: WeakReference<MailboxActivity>,
|
||||
private val messageDetailsRepository: MessageDetailsRepository,
|
||||
private val messageDetailsRepositoryFactory: MessageDetailsRepository.AssistedFactory,
|
||||
private val messageId: String,
|
||||
private val messageSubject: String,
|
||||
private val currentMailboxLocationType: Int
|
||||
private val currentMailboxLocationType: MessageLocationType,
|
||||
private val userId: UserId
|
||||
) : AsyncTask<Unit, Unit, Message>() {
|
||||
|
||||
private val messageDetailsRepository = messageDetailsRepositoryFactory.create(userId)
|
||||
|
||||
override fun doInBackground(vararg params: Unit): Message? =
|
||||
messageDetailsRepository.findMessageByIdBlocking(messageId)
|
||||
|
||||
|
@ -1294,19 +1286,14 @@ internal class MailboxActivity :
|
|||
savedMessage.addressID
|
||||
).execute()
|
||||
} else {
|
||||
val intent = AppUtil.decorInAppIntent(
|
||||
Intent(
|
||||
mailboxActivity, MessageDetailsActivity::class.java
|
||||
mailboxActivity?.startMessageDetailsLauncher?.launch(
|
||||
StartMessageDetails.Input(
|
||||
messageId,
|
||||
currentMailboxLocationType,
|
||||
mailboxActivity.mailboxLabelId,
|
||||
messageSubject
|
||||
)
|
||||
)
|
||||
intent.putExtra(MessageDetailsActivity.EXTRA_MESSAGE_OR_CONVERSATION_ID, messageId)
|
||||
intent.putExtra(
|
||||
MessageDetailsActivity.EXTRA_MESSAGE_LOCATION_ID,
|
||||
currentMailboxLocationType
|
||||
)
|
||||
intent.putExtra(MessageDetailsActivity.EXTRA_MAILBOX_LABEL_ID, mailboxActivity?.mailboxLabelId)
|
||||
intent.putExtra(MessageDetailsActivity.EXTRA_MESSAGE_SUBJECT, messageSubject)
|
||||
mailboxActivity?.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1343,7 +1330,7 @@ internal class MailboxActivity :
|
|||
|
||||
private class SetUpNewMessageLocationTask internal constructor(
|
||||
private val mailboxActivity: WeakReference<MailboxActivity>,
|
||||
private val messageDetailsRepository: MessageDetailsRepository,
|
||||
private val messageDetailsRepositoryFactory: MessageDetailsRepository.AssistedFactory,
|
||||
private val labelId: String,
|
||||
private val isFolder: Boolean,
|
||||
private val newLocation: Int,
|
||||
|
@ -1353,6 +1340,7 @@ internal class MailboxActivity :
|
|||
|
||||
override fun doInBackground(vararg params: Unit): Label? {
|
||||
return runBlocking {
|
||||
val messageDetailsRepository = messageDetailsRepositoryFactory.create(userId)
|
||||
val labels = messageDetailsRepository.findLabelsWithIds(listOf(labelId))
|
||||
if (labels.isEmpty()) null else labels[0]
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ import kotlinx.coroutines.flow.combineTransform
|
|||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -150,7 +151,7 @@ internal class MailboxViewModel @Inject constructor(
|
|||
private val mutableMailboxState = MutableStateFlow<MailboxState>(MailboxState.Loading)
|
||||
private val mutableMailboxLocation = MutableStateFlow(INBOX)
|
||||
private val mutableMailboxLabelId = MutableStateFlow(EMPTY_STRING)
|
||||
private val mutableUserId = userManager.primaryUserId.filterNotNull()
|
||||
private val mutableUserId = userManager.primaryUserId
|
||||
private val mutableRefreshFlow = MutableSharedFlow<Boolean>(
|
||||
replay = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
|
@ -159,13 +160,15 @@ internal class MailboxViewModel @Inject constructor(
|
|||
private val messageDetailsRepository: MessageDetailsRepository
|
||||
get() = messageDetailsRepositoryFactory.create(userManager.requireCurrentUserId())
|
||||
|
||||
var pendingSendsLiveData = mutableUserId.asLiveData().switchMap {
|
||||
var pendingSendsLiveData = mutableUserId.filterNotNull().asLiveData().switchMap {
|
||||
messageDetailsRepository.findAllPendingSendsAsync()
|
||||
}
|
||||
var pendingUploadsLiveData = mutableUserId.asLiveData().switchMap {
|
||||
var pendingUploadsLiveData = mutableUserId.filterNotNull().asLiveData().switchMap {
|
||||
messageDetailsRepository.findAllPendingUploadsAsync()
|
||||
}
|
||||
|
||||
val primaryUserId: Flow<UserId> = mutableUserId.filterNotNull()
|
||||
|
||||
val manageLimitReachedWarning: LiveData<Event<Boolean>>
|
||||
get() = _manageLimitReachedWarning
|
||||
val manageLimitApproachingWarning: LiveData<Event<Boolean>>
|
||||
|
@ -184,10 +187,12 @@ internal class MailboxViewModel @Inject constructor(
|
|||
val mailboxLocation = mutableMailboxLocation.asStateFlow()
|
||||
|
||||
val drawerLabels: Flow<DrawerFoldersAndLabelsSectionUiModel> = combine(
|
||||
mutableUserId,
|
||||
mutableUserId.filterNotNull(),
|
||||
mutableRefreshFlow.onStart { emit(false) }
|
||||
) { userId, isRefresh -> userId to isRefresh }
|
||||
.flatMapLatest { userIdPair -> observeLabelsAndFoldersWithChildren(userIdPair.first, userIdPair.second) }
|
||||
.flatMapLatest { userIdPair ->
|
||||
observeLabelsAndFoldersWithChildren(userIdPair.first, userIdPair.second)
|
||||
}
|
||||
.map { labelsAndFolders ->
|
||||
drawerFoldersAndLabelsSectionUiModelMapper.toUiModels(labelsAndFolders)
|
||||
}
|
||||
|
@ -197,6 +202,7 @@ internal class MailboxViewModel @Inject constructor(
|
|||
mutableRefreshFlow.onStart { emit(false) }
|
||||
) { userId, _ -> userId }
|
||||
.flatMapLatest { userId ->
|
||||
if (userId == null) return@flatMapLatest flowOf(emptyList())
|
||||
combineTransform(
|
||||
observeAllUnreadCounters(userId),
|
||||
observeConversationModeEnabled(userId)
|
||||
|
@ -223,7 +229,7 @@ internal class MailboxViewModel @Inject constructor(
|
|||
combine(
|
||||
mutableMailboxLocation,
|
||||
mutableMailboxLabelId,
|
||||
mutableUserId,
|
||||
mutableUserId.filterNotNull(),
|
||||
mutableRefreshFlow.onStart { emit(false) }
|
||||
) { location, label, userId, isRefresh ->
|
||||
Timber.v("New location: $location, label: $label, user: $userId, isRefresh: $isRefresh")
|
||||
|
@ -260,11 +266,6 @@ internal class MailboxViewModel @Inject constructor(
|
|||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
fun reloadDependenciesForUser() {
|
||||
pendingSendsLiveData = messageDetailsRepository.findAllPendingSendsAsync()
|
||||
pendingUploadsLiveData = messageDetailsRepository.findAllPendingUploadsAsync()
|
||||
}
|
||||
|
||||
fun usedSpaceActionEvent(limitReachedFlow: Int) {
|
||||
viewModelScope.launch {
|
||||
userManager.setShowStorageLimitReached(true)
|
||||
|
|
|
@ -39,7 +39,6 @@ import ch.protonmail.android.jobs.PostStarJob
|
|||
import ch.protonmail.android.jobs.PostUnreadJob
|
||||
import ch.protonmail.android.jobs.PostUnstarJob
|
||||
import ch.protonmail.android.labels.domain.LabelRepository
|
||||
import ch.protonmail.android.mailbox.data.local.UnreadCounterDao
|
||||
import ch.protonmail.android.mailbox.data.local.model.UnreadCounterEntity.Type
|
||||
import ch.protonmail.android.mailbox.data.mapper.ApiToDatabaseUnreadCounterMapper
|
||||
import ch.protonmail.android.mailbox.data.mapper.DatabaseToDomainUnreadCounterMapper
|
||||
|
@ -76,7 +75,6 @@ private const val FILE_PREFIX = "file://"
|
|||
*/
|
||||
class MessageRepository @Inject constructor(
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
private val unreadCounterDao: UnreadCounterDao,
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val protonMailApiManager: ProtonMailApiManager,
|
||||
private val databaseToDomainUnreadCounterMapper: DatabaseToDomainUnreadCounterMapper,
|
||||
|
@ -222,6 +220,7 @@ class MessageRepository @Inject constructor(
|
|||
Timber.v("Fetch Messages Unread response: $response")
|
||||
val counts = response.counts
|
||||
.map(apiToDatabaseUnreadCounterMapper) { toDatabaseModel(it, userId, Type.MESSAGES) }
|
||||
val unreadCounterDao = databaseProvider.provideUnreadCounterDao(userId)
|
||||
unreadCounterDao.insertOrUpdate(counts)
|
||||
}
|
||||
|
||||
|
@ -359,7 +358,9 @@ class MessageRepository @Inject constructor(
|
|||
}
|
||||
|
||||
private fun observerUnreadCountersFromDatabase(userId: UserId): Flow<DataResult<List<UnreadCounter>>> =
|
||||
unreadCounterDao.observeMessagesUnreadCounters(userId).map { list ->
|
||||
databaseProvider
|
||||
.provideUnreadCounterDao(userId)
|
||||
.observeMessagesUnreadCounters(userId).map { list ->
|
||||
val domainModels = databaseToDomainUnreadCounterMapper.toDomainModels(list)
|
||||
DataResult.Success(ResponseSource.Local, domainModels)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
package ch.protonmail.android.usecase.delete
|
||||
|
||||
import ch.protonmail.android.activities.messageDetails.repository.MessageDetailsRepository
|
||||
import ch.protonmail.android.data.local.PendingActionDao
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.data.local.model.PendingSend
|
||||
import ch.protonmail.android.data.local.model.PendingUpload
|
||||
|
@ -39,10 +39,10 @@ import javax.inject.Inject
|
|||
* [DeleteMessageWorker] that will send a deferrable delete message network request.
|
||||
*/
|
||||
class DeleteMessage @Inject constructor(
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val conversationsRepository: ConversationsRepository,
|
||||
private val dispatchers: DispatcherProvider,
|
||||
private val messageDetailsRepository: MessageDetailsRepository,
|
||||
private val pendingActionDatabase: PendingActionDao,
|
||||
private val messageDetailsRepositoryFactory: MessageDetailsRepository.AssistedFactory,
|
||||
private val workerScheduler: DeleteMessageWorker.Enqueuer
|
||||
) {
|
||||
|
||||
|
@ -52,8 +52,9 @@ class DeleteMessage @Inject constructor(
|
|||
userId: UserId
|
||||
): DeleteMessageResult =
|
||||
withContext(dispatchers.Io) {
|
||||
val messageDetailsRepository = messageDetailsRepositoryFactory.create(userId)
|
||||
|
||||
val (validMessageIdList, invalidMessageIdList) = getValidAndInvalidMessages(messageIds)
|
||||
val (validMessageIdList, invalidMessageIdList) = getValidAndInvalidMessages(userId, messageIds)
|
||||
|
||||
val messagesToSave = mutableListOf<Message>()
|
||||
|
||||
|
@ -76,7 +77,7 @@ class DeleteMessage @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getValidAndInvalidMessages(messageIds: List<String>): Pair<List<String>, List<String>> {
|
||||
private fun getValidAndInvalidMessages(userId: UserId, messageIds: List<String>): Pair<List<String>, List<String>> {
|
||||
val validMessageIdList = mutableListOf<String>()
|
||||
val invalidMessageIdList = mutableListOf<String>()
|
||||
|
||||
|
@ -84,8 +85,9 @@ class DeleteMessage @Inject constructor(
|
|||
if (id.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
val pendingUploads = pendingActionDatabase.findPendingUploadByMessageId(id)
|
||||
val pendingForSending = pendingActionDatabase.findPendingSendByMessageId(id)
|
||||
val pendingActionDao = databaseProvider.providePendingActionDao(userId)
|
||||
val pendingUploads = pendingActionDao.findPendingUploadByMessageId(id)
|
||||
val pendingForSending = pendingActionDao.findPendingSendByMessageId(id)
|
||||
|
||||
if (areThereAnyPendingUplandsOrSends(pendingUploads, pendingForSending)) {
|
||||
invalidMessageIdList.add(id)
|
||||
|
|
|
@ -21,7 +21,6 @@ package ch.protonmail.android.utils
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import ch.protonmail.android.activities.EXTRA_FIRST_LOGIN
|
||||
import ch.protonmail.android.activities.SplashActivity
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.core.ProtonMailApplication
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxActivity
|
||||
|
@ -29,12 +28,6 @@ import ch.protonmail.android.servers.notification.EXTRA_MAILBOX_LOCATION
|
|||
import ch.protonmail.android.servers.notification.EXTRA_USER_ID
|
||||
import me.proton.core.domain.entity.UserId
|
||||
|
||||
fun Context.startSplashActivity() =
|
||||
startActivity(getSplashActivityIntent())
|
||||
|
||||
fun Context.getSplashActivityIntent(): Intent =
|
||||
Intent(this, SplashActivity::class.java)
|
||||
|
||||
fun Context.startMailboxActivity(
|
||||
userId: UserId? = null,
|
||||
type: Constants.MessageLocationType? = null
|
||||
|
|
|
@ -30,8 +30,10 @@ import androidx.work.WorkManager
|
|||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.ProtonMailApiManager
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.IDList
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.local.ContactDao
|
||||
import ch.protonmail.android.data.local.ContactDatabase
|
||||
import dagger.assisted.Assisted
|
||||
|
@ -55,13 +57,19 @@ class DeleteContactWorker @AssistedInject constructor(
|
|||
@Assisted context: Context,
|
||||
@Assisted params: WorkerParameters,
|
||||
private val api: ProtonMailApiManager,
|
||||
private val contactDao: ContactDao,
|
||||
private val contactDatabase: ContactDatabase,
|
||||
private val userManager: UserManager,
|
||||
private val databaseProvider: DatabaseProvider,
|
||||
private val dispatchers: DispatcherProvider
|
||||
) : CoroutineWorker(context, params) {
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
private val contactDatabase: ContactDatabase
|
||||
get() = databaseProvider.provideContactDatabase(userManager.requireCurrentUserId())
|
||||
|
||||
private val contactDao: ContactDao
|
||||
get() = databaseProvider.provideContactDao(userManager.requireCurrentUserId())
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
// TODO: Pass userId (requireCurrentUserId would not always be the right one).
|
||||
val contactIds = inputData.getStringArray(KEY_INPUT_DATA_CONTACT_IDS)
|
||||
?: emptyArray()
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import androidx.work.ListenableWorker
|
|||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.ProtonMailApi
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.local.CounterRepository
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.worker.KEY_WORKER_ERROR_DESCRIPTION
|
||||
|
@ -32,9 +33,7 @@ import io.mockk.coEvery
|
|||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import me.proton.core.accountmanager.domain.AccountManager
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
|
@ -48,7 +47,7 @@ class RemoveMessageLabelWorkerTest {
|
|||
|
||||
private val api = mockk<ProtonMailApi>()
|
||||
|
||||
private val accountManager = mockk<AccountManager>()
|
||||
private val userManager = mockk<UserManager>()
|
||||
|
||||
private val counterRepository = mockk<CounterRepository>()
|
||||
|
||||
|
@ -59,12 +58,12 @@ class RemoveMessageLabelWorkerTest {
|
|||
@BeforeTest
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { accountManager.getPrimaryUserId() } returns flowOf(testUserId)
|
||||
every { userManager.currentUserId } returns testUserId
|
||||
|
||||
worker = RemoveMessageLabelWorker(
|
||||
context,
|
||||
parameters,
|
||||
accountManager,
|
||||
userManager,
|
||||
counterRepository,
|
||||
api
|
||||
)
|
||||
|
|
|
@ -21,11 +21,13 @@ package ch.protonmail.android.mailbox.data
|
|||
|
||||
import app.cash.turbine.test
|
||||
import ch.protonmail.android.api.ProtonMailApiManager
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.MessageRecipient
|
||||
import ch.protonmail.android.api.models.messages.receive.MessageFactory
|
||||
import ch.protonmail.android.api.models.messages.receive.ServerMessage
|
||||
import ch.protonmail.android.core.Constants.MessageLocationType
|
||||
import ch.protonmail.android.core.NetworkConnectivityManager
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.local.MessageDao
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.data.local.model.MessageSender
|
||||
|
@ -183,6 +185,11 @@ class ConversationsRepositoryImplTest : ArchTest {
|
|||
)
|
||||
)
|
||||
|
||||
private val userManager: UserManager = mockk {
|
||||
every { currentUserId } returns testUserId
|
||||
every { requireCurrentUserId() } returns testUserId
|
||||
}
|
||||
|
||||
private val conversationDao: ConversationDao = mockk {
|
||||
coEvery { updateLabels(any(), any()) } just Runs
|
||||
coEvery { insertOrUpdate(*anyVararg()) } just Runs
|
||||
|
@ -198,6 +205,12 @@ class ConversationsRepositoryImplTest : ArchTest {
|
|||
coEvery { insertOrUpdate(any<Collection<UnreadCounterEntity>>()) } just Runs
|
||||
}
|
||||
|
||||
private val databaseProvider: DatabaseProvider = mockk {
|
||||
every { provideConversationDao(any()) } returns conversationDao
|
||||
every { provideMessageDao(any()) } returns messageDao
|
||||
every { provideUnreadCounterDao(any()) } returns unreadCounterDao
|
||||
}
|
||||
|
||||
private val api: ProtonMailApiManager = mockk {
|
||||
coEvery { fetchConversationsCounts(testUserId) } returns CountsResponse(emptyList())
|
||||
}
|
||||
|
@ -252,9 +265,8 @@ class ConversationsRepositoryImplTest : ArchTest {
|
|||
}
|
||||
|
||||
private val conversationsRepository = ConversationsRepositoryImpl(
|
||||
conversationDao = conversationDao,
|
||||
messageDao = messageDao,
|
||||
unreadCounterDao = unreadCounterDao,
|
||||
userManager = userManager,
|
||||
databaseProvider = databaseProvider,
|
||||
api = api,
|
||||
responseToConversationsMapper = ConversationsResponseToConversationsMapper(
|
||||
conversationApiModelToConversationMapper
|
||||
|
|
|
@ -85,6 +85,7 @@ class MessageRepositoryTest {
|
|||
|
||||
private val databaseProvider: DatabaseProvider = mockk {
|
||||
every { provideMessageDao(any()) } returns messageDao
|
||||
every { provideUnreadCounterDao(any()) } returns unreadCounterDao
|
||||
}
|
||||
|
||||
private val messageBodyFileManager: MessageBodyFileManager = mockk()
|
||||
|
@ -126,7 +127,6 @@ class MessageRepositoryTest {
|
|||
|
||||
private val messageRepository = MessageRepository(
|
||||
dispatcherProvider = TestDispatcherProvider,
|
||||
unreadCounterDao = unreadCounterDao,
|
||||
databaseProvider = databaseProvider,
|
||||
protonMailApiManager = protonMailApiManager,
|
||||
databaseToDomainUnreadCounterMapper = DatabaseToDomainUnreadCounterMapper(),
|
||||
|
|
|
@ -21,6 +21,7 @@ package ch.protonmail.android.usecase.delete
|
|||
|
||||
import androidx.work.Operation
|
||||
import ch.protonmail.android.activities.messageDetails.repository.MessageDetailsRepository
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.data.local.PendingActionDao
|
||||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.data.local.model.PendingSend
|
||||
|
@ -48,12 +49,18 @@ class DeleteMessageTest {
|
|||
|
||||
private val workScheduler: DeleteMessageWorker.Enqueuer = mockk()
|
||||
|
||||
private val db: PendingActionDao = mockk()
|
||||
|
||||
private val messageDetailsRepository: MessageDetailsRepository = mockk()
|
||||
private val messageDetailsRepositoryFactory: MessageDetailsRepository.AssistedFactory = mockk() {
|
||||
every { create(any()) } returns messageDetailsRepository
|
||||
}
|
||||
|
||||
private val pendingActionDao: PendingActionDao = mockk()
|
||||
private val conversationsRepository: ConversationsRepository = mockk()
|
||||
|
||||
private val databaseProvider: DatabaseProvider = mockk {
|
||||
every { providePendingActionDao(any()) } returns pendingActionDao
|
||||
}
|
||||
|
||||
private lateinit var deleteMessage: DeleteMessage
|
||||
|
||||
private val messId = "Id1"
|
||||
|
@ -70,10 +77,10 @@ class DeleteMessageTest {
|
|||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
deleteMessage = DeleteMessage(
|
||||
databaseProvider,
|
||||
conversationsRepository,
|
||||
TestDispatcherProvider,
|
||||
messageDetailsRepository,
|
||||
db,
|
||||
messageDetailsRepositoryFactory,
|
||||
workScheduler
|
||||
)
|
||||
|
||||
|
@ -90,8 +97,8 @@ class DeleteMessageTest {
|
|||
fun verifyThatMessageIsSuccessfullyDeletedWithoutPendingMessagesInTheDb() {
|
||||
runBlockingTest {
|
||||
// given
|
||||
every { db.findPendingUploadByMessageId(any()) } returns null
|
||||
every { db.findPendingSendByMessageId(any()) } returns null
|
||||
every { pendingActionDao.findPendingUploadByMessageId(any()) } returns null
|
||||
every { pendingActionDao.findPendingSendByMessageId(any()) } returns null
|
||||
every { messageDetailsRepository.findMessageById(messId) } returns flowOf(message)
|
||||
|
||||
// when
|
||||
|
@ -112,8 +119,8 @@ class DeleteMessageTest {
|
|||
runBlockingTest {
|
||||
// given
|
||||
val pendingUpload = mockk<PendingUpload>(relaxed = true)
|
||||
every { db.findPendingUploadByMessageId(any()) } returns pendingUpload
|
||||
every { db.findPendingSendByMessageId(any()) } returns null
|
||||
every { pendingActionDao.findPendingUploadByMessageId(any()) } returns pendingUpload
|
||||
every { pendingActionDao.findPendingSendByMessageId(any()) } returns null
|
||||
every { messageDetailsRepository.findMessageByIdBlocking(messId) } returns message
|
||||
coEvery { messageDetailsRepository.saveMessage(message) } returns 1L
|
||||
|
||||
|
@ -137,8 +144,8 @@ class DeleteMessageTest {
|
|||
val pendingSend = mockk<PendingSend>(relaxed = true) {
|
||||
every { sent } returns true
|
||||
}
|
||||
every { db.findPendingUploadByMessageId(any()) } returns null
|
||||
every { db.findPendingSendByMessageId(any()) } returns pendingSend
|
||||
every { pendingActionDao.findPendingUploadByMessageId(any()) } returns null
|
||||
every { pendingActionDao.findPendingSendByMessageId(any()) } returns pendingSend
|
||||
every { messageDetailsRepository.findMessageByIdBlocking(messId) } returns null
|
||||
coEvery { messageDetailsRepository.saveMessage(message) } returns 1L
|
||||
|
||||
|
|
|
@ -24,8 +24,10 @@ import androidx.work.ListenableWorker
|
|||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import ch.protonmail.android.api.ProtonMailApiManager
|
||||
import ch.protonmail.android.api.models.DatabaseProvider
|
||||
import ch.protonmail.android.api.models.DeleteResponse
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.local.ContactDao
|
||||
import ch.protonmail.android.data.local.ContactDatabase
|
||||
import ch.protonmail.android.data.local.model.ContactData
|
||||
|
@ -50,6 +52,12 @@ class DeleteContactWorkerTest {
|
|||
@RelaxedMockK
|
||||
private lateinit var parameters: WorkerParameters
|
||||
|
||||
@MockK
|
||||
private lateinit var userManager: UserManager
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var databaseProvider: DatabaseProvider
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var contactDatabase: ContactDatabase
|
||||
|
||||
|
@ -64,12 +72,17 @@ class DeleteContactWorkerTest {
|
|||
@BeforeTest
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
|
||||
every { userManager.requireCurrentUserId() } returns mockk()
|
||||
every { databaseProvider.provideContactDatabase(any()) } returns contactDatabase
|
||||
every { databaseProvider.provideContactDao(any()) } returns contactDao
|
||||
|
||||
worker = DeleteContactWorker(
|
||||
context,
|
||||
parameters,
|
||||
api,
|
||||
contactDao,
|
||||
contactDatabase,
|
||||
userManager,
|
||||
databaseProvider,
|
||||
TestDispatcherProvider
|
||||
)
|
||||
}
|
||||
|
@ -100,15 +113,14 @@ class DeleteContactWorkerTest {
|
|||
every { code } returns Constants.RESPONSE_CODE_OK
|
||||
}
|
||||
val contactData = mockk<ContactData>()
|
||||
val contactEmail= mockk<ContactEmail>()
|
||||
val contactEmail = mockk<ContactEmail>()
|
||||
val expected = ListenableWorker.Result.success()
|
||||
|
||||
every { contactDao.findContactDataByIdBlocking(contactId) } returns contactData
|
||||
every { contactDao.findContactEmailsByContactIdBlocking(contactId) } returns listOf(contactEmail)
|
||||
every { contactDao.deleteAllContactsEmailsBlocking(any()) } returns mockk()
|
||||
every { contactDao.deleteContactData(any()) } returns mockk()
|
||||
every { parameters.inputData } returns
|
||||
workDataOf(KEY_INPUT_DATA_CONTACT_IDS to arrayOf(contactId))
|
||||
every { parameters.inputData } returns workDataOf(KEY_INPUT_DATA_CONTACT_IDS to arrayOf(contactId))
|
||||
coEvery { api.deleteContact(any()) } returns deleteResponse
|
||||
|
||||
// when
|
||||
|
@ -129,7 +141,7 @@ class DeleteContactWorkerTest {
|
|||
every { code } returns randomErrorCode
|
||||
}
|
||||
val contactData = mockk<ContactData>()
|
||||
val contactEmail= mockk<ContactEmail>()
|
||||
val contactEmail = mockk<ContactEmail>()
|
||||
val expected = ListenableWorker.Result.failure(
|
||||
workDataOf(KEY_WORKER_ERROR_DESCRIPTION to "ApiException response code $randomErrorCode")
|
||||
)
|
||||
|
@ -138,8 +150,7 @@ class DeleteContactWorkerTest {
|
|||
every { contactDao.findContactEmailsByContactIdBlocking(contactId) } returns listOf(contactEmail)
|
||||
every { contactDao.deleteAllContactsEmailsBlocking(any()) } returns mockk()
|
||||
every { contactDao.deleteContactData(any()) } returns mockk()
|
||||
every { parameters.inputData } returns
|
||||
workDataOf(KEY_INPUT_DATA_CONTACT_IDS to arrayOf(contactId))
|
||||
every { parameters.inputData } returns workDataOf(KEY_INPUT_DATA_CONTACT_IDS to arrayOf(contactId))
|
||||
coEvery { api.deleteContact(any()) } returns deleteResponse
|
||||
|
||||
// when
|
||||
|
@ -149,5 +160,4 @@ class DeleteContactWorkerTest {
|
|||
assertEquals(operationResult, expected)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue