Add promo for subscribing to gem purchase page

This commit is contained in:
Phillip Thelen 2019-09-26 14:17:18 +02:00
parent 8cc46fb860
commit bbd5684950
16 changed files with 308 additions and 128 deletions

View file

@ -6,125 +6,135 @@
android:scrollbarSize="3dp"
android:scrollbarThumbVertical="@color/scrollbarThumb"
android:scrollbars="vertical">
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<TextView
android:layout_width="match_parent"
android:orientation="vertical">
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/gem_purchase_subtitle"
android:gravity="center"
android:textStyle="normal|bold"
android:textColor="?colorPrimary"
android:textSize="16sp"
android:lineSpacingExtra="4dp"
android:layout_marginTop="23dp"
android:layout_marginBottom="12dp"/>
android:padding="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/gem_purchase_subtitle"
android:gravity="center"
android:textStyle="normal|bold"
android:textColor="?colorPrimary"
android:textSize="16sp"
android:lineSpacingExtra="4dp"
android:layout_marginTop="23dp"
android:layout_marginBottom="12dp"/>
<TextView
android:text="@string/gem_purchase_listitem1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/no_billing_gems"
android:paddingTop="50dp"
android:paddingBottom="10dp"
android:visibility="gone" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/visit_habitica_website"
android:layout_marginBottom="50dp"
style="@style/HabiticaButton.Purple"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:text="@string/gem_purchase_listitem1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:text="@string/gem_purchase_listitem4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/GemPurchaseListItem"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/no_billing_gems"
android:paddingTop="50dp"
android:paddingBottom="10dp"
android:visibility="gone" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/visit_habitica_website"
android:layout_marginBottom="50dp"
style="@style/HabiticaButton.Purple"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_4_view"
android:layout_width="0dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="4"
app:gemDrawable="@drawable/gems_4"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
/>
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_21_view"
android:layout_width="0dp"
android:orientation="horizontal"
android:layout_marginBottom="16dp">
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_4_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="4"
app:gemDrawable="@drawable/gems_4"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
/>
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_21_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="21"
app:gemDrawable="@drawable/gems_21" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="21"
app:gemDrawable="@drawable/gems_21" />
android:orientation="horizontal"
android:dividerPadding="16dp"
android:showDividers="middle"
android:divider="@android:color/white">
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_42_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="42"
app:gemDrawable="@drawable/gems_42"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp" />
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_84_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="84"
app:gemDrawable="@drawable/gems_84" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
<TextView android:id="@+id/supportTextView"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:dividerPadding="16dp"
android:showDividers="middle"
android:divider="@android:color/white">
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_42_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="42"
app:gemDrawable="@drawable/gems_42"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp" />
<com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
android:id="@+id/gems_84_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:gemAmount="84"
app:gemDrawable="@drawable/gems_84" />
</LinearLayout>
android:layout_width="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="20dp"
android:text="@string/gem_purchase_title"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:textColor="@color/blue_10"
android:textSize="14sp"
android:lineSpacingExtra="4dp" />
</LinearLayout>
<TextView android:id="@+id/supportTextView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="20dp"
android:text="@string/gem_purchase_title"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:textColor="@color/blue_10"
android:textSize="14sp"
android:lineSpacingExtra="4dp" />
<com.habitrpg.android.habitica.ui.views.promo.SubscriptionBuyGemsPromoView
android:id="@+id/subscription_promo"
android:layout_width="match_parent"
android:layout_height="139dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:parentTag="android.widget.RelativeLayout"
android:background="@color/blue_50">
<LinearLayout
android:id="@+id/contentWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="vertical"
android:gravity="center"
android:paddingStart="@dimen/spacing_large"
android:paddingEnd="@dimen/spacing_large"
>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/promo_subscription_buy_gems_prompt"
android:textColor="@color/white"
style="@style/Subheader1"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:minWidth="100dp"
android:text="@string/subscribe"
android:textAllCaps="false"
android:textColor="@color/white"
android:background="@drawable/white_rounded_border"
android:elevation="0dp"
android:shadowColor="@color/transparent"
android:layout_marginTop="19dp"/>
</LinearLayout>
</merge>

View file

@ -845,4 +845,5 @@
<string name="search">Search</string>
<string name="search_hint">Search tasks</string>
<string name="preference_push_party_activity">Party Activity</string>
<string name="promo_subscription_buy_gems_prompt">Want to buy gems with gold?</string>
</resources>

View file

