Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add restore option #3918

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ interface SubscriptionsManager {
*/
suspend fun getAccessToken(): AccessToken

/**
* Returns [true] if the user has an active subscription and [false] otherwise
*/
suspend fun hasSubscription(): Boolean

/**
* Flow to know if a user is signed in or not
*/
Expand All @@ -93,7 +98,7 @@ interface SubscriptionsManager {
val hasSubscription: Flow<Boolean>

/**
* Flow to know if a user is signed in or not
* Flow to know the state of the current purchase
*/
val currentPurchaseState: Flow<CurrentPurchase>

Expand Down Expand Up @@ -173,10 +178,11 @@ class RealSubscriptionsManager @Inject constructor(
_hasSubscription.emit(hasSubscription)
}

private suspend fun hasSubscription(): Boolean {
override suspend fun hasSubscription(): Boolean {
return when (val result = getSubscriptionData()) {
is Success -> {
val isSubscribed = result.entitlements.isNotEmpty()
_hasSubscription.emit(isSubscribed)
isSubscribed
}
is Failure -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,23 @@ class SubscriptionWebViewViewModel @Inject constructor(
"backToSettings" -> backToSettings()
"getSubscriptionOptions" -> id?.let { getSubscriptionOptions(featureName, method, it) }
"subscriptionSelected" -> subscriptionSelected(data)
"activateSubscription" -> activateOnAnotherDevice()
"activateSubscription" -> activateSubscription()
else -> {
// NOOP
}
}
}

private fun activateSubscription() {
viewModelScope.launch(dispatcherProvider.io()) {
if (subscriptionsManager.hasSubscription()) {
activateOnAnotherDevice()
} else {
recoverSubscription()
}
}
}

private fun subscriptionSelected(data: JSONObject?) {
viewModelScope.launch(dispatcherProvider.io()) {
val id = runCatching { data?.getString("id") }.getOrNull()
Expand Down Expand Up @@ -159,6 +169,12 @@ class SubscriptionWebViewViewModel @Inject constructor(
}
}

private fun recoverSubscription() {
viewModelScope.launch {
command.send(RestoreSubscription)
}
}

private fun activateOnAnotherDevice() {
viewModelScope.launch {
command.send(ActivateOnAnotherDevice)
Expand Down Expand Up @@ -198,6 +214,7 @@ class SubscriptionWebViewViewModel @Inject constructor(
data class SendResponseToJs(val data: JsCallbackData) : Command()
data class SubscriptionSelected(val id: String) : Command()
data object ActivateOnAnotherDevice : Command()
data object RestoreSubscription : Command()
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ import com.duckduckgo.navigation.api.getActivityParams
import com.duckduckgo.subscriptions.impl.R.string
import com.duckduckgo.subscriptions.impl.databinding.ActivitySubscriptionsWebviewBinding
import com.duckduckgo.subscriptions.impl.ui.AddDeviceActivity.Companion.AddDeviceScreenWithEmptyParams
import com.duckduckgo.subscriptions.impl.ui.RestoreSubscriptionActivity.Companion.RestoreSubscriptionScreenWithEmptyParams
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.ActivateOnAnotherDevice
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.BackToSettings
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.RestoreSubscription
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.SendResponseToJs
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.SubscriptionSelected
import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.PurchaseStateView
Expand Down Expand Up @@ -141,6 +143,7 @@ class SubscriptionsWebViewActivity : DuckDuckGoActivity() {
is SendResponseToJs -> sendResponseToJs(command.data)
is SubscriptionSelected -> selectSubscription(command.id)
is ActivateOnAnotherDevice -> activateOnAnotherDevice()
is RestoreSubscription -> restoreSubscription()
}
}

Expand Down Expand Up @@ -234,6 +237,10 @@ class SubscriptionsWebViewActivity : DuckDuckGoActivity() {
globalActivityStarter.start(this, AddDeviceScreenWithEmptyParams)
}

private fun restoreSubscription() {
globalActivityStarter.start(this, RestoreSubscriptionScreenWithEmptyParams)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,23 @@ class SubscriptionWebViewViewModelTest {
}

@Test
fun whenActivateSubscriptionThenCommandSent() = runTest {
fun whenActivateSubscriptionAndSubscriptionActiveThenCommandSent() = runTest {
whenever(subscriptionsManager.hasSubscription()).thenReturn(true)
viewModel.commands().test {
viewModel.processJsCallbackMessage("test", "activateSubscription", null, null)
assertTrue(awaitItem() is Command.ActivateOnAnotherDevice)
}
}

@Test
fun whenActivateSubscriptionAndSubscriptionInactiveThenCommandSent() = runTest {
whenever(subscriptionsManager.hasSubscription()).thenReturn(false)
viewModel.commands().test {
viewModel.processJsCallbackMessage("test", "activateSubscription", null, null)
assertTrue(awaitItem() is Command.RestoreSubscription)
}
}

private fun getSubscriptionOfferDetails(planId: String): SubscriptionOfferDetails {
val subscriptionOfferDetails: SubscriptionOfferDetails = mock()
whenever(subscriptionOfferDetails.basePlanId).thenReturn(planId)
Expand Down
Loading