fix(android): add copy feedback and explorer link to wallet detail

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 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-01 03:32:33 -08:00
parent f7de1e8d09
commit 2b0920f9b1
2 changed files with 58 additions and 12 deletions

View File

@ -161,6 +161,7 @@ fun TssPartyApp(
shares = shares, shares = shares,
isConnected = uiState.isConnected, isConnected = uiState.isConnected,
balances = balances, balances = balances,
networkType = settings.networkType,
onDeleteShare = { viewModel.deleteShare(it) }, onDeleteShare = { viewModel.deleteShare(it) },
onRefreshBalance = { address -> viewModel.fetchBalance(address) }, onRefreshBalance = { address -> viewModel.fetchBalance(address) },
onTransfer = { shareId, toAddress, amount, password -> onTransfer = { shareId, toAddress, amount, password ->

View File

@ -32,9 +32,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog 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.durian.tssparty.domain.model.ShareRecord
import com.google.zxing.BarcodeFormat import com.google.zxing.BarcodeFormat
import com.google.zxing.qrcode.QRCodeWriter import com.google.zxing.qrcode.QRCodeWriter
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -42,6 +47,7 @@ fun WalletsScreen(
shares: List<ShareRecord>, shares: List<ShareRecord>,
isConnected: Boolean, isConnected: Boolean,
balances: Map<String, String> = emptyMap(), balances: Map<String, String> = emptyMap(),
networkType: NetworkType = NetworkType.MAINNET,
onDeleteShare: (Long) -> Unit, onDeleteShare: (Long) -> Unit,
onRefreshBalance: ((String) -> Unit)? = null, onRefreshBalance: ((String) -> Unit)? = null,
onTransfer: ((shareId: Long, toAddress: String, amount: String, password: String) -> Unit)? = null, onTransfer: ((shareId: Long, toAddress: String, amount: String, password: String) -> Unit)? = null,
@ -175,6 +181,7 @@ fun WalletsScreen(
selectedWallet?.let { wallet -> selectedWallet?.let { wallet ->
WalletDetailDialog( WalletDetailDialog(
wallet = wallet, wallet = wallet,
networkType = networkType,
onDismiss = { selectedWallet = null }, onDismiss = { selectedWallet = null },
onTransfer = { onTransfer = {
selectedWallet = null selectedWallet = null
@ -385,12 +392,16 @@ private fun WalletItemCard(
@Composable @Composable
private fun WalletDetailDialog( private fun WalletDetailDialog(
wallet: ShareRecord, wallet: ShareRecord,
networkType: NetworkType = NetworkType.MAINNET,
onDismiss: () -> Unit, onDismiss: () -> Unit,
onTransfer: () -> Unit, onTransfer: () -> Unit,
onExport: ((String) -> Unit)? onExport: ((String) -> Unit)?
) { ) {
val clipboardManager = LocalClipboardManager.current val clipboardManager = LocalClipboardManager.current
val context = androidx.compose.ui.platform.LocalContext.current
val scope = rememberCoroutineScope()
var showExportDialog by remember { mutableStateOf(false) } var showExportDialog by remember { mutableStateOf(false) }
var copySuccess by remember { mutableStateOf(false) }
Dialog(onDismissRequest = onDismiss) { Dialog(onDismissRequest = onDismiss) {
Card( Card(
@ -455,19 +466,53 @@ private fun WalletDetailDialog(
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
// Copy button // Action buttons row
OutlinedButton( Row(
onClick = { modifier = Modifier.fillMaxWidth(),
clipboardManager.setText(AnnotatedString(wallet.address)) horizontalArrangement = Arrangement.spacedBy(8.dp)
}
) { ) {
Icon( // Copy button
Icons.Default.ContentCopy, OutlinedButton(
contentDescription = null, onClick = {
modifier = Modifier.size(18.dp) clipboardManager.setText(AnnotatedString(wallet.address))
) copySuccess = true
Spacer(modifier = Modifier.width(8.dp)) scope.launch {
Text("复制地址") 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)) Spacer(modifier = Modifier.height(16.dp))