Composed alerts in accounts and audio activities

This commit is contained in:
Juha Heinanen
2025-04-15 08:32:51 +03:00
parent 3543945c92
commit c1b7e4b01e
3 changed files with 130 additions and 88 deletions
@@ -77,6 +77,10 @@ class AccountsActivity : ComponentActivity() {
private var lastClick: Long = 0 private var lastClick: Long = 0
private val scope = CoroutineScope(Job() + Dispatchers.Main) private val scope = CoroutineScope(Job() + Dispatchers.Main)
private val alertTitle = mutableStateOf("")
private val alertMessage = mutableStateOf("")
private val showAlert = mutableStateOf(false)
private val onBackPressedCallback = object : OnBackPressedCallback(true) { private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
goBack() goBack()
@@ -167,6 +171,15 @@ class AccountsActivity : ComponentActivity() {
negativeButtonText = getString(R.string.cancel), negativeButtonText = getString(R.string.cancel),
) )
if (showAlert.value) {
AlertDialog(
showDialog = showAlert,
title = alertTitle.value,
message = alertMessage.value,
positiveButtonText = stringResource(R.string.ok),
)
}
if (showAccounts.value && BaresipService.uas.value.isNotEmpty()) { if (showAccounts.value && BaresipService.uas.value.isNotEmpty()) {
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
Column( Column(
@@ -249,15 +262,17 @@ class AccountsActivity : ComponentActivity() {
) { ) {
OutlinedTextField( OutlinedTextField(
value = newAor, value = newAor,
placeholder = { CustomElements.Text(text = getString(R.string.new_account)) }, placeholder = { Text(text = getString(R.string.new_account)) },
onValueChange = { newAor = it }, onValueChange = { newAor = it },
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.padding(end = 8.dp) .padding(end = 8.dp)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.clickable { .clickable {
Utils.alertView(ctx, getString(R.string.new_account), alertTitle.value = getString(R.string.new_account)
getString(R.string.accounts_help)) }, alertMessage.value = getString(R.string.accounts_help)
showAlert.value = true
},
singleLine = false, singleLine = false,
trailingIcon = { trailingIcon = {
if (newAor.isNotEmpty()) { if (newAor.isNotEmpty()) {
@@ -311,22 +326,16 @@ class AccountsActivity : ComponentActivity() {
"sip:$newAor" "sip:$newAor"
if (!Utils.checkAor(aor)) { if (!Utils.checkAor(aor)) {
Log.d(TAG, "Invalid Address of Record $aor") alertTitle.value = getString(R.string.notice)
Utils.alertView( alertMessage.value = String.format(getString(R.string.invalid_aor), aor.split(":")[1])
this, getString(R.string.notice), showAlert.value = true
String.format(getString(R.string.invalid_aor),
aor.split(":")[1])
)
return null return null
} }
if (Account.ofAor(aor) != null) { if (Account.ofAor(aor) != null) {
Log.d(TAG, "Account $aor already exists") alertTitle.value = getString(R.string.notice)
Utils.alertView( alertMessage.value = String.format(getString(R.string.account_exists), aor.split(":")[1])
this, getString(R.string.notice), showAlert.value = true
String.format(getString(R.string.account_exists),
aor.split(":")[1])
)
return null return null
} }
@@ -334,11 +343,9 @@ class AccountsActivity : ComponentActivity() {
"<$aor>;stunserver=\"stun:stun.l.google.com:19302\";regq=0.5;pubint=0;regint=0;mwi=no" "<$aor>;stunserver=\"stun:stun.l.google.com:19302\";regq=0.5;pubint=0;regint=0;mwi=no"
) )
if (ua == null) { if (ua == null) {
Log.e(TAG, "Failed to allocate UA for $aor") alertTitle.value = getString(R.string.notice)
Utils.alertView( alertMessage.value = getString(R.string.account_allocation_failure)
this, getString(R.string.notice), showAlert.value = true
getString(R.string.account_allocation_failure)
)
return null return null
} }
@@ -50,7 +50,9 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.tutpro.baresip.CustomElements.AlertDialog
import com.tutpro.baresip.CustomElements.Checkbox import com.tutpro.baresip.CustomElements.Checkbox
import com.tutpro.baresip.CustomElements.LabelText
import com.tutpro.baresip.CustomElements.verticalScrollbar import com.tutpro.baresip.CustomElements.verticalScrollbar
class AudioActivity : ComponentActivity() { class AudioActivity : ComponentActivity() {
@@ -72,6 +74,10 @@ class AudioActivity : ComponentActivity() {
private var newToneCountry = BaresipService.toneCountry private var newToneCountry = BaresipService.toneCountry
private var arrowTint = Color.Unspecified private var arrowTint = Color.Unspecified
private val alertTitle = mutableStateOf("")
private val alertMessage = mutableStateOf("")
private val showAlert = mutableStateOf(false)
private val onBackPressedCallback = object : OnBackPressedCallback(true) { private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
goBack() goBack()
@@ -115,7 +121,7 @@ class AudioActivity : ComponentActivity() {
containerColor = LocalCustomColors.current.background, containerColor = LocalCustomColors.current.background,
topBar = { TopAppBar(title, navigateBack) }, topBar = { TopAppBar(title, navigateBack) },
content = { contentPadding -> content = { contentPadding ->
AudioContent(ctx, contentPadding) AudioContent(contentPadding)
} }
) )
} }
@@ -158,12 +164,23 @@ class AudioActivity : ComponentActivity() {
} }
@Composable @Composable
fun AudioContent(ctx: Context, contentPadding: PaddingValues) { fun AudioContent(contentPadding: PaddingValues) {
arrowTint = if (BaresipService.darkTheme.value) arrowTint = if (BaresipService.darkTheme.value)
LocalCustomColors.current.grayLight LocalCustomColors.current.grayLight
else else
LocalCustomColors.current.black LocalCustomColors.current.black
if (showAlert.value) {
AlertDialog(
showDialog = showAlert,
title = alertTitle.value,
message = alertMessage.value,
positiveButtonText = stringResource(R.string.ok),
)
}
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
Column( Column(
modifier = Modifier modifier = Modifier
.imePadding() .imePadding()
@@ -174,19 +191,19 @@ class AudioActivity : ComponentActivity() {
.verticalScroll(state = scrollState), .verticalScroll(state = scrollState),
verticalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp),
) { ) {
CallVolume(ctx) CallVolume()
MicGain(ctx) MicGain()
SpeakerPhone(ctx) SpeakerPhone()
AudioModules(ctx) AudioModules()
OpusBitRate(ctx) OpusBitRate()
OpusPacketLoss(ctx) OpusPacketLoss()
AudioDelay(ctx) AudioDelay()
ToneCountry(ctx) ToneCountry()
} }
} }
@Composable @Composable
private fun CallVolume(ctx: Context) { private fun CallVolume() {
Row( Row(
Modifier.fillMaxWidth(), Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -196,10 +213,9 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.clickable { .clickable {
Utils.alertView( alertTitle.value = getString(R.string.default_call_volume)
ctx, getString(R.string.default_call_volume), alertMessage.value = getString(R.string.default_call_volume_help)
getString(R.string.default_call_volume_help) showAlert.value = true
)
}, },
color = LocalCustomColors.current.itemText, color = LocalCustomColors.current.itemText,
fontSize = 18.sp) fontSize = 18.sp)
@@ -250,7 +266,7 @@ class AudioActivity : ComponentActivity() {
} }
@Composable @Composable
private fun MicGain(ctx: Context) { private fun MicGain() {
if (!BaresipService.agcAvailable) if (!BaresipService.agcAvailable)
Row( Row(
Modifier.fillMaxWidth().padding(end = 10.dp), Modifier.fillMaxWidth().padding(end = 10.dp),
@@ -269,22 +285,21 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
Utils.alertView( alertTitle.value = getString(R.string.microphone_gain)
ctx, getString(R.string.microphone_gain), alertMessage.value = getString(R.string.microphone_gain_help)
getString(R.string.microphone_gain_help) showAlert.value = true
)
}, },
textStyle = androidx.compose.ui.text.TextStyle( textStyle = androidx.compose.ui.text.TextStyle(
fontSize = 18.sp, color = LocalCustomColors.current.itemText fontSize = 18.sp, color = LocalCustomColors.current.itemText
), ),
label = { Text(stringResource(R.string.microphone_gain)) }, label = { LabelText(stringResource(R.string.microphone_gain)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text) keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
) )
} }
} }
@Composable @Composable
private fun SpeakerPhone(ctx: Context) { private fun SpeakerPhone() {
Row( Row(
Modifier.fillMaxWidth(), Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -294,10 +309,9 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.clickable { .clickable {
Utils.alertView( alertTitle.value = getString(R.string.speaker_phone)
ctx, getString(R.string.speaker_phone), alertMessage.value = getString(R.string.speaker_phone_help)
getString(R.string.speaker_phone_help) showAlert.value = true
)
}, },
color = LocalCustomColors.current.itemText, color = LocalCustomColors.current.itemText,
fontSize = 18.sp) fontSize = 18.sp)
@@ -314,7 +328,7 @@ class AudioActivity : ComponentActivity() {
} }
@Composable @Composable
private fun AudioModules(ctx: Context) { private fun AudioModules() {
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.Start, horizontalAlignment = Alignment.Start,
@@ -323,8 +337,9 @@ class AudioActivity : ComponentActivity() {
color = LocalCustomColors.current.itemText, color = LocalCustomColors.current.itemText,
fontSize = 18.sp, fontSize = 18.sp,
modifier = Modifier.clickable { modifier = Modifier.clickable {
Utils.alertView(ctx, getString(R.string.audio_modules_title), alertTitle.value = getString(R.string.audio_modules_title)
getString(R.string.audio_modules_help)) alertMessage.value = getString(R.string.audio_modules_help)
showAlert.value = true
}) })
for (module in audioModules) { for (module in audioModules) {
Row(horizontalArrangement = Arrangement.Start, Row(horizontalArrangement = Arrangement.Start,
@@ -347,7 +362,7 @@ class AudioActivity : ComponentActivity() {
} }
@Composable @Composable
private fun OpusBitRate(ctx: Context) { private fun OpusBitRate() {
Row( Row(
Modifier.fillMaxWidth().padding(end = 10.dp), Modifier.fillMaxWidth().padding(end = 10.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -365,20 +380,20 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
Utils.alertView(ctx, getString(R.string.opus_bit_rate), alertTitle.value = getString(R.string.opus_bit_rate)
getString(R.string.opus_bit_rate_help) alertMessage.value = getString(R.string.opus_bit_rate_help)
) showAlert.value = true
}, },
textStyle = androidx.compose.ui.text.TextStyle( textStyle = androidx.compose.ui.text.TextStyle(
fontSize = 18.sp, color = LocalCustomColors.current.itemText), fontSize = 18.sp, color = LocalCustomColors.current.itemText),
label = { Text(stringResource(R.string.opus_bit_rate)) }, label = { LabelText(stringResource(R.string.opus_bit_rate)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text) keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
) )
} }
} }
@Composable @Composable
private fun OpusPacketLoss(ctx: Context) { private fun OpusPacketLoss() {
Row( Row(
Modifier.fillMaxWidth().padding(end = 10.dp, top = 8.dp), Modifier.fillMaxWidth().padding(end = 10.dp, top = 8.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -396,20 +411,20 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
Utils.alertView(ctx, getString(R.string.opus_packet_loss), alertTitle.value = getString(R.string.opus_packet_loss)
getString(R.string.opus_packet_loss_help) alertMessage.value = getString(R.string.opus_packet_loss_help)
) showAlert.value = true
}, },
textStyle = androidx.compose.ui.text.TextStyle( textStyle = androidx.compose.ui.text.TextStyle(
fontSize = 18.sp, color = LocalCustomColors.current.itemText), fontSize = 18.sp, color = LocalCustomColors.current.itemText),
label = { Text(stringResource(R.string.opus_packet_loss)) }, label = { LabelText(stringResource(R.string.opus_packet_loss)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text) keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
) )
} }
} }
@Composable @Composable
private fun AudioDelay(ctx: Context) { private fun AudioDelay() {
Row( Row(
Modifier.fillMaxWidth().padding(end = 10.dp, top = 8.dp), Modifier.fillMaxWidth().padding(end = 10.dp, top = 8.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -419,7 +434,7 @@ class AudioActivity : ComponentActivity() {
newAudioDelay = audioDelay newAudioDelay = audioDelay
OutlinedTextField( OutlinedTextField(
value = audioDelay, value = audioDelay,
placeholder = { Text(stringResource(R.string.audio_delay)) }, placeholder = { Text(getString(R.string.audio_delay)) },
onValueChange = { onValueChange = {
audioDelay = it audioDelay = it
newAudioDelay = audioDelay newAudioDelay = audioDelay
@@ -427,20 +442,20 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { .clickable {
Utils.alertView(ctx, getString(R.string.audio_delay), alertTitle.value = getString(R.string.audio_delay)
getString(R.string.audio_delay_help) alertMessage.value = getString(R.string.audio_delay_help)
) showAlert.value = true
}, },
textStyle = androidx.compose.ui.text.TextStyle( textStyle = androidx.compose.ui.text.TextStyle(
fontSize = 18.sp, color = LocalCustomColors.current.itemText), fontSize = 18.sp, color = LocalCustomColors.current.itemText),
label = { Text(stringResource(R.string.audio_delay)) }, label = { LabelText(getString(R.string.audio_delay)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text) keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
) )
} }
} }
@Composable @Composable
private fun ToneCountry(ctx: Context) { private fun ToneCountry() {
Row( Row(
Modifier.fillMaxWidth(), Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -450,10 +465,9 @@ class AudioActivity : ComponentActivity() {
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.clickable { .clickable {
Utils.alertView( alertTitle.value = getString(R.string.tone_country)
ctx, getString(R.string.tone_country), alertMessage.value = getString(R.string.tone_country_help)
getString(R.string.tone_country_help) showAlert.value = true
)
}, },
color = LocalCustomColors.current.itemText, color = LocalCustomColors.current.itemText,
fontSize = 18.sp) fontSize = 18.sp)
@@ -520,10 +534,9 @@ class AudioActivity : ComponentActivity() {
gain = "$gain.0" gain = "$gain.0"
if (gain != oldMicGain) { if (gain != oldMicGain) {
if (!checkMicGain(gain)) { if (!checkMicGain(gain)) {
Utils.alertView( alertTitle.value = getString(R.string.notice)
this, getString(R.string.notice), alertMessage.value = "${getString(R.string.invalid_microphone_gain)}: $gain."
"${getString(R.string.invalid_microphone_gain)}: $gain." showAlert.value = true
)
return return
} }
if (gain == "1.0") { if (gain == "1.0") {
@@ -533,10 +546,9 @@ class AudioActivity : ComponentActivity() {
} else { } else {
if (oldMicGain == "1.0") { if (oldMicGain == "1.0") {
if (Api.module_load("augain") != 0) { if (Api.module_load("augain") != 0) {
Utils.alertView( alertTitle.value = getString(R.string.error)
this, getString(R.string.error), alertMessage.value = getString(R.string.failed_to_load_module) + ": augain.so"
getString(R.string.failed_to_load_module) showAlert.value = true
)
return return
} }
Config.addVariable("module", "augain.so") Config.addVariable("module", "augain.so")
@@ -560,10 +572,9 @@ class AudioActivity : ComponentActivity() {
if (newAudioModules[module]!!) { if (newAudioModules[module]!!) {
if (!modules.contains("${module}.so")) { if (!modules.contains("${module}.so")) {
if (Api.module_load("${module}.so") != 0) { if (Api.module_load("${module}.so") != 0) {
Utils.alertView( alertTitle.value = getString(R.string.error)
this, getString(R.string.error), alertMessage.value = "${getString(R.string.failed_to_load_module)}: ${module}.so"
"${getString(R.string.failed_to_load_module)}: ${module}.so" showAlert.value = true
)
return return
} }
Config.addVariable("module", "${module}.so") Config.addVariable("module", "${module}.so")
@@ -582,8 +593,9 @@ class AudioActivity : ComponentActivity() {
if (newOpusBitrate != oldOpusBitrate) { if (newOpusBitrate != oldOpusBitrate) {
if (!checkOpusBitRate(newOpusBitrate)) { if (!checkOpusBitRate(newOpusBitrate)) {
Utils.alertView(this, getString(R.string.notice), alertTitle.value = getString(R.string.notice)
"${getString(R.string.invalid_opus_bitrate)}: $newOpusBitrate.") alertMessage.value = "${getString(R.string.invalid_opus_bitrate)}: $newOpusBitrate."
showAlert.value = true
return return
} }
Config.replaceVariable("opus_bitrate", newOpusBitrate) Config.replaceVariable("opus_bitrate", newOpusBitrate)
@@ -593,8 +605,9 @@ class AudioActivity : ComponentActivity() {
if (newOpusPacketLoss != oldOpusPacketLoss) { if (newOpusPacketLoss != oldOpusPacketLoss) {
if (!checkOpusPacketLoss(newOpusPacketLoss)) { if (!checkOpusPacketLoss(newOpusPacketLoss)) {
Utils.alertView(this, getString(R.string.notice), alertTitle.value = getString(R.string.notice)
"${getString(R.string.invalid_opus_packet_loss)}: $newOpusPacketLoss") alertMessage.value = "${getString(R.string.invalid_opus_packet_loss)}: $newOpusPacketLoss"
showAlert.value = true
return return
} }
Config.replaceVariable("opus_packet_loss", newOpusPacketLoss) Config.replaceVariable("opus_packet_loss", newOpusPacketLoss)
@@ -605,8 +618,9 @@ class AudioActivity : ComponentActivity() {
val audioDelay = newAudioDelay.trim() val audioDelay = newAudioDelay.trim()
if (audioDelay != BaresipService.audioDelay.toString()) { if (audioDelay != BaresipService.audioDelay.toString()) {
if (!checkAudioDelay(audioDelay)) { if (!checkAudioDelay(audioDelay)) {
Utils.alertView(this, getString(R.string.notice), alertTitle.value = getString(R.string.notice)
String.format(getString(R.string.invalid_audio_delay), audioDelay)) alertMessage.value = String.format(getString(R.string.invalid_audio_delay), audioDelay)
showAlert.value = true
return return
} }
Config.replaceVariable("audio_delay", audioDelay) Config.replaceVariable("audio_delay", audioDelay)
@@ -115,6 +115,27 @@ object CustomElements {
) )
} }
@Composable
fun LabelText(
text: String,
modifier: Modifier = Modifier,
color: Color = LocalCustomColors.current.itemText,
fontSize: TextUnit = 16.sp,
fontWeight: FontWeight = FontWeight.Normal,
textAlign: TextAlign? = null,
maxLines: Int = 1,
) {
androidx.compose.material3.Text(
text = text,
modifier = modifier,
color = color,
fontSize = fontSize,
fontWeight = fontWeight,
textAlign = textAlign,
maxLines = maxLines
)
}
@Composable @Composable
fun Button( fun Button(
onClick: () -> Unit, onClick: () -> Unit,