mirror of
https://github.com/mollyim/monero-wallet-sdk.git
synced 2025-01-12 07:59:30 -05:00
demo: add initial balance view
This commit is contained in:
parent
471f22777c
commit
a84375d384
@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.onStart
|
|||||||
sealed interface Result<out T> {
|
sealed interface Result<out T> {
|
||||||
data class Success<T>(val data: T) : Result<T>
|
data class Success<T>(val data: T) : Result<T>
|
||||||
data class Error(val exception: Throwable? = null) : Result<Nothing>
|
data class Error(val exception: Throwable? = null) : Result<Nothing>
|
||||||
object Loading : Result<Nothing>
|
data object Loading : Result<Nothing>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,16 +21,16 @@ class HomeViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed interface HomeUiState {
|
sealed interface HomeUiState {
|
||||||
object Loading : HomeUiState
|
data object Loading : HomeUiState
|
||||||
|
|
||||||
// data class Ready(
|
// data class Ready(
|
||||||
// val wallets: List<WalletDetails>
|
// val wallets: List<WalletDetails>
|
||||||
// ) : HomeUiState
|
// ) : HomeUiState
|
||||||
|
|
||||||
object Empty : HomeUiState
|
data object Empty : HomeUiState
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface WalletListUiState {
|
sealed interface WalletListUiState {
|
||||||
data class Success(val ids: List<Long>) : WalletListUiState
|
data class Success(val ids: List<Long>) : WalletListUiState
|
||||||
object Loading : WalletListUiState
|
data object Loading : WalletListUiState
|
||||||
}
|
}
|
||||||
|
@ -98,5 +98,5 @@ sealed interface SettingsUiState {
|
|||||||
val remoteNodes: List<RemoteNode>,
|
val remoteNodes: List<RemoteNode>,
|
||||||
) : SettingsUiState
|
) : SettingsUiState
|
||||||
|
|
||||||
object Loading : SettingsUiState
|
data object Loading : SettingsUiState
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
package im.molly.monero.demo.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import im.molly.monero.MoneroAmount
|
||||||
|
import im.molly.monero.Balance
|
||||||
|
import im.molly.monero.BlockchainTime
|
||||||
|
import im.molly.monero.MoneroCurrency
|
||||||
|
import im.molly.monero.TimeLocked
|
||||||
|
import im.molly.monero.demo.ui.theme.AppTheme
|
||||||
|
import im.molly.monero.xmr
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
import kotlin.time.toKotlinDuration
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WalletBalanceView(
|
||||||
|
balance: Balance,
|
||||||
|
blockchainTime: BlockchainTime,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
var now by remember { mutableStateOf(Instant.now()) }
|
||||||
|
|
||||||
|
LaunchedEffect(now) {
|
||||||
|
delay(1.seconds)
|
||||||
|
now = Instant.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
text = "Balance at Block #${blockchainTime.height}",
|
||||||
|
)
|
||||||
|
|
||||||
|
BalanceRow("Confirmed", balance.confirmedAmount)
|
||||||
|
BalanceRow("Pending", balance.pendingAmount)
|
||||||
|
Divider()
|
||||||
|
BalanceRow("Total", balance.totalAmount)
|
||||||
|
|
||||||
|
BalanceRow("Unlocked", balance.unlockedAmountAt(blockchainTime.height, now))
|
||||||
|
balance.lockedAmountsAt(blockchainTime.height, now).forEach { (timeSpan, amount) ->
|
||||||
|
LockedBalanceRow("Locked", amount, timeSpan.blocks, timeSpan.timeRemaining)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BalanceRow(
|
||||||
|
label: String,
|
||||||
|
amount: MoneroAmount,
|
||||||
|
format: MoneroCurrency.Format = MoneroCurrency.Format(),
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Text(text = label)
|
||||||
|
Text(text = format.format(amount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LockedBalanceRow(
|
||||||
|
label: String,
|
||||||
|
amount: MoneroAmount,
|
||||||
|
blockCount: Int,
|
||||||
|
timeRemaining: Duration,
|
||||||
|
moneroFormat: MoneroCurrency.Format = MoneroCurrency.DefaultFormat,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
val durationText =
|
||||||
|
"${timeRemaining.toKotlinDuration()} ($blockCount blocks)"
|
||||||
|
Column {
|
||||||
|
Text(text = label)
|
||||||
|
Text(text = durationText, fontSize = 12.sp)
|
||||||
|
}
|
||||||
|
Text(text = moneroFormat.format(amount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun WalletBalanceDetailsPreview() {
|
||||||
|
AppTheme {
|
||||||
|
WalletBalanceView(
|
||||||
|
balance = Balance(
|
||||||
|
pendingAmount = 5.xmr,
|
||||||
|
timeLockedAmounts = listOf(
|
||||||
|
TimeLocked(10.xmr, BlockchainTime.Genesis),
|
||||||
|
TimeLocked(BigDecimal("0.000000000001").xmr, BlockchainTime.Block(10)),
|
||||||
|
TimeLocked(30.xmr, BlockchainTime.Block(500)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
blockchainTime = BlockchainTime.Genesis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -113,11 +113,16 @@ private fun WalletScreenPopulated(
|
|||||||
text = buildAnnotatedString {
|
text = buildAnnotatedString {
|
||||||
append(MoneroCurrency.SYMBOL + " ")
|
append(MoneroCurrency.SYMBOL + " ")
|
||||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||||
append(MoneroCurrency.Formatter(precision = 5).format(ledger.balance.confirmedAmount))
|
append(MoneroCurrency.Format(precision = 5).format(ledger.balance.confirmedAmount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Text(text = walletConfig.name, style = MaterialTheme.typography.headlineSmall)
|
Text(text = walletConfig.name, style = MaterialTheme.typography.headlineSmall)
|
||||||
|
|
||||||
|
WalletBalanceView(
|
||||||
|
balance = ledger.balance,
|
||||||
|
blockchainTime = ledger.checkedAt,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showRenameDialog) {
|
if (showRenameDialog) {
|
||||||
|
@ -71,6 +71,6 @@ sealed interface WalletUiState {
|
|||||||
val ledger: Ledger,
|
val ledger: Ledger,
|
||||||
) : WalletUiState
|
) : WalletUiState
|
||||||
|
|
||||||
object Error : WalletUiState
|
data object Error : WalletUiState
|
||||||
object Loading : WalletUiState
|
data object Loading : WalletUiState
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ object MoneroCurrency {
|
|||||||
|
|
||||||
const val MAX_PRECISION = MoneroAmount.ATOMIC_UNIT_SCALE
|
const val MAX_PRECISION = MoneroAmount.ATOMIC_UNIT_SCALE
|
||||||
|
|
||||||
val DefaultFormatter = Formatter()
|
val DefaultFormat = Format()
|
||||||
|
|
||||||
data class Formatter(
|
data class Format(
|
||||||
val precision: Int = MAX_PRECISION,
|
val precision: Int = MAX_PRECISION,
|
||||||
val locale: Locale = Locale.US,
|
val locale: Locale = Locale.US,
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user