Skip to content

Commit d284dbb

Browse files
committed
chore(flipcash): manually handle price formatting for IAPs
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent c765d70 commit d284dbb

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

apps/flipcash/features/purchase/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ dependencies {
6262
implementation(project(":libs:messaging"))
6363

6464
implementation(project(":services:flipcash"))
65+
implementation(project(":services:opencode"))
6566

6667
implementation(project(":ui:analytics"))
6768
implementation(project(":ui:core"))

apps/flipcash/features/purchase/src/main/kotlin/com/flipcash/app/purchase/internal/PurchaseAccountViewModel.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import com.flipcash.services.billing.BillingClient
1111
import com.flipcash.services.billing.BillingClientState
1212
import com.flipcash.services.billing.IapPaymentEvent
1313
import com.flipcash.services.billing.IapProduct
14+
import com.flipcash.services.billing.ProductPrice
1415
import com.getcode.manager.TopBarManager
16+
import com.getcode.opencode.model.financial.CurrencyCode
17+
import com.getcode.opencode.model.financial.Fiat
1518
import com.getcode.util.resources.ResourceHelper
1619
import com.getcode.view.BaseViewModel2
1720
import com.getcode.view.LoadingSuccessState
@@ -40,7 +43,8 @@ internal class PurchaseAccountViewModel @Inject constructor(
4043
) {
4144
data class State(
4245
internal val productToBuy: IapProduct? = null,
43-
private val costOfAccount: String = "",
46+
internal val costOfAccount: ProductPrice? = null,
47+
private val formattedCost: String = "",
4448
val creatingAccount: LoadingSuccessState = LoadingSuccessState(),
4549
) {
4650
val hasProduct: Boolean
@@ -50,10 +54,10 @@ internal class PurchaseAccountViewModel @Inject constructor(
5054
get() = productToBuy != IapProduct.CreateAccountWithWelcomeBonus
5155

5256
private val safeCost: String
53-
get() = costOfAccount.trim().takeIf { it.isNotEmpty() } ?: if (BuildConfig.DEBUG) "💰💰💰" else "\$XX"
57+
get() = formattedCost.trim().takeIf { it.isNotEmpty() } ?: if (BuildConfig.DEBUG) "💰💰💰" else "\$XX"
5458

5559
private val safeReward: String
56-
get() = costOfAccount.trim().takeIf { it.isNotEmpty() } ?: if (BuildConfig.DEBUG) "¯\\_(ツ)_/¯" else "\$XX"
60+
get() = formattedCost.trim().takeIf { it.isNotEmpty() } ?: if (BuildConfig.DEBUG) "¯\\_(ツ)_/¯" else "\$XX"
5761

5862
private val titleForWelcomeBonus: String
5963
@Composable get() = stringResource(R.string.title_finalizeAccountCreationWithWelcomeBonus, safeCost, safeReward)
@@ -83,7 +87,8 @@ internal class PurchaseAccountViewModel @Inject constructor(
8387
}
8488

8589
sealed interface Event {
86-
data class OnProductChanged(val product: IapProduct, val cost: String) : Event
90+
data class OnProductChanged(val product: IapProduct, val cost: ProductPrice?) : Event
91+
data class OnPriceFormatted(val cost: String): Event
8792
data class BuyAccount(val activity: Activity) : Event
8893
data class OnCreatingChanged(val creating: Boolean, val created: Boolean = false) : Event
8994
data object OnAccountCreated : Event
@@ -109,6 +114,13 @@ internal class PurchaseAccountViewModel @Inject constructor(
109114
)
110115
}.launchIn(viewModelScope)
111116

117+
stateFlow
118+
.mapNotNull { it.costOfAccount }
119+
.map { it.amount to (CurrencyCode.tryValueOf(it.currency) ?: CurrencyCode.USD) }
120+
.map { (amount, currency) -> Fiat(amount, currency) }
121+
.onEach { dispatchEvent(Event.OnPriceFormatted(it.formatted(truncated = true))) }
122+
.launchIn(viewModelScope)
123+
112124
eventFlow
113125
.filterIsInstance<Event.BuyAccount>()
114126
.mapNotNull {
@@ -160,14 +172,15 @@ internal class PurchaseAccountViewModel @Inject constructor(
160172

161173
companion object {
162174
val updateStateForEvent: (Event) -> ((State) -> State) = { event ->
163-
println("PurchaseAccountViewModel.updateStateForEvent $event")
164175
when (event) {
165176
Event.OnAccountCreated -> { state -> state }
166177
is Event.BuyAccount -> { state -> state }
167178
is Event.OnProductChanged -> { state ->
168179
state.copy(productToBuy = event.product, costOfAccount = event.cost)
169180
}
170181

182+
is Event.OnPriceFormatted -> { state -> state.copy(formattedCost = event.cost) }
183+
171184
is Event.OnCreatingChanged -> { state ->
172185
state.copy(
173186
creatingAccount = LoadingSuccessState(

services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ data class Fiat(
4646
// Formatting
4747
fun formatted(suffix: String? = null, truncated: Boolean = false): String {
4848
val formatter = android.icu.text.DecimalFormat.getInstance(ULocale.US).apply {
49-
minimumFractionDigits = 2
50-
maximumFractionDigits = 2
49+
minimumFractionDigits = if (truncated) 0 else 2
50+
maximumFractionDigits = if (truncated) 0 else 2
5151
roundingMode = if (truncated) RoundingMode.DOWN.ordinal else RoundingMode.HALF_DOWN.ordinal
5252
(this as android.icu.text.DecimalFormat).decimalFormatSymbols = decimalFormatSymbols.apply {
5353
currencySymbol = ""

0 commit comments

Comments
 (0)