From 811aab972074005123f7d21f975b3d21d730225e Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:57:43 +0200 Subject: [PATCH] focus around --- .../android/wallet/ui/ReceiveDialog.kt | 48 ++++++++++++++++++- .../android/wallet/ui/ReceiveEcashDialog.kt | 9 +++- .../wallet/ui/ReceiveLightningDialog.kt | 9 +++- .../wallet/viewmodel/LightningManager.kt | 45 +++++++++++------ 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveDialog.kt b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveDialog.kt index cc6f8351..a749a6e9 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveDialog.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveDialog.kt @@ -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 ) } } diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveEcashDialog.kt b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveEcashDialog.kt index 047f9a98..cc3f90ac 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveEcashDialog.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveEcashDialog.kt @@ -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), diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveLightningDialog.kt b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveLightningDialog.kt index 9e051ef0..1e3c10ce 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveLightningDialog.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/ReceiveLightningDialog.kt @@ -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) ) diff --git a/app/src/main/java/com/bitchat/android/wallet/viewmodel/LightningManager.kt b/app/src/main/java/com/bitchat/android/wallet/viewmodel/LightningManager.kt index 60b7d401..2526c112 100644 --- a/app/src/main/java/com/bitchat/android/wallet/viewmodel/LightningManager.kt +++ b/app/src/main/java/com/bitchat/android/wallet/viewmodel/LightningManager.kt @@ -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() } }