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,
isConnected = uiState.isConnected,
balances = balances,
networkType = settings.networkType,
onDeleteShare = { viewModel.deleteShare(it) },
onRefreshBalance = { address -> viewModel.fetchBalance(address) },
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.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<ShareRecord>,
isConnected: Boolean,
balances: Map<String, String> = 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))