focus around

This commit is contained in:
callebtc
2025-07-17 23:57:43 +02:00
parent 198a8ba6c5
commit 811aab9720
4 changed files with 91 additions and 20 deletions
@@ -13,6 +13,8 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
@@ -33,9 +35,49 @@ fun ReceiveView(
val currentMintQuote by viewModel.currentMintQuote.observeAsState()
val isLoading by viewModel.isLoading.observeAsState(false)
// Focus requesters for each input type
val cashuFocusRequester = remember { FocusRequester() }
val lightningFocusRequester = remember { FocusRequester() }
// Determine if we should show type selector
val showTypeSelector = decodedToken == null && currentMintQuote == null
// Focus the appropriate input when switching types
LaunchedEffect(receiveType) {
if (showTypeSelector) {
when (receiveType) {
WalletViewModel.ReceiveType.CASHU -> {
if (decodedToken == null) {
cashuFocusRequester.requestFocus()
}
}
WalletViewModel.ReceiveType.LIGHTNING -> {
if (currentMintQuote == null) {
lightningFocusRequester.requestFocus()
}
}
}
}
}
// Initial focus when the view is first shown
LaunchedEffect(Unit) {
if (showTypeSelector) {
when (receiveType) {
WalletViewModel.ReceiveType.CASHU -> {
if (decodedToken == null) {
cashuFocusRequester.requestFocus()
}
}
WalletViewModel.ReceiveType.LIGHTNING -> {
if (currentMintQuote == null) {
lightningFocusRequester.requestFocus()
}
}
}
}
}
Box(
modifier = Modifier
.fillMaxSize()
@@ -145,14 +187,16 @@ fun ReceiveView(
ReceiveEcashDialog(
viewModel = viewModel,
decodedToken = decodedToken,
isLoading = isLoading
isLoading = isLoading,
focusRequester = cashuFocusRequester
)
}
WalletViewModel.ReceiveType.LIGHTNING -> {
ReceiveLightningDialog(
viewModel = viewModel,
currentMintQuote = currentMintQuote,
isLoading = isLoading
isLoading = isLoading,
focusRequester = lightningFocusRequester
)
}
}
@@ -5,6 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
@@ -13,6 +14,8 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
@@ -31,7 +34,8 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel
fun ReceiveEcashDialog(
viewModel: WalletViewModel,
decodedToken: CashuToken?,
isLoading: Boolean
isLoading: Boolean,
focusRequester: FocusRequester
) {
val token by viewModel.tokenInput.observeAsState("")
val clipboardManager = LocalClipboardManager.current
@@ -206,7 +210,8 @@ fun ReceiveEcashDialog(
),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 24.dp),
.padding(bottom = 24.dp)
.focusRequester(focusRequester),
minLines = 3,
maxLines = 4,
shape = RoundedCornerShape(16.dp),
@@ -5,6 +5,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
@@ -12,6 +13,8 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
@@ -30,7 +33,8 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel
fun ReceiveLightningDialog(
viewModel: WalletViewModel,
currentMintQuote: MintQuote?,
isLoading: Boolean
isLoading: Boolean,
focusRequester: FocusRequester
) {
var amount by remember { mutableStateOf("") }
var description by remember { mutableStateOf("") }
@@ -196,7 +200,8 @@ fun ReceiveLightningDialog(
),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 16.dp),
.padding(bottom = 16.dp)
.focusRequester(focusRequester),
shape = RoundedCornerShape(16.dp)
)
@@ -45,12 +45,17 @@ class LightningManager(
coroutineScope.launch {
try {
uiStateManager.setLoading(true)
cashuService.createMintQuote(amount, description).onSuccess { quote ->
// Create the mint quote first
val mintQuoteResult = cashuService.createMintQuote(amount, description)
mintQuoteResult.onSuccess { quote ->
_currentMintQuote.value = quote
// Save quote for tracking
repository.saveMintQuote(quote).onSuccess {
loadPendingQuotes()
val saveResult = repository.saveMintQuote(quote)
saveResult.onSuccess {
// Now load pending quotes directly in current coroutine
loadPendingQuotesInternal()
}.onFailure { error ->
Log.e(TAG, "Failed to save mint quote", error)
_errorMessage.value = "Failed to save invoice: ${error.message}"
@@ -71,12 +76,17 @@ class LightningManager(
coroutineScope.launch {
try {
uiStateManager.setLoading(true)
cashuService.createMeltQuote(invoice).onSuccess { quote ->
// Create the melt quote first
val meltQuoteResult = cashuService.createMeltQuote(invoice)
meltQuoteResult.onSuccess { quote ->
_currentMeltQuote.value = quote
// Save quote for tracking
repository.saveMeltQuote(quote).onSuccess {
loadPendingQuotes()
val saveResult = repository.saveMeltQuote(quote)
saveResult.onSuccess {
// Load pending quotes directly in current coroutine
loadPendingQuotesInternal()
onQuoteCreated()
}.onFailure { error ->
Log.e(TAG, "Failed to save melt quote", error)
@@ -201,17 +211,24 @@ class LightningManager(
}
/**
* Load pending quotes from repository
* Load pending quotes from repository (internal suspend method)
*/
private suspend fun loadPendingQuotesInternal() {
repository.getMintQuotes().onSuccess { quotes ->
_pendingMintQuotes.value = quotes.filter { !it.paid }
}
repository.getMeltQuotes().onSuccess { quotes ->
_pendingMeltQuotes.value = quotes.filter { it.state != MeltQuoteState.PAID }
}
}
/**
* Load pending quotes from repository (public method for external calls)
*/
fun loadPendingQuotes() {
coroutineScope.launch {
repository.getMintQuotes().onSuccess { quotes ->
_pendingMintQuotes.value = quotes.filter { !it.paid }
}
repository.getMeltQuotes().onSuccess { quotes ->
_pendingMeltQuotes.value = quotes.filter { it.state != MeltQuoteState.PAID }
}
loadPendingQuotesInternal()
}
}