Skip to content

Commit

Permalink
[Paywalls V2] Adds a StyleFactory (#1965)
Browse files Browse the repository at this point in the history
  • Loading branch information
JayShortway authored Dec 10, 2024
1 parent 81fc790 commit 43cbbf1
Show file tree
Hide file tree
Showing 33 changed files with 1,047 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.revenuecat.purchases.InternalRevenueCatAPI
import com.revenuecat.purchases.paywalls.components.ButtonComponent.Action
import com.revenuecat.purchases.paywalls.components.ButtonComponent.Destination
import com.revenuecat.purchases.paywalls.components.ButtonComponent.UrlMethod
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand All @@ -12,9 +13,10 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("button")
internal data class ButtonComponent(
class ButtonComponent internal constructor(
@get:JvmSynthetic val action: Action,
@get:JvmSynthetic val stack: StackComponent,
) : PaywallComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ import com.revenuecat.purchases.paywalls.components.properties.Size
import com.revenuecat.purchases.paywalls.components.properties.SizeConstraint.Fill
import com.revenuecat.purchases.paywalls.components.properties.SizeConstraint.Fit
import com.revenuecat.purchases.paywalls.components.properties.ThemeImageUrls
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Suppress("LongParameterList")
@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("image")
internal data class ImageComponent(
class ImageComponent internal constructor(
@get:JvmSynthetic
val source: ThemeImageUrls,
@get:JvmSynthetic
Expand All @@ -38,9 +41,11 @@ internal data class ImageComponent(
val overrides: ComponentOverrides<PartialImageComponent>? = null,
) : PaywallComponent

@Suppress("LongParameterList")
@InternalRevenueCatAPI
@Poko
@Serializable
internal data class PartialImageComponent(
class PartialImageComponent internal constructor(
@get:JvmSynthetic
val visible: Boolean? = true,
@get:JvmSynthetic
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("package")
internal data class PackageComponent(
class PackageComponent internal constructor(
@get:JvmSynthetic
@SerialName("package_id")
val packageId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Serializable
internal sealed interface PaywallComponent
sealed interface PaywallComponent
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("purchase_button")
internal data class PurchaseButtonComponent(
class PurchaseButtonComponent internal constructor(
@get:JvmSynthetic val stack: StackComponent,
) : PaywallComponent
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ import com.revenuecat.purchases.paywalls.components.properties.Shadow
import com.revenuecat.purchases.paywalls.components.properties.Shape
import com.revenuecat.purchases.paywalls.components.properties.Size
import com.revenuecat.purchases.paywalls.components.properties.SizeConstraint
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Suppress("LongParameterList")
@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("stack")
internal data class StackComponent(
class StackComponent(
@get:JvmSynthetic
val components: List<PaywallComponent>,
@get:JvmSynthetic
Expand All @@ -46,9 +49,11 @@ internal data class StackComponent(
val overrides: ComponentOverrides<PartialStackComponent>? = null,
) : PaywallComponent

@Suppress("LongParameterList")
@InternalRevenueCatAPI
@Poko
@Serializable
internal data class PartialStackComponent(
class PartialStackComponent(
@get:JvmSynthetic
val visible: Boolean? = true,
@get:JvmSynthetic
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Poko
@Serializable
@SerialName("sticky_footer")
internal data class StickyFooterComponent(
class StickyFooterComponent internal constructor(
@get:JvmSynthetic
val stack: StackComponent,
) : PaywallComponent
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import kotlinx.serialization.Serializable
@SerialName("text")
class TextComponent
@Suppress("LongParameterList")
internal constructor(
constructor(
@get:JvmSynthetic
@SerialName("text_lid")
val text: LocalizationKey,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.revenuecat.purchases.paywalls.components.properties

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Poko
@Serializable
internal data class Border(
class Border internal constructor(
@get:JvmSynthetic
val color: ColorScheme,
@get:JvmSynthetic
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.revenuecat.purchases.paywalls.components.properties

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Contains radius values for 4 corners, in dp.
*/
@InternalRevenueCatAPI
@Poko
@Serializable
internal data class CornerRadiuses(
class CornerRadiuses internal constructor(
/**
* The top-leading, or top-start, corner radius, in dp.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Serializable
internal enum class FitMode {
enum class FitMode {
@SerialName("fit")
FIT,

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.revenuecat.purchases.paywalls.components.properties

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Serializable
internal sealed interface MaskShape {
sealed interface MaskShape {

@Poko
@Serializable
@SerialName("rectangle")
data class Rectangle(
class Rectangle(
@get:JvmSynthetic val corners: CornerRadiuses? = null,
) : MaskShape

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.revenuecat.purchases.paywalls.components.properties

import com.revenuecat.purchases.InternalRevenueCatAPI
import dev.drewhamilton.poko.Poko
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@InternalRevenueCatAPI
@Serializable
internal sealed interface Shape {
sealed interface Shape {

@Serializable
@Poko
@SerialName("rectangle")
data class Rectangle(
class Rectangle(
@get:JvmSynthetic val corners: CornerRadiuses? = null,
) : Shape

Expand Down
12 changes: 12 additions & 0 deletions purchases/src/main/kotlin/com/revenuecat/purchases/utils/Result.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
package com.revenuecat.purchases.utils

/**
* This is an exact duplicate of `com.revenuecat.purchases.ui.revenuecatui.helpers.Result`, which is internal to
* revenuecatui. We don't want to make this one public (marked with `@InternalRevenueCatAPI`), as that will still show
* up in autocomplete if devs are trying to use the built-in `kotlin.Result` type.
*
* That version, in revenuecatui, has some additional extensions. If we ever want to consolidate the two `Result`
* classes, or use those extensions in purchases, we can consider these alternatives:
* * Rename `com.revenuecat.purchases.utils.Result` to something like `RcResult`, make it public, and mark it with
* `@InternalRevenueCatAPI`. Refactor the extensions to use `RcResult`.
* * Create a separate Gradle module, move `Result` there together with the extensions, and make it an `implementation`
* of both purchases and revenuecatui.
*/
internal sealed class Result<out A, out B> {
class Success<A>(val value: A) : Result<A, Nothing>()
class Error<B>(val value: B) : Result<Nothing, B>()
Expand Down
1 change: 1 addition & 0 deletions ui/revenuecatui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ dependencies {
testImplementation libs.coroutines.test
testImplementation libs.kotlinx.serialization.json
testImplementation libs.androidx.test.compose
testImplementation libs.androidx.test.compose.manifest
testImplementation libs.hamcrest.core

androidTestImplementation libs.assertJ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package com.revenuecat.purchases.ui.revenuecatui.components
import com.revenuecat.purchases.paywalls.components.PartialTextComponent
import com.revenuecat.purchases.paywalls.components.common.LocalizationDictionary
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.string
import com.revenuecat.purchases.ui.revenuecatui.errors.PaywallValidationError
import com.revenuecat.purchases.ui.revenuecatui.helpers.Result
import com.revenuecat.purchases.ui.revenuecatui.helpers.map
import com.revenuecat.purchases.ui.revenuecatui.helpers.orSuccessfullyNull
import dev.drewhamilton.poko.Poko

@Poko
Expand All @@ -21,16 +25,16 @@ internal class LocalizedTextPartial private constructor(
operator fun invoke(
from: PartialTextComponent,
using: LocalizationDictionary,
): Result<LocalizedTextPartial> {
val stringResult: Result<String?> = from.text?.let(using::string) ?: Result.success(null)

return stringResult.map { string ->
LocalizedTextPartial(
text = string,
partial = from,
)
}
}
): Result<LocalizedTextPartial, PaywallValidationError> =
from.text
?.let(using::string)
.orSuccessfullyNull()
.map { string: String? ->
LocalizedTextPartial(
text = string,
partial = from,
)
}
}

@JvmSynthetic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package com.revenuecat.purchases.ui.revenuecatui.components

import com.revenuecat.purchases.paywalls.components.PartialComponent
import com.revenuecat.purchases.paywalls.components.common.ComponentOverrides
import com.revenuecat.purchases.ui.revenuecatui.errors.PaywallValidationError
import com.revenuecat.purchases.ui.revenuecatui.helpers.Result
import com.revenuecat.purchases.ui.revenuecatui.helpers.getOrElse
import dev.drewhamilton.poko.Poko

/**
Expand Down Expand Up @@ -80,25 +83,25 @@ internal class PresentedConditions<T : PresentedPartial<T>>(
@Suppress("ReturnCount")
@JvmSynthetic
internal fun <T : PartialComponent, P : PresentedPartial<P>> ComponentOverrides<T>.toPresentedOverrides(
transform: (T) -> Result<P>,
): Result<PresentedOverrides<P>> {
transform: (T) -> Result<P, PaywallValidationError>,
): Result<PresentedOverrides<P>, PaywallValidationError> {
val introOffer = introOffer?.let(transform)
?.getOrElse { return Result.failure(it) }
?.getOrElse { return Result.Error(it) }

val selectedState = states?.selected?.let(transform)
?.getOrElse { return Result.failure(it) }
?.getOrElse { return Result.Error(it) }

val states = states?.let { PresentedStates(selected = selectedState) }

val conditions = conditions?.let { conditions ->
PresentedConditions(
compact = conditions.compact?.let(transform)?.getOrElse { return Result.failure(it) },
medium = conditions.medium?.let(transform)?.getOrElse { return Result.failure(it) },
expanded = conditions.expanded?.let(transform)?.getOrElse { return Result.failure(it) },
compact = conditions.compact?.let(transform)?.getOrElse { return Result.Error(it) },
medium = conditions.medium?.let(transform)?.getOrElse { return Result.Error(it) },
expanded = conditions.expanded?.let(transform)?.getOrElse { return Result.Error(it) },
)
}

return Result.success(
return Result.Success(
PresentedOverrides(
introOffer = introOffer,
states = states,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.revenuecat.purchases.ui.revenuecatui.components

import com.revenuecat.purchases.paywalls.components.PartialStackComponent
import dev.drewhamilton.poko.Poko

@Poko
internal class PresentedStackPartial(
@get:JvmSynthetic val partial: PartialStackComponent,
) : PresentedPartial<PresentedStackPartial> {
override fun combine(with: PresentedStackPartial?): PresentedStackPartial {
val otherPartial = with?.partial

return PresentedStackPartial(
partial = PartialStackComponent(
visible = otherPartial?.visible ?: partial.visible,
dimension = otherPartial?.dimension ?: partial.dimension,
size = otherPartial?.size ?: partial.size,
spacing = otherPartial?.spacing ?: partial.spacing,
backgroundColor = otherPartial?.backgroundColor ?: partial.backgroundColor,
padding = otherPartial?.padding ?: partial.padding,
margin = otherPartial?.margin ?: partial.margin,
shape = otherPartial?.shape ?: partial.shape,
border = otherPartial?.border ?: partial.border,
shadow = otherPartial?.shadow ?: partial.shadow,
),
)
}
}
Loading

0 comments on commit 43cbbf1

Please sign in to comment.