Skip to content

Commit

Permalink
[Paywalls V2] TextComponentStyle no longer needs a Composable context (
Browse files Browse the repository at this point in the history
  • Loading branch information
JayShortway authored Dec 17, 2024
1 parent d098930 commit ab1b344
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 233 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.window.core.layout.WindowSizeClass
import com.revenuecat.purchases.Offering
Expand Down Expand Up @@ -47,12 +46,9 @@ import com.revenuecat.purchases.paywalls.components.properties.TwoDimensionalAli
import com.revenuecat.purchases.paywalls.components.properties.TwoDimensionalAlignment.BOTTOM
import com.revenuecat.purchases.ui.revenuecatui.components.modifier.background
import com.revenuecat.purchases.ui.revenuecatui.components.properties.toBackgroundStyle
import com.revenuecat.purchases.ui.revenuecatui.components.state.PackageContext
import com.revenuecat.purchases.ui.revenuecatui.components.style.StyleFactory
import com.revenuecat.purchases.ui.revenuecatui.data.PaywallState
import com.revenuecat.purchases.ui.revenuecatui.data.processed.VariableDataProvider
import com.revenuecat.purchases.ui.revenuecatui.helpers.getOrThrow
import com.revenuecat.purchases.ui.revenuecatui.helpers.toResourceProvider
import java.net.URL
import java.util.Locale

Expand All @@ -61,7 +57,6 @@ internal fun LoadedPaywallComponents(
state: PaywallState.Loaded.Components,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val configuration = LocalConfiguration.current
// Configured locales take precedence over the default one.
val preferredIds = configuration.locales.mapToLocaleIds() + state.data.defaultLocaleIdentifier
Expand All @@ -78,16 +73,7 @@ internal fun LoadedPaywallComponents(
windowSize = windowSize,
isEligibleForIntroOffer = false,
componentState = ComponentViewState.DEFAULT,
packageContext = PackageContext(
initialSelectedPackage = null,
initialVariableContext = PackageContext.VariableContext(
packages = state.offering.availablePackages,
showZeroDecimalPlacePrices = true,
),
),
localizationDictionary = localizationDictionary,
locale = locale,
variables = VariableDataProvider(context.toResourceProvider()),
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@file:JvmSynthetic

package com.revenuecat.purchases.ui.revenuecatui.components

import androidx.compose.ui.text.font.DeviceFontFamilyName
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight

/**
* Get an Android system-installed font by [familyName].
*/
@Suppress("FunctionName")
@JvmSynthetic
internal fun SystemFontFamily(familyName: String, weight: FontWeight?): FontFamily =
FontFamily(
Font(
familyName = DeviceFontFamilyName(familyName),
weight = weight ?: FontWeight.Normal,
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import com.revenuecat.purchases.paywalls.components.properties.Shadow
import com.revenuecat.purchases.paywalls.components.properties.Size
import com.revenuecat.purchases.paywalls.components.properties.SizeConstraint.Fit
import com.revenuecat.purchases.ui.revenuecatui.components.PaywallAction
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toAlignment
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toFontWeight
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toPaddingValues
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toTextAlign
import com.revenuecat.purchases.ui.revenuecatui.components.stack.StackComponentView
import com.revenuecat.purchases.ui.revenuecatui.components.style.ButtonComponentStyle
import com.revenuecat.purchases.ui.revenuecatui.components.style.StackComponentStyle
Expand Down Expand Up @@ -58,16 +62,16 @@ private fun previewButtonComponentStyle(
light = ColorInfo.Hex(Color.Black.toArgb()),
),
fontSize = FontSize.BODY_M,
fontWeight = FontWeight.REGULAR,
fontWeight = FontWeight.REGULAR.toFontWeight(),
fontFamily = null,
textAlign = HorizontalAlignment.CENTER,
horizontalAlignment = HorizontalAlignment.CENTER,
textAlign = HorizontalAlignment.CENTER.toTextAlign(),
horizontalAlignment = HorizontalAlignment.CENTER.toAlignment(),
backgroundColor = ColorScheme(
light = ColorInfo.Hex(Color.Yellow.toArgb()),
),
size = Size(width = Fit, height = Fit),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0),
margin = Padding(top = 0.0, bottom = 24.0, leading = 0.0, trailing = 24.0),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0).toPaddingValues(),
margin = Padding(top = 0.0, bottom = 24.0, leading = 0.0, trailing = 24.0).toPaddingValues(),
),
),
dimension = Dimension.Vertical(alignment = HorizontalAlignment.CENTER, distribution = START),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ import com.revenuecat.purchases.paywalls.components.properties.TwoDimensionalAli
import com.revenuecat.purchases.paywalls.components.properties.VerticalAlignment
import com.revenuecat.purchases.ui.revenuecatui.components.ComponentView
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toAlignment
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toFontWeight
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toHorizontalAlignmentOrNull
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toHorizontalArrangement
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toPaddingValues
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toTextAlign
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toVerticalAlignmentOrNull
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toVerticalArrangement
import com.revenuecat.purchases.ui.revenuecatui.components.modifier.background
Expand Down Expand Up @@ -195,17 +198,17 @@ private fun StackComponentView_Preview_ZLayer() {
light = ColorInfo.Hex(Color.Black.toArgb()),
),
fontSize = FontSize.BODY_M,
fontWeight = FontWeight.REGULAR,
fontWeight = FontWeight.REGULAR.toFontWeight(),
fontFamily = null,
textAlign = HorizontalAlignment.CENTER,
horizontalAlignment = HorizontalAlignment.CENTER,
textAlign = HorizontalAlignment.CENTER.toTextAlign(),
horizontalAlignment = HorizontalAlignment.CENTER.toAlignment(),
backgroundColor = ColorScheme(
light = ColorInfo.Hex(Color.Yellow.toArgb()),
dark = ColorInfo.Hex(Color.Red.toArgb()),
),
size = Size(width = Fit, height = Fit),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0),
margin = Padding(top = 0.0, bottom = 24.0, leading = 0.0, trailing = 24.0),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0).toPaddingValues(),
margin = Padding(top = 0.0, bottom = 24.0, leading = 0.0, trailing = 24.0).toPaddingValues(),
),
TextComponentStyle(
visible = true,
Expand All @@ -214,16 +217,16 @@ private fun StackComponentView_Preview_ZLayer() {
light = ColorInfo.Hex(Color.Black.toArgb()),
),
fontSize = FontSize.BODY_M,
fontWeight = FontWeight.REGULAR,
fontWeight = FontWeight.REGULAR.toFontWeight(),
fontFamily = null,
textAlign = HorizontalAlignment.CENTER,
horizontalAlignment = HorizontalAlignment.CENTER,
textAlign = HorizontalAlignment.CENTER.toTextAlign(),
horizontalAlignment = HorizontalAlignment.CENTER.toAlignment(),
backgroundColor = ColorScheme(
light = ColorInfo.Hex(Color.Blue.toArgb()),
),
size = Size(width = Fit, height = Fit),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0).toPaddingValues(),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0).toPaddingValues(),
),
),
dimension = Dimension.ZLayer(alignment = TwoDimensionalAlignment.BOTTOM_TRAILING),
Expand Down Expand Up @@ -257,16 +260,16 @@ private fun previewChildren() = listOf(
light = ColorInfo.Hex(Color.Black.toArgb()),
),
fontSize = FontSize.BODY_M,
fontWeight = FontWeight.REGULAR,
fontWeight = FontWeight.REGULAR.toFontWeight(),
fontFamily = null,
textAlign = HorizontalAlignment.CENTER,
horizontalAlignment = HorizontalAlignment.CENTER,
textAlign = HorizontalAlignment.CENTER.toTextAlign(),
horizontalAlignment = HorizontalAlignment.CENTER.toAlignment(),
backgroundColor = ColorScheme(
light = ColorInfo.Hex(Color.Blue.toArgb()),
),
size = Size(width = Fit, height = Fit),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0).toPaddingValues(),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0).toPaddingValues(),
),
TextComponentStyle(
visible = true,
Expand All @@ -275,15 +278,15 @@ private fun previewChildren() = listOf(
light = ColorInfo.Hex(Color.Black.toArgb()),
),
fontSize = FontSize.BODY_M,
fontWeight = FontWeight.REGULAR,
fontWeight = FontWeight.REGULAR.toFontWeight(),
fontFamily = null,
textAlign = HorizontalAlignment.CENTER,
horizontalAlignment = HorizontalAlignment.CENTER,
textAlign = HorizontalAlignment.CENTER.toTextAlign(),
horizontalAlignment = HorizontalAlignment.CENTER.toAlignment(),
backgroundColor = ColorScheme(
light = ColorInfo.Hex(Color.Blue.toArgb()),
),
size = Size(width = Fit, height = Fit),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0),
padding = Padding(top = 8.0, bottom = 8.0, leading = 8.0, trailing = 8.0).toPaddingValues(),
margin = Padding(top = 0.0, bottom = 0.0, leading = 0.0, trailing = 0.0).toPaddingValues(),
),
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package com.revenuecat.purchases.ui.revenuecatui.components.style

