From 26f3ab6ac06527fcadcd533ae783fab15f55545b Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 6 Jul 2025 15:02:33 +0300 Subject: [PATCH 1/3] Added Colorblind setting and registration status icons --- .../com/tutpro/baresip/BaresipService.kt | 9 ++-- .../main/kotlin/com/tutpro/baresip/Config.kt | 7 +++ .../com/tutpro/baresip/SettingsScreen.kt | 44 +++++++++++++++++++ .../kotlin/com/tutpro/baresip/UserAgent.kt | 2 +- .../main/kotlin/com/tutpro/baresip/Utils.kt | 21 +++++++++ app/src/main/res/drawable/circle_green.xml | 4 +- .../main/res/drawable/circle_green_blind.xml | 10 +++++ app/src/main/res/drawable/circle_red.xml | 4 +- .../main/res/drawable/circle_red_blind.xml | 10 +++++ app/src/main/res/drawable/circle_white.xml | 4 +- app/src/main/res/drawable/circle_yellow.xml | 4 +- .../main/res/drawable/circle_yellow_blind.xml | 10 +++++ app/src/main/res/values-fi/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 14 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 app/src/main/res/drawable/circle_green_blind.xml create mode 100644 app/src/main/res/drawable/circle_red_blind.xml create mode 100644 app/src/main/res/drawable/circle_yellow_blind.xml diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 36f768a9..1469ff29 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -676,7 +676,7 @@ class BaresipService: Service() { ua.status = if (ua.account.regint == 0) R.drawable.circle_white else - R.drawable.circle_yellow + Utils.circleYellow() ua.add() val acc = ua.account @@ -773,7 +773,7 @@ class BaresipService: Service() { when (ev[0]) { "registering", "unregistering" -> { updateStatusNotification() - ua.uaUpdateStatus(R.drawable.circle_yellow) + ua.uaUpdateStatus(Utils.circleYellow()) if (isMainVisible) registrationUpdate.postValue(System.currentTimeMillis()) return @@ -783,7 +783,7 @@ class BaresipService: Service() { if (Api.account_regint(ua.account.accp) == 0) R.drawable.circle_white else - R.drawable.circle_green) + Utils.circleGreen()) updateStatusNotification() if (isMainVisible) registrationUpdate.postValue(System.currentTimeMillis()) @@ -793,7 +793,7 @@ class BaresipService: Service() { ua.uaUpdateStatus(if (Api.account_regint(ua.account.accp) == 0) R.drawable.circle_white else - R.drawable.circle_red) + Utils.circleRed()) updateStatusNotification() if (isMainVisible) registrationUpdate.postValue(System.currentTimeMillis()) @@ -1725,6 +1725,7 @@ class BaresipService: Service() { var contactsMode = "baresip" var addressFamily = "" var dnsServers = listOf() + var colorblind = false // of those accounts that have auth username without auth password val aorPasswords = mutableMapOf() var audioFocusRequest: AudioFocusRequestCompat? = null diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index 1874d8fa..8c9f3669 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -119,6 +119,13 @@ object Config { AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } + val colorblind = previousVariable("colorblind") + config = if (colorblind != "") + "${config}colorblind $colorblind\n" + else + "${config}colorblind no\n" + BaresipService.colorblind = colorblind == "yes" + var contactsMode = previousVariable("contacts_mode").lowercase() if (contactsMode != "") { if (contactsMode != "baresip" && diff --git a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt index 342f9bc8..75dd5edd 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt @@ -246,6 +246,8 @@ private var newBatteryOptimizations = false private var newDarkTheme = false +private var newColorblind = false + private var newDefaultDialer = false private var newDebug = false @@ -312,6 +314,7 @@ private fun SettingsContent( Ringtone(ctx) BatteryOptimizations() DarkTheme() + ColorBlind() if (VERSION.SDK_INT >= 29) DefaultDialer() Debug() @@ -1085,6 +1088,37 @@ private fun DarkTheme() { ) } } +@Composable +private fun ColorBlind() { + Row( + Modifier + .fillMaxWidth() + .padding(end = 10.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + val ctx = LocalContext.current + Text(text = stringResource(R.string.colorblind), + modifier = Modifier + .weight(1f) + .clickable { + alertTitle.value = ctx.getString(R.string.colorblind) + alertMessage.value = ctx.getString(R.string.colorblind_help) + showAlert.value = true + }, + color = LocalCustomColors.current.itemText, + fontSize = 18.sp) + var colorblind by remember { mutableStateOf(Config.variable("colorblind") == "yes") } + newColorblind = colorblind + Switch( + checked = colorblind, + onCheckedChange = { + colorblind = it + newColorblind = colorblind + } + ) + } +} @RequiresApi(29) @Composable @@ -1369,6 +1403,16 @@ private fun checkOnClick(ctx: Context) { save = true } + if ((Config.variable("colorblind") == "yes") != newColorblind) { + Config.replaceVariable( + "colorblind", + if (newColorblind) "yes" else "no" + ) + BaresipService.colorblind = newColorblind + save = true + restart = true + } + if ((Config.variable("log_level") == "0") != newDebug) { val logLevelString = if (newDebug) "0" else "2" Config.replaceVariable("log_level", logLevelString) diff --git a/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt b/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt index abc7df4b..f998f81b 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt @@ -46,7 +46,7 @@ class UserAgent(val uap: Long) { } fun reRegister() { - this.status = R.drawable.circle_yellow + this.status = Utils.circleYellow() if (this.account.regint == 0) Api.ua_unregister(this.uap) else diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index ef922d05..a0150a35 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -996,6 +996,27 @@ object Utils { } + fun circleGreen(): Int { + return if (BaresipService.colorblind) + R.drawable.circle_green_blind + else + R.drawable.circle_green + } + + fun circleYellow(): Int { + return if (BaresipService.colorblind) + R.drawable.circle_yellow_blind + else + R.drawable.circle_yellow + } + + fun circleRed(): Int { + return if (BaresipService.colorblind) + R.drawable.circle_red_blind + else + R.drawable.circle_red + } + /*fun listFilesInDirectory(directoryPath: String): List { val directory = File(directoryPath) if (!directory.exists()) { diff --git a/app/src/main/res/drawable/circle_green.xml b/app/src/main/res/drawable/circle_green.xml index d47778d7..1b32aabb 100644 --- a/app/src/main/res/drawable/circle_green.xml +++ b/app/src/main/res/drawable/circle_green.xml @@ -1,6 +1,6 @@ - +android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/drawable/circle_green_blind.xml b/app/src/main/res/drawable/circle_green_blind.xml new file mode 100644 index 00000000..0ec8ac99 --- /dev/null +++ b/app/src/main/res/drawable/circle_green_blind.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/circle_red.xml b/app/src/main/res/drawable/circle_red.xml index b060591a..39bbd7c5 100644 --- a/app/src/main/res/drawable/circle_red.xml +++ b/app/src/main/res/drawable/circle_red.xml @@ -1,6 +1,6 @@ - + android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/drawable/circle_red_blind.xml b/app/src/main/res/drawable/circle_red_blind.xml new file mode 100644 index 00000000..6c10f465 --- /dev/null +++ b/app/src/main/res/drawable/circle_red_blind.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/circle_white.xml b/app/src/main/res/drawable/circle_white.xml index 02e90016..0ec69239 100644 --- a/app/src/main/res/drawable/circle_white.xml +++ b/app/src/main/res/drawable/circle_white.xml @@ -1,6 +1,6 @@ - + android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/drawable/circle_yellow.xml b/app/src/main/res/drawable/circle_yellow.xml index 2a83258a..8833e882 100644 --- a/app/src/main/res/drawable/circle_yellow.xml +++ b/app/src/main/res/drawable/circle_yellow.xml @@ -1,6 +1,6 @@ - + android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/drawable/circle_yellow_blind.xml b/app/src/main/res/drawable/circle_yellow_blind.xml new file mode 100644 index 00000000..fbd635f4 --- /dev/null +++ b/app/src/main/res/drawable/circle_yellow_blind.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index bbb8b426..0b7103b9 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -416,6 +416,8 @@ Soitto-, odotus- ja varattuäänien maa Tumma teema Käytä aina tummaa näyttöteemaa + Värisokea + Käytä värisokealle ystävällisiä rekisteröintitilaikoineita Videon kehyskoko Lähetettävän videon kehyskoko (leveys x korkeus) Videokehysten lähetystaajuus diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a7413857..c79060ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -387,6 +387,8 @@ Country of call ringing, waiting, and callee busy tones Dark Theme Force dark display theme + Colorblind + Use colorblind friendly registration status icons Video Frame Size Size of transmitted video frames (width x height) Video Frames Per Second From 926d2b672cc26f73a7e9fc795584d16cbb598b91 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 6 Jul 2025 17:32:16 +0300 Subject: [PATCH 2/3] Avoid need to restart after Colorblind setting change --- .../com/tutpro/baresip/SettingsScreen.kt | 5 ++++- .../kotlin/com/tutpro/baresip/UserAgent.kt | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt index 75dd5edd..e180432d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/SettingsScreen.kt @@ -1409,8 +1409,11 @@ private fun checkOnClick(ctx: Context) { if (newColorblind) "yes" else "no" ) BaresipService.colorblind = newColorblind + UserAgent.updateColorblindStatus() + val baresipService = Intent(ctx, BaresipService::class.java) + baresipService.action = "Update Notification" + ctx.startService(baresipService) save = true - restart = true } if ((Config.variable("log_level") == "0") != newDebug) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt b/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt index f998f81b..4fa82c66 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/UserAgent.kt @@ -105,6 +105,28 @@ class UserAgent(val uap: Long) { } } + fun updateColorblindStatus() { + val updatedUas = uas.value.toMutableList() + for (ua in updatedUas) + ua.status = + if (BaresipService.colorblind) + when (ua.status) { + R.drawable.circle_green -> R.drawable.circle_green_blind + R.drawable.circle_yellow -> R.drawable.circle_yellow_blind + R.drawable.circle_red -> R.drawable.circle_red_blind + else -> R.drawable.circle_white + } + else + when (ua.status) { + R.drawable.circle_green_blind -> R.drawable.circle_green + R.drawable.circle_yellow_blind -> R.drawable.circle_yellow + R.drawable.circle_red_blind -> R.drawable.circle_red + else -> R.drawable.circle_white + } + uas.value = updatedUas.toList() + uasStatus.value = statusMap() + } + fun statusMap(): Map { val result = emptyMap().toMutableMap() for (ua in uas.value) From b4ca26dba9b6660cfb89dd2f4d33d0e7b76c01c2 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Mon, 7 Jul 2025 11:35:27 +0300 Subject: [PATCH 3/3] Added shouldStartRinging check to incoming call --- .../com/tutpro/baresip/BaresipService.kt | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 1469ff29..38ef8b79 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -873,19 +873,19 @@ class BaresipService: Service() { Call(callp, ua, peerUri, "in", "incoming").add() if (speakerPhone && !Utils.isSpeakerPhoneOn(am)) Utils.toggleSpeakerPhone(ContextCompat.getMainExecutor(this), am) - if (ua.account.answerMode == Api.ANSWERMODE_MANUAL) { - Log.d(TAG, "CurrentInterruptionFilter ${nm.currentInterruptionFilter}") - if (nm.currentInterruptionFilter <= NotificationManager.INTERRUPTION_FILTER_ALL) - startRinging() - } else { + if (ua.account.answerMode == Api.ANSWERMODE_AUTO) { val newIntent = Intent(this, MainActivity::class.java) - newIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or - Intent.FLAG_ACTIVITY_NEW_TASK + newIntent.flags = + Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or + Intent.FLAG_ACTIVITY_NEW_TASK newIntent.putExtra("action", "call answer") newIntent.putExtra("callp", callp) startActivity(newIntent) return } + val channelId = if (shouldVibrate()) MEDIUM_CHANNEL_ID else HIGH_CHANNEL_ID + if (shouldStartRinging(channelId)) + startRinging() if (!Utils.isVisible()) { val piFlags = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT val intent = Intent(applicationContext, MainActivity::class.java) @@ -894,8 +894,7 @@ class BaresipService: Service() { intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK val pi = PendingIntent.getActivity(applicationContext, CALL_REQ_CODE, intent, piFlags) - val nb = NotificationCompat.Builder(this, - if (shouldVibrate()) MEDIUM_CHANNEL_ID else HIGH_CHANNEL_ID) + val nb = NotificationCompat.Builder(this, channelId) val caller = Utils.friendlyUri(this, peerUri, ua.account) val person = Person.Builder().setName(caller).build() nb.setSmallIcon(R.drawable.ic_stat_call) @@ -1293,6 +1292,7 @@ class BaresipService: Service() { private fun createNotificationChannels() { val lowChannel = NotificationChannel(LOW_CHANNEL_ID, "No sound or vibrate", NotificationManager.IMPORTANCE_LOW) + lowChannel.enableVibration(false) lowChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC nm.createNotificationChannel(lowChannel) @@ -1304,8 +1304,8 @@ class BaresipService: Service() { val mediumChannel = NotificationChannel(MEDIUM_CHANNEL_ID, "Sound", NotificationManager.IMPORTANCE_HIGH) - highChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC - highChannel.enableVibration(false) + mediumChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC + mediumChannel.enableVibration(false) nm.createNotificationChannel(mediumChannel) } @@ -1397,21 +1397,29 @@ class BaresipService: Service() { } } + + private fun shouldStartRinging(channelId: String): Boolean { + val currentFilter = nm.currentInterruptionFilter + val dndAllowsRinging = currentFilter == NotificationManager.INTERRUPTION_FILTER_ALL || + currentFilter == NotificationManager.INTERRUPTION_FILTER_PRIORITY + if (dndAllowsRinging) + return true + val channel = nm.getNotificationChannel(channelId) + return channel != null && channel.canBypassDnd() + } + private fun shouldVibrate(): Boolean { - return if (am.ringerMode != RINGER_MODE_SILENT) { - if (am.ringerMode == AudioManager.RINGER_MODE_VIBRATE) { + return if (am.ringerMode != RINGER_MODE_SILENT) + if (am.ringerMode == AudioManager.RINGER_MODE_VIBRATE) true - } else { - if (am.getStreamVolume(AudioManager.STREAM_RING) != 0) { + else + if (am.getStreamVolume(AudioManager.STREAM_RING) != 0) @Suppress("DEPRECATION") - Settings.System.getInt(contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 0) == 1 - } else { + Settings.System.getInt(contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 0) != 0 + else false - } - } - } else { + else false - } } private fun stopRinging() {