Improved showing and hiding of soft keyboard

This commit is contained in:
Juha Heinanen
2025-10-09 18:55:47 +03:00
parent 288679c6c0
commit 17db3e9572
2 changed files with 60 additions and 18 deletions

View File

@ -6,7 +6,7 @@ import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.content.res.Configuration
import android.media.AudioManager
import android.net.Uri
import android.os.Build
@ -101,8 +101,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle
@ -152,8 +153,6 @@ private var password = mutableStateOf("")
private val selectItems = mutableStateOf(listOf<String>())
private val selectItemAction = mutableStateOf<(Int) -> Unit>({ _ -> run {} })
private val showSelectItemDialog = mutableStateOf(false)
private var keyboardController: SoftwareKeyboardController? = null
private var callRunnable: Runnable? = null
private var callHandler: Handler = Handler(Looper.getMainLooper())
private var audioModeChangedListener: AudioManager.OnModeChangedListener? = null
@ -186,6 +185,21 @@ private fun MainScreen(
) {
val ctx = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val configuration = LocalConfiguration.current
val keyboardController = LocalSoftwareKeyboardController.current
val ua = uas.value.find { it.account.aor == viewModel.selectedAor.value }
val call = ua?.currentCall()
LaunchedEffect(viewModel.showKeyboard.value) {
if (viewModel.showKeyboard.value > 0)
keyboardController?.show()
}
LaunchedEffect(viewModel.hideKeyboard.value) {
if (viewModel.hideKeyboard.value > 0)
keyboardController?.hide()
}
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
@ -344,6 +358,18 @@ private fun MainScreen(
}
}
LaunchedEffect(key1 = call?.status, key2 = configuration.orientation) {
val isConnected = call != null && call.status == "connected" && !call.held
if (isConnected) {
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
focusDtmf.value = true
keyboardController?.show()
}
else
keyboardController?.hide()
}
}
if (showPasswordDialog.value)
PasswordDialog(
ctx = ctx,
@ -1429,7 +1455,7 @@ private fun CallRow(ctx: Context, viewModel: ViewModel) {
if (showDialog.value)
BasicAlertDialog(
onDismissRequest = {
keyboardController?.hide()
viewModel.requestHideKeyboard()
showDialog.value = false
showTransferDialog = false
}
@ -1593,7 +1619,7 @@ private fun CallRow(ctx: Context, viewModel: ViewModel) {
) {
TextButton(
onClick = {
keyboardController?.hide()
viewModel.requestHideKeyboard()
showDialog.value = false
showTransferDialog = false
},
@ -1635,7 +1661,7 @@ private fun CallRow(ctx: Context, viewModel: ViewModel) {
!blindChecked.value
)
}
keyboardController?.hide()
viewModel.requestHideKeyboard()
showDialog.value = false
showTransferDialog = false
}
@ -1998,7 +2024,6 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
callUri.value = ""
callUriLabel.value = ctx.getString(R.string.outgoing_call_to_dots)
callUriEnabled.value = true
keyboardController?.hide()
showCallTimer.value = false
securityIcon.intValue = -1
showHangupButton.value = false
@ -2019,6 +2044,19 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
} else {
pullToRefreshEnabled.value = false
callUriEnabled.value = false
val isLandscape = ctx.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
if (isLandscape || call.held || call.status != "connected") {
focusDtmf.value = false
dtmfEnabled.value = !call.held
Handler(Looper.getMainLooper()).postDelayed({
viewModel.requestHideKeyboard()
}, 25)
}
else {
dtmfEnabled.value = true
focusDtmf.value = true
viewModel.requestShowKeyboard()
}
when (call.status) {
"outgoing", "transferring", "answered" -> {
callUriLabel.value = if (call.status == "answered")
@ -2090,16 +2128,6 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
Handler(Looper.getMainLooper()).postDelayed({
showOnHoldNotice.value = call.held
}, 100)
if (call.held) {
keyboardController?.hide()
dtmfEnabled.value = false
focusDtmf.value = false
} else {
dtmfEnabled.value = true
focusDtmf.value = true
if (ctx.resources.configuration.orientation == ORIENTATION_PORTRAIT)
keyboardController?.show()
}
}
}
}

View File

@ -45,6 +45,20 @@ class ViewModel(application: Application) : AndroidViewModel(application) {
_aorPeerMessage.value = newMap
}
private val _showKeyboard = mutableStateOf(0)
val showKeyboard: State<Int> = _showKeyboard
fun requestShowKeyboard() {
_showKeyboard.value++
}
private val _hideKeyboard = mutableStateOf(0)
val hideKeyboard: State<Int> = _hideKeyboard
fun requestHideKeyboard() {
_hideKeyboard.value++
}
private val _speakerIcon = MutableStateFlow(R.drawable.speaker_off)
val speakerIcon: StateFlow<Int> = _speakerIcon.asStateFlow()