mirror of
https://github.com/ProtonMail/android-mail.git
synced 2026-05-15 09:50:40 +00:00
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:
@@ -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()
|
||||
|
||||
-2
@@ -121,5 +121,3 @@ data object ShowRatingBoosterEnabled : FeatureFlagDefinition(
|
||||
description = "Show the rating app store dialog",
|
||||
defaultValue = false
|
||||
)
|
||||
|
||||
|
||||
|
||||
+6
-3
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+109
@@ -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)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user