Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,6 @@ class CoinControlManager internal constructor(
buttonPresentation(key)
}

val totalSelectedAmount: String
get() = displayAmount(totalSelected)

val totalSelectedSats: Long
get() = totalSelected.asSats().toLong()

Expand Down Expand Up @@ -211,6 +208,24 @@ class CoinControlManager internal constructor(
fun displayAmount(amount: Amount, showUnit: Boolean = true): String =
if (showUnit) amount.fmtStringWithUnit(unit) else amount.fmtString(unit)

fun displayAmountWithFiat(
amount: Amount,
prices: PriceResponse?,
currency: FiatCurrency,
): String =
withRustOr(displayAmount(amount)) {
displayAmountWithFiat(amount, prices, currency)
}

fun displayFiatAmount(
amount: Amount,
prices: PriceResponse?,
currency: FiatCurrency,
): String? =
withRustOr(null) {
displayFiatAmount(amount, prices, currency)
}

suspend fun reloadLabels() {
withRustOrSuspend(Unit) {
reloadLabels()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,15 @@ fun UtxoListScreen(
utxos = manager.utxos,
selected = manager.selected,
lockStateLoadFailed = manager.lockStateLoadFailed,
totalSelectedAmount = manager.totalSelectedAmount,
totalSelectedAmount =
manager.displayAmountWithFiat(
manager.totalSelected,
app.prices,
app.selectedFiatCurrency,
),
searchQuery = manager.search,
prices = app.prices,
fiatCurrency = app.selectedFiatCurrency,
onBack = { app.popRoute() },
onToggleUnit = {
manager.dispatch(org.bitcoinppl.cove_core.CoinControlManagerAction.ToggleUnit)
Expand Down Expand Up @@ -183,6 +190,8 @@ private fun UtxoListScreenContent(
lockStateLoadFailed: Boolean,
totalSelectedAmount: String,
searchQuery: String,
prices: org.bitcoinppl.cove_core.PriceResponse?,
fiatCurrency: org.bitcoinppl.cove_core.FiatCurrency,
onBack: () -> Unit,
onToggleUnit: () -> Unit,
onToggle: (org.bitcoinppl.cove_core.types.Utxo) -> Unit,
Expand Down Expand Up @@ -352,8 +361,17 @@ private fun UtxoListScreenContent(
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
utxos.forEachIndexed { index, utxo ->
UtxoItemRow(
manager = manager,
utxo = utxo,
amount =
UtxoRowAmount(
bitcoin = manager.displayAmount(utxo.amount),
fiat =
manager.displayFiatAmount(
utxo.amount,
prices,
fiatCurrency,
),
),
selected = utxo.spendable && selected.contains(utxo.id),
onToggle = { onToggle(utxo) },
onSetSpendability = {
Expand Down Expand Up @@ -458,11 +476,17 @@ private fun UtxoListScreenContent(
}
}

// fiat is null when no prices are available, so the row hides the fiat line
private data class UtxoRowAmount(
val bitcoin: String,
val fiat: String?,
)

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun UtxoItemRow(
manager: org.bitcoinppl.cove.CoinControlManager,
utxo: org.bitcoinppl.cove_core.types.Utxo,
amount: UtxoRowAmount,
selected: Boolean,
onToggle: () -> Unit,
onSetSpendability: () -> Unit,
Expand Down Expand Up @@ -508,11 +532,23 @@ private fun UtxoItemRow(
}
Column(horizontalAlignment = Alignment.End) {
Text(
manager.displayAmount(utxo.amount),
amount.bitcoin,
fontWeight = FontWeight.Normal,
fontSize = 13.sp,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
Comment on lines 533 to +540

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Amount Can Collapse Labels

The expanded amount column has no width constraint, so a long Bitcoin-plus-fiat value can consume nearly all of the row on compact screens or with enlarged text. This leaves little room for the weighted name and address column, making the UTXO hard to identify. Please constrain both sides or preserve a minimum width for the identifying column, as the iOS row does.

Knowledge Base Used:

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

)
amount.fiat?.let { fiat ->
Spacer(Modifier.height(4.dp))
Text(
fiat,
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 12.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
Spacer(Modifier.height(4.dp))
Text(
utxo.displayDate,
Expand Down
104 changes: 104 additions & 0 deletions android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,10 @@ internal object IntegrityCheckingUniffiLib {
): Short
external fun uniffi_cove_checksum_method_rustcoincontrolmanager_utxos(
): Short
external fun uniffi_cove_checksum_method_rustcoincontrolmanager_display_amount_with_fiat(
): Short
external fun uniffi_cove_checksum_method_rustcoincontrolmanager_display_fiat_amount(
): Short
external fun uniffi_cove_checksum_method_rustconnectivitymanager_is_connected(
): Short
external fun uniffi_cove_checksum_method_rustconnectivitymanager_set_connection_state(
Expand Down Expand Up @@ -2725,6 +2729,10 @@ internal object UniffiLib {
): RustBufferBitcoinUnit.ByValue
external fun uniffi_cove_fn_method_rustcoincontrolmanager_utxos(`ptr`: Long,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
external fun uniffi_cove_fn_method_rustcoincontrolmanager_display_amount_with_fiat(`ptr`: Long,`amount`: Long,`prices`: RustBuffer.ByValue,`currency`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
external fun uniffi_cove_fn_method_rustcoincontrolmanager_display_fiat_amount(`ptr`: Long,`amount`: Long,`prices`: RustBuffer.ByValue,`currency`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
): RustBuffer.ByValue
external fun uniffi_cove_fn_clone_coincontrolmanagerstate(`handle`: Long,uniffi_out_err: UniffiRustCallStatus,
): Long
external fun uniffi_cove_fn_free_coincontrolmanagerstate(`handle`: Long,uniffi_out_err: UniffiRustCallStatus,
Expand Down Expand Up @@ -4614,6 +4622,12 @@ private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) {
if (lib.uniffi_cove_checksum_method_rustcoincontrolmanager_utxos() != 43520.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_rustcoincontrolmanager_display_amount_with_fiat() != 29447.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_rustcoincontrolmanager_display_fiat_amount() != 8420.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_cove_checksum_method_rustconnectivitymanager_is_connected() != 47607.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
Expand Down Expand Up @@ -21365,6 +21379,21 @@ public interface RustCoinControlManagerInterface {

fun `utxos`(): List<Utxo>

/**
* Formats an amount followed by its fiat value in brackets (e.g. "50,000 SATS ($31.25)")
*
* Used for the selected total. Falls back to the bitcoin amount on its own when no
* prices are available, so the amount is never followed by empty brackets.
*/
fun `displayAmountWithFiat`(`amount`: Amount, `prices`: PriceResponse?, `currency`: FiatCurrency): kotlin.String

/**
* Formats the fiat value of an amount on its own (e.g. "$31.25" or "31.25 CHF")
*
* Returns None when no prices are available, so the fiat line can be hidden.
*/
fun `displayFiatAmount`(`amount`: Amount, `prices`: PriceResponse?, `currency`: FiatCurrency): kotlin.String?

companion object
}

Expand Down Expand Up @@ -21624,6 +21653,49 @@ open class RustCoinControlManager: Disposable, AutoCloseable, RustCoinControlMan



/**
* Formats an amount followed by its fiat value in brackets (e.g. "50,000 SATS ($31.25)")
*
* Used for the selected total. Falls back to the bitcoin amount on its own when no
* prices are available, so the amount is never followed by empty brackets.
*/override fun `displayAmountWithFiat`(`amount`: Amount, `prices`: PriceResponse?, `currency`: FiatCurrency): kotlin.String {
return FfiConverterString.lift(
callWithHandle {
uniffiRustCall() { _status ->
UniffiLib.uniffi_cove_fn_method_rustcoincontrolmanager_display_amount_with_fiat(
it,

FfiConverterTypeAmount.lower(`amount`),
FfiConverterOptionalTypePriceResponse.lower(`prices`),
FfiConverterTypeFiatCurrency.lower(`currency`),_status)
}
}
)
}



/**
* Formats the fiat value of an amount on its own (e.g. "$31.25" or "31.25 CHF")
*
* Returns None when no prices are available, so the fiat line can be hidden.
*/override fun `displayFiatAmount`(`amount`: Amount, `prices`: PriceResponse?, `currency`: FiatCurrency): kotlin.String? {
return FfiConverterOptionalString.lift(
callWithHandle {
uniffiRustCall() { _status ->
UniffiLib.uniffi_cove_fn_method_rustcoincontrolmanager_display_fiat_amount(
it,

FfiConverterTypeAmount.lower(`amount`),
FfiConverterOptionalTypePriceResponse.lower(`prices`),
FfiConverterTypeFiatCurrency.lower(`currency`),_status)
}
}
)
}






Expand Down Expand Up @@ -66743,6 +66815,38 @@ public object FfiConverterOptionalTypeMigration: FfiConverterRustBuffer<Migratio



/**
* @suppress
*/
public object FfiConverterOptionalTypePriceResponse: FfiConverterRustBuffer<PriceResponse?> {
override fun read(buf: ByteBuffer): PriceResponse? {
if (buf.get().toInt() == 0) {
return null
}
return FfiConverterTypePriceResponse.read(buf)
}

override fun allocationSize(value: PriceResponse?): ULong {
if (value == null) {
return 1UL
} else {
return 1UL + FfiConverterTypePriceResponse.allocationSize(value)
}
}

override fun write(value: PriceResponse?, buf: ByteBuffer) {
if (value == null) {
buf.put(0)
} else {
buf.put(1)
FfiConverterTypePriceResponse.write(value, buf)
}
}
}




/**
* @suppress
*/
Expand Down
14 changes: 10 additions & 4 deletions ios/Cove/CoinControlManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,6 @@ private enum CoinControlManagerError: LocalizedError {
selection.total
}

public var totalSelectedAmount: String {
displayAmount(self.totalSelected)
}

public var totalSelectedSats: Int {
Int(self.totalSelected.asSats())
}
Expand Down Expand Up @@ -177,6 +173,16 @@ private enum CoinControlManagerError: LocalizedError {
showUnit ? amount.fmtStringWithUnit(unit: unit) : amount.fmtString(unit: unit)
}

func displayAmountWithFiat(_ amount: Amount, prices: PriceResponse?, currency: FiatCurrency) -> String {
guard let rust else { return displayAmount(amount) }

return rust.displayAmountWithFiat(amount: amount, prices: prices, currency: currency)
}

func displayFiatAmount(_ amount: Amount, prices: PriceResponse?, currency: FiatCurrency) -> String? {
rust?.displayFiatAmount(amount: amount, prices: prices, currency: currency)
}

func reloadLabels() async {
guard let rust else { return }

Expand Down
28 changes: 26 additions & 2 deletions ios/Cove/Flows/CoinControlFlow/UtxoListScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,22 @@ private struct UtxoSortButton: View {
}

private struct UtxoSelectionSection: View {
@Environment(AppManager.self) private var app

let manager: CoinControlManager
let onShowTransaction: (Utxo) -> Void

@Binding var showLockedSelectionAlert: Bool
@Binding var utxoLockUpdateError: String?

private var totalSelectedAmount: String {
manager.displayAmountWithFiat(
manager.totalSelected,
prices: app.prices,
currency: app.selectedFiatCurrency
)
}

var body: some View {
VStack(spacing: 8) {
UtxoSelectionHeader(
Expand All @@ -328,12 +338,12 @@ private struct UtxoSelectionSection: View {
.padding(.horizontal)
}

Text(manager.totalSelectedAmount)
Text(totalSelectedAmount)
.font(.caption2.weight(.semibold))
.foregroundStyle(.secondary)
.opacity(manager.selected.isEmpty ? 0 : 0.8)
.contentTransition(.numericText())
.animation(.easeInOut(duration: 0.1), value: manager.totalSelectedAmount)
.animation(.easeInOut(duration: 0.1), value: totalSelectedAmount)
}
}
}
Expand Down Expand Up @@ -544,6 +554,8 @@ private struct UtxoListToolbarMenu: View {
// MARK: - Row

private struct UtxoRow: View {
@Environment(AppManager.self) private var app

var manager: CoinControlManager
let utxo: Utxo
let onLockedSelectionAttempt: () -> Void
Expand Down Expand Up @@ -590,6 +602,16 @@ private struct UtxoRow: View {
.font(.footnote)
.fontWeight(.regular)

if let fiat = manager.displayFiatAmount(
utxo.amount,
prices: app.prices,
currency: app.selectedFiatCurrency
) {
Text(fiat)
.font(.caption)
.foregroundColor(.secondary)
}

Text(utxo.date())
.font(.caption)
.foregroundColor(.secondary)
Expand All @@ -615,6 +637,7 @@ private struct UtxoRow: View {
manager: CoinControlManager(RustCoinControlManager.previewNew())
)
.environment(WalletManager(preview: .only))
.environment(AppManager.shared)
}
}

Expand All @@ -626,5 +649,6 @@ private struct UtxoRow: View {
)
)
.environment(WalletManager(preview: .only))
.environment(AppManager.shared)
}
}
Loading
Loading