@ -27,7 +27,7 @@ class NotificationOpenHandler {
}
private fun openSubscriptionScreen() {
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true)))
}
private fun openPrivateMessageScreen(userID: String?) {

View file

@ -219,4 +219,16 @@ open class User : RealmObject(), Avatar, VersionedObject {
fun hasParty(): Boolean {
return this.party?.id?.length ?: 0 > 0
}
val isSubscribed: Boolean
get() {
val plan = purchased?.plan
var isSubscribed = false
if (plan != null) {
if (plan.isActive) {
isSubscribed = true
}
}
return isSubscribed
}
}

View file

@ -8,6 +8,7 @@ import android.os.Build
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.events.BoughtGemsEvent
@ -102,7 +103,7 @@ class AvatarWithBarsViewModel(private val context: Context, view: View, userRepo
}
currencyView.setOnClickListener {
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
}
avatarView.setOnClickListener {
MainNavigationController.navigate(R.id.avatarOverviewFragment)

View file

@ -63,10 +63,17 @@ class GemPurchaseActivity : BaseActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.setTitle(R.string.gem_purchase_toolbartitle)
viewPager.currentItem = 0
setViewPagerAdapter()
viewPager.currentItem = if (intent.extras?.containsKey("openSubscription") == true) {
if (intent.extras?.getBoolean("openSubscription") == false) {
1
} else {
0
}
} else {
0
}
}
override fun onStart() {

View file

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import com.facebook.drawee.view.SimpleDraweeView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.helpers.MainNavigationController
@ -13,8 +14,8 @@ import com.habitrpg.android.habitica.models.inventory.Customization
import com.habitrpg.android.habitica.models.inventory.CustomizationSet
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.subjects.PublishSubject
@ -176,7 +177,7 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
val dialog = HabiticaAlertDialog(itemView.context)
dialog.addButton(R.string.purchase_button, true) { _, _ ->
if (customization?.price ?: 0 > gemBalance) {
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
return@addButton
}
@ -232,7 +233,7 @@ class CustomizationRecyclerViewAdapter : androidx.recyclerview.widget.RecyclerVi
val dialog = HabiticaAlertDialog(context)
dialog.addButton(R.string.purchase_button, true) { _, _ ->
if (set?.price ?: 0 > gemBalance) {
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
return@addButton
}
set?.customizations = ArrayList()

View file

@ -8,13 +8,17 @@ import android.view.ViewGroup
import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.helpers.PurchaseTypes
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
import com.habitrpg.android.habitica.ui.GemPurchaseOptionsView
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.promo.SubscriptionBuyGemsPromoView
import io.reactivex.functions.Consumer
import org.solovyev.android.checkout.BillingRequests
import org.solovyev.android.checkout.Inventory
import org.solovyev.android.checkout.ProductTypes
@ -26,10 +30,13 @@ class GemsPurchaseFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
private val gems21View: GemPurchaseOptionsView? by bindView(R.id.gems_21_view)
private val gems42View: GemPurchaseOptionsView? by bindView(R.id.gems_42_view)
private val gems84View: GemPurchaseOptionsView? by bindView(R.id.gems_84_view)
private val subscriptionPromoView: SubscriptionBuyGemsPromoView? by bindView(R.id.subscription_promo)
private val supportTextView: TextView? by bindView(R.id.supportTextView)
@Inject
lateinit var crashlyticsProxy: CrashlyticsProxy
@Inject
lateinit var userRepository: UserRepository
private var listener: GemPurchaseActivity? = null
private var billingRequests: BillingRequests? = null
@ -56,6 +63,10 @@ class GemsPurchaseFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
val heartDrawable = BitmapDrawable(resources, HabiticaIconsHelper.imageOfHeartLarge())
supportTextView?.setCompoundDrawables(null, heartDrawable, null, null)
compositeSubscription.add(userRepository.getUser().subscribe(Consumer {
subscriptionPromoView?.visibility = if (it.isSubscribed) View.GONE else View.VISIBLE
}, RxErrorHandler.handleEmptyError()))
}
override fun setupCheckout() {

View file

@ -241,13 +241,7 @@ class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
private fun updateSubscriptionInfo() {
if (user != null) {
val plan = user?.purchased?.plan
var isSubscribed = false
if (plan != null) {
if (plan.isActive) {
isSubscribed = true
}
}
val isSubscribed = user?.isSubscribed ?: false
if (this.subscriptionDetailsView == null) {
return
@ -255,7 +249,7 @@ class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
if (isSubscribed) {
this.subscriptionDetailsView?.visibility = View.VISIBLE
plan?.let { this.subscriptionDetailsView?.setPlan(it) }
user?.purchased?.plan?.let { this.subscriptionDetailsView?.setPlan(it) }
this.subscribeBenefitsTitle?.setText(R.string.subscribe_prompt_thanks)
this.subscriptionOptions?.visibility = View.GONE
} else {

View file

@ -8,6 +8,7 @@ import android.os.Bundle
import android.text.InputType
import android.widget.EditText
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.preference.Preference
import com.google.android.material.textfield.TextInputLayout
import com.habitrpg.android.habitica.HabiticaBaseApplication
@ -80,7 +81,7 @@ class AuthenticationPreferenceFragment: BasePreferencesFragment() {
showSubscriptionStatusDialog()
return super.onPreferenceTreeClick(preference)
}
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true)))
}
"reset_account" -> showAccountResetConfirmation()
"delete_account" -> showAccountDeleteConfirmation()

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.ui.views.insufficientCurrency
import android.content.Context
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.addCloseButton
import com.habitrpg.android.habitica.helpers.MainNavigationController
@ -17,7 +18,7 @@ class InsufficientGemsDialog(context: Context) : InsufficientCurrencyDialog(cont
imageView.setImageResource(R.drawable.gems_84)
textView.setText(R.string.insufficientGems)
addButton(R.string.purchase_gems, true) { _, _ -> MainNavigationController.navigate(R.id.gemPurchaseActivity) }
addButton(R.string.purchase_gems, true) { _, _ -> MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true))) }
addCloseButton()
}
}

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.ui.views.insufficientCurrency
import android.content.Context
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.addCloseButton
import com.habitrpg.android.habitica.helpers.MainNavigationController
@ -11,7 +12,7 @@ class InsufficientHourglassesDialog(context: Context) : InsufficientCurrencyDial
imageView.setImageBitmap(HabiticaIconsHelper.imageOfHourglassShop())
textView.setText(R.string.insufficientHourglasses)
addButton(R.string.get_hourglasses, true) { _, _ -> MainNavigationController.navigate(R.id.gemPurchaseActivity) }
addButton(R.string.get_hourglasses, true) { _, _ -> MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true))) }
addCloseButton()
}
}

