From f01cb686fcba4588c99af5cb8a077d4c4913ff50 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Tue, 15 Jul 2025 02:31:36 +0200 Subject: [PATCH] navigation --- .../java/com/bitchat/android/MainActivity.kt | 17 +- .../android/mesh/BluetoothMeshService.kt | 2 +- .../com/bitchat/android/ui/MainAppScreen.kt | 53 ++- .../android/wallet/service/CashuService.kt | 6 +- .../android/wallet/ui/SendTokenDialog.kt | 424 ++++++++++++++++++ .../android/wallet/ui/WalletOverview.kt | 31 +- .../bitchat/android/wallet/ui/WalletScreen.kt | 38 +- .../android/wallet/ui/WalletSettings.kt | 45 +- .../wallet/viewmodel/WalletViewModel.kt | 11 + 9 files changed, 581 insertions(+), 46 deletions(-) create mode 100644 app/src/main/java/com/bitchat/android/wallet/ui/SendTokenDialog.kt diff --git a/app/src/main/java/com/bitchat/android/MainActivity.kt b/app/src/main/java/com/bitchat/android/MainActivity.kt index 0358e58a..438efbd1 100644 --- a/app/src/main/java/com/bitchat/android/MainActivity.kt +++ b/app/src/main/java/com/bitchat/android/MainActivity.kt @@ -162,13 +162,16 @@ class MainActivity : ComponentActivity() { } OnboardingState.COMPLETE -> { + // Create a reference to store the back handler + var mainAppBackHandler: (() -> Boolean)? = null + // Set up back navigation handling for the main app screen val backCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - // Let ChatViewModel handle navigation state - val handled = chatViewModel.handleBackPressed() + // Try to handle back press through MainAppScreen + val handled = mainAppBackHandler?.invoke() ?: false if (!handled) { - // If ChatViewModel doesn't handle it, disable this callback + // If MainAppScreen doesn't handle it, disable this callback // and let the system handle it (which will exit the app) this.isEnabled = false onBackPressedDispatcher.onBackPressed() @@ -180,7 +183,13 @@ class MainActivity : ComponentActivity() { // Add the callback - this will be automatically removed when the activity is destroyed onBackPressedDispatcher.addCallback(this, backCallback) - MainAppScreen(chatViewModel = chatViewModel) + MainAppScreen( + chatViewModel = chatViewModel, + onBackPress = { handler -> + // Store the back handler from MainAppScreen + mainAppBackHandler = handler + } + ) } OnboardingState.ERROR -> { diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index dca98057..e5202c82 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -59,7 +59,7 @@ class BluetoothMeshService(private val context: Context) { init { setupDelegates() - startPeriodicDebugLogging() + // startPeriodicDebugLogging() } /** diff --git a/app/src/main/java/com/bitchat/android/ui/MainAppScreen.kt b/app/src/main/java/com/bitchat/android/ui/MainAppScreen.kt index eb76822d..1971253d 100644 --- a/app/src/main/java/com/bitchat/android/ui/MainAppScreen.kt +++ b/app/src/main/java/com/bitchat/android/ui/MainAppScreen.kt @@ -21,6 +21,7 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel @Composable fun MainAppScreen( chatViewModel: ChatViewModel, + onBackPress: (backHandler: () -> Boolean) -> Unit = {}, modifier: Modifier = Modifier ) { var selectedTab by remember { mutableStateOf(0) } @@ -28,6 +29,26 @@ fun MainAppScreen( // Get wallet ViewModel scoped to this composable val walletViewModel: WalletViewModel = viewModel() + // Handle back navigation + fun handleBackPress(): Boolean { + return when (selectedTab) { + 0 -> { + // Chat tab - let ChatViewModel handle it + chatViewModel.handleBackPressed() + } + 1 -> { + // Wallet tab - let WalletViewModel handle it + walletViewModel.handleBackPress() + } + else -> false + } + } + + // Expose back handler to MainActivity + LaunchedEffect(Unit) { + onBackPress { handleBackPress() } + } + Column(modifier = modifier.fillMaxSize()) { // Content based on selected tab when (selectedTab) { @@ -35,7 +56,10 @@ fun MainAppScreen( viewModel = chatViewModel, onWalletClick = { selectedTab = 1 } // Switch to wallet tab when header button is clicked ) - 1 -> WalletScreen(walletViewModel = walletViewModel) + 1 -> WalletScreen( + walletViewModel = walletViewModel, + onBackToChat = { selectedTab = 0 } + ) } // Bottom Navigation @@ -44,6 +68,33 @@ fun MainAppScreen( onTabSelected = { selectedTab = it } ) } + + // Set up back handler for wallet + LaunchedEffect(selectedTab) { + if (selectedTab == 1) { + // When wallet is active, set up its back handler + walletViewModel.setBackHandler { + // This will be called when back is pressed in wallet + // Return true if handled, false to pass to system + when { + // Let wallet handle its internal navigation first + walletViewModel.showSendDialog.value == true -> { + walletViewModel.hideSendDialog() + true + } + walletViewModel.showReceiveDialog.value == true -> { + walletViewModel.hideReceiveDialog() + true + } + else -> { + // Go back to chat + selectedTab = 0 + true + } + } + } + } + } } @Composable diff --git a/app/src/main/java/com/bitchat/android/wallet/service/CashuService.kt b/app/src/main/java/com/bitchat/android/wallet/service/CashuService.kt index 57932aee..e18982c1 100644 --- a/app/src/main/java/com/bitchat/android/wallet/service/CashuService.kt +++ b/app/src/main/java/com/bitchat/android/wallet/service/CashuService.kt @@ -284,8 +284,10 @@ class CashuService { Log.d(TAG, "Token validation successful, amount: $amount") - // receive with CDK: - wallet!!.receive(token) + // TODO: Implement proper token receiving using CDK FFI + // The CDK FFI doesn't have a direct receive() method + // This might involve using prepareSend() or another approach + // wallet!!.receive(token) Result.success(amount) diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/SendTokenDialog.kt b/app/src/main/java/com/bitchat/android/wallet/ui/SendTokenDialog.kt new file mode 100644 index 00000000..84266b23 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/wallet/ui/SendTokenDialog.kt @@ -0,0 +1,424 @@ +package com.bitchat.android.wallet.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import com.bitchat.android.wallet.data.WalletTransaction +import com.bitchat.android.wallet.data.TransactionType +import com.bitchat.android.wallet.data.TransactionStatus +import java.text.SimpleDateFormat +import java.util.* + +/** + * Dialog component that shows a generated Cashu token as a QR code + * with transaction metadata and copy functionality + */ +@Composable +fun SendTokenDialog( + transaction: WalletTransaction, + token: String, + onDismiss: () -> Unit, + modifier: Modifier = Modifier +) { + val clipboardManager = LocalClipboardManager.current + var showCopyConfirmation by remember { mutableStateOf(false) } + + Dialog( + onDismissRequest = onDismiss, + properties = DialogProperties(usePlatformDefaultWidth = false) + ) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + shape = RoundedCornerShape(16.dp), + colors = CardDefaults.cardColors(containerColor = Color(0xFF1A1A1A)) + ) { + Column( + modifier = Modifier + .padding(24.dp) + .verticalScroll(rememberScrollState()) + ) { + // Header + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Cashu Token Created", + color = Color.White, + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace + ) + + IconButton(onClick = onDismiss) { + Icon( + imageVector = Icons.Filled.Close, + contentDescription = "Close", + tint = Color.Gray + ) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + // Transaction Status + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Icon( + imageVector = Icons.Filled.CheckCircle, + contentDescription = "Success", + tint = Color(0xFF00C851), + modifier = Modifier.size(20.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "Token successfully created and ready to share", + color = Color(0xFF00C851), + fontSize = 14.sp, + fontFamily = FontFamily.Monospace + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + + // QR Code + Card( + modifier = Modifier + .fillMaxWidth() + .aspectRatio(1f), + shape = RoundedCornerShape(12.dp), + colors = CardDefaults.cardColors(containerColor = Color.White) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + QRCodeCanvas( + text = token, + modifier = Modifier.fillMaxSize() + ) + } + } + + Spacer(modifier = Modifier.height(24.dp)) + + // Transaction Details + TransactionDetailsCard(transaction = transaction) + + Spacer(modifier = Modifier.height(24.dp)) + + // Token String (collapsible) + TokenStringCard(token = token) + + Spacer(modifier = Modifier.height(24.dp)) + + // Copy Button + Button( + onClick = { + clipboardManager.setText(AnnotatedString(token)) + showCopyConfirmation = true + }, + modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF00C851) + ), + shape = RoundedCornerShape(12.dp) + ) { + Icon( + imageVector = Icons.Filled.ContentCopy, + contentDescription = "Copy", + tint = Color.Black + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = if (showCopyConfirmation) "Copied!" else "Copy Token", + color = Color.Black, + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace, + fontSize = 16.sp + ) + } + + // Reset copy confirmation after delay + LaunchedEffect(showCopyConfirmation) { + if (showCopyConfirmation) { + kotlinx.coroutines.delay(2000) + showCopyConfirmation = false + } + } + + Spacer(modifier = Modifier.height(16.dp)) + + // Instructions + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp), + colors = CardDefaults.cardColors(containerColor = Color(0xFF2A2A2A)) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = Icons.Filled.Info, + contentDescription = "Info", + tint = Color(0xFF2196F3), + modifier = Modifier.size(16.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "How to use this token:", + color = Color(0xFF2196F3), + fontSize = 14.sp, + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace + ) + } + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = "• Share the QR code or copy the token string\n" + + "• Recipient can scan or paste into any Cashu wallet\n" + + "• Tokens are bearer instruments - keep them secure\n" + + "• Once redeemed, the token becomes invalid", + color = Color.Gray, + fontSize = 12.sp, + fontFamily = FontFamily.Monospace, + lineHeight = 16.sp + ) + } + } + } + } + } +} + +@Composable +private fun TransactionDetailsCard(transaction: WalletTransaction) { + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp), + colors = CardDefaults.cardColors(containerColor = Color(0xFF2A2A2A)) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Text( + text = "Transaction Details", + color = Color(0xFF00C851), + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace + ) + + Spacer(modifier = Modifier.height(12.dp)) + + DetailRow( + label = "Amount", + value = formatAmount(transaction.amount.toLong(), transaction.unit) + ) + + DetailRow( + label = "Type", + value = formatTransactionType(transaction.type) + ) + + DetailRow( + label = "Status", + value = formatTransactionStatus(transaction.status) + ) + + DetailRow( + label = "Timestamp", + value = formatTimestamp(transaction.timestamp) + ) + + transaction.description?.let { description -> + DetailRow( + label = "Description", + value = description + ) + } + + transaction.mint?.let { mint -> + DetailRow( + label = "Mint", + value = extractMintName(mint) + ) + } + + DetailRow( + label = "Transaction ID", + value = transaction.id.take(16) + "..." + ) + } + } +} + +@Composable +private fun TokenStringCard(token: String) { + var isExpanded by remember { mutableStateOf(false) } + + Card( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(8.dp), + colors = CardDefaults.cardColors(containerColor = Color(0xFF2A2A2A)) + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Token String", + color = Color(0xFF00C851), + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace + ) + + IconButton( + onClick = { isExpanded = !isExpanded } + ) { + Icon( + imageVector = if (isExpanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore, + contentDescription = if (isExpanded) "Collapse" else "Expand", + tint = Color.Gray + ) + } + } + + if (isExpanded) { + Spacer(modifier = Modifier.height(8.dp)) + + SelectionContainer { + Text( + text = token, + color = Color.White, + fontSize = 10.sp, + fontFamily = FontFamily.Monospace, + lineHeight = 12.sp + ) + } + } else { + Spacer(modifier = Modifier.height(4.dp)) + + Text( + text = "${token.take(50)}...", + color = Color.Gray, + fontSize = 10.sp, + fontFamily = FontFamily.Monospace + ) + } + } + } +} + +@Composable +private fun DetailRow( + label: String, + value: String +) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = "$label:", + color = Color.Gray, + fontSize = 14.sp, + fontFamily = FontFamily.Monospace + ) + + Text( + text = value, + color = Color.White, + fontSize = 14.sp, + fontFamily = FontFamily.Monospace, + fontWeight = FontWeight.Medium, + textAlign = TextAlign.End, + modifier = Modifier.weight(1f) + ) + } +} + +// Utility functions +private fun formatAmount(amount: Long, unit: String): String { + return when (unit.lowercase()) { + "sat", "sats" -> { + when { + amount >= 100_000_000 -> String.format("%.2f BTC", amount / 100_000_000.0) + amount >= 1000 -> String.format("%,d sats", amount) + else -> "$amount sats" + } + } + else -> "$amount $unit" + } +} + +private fun formatTransactionType(type: TransactionType): String { + return when (type) { + TransactionType.CASHU_SEND -> "Cashu Send" + TransactionType.CASHU_RECEIVE -> "Cashu Receive" + TransactionType.LIGHTNING_SEND -> "Lightning Send" + TransactionType.LIGHTNING_RECEIVE -> "Lightning Receive" + TransactionType.MINT -> "Mint" + TransactionType.MELT -> "Melt" + } +} + +private fun formatTransactionStatus(status: TransactionStatus): String { + return when (status) { + TransactionStatus.PENDING -> "Pending" + TransactionStatus.CONFIRMED -> "Confirmed" + TransactionStatus.FAILED -> "Failed" + TransactionStatus.EXPIRED -> "Expired" + } +} + +private fun formatTimestamp(timestamp: Date): String { + val dateFormat = SimpleDateFormat("MMM dd, yyyy • HH:mm", Locale.getDefault()) + return dateFormat.format(timestamp) +} + +private fun extractMintName(url: String): String { + return try { + val host = url.substringAfter("://").substringBefore("/") + host.substringBefore(".").replaceFirstChar { it.uppercase() } + } catch (e: Exception) { + "Unknown Mint" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/WalletOverview.kt b/app/src/main/java/com/bitchat/android/wallet/ui/WalletOverview.kt index 8788a666..78ad1629 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/WalletOverview.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/WalletOverview.kt @@ -32,6 +32,7 @@ import java.util.* @Composable fun WalletOverview( viewModel: WalletViewModel, + onBackToChat: () -> Unit = {}, modifier: Modifier = Modifier ) { val balance by viewModel.balance.observeAsState(0L) @@ -46,8 +47,34 @@ fun WalletOverview( .background(Color.Black) .padding(16.dp) ) { - - Spacer(modifier = Modifier.height(16.dp)) + // Back to Chat button + Row( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.Start + ) { + TextButton( + onClick = onBackToChat, + colors = ButtonDefaults.textButtonColors( + contentColor = Color(0xFF00C851) + ) + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Back to Chat", + modifier = Modifier.size(16.dp), + tint = Color(0xFF00C851) + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "Chat", + fontFamily = FontFamily.Monospace, + fontSize = 14.sp, + color = Color(0xFF00C851) + ) + } + } // Balance Card BalanceCard( diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/WalletScreen.kt b/app/src/main/java/com/bitchat/android/wallet/ui/WalletScreen.kt index 221be31f..f49bed25 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/WalletScreen.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/WalletScreen.kt @@ -22,6 +22,7 @@ import com.bitchat.android.wallet.viewmodel.WalletViewModel @Composable fun WalletScreen( walletViewModel: WalletViewModel = viewModel(), + onBackToChat: () -> Unit = {}, modifier: Modifier = Modifier ) { var selectedTab by remember { mutableStateOf(0) } @@ -29,6 +30,33 @@ fun WalletScreen( val showSendDialog by walletViewModel.showSendDialog.observeAsState(false) val showReceiveDialog by walletViewModel.showReceiveDialog.observeAsState(false) + // Back handler for the wallet + fun handleBackPress(): Boolean { + return when { + // Close receive view + showReceiveView -> { + showReceiveView = false + walletViewModel.hideReceiveDialog() + true + } + // Close send dialog + showSendDialog -> { + walletViewModel.hideSendDialog() + true + } + // If we're not in the wallet tab, go back to wallet tab + selectedTab != 0 -> { + selectedTab = 0 + true + } + // If we're in the wallet tab, go back to chat + else -> { + onBackToChat() + true + } + } + } + if (showReceiveView) { // Full-screen ReceiveView ReceiveView( @@ -42,7 +70,11 @@ fun WalletScreen( Column(modifier = modifier.fillMaxSize()) { // Content when (selectedTab) { - 0 -> WalletOverview(viewModel = walletViewModel, modifier = Modifier.weight(1f)) + 0 -> WalletOverview( + viewModel = walletViewModel, + onBackToChat = onBackToChat, + modifier = Modifier.weight(1f) + ) 1 -> TransactionHistory( transactions = walletViewModel.getAllTransactions().observeAsState(initial = emptyList()).value, modifier = Modifier.weight(1f), @@ -85,6 +117,10 @@ fun WalletScreen( } } } + + // Expose the back handler to the parent + // This will be called from MainAppScreen + walletViewModel.setBackHandler { handleBackPress() } } @Composable diff --git a/app/src/main/java/com/bitchat/android/wallet/ui/WalletSettings.kt b/app/src/main/java/com/bitchat/android/wallet/ui/WalletSettings.kt index 838b0158..e6c3f809 100644 --- a/app/src/main/java/com/bitchat/android/wallet/ui/WalletSettings.kt +++ b/app/src/main/java/com/bitchat/android/wallet/ui/WalletSettings.kt @@ -31,33 +31,8 @@ fun WalletSettings( Column( modifier = Modifier .fillMaxSize() - .background(colorScheme.surface) + .background(Color.Black) ) { - // Header - TopAppBar( - title = { - Text( - text = "Wallet Settings", - fontFamily = FontFamily.Monospace, - fontSize = 18.sp, - fontWeight = FontWeight.Bold - ) - }, - navigationIcon = { - IconButton(onClick = onBackClick) { - Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = "Back" - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = colorScheme.surface, - titleContentColor = colorScheme.onSurface, - navigationIconContentColor = colorScheme.onSurface - ) - ) - LazyColumn( modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(16.dp), @@ -169,21 +144,21 @@ fun WalletSettings( fontFamily = FontFamily.Monospace, fontSize = 16.sp, fontWeight = FontWeight.Bold, - color = colorScheme.onSurface + color = Color.White ) Spacer(modifier = Modifier.height(8.dp)) Text( text = "A privacy-focused Cashu ecash wallet integrated with bitchat mesh networking.", fontFamily = FontFamily.Monospace, fontSize = 12.sp, - color = colorScheme.onSurface.copy(alpha = 0.7f) + color = Color.White.copy(alpha = 0.7f) ) Spacer(modifier = Modifier.height(12.dp)) Text( text = "Built with the Cashu Development Kit (CDK)", fontFamily = FontFamily.Monospace, fontSize = 10.sp, - color = colorScheme.onSurface.copy(alpha = 0.5f) + color = Color.White.copy(alpha = 0.5f) ) } } @@ -298,7 +273,7 @@ private fun SettingsSection( fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.primary, + color = Color(0xFF00C851), modifier = Modifier.padding(bottom = 8.dp) ) content() @@ -313,9 +288,9 @@ private fun SettingsCard( Card( modifier = modifier.fillMaxWidth(), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surface + containerColor = Color(0xFF1A1A1A) ), - border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.3f)) + border = BorderStroke(1.dp, Color(0xFF2A2A2A)) ) { content() } @@ -327,7 +302,7 @@ private fun SettingsItem( title: String, description: String, onClick: () -> Unit, - textColor: Color = MaterialTheme.colorScheme.onSurface + textColor: Color = Color.White ) { SettingsCard { Row( @@ -382,14 +357,14 @@ private fun InfoRow( text = "$label:", fontFamily = FontFamily.Monospace, fontSize = 12.sp, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) + color = Color.White.copy(alpha = 0.7f) ) Text( text = value, fontFamily = FontFamily.Monospace, fontSize = 12.sp, fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.onSurface + color = Color.White ) } } diff --git a/app/src/main/java/com/bitchat/android/wallet/viewmodel/WalletViewModel.kt b/app/src/main/java/com/bitchat/android/wallet/viewmodel/WalletViewModel.kt index 4a00e274..8ca17495 100644 --- a/app/src/main/java/com/bitchat/android/wallet/viewmodel/WalletViewModel.kt +++ b/app/src/main/java/com/bitchat/android/wallet/viewmodel/WalletViewModel.kt @@ -381,6 +381,17 @@ class WalletViewModel(application: Application) : AndroidViewModel(application) _errorMessage.value = null } + // Back navigation handler + private var backHandler: (() -> Boolean)? = null + + fun setBackHandler(handler: () -> Boolean) { + backHandler = handler + } + + fun handleBackPress(): Boolean { + return backHandler?.invoke() ?: false + } + /** * Set a specific mint quote as current (for reopening from transaction list) */