mirror of
https://github.com/ProtonMail/android-mail.git
synced 2026-05-15 09:50:40 +00:00
Include Lumo in installed app packages, add NPS FF
MAILANDR-2635: submit/skip NPS feedback via separate edpoints
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
<package android:name="ch.protonvpn.android" />
|
||||
<package android:name="proton.android.pass" />
|
||||
<package android:name="me.proton.wallet.android" />
|
||||
<package android:name="me.proton.android.lumo" />
|
||||
</queries>
|
||||
|
||||
<application
|
||||
|
||||
+29
-8
@@ -29,23 +29,28 @@ import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import me.proton.core.featureflag.domain.entity.FeatureFlag
|
||||
import org.junit.Test
|
||||
import javax.inject.Provider
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal class ObserveNPSEligibilityTest {
|
||||
|
||||
private val observePrimaryUser = mockk<ObservePrimaryUser>()
|
||||
private val observeMailFeature = mockk<ObserveMailFeature>()
|
||||
private val npsEnabled = mockk<Provider<Boolean>>()
|
||||
|
||||
private val sut = ObserveNPSEligibility(
|
||||
observePrimaryUser,
|
||||
observeMailFeature
|
||||
)
|
||||
private val sut: ObserveNPSEligibility
|
||||
get() = ObserveNPSEligibility(
|
||||
observePrimaryUser,
|
||||
observeMailFeature,
|
||||
npsEnabled.get()
|
||||
)
|
||||
|
||||
private val user = UserSample.Primary
|
||||
|
||||
@Test
|
||||
fun `should emit false when primary user is null`() = runTest {
|
||||
every { observePrimaryUser() } returns flowOf(null)
|
||||
expectNPSEnabled(true)
|
||||
sut().test {
|
||||
assertEquals(false, awaitItem())
|
||||
awaitComplete()
|
||||
@@ -53,9 +58,20 @@ internal class ObserveNPSEligibilityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should emit false when mail feature flag is disabled`() = runTest {
|
||||
fun `should emit false when FF disabled`() = runTest {
|
||||
every { observePrimaryUser() } returns flowOf(user)
|
||||
isFFEnabled(false)
|
||||
expectNPSEnabled(false)
|
||||
sut().test {
|
||||
assertEquals(false, awaitItem())
|
||||
awaitComplete()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should emit false when per-user feature flag is disabled`() = runTest {
|
||||
every { observePrimaryUser() } returns flowOf(user)
|
||||
expectPerUserFlagEnabled(false)
|
||||
expectNPSEnabled(true)
|
||||
|
||||
sut().test {
|
||||
assertEquals(false, awaitItem())
|
||||
@@ -66,7 +82,8 @@ internal class ObserveNPSEligibilityTest {
|
||||
@Test
|
||||
fun `should emit true when feature enabled`() = runTest {
|
||||
every { observePrimaryUser() } returns flowOf(user)
|
||||
isFFEnabled(true)
|
||||
expectPerUserFlagEnabled(true)
|
||||
expectNPSEnabled(true)
|
||||
|
||||
sut().test {
|
||||
assertEquals(true, awaitItem())
|
||||
@@ -74,8 +91,12 @@ internal class ObserveNPSEligibilityTest {
|
||||
}
|
||||
}
|
||||
|
||||
private fun isFFEnabled(enabled: Boolean) {
|
||||
private fun expectPerUserFlagEnabled(enabled: Boolean) {
|
||||
every { observeMailFeature(user.userId, MailFeatureId.NPSFeedback) } returns
|
||||
flowOf(FeatureFlag.default("ff1", defaultValue = enabled))
|
||||
}
|
||||
|
||||
private fun expectNPSEnabled(value: Boolean) {
|
||||
every { npsEnabled.get() } returns value
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -29,6 +29,7 @@ import ch.protonmail.android.mailupselling.domain.annotations.DriveSpotlightEnab
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.ForceOneClickUpsellingDetailsOverride
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.HeaderUpsellSocialProofLayoutEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.HeaderUpsellVariantLayoutEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.NPSEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.OneClickUpsellingAlwaysShown
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.OneClickUpsellingTelemetryEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.SidebarUpsellingEnabled
|
||||
@@ -48,6 +49,7 @@ import ch.protonmail.android.mailupselling.domain.usecase.featureflags.AlwaysSho
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsDriveSpotlightEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsHeaderUpsellSocialProofLayoutEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsHeaderUpsellVariantLayoutEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsNPSEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsOneClickUpsellingTelemetryEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsSidebarUpsellingEnabled
|
||||
import ch.protonmail.android.mailupselling.domain.usecase.featureflags.IsSignupPaidPlanSupportEnabled
|
||||
@@ -101,6 +103,10 @@ object UpsellingModule {
|
||||
@DriveSpotlightEnabled
|
||||
fun provideDriveSpotlightEnabled(isEnabled: IsDriveSpotlightEnabled) = isEnabled(null)
|
||||
|
||||
@Provides
|
||||
@NPSEnabled
|
||||
fun provideNPSEnabled(isEnabled: IsNPSEnabled) = isEnabled(null)
|
||||
|
||||
@Provides
|
||||
@HeaderUpsellSocialProofLayoutEnabled
|
||||
fun provideUpsellSocialProofLayoutEnabled(isEnabled: IsHeaderUpsellSocialProofLayoutEnabled) = isEnabled(null)
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.mailupselling.domain.annotations
|
||||
|
||||
import javax.inject.Qualifier
|
||||
|
||||
/**
|
||||
* Indicates whether the NPS is enabled. If disabled, individual user' feature flags will not be checked further.
|
||||
*/
|
||||
@Qualifier
|
||||
annotation class NPSEnabled
|
||||
+2
-1
@@ -57,5 +57,6 @@ private val ProtonPackages = listOf(
|
||||
"me.proton.android.drive",
|
||||
"me.proton.android.calendar",
|
||||
"proton.android.pass",
|
||||
"me.proton.wallet.android"
|
||||
"me.proton.wallet.android",
|
||||
"me.proton.android.lumo"
|
||||
)
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.mailupselling.domain.usecase.featureflags
|
||||
|
||||
import me.proton.core.domain.entity.UserId
|
||||
import me.proton.core.featureflag.domain.ExperimentalProtonFeatureFlag
|
||||
import me.proton.core.featureflag.domain.FeatureFlagManager
|
||||
import me.proton.core.featureflag.domain.entity.FeatureId
|
||||
import javax.inject.Inject
|
||||
|
||||
class IsNPSEnabled @Inject constructor(
|
||||
private val featureFlagManager: FeatureFlagManager
|
||||
) {
|
||||
|
||||
@OptIn(ExperimentalProtonFeatureFlag::class)
|
||||
operator fun invoke(userId: UserId?) = featureFlagManager.getValue(userId, FeatureId(FeatureFlagId))
|
||||
|
||||
private companion object {
|
||||
|
||||
const val FeatureFlagId = "MailAndroidNpsFeedback"
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -121,7 +121,8 @@ internal class GetInstalledProtonAppsTest {
|
||||
"me.proton.android.drive" to "v2",
|
||||
"me.proton.android.calendar" to "v3",
|
||||
"proton.android.pass" to "v4",
|
||||
"me.proton.wallet.android" to "v5"
|
||||
"me.proton.wallet.android" to "v5",
|
||||
"me.proton.android.lumo" to "v6"
|
||||
)
|
||||
mockInstalled(*all.toTypedArray())
|
||||
|
||||
|
||||
+4
-1
@@ -21,6 +21,7 @@ package ch.protonmail.android.mailupselling.presentation.usecase
|
||||
import ch.protonmail.android.mailcommon.domain.MailFeatureId
|
||||
import ch.protonmail.android.mailcommon.domain.usecase.ObserveMailFeature
|
||||
import ch.protonmail.android.mailcommon.domain.usecase.ObservePrimaryUser
|
||||
import ch.protonmail.android.mailupselling.domain.annotations.DriveSpotlightEnabled
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
@@ -30,12 +31,14 @@ import javax.inject.Inject
|
||||
|
||||
class ObserveNPSEligibility @Inject constructor(
|
||||
private val observePrimaryUser: ObservePrimaryUser,
|
||||
private val observeMailFeature: ObserveMailFeature
|
||||
private val observeMailFeature: ObserveMailFeature,
|
||||
@DriveSpotlightEnabled private val driveSpotlightEnabled: Boolean
|
||||
) {
|
||||
operator fun invoke(): Flow<Boolean> = observePrimaryUser()
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { user ->
|
||||
if (user == null) return@flatMapLatest flowOf(false)
|
||||
if (!driveSpotlightEnabled) return@flatMapLatest flowOf(false)
|
||||
observeMailFeature(user.userId, MailFeatureId.NPSFeedback).map { npsFeatureFlag ->
|
||||
npsFeatureFlag.value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user