WIP: Cleanup

This commit is contained in:
2026-08-30 17:45:40 +09:00
parent a3fa7b21d0
commit 0fba9434e6
12 changed files with 44 additions and 72 deletions
@@ -520,7 +520,7 @@ fun GajuRouter(
val status = withContext(Dispatchers.IO) { client.status() }
val reportedNetworkId = status["network_id"] as? String
if ((reportedNetworkId != null && reportedNetworkId != wallet.networkId)) {
if ((reportedNetworkId != null) && (reportedNetworkId != wallet.networkId)) {
val allWallets = walletRepo.listWallets().mapNotNull { walletRepo.loadWallet(it) }
val targetWallet = allWallets.find { it.networkId == reportedNetworkId }
@@ -556,7 +556,7 @@ fun GajuRouter(
val status = withContext(Dispatchers.IO) { client.status() }
val reportedNetworkId = status["network_id"] as? String
if ((reportedNetworkId != null && reportedNetworkId != wallet.networkId)) {
if ((reportedNetworkId != null) && (reportedNetworkId != wallet.networkId)) {
// Mismatch logic
val allWallets = walletRepo.listWallets().mapNotNull { walletRepo.loadWallet(it) }
val targetWallet = allWallets.find { it.networkId == reportedNetworkId }
@@ -837,7 +837,7 @@ fun GajuRouter(
// If request specifies an ID, try to find that account
val signAccount = if (request.publicId != null && request.publicId != "false") {
wallets.flatMap { it.accounts }.find { it.gajuId == request.publicId }
wallets.asSequence().flatMap { it.accounts }.find { it.gajuId == request.publicId }
} else {
activeAccount
}
@@ -4,7 +4,6 @@ import android.content.Context
import kotlinx.serialization.json.Json
import swiss.qpq.gajumobile.data.models.Account
import swiss.qpq.gajumobile.data.models.Wallet
import swiss.qpq.gajumobile.security.AccountAirlock
import swiss.qpq.gajumobile.security.EncryptionService
import swiss.qpq.gajumobile.security.KeyManager
import swiss.qpq.gajumaru.core.tools.NodeClient
@@ -69,7 +68,6 @@ class WalletRepository(private val context: Context) {
}
val balance = accountInfo["balance"]?.toString() ?: "0"
val nonce = (accountInfo["nonce"] as? Number)?.toLong() ?: 0L
val updatedAccount = account.copy(
cachedBalance = CachedBalance(
@@ -90,28 +88,6 @@ class WalletRepository(private val context: Context) {
}
}
suspend fun getStatus(wallet: Wallet): Map<String, Any?>? {
val client = NodeClient(wallet.endpoints.map { NodeClient.Endpoint(it.host, it.port, it.useTls) })
return try {
withContext(Dispatchers.IO) {
client.status()
}
} catch (e: Exception) {
null
}
}
suspend fun postTransaction(wallet: Wallet, signedTx: String): Map<String, Any?>? {
val client = NodeClient(wallet.endpoints.map { NodeClient.Endpoint(it.host, it.port, it.useTls) })
return try {
withContext(Dispatchers.IO) {
client.postTx(signedTx)
}
} catch (e: Exception) {
null
}
}
fun listWallets(): List<String> {
val dir = File(context.filesDir, "wallets")
if (!dir.exists()) return emptyList()
@@ -4,7 +4,6 @@ import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.UUID;
import javax.crypto.SecretKey;
import swiss.qpq.gajumaru.core.crypto.Vault;
import swiss.qpq.gajumaru.core.encoding.Mnemonic;
import swiss.qpq.gajumaru.core.tools.CryptoUtils;
import swiss.qpq.gajumaru.core.tools.TransactionService;
@@ -191,22 +190,10 @@ public final class AccountAirlock {
try {
return Mnemonic.encode(plaintextPrivateKey);
} finally {
if (plaintextPrivateKey != null) safeMemzero(plaintextPrivateKey);
safeMemzero(plaintextPrivateKey);
}
}
/**
* Utility to convert a UI String into the internal airlock byte[][] format.
*/
public static byte[][] stringToPhrase(String phrase) {
String[] words = phrase.trim().split("\\s+");
byte[][] result = new byte[words.length][];
for (int i = 0; i < words.length; i++) {
result[i] = words[i].getBytes(StandardCharsets.UTF_8);
}
return result;
}
/**
* Utility to wipe a phrase returned by the airlock.
*/
@@ -33,7 +33,7 @@ import swiss.qpq.gajumobile.ui.components.GajuTextField
@Composable
fun CreateWalletScreen(
onWalletCreated: (name: String, networkId: String) -> Unit,
onBack: (() -> Unit)? = null
onBack: (() -> Unit)? = null,
) {
var walletName by remember { mutableStateOf("") }
var selectedNetwork by remember { mutableStateOf("groot.mainnet") }
@@ -2,7 +2,7 @@ package swiss.qpq.gajumobile.ui.screens
import android.content.ClipData
import android.content.Intent
import android.net.Uri
import androidx.core.net.toUri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -267,7 +267,7 @@ fun DashboardScreen(
androidx.compose.material3.TextButton(
onClick = {
val url = "https://${currentWallet.networkId}.gajumaru.io/account/${account.gajuId}"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
context.startActivity(intent)
},
modifier = Modifier.padding(bottom = 12.dp)
@@ -72,7 +72,7 @@ fun ManageAccountScreen(
Surface(
shape = RoundedCornerShape(16.dp),
color = MaterialTheme.colorScheme.surface,
tonalElevation = 8.dp
tonalElevation = 8.dp,
) {
Column(modifier = Modifier.padding(24.dp)) {
Text(stringResource(R.string.rename_account_title), style = MaterialTheme.typography.headlineSmall)
@@ -84,12 +84,20 @@ fun ManageAccountScreen(
)
Spacer(modifier = Modifier.height(24.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
TextButton(onClick = { showRenameDialog = false }) { Text(stringResource(R.string.cancel)) }
TextButton(
onClick = { showRenameDialog = false }
) {
Text(stringResource(R.string.cancel))
}
Spacer(modifier = Modifier.width(8.dp))
TextButton(onClick = {
onRename(newName)
showRenameDialog = false
}) { Text(stringResource(R.string.save_button_caps)) }
TextButton(
onClick = {
onRename(newName)
showRenameDialog = false
}
) {
Text(stringResource(R.string.save_button_caps))
}
}
}
}
@@ -47,11 +47,11 @@ import swiss.qpq.gajumobile.ui.components.GajuTextField
@Composable
fun MnemonicRecoveryScreen(
onMnemonicConfirmed: (Array<ByteArray>) -> Unit,
onBack: () -> Unit
onBack: () -> Unit,
) {
var committedWords by remember { mutableStateOf(listOf<String>()) }
var currentDraft by remember { mutableStateOf("") }
var isAddingWord by remember { mutableStateOf(true) }
var isAddingWord by remember { mutableStateOf(value = true) }
val allWords = remember { AccountAirlock.getWordList().toList() }
val focusRequester = remember { FocusRequester() }
@@ -61,7 +61,7 @@ fun MnemonicRecoveryScreen(
}
val suggestions = if (currentDraft.length >= 2) {
allWords.filter { it.startsWith(currentDraft) }.take(5)
allWords.asSequence().filter { it.startsWith(currentDraft) }.take(5).toList()
} else emptyList()
Scaffold(
@@ -72,7 +72,7 @@ fun MnemonicRecoveryScreen(
Surface(
modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.surfaceVariant,
tonalElevation = 8.dp
tonalElevation = 8.dp,
) {
FlowRow(
modifier = Modifier.padding(8.dp).fillMaxWidth(),
@@ -81,7 +81,7 @@ fun MnemonicRecoveryScreen(
suggestions.forEach { suggestion ->
SuggestionChip(
onClick = {
committedWords = committedWords + suggestion
committedWords += suggestion
currentDraft = ""
isAddingWord = false
},
@@ -109,7 +109,7 @@ fun MnemonicRecoveryScreen(
Spacer(modifier = Modifier.width(16.dp))
GajuButton(
text = stringResource(R.string.recover_button_caps),
enabled = committedWords.size >= 21 && !isAddingWord,
enabled = (committedWords.size >= 21) && !isAddingWord,
onClick = {
val phrase = committedWords.map { it.toByteArray(Charsets.UTF_8) }.toTypedArray()
onMnemonicConfirmed(phrase)
@@ -160,12 +160,12 @@ fun MnemonicRecoveryScreen(
)
}
if (isAddingWord && committedWords.size < 23) {
if ((isAddingWord) && (committedWords.size < 23)) {
Box(modifier = Modifier.width(120.dp)) {
GajuTextField(
value = currentDraft,
onValueChange = { currentDraft = it.lowercase() },
label = "${committedWords.size + 1}",
label = (committedWords.size + 1).toString(),
placeholder = "...",
modifier = Modifier.focusRequester(focusRequester)
)
@@ -49,11 +49,11 @@ fun MnemonicVerifyScreen(
label: String,
expectedPhrase: Array<ByteArray>,
onVerified: () -> Unit,
onBack: () -> Unit
onBack: () -> Unit,
) {
var committedWords by remember { mutableStateOf(listOf<String>()) }
var currentDraft by remember { mutableStateOf("") }
var isAddingWord by remember { mutableStateOf(true) }
var isAddingWord by remember { mutableStateOf(value = true) }
var verificationError by remember { mutableStateOf(false) }
val allWords = remember { AccountAirlock.getWordList().toList() }
@@ -64,7 +64,7 @@ fun MnemonicVerifyScreen(
}
val suggestions = if (currentDraft.length >= 2) {
allWords.filter { it.startsWith(currentDraft) }.take(5)
allWords.asSequence().filter { it.startsWith(currentDraft) }.take(5).toList()
} else emptyList()
Scaffold(
@@ -84,7 +84,7 @@ fun MnemonicVerifyScreen(
suggestions.forEach { suggestion ->
SuggestionChip(
onClick = {
committedWords = committedWords + suggestion
committedWords += suggestion
currentDraft = ""
isAddingWord = false
verificationError = false
@@ -113,7 +113,7 @@ fun MnemonicVerifyScreen(
Spacer(modifier = Modifier.width(16.dp))
GajuButton(
text = stringResource(R.string.verify_button_caps),
enabled = committedWords.size == expectedPhrase.size && !isAddingWord,
enabled = (committedWords.size == expectedPhrase.size) && !isAddingWord,
onClick = {
val inputPhrase = committedWords.map { it.toByteArray(Charsets.UTF_8) }
var match = true
@@ -179,7 +179,7 @@ fun MnemonicVerifyScreen(
GajuTextField(
value = currentDraft,
onValueChange = { currentDraft = it.lowercase() },
label = "${committedWords.size + 1}",
label = (committedWords.size + 1).toString(),
placeholder = "...",
modifier = Modifier.focusRequester(focusRequester)
)
@@ -62,7 +62,9 @@ fun SendReviewScreen(
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { confirmed = !confirmed }.padding(bottom = 24.dp)
modifier = Modifier
.clickable { confirmed = !confirmed }
.padding(bottom = 24.dp),
) {
Checkbox(checked = confirmed, onCheckedChange = { confirmed = it })
Text(
@@ -19,7 +19,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -50,12 +49,12 @@ import swiss.qpq.gajumaru.core.formatting.GajuFormat
fun SettingsScreen(
balanceFormat: GajuFormat.Type,
onFormatChange: (GajuFormat.Type) -> Unit,
onNavigate: (String) -> Unit
onNavigate: (String) -> Unit,
) {
val context = LocalContext.current
val localeManager = remember { context.getSystemService(LocaleManager::class.java) }
val currentLocales = localeManager.applicationLocales
val currentLanguage = if (currentLocales.isEmpty) "en" else currentLocales.get(0).language
val currentLanguage = if (currentLocales.isEmpty) "en" else currentLocales[0].language
Scaffold(
topBar = { GajuTopBar(onNavigate = onNavigate) },
@@ -161,7 +160,7 @@ fun SettingsScreen(
Spacer(modifier = Modifier.weight(1f))
var showWipeConfirm by remember { mutableStateOf(false) }
var showWipeConfirm by remember { mutableStateOf(value = false) }
if (showWipeConfirm) {
Surface(
@@ -1,7 +1,7 @@
package swiss.qpq.gajumobile.ui.screens
import android.content.Intent
import android.net.Uri
import androidx.core.net.toUri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
@@ -68,7 +68,7 @@ fun TransactionSuccessScreen(
modifier = Modifier
.clickable {
val url = "https://$networkId.gajumaru.io/tx/$txHash"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
context.startActivity(intent)
}
.padding(8.dp)
+1 -1
Submodule gm-java updated: 6714353f8c...381c8f1b9a