From 9c3d470e141cfc24846c60c81193e9f29c78aeec Mon Sep 17 00:00:00 2001 From: Marino Meneghel Date: Fri, 14 Apr 2023 12:54:32 +0200 Subject: [PATCH 1/3] Call launch review flow to prompt user the rating dialog - Inject review manager over using static constructor MAILAND-3071 --- .../protonmail/android/di/ViewModelModule.kt | 15 ++++- .../feature/rating/StartRateAppFlow.kt | 20 +++--- ...wIfNeeded.kt => ShouldStartRateAppFlow.kt} | 26 ++++---- .../presentation/ui/MailboxActivity.kt | 9 +++ .../viewmodel/MailboxViewModel.kt | 14 +++- .../feature/rating/StartRateAppFlowTest.kt | 64 +++++++++++++------ ...dTest.kt => ShouldStartRateAppFlowTest.kt} | 48 ++++++++------ .../viewmodel/MailboxViewModelTest.kt | 38 +++++++---- 8 files changed, 157 insertions(+), 77 deletions(-) rename app/src/main/java/ch/protonmail/android/feature/rating/usecase/{StartRateAppFlowIfNeeded.kt => ShouldStartRateAppFlow.kt} (72%) rename app/src/test/java/ch/protonmail/android/feature/rating/usecase/{StartRateAppFlowIfNeededTest.kt => ShouldStartRateAppFlowTest.kt} (71%) diff --git a/app/src/main/java/ch/protonmail/android/di/ViewModelModule.kt b/app/src/main/java/ch/protonmail/android/di/ViewModelModule.kt index b93fc6b65..bca969fa5 100644 --- a/app/src/main/java/ch/protonmail/android/di/ViewModelModule.kt +++ b/app/src/main/java/ch/protonmail/android/di/ViewModelModule.kt @@ -20,6 +20,7 @@ package ch.protonmail.android.di +import android.content.Context import androidx.lifecycle.ViewModelProvider import ch.protonmail.android.activities.messageDetails.repository.MessageDetailsRepository import ch.protonmail.android.activities.settings.NotificationSettingsViewModel @@ -31,7 +32,7 @@ import ch.protonmail.android.contacts.groups.edit.chooser.AddressChooserViewMode import ch.protonmail.android.core.ProtonMailApplication import ch.protonmail.android.core.UserManager import ch.protonmail.android.drawer.presentation.mapper.DrawerFoldersAndLabelsSectionUiModelMapper -import ch.protonmail.android.feature.rating.usecase.StartRateAppFlowIfNeeded +import ch.protonmail.android.feature.rating.usecase.ShouldStartRateAppFlow import ch.protonmail.android.labels.domain.LabelRepository import ch.protonmail.android.labels.domain.usecase.ObserveLabels import ch.protonmail.android.labels.domain.usecase.ObserveLabelsAndFoldersWithChildren @@ -54,9 +55,12 @@ import ch.protonmail.android.usecase.delete.DeleteMessage import ch.protonmail.android.usecase.delete.EmptyFolder import ch.protonmail.android.usecase.message.ChangeMessagesReadStatus import ch.protonmail.android.usecase.message.ChangeMessagesStarredStatus +import com.google.android.play.core.review.ReviewManager +import com.google.android.play.core.review.ReviewManagerFactory 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.util.kotlin.DispatcherProvider @@ -91,6 +95,11 @@ internal class ViewModelModule { pinFragmentViewModelFactory: PinFragmentViewModelFactory ): ViewModelProvider.NewInstanceFactory = pinFragmentViewModelFactory + @Provides + fun provideReviewManager( + @ApplicationContext context: Context + ): ReviewManager = ReviewManagerFactory.create(context) + @Suppress("LongParameterList") // Every new parameter adds a new issue and breaks the build @Provides fun provideMailboxViewModel( @@ -119,7 +128,7 @@ internal class ViewModelModule { mailboxItemUiModelMapper: MailboxItemUiModelMapper, fetchEventsAndReschedule: FetchEventsAndReschedule, clearNotificationsForUser: ClearNotificationsForUser, - startRateAppFlowIfNeeded: StartRateAppFlowIfNeeded + shouldStartRateAppFlow: ShouldStartRateAppFlow ) = MailboxViewModel( messageDetailsRepositoryFactory = messageDetailsRepositoryFactory, userManager = userManager, @@ -146,6 +155,6 @@ internal class ViewModelModule { mailboxItemUiModelMapper = mailboxItemUiModelMapper, fetchEventsAndReschedule = fetchEventsAndReschedule, clearNotificationsForUser = clearNotificationsForUser, - startRateAppFlowIfNeeded = startRateAppFlowIfNeeded + shouldStartRateAppFlow = shouldStartRateAppFlow ) } diff --git a/app/src/main/java/ch/protonmail/android/feature/rating/StartRateAppFlow.kt b/app/src/main/java/ch/protonmail/android/feature/rating/StartRateAppFlow.kt index 7f8ac4039..2f6eee70f 100644 --- a/app/src/main/java/ch/protonmail/android/feature/rating/StartRateAppFlow.kt +++ b/app/src/main/java/ch/protonmail/android/feature/rating/StartRateAppFlow.kt @@ -18,22 +18,22 @@ */ package ch.protonmail.android.feature.rating -import android.content.Context -import com.google.android.play.core.review.ReviewManagerFactory -import dagger.hilt.android.qualifiers.ApplicationContext +import android.app.Activity +import com.google.android.play.core.review.ReviewManager import timber.log.Timber import javax.inject.Inject class StartRateAppFlow @Inject constructor( - @ApplicationContext - private val context: Context + private val reviewManager: ReviewManager ) { - operator fun invoke() { - val manager = ReviewManagerFactory.create(context) - manager.requestReviewFlow().addOnCompleteListener { - Timber.d("App review finished. Success = ${it.isSuccessful}") + operator fun invoke(activity: Activity) { + val request = reviewManager.requestReviewFlow() + request.addOnSuccessListener { reviewInfo -> + reviewManager.launchReviewFlow(activity, reviewInfo) + } + request.addOnFailureListener { + Timber.d("Rate app flow request failed ") } - } } \ No newline at end of file diff --git a/app/src/main/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeeded.kt b/app/src/main/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlow.kt similarity index 72% rename from app/src/main/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeeded.kt rename to app/src/main/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlow.kt index 784ca497e..ab4585c22 100644 --- a/app/src/main/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeeded.kt +++ b/app/src/main/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlow.kt @@ -20,33 +20,31 @@ package ch.protonmail.android.feature.rating.usecase import ch.protonmail.android.feature.rating.MailboxScreenViewInMemoryRepository -import ch.protonmail.android.feature.rating.StartRateAppFlow import ch.protonmail.android.featureflags.MailFeatureFlags import me.proton.core.domain.entity.UserId import me.proton.core.featureflag.domain.FeatureFlagManager import me.proton.core.featureflag.domain.entity.FeatureFlag import javax.inject.Inject -class StartRateAppFlowIfNeeded @Inject constructor( +class ShouldStartRateAppFlow @Inject constructor( private val mailboxScreenViewsRepository: MailboxScreenViewInMemoryRepository, - private val featureFlagManager: FeatureFlagManager, - private val startRateAppFlow: StartRateAppFlow + private val featureFlagManager: FeatureFlagManager ) { - suspend operator fun invoke(userId: UserId) { + suspend operator fun invoke(userId: UserId) : Boolean { if (!isShowReviewFeatureFlagEnabled(userId)) { - return + return false } if (mailboxScreenViewsRepository.screenViewCount < MailboxScreenViewsThreshold) { - return + return false } - startRateAppFlow() - recordReviewFlowStarted(userId) + recordShowReviewFlowConditionsMet(userId) + return true } - private suspend fun recordReviewFlowStarted(userId: UserId) { + private suspend fun recordShowReviewFlowConditionsMet(userId: UserId) { val featureFlag = getShowReviewFeatureFlag(userId) - val offFeatureFlag = featureFlag.copy(defaultValue = false, value = false) + val offFeatureFlag = featureFlag.copy(value = false) featureFlagManager.update(offFeatureFlag) } @@ -55,9 +53,9 @@ class StartRateAppFlowIfNeeded @Inject constructor( private suspend fun getShowReviewFeatureFlag( userId: UserId ) = featureFlagManager.getOrDefault( - userId, - MailFeatureFlags.ShowReviewAppDialog.featureId, - FeatureFlag.default(MailFeatureFlags.ShowReviewAppDialog.featureId.id, false) + userId = userId, + featureId = MailFeatureFlags.ShowReviewAppDialog.featureId, + default = FeatureFlag.default(MailFeatureFlags.ShowReviewAppDialog.featureId.id, false) ) companion object { diff --git a/app/src/main/java/ch/protonmail/android/mailbox/presentation/ui/MailboxActivity.kt b/app/src/main/java/ch/protonmail/android/mailbox/presentation/ui/MailboxActivity.kt index 7a80f9bac..b77e9248a 100644 --- a/app/src/main/java/ch/protonmail/android/mailbox/presentation/ui/MailboxActivity.kt +++ b/app/src/main/java/ch/protonmail/android/mailbox/presentation/ui/MailboxActivity.kt @@ -89,6 +89,7 @@ import ch.protonmail.android.events.MailboxNoMessagesEvent import ch.protonmail.android.events.SettingsChangedEvent import ch.protonmail.android.events.Status import ch.protonmail.android.feature.account.AccountStateManager +import ch.protonmail.android.feature.rating.StartRateAppFlow import ch.protonmail.android.labels.domain.model.Label import ch.protonmail.android.labels.domain.model.LabelId import ch.protonmail.android.labels.domain.model.LabelType @@ -189,6 +190,9 @@ internal class MailboxActivity : @Inject lateinit var isConversationModeEnabled: ConversationModeEnabled + @Inject + lateinit var startRateAppFlow: StartRateAppFlow + @Inject @DefaultSharedPreferences lateinit var defaultSharedPreferences: SharedPreferences @@ -413,6 +417,7 @@ internal class MailboxActivity : exitSelectionModeSharedFlow .onEach { if (it) actionMode?.finish() } .launchIn(lifecycleScope) + } setUpMailboxActionsView() @@ -436,6 +441,10 @@ internal class MailboxActivity : ) }.launchIn(lifecycleScope) } + + mailboxViewModel.startRateAppFlow + .onEach { startRateAppFlow(this) } + .launchIn(lifecycleScope) } private fun startObserving() { diff --git a/app/src/main/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModel.kt b/app/src/main/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModel.kt index 6c6304722..1ba555567 100644 --- a/app/src/main/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModel.kt +++ b/app/src/main/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModel.kt @@ -41,7 +41,7 @@ import ch.protonmail.android.domain.loadMoreMap import ch.protonmail.android.drawer.presentation.mapper.DrawerFoldersAndLabelsSectionUiModelMapper import ch.protonmail.android.drawer.presentation.model.DrawerFoldersAndLabelsSectionUiModel import ch.protonmail.android.feature.NotLoggedIn -import ch.protonmail.android.feature.rating.usecase.StartRateAppFlowIfNeeded +import ch.protonmail.android.feature.rating.usecase.ShouldStartRateAppFlow import ch.protonmail.android.labels.domain.LabelRepository import ch.protonmail.android.labels.domain.model.Label import ch.protonmail.android.labels.domain.model.LabelId @@ -138,7 +138,7 @@ internal class MailboxViewModel @Inject constructor( private val mailboxItemUiModelMapper: MailboxItemUiModelMapper, private val fetchEventsAndReschedule: FetchEventsAndReschedule, private val clearNotificationsForUser: ClearNotificationsForUser, - private val startRateAppFlowIfNeeded: StartRateAppFlowIfNeeded + private val shouldStartRateAppFlow: ShouldStartRateAppFlow ) : ConnectivityBaseViewModel(verifyConnection, networkConfigurator) { private val _manageLimitReachedWarning = MutableLiveData>() @@ -156,6 +156,7 @@ internal class MailboxViewModel @Inject constructor( onBufferOverflow = BufferOverflow.DROP_OLDEST ) private val _exitSelectionModeSharedFlow = MutableSharedFlow() + private val _startRateAppFlow = MutableSharedFlow() private val messageDetailsRepository: MessageDetailsRepository get() = messageDetailsRepositoryFactory.create(userManager.requireCurrentUserId()) @@ -188,6 +189,9 @@ internal class MailboxViewModel @Inject constructor( val exitSelectionModeSharedFlow: SharedFlow get() = _exitSelectionModeSharedFlow + val startRateAppFlow: SharedFlow + get() = _startRateAppFlow + val mailboxState = mutableMailboxState.asStateFlow() val mailboxLocation = mutableMailboxLocation.asStateFlow() @@ -727,7 +731,11 @@ internal class MailboxViewModel @Inject constructor( fun startRateAppFlowIfNeeded() { val userId = userManager.currentUserId ?: return viewModelScope.launch { - startRateAppFlowIfNeeded.invoke(userId) + shouldStartRateAppFlow(userId).let { startFlow -> + if (startFlow) { + _startRateAppFlow.emit(Unit) + } + } } } diff --git a/app/src/test/java/ch/protonmail/android/feature/rating/StartRateAppFlowTest.kt b/app/src/test/java/ch/protonmail/android/feature/rating/StartRateAppFlowTest.kt index 3cd616ded..cc52456a9 100644 --- a/app/src/test/java/ch/protonmail/android/feature/rating/StartRateAppFlowTest.kt +++ b/app/src/test/java/ch/protonmail/android/feature/rating/StartRateAppFlowTest.kt @@ -19,41 +19,69 @@ package ch.protonmail.android.feature.rating -import android.content.Context +import android.app.Activity +import com.google.android.gms.tasks.OnFailureListener +import com.google.android.gms.tasks.OnSuccessListener +import com.google.android.gms.tasks.Task +import com.google.android.gms.tasks.Tasks +import com.google.android.play.core.review.ReviewInfo import com.google.android.play.core.review.ReviewManager -import com.google.android.play.core.review.ReviewManagerFactory import io.mockk.every import io.mockk.mockk -import io.mockk.mockkStatic -import io.mockk.unmockkStatic import io.mockk.verify -import org.junit.After import org.junit.Test class StartRateAppFlowTest { - private val context: Context = mockk(relaxed = true) + private val activity: Activity = mockk(relaxed = true) + private val reviewInfo: ReviewInfo = mockk() + private val requestMock: Task = mockk { + every { result } returns reviewInfo + every { addOnSuccessListener(any()) } answers { + if (this@mockk.isSuccessful) { + val successListener = firstArg>() + successListener.onSuccess(reviewInfo) + } + Tasks.forResult(reviewInfo) + } + every { addOnFailureListener(any()) } answers { + val exception = Exception("Failed") + if (!this@mockk.isSuccessful) { + val failureListener = firstArg() + failureListener.onFailure(exception) + } + Tasks.forException(exception) + } + } + private val reviewManagerMock: ReviewManager = mockk { + every { requestReviewFlow() } returns requestMock + } - private val startRateAppFlow = StartRateAppFlow(context) + private val startRateAppFlow = StartRateAppFlow(reviewManagerMock) - @After - fun tearDown() { - unmockkStatic(ReviewManagerFactory::class) + @Test + fun `succeeds when review flow request is successful`() { + // given + every { requestMock.isSuccessful } returns true + every { reviewManagerMock.launchReviewFlow(activity, reviewInfo) } returns mockk() + + // when + startRateAppFlow(activity) + + // then + verify { reviewManagerMock.launchReviewFlow(activity, reviewInfo) } } @Test - fun `request review flow from google play review manager`() { + fun `fails when review flow request is not successful`() { // given - val reviewMangerMock = mockk { - every { this@mockk.requestReviewFlow() } returns mockk(relaxed = true) - } - mockkStatic(ReviewManagerFactory::class) - every { ReviewManagerFactory.create(context) } returns reviewMangerMock + every { requestMock.isSuccessful } returns false + every { reviewManagerMock.launchReviewFlow(activity, reviewInfo) } returns mockk() // when - startRateAppFlow() + startRateAppFlow(activity) // then - verify { reviewMangerMock.requestReviewFlow() } + verify(exactly = 0) { reviewManagerMock.launchReviewFlow(any(), any()) } } } \ No newline at end of file diff --git a/app/src/test/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeededTest.kt b/app/src/test/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlowTest.kt similarity index 71% rename from app/src/test/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeededTest.kt rename to app/src/test/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlowTest.kt index 2c5c106f7..6ccbe1feb 100644 --- a/app/src/test/java/ch/protonmail/android/feature/rating/usecase/StartRateAppFlowIfNeededTest.kt +++ b/app/src/test/java/ch/protonmail/android/feature/rating/usecase/ShouldStartRateAppFlowTest.kt @@ -20,47 +20,41 @@ package ch.protonmail.android.feature.rating.usecase import ch.protonmail.android.feature.rating.MailboxScreenViewInMemoryRepository -import ch.protonmail.android.feature.rating.StartRateAppFlow import ch.protonmail.android.featureflags.MailFeatureFlags import ch.protonmail.android.testdata.UserTestData -import io.mockk.Called import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import io.mockk.verify import kotlinx.coroutines.test.runTest import me.proton.core.domain.entity.UserId import me.proton.core.featureflag.domain.FeatureFlagManager import me.proton.core.featureflag.domain.entity.FeatureFlag import me.proton.core.featureflag.domain.entity.Scope import org.junit.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue -class StartRateAppFlowIfNeededTest { +class ShouldStartRateAppFlowTest { private val userId = UserTestData.userId private val mailboxScreenViewsRepository: MailboxScreenViewInMemoryRepository = mockk() private val featureFlagManager: FeatureFlagManager = mockk(relaxUnitFun = true) - private val startRateAppFlow: StartRateAppFlow = mockk(relaxUnitFun = true) - private val startRateAppFlowIfNeeded = StartRateAppFlowIfNeeded( - mailboxScreenViewsRepository, - featureFlagManager, - startRateAppFlow - ) + private val shouldStartRateAppFlow = ShouldStartRateAppFlow(mailboxScreenViewsRepository, featureFlagManager) @Test - fun `rate app flow is started when feature flag is true and mailbox screen views reached threshold`() = runTest { + fun `start rate app flow is true when feature flag is true and mailbox screen views reached threshold`() = runTest { // given mockFeatureFlagValue(userId, true) mockScreenViews(2) // when - startRateAppFlowIfNeeded(userId) + val result = shouldStartRateAppFlow(userId) // then - verify { startRateAppFlow() } + assertTrue(result) } @Test @@ -70,10 +64,10 @@ class StartRateAppFlowIfNeededTest { mockScreenViews(2) // when - startRateAppFlowIfNeeded(userId) + val result = shouldStartRateAppFlow(userId) // then - verify { startRateAppFlow wasNot Called } + assertFalse(result) } @Test @@ -83,10 +77,10 @@ class StartRateAppFlowIfNeededTest { mockScreenViews(1) // when - startRateAppFlowIfNeeded(userId) + val result = shouldStartRateAppFlow(userId) // then - verify { startRateAppFlow wasNot Called } + assertFalse(result) } @Test @@ -96,7 +90,7 @@ class StartRateAppFlowIfNeededTest { mockScreenViews(2) // when - startRateAppFlowIfNeeded(userId) + shouldStartRateAppFlow(userId) // then val featureId = MailFeatureFlags.ShowReviewAppDialog.featureId @@ -104,6 +98,24 @@ class StartRateAppFlowIfNeededTest { coVerify { featureFlagManager.update(featureFlag) } } + @Test + fun `rate app feature flag is not refreshed from network each time`() = runTest { + // This is explicitly checked as it'd be expensive due to high frequency of calls to this use case. + // Refresh from network happens at app launch through RefreshFeatureFlags use case + // given + mockFeatureFlagValue(userId, true) + mockScreenViews(2) + + // when + shouldStartRateAppFlow(userId) + + // then + val featureId = MailFeatureFlags.ShowReviewAppDialog.featureId + val default = FeatureFlag.default(featureId.id, false) + coVerify { featureFlagManager.getOrDefault(userId, featureId, default, false) } + } + + private suspend fun mockFeatureFlagValue(userId: UserId, isEnabled: Boolean) { val featureId = MailFeatureFlags.ShowReviewAppDialog.featureId coEvery { diff --git a/app/src/test/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModelTest.kt b/app/src/test/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModelTest.kt index 59c6ed0f8..fe32a912c 100644 --- a/app/src/test/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModelTest.kt +++ b/app/src/test/java/ch/protonmail/android/mailbox/presentation/viewmodel/MailboxViewModelTest.kt @@ -41,7 +41,7 @@ import ch.protonmail.android.di.JobEntryPoint import ch.protonmail.android.domain.loadMoreFlowOf import ch.protonmail.android.domain.withLoadMore import ch.protonmail.android.feature.NotLoggedIn -import ch.protonmail.android.feature.rating.usecase.StartRateAppFlowIfNeeded +import ch.protonmail.android.feature.rating.usecase.ShouldStartRateAppFlow import ch.protonmail.android.labels.domain.LabelRepository import ch.protonmail.android.labels.domain.model.Label import ch.protonmail.android.labels.domain.model.LabelId @@ -181,7 +181,7 @@ class MailboxViewModelTest : ArchTest by ArchTest(), private val fetchEventsAndReschedule: FetchEventsAndReschedule = mockk { coEvery { this@mockk.invoke() } just runs } - private val startRateAppFlowIfNeeded: StartRateAppFlowIfNeeded = mockk() + private val shouldStartRateAppFlow: ShouldStartRateAppFlow = mockk() private lateinit var viewModel: MailboxViewModel @@ -277,7 +277,7 @@ class MailboxViewModelTest : ArchTest by ArchTest(), mailboxItemUiModelMapper = mailboxItemUiModelMapper, fetchEventsAndReschedule = fetchEventsAndReschedule, clearNotificationsForUser = clearNotificationsForUser, - startRateAppFlowIfNeeded = startRateAppFlowIfNeeded + shouldStartRateAppFlow = shouldStartRateAppFlow ) } @@ -612,19 +612,35 @@ class MailboxViewModelTest : ArchTest by ArchTest(), } @Test - fun `calls to start rate app flow if needed delegates to use case`() = runTest { + fun `emit start rate app flow event when use case return true`() = runTest(dispatchers.Main) { // given - coEvery { startRateAppFlowIfNeeded.invoke(testUserId) } returns Unit + coEvery { shouldStartRateAppFlow.invoke(testUserId) } returns true - // when - viewModel.startRateAppFlowIfNeeded() + viewModel.startRateAppFlow.test { + // when + viewModel.startRateAppFlowIfNeeded() - // then - coVerify { startRateAppFlowIfNeeded.invoke(testUserId) } + // then + awaitItem() + } } @Test - fun `start rate app flow if needed is not called when current user id is invalid`() = runTest { + fun `does not emit start rate app flow event when use case returns false`() = runTest(dispatchers.Main) { + // given + coEvery { shouldStartRateAppFlow.invoke(testUserId) } returns false + + viewModel.startRateAppFlow.test { + // when + viewModel.startRateAppFlowIfNeeded() + + // then + ensureAllEventsConsumed() + } + } + + @Test + fun `start rate app flow if needed is not called when current user id is invalid`() = runTest(dispatchers.Main) { // given every { userManager.currentUserId } returns null @@ -632,7 +648,7 @@ class MailboxViewModelTest : ArchTest by ArchTest(), viewModel.startRateAppFlowIfNeeded() // then - verify { startRateAppFlowIfNeeded wasNot Called } + verify { shouldStartRateAppFlow wasNot Called } } private fun List.toMailboxState(): MailboxListState.Data = From c83647b2c0c2d36c5663131e86426ec651d12010 Mon Sep 17 00:00:00 2001 From: Marino Meneghel Date: Tue, 18 Apr 2023 14:58:37 +0200 Subject: [PATCH 2/3] Update core lib to 10.4.0 --- buildSrc/src/main/kotlin/versionsConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/versionsConfig.kt b/buildSrc/src/main/kotlin/versionsConfig.kt index b12415d1e..04a03166c 100644 --- a/buildSrc/src/main/kotlin/versionsConfig.kt +++ b/buildSrc/src/main/kotlin/versionsConfig.kt @@ -62,7 +62,7 @@ fun initVersions() { } // Proton Core -const val `Proton-core version` = "10.3.0" +const val `Proton-core version` = "10.4.0" // Test const val `aerogear version` = "1.0.0" // Released: Mar 23, 2013 From 81c29eb029a8afaa89087681271baa146eec522d Mon Sep 17 00:00:00 2001 From: Marino Meneghel Date: Tue, 18 Apr 2023 17:26:10 +0200 Subject: [PATCH 3/3] Changed build version to 3.0.14 (936) --- buildSrc/src/main/kotlin/ProtonMail.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/ProtonMail.kt b/buildSrc/src/main/kotlin/ProtonMail.kt index 93b6c91af..5af01deeb 100644 --- a/buildSrc/src/main/kotlin/ProtonMail.kt +++ b/buildSrc/src/main/kotlin/ProtonMail.kt @@ -26,7 +26,7 @@ import org.gradle.api.JavaVersion object ProtonMail { const val versionName = "3.0.14" - const val versionCode = 935 + const val versionCode = 936 const val compileSdk = 33 const val targetSdk = 31