Skip to content
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
- PREFER to use one-liners with `run {}` when applicable, e.g. `override fun someCall(value: String) = run { this.value = value }`
- ALWAYS add imports instead of inline fully-qualified names
- PREFER to place `@Suppress()` annotations at the narrowest possible scope
- ALWAYS wrap suspend functions in `withContext(bgDispatcher)` if in domain layer, using ctor injected prop `@BgDispatcher private val bgDispatcher: CoroutineDispatcher`

### Architecture Guidelines

Expand Down
14 changes: 8 additions & 6 deletions app/src/main/java/to/bitkit/di/EnvModule.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package to.bitkit.di

import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import org.lightningdevkit.ldknode.Network
import to.bitkit.env.Env
import java.util.Locale
import kotlin.time.Clock
import kotlin.time.ExperimentalTime

Expand All @@ -14,13 +17,12 @@ import kotlin.time.ExperimentalTime
object EnvModule {

@Provides
fun provideNetwork(): Network {
return Env.network
}
fun provideNetwork(): Network = Env.network

@OptIn(ExperimentalTime::class)
@Provides
fun provideClock(): Clock {
return Clock.System
}
fun provideClock(): Clock = Clock.System

@Provides
fun provideLocale(@ApplicationContext context: Context): Locale = context.resources.configuration.locales[0]
}
18 changes: 14 additions & 4 deletions app/src/main/java/to/bitkit/models/Currency.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,27 @@ data class ConvertedAmount(
)

fun bitcoinDisplay(unit: BitcoinDisplayUnit): BitcoinDisplayComponents {
val formattedValue = when (unit) {
BitcoinDisplayUnit.MODERN -> sats.formatToModernDisplay(locale)
BitcoinDisplayUnit.CLASSIC -> sats.formatToClassicDisplay(locale)
}
val formattedValue = sats.formatMoney(unit, locale)
return BitcoinDisplayComponents(
symbol = BITCOIN_SYMBOL,
value = formattedValue,
)
}
}

fun Long.formatMoney(
unit: BitcoinDisplayUnit,
locale: Locale = Locale.getDefault(),
): String = when (unit) {
BitcoinDisplayUnit.MODERN -> formatToModernDisplay(locale)
BitcoinDisplayUnit.CLASSIC -> formatToClassicDisplay(locale)
}

fun ULong.formatMoney(
unit: BitcoinDisplayUnit,
locale: Locale = Locale.getDefault(),
): String = toLong().formatMoney(unit, locale)

fun Long.formatToModernDisplay(locale: Locale = Locale.getDefault()): String {
val sats = this
val symbols = DecimalFormatSymbols(locale).apply {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/to/bitkit/services/CoreService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ class ActivityService(
)
}

@Suppress("CyclomaticComplexMethod")
private suspend fun processOnchainPayment(
kind: PaymentKind.Onchain,
payment: PaymentDetails,
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/to/bitkit/services/MigrationService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ class MigrationService @Inject constructor(
}
}

@Suppress("CyclomaticComplexMethod")
@Suppress("CyclomaticComplexMethod", "LongMethod")
private suspend fun updateOnchainActivityMetadata(
item: RNActivityItem,
onchain: OnchainActivity,
Expand Down
23 changes: 23 additions & 0 deletions app/src/main/java/to/bitkit/usecases/FormatMoneyValue.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package to.bitkit.usecases

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import to.bitkit.data.SettingsStore
import to.bitkit.di.BgDispatcher
import to.bitkit.models.formatMoney
import java.util.Locale
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class FormatMoneyValue @Inject constructor(
@BgDispatcher private val bgDispatcher: CoroutineDispatcher,
private val settingsStore: SettingsStore,
private val locale: Locale,
) {
suspend operator fun invoke(sats: ULong): String = withContext(bgDispatcher) {
val unit = settingsStore.data.first().displayUnit
sats.formatMoney(unit, locale)
}
}
14 changes: 8 additions & 6 deletions app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import to.bitkit.ui.shared.toast.ToastEventBus
import to.bitkit.ui.shared.toast.ToastQueueManager
import to.bitkit.ui.sheets.SendRoute
import to.bitkit.ui.theme.TRANSITION_SCREEN_MS
import to.bitkit.usecases.FormatMoneyValue
import to.bitkit.utils.Bip21Utils
import to.bitkit.utils.Logger
import to.bitkit.utils.NetworkValidationHelper
Expand Down Expand Up @@ -153,6 +154,7 @@ class AppViewModel @Inject constructor(
private val notificationsSheet: NotificationsTimedSheet,
private val quickPaySheet: QuickPayTimedSheet,
private val highBalanceSheet: HighBalanceTimedSheet,
private val formatMoneyValue: FormatMoneyValue,
) : ViewModel() {
val healthState = healthRepo.healthState

Expand Down Expand Up @@ -748,7 +750,7 @@ class AppViewModel @Inject constructor(
showAddressValidationError(
titleRes = R.string.other__pay_insufficient_spending,
descriptionRes = R.string.other__pay_insufficient_spending_amount_description,
descriptionArgs = mapOf("amount" to shortfall.toString()),
descriptionArgs = mapOf("amount" to formatMoneyValue(shortfall)),
testTag = "InsufficientSpendingToast",
)
return
Expand All @@ -758,7 +760,7 @@ class AppViewModel @Inject constructor(
_sendUiState.update { it.copy(isAddressInputValid = true) }
}

private fun validateOnChainAddress(invoice: OnChainInvoice) {
private suspend fun validateOnChainAddress(invoice: OnChainInvoice) {
val validatedAddress = runCatching { validateBitcoinAddress(invoice.address) }
.getOrElse {
showAddressValidationError(
Expand Down Expand Up @@ -794,7 +796,7 @@ class AppViewModel @Inject constructor(
showAddressValidationError(
titleRes = R.string.other__pay_insufficient_savings,
descriptionRes = R.string.other__pay_insufficient_savings_amount_description,
descriptionArgs = mapOf("amount" to shortfall.toString()),
descriptionArgs = mapOf("amount" to formatMoneyValue(shortfall)),
testTag = "InsufficientSavingsToast",
)
return
Expand Down Expand Up @@ -915,7 +917,7 @@ class AppViewModel @Inject constructor(
type = Toast.ToastType.ERROR,
title = context.getString(R.string.wallet__lnurl_pay__error_min__title),
description = context.getString(R.string.wallet__lnurl_pay__error_min__description)
.replace("{amount}", minSendable.toString()),
.replace("{amount}", formatMoneyValue(minSendable)),
testTag = "LnurlPayAmountTooLowToast",
)
return
Expand Down Expand Up @@ -1125,7 +1127,7 @@ class AppViewModel @Inject constructor(
type = Toast.ToastType.ERROR,
title = context.getString(R.string.other__pay_insufficient_savings),
description = context.getString(R.string.other__pay_insufficient_savings_amount_description)
.replace("{amount}", shortfall.toString()),
.replace("{amount}", formatMoneyValue(shortfall)),
testTag = "InsufficientSavingsToast",
)
return
Expand Down Expand Up @@ -1167,7 +1169,7 @@ class AppViewModel @Inject constructor(
type = Toast.ToastType.ERROR,
title = context.getString(R.string.other__pay_insufficient_spending),
description = context.getString(R.string.other__pay_insufficient_spending_amount_description)
.replace("{amount}", shortfall.toString()),
.replace("{amount}", formatMoneyValue(shortfall)),
testTag = "InsufficientSpendingToast",
)
return
Expand Down
Loading