mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 02:25:21 +00:00
focus around
This commit is contained in:
@@ -13,6 +13,8 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.graphics.Color
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -33,9 +35,49 @@ fun ReceiveView(
|
|||||||
val currentMintQuote by viewModel.currentMintQuote.observeAsState()
|
val currentMintQuote by viewModel.currentMintQuote.observeAsState()
|
||||||
val isLoading by viewModel.isLoading.observeAsState(false)
|
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
|
// Determine if we should show type selector
|
||||||
val showTypeSelector = decodedToken == null && currentMintQuote == null
|
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(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -145,14 +187,16 @@ fun ReceiveView(
|
|||||||
ReceiveEcashDialog(
|
ReceiveEcashDialog(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
decodedToken = decodedToken,
|
decodedToken = decodedToken,
|
||||||
isLoading = isLoading
|
isLoading = isLoading,
|
||||||
|
focusRequester = cashuFocusRequester
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
WalletViewModel.ReceiveType.LIGHTNING -> {
|
WalletViewModel.ReceiveType.LIGHTNING -> {
|
||||||
ReceiveLightningDialog(
|
ReceiveLightningDialog(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
currentMintQuote = currentMintQuote,
|
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.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
@@ -13,6 +14,8 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
@@ -31,7 +34,8 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel
|
|||||||
fun ReceiveEcashDialog(
|
fun ReceiveEcashDialog(
|
||||||
viewModel: WalletViewModel,
|
viewModel: WalletViewModel,
|
||||||
decodedToken: CashuToken?,
|
decodedToken: CashuToken?,
|
||||||
isLoading: Boolean
|
isLoading: Boolean,
|
||||||
|
focusRequester: FocusRequester
|
||||||
) {
|
) {
|
||||||
val token by viewModel.tokenInput.observeAsState("")
|
val token by viewModel.tokenInput.observeAsState("")
|
||||||
val clipboardManager = LocalClipboardManager.current
|
val clipboardManager = LocalClipboardManager.current
|
||||||
@@ -206,7 +210,8 @@ fun ReceiveEcashDialog(
|
|||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 24.dp),
|
.padding(bottom = 24.dp)
|
||||||
|
.focusRequester(focusRequester),
|
||||||
minLines = 3,
|
minLines = 3,
|
||||||
maxLines = 4,
|
maxLines = 4,
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
@@ -12,6 +13,8 @@ import androidx.compose.runtime.*
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
@@ -30,7 +33,8 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel
|
|||||||
fun ReceiveLightningDialog(
|
fun ReceiveLightningDialog(
|
||||||
viewModel: WalletViewModel,
|
viewModel: WalletViewModel,
|
||||||
currentMintQuote: MintQuote?,
|
currentMintQuote: MintQuote?,
|
||||||
isLoading: Boolean
|
isLoading: Boolean,
|
||||||
|
focusRequester: FocusRequester
|
||||||
) {
|
) {
|
||||||
var amount by remember { mutableStateOf("") }
|
var amount by remember { mutableStateOf("") }
|
||||||
var description by remember { mutableStateOf("") }
|
var description by remember { mutableStateOf("") }
|
||||||
@@ -196,7 +200,8 @@ fun ReceiveLightningDialog(
|
|||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(bottom = 16.dp),
|
.padding(bottom = 16.dp)
|
||||||
|
.focusRequester(focusRequester),
|
||||||
shape = RoundedCornerShape(16.dp)
|
shape = RoundedCornerShape(16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,17 @@ class LightningManager(
|
|||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
try {
|
try {
|
||||||
uiStateManager.setLoading(true)
|
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
|
_currentMintQuote.value = quote
|
||||||
|
|
||||||
// Save quote for tracking
|
// Save quote for tracking
|
||||||
repository.saveMintQuote(quote).onSuccess {
|
val saveResult = repository.saveMintQuote(quote)
|
||||||
loadPendingQuotes()
|
saveResult.onSuccess {
|
||||||
|
// Now load pending quotes directly in current coroutine
|
||||||
|
loadPendingQuotesInternal()
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
Log.e(TAG, "Failed to save mint quote", error)
|
Log.e(TAG, "Failed to save mint quote", error)
|
||||||
_errorMessage.value = "Failed to save invoice: ${error.message}"
|
_errorMessage.value = "Failed to save invoice: ${error.message}"
|
||||||
@@ -71,12 +76,17 @@ class LightningManager(
|
|||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
try {
|
try {
|
||||||
uiStateManager.setLoading(true)
|
uiStateManager.setLoading(true)
|
||||||
cashuService.createMeltQuote(invoice).onSuccess { quote ->
|
|
||||||
|
// Create the melt quote first
|
||||||
|
val meltQuoteResult = cashuService.createMeltQuote(invoice)
|
||||||
|
meltQuoteResult.onSuccess { quote ->
|
||||||
_currentMeltQuote.value = quote
|
_currentMeltQuote.value = quote
|
||||||
|
|
||||||
// Save quote for tracking
|
// Save quote for tracking
|
||||||
repository.saveMeltQuote(quote).onSuccess {
|
val saveResult = repository.saveMeltQuote(quote)
|
||||||
loadPendingQuotes()
|
saveResult.onSuccess {
|
||||||
|
// Load pending quotes directly in current coroutine
|
||||||
|
loadPendingQuotesInternal()
|
||||||
onQuoteCreated()
|
onQuoteCreated()
|
||||||
}.onFailure { error ->
|
}.onFailure { error ->
|
||||||
Log.e(TAG, "Failed to save melt quote", 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() {
|
fun loadPendingQuotes() {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
repository.getMintQuotes().onSuccess { quotes ->
|
loadPendingQuotesInternal()
|
||||||
_pendingMintQuotes.value = quotes.filter { !it.paid }
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.getMeltQuotes().onSuccess { quotes ->
|
|
||||||
_pendingMeltQuotes.value = quotes.filter { it.state != MeltQuoteState.PAID }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user