mirror of
https://github.com/bitwarden/android.git
synced 2026-10-23 19:43:26 -05:00
[PM-33513] feat: Add checkout callback deep link handling (#6692)
This commit is contained in:
1 parent
12c96de168
commit
4a069e9703
6 files changed
+86
No files matched your search
@@ -46,6 +46,7 @@ import com.x8bit.bitwarden.ui.platform.model.FeatureFlagsState
|
||||
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isPremiumCheckoutCallback
|
||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
@@ -333,6 +334,7 @@ class MainViewModel @Inject constructor(
|
||||
val hasGeneratorShortcut = intent.isPasswordGeneratorShortcut
|
||||
val hasVaultShortcut = intent.isMyVaultShortcut
|
||||
val hasAccountSecurityShortcut = intent.isAccountSecurityShortcut
|
||||
val hasPremiumCheckoutCallback = intent.isPremiumCheckoutCallback
|
||||
val completeRegistrationData = intent.getCompleteRegistrationDataIntentOrNull()
|
||||
val importCredentialsRequest = intent.getProviderImportCredentialsRequest()
|
||||
val credentialProviderRequest =
|
||||
@@ -394,6 +396,11 @@ class MainViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
hasPremiumCheckoutCallback -> {
|
||||
specialCircumstanceManager.specialCircumstance =
|
||||
SpecialCircumstance.PremiumCheckoutResult
|
||||
}
|
||||
|
||||
hasGeneratorShortcut -> {
|
||||
specialCircumstanceManager.specialCircumstance =
|
||||
SpecialCircumstance.GeneratorShortcut
|
||||
|
||||
+7
@@ -134,6 +134,13 @@ sealed class SpecialCircumstance : Parcelable {
|
||||
@Parcelize
|
||||
data object VerificationCodeShortcut : SpecialCircumstance()
|
||||
|
||||
/**
|
||||
* The app was launched via a premium checkout callback deep link,
|
||||
* indicating the user is returning from a Stripe checkout session.
|
||||
*/
|
||||
@Parcelize
|
||||
data object PremiumCheckoutResult : SpecialCircumstance()
|
||||
|
||||
/**
|
||||
* The app was launched to select an account to export credentials from.
|
||||
*/
|
||||
|
||||
+2
@@ -208,6 +208,7 @@ class RootNavViewModel @Inject constructor(
|
||||
|
||||
SpecialCircumstance.AccountSecurityShortcut,
|
||||
SpecialCircumstance.GeneratorShortcut,
|
||||
SpecialCircumstance.PremiumCheckoutResult,
|
||||
SpecialCircumstance.VaultShortcut,
|
||||
SpecialCircumstance.SendShortcut,
|
||||
is SpecialCircumstance.SearchShortcut,
|
||||
@@ -283,6 +284,7 @@ class RootNavViewModel @Inject constructor(
|
||||
when (specialCircumstance) {
|
||||
is SpecialCircumstance.AccountSecurityShortcut,
|
||||
is SpecialCircumstance.GeneratorShortcut,
|
||||
is SpecialCircumstance.PremiumCheckoutResult,
|
||||
is SpecialCircumstance.SearchShortcut,
|
||||
is SpecialCircumstance.SendShortcut,
|
||||
is SpecialCircumstance.ShareNewSend,
|
||||
|
||||
@@ -19,3 +19,10 @@ val Intent.isPasswordGeneratorShortcut: Boolean
|
||||
*/
|
||||
val Intent.isAccountSecurityShortcut: Boolean
|
||||
get() = dataString?.equals("bitwarden://settings/account_security") == true
|
||||
|
||||
/**
|
||||
* Returns `true` if the [Intent] is a deep link callback from a premium
|
||||
* checkout session, `false` otherwise.
|
||||
*/
|
||||
val Intent.isPremiumCheckoutCallback: Boolean
|
||||
get() = dataString?.equals("bitwarden://premium-upgrade-callback") == true
|
||||
@@ -71,6 +71,7 @@ import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLang
|
||||
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
||||
import com.x8bit.bitwarden.ui.platform.util.isPremiumCheckoutCallback
|
||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
@@ -200,6 +201,7 @@ class MainViewModelTest : BaseViewModelTest() {
|
||||
Intent::isMyVaultShortcut,
|
||||
Intent::isPasswordGeneratorShortcut,
|
||||
Intent::isAccountSecurityShortcut,
|
||||
Intent::isPremiumCheckoutCallback,
|
||||
)
|
||||
mockkObject(
|
||||
ProviderCreateCredentialRequest.Companion,
|
||||
@@ -231,6 +233,7 @@ class MainViewModelTest : BaseViewModelTest() {
|
||||
Intent::isMyVaultShortcut,
|
||||
Intent::isPasswordGeneratorShortcut,
|
||||
Intent::isAccountSecurityShortcut,
|
||||
Intent::isPremiumCheckoutCallback,
|
||||
)
|
||||
unmockkObject(
|
||||
ProviderCreateCredentialRequest.Companion,
|
||||
@@ -859,6 +862,40 @@ class MainViewModelTest : BaseViewModelTest() {
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on ReceiveFirstIntent with premium checkout callback should set special circumstance to PremiumCheckoutResult`() {
|
||||
val viewModel = createViewModel()
|
||||
val mockIntent = createMockIntent(
|
||||
mockIsPremiumCheckoutCallback = true,
|
||||
)
|
||||
|
||||
viewModel.trySendAction(
|
||||
MainAction.ReceiveFirstIntent(intent = mockIntent),
|
||||
)
|
||||
assertEquals(
|
||||
SpecialCircumstance.PremiumCheckoutResult,
|
||||
specialCircumstanceManager.specialCircumstance,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on ReceiveNewIntent with premium checkout callback should set special circumstance to PremiumCheckoutResult`() {
|
||||
val viewModel = createViewModel()
|
||||
val mockIntent = createMockIntent(
|
||||
mockIsPremiumCheckoutCallback = true,
|
||||
)
|
||||
|
||||
viewModel.trySendAction(
|
||||
MainAction.ReceiveNewIntent(intent = mockIntent),
|
||||
)
|
||||
assertEquals(
|
||||
SpecialCircumstance.PremiumCheckoutResult,
|
||||
specialCircumstanceManager.specialCircumstance,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `on ReceiveNewIntent with a password generator deeplink data should set the special circumstance to GeneratorShortcut`() {
|
||||
@@ -1264,6 +1301,7 @@ private fun createMockIntent(
|
||||
mockIsMyVaultShortcut: Boolean = false,
|
||||
mockIsPasswordGeneratorShortcut: Boolean = false,
|
||||
mockIsAccountSecurityShortcut: Boolean = false,
|
||||
mockIsPremiumCheckoutCallback: Boolean = false,
|
||||
mockIsAddTotpLoginItemFromAuthenticator: Boolean = false,
|
||||
mockProviderImportCredentialsRequest: ProviderImportCredentialsRequest? = null,
|
||||
): Intent = mockk<Intent> {
|
||||
@@ -1275,6 +1313,7 @@ private fun createMockIntent(
|
||||
every { isMyVaultShortcut } returns mockIsMyVaultShortcut
|
||||
every { isPasswordGeneratorShortcut } returns mockIsPasswordGeneratorShortcut
|
||||
every { isAccountSecurityShortcut } returns mockIsAccountSecurityShortcut
|
||||
every { isPremiumCheckoutCallback } returns mockIsPremiumCheckoutCallback
|
||||
every { isAddTotpLoginItemFromAuthenticator() } returns mockIsAddTotpLoginItemFromAuthenticator
|
||||
every { getProviderImportCredentialsRequest() } returns mockProviderImportCredentialsRequest
|
||||
}
|
||||
|
||||
@@ -56,4 +56,28 @@ class ShortcutUtilsTest {
|
||||
}
|
||||
assertFalse(mockIntent.isPasswordGeneratorShortcut)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isPremiumCheckoutCallback should return true when dataString is checkout callback`() {
|
||||
val mockIntent = mockk<Intent> {
|
||||
every { dataString } returns "bitwarden://premium-upgrade-callback"
|
||||
}
|
||||
assertTrue(mockIntent.isPremiumCheckoutCallback)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isPremiumCheckoutCallback should return false when dataString is not checkout callback`() {
|
||||
val mockIntent = mockk<Intent> {
|
||||
every { dataString } returns "bitwarden://some_other_callback"
|
||||
}
|
||||
assertFalse(mockIntent.isPremiumCheckoutCallback)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isPremiumCheckoutCallback should return false when dataString is null`() {
|
||||
val mockIntent = mockk<Intent> {
|
||||
every { dataString } returns null
|
||||
}
|
||||
assertFalse(mockIntent.isPremiumCheckoutCallback)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user