mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Fix gifting subscription flow
This commit is contained in:
parent
498cf32162
commit
1cba3d3068
8 changed files with 118 additions and 42 deletions
|
|
@ -848,8 +848,12 @@
|
|||
<string name="gift_one_get_one_description">Gift a sub and get a sub free event going on now!</string>
|
||||
<string name="gift_title">Who would you like to gift to?</string>
|
||||
<string name="gift_one_get_one">Gift one, Get one!</string>
|
||||
<string name="gift_one_get_one_detailed_description">While this promotion is active, you’ll receive a matching subscription automatically after sending your gift.</string>
|
||||
<string name="gift_one_get_one_detailed_description">While this promotion is active, you’ll receive a matching subscription automatically after sending your gift.</string>
|
||||
<string name="gift_subscription_subtitle">Choose the subscription you’d like to gift below! This purchase won’t automatically renew.</string>
|
||||
<string name="send_gift">Send Gift</string>
|
||||
<string name="server">Server</string>
|
||||
<string name="gift_confirmation_title">Your gift was sent!</string>
|
||||
<string name="gift_confirmation_text_g1g1">Your gifted subscription was sent and your subscription applied to your account.</string>
|
||||
<string name="gift_confirmation_text">Your gifted subscription was sent and your subscription applied to your account.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ abstract class HabiticaBaseApplication : MultiDexApplication() {
|
|||
}
|
||||
|
||||
fun checkUserAuthentication(context: Context, hostConfig: HostConfig?): Boolean {
|
||||
if (hostConfig == null || hostConfig.api == null || hostConfig.api == "" || hostConfig.user == null || hostConfig.user == "") {
|
||||
if (hostConfig?.api == null || hostConfig.api == "" || hostConfig.user == "") {
|
||||
startActivity(IntroActivity::class.java, context)
|
||||
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.habitrpg.android.habitica;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent;
|
||||
import com.habitrpg.android.habitica.events.UserSubscribedEvent;
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
|
||||
import com.habitrpg.android.habitica.models.IAPGift;
|
||||
|
|
@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.models.PurchaseValidationRequest;
|
|||
import com.habitrpg.android.habitica.models.SubscriptionValidationRequest;
|
||||
import com.habitrpg.android.habitica.models.Transaction;
|
||||
import com.habitrpg.android.habitica.models.responses.ErrorResponse;
|
||||
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
|
||||
import com.playseeds.android.sdk.Seeds;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
|
@ -30,6 +31,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
/**
|
||||
|
|
@ -79,7 +81,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
|
|||
purchasedOrderList.add(purchase.orderId);
|
||||
|
||||
requestListener.onSuccess(verifiedPurchases);
|
||||
|
||||
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
|
||||
|
||||
//TODO: find way to get $ price automatically.
|
||||
if (purchase.sku.equals(PurchaseTypes.Purchase4Gems)) {
|
||||
|
|
@ -100,6 +102,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
|
|||
purchasedOrderList.add(purchase.orderId);
|
||||
|
||||
requestListener.onSuccess(verifiedPurchases);
|
||||
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -124,6 +127,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
|
|||
pendingGifts.remove(purchase.sku);
|
||||
}
|
||||
requestListener.onSuccess(verifiedPurchases);
|
||||
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
|
||||
}, throwable -> {
|
||||
if (throwable.getClass().equals(retrofit2.adapter.rxjava2.HttpException.class)) {
|
||||
HttpException error = (HttpException)throwable;
|
||||
|
|
@ -133,6 +137,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
|
|||
purchasedOrderList.add(purchase.orderId);
|
||||
|
||||
requestListener.onSuccess(verifiedPurchases);
|
||||
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
|
|||
}
|
||||
|
||||
override fun hasAuthenticationKeys(): Boolean {
|
||||
return this.hostConfig.user != null
|
||||
return this.hostConfig.user.isNotEmpty() && hostConfig.api.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun showConnectionProblemDialog(resourceMessageString: Int) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
import org.solovyev.android.checkout.Purchase
|
||||
|
||||
class ConsumablePurchasedEvent(internal val purchase: Purchase)
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.MotionEvent
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
|
|
@ -12,12 +10,10 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent
|
||||
import com.instabug.library.InstabugTrackingDelegate
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import com.instabug.library.InstabugTrackingDelegate
|
||||
import android.view.MotionEvent
|
||||
|
||||
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
|
|
@ -23,6 +24,7 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
|
|||
import com.playseeds.android.sdk.Seeds
|
||||
import com.playseeds.android.sdk.inappmessaging.InAppMessageListener
|
||||
import io.reactivex.functions.Consumer
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.solovyev.android.checkout.*
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
|
@ -38,6 +40,7 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
|||
internal val viewPager: androidx.viewpager.widget.ViewPager by bindView(R.id.viewPager)
|
||||
|
||||
internal var fragments: MutableList<CheckoutFragment> = ArrayList()
|
||||
var isActive = false
|
||||
var activityCheckout: ActivityCheckout? = null
|
||||
private set
|
||||
private var billingRequests: BillingRequests? = null
|
||||
|
|
@ -91,28 +94,15 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
|||
}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setupCheckout()
|
||||
|
||||
activityCheckout?.destroyPurchaseFlow()
|
||||
|
||||
activityCheckout?.createPurchaseFlow(object : RequestListener<Purchase> {
|
||||
override fun onSuccess(purchase: Purchase) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
|
||||
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
|
||||
override fun onSuccess(o: Any) {
|
||||
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
if (purchase.sku == PurchaseTypes.Purchase84Gems) {
|
||||
this@GemPurchaseActivity.showSeedsPromo(getString(R.string.seeds_interstitial_sharing), "store")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
|
|
@ -140,9 +130,19 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
|||
})
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
activityCheckout?.stop()
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
isActive = true
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
isActive = false
|
||||
}
|
||||
|
||||
public override fun onStop() {
|
||||
activityCheckout?.stop()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
|
@ -270,6 +270,13 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
|||
})
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public fun onConsumablePurchased(event: ConsumablePurchasedEvent) {
|
||||
if (isActive) {
|
||||
consumePurchase(event.purchase)
|
||||
}
|
||||
}
|
||||
|
||||
interface CheckoutFragment {
|
||||
|
||||
fun setupCheckout()
|
||||
|
|
@ -279,4 +286,18 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
|
|||
fun setBillingRequests(billingRequests: BillingRequests?)
|
||||
}
|
||||
|
||||
private fun consumePurchase(purchase: Purchase) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
|
||||
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
|
||||
|
||||
override fun onSuccess(result: Any) {
|
||||
|
||||
}
|
||||
|
||||
override fun onError(response: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.AttributeSet
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.view.isVisible
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
|
|
@ -14,6 +16,7 @@ import com.habitrpg.android.habitica.HabiticaPurchaseVerifier
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.AppComponent
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent
|
||||
import com.habitrpg.android.habitica.extensions.notNull
|
||||
import com.habitrpg.android.habitica.helpers.PurchaseTypes
|
||||
import com.habitrpg.android.habitica.helpers.RemoteConfigManager
|
||||
|
|
@ -25,11 +28,9 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
|
|||
import com.habitrpg.android.habitica.ui.views.social.UsernameLabel
|
||||
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView
|
||||
import io.reactivex.functions.Consumer
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.solovyev.android.checkout.*
|
||||
import javax.inject.Inject
|
||||
import android.content.Intent
|
||||
|
||||
|
||||
|
||||
|
||||
class GiftIAPActivity: BaseActivity() {
|
||||
|
|
@ -100,9 +101,8 @@ class GiftIAPActivity: BaseActivity() {
|
|||
}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setupCheckout()
|
||||
|
||||
activityCheckout?.destroyPurchaseFlow()
|
||||
|
|
@ -135,6 +135,10 @@ class GiftIAPActivity: BaseActivity() {
|
|||
|
||||
override fun onReady(billingRequests: BillingRequests, s: String, b: Boolean) {}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
this.subscription1MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription1MonthNoRenew) })
|
||||
this.subscription3MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription3MonthNoRenew) })
|
||||
|
|
@ -142,17 +146,23 @@ class GiftIAPActivity: BaseActivity() {
|
|||
this.subscription12MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription12MonthNoRenew) })
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
override fun onStop() {
|
||||
activityCheckout?.stop()
|
||||
super.onPause()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
activityCheckout?.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
finish()
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun updateButtonLabel(sku: Sku, price: String, subscriptions: Inventory.Product) {
|
||||
val matchingView = buttonForSku(sku)
|
||||
|
|
@ -197,9 +207,8 @@ class GiftIAPActivity: BaseActivity() {
|
|||
}
|
||||
|
||||
private fun selectSubscription(sku: Sku) {
|
||||
if (this.selectedSubscriptionSku != null) {
|
||||
val oldButton = buttonForSku(this.selectedSubscriptionSku)
|
||||
oldButton?.setIsPurchased(false)
|
||||
for (thisSku in skus) {
|
||||
buttonForSku(sku)?.setIsPurchased(false)
|
||||
}
|
||||
this.selectedSubscriptionSku = sku
|
||||
val subscriptionOptionButton = buttonForSku(this.selectedSubscriptionSku)
|
||||
|
|
@ -229,4 +238,40 @@ class GiftIAPActivity: BaseActivity() {
|
|||
billingRequests?.purchase(ProductTypes.IN_APP, sku.id.code, null, it.purchaseFlow)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public fun onConsumablePurchased(event: ConsumablePurchasedEvent) {
|
||||
consumePurchase(event.purchase)
|
||||
displayConfirmationDialog()
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun displayConfirmationDialog() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert)
|
||||
} else {
|
||||
AlertDialog.Builder(this)
|
||||
}
|
||||
.setTitle(R.string.gift_confirmation_title)
|
||||
.setMessage(if (remoteConfigManager.enableGiftOneGetOne()) R.string.gift_confirmation_text_g1g1 else R.string.gift_confirmation_text)
|
||||
.setPositiveButton(android.R.string.ok) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun consumePurchase(purchase: Purchase) {
|
||||
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
|
||||
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
|
||||
|
||||
override fun onSuccess(result: Any) {
|
||||
}
|
||||
|
||||
override fun onError(response: Int, e: Exception) {
|
||||
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue