mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 05:45:19 +00:00
loading state in ui store
This commit is contained in:
@@ -119,16 +119,30 @@ fun ReceiveEcashDialog(
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(0xFF00C851),
|
||||
containerColor = if (isLoading) Color(0xFF2A2A2A) else Color(0xFF00C851),
|
||||
disabledContainerColor = Color(0xFF2A2A2A)
|
||||
),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
if (isLoading) {
|
||||
CircularProgressIndicator(
|
||||
color = Color.Black,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = Color.White,
|
||||
modifier = Modifier.size(20.dp),
|
||||
strokeWidth = 2.dp
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "RECEIVING TOKEN...",
|
||||
color = Color.White,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
letterSpacing = 1.sp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@@ -161,8 +175,11 @@ fun ReceiveEcashDialog(
|
||||
OutlinedTextField(
|
||||
value = token,
|
||||
onValueChange = {
|
||||
viewModel.setTokenInput(it)
|
||||
if (!isLoading) {
|
||||
viewModel.setTokenInput(it)
|
||||
}
|
||||
},
|
||||
enabled = !isLoading,
|
||||
label = {
|
||||
Text(
|
||||
text = "Cashu Token",
|
||||
@@ -182,7 +199,10 @@ fun ReceiveEcashDialog(
|
||||
unfocusedBorderColor = Color(0xFF2A2A2A),
|
||||
unfocusedLabelColor = Color.Gray,
|
||||
unfocusedTextColor = Color.White,
|
||||
focusedTextColor = Color.White
|
||||
focusedTextColor = Color.White,
|
||||
disabledBorderColor = Color.Gray,
|
||||
disabledLabelColor = Color.Gray,
|
||||
disabledTextColor = Color.Gray
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -193,13 +213,16 @@ fun ReceiveEcashDialog(
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
// TODO: Implement QR code scanning
|
||||
}
|
||||
if (!isLoading) {
|
||||
// TODO: Implement QR code scanning
|
||||
}
|
||||
},
|
||||
enabled = !isLoading
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.QrCode,
|
||||
contentDescription = "Scan QR",
|
||||
tint = Color(0xFF00C851)
|
||||
tint = if (isLoading) Color.Gray else Color(0xFF00C851)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -214,6 +237,7 @@ fun ReceiveEcashDialog(
|
||||
}
|
||||
}
|
||||
},
|
||||
enabled = !isLoading,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
@@ -222,7 +246,7 @@ fun ReceiveEcashDialog(
|
||||
),
|
||||
border = BorderStroke(
|
||||
2.dp,
|
||||
Color(0xFF00C851)
|
||||
if (isLoading) Color.Gray else Color(0xFF00C851)
|
||||
),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
@@ -232,13 +256,13 @@ fun ReceiveEcashDialog(
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ContentPaste,
|
||||
contentDescription = "Paste",
|
||||
tint = Color(0xFF00C851),
|
||||
tint = if (isLoading) Color.Gray else Color(0xFF00C851),
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "PASTE FROM CLIPBOARD",
|
||||
color = Color(0xFF00C851),
|
||||
color = if (isLoading) Color.Gray else Color(0xFF00C851),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
|
||||
@@ -137,7 +137,8 @@ fun SendEcashDialog(
|
||||
// Amount input
|
||||
OutlinedTextField(
|
||||
value = amount,
|
||||
onValueChange = { amount = it },
|
||||
onValueChange = { if (!isLoading) amount = it },
|
||||
enabled = !isLoading,
|
||||
label = {
|
||||
Text(
|
||||
text = "Amount (sats)",
|
||||
@@ -151,7 +152,10 @@ fun SendEcashDialog(
|
||||
unfocusedBorderColor = Color(0xFF2A2A2A),
|
||||
unfocusedLabelColor = Color.Gray,
|
||||
unfocusedTextColor = Color.White,
|
||||
focusedTextColor = Color.White
|
||||
focusedTextColor = Color.White,
|
||||
disabledBorderColor = Color.Gray,
|
||||
disabledLabelColor = Color.Gray,
|
||||
disabledTextColor = Color.Gray
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -162,7 +166,8 @@ fun SendEcashDialog(
|
||||
// Memo input
|
||||
OutlinedTextField(
|
||||
value = memo,
|
||||
onValueChange = { memo = it },
|
||||
onValueChange = { if (!isLoading) memo = it },
|
||||
enabled = !isLoading,
|
||||
label = {
|
||||
Text(
|
||||
text = "Memo (optional)",
|
||||
@@ -175,7 +180,10 @@ fun SendEcashDialog(
|
||||
unfocusedBorderColor = Color(0xFF2A2A2A),
|
||||
unfocusedLabelColor = Color.Gray,
|
||||
unfocusedTextColor = Color.White,
|
||||
focusedTextColor = Color.White
|
||||
focusedTextColor = Color.White,
|
||||
disabledBorderColor = Color.Gray,
|
||||
disabledLabelColor = Color.Gray,
|
||||
disabledTextColor = Color.Gray
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -195,16 +203,30 @@ fun SendEcashDialog(
|
||||
.fillMaxWidth()
|
||||
.height(56.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(0xFF00C851),
|
||||
containerColor = if (isLoading) Color(0xFF2A2A2A) else Color(0xFF00C851),
|
||||
disabledContainerColor = Color(0xFF2A2A2A)
|
||||
),
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
if (isLoading) {
|
||||
CircularProgressIndicator(
|
||||
color = Color.Black,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = Color.White,
|
||||
modifier = Modifier.size(20.dp),
|
||||
strokeWidth = 2.dp
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
text = "CREATING TOKEN...",
|
||||
color = Color.White,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontFamily = FontFamily.Monospace,
|
||||
letterSpacing = 1.sp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
||||
@@ -15,7 +15,8 @@ import java.util.*
|
||||
class LightningManager(
|
||||
private val repository: WalletRepository,
|
||||
private val cashuService: CashuService,
|
||||
private val coroutineScope: CoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val uiStateManager: UIStateManager
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "LightningManager"
|
||||
@@ -34,9 +35,6 @@ class LightningManager(
|
||||
private val _pendingMeltQuotes = MutableLiveData<List<MeltQuote>>(emptyList())
|
||||
val pendingMeltQuotes: androidx.lifecycle.LiveData<List<MeltQuote>> = _pendingMeltQuotes
|
||||
|
||||
private val _isLoading = MutableLiveData<Boolean>(false)
|
||||
val isLoading: androidx.lifecycle.LiveData<Boolean> = _isLoading
|
||||
|
||||
private val _errorMessage = MutableLiveData<String?>(null)
|
||||
val errorMessage: androidx.lifecycle.LiveData<String?> = _errorMessage
|
||||
|
||||
@@ -46,7 +44,7 @@ class LightningManager(
|
||||
fun createMintQuote(amount: Long, description: String? = null) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.createMintQuote(amount, description).onSuccess { quote ->
|
||||
_currentMintQuote.value = quote
|
||||
|
||||
@@ -61,7 +59,7 @@ class LightningManager(
|
||||
_errorMessage.value = "Failed to create invoice: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,7 +70,7 @@ class LightningManager(
|
||||
fun createMeltQuote(invoice: String, onQuoteCreated: () -> Unit = {}) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.createMeltQuote(invoice).onSuccess { quote ->
|
||||
_currentMeltQuote.value = quote
|
||||
|
||||
@@ -88,7 +86,7 @@ class LightningManager(
|
||||
_errorMessage.value = "Failed to process invoice: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +102,7 @@ class LightningManager(
|
||||
) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.payInvoice(quoteId).onSuccess { success ->
|
||||
if (success) {
|
||||
// Update quote status and add transaction
|
||||
@@ -143,7 +141,7 @@ class LightningManager(
|
||||
_errorMessage.value = "Payment failed: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import java.util.*
|
||||
class MintManager(
|
||||
private val repository: WalletRepository,
|
||||
private val cashuService: CashuService,
|
||||
private val coroutineScope: CoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val uiStateManager: UIStateManager
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "MintManager"
|
||||
@@ -120,7 +121,7 @@ class MintManager(
|
||||
*/
|
||||
private suspend fun initializeWalletWithMint(mintUrl: String, onWalletInitialized: () -> Unit) {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.initializeWallet(mintUrl).onSuccess {
|
||||
onWalletInitialized()
|
||||
Log.d(TAG, "Wallet initialized with mint: $mintUrl")
|
||||
@@ -129,7 +130,7 @@ class MintManager(
|
||||
_errorMessage.value = "Failed to connect to mint: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ class MintManager(
|
||||
fun addMint(mintUrl: String, nickname: String, onSuccess: () -> Unit = {}) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.getMintInfo(mintUrl).onSuccess { mintInfo ->
|
||||
val mint = Mint(
|
||||
url = mintUrl,
|
||||
@@ -184,7 +185,7 @@ class MintManager(
|
||||
_errorMessage.value = "Failed to connect to mint: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +196,7 @@ class MintManager(
|
||||
fun setActiveMint(mintUrl: String, onWalletInitialized: () -> Unit = {}) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
repository.setActiveMint(mintUrl).onSuccess {
|
||||
_activeMint.value = mintUrl
|
||||
initializeWalletWithMint(mintUrl, onWalletInitialized)
|
||||
@@ -203,7 +204,7 @@ class MintManager(
|
||||
_errorMessage.value = "Failed to set active mint: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +236,7 @@ class MintManager(
|
||||
fun syncAllMints() {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
val currentMints = _mints.value ?: emptyList()
|
||||
|
||||
for (mint in currentMints) {
|
||||
@@ -265,7 +266,7 @@ class MintManager(
|
||||
Log.e(TAG, "Error syncing mints", e)
|
||||
_errorMessage.value = "Failed to sync mints: ${e.message}"
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ import java.util.*
|
||||
class TokenManager(
|
||||
private val repository: WalletRepository,
|
||||
private val cashuService: CashuService,
|
||||
private val coroutineScope: CoroutineScope
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val uiStateManager: UIStateManager
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "TokenManager"
|
||||
@@ -37,9 +38,6 @@ class TokenManager(
|
||||
private val _tokenInput = MutableLiveData<String>("")
|
||||
val tokenInput: androidx.lifecycle.LiveData<String> = _tokenInput
|
||||
|
||||
private val _isLoading = MutableLiveData<Boolean>(false)
|
||||
val isLoading: androidx.lifecycle.LiveData<Boolean> = _isLoading
|
||||
|
||||
private val _errorMessage = MutableLiveData<String?>(null)
|
||||
val errorMessage: androidx.lifecycle.LiveData<String?> = _errorMessage
|
||||
|
||||
@@ -54,7 +52,7 @@ class TokenManager(
|
||||
) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.createToken(amount, memo).onSuccess { token ->
|
||||
_generatedToken.value = token
|
||||
|
||||
@@ -80,7 +78,7 @@ class TokenManager(
|
||||
_errorMessage.value = "Failed to create token: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,14 +139,14 @@ class TokenManager(
|
||||
fun decodeCashuToken(token: String) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
cashuService.decodeToken(token).onSuccess { decodedToken ->
|
||||
_decodedToken.value = decodedToken
|
||||
}.onFailure { error ->
|
||||
_errorMessage.value = "Invalid token: ${error.message}"
|
||||
}
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +165,7 @@ class TokenManager(
|
||||
) {
|
||||
coroutineScope.launch {
|
||||
try {
|
||||
_isLoading.value = true
|
||||
uiStateManager.setLoading(true)
|
||||
|
||||
// Get decoded token
|
||||
val decodedToken = _decodedToken.value
|
||||
@@ -257,7 +255,7 @@ class TokenManager(
|
||||
)
|
||||
onFailure(failureData)
|
||||
} finally {
|
||||
_isLoading.value = false
|
||||
uiStateManager.setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
|
||||
private val cashuService = CashuService.getInstance()
|
||||
|
||||
// Manager instances
|
||||
private val mintManager = MintManager(repository, cashuService, viewModelScope)
|
||||
private val tokenManager = TokenManager(repository, cashuService, viewModelScope)
|
||||
private val lightningManager = LightningManager(repository, cashuService, viewModelScope)
|
||||
private val transactionManager = TransactionManager(repository, viewModelScope)
|
||||
private val uiStateManager = UIStateManager()
|
||||
private val mintManager = MintManager(repository, cashuService, viewModelScope, uiStateManager)
|
||||
private val tokenManager = TokenManager(repository, cashuService, viewModelScope, uiStateManager)
|
||||
private val lightningManager = LightningManager(repository, cashuService, viewModelScope, uiStateManager)
|
||||
private val transactionManager = TransactionManager(repository, viewModelScope)
|
||||
|
||||
companion object {
|
||||
private const val TAG = "WalletViewModel"
|
||||
|
||||
Reference in New Issue
Block a user