Skip to content

Commit 33756f0

Browse files
committed
Merge branch 'master' into mainnet
2 parents 279bdaf + 69eefaa commit 33756f0

File tree

16 files changed

+199
-86
lines changed

16 files changed

+199
-86
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[versions]
2-
lightningkmp = "1.10.4"
2+
lightningkmp = "1.10.6"
33
secp256k1 = "0.18.0" # keep in check with lightning-kmp secp version
44

55
kotlin = "2.1.10"

phoenix-android/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ android {
2626
applicationId = "fr.acinq.phoenix.mainnet"
2727
minSdk = 26
2828
targetSdk = 35
29-
versionCode = 106
30-
versionName = "2.6.2"
29+
versionCode = 107
30+
versionName = gitCommitHash()
3131
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
3232
}
3333

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/inputs/ConverterInput.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ fun ConverterInput(
6666
trailingContent: @Composable (() -> Unit)? = null,
6767
internalPaddingHorizontal: Dp = 10.dp,
6868
internalPaddingVertical: Dp = 10.dp,
69+
limitDecimal: Boolean = false,
6970
enabled: Boolean = true,
7071
readonly: Boolean = false,
7172
value: String?,
@@ -86,7 +87,12 @@ fun ConverterInput(
8687
onValueChange = {
8788
if (it.length > 12) return@BasicTextField
8889
errorMessage = ""
89-
if (it.isNotBlank() && it.toDoubleOrNull() == null) {
90+
val saneInput = it.replace(",", ".")
91+
// if the input already has 2 decimals, ignore change
92+
if (limitDecimal && saneInput.contains(".") && saneInput.split(".").last().length > 2) {
93+
return@BasicTextField
94+
}
95+
if (it.isNotBlank() && saneInput.toDoubleOrNull() == null) {
9096
errorMessage = context.getString(R.string.validation_invalid_number)
9197
}
9298
internalStringValue = it
@@ -156,7 +162,6 @@ fun ConverterInput(
156162
}
157163
}
158164

159-
160165
@Composable
161166
fun RowScope.InlineNumberInput(
162167
modifier: Modifier = Modifier,

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/components/inputs/CurrencyConverter.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ private fun FiatConverterInput(
243243
null -> onAmountUpdate(null)
244244
}
245245
},
246+
limitDecimal = true,
246247
modifier = Modifier.weight(1f),
247248
backgroundColor = MaterialTheme.colors.surface,
248249
placeholder = { Text(text = stringResource(R.string.converter_placeholder_label, fiat.displayCode), style = MaterialTheme.typography.caption) },

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/send/spliceout/SpliceOutView.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ fun SpliceOutCapacityDisclaimer(showCapacityDisclaimer: Boolean, onShowCapacityD
293293
text = stringResource(id = R.string.spliceout_capacity_disclaimer_checkbox),
294294
checked = !showCapacityDisclaimer,
295295
onCheckedChange = onShowCapacityDisclaimerChange,
296-
modifier = Modifier.alpha(.3f),
297296
padding = PaddingValues(vertical = 8.dp)
298297
)
299298
}

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/FinalWalletRefundView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ fun FinalWalletRefundView(
8080
val available = finalWallet?.confirmed?.filter { it.blockHeight > 0 }?.balance
8181

8282
DefaultScreenLayout {
83-
DefaultScreenHeader(onBackClick = onBackClick, title = stringResource(id = R.string.swapinrefund_title))
83+
DefaultScreenHeader(onBackClick = onBackClick, title = stringResource(id = R.string.finalwallet_refund_title))
8484
when (available) {
8585
null -> {
8686
ProgressView(text = stringResource(id = R.string.utils_loading_data))

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddresses.kt

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,30 @@
1616

1717
package fr.acinq.phoenix.android.settings.walletinfo
1818

19+
import androidx.compose.foundation.layout.IntrinsicSize
1920
import androidx.compose.foundation.layout.PaddingValues
2021
import androidx.compose.foundation.layout.Row
2122
import androidx.compose.foundation.layout.Spacer
23+
import androidx.compose.foundation.layout.fillMaxHeight
2224
import androidx.compose.foundation.layout.fillMaxWidth
2325
import androidx.compose.foundation.layout.height
2426
import androidx.compose.foundation.layout.width
2527
import androidx.compose.foundation.lazy.LazyColumn
2628
import androidx.compose.foundation.lazy.itemsIndexed
2729
import androidx.compose.material.MaterialTheme
30+
import androidx.compose.material.Surface
2831
import androidx.compose.material.Text
2932
import androidx.compose.runtime.Composable
3033
import androidx.compose.ui.Alignment
3134
import androidx.compose.ui.Modifier
35+
import androidx.compose.ui.graphics.RectangleShape
3236
import androidx.compose.ui.platform.LocalContext
3337
import androidx.compose.ui.res.stringResource
38+
import androidx.compose.ui.text.font.FontWeight
3439
import androidx.compose.ui.text.style.TextAlign
3540
import androidx.compose.ui.text.style.TextOverflow
3641
import androidx.compose.ui.unit.dp
42+
import androidx.compose.ui.unit.sp
3743
import androidx.lifecycle.viewmodel.compose.viewModel
3844
import fr.acinq.lightning.blockchain.electrum.WalletState
3945
import fr.acinq.phoenix.android.R
@@ -47,7 +53,10 @@ import fr.acinq.phoenix.android.components.DefaultScreenLayout
4753
import fr.acinq.phoenix.android.components.ItemCard
4854
import fr.acinq.phoenix.android.components.ProgressView
4955
import fr.acinq.phoenix.android.components.openLink
56+
import fr.acinq.phoenix.android.utils.borderColor
5057
import fr.acinq.phoenix.android.utils.copyToClipboard
58+
import fr.acinq.phoenix.android.utils.darken
59+
import fr.acinq.phoenix.android.utils.monoTypo
5160
import fr.acinq.phoenix.utils.BlockchainExplorer
5261

5362

@@ -63,33 +72,36 @@ fun SwapInAddresses(
6372
title = stringResource(id = R.string.swapinaddresses_title),
6473
)
6574

66-
val addresses = vm.taprootAddresses
6775
LazyColumn(modifier = Modifier.fillMaxWidth()) {
6876
item {
6977
CardHeader(text = stringResource(id = R.string.swapinaddresses_taproot))
7078
Spacer(modifier = Modifier.height(8.dp))
7179
}
72-
if (addresses.isEmpty()) {
80+
81+
val taprootAddresses = vm.taprootAddresses
82+
if (taprootAddresses.isEmpty()) {
7383
item {
7484
Card(modifier = Modifier.fillMaxWidth()) {
7585
ProgressView(text = stringResource(id = R.string.swapinaddresses_sync), padding = PaddingValues(horizontal = 16.dp, vertical = 12.dp))
7686
}
7787
}
7888
} else {
79-
itemsIndexed(addresses) { index, (address, state) ->
80-
ItemCard(index = index, maxItemsCount = addresses.size) {
81-
AddressStateView(address = address, state = state)
89+
itemsIndexed(taprootAddresses) { index, (address, state, isCurrent) ->
90+
ItemCard(index = index, maxItemsCount = taprootAddresses.size) {
91+
AddressStateView(address = address, state = state, isCurrent = isCurrent)
8292
}
8393
}
8494
}
85-
vm.legacyAddress.value?.let { (address, state) ->
95+
96+
val legacyAddress = vm.legacyAddress.value
97+
legacyAddress?.let { (address, state) ->
8698
item {
8799
Spacer(modifier = Modifier.height(16.dp))
88100
CardHeader(text = stringResource(id = R.string.swapinaddresses_legacy))
89101
}
90102
item {
91103
Card {
92-
AddressStateView(address = address, state = state)
104+
AddressStateView(address = address, state = state, isCurrent = false)
93105
}
94106
}
95107
}
@@ -102,31 +114,39 @@ fun SwapInAddresses(
102114
private fun AddressStateView(
103115
address: String,
104116
state: WalletState.AddressState,
117+
isCurrent: Boolean,
105118
) {
106119
val context = LocalContext.current
107120
val link = business.blockchainExplorer.addressUrl(addr = address, website = BlockchainExplorer.Website.MempoolSpace)
108121
Clickable(onClick = { openLink(context, link) }) {
109122
Row(
110-
modifier = Modifier,
123+
modifier = Modifier.height(IntrinsicSize.Min),
111124
verticalAlignment = Alignment.CenterVertically,
112125
) {
113-
Spacer(modifier = Modifier.width(16.dp))
114126
val meta = state.meta
127+
if (isCurrent || state.alreadyUsed) {
128+
Surface(shape = RectangleShape, color = if (isCurrent) MaterialTheme.colors.primary else borderColor.darken(.98f), modifier = Modifier.width(3.dp).fillMaxHeight(0.9f)) { }
129+
Spacer(Modifier.width(13.dp))
130+
} else {
131+
Spacer(modifier = Modifier.width(16.dp))
132+
}
133+
115134
if (meta is WalletState.AddressMeta.Derived) {
116135
Text(
117136
text = meta.index.toString(),
118-
style = MaterialTheme.typography.caption,
137+
style = monoTypo.copy(color = if (isCurrent) MaterialTheme.typography.body1.color else MaterialTheme.typography.caption.color, fontSize = 14.sp),
119138
textAlign = TextAlign.End,
120139
)
121140
Spacer(modifier = Modifier.width(8.dp))
122141
}
123-
Text(text = address, modifier = Modifier.weight(1f), maxLines = 1, overflow = TextOverflow.MiddleEllipsis)
142+
Text(text = address, modifier = Modifier.weight(1f), maxLines = 1, overflow = TextOverflow.MiddleEllipsis,
143+
style = monoTypo.copy(fontWeight = if (isCurrent) FontWeight.Bold else FontWeight.Normal, fontSize = 14.sp))
124144
Button(
125145
icon = R.drawable.ic_copy,
126146
onClick = { copyToClipboard(context, address, "Copy address") },
147+
modifier = Modifier.fillMaxHeight(),
127148
padding = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
128149
)
129150
}
130151
}
131-
132152
}

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddressesViewModel.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ import androidx.lifecycle.ViewModelProvider
2424
import androidx.lifecycle.viewModelScope
2525
import androidx.lifecycle.viewmodel.CreationExtras
2626
import fr.acinq.lightning.blockchain.electrum.WalletState
27-
import fr.acinq.phoenix.android.PhoenixApplication
2827
import fr.acinq.phoenix.managers.PeerManager
2928
import fr.acinq.phoenix.managers.phoenixSwapInWallet
3029
import kotlinx.coroutines.launch
3130
import org.slf4j.LoggerFactory
3231

3332

33+
3434
class SwapInAddressesViewModel(private val peerManager: PeerManager) : ViewModel() {
3535

36-
val log = LoggerFactory.getLogger(this::class.java)
36+
private val log = LoggerFactory.getLogger(this::class.java)
3737

38-
val taprootAddresses = mutableStateListOf<Pair<String, WalletState.AddressState>>()
38+
val taprootAddresses = mutableStateListOf<TaprootAddress>()
3939
val legacyAddress = mutableStateOf<Pair<String, WalletState.AddressState>?>(null)
4040

4141
init {
@@ -46,16 +46,14 @@ class SwapInAddressesViewModel(private val peerManager: PeerManager) : ViewModel
4646
private fun monitorSwapAddresses() {
4747
viewModelScope.launch {
4848
peerManager.getPeer().phoenixSwapInWallet.wallet.walletStateFlow.collect { walletState ->
49-
val newAddresses = walletState.addresses.toList().sortedByDescending {
50-
val meta = it.second.meta
51-
if (meta is WalletState.AddressMeta.Derived) {
52-
meta.index
53-
} else {
54-
-1 // legacy address goes to the bottom
49+
val currentTaprootAddress = walletState.firstUnusedDerivedAddress
50+
val addresses = walletState.addresses.toList()
51+
val legacy = addresses.firstOrNull { it.second.meta is WalletState.AddressMeta.Single }
52+
val taprootList = addresses.filter { it.second.meta is WalletState.AddressMeta.Derived }
53+
.sortedByDescending { it.second.meta.indexOrNull }
54+
.map {
55+
TaprootAddress(address = it.first, state = it.second, isCurrent = it.first == currentTaprootAddress?.first)
5556
}
56-
}
57-
if (newAddresses.isEmpty()) return@collect
58-
val (legacy, taprootList) = newAddresses.last() to newAddresses.dropLast(1)
5957
log.info("swap-in taproot addresses update: ${taprootAddresses.size} -> ${taprootList.size}")
6058
taprootAddresses.clear()
6159
taprootAddresses.addAll(taprootList)
@@ -64,6 +62,8 @@ class SwapInAddressesViewModel(private val peerManager: PeerManager) : ViewModel
6462
}
6563
}
6664

65+
data class TaprootAddress(val address: String, val state: WalletState.AddressState, val isCurrent: Boolean)
66+
6767
class Factory(
6868
private val peerManager: PeerManager,
6969
) : ViewModelProvider.Factory {

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/WalletInfoView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private fun SwapInWalletView(
143143
}
144144
MenuButton(
145145
text = stringResource(id = R.string.walletinfo_swapin_addresses),
146-
icon = R.drawable.ic_list,
146+
textStyle = MaterialTheme.typography.body2,
147147
onClick = onSwapInWalletInfoClick
148148
)
149149
}

phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/Theme.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ val mutedBgColor @Composable get() = if (isDarkTheme) gray950 else gray30
259259

260260
val borderColor @Composable get() = if (isDarkTheme) gray800 else gray50
261261

262+
fun Color.darken(factor: Float = 0.8f): Color = Color(red = red * factor, green = green * factor, blue = blue * factor, alpha = alpha)
263+
262264
/** top gradient is darker/lighter than the background, but not quite black/white */
263265
private val topGradientColor @Composable get() = if (isDarkTheme) gray1000 else gray10
264266
private val bottomGradientColor @Composable get() = MaterialTheme.colors.background

0 commit comments

Comments
 (0)