diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactsScreen.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactsScreen.kt index c7c25fc9..ff4cae3b 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactsScreen.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactsScreen.kt @@ -29,14 +29,13 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.outlined.Clear import androidx.compose.material3.ExperimentalMaterial3Api @@ -112,6 +111,43 @@ private fun ContactsScreen(navController: NavController) { var expanded by remember { mutableStateOf(false) } val both = stringResource(R.string.both) val import = stringResource(R.string.import_contacts) + val export = stringResource(R.string.export_contacts) + + val vcfExportLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.CreateDocument("text/vcard") + ) { uri: android.net.Uri? -> + if (uri != null) { + try { + ctx.contentResolver.openOutputStream(uri)?.use { outputStream -> + val writer = outputStream.bufferedWriter() + for (contact in BaresipService.baresipContacts.value) { + writer.write("BEGIN:VCARD\n") + writer.write("VERSION:3.0\n") + writer.write("FN:${contact.name}\n") + val nameParts = contact.name.split(" ", limit = 2) + if (nameParts.size == 2) + writer.write("N:${nameParts[1]};${nameParts[0]};;;\n") + else + writer.write("N:;${contact.name};;;\n") + if (contact.email.isNotEmpty()) + writer.write("EMAIL:${contact.email}\n") + for (u in contact.uris) { + if (u.startsWith("tel:")) + writer.write("TEL:${u.substring(4)}\n") + else if (u.startsWith("sip:")) + writer.write("X-SIP:${u.substring(4)}\n") + } + writer.write("END:VCARD\n") + } + writer.flush() + } + Toast.makeText(ctx, R.string.contact_export_success, Toast.LENGTH_SHORT).show() + } catch (e: Exception) { + Log.e(TAG, "Failed to export VCF: ${e.message}") + Toast.makeText(ctx, R.string.contact_export_failure, Toast.LENGTH_SHORT).show() + } + } + } val vcfImportLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.OpenDocument() @@ -357,13 +393,17 @@ private fun ContactsScreen(navController: NavController) { CustomElements.DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, - items = contactNames + import, + items = contactNames + import + export, onItemClick = { name -> expanded = false if (name == import) { vcfImportLauncher.launch(arrayOf("text/vcard", "text/x-vcard")) return@DropdownMenu } + if (name == export) { + vcfExportLauncher.launch("baresip_contacts.vcf") + return@DropdownMenu + } val mode = contactValues[contactNames.indexOf(name)] val contactsPermissions = arrayOf( Manifest.permission.READ_CONTACTS, @@ -571,7 +611,9 @@ private fun ContactsContent( state = lazyListState, verticalArrangement = Arrangement.spacedBy(10.dp), ) { - items(filteredContacts, key = { it.first.id() }) { (contact, annotatedName) -> + itemsIndexed( + filteredContacts, key = { index, (contact, _) -> "${contact.id()}_$index" } + ) { _, (contact, annotatedName) -> Row( verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 1c4e0df4..4488be4e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -508,6 +508,8 @@ Tuo Yhteystietojen tuonti onnistui Yhteystietojen tuonti epäonnistui + Yhteistietojen vienti onnistui + Yhteistietojen vienti epäonnistui Varoitus diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 849fd31f..e9a8902c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -477,8 +477,11 @@ Do you want to delete contact \'%1$s\'\? Search Import + Export Contacts imported successfully Failed to import contacts + Contacts exported successfully + Failed to export contacts Alert Info