From e7823ffab1d98f315dd0874d1624bc835438104c Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Fri, 11 Apr 2025 14:49:55 +0300 Subject: [PATCH] Created AlertDialog composable and used it in calls activity --- .../com/tutpro/baresip/CallsActivity.kt | 267 ++++++++---------- .../com/tutpro/baresip/CustomElements.kt | 136 ++++++++- 2 files changed, 244 insertions(+), 159 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt index 70023761..5b599ca1 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt @@ -2,11 +2,9 @@ package com.tutpro.baresip import android.annotation.SuppressLint import android.content.Context -import android.content.DialogInterface import android.content.Intent import android.graphics.BitmapFactory import android.os.Bundle -import android.os.SystemClock import androidx.activity.ComponentActivity import androidx.activity.OnBackPressedCallback import androidx.activity.compose.setContent @@ -61,7 +59,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage -import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.tutpro.baresip.CustomElements.AlertDialog import com.tutpro.baresip.CustomElements.ImageAvatar import com.tutpro.baresip.CustomElements.TextAvatar import com.tutpro.baresip.CustomElements.verticalScrollbar @@ -71,7 +69,6 @@ class CallsActivity : ComponentActivity() { private lateinit var account: Account private var aor = "" - private var lastClick: Long = 0 private val onBackPressedCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { @@ -136,6 +133,18 @@ class CallsActivity : ComponentActivity() { val disable = String.format(getString(R.string.disable_history)) val enable = String.format(getString(R.string.enable_history)) + val openDialog = remember { mutableStateOf(false) } + val positiveAction = remember { mutableStateOf({}) } + + AlertDialog( + openDialog = openDialog, + title = getString(R.string.confirmation), + message = String.format(getString(R.string.delete_history_alert), aor.substringAfter(":")), + positiveButtonText = getString(R.string.delete), + negativeButtonText = getString(R.string.cancel), + onPositiveClicked = positiveAction.value, + ) + TopAppBar( title = { Text( @@ -172,29 +181,14 @@ class CallsActivity : ComponentActivity() { onItemClick = { selectedItem -> expanded = false when (selectedItem) { - delete -> - with( - MaterialAlertDialogBuilder(this@CallsActivity, R.style.AlertDialogTheme) - ) { - setTitle(R.string.confirmation) - setMessage( - String.format( - getString(R.string.delete_history_alert), - aor.substringAfter(":") - ) - ) - setPositiveButton(delete) { dialog, _ -> - CallHistoryNew.clear(aor) - CallHistoryNew.save() - uaHistory.value = emptyList() - dialog.dismiss() - } - setNeutralButton(getText(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - } - show() + delete -> { + positiveAction.value = { + CallHistoryNew.clear(aor) + CallHistoryNew.save() + uaHistory.value = emptyList() } - + openDialog.value = true + } disable, enable -> { account.callHistory = !account.callHistory AccountsActivity.saveAccounts() @@ -242,6 +236,25 @@ class CallsActivity : ComponentActivity() { @OptIn(ExperimentalFoundationApi::class) @Composable fun Calls(ctx: Context, account: Account) { + + val openDialog = remember { mutableStateOf(false) } + val message = remember { mutableStateOf("") } + val positiveButtonText = remember { mutableStateOf("") } + val positiveAction = remember { mutableStateOf({}) } + val neutralButtonText = remember { mutableStateOf("") } + val neutralAction = remember { mutableStateOf({}) } + + AlertDialog( + openDialog = openDialog, + title = getString(R.string.confirmation), + message = message.value, + positiveButtonText = positiveButtonText.value, + onPositiveClicked = positiveAction.value, + neutralButtonText = neutralButtonText.value, + onNeutralClicked = neutralAction.value, + negativeButtonText = getString(R.string.cancel) + ) + val lazyListState = rememberLazyListState() LazyColumn( modifier = Modifier @@ -268,10 +281,76 @@ class CallsActivity : ComponentActivity() { verticalAlignment = Alignment.CenterVertically, modifier = Modifier.combinedClickable( onClick = { - callMessageClick(ctx, callRow) + val peerUri = callRow.peerUri + val peerName = Utils.friendlyUri(ctx, peerUri, account) + message.value = String.format(ctx.getString(R.string.contact_action_question), peerName) + positiveButtonText.value = ctx.getString(R.string.call) + positiveAction.value = { + BaresipService.activities.remove("calls,$aor") + MainActivity.activityAor = aor + returnResult() + val i = Intent(this@CallsActivity, MainActivity::class.java) + i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP + i.putExtra("action", "call") + i.putExtra("uap", UserAgent.ofAor(aor)!!.uap) + i.putExtra("peer", peerUri) + startActivity(i) + } + neutralButtonText.value = ctx.getString(R.string.send_message) + neutralAction.value = { + BaresipService.activities.remove("calls,$aor") + MainActivity.activityAor = aor + returnResult() + val i = Intent(this@CallsActivity, MainActivity::class.java) + i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP + i.putExtra("action", "message") + i.putExtra("uap", UserAgent.ofAor(aor)!!.uap) + i.putExtra("peer", peerUri) + startActivity(i) + } + openDialog.value = true }, onLongClick = { - callMessageLongClick(ctx, callRow) + val peerUri = callRow.peerUri + val peerName = Utils.friendlyUri(ctx, peerUri, account) + val callText: String = if (callRow.details.size > 1) + getString(R.string.calls_calls) + else + getString(R.string.calls_call) + val contactExists = Contact.nameExists(peerName, BaresipService.contacts, false) + if (contactExists) { + message.value = String.format( + getString(R.string.calls_delete_question), + peerName, callText + ) + positiveButtonText.value = getString(R.string.delete) + positiveAction.value = { + removeFromHistory(callRow) + CallHistoryNew.save() + } + neutralButtonText.value = "" + } + else { + message.value = String.format( + getString(R.string.calls_add_delete_question), + peerName, callText + ) + positiveButtonText.value = getString(R.string.add_contact) + positiveAction.value = { + val i = Intent(ctx, BaresipContactActivity::class.java) + val b = Bundle() + b.putBoolean("new", true) + b.putString("uri", callRow.peerUri) + i.putExtras(b) + ctx.startActivity(i) + } + neutralButtonText.value = getString(R.string.delete) + neutralAction.value = { + removeFromHistory(callRow) + CallHistoryNew.save() + } + } + openDialog.value = true } ) ) { @@ -291,7 +370,9 @@ class CallsActivity : ComponentActivity() { model = thumbNailUri, contentDescription = "Avatar", contentScale = ContentScale.Crop, - modifier = Modifier.size(36.dp).clip(CircleShape), + modifier = Modifier + .size(36.dp) + .clip(CircleShape), ) else TextAvatar(contact.name, contact.color) @@ -334,7 +415,9 @@ class CallsActivity : ComponentActivity() { LocalCustomColors.current.accent else LocalCustomColors.current.itemText, - modifier = Modifier.padding(end = 16.dp).width(64.dp) + modifier = Modifier + .padding(end = 16.dp) + .width(64.dp) .clickable(onClick = { val i = Intent(ctx, CallDetailsActivity::class.java) val b = Bundle() @@ -351,130 +434,6 @@ class CallsActivity : ComponentActivity() { } } - private fun callMessageClick(ctx: Context, callRow: CallRow) { - val peerUri = callRow.peerUri - val peerName = Utils.friendlyUri(ctx, peerUri, account) - val dialogClickListener = DialogInterface.OnClickListener { _, which -> - when (which) { - DialogInterface.BUTTON_POSITIVE, DialogInterface.BUTTON_NEGATIVE -> { - BaresipService.activities.remove("calls,$aor") - MainActivity.activityAor = aor - returnResult() - val i = Intent(this@CallsActivity, MainActivity::class.java) - i.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP - if (which == DialogInterface.BUTTON_NEGATIVE) - i.putExtra("action", "call") - else - i.putExtra("action", "message") - i.putExtra("uap", UserAgent.ofAor(aor)!!.uap) - i.putExtra("peer", peerUri) - startActivity(i) - } - - DialogInterface.BUTTON_NEUTRAL -> { - } - } - } - if (SystemClock.elapsedRealtime() - lastClick > 1000) { - lastClick = SystemClock.elapsedRealtime() - with( - MaterialAlertDialogBuilder(ctx, R.style.AlertDialogTheme) - ) { - setTitle(R.string.confirmation) - setMessage( - String.format(ctx.getString(R.string.contact_action_question), peerName) - ) - setNeutralButton( - ctx.getText(R.string.cancel), - dialogClickListener - ) - setNegativeButton( - ctx.getText(R.string.call), - dialogClickListener - ) - setPositiveButton( - ctx.getText(R.string.send_message), - dialogClickListener - ) - show() - } - } - } - - private fun callMessageLongClick(ctx: Context, callRow: CallRow) { - val peerUri = callRow.peerUri - val peerName = Utils.friendlyUri(ctx, peerUri, account) - val dialogClickListener = - DialogInterface.OnClickListener { _, which -> - when (which) { - DialogInterface.BUTTON_NEGATIVE -> { - val i = Intent(ctx, BaresipContactActivity::class.java) - val b = Bundle() - b.putBoolean("new", true) - b.putString("uri", peerUri) - i.putExtras(b) - ctx.startActivity(i) - } - DialogInterface.BUTTON_POSITIVE -> { - removeFromHistory(callRow) - CallHistoryNew.save() - } - DialogInterface.BUTTON_NEUTRAL -> { - } - } - } - val callText: String = if (callRow.details.size > 1) - getString(R.string.calls_calls) - else - getString(R.string.calls_call) - val builder = MaterialAlertDialogBuilder( - this@CallsActivity, - R.style.AlertDialogTheme - ) - if (!Contact.nameExists(peerName, BaresipService.contacts, false)) - with(builder) { - setTitle(R.string.confirmation) - setMessage( - String.format( - getString(R.string.calls_add_delete_question), - peerName, callText - ) - ) - setNeutralButton( - getString(R.string.cancel), - dialogClickListener - ) - setPositiveButton( - getString(R.string.delete), - dialogClickListener - ) - setNegativeButton( - getString(R.string.add_contact), - dialogClickListener - ) - show() - } - else - with(builder) { - setTitle(R.string.confirmation) - setMessage( - String.format( - getString(R.string.calls_delete_question), - peerName, callText - ) - ) - setNeutralButton( - getString(R.string.cancel), - dialogClickListener - ) - setPositiveButton( - getString(R.string.delete), - dialogClickListener - ) - show() - } - } - private fun goBack() { BaresipService.activities.remove("calls,$aor") returnResult() diff --git a/app/src/main/kotlin/com/tutpro/baresip/CustomElements.kt b/app/src/main/kotlin/com/tutpro/baresip/CustomElements.kt index 0d5d1dee..fb88c1cf 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/CustomElements.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CustomElements.kt @@ -19,16 +19,19 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.AlertDialogDefaults import androidx.compose.material3.BasicAlertDialog import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card import androidx.compose.material3.Checkbox import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.DropdownMenu @@ -120,11 +123,13 @@ object CustomElements { Surface( shape = shape, color = color, - modifier = modifier.pointerInput(Unit) { - detectTapGestures( - onTap = { onClick() }, - onLongPress = { onLongClick() }, - ) } + modifier = modifier + .pointerInput(Unit) { + detectTapGestures( + onTap = { onClick() }, + onLongPress = { onLongClick() }, + ) + } .then(modifier), ) { Row( @@ -310,6 +315,126 @@ object CustomElements { } } + @OptIn(ExperimentalMaterial3Api::class) + @Composable + fun AlertDialog( + openDialog: MutableState, + title: String, + message: String, + positiveButtonText: String, + onPositiveClicked: () -> Unit, + negativeButtonText: String = "", + onNegativeClicked: () -> Unit = {}, + neutralButtonText: String = "", + onNeutralClicked: () -> Unit = {} + ) { + if (openDialog.value) { + BasicAlertDialog( + onDismissRequest = { + openDialog.value = false + }, + content = { + Card( + modifier = Modifier.fillMaxWidth() + .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 0.dp), + shape = RoundedCornerShape(16.dp), + ) { + Column(modifier = Modifier.padding(16.dp)) { + androidx.compose.material3.Text( + text = title, + fontSize = 20.sp, + color = LocalCustomColors.current.alert, + ) + Spacer(modifier = Modifier.height(16.dp)) + androidx.compose.material3.Text( + text = message, + fontSize = 16.sp, + color = LocalCustomColors.current.itemText, + ) + Spacer(modifier = Modifier.height(16.dp)) + if (negativeButtonText.isNotEmpty() && neutralButtonText.isNotEmpty()) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.End + ) { + TextButton(onClick = { + onPositiveClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = positiveButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.alert, + ) + } + TextButton(onClick = { + onNeutralClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = neutralButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.alert + ) + } + TextButton(onClick = { + onNegativeClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = negativeButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.gray + ) + } + } + } + else { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + if (negativeButtonText.isNotEmpty()) + TextButton(onClick = { + onNegativeClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = negativeButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.gray + ) + } + if (neutralButtonText.isNotEmpty()) + TextButton(onClick = { + onNeutralClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = neutralButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.alert + ) + } + TextButton(onClick = { + onPositiveClicked() + openDialog.value = false + }) { + androidx.compose.material3.Text( + text = positiveButtonText.uppercase(), + fontSize = 14.sp, + color = LocalCustomColors.current.alert, + ) + } + } + } + } + } + } + ) + } + } + @OptIn(ExperimentalMaterial3Api::class) @Composable fun PasswordDialog( @@ -448,4 +573,5 @@ object CustomElements { } } } + }