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

feat: page type #26

Merged
merged 3 commits into from
Mar 2, 2024
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
3 changes: 2 additions & 1 deletion demo/src/main/java/com/paypal/messagesdemo/XmlActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.ui.graphics.Color
import com.paypal.messages.PayPalMessageView
import com.paypal.messages.config.PayPalEnvironment
import com.paypal.messages.config.PayPalMessageOfferType
import com.paypal.messages.config.PayPalMessagePageType
import com.paypal.messages.config.message.PayPalMessageConfig
import com.paypal.messages.config.message.PayPalMessageData
import com.paypal.messages.config.message.PayPalMessageViewStateCallbacks
Expand Down Expand Up @@ -197,7 +198,7 @@ class XmlActivity : AppCompatActivity() {
message.clientID = ""
message.merchantID = ""
message.partnerAttributionID = ""
message.placement = ""
message.pageType = PayPalMessagePageType.CART
message.onClick = {}
message.onApply = {}
message.onLoading = {}
Expand Down
2 changes: 1 addition & 1 deletion library/src/main/java/com/paypal/messages/ModalFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import java.util.UUID
import kotlin.system.measureTimeMillis
import com.paypal.messages.config.PayPalMessageOfferType as OfferType

internal class ModalFragment constructor(
internal class ModalFragment(
private val clientId: String,
) : BottomSheetDialogFragment() {
private val TAG = "PayPalMessageModal"
Expand Down
56 changes: 32 additions & 24 deletions library/src/main/java/com/paypal/messages/PayPalMessageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import java.util.UUID
import kotlin.coroutines.CoroutineContext
import kotlin.system.measureTimeMillis
import com.paypal.messages.config.PayPalMessageOfferType as OfferType
import com.paypal.messages.config.PayPalMessagePageType as PageType
import com.paypal.messages.config.message.PayPalMessageConfig as MessageConfig
import com.paypal.messages.config.message.PayPalMessageData as MessageData
import com.paypal.messages.config.message.PayPalMessageEventsCallbacks as EventsCallbacks
Expand Down Expand Up @@ -77,7 +78,7 @@ class PayPalMessageView @JvmOverloads constructor(
amount = this.amount,
buyerCountry = this.buyerCountry,
offerType = this.offerType,
placement = this.placement,
pageType = this.pageType,
),
style = MessageStyle(this.color, this.logoType, this.textAlign),
viewStateCallbacks = ViewStateCallbacks(this.onLoading, this.onSuccess, this.onError),
Expand All @@ -92,7 +93,7 @@ class PayPalMessageView @JvmOverloads constructor(
amount = config.data.amount
buyerCountry = config.data.clientID
offerType = config.data.offerType
placement = config.data.placement
pageType = config.data.pageType
color = config.style.color
logoType = config.style.logoType
textAlign = config.style.textAlign
Expand All @@ -104,6 +105,25 @@ class PayPalMessageView @JvmOverloads constructor(
debounceUpdateContent(Unit)
}

private fun <T> debounce(
delayMs: Long = 1L,
coroutineContext: CoroutineContext = Dispatchers.Main,
callback: (T) -> Unit,
): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
if (debounceJob?.isCompleted != false) {
debounceJob = CoroutineScope(coroutineContext).launch {
delay(delayMs)
callback(param)
}
}
}
}

// This must be above the set methods to prevent errors when using XML attributes
val debounceUpdateContent = debounce<Unit> { updateMessageContent() }

/**
* DATA
*/
Expand Down Expand Up @@ -153,7 +173,7 @@ class PayPalMessageView @JvmOverloads constructor(
debounceUpdateContent(Unit)
}
}
var placement: String? = config.data.placement
var pageType: PageType? = config.data.pageType
set(arg) {
if (field != arg) {
field = arg
Expand Down Expand Up @@ -302,24 +322,6 @@ class PayPalMessageView @JvmOverloads constructor(
this.modal?.dismiss()
}

private fun <T> debounce(
delayMs: Long = 1L,
coroutineContext: CoroutineContext = Dispatchers.Main,
callback: (T) -> Unit,
): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
if (debounceJob?.isCompleted != false) {
debounceJob = CoroutineScope(coroutineContext).launch {
delay(delayMs)
callback(param)
}
}
}
}

val debounceUpdateContent = debounce<Unit> { updateMessageContent() }

/**
* This function purpose is to update only the UI of the [PayPalMessageView] component.
* It makes use of the existing values for the message content and style
Expand Down Expand Up @@ -374,8 +376,14 @@ class PayPalMessageView @JvmOverloads constructor(
}
}

if (typedArray.hasValue(R.styleable.PayPalMessageView_paypal_placement)) {
placement = typedArray.getString(R.styleable.PayPalMessageView_paypal_placement)
if (typedArray.hasValue(R.styleable.PayPalMessageView_paypal_page_type)) {
pageType = try {
PageType(typedArray.getIntOrThrow(R.styleable.PayPalMessageView_paypal_page_type))
}
catch (ex: Exception) {
LogCat.error(TAG, "Error parsing page_type attribute")
null
}
}

if (typedArray.hasValue(R.styleable.PayPalMessageView_paypal_offer_type)) {
Expand Down Expand Up @@ -629,7 +637,7 @@ class PayPalMessageView @JvmOverloads constructor(
val component = TrackingComponent(
offerType = this.offerType,
amount = this.amount.toString(),
placement = this.placement,
pageType = this.pageType,
buyerCountryCode = this.buyerCountry,
styleLogoType = this.logoType,
styleColor = this.color,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.paypal.messages.config

import com.paypal.messages.utils.PayPalErrors

/**
* [PayPalMessagePageType] provides different variations of PageTypes supported by the PayPalMessage component
*
* @property value is the index identifier for returning a PageType
*/
enum class PayPalMessagePageType(val value: Int) {
CART(0),
CHECKOUT(1),
HOME(2),
MINI_CART(3),
PRODUCT_DETAILS(4),
PRODUCT_LISTING(5),
SEARCH_RESULTS(6),
;

companion object {
/**
* Given an [attributeIndex] this will provide the correct [PayPalMessagePageType].
*
* @throws [PayPalErrors.IllegalEnumArg] when an invalid index is provided.
*/
operator fun invoke(attributeIndex: Int): PayPalMessagePageType {
return when (attributeIndex) {
CART.value -> CART
CHECKOUT.value -> CHECKOUT
HOME.value -> HOME
MINI_CART.value -> MINI_CART
PRODUCT_DETAILS.value -> PRODUCT_DETAILS
PRODUCT_LISTING.value -> PRODUCT_LISTING
SEARCH_RESULTS.value -> SEARCH_RESULTS
else -> throw PayPalErrors.IllegalEnumArg("PageType", 7)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.paypal.messages.config.message
import com.paypal.messages.io.Api
import com.paypal.messages.config.PayPalEnvironment as Environment
import com.paypal.messages.config.PayPalMessageOfferType as OfferType
import com.paypal.messages.config.PayPalMessagePageType as PageType

/**
* [PayPalMessageData] holds data used to determine the content of a PayPalMessage component
Expand All @@ -16,7 +17,7 @@ data class PayPalMessageData(
var amount: Double? = null,
var buyerCountry: String? = null,
var offerType: OfferType? = null,
var placement: String? = null,
var pageType: PageType? = null,
var environment: Environment = Environment.SANDBOX,
) : Cloneable {
init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.paypal.messages.logger

import com.google.gson.annotations.SerializedName
import com.paypal.messages.config.PayPalMessageOfferType
import com.paypal.messages.config.PayPalMessagePageType
import com.paypal.messages.config.message.style.PayPalMessageAlign
import com.paypal.messages.config.message.style.PayPalMessageColor
import com.paypal.messages.config.message.style.PayPalMessageLogoType
Expand All @@ -12,8 +13,8 @@ data class TrackingComponent(
val offerType: PayPalMessageOfferType? = null,
@SerializedName("amount")
val amount: String? = null,
@SerializedName("placement")
val placement: String? = null,
@SerializedName("page_type")
val pageType: PayPalMessagePageType? = null,
@SerializedName("buyer_country_code")
val buyerCountryCode: String? = null,
@SerializedName("channel")
Expand Down Expand Up @@ -64,5 +65,6 @@ data class TrackingComponent(
val componentEvents: MutableList<TrackingEvent>,

// Dynamic Properties, not serialized by default
@Suppress("PropertyName")
val __shared__: MutableMap<String, Any>? = mutableMapOf(),
)
10 changes: 9 additions & 1 deletion library/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@

<attr name="paypal_amount" format="float"/>

<attr name="paypal_placement" format="float"/>
<attr name="paypal_page_type" format="enum">
<enum name="CART" value="0" />
<enum name="CHECKOUT" value="1" />
<enum name="HOME" value="2" />
<enum name="MINI_CART" value="3" />
<enum name="PRODUCT_DETAILS" value="4" />
<enum name="PRODUCT_LISTING" value="5" />
<enum name="SEARCH_RESULTS" value="6" />
</attr>

<attr name="paypal_buyer_country" format="string"/>
</declare-styleable>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.paypal.messages.config

import com.paypal.messages.utils.PayPalErrors
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test

class PayPalMessagePageTypeTest {
@Test
fun testCart() {
assertEquals(PayPalMessagePageType.CART.value, 0)
assertEquals(PayPalMessagePageType.CART.toString(), "CART")
}

@Test
fun testCheckout() {
assertEquals(PayPalMessagePageType.CHECKOUT.value, 1)
assertEquals(PayPalMessagePageType.CHECKOUT.toString(), "CHECKOUT")
}

@Test
fun testHome() {
assertEquals(PayPalMessagePageType.HOME.value, 2)
assertEquals(PayPalMessagePageType.HOME.toString(), "HOME")
}

@Test
fun testMini_cart() {
assertEquals(PayPalMessagePageType.MINI_CART.value, 3)
assertEquals(PayPalMessagePageType.MINI_CART.toString(), "MINI_CART")
}

@Test
fun testProduct_details() {
assertEquals(PayPalMessagePageType.PRODUCT_DETAILS.value, 4)
assertEquals(PayPalMessagePageType.PRODUCT_DETAILS.toString(), "PRODUCT_DETAILS")
}

@Test
fun testProduct_listing() {
assertEquals(PayPalMessagePageType.PRODUCT_LISTING.value, 5)
assertEquals(PayPalMessagePageType.PRODUCT_LISTING.toString(), "PRODUCT_LISTING")
}

@Test
fun testSearch_results() {
assertEquals(PayPalMessagePageType.SEARCH_RESULTS.value, 6)
assertEquals(PayPalMessagePageType.SEARCH_RESULTS.toString(), "SEARCH_RESULTS")
}

@Test
fun testInvalidIndex() {
assertThrows(PayPalErrors.IllegalEnumArg::class.java) { PayPalMessagePageType(99) }
}

@Test
fun testFromString() {
assertEquals(PayPalMessagePageType.CART, PayPalMessagePageType(0))
assertEquals(PayPalMessagePageType.CHECKOUT, PayPalMessagePageType(1))
assertEquals(PayPalMessagePageType.HOME, PayPalMessagePageType(2))
assertEquals(PayPalMessagePageType.MINI_CART, PayPalMessagePageType(3))
assertEquals(PayPalMessagePageType.PRODUCT_DETAILS, PayPalMessagePageType(4))
assertEquals(PayPalMessagePageType.PRODUCT_LISTING, PayPalMessagePageType(5))
assertEquals(PayPalMessagePageType.SEARCH_RESULTS, PayPalMessagePageType(6))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.paypal.messages.config.message

import com.paypal.messages.config.PayPalEnvironment
import com.paypal.messages.config.PayPalMessageOfferType
import com.paypal.messages.config.PayPalMessagePageType
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotEquals
import org.junit.jupiter.api.Test
Expand All @@ -14,7 +15,7 @@ class PayPalMessageDataTest {
val data = PayPalMessageData(
clientID = initialClientID,
amount = 115.0,
placement = "placement_test",
pageType = PayPalMessagePageType.CART,
offerType = PayPalMessageOfferType.PAY_LATER_PAY_IN_1,
buyerCountry = "buyer_country_test",
merchantID = "merchant_id_test",
Expand All @@ -24,7 +25,7 @@ class PayPalMessageDataTest {

assertEquals(data.clientID, initialClientID)
assertEquals(data.amount, 115.0)
assertEquals(data.placement, "placement_test")
assertEquals(data.pageType, PayPalMessagePageType.CART)
assertEquals(data.offerType, PayPalMessageOfferType.PAY_LATER_PAY_IN_1)
assertEquals(data.buyerCountry, "buyer_country_test")
assertEquals(data.merchantID, "merchant_id_test")
Expand All @@ -41,7 +42,7 @@ class PayPalMessageDataTest {
amount = 115.0,
buyerCountry = "ES",
offerType = PayPalMessageOfferType.PAY_LATER_PAY_IN_1,
placement = "test_placement",
pageType = PayPalMessagePageType.CART,
environment = PayPalEnvironment.LOCAL,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.paypal.messages.logger

import com.google.gson.Gson
import com.paypal.messages.config.PayPalMessageOfferType
import com.paypal.messages.config.PayPalMessagePageType
import com.paypal.messages.config.message.style.PayPalMessageAlign
import com.paypal.messages.config.message.style.PayPalMessageColor
import com.paypal.messages.config.message.style.PayPalMessageLogoType
Expand All @@ -11,7 +12,7 @@ import org.junit.jupiter.api.Test
class TrackingComponentTest {
private val offerType = PayPalMessageOfferType.PAY_LATER_SHORT_TERM
private val amount = "100.00"
private val placement = "CART"
private val pageType = PayPalMessagePageType.CART
private val buyerCountryCode = "US"
private val channel = "NATIVE"
private val styleLogoType = PayPalMessageLogoType.ALTERNATIVE
Expand All @@ -37,7 +38,7 @@ class TrackingComponentTest {
private val trackingComponent = TrackingComponent(
offerType = offerType,
amount = amount,
placement = placement,
pageType = pageType,
buyerCountryCode = buyerCountryCode,
channel = channel,
styleLogoType = styleLogoType,
Expand Down Expand Up @@ -65,7 +66,7 @@ class TrackingComponentTest {
fun testConstructor() {
assertEquals(offerType, trackingComponent.offerType)
assertEquals(amount, trackingComponent.amount)
assertEquals(placement, trackingComponent.placement)
assertEquals(pageType, trackingComponent.pageType)
assertEquals(buyerCountryCode, trackingComponent.buyerCountryCode)
assertEquals(channel, trackingComponent.channel)
assertEquals(styleLogoType, trackingComponent.styleLogoType)
Expand Down Expand Up @@ -95,7 +96,7 @@ class TrackingComponentTest {
val json = gson.toJson(trackingComponent)

@Suppress("ktlint:standard:max-line-length")
val expectedJson = """{"offer_type":"PAY_LATER_SHORT_TERM","amount":"100.00","placement":"CART","buyer_country_code":"US","channel":"NATIVE","style_logo_type":"ALTERNATIVE","style_color":"MONOCHROME","style_text_align":"CENTER","message_type":"OFFER","views":["VIEW"],"qualified_products":["PRODUCT"],"fdata":"test_fdata","debug_id":"test_debug_id","experimentation_experience_ids":["EXP_1","EXP_2"],"experimentation_treatment_ids":["TRT_1","TRT_2"],"credit_product_identifiers":["CPI_1","CPI_2"],"offer_country_code":"US","merchant_country_code":"US","type":"OFFER","instance_id":"test_instance_id","originating_instance_id":"test_originating_instance_id","session_id":"test_session_id","component_events":[{"event_type":"MESSAGE_CLICK"}],"__shared__":{}}"""
val expectedJson = """{"offer_type":"PAY_LATER_SHORT_TERM","amount":"100.00","page_type":"CART","buyer_country_code":"US","channel":"NATIVE","style_logo_type":"ALTERNATIVE","style_color":"MONOCHROME","style_text_align":"CENTER","message_type":"OFFER","views":["VIEW"],"qualified_products":["PRODUCT"],"fdata":"test_fdata","debug_id":"test_debug_id","experimentation_experience_ids":["EXP_1","EXP_2"],"experimentation_treatment_ids":["TRT_1","TRT_2"],"credit_product_identifiers":["CPI_1","CPI_2"],"offer_country_code":"US","merchant_country_code":"US","type":"OFFER","instance_id":"test_instance_id","originating_instance_id":"test_originating_instance_id","session_id":"test_session_id","component_events":[{"event_type":"MESSAGE_CLICK"}],"__shared__":{}}"""
assertEquals(expectedJson, json)
}
}
Loading
Loading