Skip to content

Commit

Permalink
Merge branch 'shorten-big-prices'
Browse files Browse the repository at this point in the history
  • Loading branch information
shorthouse committed Apr 2, 2024
2 parents a0ac4cb + c9f30fb commit 0ce4588
Show file tree
Hide file tree
Showing 3 changed files with 571 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ class DetailsScreenTest {
onNodeWithText("Market Cap Rank").assertIsDisplayed()
onNodeWithText("2").assertIsDisplayed()
onNodeWithText("Market Cap").assertIsDisplayed()
onNodeWithText("$225,722,901,094.00").assertIsDisplayed()
onNodeWithText("$225.72B").assertIsDisplayed()
onNodeWithText("Volume (24h)").assertIsDisplayed()
onNodeWithText("$6,627,669,115.00").assertIsDisplayed()
onNodeWithText("$6.63B").assertIsDisplayed()
onNodeWithText("Circulating Supply").assertIsDisplayed()
onNodeWithText("120,186,525").assertIsDisplayed()
onNodeWithText("All Time High").assertIsDisplayed()
Expand Down Expand Up @@ -518,9 +518,9 @@ class DetailsScreenTest {
onNodeWithText("Market Cap Rank").assertIsDisplayed()
onNodeWithText("2").assertIsDisplayed()
onNodeWithText("Market Cap").assertIsDisplayed()
onNodeWithText("£225,722,901,094.00").assertIsDisplayed()
onNodeWithText("£225.72B").assertIsDisplayed()
onNodeWithText("Volume (24h)").assertIsDisplayed()
onNodeWithText("$6,627,669,115.00").assertIsDisplayed()
onNodeWithText("$6.63B").assertIsDisplayed()
onNodeWithText("Circulating Supply").assertIsDisplayed()
onNodeWithText("120,186,525").assertIsDisplayed()
onNodeWithText("All Time High ($)").assertIsDisplayed()
Expand All @@ -531,4 +531,93 @@ class DetailsScreenTest {
onNodeWithText("7 Aug 2015").assertIsDisplayed()
}
}

@Test
fun when_pricesAreLarge_should_showShortenedPrices() {
val uiStateSuccess = DetailsUiState.Success(
CoinDetails(
id = "ethereum",
name = "Ethereum",
symbol = "ETH",
imageUrl = "https://cdn.coinranking.com/rk4RKHOuW/eth.svg",
currentPrice = Price("1879.14"),
marketCap = Price("49491394.23440234"),
marketCapRank = "2",
volume24h = Price("1009900243"),
circulatingSupply = "120,186,525",
allTimeHigh = Price("3084938574102"),
allTimeHighDate = "10 Nov 2021",
listedDate = "7 Aug 2015"
),
CoinChart(
prices = persistentListOf(
BigDecimal("1755.19"),
BigDecimal("1749.71"),
BigDecimal("1750.94"),
BigDecimal("1748.44"),
BigDecimal("1743.98"),
BigDecimal("1740.25")
),
minPrice = Price("1632.46"),
maxPrice = Price("1922.83"),
periodPriceChangePercentage = Percentage("7.06")
),
chartPeriod = ChartPeriod.Day,
isCoinFavourite = true
)

composeTestRule.setContent {
AppTheme {
DetailsScreen(
uiState = uiStateSuccess,
onNavigateUp = {},
onClickFavouriteCoin = {},
onClickChartPeriod = {}
)
}
}

composeTestRule.apply {
onNodeWithContentDescription("Back").assertIsDisplayed()
onNodeWithContentDescription("Favourite").assertIsDisplayed()

onNodeWithText("Ethereum").assertIsDisplayed()
onNodeWithText("ETH").assertIsDisplayed()
onNodeWithText("$1,879.14").assertIsDisplayed()
onNodeWithText("+7.06%").assertIsDisplayed()
onNodeWithText("Past day").assertIsDisplayed()

onNodeWithText("1H").assertIsDisplayed()
onNodeWithText("1D").assertIsDisplayed()
onNodeWithText("1W").assertIsDisplayed()
onNodeWithText("1M").assertIsDisplayed()
onNodeWithText("3M").assertIsDisplayed()
onNodeWithText("1Y").assertIsDisplayed()
onNodeWithText("5Y").assertIsDisplayed()

onNodeWithText("Chart Range").assertIsDisplayed()
onNodeWithText("Low").assertIsDisplayed()
onNodeWithText("$1,632.46").assertIsDisplayed()
onNodeWithText("High").assertIsDisplayed()
onNodeWithText("$1,922.83").assertIsDisplayed()

onNodeWithText("7 Aug 2015").performScrollTo()

onNodeWithText("Market Stats").assertIsDisplayed()
onNodeWithText("Market Cap Rank").assertIsDisplayed()
onNodeWithText("2").assertIsDisplayed()
onNodeWithText("Market Cap").assertIsDisplayed()
onNodeWithText("$49.49M").assertIsDisplayed()
onNodeWithText("Volume (24h)").assertIsDisplayed()
onNodeWithText("$1.01B").assertIsDisplayed()
onNodeWithText("Circulating Supply").assertIsDisplayed()
onNodeWithText("120,186,525").assertIsDisplayed()
onNodeWithText("All Time High").assertIsDisplayed()
onNodeWithText("$3.08T").assertIsDisplayed()
onNodeWithText("All Time High Date").assertIsDisplayed()
onNodeWithText("10 Nov 2021").assertIsDisplayed()
onNodeWithText("Listed Date").assertIsDisplayed()
onNodeWithText("7 Aug 2015").assertIsDisplayed()
}
}
}
81 changes: 55 additions & 26 deletions app/src/main/java/dev/shorthouse/coinwatch/model/Price.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,74 @@ package dev.shorthouse.coinwatch.model
import dev.shorthouse.coinwatch.common.toSanitisedBigDecimalOrZero
import dev.shorthouse.coinwatch.data.preferences.global.Currency
import java.math.BigDecimal
import java.math.MathContext
import java.math.RoundingMode
import java.text.DecimalFormat
import java.util.Currency as CurrencyCode
import java.util.Locale
import java.util.Currency as CurrencyCode

