Wire in Ratings booster to FeatureFlag

ET-5166

# Conflicts:
#	mail-featureflags/domain/src/main/kotlin/ch/protonmail/android/mailfeatureflags/domain/model/FeatureFlagDefinitionItems.kt
#	mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxViewModel.kt
#	mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/usecase/ShouldShowRatingBooster.kt
#	mail-session/domain/src/main/kotlin/ch/protonmail/android/mailsession/domain/wrapper/MailUserSessionWrapper.kt
This commit is contained in:
Seren
2025-12-04 14:49:22 +01:00
committed by Seren Matthews
parent 8d468dc5bd
commit 435754bc7a
6 changed files with 117 additions and 10 deletions
@@ -118,9 +118,6 @@ class MainActivity : AppCompatActivity() {
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
startActivity(intent)
}
val intent = Intent(this, LockScreenActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
},
launchRatingBooster = {
handleLaunchInAppReview()
@@ -121,5 +121,3 @@ data object ShowRatingBoosterEnabled : FeatureFlagDefinition(
description = "Show the rating app store dialog",
defaultValue = false
)
@@ -147,6 +147,7 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
@@ -336,12 +337,14 @@ class MailboxViewModel @Inject constructor(
primaryUserId.flatMapLatest { userId ->
shouldShowRatingBooster(userId)
}.onEach { shouldShowRatingBooster ->
if (shouldShowRatingBooster) {
}.distinctUntilChanged()
.filter { it }
.onEach { shouldShowRatingBooster ->
recordRatingBoosterTriggered()
emitNewStateFrom(MailboxEvent.ShowRatingBooster)
}
}.launchIn(viewModelScope)
.launchIn(viewModelScope)
}
override fun onCleared() {
@@ -32,7 +32,7 @@ class ShouldShowRatingBooster @Inject constructor(
operator fun invoke(userId: UserId): Flow<Boolean> {
return inMemoryMailboxRepository.observeScreenViewCount().map { screenViewCount ->
showRatingBooster.get() && screenViewCount >= SCREEN_VIEW_COUNT_THRESHOLD
showRatingBooster.get() && screenViewCount == SCREEN_VIEW_COUNT_THRESHOLD
}
}
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2025 Proton Technologies AG
* This file is part of Proton Technologies AG and Proton Mail.
*
* Proton Mail 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.
*
* Proton Mail 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 Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.mailmailbox.presentation.usecase
import ch.protonmail.android.mailfeatureflags.domain.model.FeatureFlag
import ch.protonmail.android.mailmailbox.domain.repository.InMemoryMailboxRepository
import ch.protonmail.android.mailmailbox.presentation.mailbox.usecase.ShouldShowRatingBooster
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
import me.proton.core.domain.entity.UserId
import org.junit.Before
import kotlin.test.Test
import kotlin.test.assertEquals
class ShouldShowRatingBoosterTest {
private val inMemoryMailboxRepository: InMemoryMailboxRepository = mockk()
private val showRatingBooster: FeatureFlag<Boolean> = mockk()
private lateinit var shouldShowRatingBooster: ShouldShowRatingBooster
private val testUserId = UserId("user-123")
private val threshold = ShouldShowRatingBooster.SCREEN_VIEW_COUNT_THRESHOLD // 2
@Before
fun setUp() {
shouldShowRatingBooster = ShouldShowRatingBooster(
inMemoryMailboxRepository,
showRatingBooster
)
}
@Test
fun `when flag is enabled and screen count is below threshold then show is false`() = runTest {
// Given
val screenViewCount = threshold - 1 // 1
every { inMemoryMailboxRepository.observeScreenViewCount() } returns flowOf(screenViewCount)
coEvery { showRatingBooster.get() } returns true
// When
val result = shouldShowRatingBooster(testUserId).toList(destination = mutableListOf())
// Then
assertEquals(listOf(false), result)
}
@Test
fun `when flag is enabled and screen count is at threshold then show is true`() = runTest {
// Given
val screenViewCount = threshold // 2
every { inMemoryMailboxRepository.observeScreenViewCount() } returns flowOf(screenViewCount)
coEvery { showRatingBooster.get() } returns true
// When
val result = shouldShowRatingBooster(testUserId).toList(destination = mutableListOf())
// Then
assertEquals(listOf(true), result)
}
@Test
fun `when flag is disabled and screen count is above threshold then show is false`() = runTest {
// Given
val screenViewCount = threshold + 1 // 3
every { inMemoryMailboxRepository.observeScreenViewCount() } returns flowOf(screenViewCount)
coEvery { showRatingBooster.get() } returns false
// When
val result = shouldShowRatingBooster(testUserId).toList(destination = mutableListOf())
// Then
assertEquals(listOf(false), result)
}
@Test
fun `when flow emits multiple counts then the output flow correctly maps each value`() = runTest {
// Given
val screenViewCounts = flowOf(1, 2, 0, 2)
every { inMemoryMailboxRepository.observeScreenViewCount() } returns screenViewCounts
coEvery { showRatingBooster.get() } returns true
// When
val result = shouldShowRatingBooster(testUserId).toList(destination = mutableListOf())
// Then
val expected = listOf(false, true, false, true)
assertEquals(expected, result)
}
}
@@ -94,7 +94,7 @@ class MailUserSessionWrapper(private val userSession: MailUserSession) {
when (val result = userSession.overrideUserFeatureFlag(flagName = flagName, newValue = newValue)) {
is MailUserSessionOverrideUserFeatureFlagResult.Ok -> Unit.right()
is MailUserSessionOverrideUserFeatureFlagResult.Error -> {
Timber.e("Rating booster UserSession:: Unable set set feature flag ${result.v1}")
Timber.e("MailUserSession FeatureFlag Override:: Unable set set feature flag ${result.v1}")
result.v1.toDataError().left()
}
}