Added support for multiple uris in baresip contact

Improved selectable alert dialog colors
This commit is contained in:
Juha Heinanen
2026-05-17 18:50:36 +03:00
parent de575d52b7
commit aa0098b16b
6 changed files with 279 additions and 86 deletions

View File

@ -37,7 +37,9 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -108,7 +110,7 @@ private data class ScreenState(
val id: Long = 0, val id: Long = 0,
val newId: Long = 0, val newId: Long = 0,
val name: String = "", val name: String = "",
val uri: String = "", val uris: List<String> = emptyList(),
val color: Int = 0, val color: Int = 0,
val avatarImageUri: String? = null, val avatarImageUri: String? = null,
val tmpAvatarFile: File? = null, val tmpAvatarFile: File? = null,
@ -138,7 +140,7 @@ private fun ContactScreen(
screenState = ScreenState( screenState = ScreenState(
new = true, new = true,
name = "", name = "",
uri = uriOrNameArg, uris = if (uriOrNameArg == "") emptyList() else listOf(uriOrNameArg),
favorite = false, favorite = false,
android = BaresipService.contactsMode == "android", android = BaresipService.contactsMode == "android",
color = Utils.randomColor(), color = Utils.randomColor(),
@ -153,7 +155,7 @@ private fun ContactScreen(
screenState = ScreenState( screenState = ScreenState(
new = false, new = false,
name = uriOrNameArg, name = uriOrNameArg,
uri = contact.uri, uris = contact.uris,
favorite = contact.favorite, favorite = contact.favorite,
android = false, android = false,
color = contact.color, color = contact.color,
@ -320,9 +322,9 @@ private fun ContactContent(
new = screenState.new, new = screenState.new,
onNameChange = { newName -> onStateChange(screenState.copy(name = newName)) } onNameChange = { newName -> onStateChange(screenState.copy(name = newName)) }
) )
ContactUri( ContactUris(
uri = screenState.uri, uris = screenState.uris,
onUriChange = { newUri -> onStateChange(screenState.copy(uri = newUri)) } onUrisChange = { newUris -> onStateChange(screenState.copy(uris = newUris)) }
) )
Favorite( Favorite(
ctx = ctx, ctx = ctx,
@ -456,16 +458,62 @@ private fun ContactName(name: String, new: Boolean, onNameChange: (String) -> Un
} }
@Composable @Composable
private fun ContactUri(uri: String, onUriChange: (String) -> Unit) { private fun ContactUris(uris: List<String>, onUrisChange: (List<String>) -> Unit) {
OutlinedTextField( Column(
value = uri,
placeholder = { Text(stringResource(R.string.user_domain_or_number)) },
onValueChange = onUriChange,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
textStyle = androidx.compose.ui.text.TextStyle(fontSize = 18.sp), verticalArrangement = Arrangement.spacedBy(8.dp)
label = { Text(stringResource(R.string.sip_or_tel_uri)) }, ) {
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text) uris.forEachIndexed { index, uri ->
) Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
OutlinedTextField(
value = uri,
placeholder = { Text(stringResource(R.string.user_domain_or_number)) },
onValueChange = { newUri ->
val newList = uris.toMutableList()
newList[index] = newUri
onUrisChange(newList.toList())
},
modifier = Modifier.weight(1f),
textStyle = androidx.compose.ui.text.TextStyle(fontSize = 18.sp),
label = { Text("${stringResource(R.string.sip_or_tel_uri)} ${index + 1}") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
)
if (uris.size > 1) {
IconButton(
onClick = {
val newList = uris.toMutableList()
newList.removeAt(index)
onUrisChange(newList.toList())
},
modifier = Modifier.padding(start = 4.dp)
) {
Icon(
imageVector = Icons.Filled.Delete,
contentDescription = "Delete",
tint = MaterialTheme.colorScheme.error
)
}
}
}
}
IconButton(
onClick = {
val newList = uris.toMutableList()
newList.add("")
onUrisChange(newList.toList())
},
modifier = Modifier.align(Alignment.Start)
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "Add",
tint = MaterialTheme.colorScheme.primary
)
}
}
} }
@Composable @Composable
@ -520,22 +568,34 @@ private fun checkOnClick(
uriOrNameArg: String uriOrNameArg: String
): Boolean { ): Boolean {
var newUri = currentState.uri.filterNot{setOf('-', ' ', '(', ')').contains(it)} val newUris = ArrayList<String>()
if (!newUri.startsWith("sip:") && !newUri.startsWith("tel:")) for (uri in currentState.uris) {
newUri = if (Utils.isTelNumber(newUri)) var u = uri.filterNot{setOf('-', ' ', '(', ')').contains(it)}
"tel:$newUri" if (u == "") continue
else if (!u.startsWith("sip:") && !u.startsWith("tel:"))
"sip:$newUri" u = if (Utils.isTelNumber(u))
"tel:$u"
else
"sip:$u"
if (!Utils.checkUri(newUri)) { if (!Utils.checkUri(u)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = String.format(ctx.getString(R.string.invalid_sip_or_tel_uri), u)
showAlert.value = true
return false
}
newUris.add(u)
}
if (newUris.isEmpty()) {
alertTitle.value = ctx.getString(R.string.notice) alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = String.format(ctx.getString(R.string.invalid_sip_or_tel_uri), newUri) alertMessage.value = ctx.getString(R.string.sip_or_tel_uri)
showAlert.value = true showAlert.value = true
return false return false
} }
var newName = currentState.name.trim() var newName = currentState.name.trim()
if (newName == "") newName = newUri.substringAfter(":") if (newName == "") newName = newUris[0].substringAfter(":")
if (!Utils.checkName(newName)) { if (!Utils.checkName(newName)) {
alertTitle.value = ctx.getString(R.string.notice) alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = String.format(ctx.getString(R.string.invalid_contact), newName) alertMessage.value = String.format(ctx.getString(R.string.invalid_contact), newName)
@ -572,7 +632,7 @@ private fun checkOnClick(
val contact: Contact.BaresipContact = val contact: Contact.BaresipContact =
Contact.BaresipContact( Contact.BaresipContact(
newName, newName,
newUri, newUris,
currentState.color, currentState.color,
idToUse, idToUse,
currentState.favorite currentState.favorite
@ -683,17 +743,19 @@ private fun addAndroidContact(ctx: Context, contact: Contact.BaresipContact): Bo
.withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, contact.name) .withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, contact.name)
.build()) .build())
val mimeType = if (contact.uri.startsWith("sip:")) for (uri in contact.uris) {
CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE val mimeType = if (uri.startsWith("sip:"))
else CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
CommonDataKinds.Phone.CONTENT_ITEM_TYPE else
ops.add( CommonDataKinds.Phone.CONTENT_ITEM_TYPE
ContentProviderOperation ops.add(
.newInsert(ContactsContract.Data.CONTENT_URI) ContentProviderOperation
.withValueBackReference(Data.RAW_CONTACT_ID, 0) .newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(Data.MIMETYPE, mimeType) .withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.DATA1, contact.uri.substringAfter(":")) .withValue(Data.MIMETYPE, mimeType)
.build()) .withValue(Data.DATA1, uri.substringAfter(":"))
.build())
}
if (contact.avatarImage != null) { if (contact.avatarImage != null) {
val photoData: ByteArray? = bitmapToPNGByteArray(contact.avatarImage!!) val photoData: ByteArray? = bitmapToPNGByteArray(contact.avatarImage!!)
@ -717,8 +779,9 @@ private fun addAndroidContact(ctx: Context, contact: Contact.BaresipContact): Bo
} }
private fun updateAndroidContact(ctx: Context, rawContactId: Long, contact: Contact.BaresipContact) { private fun updateAndroidContact(ctx: Context, rawContactId: Long, contact: Contact.BaresipContact) {
if (updateAndroidUri(ctx, rawContactId, contact.uri) == 0) for (uri in contact.uris)
addAndroidUri(ctx, rawContactId, contact.uri) if (updateAndroidUri(ctx, rawContactId, uri) == 0)
addAndroidUri(ctx, rawContactId, uri)
if (updateAndroidPhoto(ctx, rawContactId, contact.avatarImage) == 0) if (updateAndroidPhoto(ctx, rawContactId, contact.avatarImage) == 0)
if (contact.avatarImage != null) if (contact.avatarImage != null)
addAndroidPhoto(ctx, rawContactId, contact.avatarImage!!) addAndroidPhoto(ctx, rawContactId, contact.avatarImage!!)

View File

@ -72,6 +72,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.navArgument import androidx.navigation.navArgument
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.tutpro.baresip.CustomElements.AlertDialog import com.tutpro.baresip.CustomElements.AlertDialog
import com.tutpro.baresip.CustomElements.SelectableAlertDialog
import com.tutpro.baresip.CustomElements.verticalScrollbar import com.tutpro.baresip.CustomElements.verticalScrollbar
fun NavGraphBuilder.callsScreenRoute(navController: NavController, viewModel: ViewModel) { fun NavGraphBuilder.callsScreenRoute(navController: NavController, viewModel: ViewModel) {
@ -303,6 +304,15 @@ private fun Calls(
lastButtonText = stringResource(R.string.ok), lastButtonText = stringResource(R.string.ok),
) )
SelectableAlertDialog(
openDialog = CustomElements.showSelectItemDialog,
title = stringResource(R.string.choose_destination_uri),
items = CustomElements.selectItems.value,
onItemClicked = CustomElements.selectItemAction.value,
neutralButtonText = stringResource(R.string.cancel),
onNeutralClicked = {}
)
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
@ -339,32 +349,88 @@ private fun Calls(
secondButtonText.value = ctx.getString(R.string.call) secondButtonText.value = ctx.getString(R.string.call)
secondAction.value = { secondAction.value = {
if (ua != null) { if (ua != null) {
handleIntent(ctx, viewModel, intent, "call") val contact = Contact.findContact(peerUri)
navController.navigate("main") { val uris = if (contact is Contact.BaresipContact) {
popUpTo("main") if (ua.account.isMobile)
launchSingleTop = true contact.uris.filter { it.startsWith("tel:") }
else
contact.uris
} else {
listOf(peerUri)
}
if (uris.size > 1) {
CustomElements.selectItems.value = uris
CustomElements.selectItemAction.value = { index ->
intent.putExtra("peer", uris[index])
handleIntent(ctx, viewModel, intent, "call")
navController.navigate("main") {
popUpTo("main")
launchSingleTop = true
}
CustomElements.showSelectItemDialog.value = false
}
CustomElements.showSelectItemDialog.value = true
} else if (uris.size == 1) {
intent.putExtra("peer", uris[0])
handleIntent(ctx, viewModel, intent, "call")
navController.navigate("main") {
popUpTo("main")
launchSingleTop = true
}
} }
} }
} }
lastButtonText.value = ctx.getString(R.string.send_message) lastButtonText.value = ctx.getString(R.string.send_message)
lastAction.value = { lastAction.value = {
if (account.isMobile) { if (ua != null) {
if (!Utils.isDefaultSmsApp(ctx)) { val contact = Contact.findContact(peerUri)
alertTitle.value = ctx.getString(R.string.notice) val uris = if (contact is Contact.BaresipContact) {
alertMessage.value = ctx.getString(R.string.enable_default_messaging) if (ua.account.isMobile)
showAlert.value = true contact.uris.filter { it.startsWith("tel:") }
else
contact.uris
} else { } else {
if (ua != null) { listOf(peerUri)
}
if (uris.size > 1) {
CustomElements.selectItems.value = uris
CustomElements.selectItemAction.value = { index ->
intent.putExtra("peer", uris[index])
if (ua.account.isMobile) {
if (!Utils.isDefaultSmsApp(ctx)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.enable_default_messaging)
showAlert.value = true
} else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
} else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
CustomElements.showSelectItemDialog.value = false
}
CustomElements.showSelectItemDialog.value = true
} else if (uris.size == 1) {
intent.putExtra("peer", uris[0])
if (ua.account.isMobile) {
if (!Utils.isDefaultSmsApp(ctx)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.enable_default_messaging)
showAlert.value = true
} else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
} else {
handleIntent(ctx, viewModel, intent, "message") handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp() navController.navigateUp()
} }
} }
} }
else
if (ua != null) {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
} }
showDialog.value = true showDialog.value = true
}, },

View File

@ -13,7 +13,7 @@ import java.util.ArrayList
sealed class Contact { sealed class Contact {
class BaresipContact(var name: String, var uri: String, var color: Int, var id: Long, class BaresipContact(var name: String, val uris: ArrayList<String>, var color: Int, var id: Long,
var favorite: Boolean): Contact() { var favorite: Boolean): Contact() {
var avatarImage: Bitmap? = null var avatarImage: Bitmap? = null
} }
@ -57,7 +57,7 @@ sealed class Contact {
fun copy(): Contact { fun copy(): Contact {
val copy = when (this) { val copy = when (this) {
is BaresipContact -> is BaresipContact ->
BaresipContact(name, uri, color, id, favorite) BaresipContact(name, ArrayList(uris), color, id, favorite)
is AndroidContact -> is AndroidContact ->
AndroidContact(name, color, thumbnailUri, id, favorite) AndroidContact(name, color, thumbnailUri, id, favorite)
} }
@ -107,9 +107,10 @@ sealed class Contact {
when (c) { when (c) {
is BaresipContact -> { is BaresipContact -> {
if (c.name.equals(name, ignoreCase = true)) { if (c.name.equals(name, ignoreCase = true)) {
uris.add(c.uri.removePrefix("<") for (u in c.uris)
.replaceAfter(">", "") uris.add(u.removePrefix("<")
.replace(">", "")) .replaceAfter(">", "")
.replace(">", ""))
return uris return uris
} }
} }
@ -128,8 +129,9 @@ sealed class Contact {
for (c in BaresipService.contacts) for (c in BaresipService.contacts)
when (c) { when (c) {
is BaresipContact -> { is BaresipContact -> {
if (Utils.uriMatch(c.uri, uri)) for (u in c.uris)
return c if (Utils.uriMatch(u, uri))
return c
} }
is AndroidContact -> { is AndroidContact -> {
val cleanUri = uri.filterNot{setOf('-', ' ', '(', ')').contains(it)} val cleanUri = uri.filterNot{setOf('-', ' ', '(', ')').contains(it)}
@ -153,7 +155,7 @@ sealed class Contact {
val avatarFiles = avatarFileNames() val avatarFiles = avatarFileNames()
var contents = "" var contents = ""
for (c in BaresipService.baresipContacts.value) { for (c in BaresipService.baresipContacts.value) {
contents += "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color}" + contents += "\"${c.name}\" <${c.uris.joinToString(",")}>;id=${c.id};color=${c.color}" +
";favorite=${if (c.favorite) "yes" else "no"}\n" ";favorite=${if (c.favorite) "yes" else "no"}\n"
avatarFiles.remove(c.id.toString() + ".png") avatarFiles.remove(c.id.toString() + ".png")
} }
@ -236,7 +238,8 @@ sealed class Contact {
contactNo++ contactNo++
val name = parts[1] val name = parts[1]
val uriParams = parts[2].trim() val uriParams = parts[2].trim()
val uri = uriParams.substringAfter("<").substringBefore(">") val urisPart = uriParams.substringAfter("<").substringBefore(">")
val uris = ArrayList(urisPart.split(","))
val params = uriParams.substringAfter(">;") val params = uriParams.substringAfter(">;")
val colorValue = Utils.paramValue(params, "color" ) val colorValue = Utils.paramValue(params, "color" )
val color: Int = if (colorValue != "") val color: Int = if (colorValue != "")
@ -249,8 +252,8 @@ sealed class Contact {
else else
baseId + contactNo baseId + contactNo
val favorite = Utils.paramValue(params, "favorite" ) == "yes" val favorite = Utils.paramValue(params, "favorite" ) == "yes"
Log.d(TAG, "Restoring contact $name, $uri, $color, $id") Log.d(TAG, "Restoring contact $name, $urisPart, $color, $id")
val contact = BaresipContact(name, uri, color, id, favorite) val contact = BaresipContact(name, uris, color, id, favorite)
val avatarFilePath = BaresipService.filesPath + "/$id.png" val avatarFilePath = BaresipService.filesPath + "/$id.png"
if (File(avatarFilePath).exists()) { if (File(avatarFilePath).exists()) {
try { try {

View File

@ -77,6 +77,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.tutpro.baresip.CustomElements.AlertDialog import com.tutpro.baresip.CustomElements.AlertDialog
import com.tutpro.baresip.CustomElements.SelectableAlertDialog
import com.tutpro.baresip.CustomElements.TextAvatar import com.tutpro.baresip.CustomElements.TextAvatar
import com.tutpro.baresip.CustomElements.verticalScrollbar import com.tutpro.baresip.CustomElements.verticalScrollbar
import java.io.File import java.io.File
@ -209,6 +210,15 @@ private fun ContactsScreen(
} }
) )
SelectableAlertDialog(
openDialog = CustomElements.showSelectItemDialog,
title = stringResource(R.string.choose_destination_uri),
items = CustomElements.selectItems.value,
onItemClicked = CustomElements.selectItemAction.value,
neutralButtonText = stringResource(R.string.cancel),
onNeutralClicked = {}
)
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize().imePadding(), modifier = Modifier.fillMaxSize().imePadding(),
containerColor = MaterialTheme.colorScheme.background, containerColor = MaterialTheme.colorScheme.background,
@ -508,7 +518,6 @@ private fun ContactsContent(
val intent = Intent(ctx, MainActivity::class.java) val intent = Intent(ctx, MainActivity::class.java)
if (ua != null) { if (ua != null) {
intent.putExtra("uap", ua.uap) intent.putExtra("uap", ua.uap)
intent.putExtra("peer", contact.uri)
} }
else else
Log.w(TAG, "onClickListener did not find UA for $aor") Log.w(TAG, "onClickListener did not find UA for $aor")
@ -519,30 +528,79 @@ private fun ContactsContent(
secondText.value = ctx.getString(R.string.call) secondText.value = ctx.getString(R.string.call)
secondAction.value = { secondAction.value = {
if (ua != null) { if (ua != null) {
handleIntent(ctx, viewModel, intent, "call") val uris = if (ua.account.isMobile)
navController.navigate("main") { contact.uris.filter { it.startsWith("tel:") }
popUpTo("main") else
launchSingleTop = true contact.uris
if (uris.size > 1) {
CustomElements.selectItems.value = uris
CustomElements.selectItemAction.value = { index: Int ->
intent.putExtra("peer", uris[index])
handleIntent(ctx, viewModel, intent, "call")
navController.navigate("main") {
popUpTo("main")
launchSingleTop = true
}
CustomElements.showSelectItemDialog.value = false
}
CustomElements.showSelectItemDialog.value = true
} else if (uris.size == 1) {
intent.putExtra("peer", uris[0])
handleIntent(ctx, viewModel, intent, "call")
navController.navigate("main") {
popUpTo("main")
launchSingleTop = true
}
} }
} }
} }
lastText.value = ctx.getString(R.string.send_message) lastText.value = ctx.getString(R.string.send_message)
lastAction.value = { lastAction.value = {
if (ua != null) { if (ua != null) {
if (ua.account.isMobile) { val uris = if (ua.account.isMobile)
if (!Utils.isDefaultSmsApp(ctx)) { contact.uris.filter { it.startsWith("tel:") }
alertTitle.value = ctx.getString(R.string.notice) else
alertMessage.value = ctx.getString(R.string.enable_default_messaging) contact.uris
showAlert.value = true
} else { if (uris.size > 1) {
CustomElements.selectItems.value = uris
CustomElements.selectItemAction.value = { index: Int ->
intent.putExtra("peer", uris[index])
if (ua.account.isMobile) {
if (!Utils.isDefaultSmsApp(ctx)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.enable_default_messaging)
showAlert.value = true
} else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
}
else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
CustomElements.showSelectItemDialog.value = false
}
CustomElements.showSelectItemDialog.value = true
} else if (uris.size == 1) {
intent.putExtra("peer", uris[0])
if (ua.account.isMobile) {
if (!Utils.isDefaultSmsApp(ctx)) {
alertTitle.value = ctx.getString(R.string.notice)
alertMessage.value = ctx.getString(R.string.enable_default_messaging)
showAlert.value = true
} else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
}
else {
handleIntent(ctx, viewModel, intent, "message") handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp() navController.navigateUp()
} }
} }
else {
handleIntent(ctx, viewModel, intent, "message")
navController.navigateUp()
}
} }
} }
showDialog.value = true showDialog.value = true

View File

@ -82,6 +82,10 @@ import androidx.compose.ui.window.DialogProperties
object CustomElements { object CustomElements {
val selectItems = mutableStateOf(listOf<String>())
val selectItemAction = mutableStateOf<(Int) -> Unit>({ _ -> run {} })
val showSelectItemDialog = mutableStateOf(false)
@Composable @Composable
fun Button( fun Button(
onClick: () -> Unit, onClick: () -> Unit,
@ -424,7 +428,7 @@ object CustomElements {
.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 0.dp), .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 0.dp),
shape = RoundedCornerShape(16.dp), shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors( colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainer containerColor = MaterialTheme.colorScheme.surfaceVariant
) )
) { ) {
Column(modifier = Modifier.padding(16.dp)) { Column(modifier = Modifier.padding(16.dp)) {
@ -449,8 +453,8 @@ object CustomElements {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text( Text(
text = item, text = stringResource(R.string.bullet_item, item),
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.primary,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Start textAlign = TextAlign.Start
) )

View File

@ -6,7 +6,6 @@ import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity import android.app.Activity
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.app.KeyguardManager import android.app.KeyguardManager
import android.app.role.RoleManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
@ -180,9 +179,9 @@ private val showPasswordsDialog = mutableStateOf(false)
private var passwordAccounts = mutableListOf<String>() private var passwordAccounts = mutableListOf<String>()
private var password = mutableStateOf("") private var password = mutableStateOf("")
private val selectItems = mutableStateOf(listOf<String>()) private val selectItems = CustomElements.selectItems
private val selectItemAction = mutableStateOf<(Int) -> Unit>({ _ -> run {} }) private val selectItemAction = CustomElements.selectItemAction
private val showSelectItemDialog = mutableStateOf(false) private val showSelectItemDialog = CustomElements.showSelectItemDialog
fun NavGraphBuilder.mainScreenRoute( fun NavGraphBuilder.mainScreenRoute(
navController: NavController, navController: NavController,