Skip to content

Commit 60e303c

Browse files
authored
Placements (#73)
* add placements * globar refactors
1 parent 261076f commit 60e303c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1668
-1236
lines changed

demo/src/main/java/com/apphud/demo/ApphudApplication.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ package com.apphud.demo
22

33
import android.app.Application
44
import android.content.Context
5+
import android.util.Log
6+
import androidx.lifecycle.lifecycleScope
57
import com.apphud.sdk.Apphud
8+
import com.apphud.sdk.ApphudUtils
9+
import com.apphud.sdk.client.ApiClient
10+
import kotlinx.coroutines.GlobalScope
11+
import kotlinx.coroutines.launch
612

713
class ApphudApplication : Application() {
8-
val API_KEY = "app_4sY9cLggXpMDDQMmvc5wXUPGReMp8G"
14+
var API_KEY = "app_4sY9cLggXpMDDQMmvc5wXUPGReMp8G"
915

1016
companion object {
1117
private lateinit var instance: ApphudApplication
@@ -28,6 +34,13 @@ class ApphudApplication : Application() {
2834

2935
Apphud.enableDebugLogs()
3036
// Apphud.optOutOfTracking()
37+
38+
if (BuildConfig.DEBUG) {
39+
ApphudUtils.enableAllLogs()
40+
}
41+
42+
// check again restore cache from previous sdk version
43+
3144
Apphud.start(this, API_KEY)
3245
Apphud.collectDeviceIdentifiers()
3346
}

demo/src/main/java/com/apphud/demo/MainActivity.kt

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,18 @@ class MainActivity : AppCompatActivity() {
6363
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
6464
binding.drawerLayout.closeDrawer(GravityCompat.START)
6565
} else {
66-
if (!findNavController(R.id.nav_host_fragment_content_main).navigateUp())
67-
{
68-
if (backPress + 2000 > System.currentTimeMillis()) {
69-
super.onBackPressed()
70-
} else {
71-
Toast.makeText(
72-
baseContext,
73-
"Please press again to exit!",
74-
Toast.LENGTH_SHORT,
75-
).show()
76-
backPress = System.currentTimeMillis()
77-
}
66+
if (!findNavController(R.id.nav_host_fragment_content_main).navigateUp()) {
67+
if (backPress + 2000 > System.currentTimeMillis()) {
68+
super.onBackPressed()
69+
} else {
70+
Toast.makeText(
71+
baseContext,
72+
"Please press again to exit!",
73+
Toast.LENGTH_SHORT,
74+
).show()
75+
backPress = System.currentTimeMillis()
7876
}
77+
}
7978
}
8079
}
8180
}

demo/src/main/java/com/apphud/demo/ui/billing/BillingClientWrapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class BillingClientWrapper(
2121
context: Context,
2222
) : PurchasesUpdatedListener, ProductDetailsResponseListener {
2323
companion object {
24-
private const val TAG = "BillingClient"
24+
private const val TAG = "ApphudLogs"
2525

2626
// List of subscription product offerings
2727
private const val PEACH = "com.apphud.demo.consumable.peach"

demo/src/main/java/com/apphud/demo/ui/billing/BillingFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class BillingFragment : Fragment() {
4141
viewAdapter.selectProduct = { product ->
4242
activity?.let { activity ->
4343
val offers = product.subscriptionOfferDetails?.map { it.pricingPhases.pricingPhaseList[0].formattedPrice }
44-
offers?.let { offers ->
44+
offers?.let { _ ->
4545

4646
product.subscriptionOfferDetails?.let {
4747
val fragment = OffersFragment()

demo/src/main/java/com/apphud/demo/ui/billing/BillingViewModel.kt

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import com.apphud.sdk.Apphud
1414

1515
class BillingViewModel : ViewModel() {
1616
companion object {
17-
private const val TAG: String = "BillingViewModel"
17+
private const val TAG: String = "ApphudLogs"
1818
private const val MAX_CURRENT_PURCHASES_ALLOWED = 1
1919
}
2020

@@ -29,7 +29,7 @@ class BillingViewModel : ViewModel() {
2929

3030
var items = mutableListOf<Any>()
3131

32-
fun updateData() {
32+
fun updateData() {
3333
items.clear()
3434
for (item in billingClient.productWithProductDetails) {
3535
items.add(item.value)
@@ -171,23 +171,20 @@ class BillingViewModel : ViewModel() {
171171
val oldPurchaseToken: String
172172

173173
billingClient.purchaseSuccessListener = { purchase, billingResult ->
174-
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK)
175-
{
176-
purchase?.let { p ->
177-
if (p.purchaseState == Purchase.PurchaseState.PURCHASED) {
178-
Log.d(TAG, "Purchase SUCCESS notify Apphud")
179-
Apphud.trackPurchase(p, productDetails, offerIdToken)
180-
} else
181-
{
182-
Log.e(TAG, "Purchase SUCCESS but purchase state is " + p.purchaseState)
183-
}
184-
} ?: run {
185-
Log.e(TAG, "Purchase SUCCESS but purchase is null")
174+
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
175+
purchase?.let { p ->
176+
if (p.purchaseState == Purchase.PurchaseState.PURCHASED) {
177+
Log.d(TAG, "Purchase SUCCESS notify Apphud")
178+
Apphud.trackPurchase(p, productDetails, offerIdToken)
179+
} else {
180+
Log.e(TAG, "Purchase SUCCESS but purchase state is " + p.purchaseState)
186181
}
187-
} else
188-
{
189-
Log.e(TAG, "Purchase ERROR: code=" + billingResult.responseCode)
182+
} ?: run {
183+
Log.e(TAG, "Purchase SUCCESS but purchase is null")
190184
}
185+
} else {
186+
Log.e(TAG, "Purchase ERROR: code=" + billingResult.responseCode)
187+
}
191188
}
192189

193190
// Get current purchase. In this app, a user can only have one current purchase at

demo/src/main/java/com/apphud/demo/ui/customer/CustomerFragment.kt

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import android.view.ViewGroup
88
import android.widget.TextView
99
import androidx.fragment.app.Fragment
1010
import androidx.lifecycle.ViewModelProvider
11+
import androidx.lifecycle.lifecycleScope
1112
import androidx.navigation.fragment.findNavController
1213
import androidx.recyclerview.widget.DividerItemDecoration
1314
import androidx.recyclerview.widget.RecyclerView
@@ -18,8 +19,13 @@ import com.apphud.sdk.Apphud
1819
import com.apphud.sdk.ApphudListener
1920
import com.apphud.sdk.domain.ApphudNonRenewingPurchase
2021
import com.apphud.sdk.domain.ApphudPaywall
22+
import com.apphud.sdk.domain.ApphudPlacement
2123
import com.apphud.sdk.domain.ApphudSubscription
24+
import com.apphud.sdk.domain.ApphudUser
2225
import com.apphud.sdk.managers.HeadersInterceptor
26+
import kotlinx.coroutines.Dispatchers
27+
import kotlinx.coroutines.launch
28+
import kotlinx.coroutines.withContext
2329

2430
class CustomerFragment : Fragment() {
2531
private var _binding: FragmentCustomerBinding? = null
@@ -48,8 +54,8 @@ class CustomerFragment : Fragment() {
4854

4955
paywallsViewModel = ViewModelProvider(this)[PaywallsViewModel::class.java]
5056
viewAdapter = PaywallsAdapter(paywallsViewModel, context)
51-
viewAdapter.selectPaywall = { paywall ->
52-
findNavController().navigate(CustomerFragmentDirections.actionNavCustomerToProductsFragment(paywall.identifier))
57+
viewAdapter.selectItem = { item ->
58+
findNavController().navigate(CustomerFragmentDirections.actionNavCustomerToProductsFragment(item.paywall?.identifier, item.placement?.identifier))
5359
}
5460

5561
val recyclerView: RecyclerView = binding.paywallsList
@@ -58,6 +64,11 @@ class CustomerFragment : Fragment() {
5864
addItemDecoration(DividerItemDecoration(this.context, DividerItemDecoration.VERTICAL))
5965
}
6066

67+
binding.toggleButton.setOnCheckedChangeListener { buttonView, isChecked ->
68+
paywallsViewModel.showPlacements = isChecked
69+
updateData()
70+
}
71+
6172
binding.swipeRefresh.setOnRefreshListener {
6273
updateData()
6374
binding.swipeRefresh.isRefreshing = false
@@ -66,30 +77,36 @@ class CustomerFragment : Fragment() {
6677
val listener =
6778
object : ApphudListener {
6879
override fun apphudSubscriptionsUpdated(subscriptions: List<ApphudSubscription>) {
69-
Log.d("Apphud", "apphudSubscriptionsUpdated")
80+
Log.d("ApphudDemo", "apphudSubscriptionsUpdated")
7081
}
7182

7283
override fun apphudNonRenewingPurchasesUpdated(purchases: List<ApphudNonRenewingPurchase>) {
73-
Log.d("Apphud", "apphudNonRenewingPurchasesUpdated")
84+
Log.d("ApphudDemo", "apphudNonRenewingPurchasesUpdated")
7485
}
7586

7687
override fun apphudFetchProductDetails(details: List<ProductDetails>) {
77-
Log.d("Apphud", "apphudFetchProductDetails()")
88+
Log.d("ApphudDemo", "apphudFetchProductDetails()")
7889
// TODO handle loaded sku details
7990
}
8091

8192
override fun apphudDidChangeUserID(userId: String) {
82-
Log.d("Apphud", "apphudDidChangeUserID()")
93+
Log.d("ApphudDemo", "apphudDidChangeUserID()")
8394
// TODO handle User ID changed event
8495
}
8596

86-
override fun userDidLoad() {
87-
Log.d("Apphud", "userDidLoad()")
97+
override fun userDidLoad(user: ApphudUser) {
98+
Log.d("ApphudDemo", "userDidLoad()")
8899
// TODO handle user registered event
100+
updateData()
89101
}
90102

91-
override fun paywallsDidFullyLoad(paywalls: List<ApphudPaywall>) {
92-
Log.d("Apphud", "paywallsDidFullyLoad()")
103+
override fun paywallsDidFullyLoad(paywalls: List<ApphudPaywall>) {
104+
Log.d("ApphudDemo", "paywallsDidFullyLoad()")
105+
updateData()
106+
}
107+
108+
override fun placementsDidFullyLoad(placements: List<ApphudPlacement>) {
109+
Log.d("ApphudDemo", "placementsDidFullyLoad()")
93110
updateData()
94111
}
95112
}
@@ -100,9 +117,13 @@ class CustomerFragment : Fragment() {
100117
return root
101118
}
102119

103-
private fun updateData() {
104-
paywallsViewModel.updateData()
105-
viewAdapter.notifyDataSetChanged()
120+
private fun updateData() {
121+
lifecycleScope.launch {
122+
paywallsViewModel.updateData()
123+
withContext(Dispatchers.Main) {
124+
viewAdapter.notifyDataSetChanged()
125+
}
126+
}
106127
}
107128

108129
override fun onDestroyView() {

demo/src/main/java/com/apphud/demo/ui/customer/PaywallsAdapter.kt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import android.widget.LinearLayout
99
import android.widget.TextView
1010
import androidx.recyclerview.widget.RecyclerView
1111
import com.apphud.demo.R
12-
import com.apphud.sdk.domain.ApphudPaywall
1312

1413
class PaywallsAdapter(private val paywallsViewModel: PaywallsViewModel, private val context: Context?) : RecyclerView.Adapter<PaywallsAdapter.BaseViewHolder<*>>() {
15-
var selectPaywall: ((account: ApphudPaywall) -> Unit)? = null
14+
var selectItem: ((item: AdapterItem) -> Unit)? = null
1615

1716
abstract class BaseViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
1817
abstract fun bind(
@@ -21,24 +20,35 @@ class PaywallsAdapter(private val paywallsViewModel: PaywallsViewModel, private
2120
)
2221
}
2322

24-
inner class PaywallViewHolder(itemView: View) : BaseViewHolder<ApphudPaywall>(itemView) {
23+
inner class PaywallViewHolder(itemView: View) : BaseViewHolder<AdapterItem>(itemView) {
2524
private val paywallName: TextView = itemView.findViewById(R.id.paywallName)
25+
private val paywallIdentifier: TextView = itemView.findViewById(R.id.paywallIdentifier)
2626
private val paywallDefault: TextView = itemView.findViewById(R.id.paywallDefault)
2727
private val paywallExperiment: TextView = itemView.findViewById(R.id.paywallExperiment)
2828
private val paywallVariation: TextView = itemView.findViewById(R.id.paywallVariation)
2929
private val paywallJson: TextView = itemView.findViewById(R.id.paywallJson)
3030
private val layoutHolder: LinearLayout = itemView.findViewById(R.id.layoutHolder)
3131

3232
override fun bind(
33-
item: ApphudPaywall,
33+
item: AdapterItem,
3434
position: Int,
3535
) {
36-
paywallName.text = item.name
37-
paywallDefault.text = item.default.toString()
38-
paywallExperiment.text = item.experimentName ?: "-"
36+
val paywall = item.paywall ?: item.placement?.paywall
37+
38+
val experimentName = item.placement?.experimentName ?: paywall?.experimentName
39+
40+
paywallName.text =
41+
if (item.placement != null) {
42+
"${item.placement.identifier} -> ${paywall?.name}"
43+
} else {
44+
paywall?.name
45+
}
46+
paywallIdentifier.text = "Paywall ID: " + (paywall?.identifier ?: "N/A")
47+
paywallDefault.text = paywall?.default.toString()
48+
paywallExperiment.text = item.placement?.experimentName ?: paywall?.experimentName ?: "N/A"
3949
paywallVariation.text = "N/A"
40-
paywallJson.text = if (item.json != null) "true" else "false"
41-
item.experimentName?.let {
50+
paywallJson.text = if (paywall?.json != null) "true" else "false"
51+
experimentName?.let {
4252
layoutHolder.setBackgroundResource(R.color.teal_200)
4353
paywallDefault.setTextColor(Color.WHITE)
4454
paywallExperiment.setTextColor(Color.WHITE)
@@ -51,7 +61,9 @@ class PaywallsAdapter(private val paywallsViewModel: PaywallsViewModel, private
5161
}
5262

5363
itemView.setOnClickListener {
54-
selectPaywall?.invoke(item)
64+
paywall?.let { paywall ->
65+
selectItem?.invoke(item)
66+
}
5567
}
5668
}
5769
}
@@ -81,14 +93,14 @@ class PaywallsAdapter(private val paywallsViewModel: PaywallsViewModel, private
8193
) {
8294
val element = paywallsViewModel.items[position]
8395
when (holder) {
84-
is PaywallViewHolder -> holder.bind(element as ApphudPaywall, position)
96+
is PaywallViewHolder -> holder.bind(element as AdapterItem, position)
8597
else -> throw IllegalArgumentException()
8698
}
8799
}
88100

89101
override fun getItemViewType(position: Int): Int {
90102
return when (paywallsViewModel.items[position]) {
91-
is ApphudPaywall -> TYPE_PAYWALL
103+
is AdapterItem -> TYPE_PAYWALL
92104
else -> throw IllegalArgumentException("Invalid type of data " + position)
93105
}
94106
}

demo/src/main/java/com/apphud/demo/ui/customer/PaywallsViewModel.kt

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,31 @@ package com.apphud.demo.ui.customer
22

33
import androidx.lifecycle.ViewModel
44
import com.apphud.sdk.Apphud
5+
import com.apphud.sdk.domain.ApphudPaywall
6+
import com.apphud.sdk.domain.ApphudPlacement
7+
8+
class AdapterItem(
9+
val paywall: ApphudPaywall?,
10+
val placement: ApphudPlacement?,
11+
)
512

613
class PaywallsViewModel : ViewModel() {
714
var items = mutableListOf<Any>()
15+
var showPlacements: Boolean = false
816

9-
fun updateData() {
10-
val list = Apphud.paywalls()
11-
items.clear()
12-
list.forEach {
13-
items.add(it)
17+
suspend fun updateData() {
18+
if (showPlacements) {
19+
items.clear()
20+
val placements = Apphud.placements()
21+
placements.forEach {
22+
items.add(AdapterItem(null, it))
23+
}
24+
} else {
25+
val list = Apphud.paywalls()
26+
items.clear()
27+
list.forEach {
28+
items.add(AdapterItem(it, null))
29+
}
1430
}
1531
}
1632
}

demo/src/main/java/com/apphud/demo/ui/groups/GroupsAdapter.kt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,14 @@ class GroupsAdapter(private val groupsViewModel: GroupsViewModel, private val co
4646
position: Int,
4747
) {
4848
productName.text = item.name
49-
productId.text = item.product_id
49+
productId.text = item.productId
5050

5151
item.productDetails?.let { details ->
52-
if (details.productType == BillingClient.ProductType.SUBS)
53-
{
54-
productPrice.text = details.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()?.formattedPrice ?: ""
55-
} else
56-
{
57-
productPrice.text = details.oneTimePurchaseOfferDetails?.formattedPrice ?: ""
58-
}
52+
if (details.productType == BillingClient.ProductType.SUBS) {
53+
productPrice.text = details.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()?.formattedPrice ?: ""
54+
} else {
55+
productPrice.text = details.oneTimePurchaseOfferDetails?.formattedPrice ?: ""
56+
}
5957
} ?: run {
6058
productPrice.text = ""
6159
}

demo/src/main/java/com/apphud/demo/ui/groups/GroupsFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class GroupsFragment : Fragment() {
5050
return root
5151
}
5252

53-
private fun updateData() {
53+
private fun updateData() {
5454
groupsViewModel.updateData()
5555
}
5656

0 commit comments

Comments
 (0)