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

[Paywalls V2] LocalizationKey is an inline value class now. #1936

Merged
merged 93 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 92 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
aaa66b6
Adds ImageUrls and tests.
JayShortway Nov 20, 2024
e41629c
Adds ColorInfo and tests.
JayShortway Nov 20, 2024
ff61b28
Moves and adjusts parseRGBAColor() from PaywallColor so it can be use…
JayShortway Nov 20, 2024
0891b50
ColorInfo.Hex contains a ColorInt now instead of a string.
JayShortway Nov 20, 2024
31fde3e
Adjusts a comment.
JayShortway Nov 20, 2024
4153ef3
Adds CornerRadiuses and tests.
JayShortway Nov 20, 2024
1f25a47
Adds Shape and tests.
JayShortway Nov 20, 2024
584fd0a
Adds MaskShape and tests.
JayShortway Nov 20, 2024
740b124
Adds Padding and tests.
JayShortway Nov 20, 2024
7d5152a
Adds Size, SizeConstraint and tests.
JayShortway Nov 20, 2024
c1992b5
Adds Shadow and tests.
JayShortway Nov 20, 2024
9fbf37f
Adds FlexDistribution and tests.
JayShortway Nov 21, 2024
ab136d6
Adds Alignment and tests.
JayShortway Nov 21, 2024
2390dcc
Adds Font and tests.
JayShortway Nov 21, 2024
5e4c618
Adds FitMode and tests.
JayShortway Nov 21, 2024
64d92ed
Adds with and height properties to ImageUrls.
JayShortway Nov 21, 2024
03c4990
Adds TextComponent and tests.
JayShortway Nov 21, 2024
f7b1aeb
ColorInfo is now a sealed interface instead of a sealed class.
JayShortway Nov 21, 2024
21f9a72
Shape and MaskShape are now sealed interfaces instead of a sealed cla…
JayShortway Nov 21, 2024
a7e6ba7
SizeConstraint is now a sealed interface instead of a sealed class.
JayShortway Nov 21, 2024
d474209
Merge branch 'pw2-properties-images-colors' into pw2-properties-shapes
JayShortway Nov 21, 2024
8ce7f2e
Merge branch 'pw2-properties-shapes' into pw2-properties-size-padding
JayShortway Nov 21, 2024
7ab6cee
Merge branch 'pw2-properties-size-padding' into pw2-properties-enums
JayShortway Nov 21, 2024
0586214
Merge branch 'pw2-properties-enums' into pw2-textcomponent
JayShortway Nov 21, 2024
6c1a8c5
Adds ImageComponent and tests.
JayShortway Nov 21, 2024
40ac835
Adds Linear and Radial gradients to ColorInfo.
JayShortway Nov 21, 2024
d2eba36
Merge branch 'pw2-properties-images-colors' into pw2-properties-shapes
JayShortway Nov 21, 2024
c77b8d9
Merge branch 'pw2-properties-shapes' into pw2-properties-size-padding
JayShortway Nov 21, 2024
25422b4
Merge branch 'pw2-properties-size-padding' into pw2-properties-enums
JayShortway Nov 21, 2024
199e962
Merge branch 'pw2-properties-enums' into pw2-textcomponent
JayShortway Nov 21, 2024
6f51252
Merge branch 'pw2-textcomponent' into pw2-imagecomponent
JayShortway Nov 21, 2024
faa0bfd
Adds ComponentOverrides.
JayShortway Nov 21, 2024
f121f4e
Adds PartialTextComponent and PartialImageComponent.
JayShortway Nov 21, 2024
84024d1
Adds tests for PartialTextComponent and PartialImageComponent.
JayShortway Nov 21, 2024
81cc4c9
Adds ComponentOverridesTests.
JayShortway Nov 21, 2024
6da048a
Adds Dimension and tests.
JayShortway Nov 21, 2024
ad85fdd
Adds Border and tests.
JayShortway Nov 21, 2024
2d42d98
Adds StackComponent and tests.
JayShortway Nov 21, 2024
6894d50
Merge branch 'main' into pw2-properties-shapes
JayShortway Nov 22, 2024
fc970b8
Merge branch 'pw2-properties-shapes' into pw2-properties-size-padding
JayShortway Nov 22, 2024
1ae2f89
Merge branch 'pw2-properties-size-padding' into pw2-properties-enums
JayShortway Nov 22, 2024
38def75
Merge branch 'pw2-properties-enums' into pw2-textcomponent
JayShortway Nov 22, 2024
9491eeb
Merge branch 'pw2-textcomponent' into pw2-imagecomponent
JayShortway Nov 22, 2024
ca6d5dc
Merge branch 'pw2-imagecomponent' into pw2-overrides
JayShortway Nov 22, 2024
bdf7fc9
Merge branch 'pw2-overrides' into pw2-stackcomponent
JayShortway Nov 22, 2024
e3153e3
Merge branch 'main' into pw2-properties-size-padding
JayShortway Nov 22, 2024
b03c253
Merge branch 'pw2-properties-size-padding' into pw2-properties-enums
JayShortway Nov 22, 2024
f5be3cb
Merge branch 'pw2-properties-enums' into pw2-textcomponent
JayShortway Nov 22, 2024
66041c2
Merge branch 'pw2-textcomponent' into pw2-imagecomponent
JayShortway Nov 22, 2024
6ceea3b
Merge branch 'pw2-imagecomponent' into pw2-overrides
JayShortway Nov 22, 2024
fae7d40
Merge branch 'pw2-overrides' into pw2-stackcomponent
JayShortway Nov 22, 2024
3174a94
Adds ButtonComponent and tests.
JayShortway Nov 22, 2024
6d1caf0
Updates a comment.
JayShortway Nov 22, 2024
9e69018
Merge branch 'main' into pw2-properties-enums
JayShortway Nov 22, 2024
1e4a7d3
Adds PackageComponent and tests.
JayShortway Nov 22, 2024
3f4ec6f
Merge branch 'pw2-properties-enums' into pw2-textcomponent
JayShortway Nov 22, 2024
e7a047b
Merge branch 'pw2-textcomponent' into pw2-imagecomponent
JayShortway Nov 22, 2024
577fba8
Merge branch 'pw2-imagecomponent' into pw2-overrides
JayShortway Nov 22, 2024
bf26c54
Merge branch 'pw2-overrides' into pw2-stackcomponent
JayShortway Nov 22, 2024
7fc7476
Merge branch 'pw2-stackcomponent' into pw2-buttoncomponent
JayShortway Nov 22, 2024
8f008bc
Merge branch 'pw2-buttoncomponent' into pw2-packagecomponent
JayShortway Nov 22, 2024
0d4fe06
Merge branch 'main' into pw2-textcomponent
JayShortway Nov 22, 2024
ee3fcc7
Adds PurchaseButtonComponent and tests.
JayShortway Nov 22, 2024
4d8e616
Merge branch 'pw2-textcomponent' into pw2-imagecomponent
JayShortway Nov 22, 2024
c464fc4
Merge branch 'pw2-imagecomponent' into pw2-overrides
JayShortway Nov 22, 2024
47430db
Merge branch 'pw2-overrides' into pw2-stackcomponent
JayShortway Nov 22, 2024
881fe64
Merge branch 'pw2-stackcomponent' into pw2-buttoncomponent
JayShortway Nov 22, 2024
287e471
Merge branch 'pw2-buttoncomponent' into pw2-packagecomponent
JayShortway Nov 22, 2024
422ddc9
Merge branch 'pw2-packagecomponent' into pw2-purchasebuttoncomponent
JayShortway Nov 22, 2024
20dea35
Adds StickyFooterComponent and tests.
JayShortway Nov 22, 2024
68c5091
Merge branch 'main' into pw2-imagecomponent
JayShortway Nov 22, 2024
8942966
Merge branch 'pw2-imagecomponent' into pw2-overrides
JayShortway Nov 22, 2024
6808659
Merge branch 'pw2-overrides' into pw2-stackcomponent
JayShortway Nov 22, 2024
aef40eb
Merge branch 'pw2-stackcomponent' into pw2-buttoncomponent
JayShortway Nov 22, 2024
3cd711c
Merge branch 'pw2-buttoncomponent' into pw2-packagecomponent
JayShortway Nov 22, 2024
426930e
Merge branch 'pw2-packagecomponent' into pw2-purchasebuttoncomponent
JayShortway Nov 22, 2024
1c6a7e1
Merge branch 'pw2-purchasebuttoncomponent' into pw2-stickyfootercompo…
JayShortway Nov 22, 2024
fa3b7ad
Adds ComponentsConfig and tests.
JayShortway Nov 22, 2024
a509254
Adds LocalizationData and tests.
JayShortway Nov 22, 2024
fb91be8
Adds PaywallComponentsData and tests.
JayShortway Nov 22, 2024
cbc6747
Adds Background and tests.
JayShortway Nov 22, 2024
1f4451f
Merge branch 'main' into pw2-buttoncomponent
JayShortway Nov 22, 2024
9c915db
Merge branch 'pw2-buttoncomponent' into pw2-packagecomponent
JayShortway Nov 22, 2024
f0a6724
Merge branch 'pw2-packagecomponent' into pw2-purchasebuttoncomponent
JayShortway Nov 22, 2024
c9fcf24
Merge branch 'pw2-purchasebuttoncomponent' into pw2-stickyfootercompo…
JayShortway Nov 22, 2024
5b7031a
Merge branch 'pw2-stickyfootercomponent' into pw2-paywallcomponentsdata
JayShortway Nov 22, 2024
83bdc71
LocalizationKey is an inline value class now.
JayShortway Nov 22, 2024
8d24d9a
Merge branch 'main' into pw2-stickyfootercomponent
JayShortway Nov 25, 2024
ae085c5
Merge branch 'pw2-stickyfootercomponent' into pw2-paywallcomponentsdata
JayShortway Nov 25, 2024
420b236
Merge branch 'pw2-paywallcomponentsdata' into pw2-localizationkey
JayShortway Nov 25, 2024
3176104
Merge branch 'main' into pw2-paywallcomponentsdata
JayShortway Nov 25, 2024
938fc43
Merge branch 'pw2-paywallcomponentsdata' into pw2-localizationkey
JayShortway Nov 25, 2024
586b7c6
Merge branch 'main' into pw2-localizationkey
JayShortway Nov 25, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.paywalls.components.properties.ColorScheme
import com.revenuecat.purchases.paywalls.components.properties.ThemeImageUrls
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
internal sealed interface Background {
@Serializable
@SerialName("color")
data class Color(val value: ColorScheme) : Background

@Serializable
@SerialName("image")
data class Image(val value: ThemeImageUrls) : Background
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.revenuecat.purchases.paywalls.components

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
internal data class ComponentsConfig(
val base: PaywallComponentsConfig,
)

@Serializable
internal data class PaywallComponentsConfig(
val stack: StackComponent,
val background: Background,
@SerialName("sticky_footer")
val stickyFooter: StickyFooterComponent? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.paywalls.components.properties.ThemeImageUrls
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.descriptors.PolymorphicKind
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

@Serializable
@JvmInline
internal value class LocaleId(val value: String)

@Serializable
@JvmInline
internal value class LocalizationKey(val value: String)
Comment on lines +19 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally know what a @JvmInline is... yup yup yup 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, this instructs the Kotlin compiler to make it a value class from a Java perspective.


internal typealias LocalizationDictionary = Map<LocalizationKey, LocalizationData>

/**
* A make-shift union type. LocalizationData is either a plain String or a ThemeImageUrls object.
*/
@Serializable(with = LocalizationDataSerializer::class)
internal sealed interface LocalizationData {
@Serializable
@JvmInline
value class Text(val value: String) : LocalizationData

@Serializable
@JvmInline
value class Image(val value: ThemeImageUrls) : LocalizationData
}

private object LocalizationDataSerializer : KSerializer<LocalizationData> {
// Documentation says to use either PrimitiveSerialDescriptor or buildClassSerialDescriptor. However, we need a
// polymorphic descriptor that's either a primitive (string) or a class. So neither of those options fit the bill.
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
override val descriptor: SerialDescriptor = buildSerialDescriptor(
serialName = "LocalizationData",
kind = PolymorphicKind.SEALED,
)

override fun serialize(encoder: Encoder, value: LocalizationData) {
error("Serialization is not implemented as it is not (yet) needed.")
}

@Suppress("SwallowedException")
override fun deserialize(decoder: Decoder): LocalizationData =
// We have no `type` descriptor field, so we resort to trial and error.
try {
decoder.decodeSerializableValue(LocalizationData.Text.serializer())
} catch (e: SerializationException) {
decoder.decodeSerializableValue(LocalizationData.Image.serializer())
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.utils.serializers.URLSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.net.URL

@Serializable
internal data class PaywallComponentsData(
@SerialName("template_name")
val templateName: String,
@Serializable(with = URLSerializer::class)
@SerialName("asset_base_url")
val assetBaseURL: URL,
@SerialName("components_config")
val componentsConfig: ComponentsConfig,
@SerialName("components_localizations")
val componentsLocalizations: Map<LocaleId, LocalizationDictionary>,
@SerialName("default_locale")
val defaultLocaleIdentifier: LocaleId,
val revision: Int = 0,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.revenuecat.purchases.paywalls.components

import com.revenuecat.purchases.common.OfferingParser
import com.revenuecat.purchases.paywalls.components.properties.ColorInfo
import com.revenuecat.purchases.paywalls.components.properties.ColorScheme
import com.revenuecat.purchases.paywalls.components.properties.ImageUrls
import com.revenuecat.purchases.paywalls.components.properties.ThemeImageUrls
import org.intellij.lang.annotations.Language
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.net.URL

@RunWith(Parameterized::class)
internal class BackgroundTests(@Suppress("UNUSED_PARAMETER") name: String, private val args: Args) {

class Args(
@Language("json")
val json: String,
val expected: Background,
)

companion object {

@Suppress("LongMethod")
@JvmStatic
@Parameterized.Parameters(name = "{0}")
fun parameters(): Collection<*> = listOf(
arrayOf(
"String",
Args(
json = """
{
"type": "color",
"value": {
"light": {
"type": "alias",
"value": "primary"
}
}
}
""".trimIndent(),
expected = Background.Color(
value = ColorScheme(
light = ColorInfo.Alias("primary")
)
),
),
),
arrayOf(
"ThemeImageUrls",
Args(
json = """
{
"type": "image",
"value": {
"light": {
"heic": "https://assets.pawwalls.com/1151049_1732039548.heic",
"heic_low_res": "https://assets.pawwalls.com/1151049_low_res_1732039548.heic",
"original": "https://assets.pawwalls.com/1151049_1732039548.png",
"webp": "https://assets.pawwalls.com/1151049_1732039548.webp",
"webp_low_res": "https://assets.pawwalls.com/1151049_low_res_1732039548.webp",
"width": 2345,
"height": 1234
}
}
}
""".trimIndent(),
expected = Background.Image(
value = ThemeImageUrls(
light = ImageUrls(
original = URL("https://assets.pawwalls.com/1151049_1732039548.png"),
webp = URL("https://assets.pawwalls.com/1151049_1732039548.webp"),
webpLowRes = URL("https://assets.pawwalls.com/1151049_low_res_1732039548.webp"),
width = 2345.toUInt(),
height = 1234.toUInt(),
)
)
),
),
),
)
}

@Test
fun `Should properly deserialize Background`() {
// Arrange, Act
val actual = OfferingParser.json.decodeFromString<Background>(args.json)

// Assert
assert(actual == args.expected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down Expand Up @@ -104,7 +104,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down Expand Up @@ -149,7 +149,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down Expand Up @@ -201,7 +201,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down Expand Up @@ -253,7 +253,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down Expand Up @@ -305,7 +305,7 @@ internal class ButtonComponentTests {
stack = StackComponent(
components = listOf(
TextComponent(
text = "7bkohQjzIE",
text = LocalizationKey("7bkohQjzIE"),
color = ColorScheme(light = ColorInfo.Alias("primary"))
)
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@ internal class ComponentOverridesTests {
}
""".trimIndent(),
expected = ComponentOverrides(
introOffer = PartialImageComponent(overrideSourceLid = "intro"),
introOffer = PartialImageComponent(overrideSourceLid = LocalizationKey("intro")),
states = ComponentStates(
selected = PartialImageComponent(overrideSourceLid = "selected")
selected = PartialImageComponent(overrideSourceLid = LocalizationKey("selected"))
),
conditions = ComponentConditions(
compact = PartialImageComponent(overrideSourceLid = "compact"),
medium = PartialImageComponent(overrideSourceLid = "medium"),
expanded = PartialImageComponent(overrideSourceLid = "expanded"),
compact = PartialImageComponent(overrideSourceLid = LocalizationKey("compact")),
medium = PartialImageComponent(overrideSourceLid = LocalizationKey("medium")),
expanded = PartialImageComponent(overrideSourceLid = LocalizationKey("expanded")),
)
)
)
Expand Down
Loading