View file

@ -0,0 +1,93 @@
package com.habitrpg.android.habitica.ui.views.promo
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.util.AttributeSet
import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.dpToPx
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import kotlinx.android.synthetic.main.promo_subscription_buy_gems.view.*
import java.util.*
class SubscriptionBuyGemsPromoView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {
private var didLayoutGold: Boolean = false
private var goldViews = mutableListOf<AppCompatImageView>()
private val random: Random = Random()
private var iconSize = 30.dpToPx(context)
private val starParams: LayoutParams
get() {
val params = LayoutParams(iconSize, iconSize)
params.leftMargin = if (random.nextBoolean()) {
-20 + random.nextInt(contentWrapper.left)
} else {
contentWrapper.right + random.nextInt(width - contentWrapper.right)
}
params.topMargin = -20 + random.nextInt(height + 20)
return params
}
init {
inflate(R.layout.promo_subscription_buy_gems, true)
setBackgroundColor(ContextCompat.getColor(context, R.color.blue_50))
clipToPadding = false
clipChildren = false
clipToOutline = false
generateGold()
button.setOnClickListener { MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true))) }
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
updateGoldLayoutParams()
}
private fun generateGold() {
removeGoldViews()
for (x in 0 until 8) {
generateGoldView()
}
requestLayout()
}
private fun removeGoldViews() {
if (goldViews.size > 0) {
goldViews.forEach { this.removeView(it) }
goldViews.clear()
}
}
private fun generateGoldView() {
val goldView = AppCompatImageView(context)
goldView.scaleType = ImageView.ScaleType.CENTER
goldView.setImageDrawable(BitmapDrawable(resources, HabiticaIconsHelper.imageOfGoldReward()))
goldView.rotation = random.nextFloat() * 360
goldViews.add(goldView)
if (width > 0 && height > 0) {
this.addView(goldView, 0, starParams)
} else {
this.addView(goldView, 0)
}
}
private fun updateGoldLayoutParams() {
if (width <= 0 || height <= 0 || didLayoutGold || goldViews.size == 0) {
return
}
for (view in goldViews) {
view.layoutParams = starParams
}
didLayoutGold = true
}
}

View file

@ -0,0 +1,6 @@
package com.habitrpg.android.habitica.ui.views.promo
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class SubscriptionBuyGemsPromoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

View file

@ -8,6 +8,7 @@ import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
@ -263,7 +264,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
if (throwable.javaClass.isAssignableFrom(retrofit2.HttpException::class.java)) {
val error = throwable as retrofit2.HttpException
if (error.code() == 401 && shopItem.currency == "gems") {
MainNavigationController.navigate(R.id.gemPurchaseActivity)
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
}
}
}