From 2b0920f9b1f916e21231d5574faefed2c1444edf Mon Sep 17 00:00:00 2001 From: hailin Date: Thu, 1 Jan 2026 03:32:33 -0800 Subject: [PATCH] fix(android): add copy feedback and explorer link to wallet detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Matching Electron app functionality: 1. Copy address button: - Shows "✓ 已复制" feedback after copying - Auto-resets after 2 seconds 2. Explorer link button (new): - Opens address in Kava block explorer - Uses correct URL based on network type: - Mainnet: kavascan.com - Testnet: testnet.kavascan.com Changes: - WalletsScreen: Added networkType parameter - WalletDetailDialog: Added copy feedback state and explorer button - MainActivity: Pass networkType to WalletsScreen 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../java/com/durian/tssparty/MainActivity.kt | 1 + .../presentation/screens/WalletsScreen.kt | 69 +++++++++++++++---- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/MainActivity.kt b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/MainActivity.kt index 0c857edd..e7cdbf43 100644 --- a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/MainActivity.kt +++ b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/MainActivity.kt @@ -161,6 +161,7 @@ fun TssPartyApp( shares = shares, isConnected = uiState.isConnected, balances = balances, + networkType = settings.networkType, onDeleteShare = { viewModel.deleteShare(it) }, onRefreshBalance = { address -> viewModel.fetchBalance(address) }, onTransfer = { shareId, toAddress, amount, password -> diff --git a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/presentation/screens/WalletsScreen.kt b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/presentation/screens/WalletsScreen.kt index 4255531d..0528089f 100644 --- a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/presentation/screens/WalletsScreen.kt +++ b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/presentation/screens/WalletsScreen.kt @@ -32,9 +32,14 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog +import android.content.Intent +import android.net.Uri +import com.durian.tssparty.domain.model.NetworkType import com.durian.tssparty.domain.model.ShareRecord import com.google.zxing.BarcodeFormat import com.google.zxing.qrcode.QRCodeWriter +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -42,6 +47,7 @@ fun WalletsScreen( shares: List, isConnected: Boolean, balances: Map = emptyMap(), + networkType: NetworkType = NetworkType.MAINNET, onDeleteShare: (Long) -> Unit, onRefreshBalance: ((String) -> Unit)? = null, onTransfer: ((shareId: Long, toAddress: String, amount: String, password: String) -> Unit)? = null, @@ -175,6 +181,7 @@ fun WalletsScreen( selectedWallet?.let { wallet -> WalletDetailDialog( wallet = wallet, + networkType = networkType, onDismiss = { selectedWallet = null }, onTransfer = { selectedWallet = null @@ -385,12 +392,16 @@ private fun WalletItemCard( @Composable private fun WalletDetailDialog( wallet: ShareRecord, + networkType: NetworkType = NetworkType.MAINNET, onDismiss: () -> Unit, onTransfer: () -> Unit, onExport: ((String) -> Unit)? ) { val clipboardManager = LocalClipboardManager.current + val context = androidx.compose.ui.platform.LocalContext.current + val scope = rememberCoroutineScope() var showExportDialog by remember { mutableStateOf(false) } + var copySuccess by remember { mutableStateOf(false) } Dialog(onDismissRequest = onDismiss) { Card( @@ -455,19 +466,53 @@ private fun WalletDetailDialog( Spacer(modifier = Modifier.height(8.dp)) - // Copy button - OutlinedButton( - onClick = { - clipboardManager.setText(AnnotatedString(wallet.address)) - } + // Action buttons row + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - Icon( - Icons.Default.ContentCopy, - contentDescription = null, - modifier = Modifier.size(18.dp) - ) - Spacer(modifier = Modifier.width(8.dp)) - Text("复制地址") + // Copy button + OutlinedButton( + onClick = { + clipboardManager.setText(AnnotatedString(wallet.address)) + copySuccess = true + scope.launch { + delay(2000) + copySuccess = false + } + }, + modifier = Modifier.weight(1f) + ) { + Icon( + if (copySuccess) Icons.Default.Check else Icons.Default.ContentCopy, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(4.dp)) + Text(if (copySuccess) "已复制" else "复制地址") + } + + // Explorer button + OutlinedButton( + onClick = { + val baseUrl = if (networkType == NetworkType.TESTNET) { + "https://testnet.kavascan.com" + } else { + "https://kavascan.com" + } + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("$baseUrl/address/${wallet.address}")) + context.startActivity(intent) + }, + modifier = Modifier.weight(1f) + ) { + Icon( + Icons.Default.OpenInNew, + contentDescription = null, + modifier = Modifier.size(18.dp) + ) + Spacer(modifier = Modifier.width(4.dp)) + Text("浏览器") + } } Spacer(modifier = Modifier.height(16.dp))