diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 5baaf583e..9f30c1093 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -848,8 +848,12 @@
Gift a sub and get a sub free event going on now!
Who would you like to gift to?
Gift one, Get one!
- While this promotion is active, you’ll receive a matching subscription automatically after sending your gift.
+ While this promotion is active, you’ll receive a matching subscription automatically after sending your gift.
Choose the subscription you’d like to gift below! This purchase won’t automatically renew.
Send Gift
Server
+ Your gift was sent!
+ Your gifted subscription was sent and your subscription applied to your account.
+ Your gifted subscription was sent and your subscription applied to your account.
+
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.kt
index c80872dd5..97fa85347 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaBaseApplication.kt
@@ -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
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java
index 1d70a6c4f..19b228300 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java
@@ -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;
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
index 42598ec2b..01080814c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
@@ -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) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/events/ConsumablePurchasedEvent.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/events/ConsumablePurchasedEvent.kt
new file mode 100644
index 000000000..b8ed8dd0a
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/events/ConsumablePurchasedEvent.kt
@@ -0,0 +1,5 @@
+package com.habitrpg.android.habitica.events
+
+import org.solovyev.android.checkout.Purchase
+
+class ConsumablePurchasedEvent(internal val purchase: Purchase)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
index 44e70bd7e..78084dc7d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt
@@ -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() {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GemPurchaseActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GemPurchaseActivity.kt
index c71cbcc39..da8e9328a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GemPurchaseActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GemPurchaseActivity.kt
@@ -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 = 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 {
override fun onSuccess(purchase: Purchase) {
- if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
- billingRequests?.consume(purchase.token, object : RequestListener {
- 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 {
+
+ override fun onSuccess(result: Any) {
+
+ }
+
+ override fun onError(response: Int, e: Exception) {
+ crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
+ }
+ })
+ }
+ }
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt
index 7badf3b47..3ae359750 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt
@@ -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 {
+
+ override fun onSuccess(result: Any) {
+ }
+
+ override fun onError(response: Int, e: Exception) {
+ crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
+ }
+ })
+ }
+ }
}
\ No newline at end of file