import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import com.revenuecat.purchases.paywalls.components.ButtonComponent
Expand All @@ -19,14 +15,15 @@ import com.revenuecat.purchases.ui.revenuecatui.components.ComponentViewState
import com.revenuecat.purchases.ui.revenuecatui.components.LocalizedTextPartial
import com.revenuecat.purchases.ui.revenuecatui.components.PresentedStackPartial
import com.revenuecat.purchases.ui.revenuecatui.components.ScreenCondition
import com.revenuecat.purchases.ui.revenuecatui.components.SystemFontFamily
import com.revenuecat.purchases.ui.revenuecatui.components.buildPresentedPartial
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.string
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toAlignment
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toFontWeight
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toPaddingValues
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toShape
import com.revenuecat.purchases.ui.revenuecatui.components.state.PackageContext
import com.revenuecat.purchases.ui.revenuecatui.components.ktx.toTextAlign
import com.revenuecat.purchases.ui.revenuecatui.components.toPresentedOverrides
import com.revenuecat.purchases.ui.revenuecatui.data.processed.VariableDataProvider
import com.revenuecat.purchases.ui.revenuecatui.data.processed.VariableProcessor
import com.revenuecat.purchases.ui.revenuecatui.errors.PaywallValidationError
import com.revenuecat.purchases.ui.revenuecatui.helpers.NonEmptyList
import com.revenuecat.purchases.ui.revenuecatui.helpers.Result
Expand All @@ -36,25 +33,19 @@ import com.revenuecat.purchases.ui.revenuecatui.helpers.mapOrAccumulate
import com.revenuecat.purchases.ui.revenuecatui.helpers.nonEmptyListOf
import com.revenuecat.purchases.ui.revenuecatui.helpers.orSuccessfullyNull
import com.revenuecat.purchases.ui.revenuecatui.helpers.zipOrAccumulate
import java.util.Locale