data class Price(val price: String?, val currency: Currency = Currency.USD) : Comparable<Price> {
companion object {
private val precisionThreshold = BigDecimal("-1.00")..BigDecimal("1.00")
val amount: BigDecimal = price.toSanitisedBigDecimalOrZero()

private fun createCurrencyFormat(decimalPlaces: Int, currency: Currency): DecimalFormat {
val currencyFormat = DecimalFormat.getCurrencyInstance(Locale.US) as DecimalFormat
private val currencyFormat by lazy {
val currencyFormat = DecimalFormat.getCurrencyInstance(Locale.US) as DecimalFormat

currencyFormat.minimumFractionDigits = decimalPlaces
currencyFormat.maximumFractionDigits = decimalPlaces
val decimalPlaces = if (amount in belowOneThreshold) 6 else 2
val currencyCode = try {
CurrencyCode.getInstance(currency.name)
} catch (e: IllegalArgumentException) {
CurrencyCode.getInstance(Currency.USD.name)
}

val currencyCode = try {
CurrencyCode.getInstance(currency.name)
} catch (e: IllegalArgumentException) {
CurrencyCode.getInstance(Currency.USD.name)
}
currencyFormat.currency = currencyCode
currencyFormat.minimumFractionDigits = decimalPlaces
currencyFormat.maximumFractionDigits = decimalPlaces
currencyFormat.currency = currencyCode

return currencyFormat
}
currencyFormat
}

val amount: BigDecimal = price.toSanitisedBigDecimalOrZero()
val formattedAmount: String = when {
price.isNullOrBlank() -> "${currency.symbol}--"
amount in belowOneThreshold || amount in smallThreshold -> currencyFormat.format(amount)
else -> {
val roundedAmount = amount.round(MathContext(5, RoundingMode.HALF_EVEN))

private val currencyFormat = if (amount in precisionThreshold) {
createCurrencyFormat(decimalPlaces = 6, currency = currency)
} else {
createCurrencyFormat(decimalPlaces = 2, currency = currency)
}
val divisor = when (roundedAmount) {
in millionThreshold -> million
in billionThreshold -> billion
in trillionThreshold -> trillion
in quadrillionThreshold -> quadrillion
else -> BigDecimal.ONE
}

val symbol = when (roundedAmount) {
in millionThreshold -> "M"
in billionThreshold -> "B"
in trillionThreshold -> "T"
in quadrillionThreshold -> "Q"
else -> ""
}

val shortenedAmount = amount.divide(divisor, 2, RoundingMode.HALF_EVEN)

val formattedAmount: String = when (price) {
null -> "${currency.symbol} --"
else -> currencyFormat.format(amount)
currencyFormat.format(shortenedAmount) + symbol
}
}

override fun compareTo(other: Price): Int {
return amount.compareTo(other.amount)
override fun compareTo(other: Price) = amount.compareTo(other.amount)

companion object {
private val million = BigDecimal("1000000")
private val billion = BigDecimal("1000000000")
private val trillion = BigDecimal("1000000000000")
private val quadrillion = BigDecimal("1000000000000000")
private val quintillion = BigDecimal("1000000000000000000")

private val belowOneThreshold = BigDecimal("-1.00")..BigDecimal("1.00")
private val smallThreshold = BigDecimal("1.00")..<million
private val millionThreshold = million..<billion
private val billionThreshold = billion..<trillion
private val trillionThreshold = trillion..<quadrillion
private val quadrillionThreshold = quadrillion..<quintillion
}
}
Loading

0 comments on commit 0ce4588

Please sign in to comment.