commit 5ca8e78d2e1666fef8e52ce9c819be9b5458d724
parent a0a5e6e05ca585d366af2c90616543d3f85a6eac
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Thu, 22 Oct 2026 22:28:42 +0200
aliases: update to recent wallet API changes. Add browser redirect for alias types other than email and phone. and actually get supported aliases from server
Diffstat:
2 files changed, 75 insertions(+), 21 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/contacts/AliasRegistrationScreen.kt b/wallet/src/main/java/net/taler/wallet/contacts/AliasRegistrationScreen.kt
@@ -16,6 +16,8 @@
package net.taler.wallet.contacts
+import android.content.Intent
+import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -66,6 +68,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
@@ -81,10 +84,12 @@ fun AliasRegistrationScreen(
model: MainViewModel,
onNavigateBack: () -> Unit,
) {
+ val context = LocalContext.current
val mailboxState by model.mailboxManager.mailbox.collectAsState()
val registerResult by model.contactManager.registerResult.collectAsState()
val contactsResult by model.contactManager.contacts.collectAsState()
val aliasStatuses by model.contactManager.aliasStatuses.collectAsState()
+ val supportedAliasTypes by model.contactManager.supportedAliasTypes.collectAsState()
var showAddAliasDialog by remember { mutableStateOf(false) }
var activeRegistrationAlias by remember { mutableStateOf<ContactEntry?>(null) }
@@ -92,13 +97,14 @@ fun AliasRegistrationScreen(
LaunchedEffect(Unit) {
model.contactManager.loadContacts()
+ model.contactManager.loadSupportedAliasTypes()
}
val mailboxConfig = (mailboxState as? MailboxResult.Success)?.config
LaunchedEffect(contactsResult, mailboxConfig) {
if (contactsResult is ContactResult.Success && mailboxConfig != null) {
- val userAliases = (contactsResult as ContactResult.Success).contacts.filter { it.self }
+ val userAliases = (contactsResult as ContactResult.Success).contacts.filter { it.isSelf || it.source == "self" }
userAliases.forEach { contact ->
model.contactManager.checkAliasRegistration(
alias = contact.alias,
@@ -116,7 +122,7 @@ fun AliasRegistrationScreen(
}
}
- val userAliases = (contactsResult as? ContactResult.Success)?.contacts?.filter { it.self } ?: emptyList()
+ val userAliases = (contactsResult as? ContactResult.Success)?.contacts?.filter { it.isSelf || it.source == "self" } ?: emptyList()
AliasRegistrationContent(
userAliases = userAliases,
@@ -131,14 +137,25 @@ fun AliasRegistrationScreen(
activeRegistrationAlias = contact
isUnlinking = false
if (mailboxConfig != null) {
- model.contactManager.taldirRegister(
- alias = contact.alias,
- aliasType = contact.aliasType,
- taldirBaseUri = "https://taldir.gnunet.org",
- mailboxBaseUrl = mailboxConfig.mailboxBaseUrl,
- mailboxAddress = mailboxConfig.hAddress,
- durationMonths = 12,
- )
+ val type = contact.aliasType.lowercase()
+ val taldirBaseUrl = "https://taldir.gnunet.org"
+ if (type == "email" || type == "phone") {
+ model.contactManager.taldirRegister(
+ alias = contact.alias,
+ aliasType = contact.aliasType,
+ taldirBaseUri = taldirBaseUrl,
+ mailboxBaseUrl = mailboxConfig.mailboxBaseUrl,
+ mailboxAddress = mailboxConfig.hAddress,
+ durationMonths = 12,
+ )
+ } else {
+ val targetUri = "${mailboxConfig.mailboxBaseUrl.trimEnd('/')}/${mailboxConfig.hAddress}"
+ val encodedAlias = Uri.encode(contact.alias)
+ val encodedTargetUri = Uri.encode(targetUri)
+ val browserUrl = "$taldirBaseUrl/lookup/${contact.aliasType}?alias=$encodedAlias&targetUri=$encodedTargetUri"
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(browserUrl))
+ context.startActivity(intent)
+ }
}
},
onCompleteRegister = { solution ->
@@ -228,6 +245,7 @@ fun AliasRegistrationScreen(
if (showAddAliasDialog && mailboxConfig != null) {
AddAliasDialog(
+ supportedAliasTypes = supportedAliasTypes,
onDismiss = { showAddAliasDialog = false },
onConfirm = { alias, aliasType, nickname ->
model.contactManager.addContact(
@@ -481,16 +499,24 @@ fun UserAliasCard(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AddAliasDialog(
+ supportedAliasTypes: List<TaldirAliasType>,
onDismiss: () -> Unit,
onConfirm: (alias: String, aliasType: String, nickname: String) -> Unit,
) {
- var aliasType by remember { mutableStateOf("email") }
+ val options = if (supportedAliasTypes.isNotEmpty()) {
+ supportedAliasTypes
+ } else {
+ listOf(
+ TaldirAliasType(name = "email", display = "email"),
+ TaldirAliasType(name = "phone", display = "phone")
+ )
+ }
+
+ var selectedType by remember(options) { mutableStateOf(options.first()) }
var aliasTypeExpanded by remember { mutableStateOf(false) }
var alias by remember { mutableStateOf("") }
var nickname by remember { mutableStateOf("") }
- val aliasTypeOptions = listOf("email", "phone")
-
AlertDialog(
onDismissRequest = onDismiss,
title = { Text("Add Alias") },
@@ -502,7 +528,7 @@ fun AddAliasDialog(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
) {
OutlinedTextField(
- value = aliasType,
+ value = selectedType.display,
onValueChange = {},
readOnly = true,
label = { Text(stringResource(R.string.alias_registration_alias_type)) },
@@ -514,11 +540,11 @@ fun AddAliasDialog(
expanded = aliasTypeExpanded,
onDismissRequest = { aliasTypeExpanded = false }
) {
- aliasTypeOptions.forEach { option ->
+ options.forEach { type ->
DropdownMenuItem(
- text = { Text(option) },
+ text = { Text(type.display) },
onClick = {
- aliasType = option
+ selectedType = type
aliasTypeExpanded = false
}
)
@@ -531,7 +557,7 @@ fun AddAliasDialog(
onValueChange = { alias = it },
label = { Text(stringResource(R.string.alias_registration_alias)) },
placeholder = {
- Text(if (aliasType == "email") "user@example.com" else "+1234567890")
+ Text(if (selectedType.name == "email") "user@example.com" else "+1234567890")
},
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
)
@@ -546,7 +572,7 @@ fun AddAliasDialog(
},
confirmButton = {
Button(
- onClick = { onConfirm(alias.trim(), aliasType, nickname.trim()) },
+ onClick = { onConfirm(alias.trim(), selectedType.name, nickname.trim()) },
enabled = alias.isNotBlank()
) {
Text(stringResource(R.string.ok))
diff --git a/wallet/src/main/java/net/taler/wallet/contacts/ContactManager.kt b/wallet/src/main/java/net/taler/wallet/contacts/ContactManager.kt
@@ -101,6 +101,19 @@ sealed class AliasRegistrationStatus {
data class Mismatched(val targetUri: String) : AliasRegistrationStatus()
}
+@Serializable
+data class TaldirAliasType(
+ val name: String,
+ val display: String = name,
+ @SerialName("challenge_fee")
+ val challengeFee: String? = null,
+)
+
+@Serializable
+data class TaldirSupportedAliasesResponse(
+ val supportedAliases: List<TaldirAliasType>,
+)
+
class ContactManager(
private val api: WalletBackendApi,
private val scope: CoroutineScope,
@@ -117,6 +130,9 @@ class ContactManager(
private val _aliasStatuses = MutableStateFlow<Map<String, AliasRegistrationStatus>>(emptyMap())
val aliasStatuses = _aliasStatuses.asStateFlow()
+ private val _supportedAliasTypes = MutableStateFlow<List<TaldirAliasType>>(emptyList())
+ val supportedAliasTypes = _supportedAliasTypes.asStateFlow()
+
fun resetLookup() {
_lookupResult.value = LookupResult.Idle
}
@@ -125,6 +141,18 @@ class ContactManager(
_registerResult.value = RegisterResult.Idle
}
+ fun loadSupportedAliasTypes(taldirBaseUri: String = "https://taldir.gnunet.org") {
+ scope.launch {
+ api.request("getSupportedAliasTypes", TaldirSupportedAliasesResponse.serializer()) {
+ put("taldirBaseUrl", taldirBaseUri)
+ }.onSuccess { resp ->
+ _supportedAliasTypes.value = resp.supportedAliases
+ }.onError {
+ Log.e(TAG, "Error getting supported alias types: $it")
+ }
+ }
+ }
+
fun loadContacts() {
_contacts.value = ContactResult.Loading
scope.launch {
@@ -345,12 +373,12 @@ class ContactManager(
))
}
} else {
- if (targetUri.isNullOrBlank()) {
+ if (targetUri.isBlank()) {
_registerResult.value = RegisterResult.Error(TalerErrorInfo(
code = TalerErrorCode.UNKNOWN,
message = "Alias not found",
))
- } else if (targetUri != expectedTargetUri) {
+ } else if (targetUri.trimEnd('/') != expectedTargetUri.trimEnd('/') && !targetUri.endsWith(expectedTargetUri.substringAfterLast('/'))) {
_registerResult.value = RegisterResult.Error(TalerErrorInfo(
code = TalerErrorCode.UNKNOWN,
message = "Existing registration points to a different mailbox URI",