@Suppress("LongParameterList")
internal class StyleFactory(
private val windowSize: ScreenCondition,
private val isEligibleForIntroOffer: Boolean,
private val componentState: ComponentViewState,
private val packageContext: PackageContext,
private val localizationDictionary: LocalizationDictionary,
private val locale: Locale,
private val variables: VariableDataProvider,
) {

private companion object {
private const val DEFAULT_SPACING = 0f
private val DEFAULT_SHAPE = RectangleShape
}

@Composable
fun create(component: PaywallComponent): Result<ComponentStyle, NonEmptyList<PaywallValidationError>> =
when (component) {
is ButtonComponent -> TODO("ButtonComponentStyle is not yet implemented.")
Expand All @@ -66,7 +57,6 @@ internal class StyleFactory(
is TextComponent -> createTextComponentStyle(component = component)
}

@Composable
private fun createStackComponentStyle(
component: StackComponent,
): Result<StackComponentStyle, NonEmptyList<PaywallValidationError>> = zipOrAccumulate(
Expand Down Expand Up @@ -102,7 +92,6 @@ internal class StyleFactory(
)
}

@Composable
private fun createTextComponentStyle(
component: TextComponent,
): Result<TextComponentStyle, NonEmptyList<PaywallValidationError>> = zipOrAccumulate(
Expand All @@ -118,72 +107,21 @@ internal class StyleFactory(
) { text, presentedPartial ->
// Combine the text and PresentedPartial into a TextComponentStyle.
val partial = presentedPartial?.partial
val weight = (partial?.fontWeight ?: component.fontWeight).toFontWeight()

TextComponentStyle(
visible = partial?.visible ?: true,
text = rememberProcessedText(
originalText = presentedPartial?.text ?: text,
packageContext = packageContext,
locale = locale,
variables = variables,
),
text = presentedPartial?.text ?: text,
color = partial?.color ?: component.color,
fontSize = partial?.fontSize ?: component.fontSize,
fontWeight = partial?.fontWeight ?: component.fontWeight,
fontFamily = partial?.fontName ?: component.fontName,
textAlign = partial?.horizontalAlignment ?: component.horizontalAlignment,
horizontalAlignment = partial?.horizontalAlignment ?: component.horizontalAlignment,
fontWeight = weight,
fontFamily = (partial?.fontName ?: component.fontName)?.let { SystemFontFamily(it, weight) },
textAlign = (partial?.horizontalAlignment ?: component.horizontalAlignment).toTextAlign(),
horizontalAlignment = (partial?.horizontalAlignment ?: component.horizontalAlignment).toAlignment(),
backgroundColor = partial?.backgroundColor ?: component.backgroundColor,
size = partial?.size ?: component.size,
padding = partial?.padding ?: component.padding,
margin = partial?.margin ?: component.margin,
padding = (partial?.padding ?: component.padding).toPaddingValues(),
margin = (partial?.margin ?: component.margin).toPaddingValues(),
)
}

/**
* Replaces any [variables] in the [originalText] with values based on the currently selected
* [package][PackageContext.selectedPackage] and [locale].
*/
@Composable
private fun rememberProcessedText(
originalText: String,
packageContext: PackageContext,
variables: VariableDataProvider,
locale: Locale,
): String {
val processedText by remember(packageContext, variables, locale) {
derivedStateOf {
packageContext.selectedPackage?.let { selectedPackage ->
val discount = discountPercentage(
pricePerMonthMicros = selectedPackage.product.pricePerMonth()?.amountMicros,
mostExpensiveMicros = packageContext.variableContext.mostExpensivePricePerMonthMicros,
)
val variableContext: VariableProcessor.PackageContext = VariableProcessor.PackageContext(
discountRelativeToMostExpensivePerMonth = discount,
showZeroDecimalPlacePrices = packageContext.variableContext.showZeroDecimalPlacePrices,
)
VariableProcessor.processVariables(
variableDataProvider = variables,
context = variableContext,
originalString = originalText,
rcPackage = selectedPackage,
locale = locale,
)
} ?: originalText
}
}

return processedText
}

private fun discountPercentage(pricePerMonthMicros: Long?, mostExpensiveMicros: Long?): Double? {
if (pricePerMonthMicros == null ||
mostExpensiveMicros == null ||
mostExpensiveMicros <= pricePerMonthMicros
) {
return null
}

return (mostExpensiveMicros - pricePerMonthMicros) / mostExpensiveMicros.toDouble()
}
}
Loading

0 comments on commit ab1b344

Please sign in to comment.