mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 00:16:59 +00:00
feat: move lightning address and payment targets to wallet setup screen
- Add trailingContent lambda to UpdateZapAmountContent so callers can inject sections inside its scrollable Column - Inject lightning address field and payment targets row into NIP47SetupScreen via trailingContent - Add WalletViewModel to NIP47SetupScreen to load/save the lightning address - Add settings icon button to WalletScreen TopAppBar when wallet is configured, navigating back to NIP47SetupScreen - Restore WalletScreen to its original layout (no ln/payment sections) https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
This commit is contained in:
@@ -46,6 +46,7 @@ import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -148,6 +149,7 @@ fun UpdateZapAmountContent(
|
||||
onClose: () -> Unit,
|
||||
nip47uri: String? = null,
|
||||
accountViewModel: AccountViewModel,
|
||||
trailingContent: @Composable ColumnScope.() -> Unit = {},
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val clipboardManager = LocalClipboard.current
|
||||
@@ -649,6 +651,8 @@ fun UpdateZapAmountContent(
|
||||
}
|
||||
}
|
||||
|
||||
trailingContent()
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
+112
-5
@@ -20,20 +20,43 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AccountBalanceWallet
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.SavingTopBar
|
||||
import com.vitorpamplona.amethyst.ui.note.UpdateZapAmountContent
|
||||
import com.vitorpamplona.amethyst.ui.note.UpdateZapAmountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.wallet.WalletViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
|
||||
@Composable
|
||||
fun NIP47SetupScreen(
|
||||
@@ -44,17 +67,22 @@ fun NIP47SetupScreen(
|
||||
val postViewModel: UpdateZapAmountViewModel = viewModel()
|
||||
postViewModel.init(accountViewModel)
|
||||
|
||||
val walletViewModel: WalletViewModel = viewModel()
|
||||
walletViewModel.init(accountViewModel)
|
||||
|
||||
LaunchedEffect(accountViewModel, postViewModel) {
|
||||
postViewModel.load()
|
||||
walletViewModel.loadLnAddress()
|
||||
}
|
||||
|
||||
NIP47SetupScreen(postViewModel, accountViewModel, nav, nip47)
|
||||
NIP47SetupScreen(postViewModel, walletViewModel, accountViewModel, nav, nip47)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NIP47SetupScreen(
|
||||
postViewModel: UpdateZapAmountViewModel,
|
||||
walletViewModel: WalletViewModel,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
nip47: String?,
|
||||
@@ -76,10 +104,89 @@ fun NIP47SetupScreen(
|
||||
},
|
||||
) {
|
||||
Column(Modifier.padding(it)) {
|
||||
UpdateZapAmountContent(postViewModel, onClose = {
|
||||
postViewModel.cancel()
|
||||
nav.popBack()
|
||||
}, nip47, accountViewModel)
|
||||
UpdateZapAmountContent(
|
||||
postViewModel,
|
||||
onClose = {
|
||||
postViewModel.cancel()
|
||||
nav.popBack()
|
||||
},
|
||||
nip47,
|
||||
accountViewModel,
|
||||
) {
|
||||
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
|
||||
LightningAddressSetupSection(walletViewModel)
|
||||
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
|
||||
PaymentTargetsSetupRow(nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LightningAddressSetupSection(walletViewModel: WalletViewModel) {
|
||||
val lnAddress by walletViewModel.lnAddress.collectAsState()
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 0.dp, vertical = 4.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.lightning_address),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = lnAddress,
|
||||
onValueChange = { walletViewModel.updateLnAddress(it) },
|
||||
modifier = Modifier.weight(1f),
|
||||
placeholder = {
|
||||
Text(
|
||||
text = "me@mylightningnode.com",
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
},
|
||||
singleLine = true,
|
||||
)
|
||||
TextButton(onClick = { walletViewModel.saveLnAddress() }) {
|
||||
Text(text = stringRes(R.string.save))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PaymentTargetsSetupRow(nav: INav) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AccountBalanceWallet,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringRes(R.string.payment_targets),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
TextButton(onClick = { nav.nav(Route.EditPaymentTargets) }) {
|
||||
Text(
|
||||
text = stringRes(R.string.manage),
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-102
@@ -30,28 +30,23 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.List
|
||||
import androidx.compose.material.icons.filled.ArrowDownward
|
||||
import androidx.compose.material.icons.filled.ArrowUpward
|
||||
import androidx.compose.material.icons.outlined.AccountBalanceWallet
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -70,7 +65,6 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import java.text.NumberFormat
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -84,10 +78,6 @@ fun WalletScreen(
|
||||
|
||||
val hasWallet by walletViewModel.hasWalletSetup.collectAsState()
|
||||
|
||||
LaunchedEffect(accountViewModel) {
|
||||
walletViewModel.loadLnAddress()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -100,39 +90,43 @@ fun WalletScreen(
|
||||
)
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
if (hasWallet) {
|
||||
IconButton(onClick = { nav.nav(Route.Nip47NWCSetup()) }) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Settings,
|
||||
contentDescription = stringRes(R.string.settings),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(padding)
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
if (!hasWallet) {
|
||||
NoWalletSetup(nav = nav)
|
||||
} else {
|
||||
WalletHomeContent(
|
||||
walletViewModel = walletViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider()
|
||||
LightningAddressSection(walletViewModel = walletViewModel)
|
||||
HorizontalDivider()
|
||||
PaymentTargetsRow(nav = nav)
|
||||
if (!hasWallet) {
|
||||
NoWalletSetup(
|
||||
modifier = Modifier.padding(padding),
|
||||
nav = nav,
|
||||
)
|
||||
} else {
|
||||
WalletHomeContent(
|
||||
walletViewModel = walletViewModel,
|
||||
modifier = Modifier.padding(padding),
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NoWalletSetup(nav: INav) {
|
||||
private fun NoWalletSetup(
|
||||
modifier: Modifier,
|
||||
nav: INav,
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
modifier
|
||||
.fillMaxSize()
|
||||
.padding(32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
@@ -159,6 +153,7 @@ private fun NoWalletSetup(nav: INav) {
|
||||
@Composable
|
||||
private fun WalletHomeContent(
|
||||
walletViewModel: WalletViewModel,
|
||||
modifier: Modifier,
|
||||
nav: INav,
|
||||
) {
|
||||
val balance by walletViewModel.balanceSats.collectAsState()
|
||||
@@ -173,8 +168,8 @@ private fun WalletHomeContent(
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
modifier
|
||||
.fillMaxSize()
|
||||
.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
@@ -222,7 +217,7 @@ private fun WalletHomeContent(
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
// Action buttons
|
||||
Row(
|
||||
@@ -292,68 +287,3 @@ private fun WalletHomeContent(
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LightningAddressSection(walletViewModel: WalletViewModel) {
|
||||
val lnAddress by walletViewModel.lnAddress.collectAsState()
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringRes(R.string.lightning_address),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = lnAddress,
|
||||
onValueChange = { walletViewModel.updateLnAddress(it) },
|
||||
modifier = Modifier.weight(1f),
|
||||
placeholder = {
|
||||
Text(
|
||||
text = "me@mylightningnode.com",
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
},
|
||||
singleLine = true,
|
||||
)
|
||||
TextButton(onClick = { walletViewModel.saveLnAddress() }) {
|
||||
Text(text = stringRes(R.string.save))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PaymentTargetsRow(nav: INav) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AccountBalanceWallet,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
Text(
|
||||
text = stringRes(R.string.payment_targets),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
}
|
||||
TextButton(onClick = { nav.nav(Route.EditPaymentTargets) }) {
|
||||
Text(text = stringRes(R.string.manage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user