Avoid redundant rendering of main screen when call is coming in
This commit is contained in:
@ -152,7 +152,6 @@ import androidx.lifecycle.compose.LocalLifecycleOwner
|
|||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.NavGraphBuilder
|
import androidx.navigation.NavGraphBuilder
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
||||||
import com.tutpro.baresip.BaresipService.Companion.contactNames
|
import com.tutpro.baresip.BaresipService.Companion.contactNames
|
||||||
import com.tutpro.baresip.BaresipService.Companion.uas
|
import com.tutpro.baresip.BaresipService.Companion.uas
|
||||||
import com.tutpro.baresip.BaresipService.Companion.uasStatus
|
import com.tutpro.baresip.BaresipService.Companion.uasStatus
|
||||||
@ -247,15 +246,12 @@ private fun MainScreen(
|
|||||||
(ctx as? Activity)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
(ctx as? Activity)?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
|
||||||
(Call.call("incoming") ?: Call.calls().lastOrNull())?.let {
|
(Call.call("incoming") ?: Call.calls().lastOrNull())?.let {
|
||||||
spinToAor(viewModel, it.ua.account.aor)
|
spinToAor(viewModel, it.ua.account.aor, it)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
if (uas.value.isNotEmpty() && viewModel.selectedAor.value == "")
|
if (uas.value.isNotEmpty() && viewModel.selectedAor.value == "")
|
||||||
spinToAor(viewModel, uas.value.first().account.aor)
|
spinToAor(viewModel, uas.value.first().account.aor)
|
||||||
}
|
else
|
||||||
val ua = UserAgent.ofAor(viewModel.selectedAor.value)
|
viewModel.triggerAccountUpdate()
|
||||||
if (ua != null) {
|
|
||||||
showCall(ctx, viewModel, ua)
|
|
||||||
viewModel.triggerAccountUpdate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Lifecycle.Event.ON_PAUSE -> {
|
Lifecycle.Event.ON_PAUSE -> {
|
||||||
@ -479,16 +475,6 @@ private fun MainScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
|
||||||
val currentRoute = navBackStackEntry?.destination?.route
|
|
||||||
|
|
||||||
LaunchedEffect(currentRoute, viewModel.selectedAor.collectAsState()) {
|
|
||||||
if (currentRoute == "main") {
|
|
||||||
Log.d(TAG, "Updating icons for AOR: ${viewModel.selectedAor.value}")
|
|
||||||
viewModel.triggerAccountUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@ -1050,20 +1036,21 @@ private fun AccountSpinner(ctx: Context, viewModel: ViewModel, navController: Na
|
|||||||
|
|
||||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
val selected: String by viewModel.selectedAor.collectAsState()
|
val selected: String by viewModel.selectedAor.collectAsState()
|
||||||
|
val accountUpdate by viewModel.accountUpdate.collectAsState()
|
||||||
val uasValue by uas
|
val uasValue by uas
|
||||||
|
|
||||||
LaunchedEffect(uasValue, selected) {
|
LaunchedEffect(uasValue, selected, accountUpdate) {
|
||||||
if (uasValue.isEmpty()) {
|
val selected = viewModel.selectedAor.value
|
||||||
|
if (uas.value.isEmpty()) {
|
||||||
if (selected != "") viewModel.updateSelectedAor("")
|
if (selected != "") viewModel.updateSelectedAor("")
|
||||||
} else {
|
} else {
|
||||||
if (selected == "" || UserAgent.ofAor(selected) == null) {
|
if (selected == "" || UserAgent.ofAor(selected) == null) {
|
||||||
viewModel.updateSelectedAor(uasValue.first().account.aor)
|
viewModel.updateSelectedAor(uas.value.first().account.aor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val ua = UserAgent.ofAor(selected)
|
val ua = UserAgent.ofAor(viewModel.selectedAor.value)
|
||||||
if (ua != null) {
|
if (ua != null) {
|
||||||
showCall(ctx, viewModel, ua)
|
showCall(ctx, viewModel, ua, viewModel.focusedCall.value)
|
||||||
viewModel.triggerAccountUpdate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,9 +1177,7 @@ private fun AccountSpinner(ctx: Context, viewModel: ViewModel, navController: Na
|
|||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
expanded = false
|
expanded = false
|
||||||
viewModel.updateSelectedAor(acc.aor)
|
spinToAor(viewModel, acc.aor)
|
||||||
showCall(ctx, viewModel, ua)
|
|
||||||
viewModel.triggerAccountUpdate()
|
|
||||||
},
|
},
|
||||||
text = { Text(
|
text = { Text(
|
||||||
text = acc.text(),
|
text = acc.text(),
|
||||||
@ -2049,10 +2034,14 @@ private fun OnHoldNotice() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun spinToAor(viewModel: ViewModel, aor: String) {
|
private fun spinToAor(viewModel: ViewModel, aor: String, call: Call? = null) {
|
||||||
if (aor != viewModel.selectedAor.value)
|
val aorChanged = aor != viewModel.selectedAor.value
|
||||||
viewModel.updateSelectedAor(aor)
|
val callChanged = call != viewModel.focusedCall.value
|
||||||
viewModel.triggerAccountUpdate()
|
val statusChanged = call != null && call.status.value != viewModel.focusedCall.value?.status?.value
|
||||||
|
if (aorChanged || callChanged || statusChanged) {
|
||||||
|
if (aorChanged) viewModel.updateSelectedAor(aor)
|
||||||
|
viewModel.triggerAccountUpdate(call)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun callClick(ctx: Context, viewModel: ViewModel, dialerState: ViewModel.DialerState?) {
|
private fun callClick(ctx: Context, viewModel: ViewModel, dialerState: ViewModel.DialerState?) {
|
||||||
@ -2239,6 +2228,13 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
|
|||||||
if (ua == null)
|
if (ua == null)
|
||||||
return
|
return
|
||||||
val call = showCall ?: ua.currentCall()
|
val call = showCall ?: ua.currentCall()
|
||||||
|
val aor = ua.account.aor
|
||||||
|
val callp = call?.callp ?: 0L
|
||||||
|
val status = call?.status?.value ?: "idle"
|
||||||
|
val security = call?.security ?: -1
|
||||||
|
|
||||||
|
if (viewModel.isUIRedundant(aor, callp, status, security)) return
|
||||||
|
|
||||||
if (call == null) {
|
if (call == null) {
|
||||||
pullToRefreshEnabled.value = true
|
pullToRefreshEnabled.value = true
|
||||||
viewModel.dialerState.callUri.value = ua.account.resumeUri
|
viewModel.dialerState.callUri.value = ua.account.resumeUri
|
||||||
@ -2272,10 +2268,10 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
|
|||||||
call.focusDtmf.value = true
|
call.focusDtmf.value = true
|
||||||
viewModel.requestShowKeyboard()
|
viewModel.requestShowKeyboard()
|
||||||
}
|
}
|
||||||
Log.d(TAG, "Showing call ${call.callp} from ${call.ua.account.aor} with status ${call.status.value}")
|
Log.d(TAG, "Showing call $callp from $aor with status $status")
|
||||||
when (call.status.value) {
|
when (status) {
|
||||||
"outgoing", "transferring", "answered" -> {
|
"outgoing", "transferring", "answered" -> {
|
||||||
call.callUriLabel.value = if (call.status.value == "answered")
|
call.callUriLabel.value = if (status == "answered")
|
||||||
ctx.getString(R.string.incoming_call_from_dots)
|
ctx.getString(R.string.incoming_call_from_dots)
|
||||||
else
|
else
|
||||||
ctx.getString(R.string.outgoing_call_to_dots)
|
ctx.getString(R.string.outgoing_call_to_dots)
|
||||||
@ -2284,7 +2280,7 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
|
|||||||
call.showCallTimer.value = false
|
call.showCallTimer.value = false
|
||||||
call.securityIconTint.value = -1
|
call.securityIconTint.value = -1
|
||||||
call.showCallButton.value = false
|
call.showCallButton.value = false
|
||||||
call.showCancelButton.value = call.status.value == "outgoing"
|
call.showCancelButton.value = status == "outgoing"
|
||||||
call.showHangupButton.value = !call.showCancelButton.value
|
call.showHangupButton.value = !call.showCancelButton.value
|
||||||
call.showAnswerRejectButtons.value = false
|
call.showAnswerRejectButtons.value = false
|
||||||
call.showOnHoldNotice.value = false
|
call.showOnHoldNotice.value = false
|
||||||
@ -2344,6 +2340,7 @@ private fun showCall(ctx: Context, viewModel: ViewModel, ua: UserAgent?, showCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
viewModel.markUIRendered(aor, callp, status, security)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params: ArrayList<Any>) {
|
fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params: ArrayList<Any>) {
|
||||||
@ -2412,15 +2409,13 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
|||||||
val callp = params[1] as Long
|
val callp = params[1] as Long
|
||||||
if (!BaresipService.isMainVisible)
|
if (!BaresipService.isMainVisible)
|
||||||
viewModel.navigateToHome()
|
viewModel.navigateToHome()
|
||||||
spinToAor(viewModel, aor)
|
spinToAor(viewModel, aor, Call.ofCallp(callp))
|
||||||
showCall(ctx, viewModel, ua, Call.ofCallp(callp))
|
|
||||||
}
|
}
|
||||||
"call answered" -> {
|
"call answered" -> {
|
||||||
|
val callp = params[1] as Long
|
||||||
if (!BaresipService.isMainVisible)
|
if (!BaresipService.isMainVisible)
|
||||||
viewModel.navigateToHome()
|
viewModel.navigateToHome()
|
||||||
spinToAor(viewModel, aor)
|
spinToAor(viewModel, aor, Call.ofCallp(callp))
|
||||||
val callp = params[1] as Long
|
|
||||||
showCall(ctx, viewModel, ua, Call.ofCallp(callp))
|
|
||||||
}
|
}
|
||||||
"call redirect" -> {
|
"call redirect" -> {
|
||||||
val redirectUri = ev[1]
|
val redirectUri = ev[1]
|
||||||
@ -2444,7 +2439,7 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
|||||||
}
|
}
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
}
|
}
|
||||||
showCall(ctx, viewModel, ua)
|
viewModel.triggerAccountUpdate()
|
||||||
}
|
}
|
||||||
"call established" -> {
|
"call established" -> {
|
||||||
(ctx as? Activity)?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
(ctx as? Activity)?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
@ -2457,11 +2452,11 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
|||||||
if (call.conferenceCall)
|
if (call.conferenceCall)
|
||||||
Api.cmd_exec("conference")
|
Api.cmd_exec("conference")
|
||||||
}
|
}
|
||||||
showCall(ctx, viewModel, ua, call)
|
viewModel.triggerAccountUpdate(call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"call update" -> {
|
"call update" -> {
|
||||||
showCall(ctx, viewModel, ua)
|
viewModel.triggerAccountUpdate()
|
||||||
}
|
}
|
||||||
"call verify" -> {
|
"call verify" -> {
|
||||||
val callp = params[1] as Long
|
val callp = params[1] as Long
|
||||||
@ -2502,8 +2497,10 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
|||||||
handleNextEvent("Call $callp that is verified is not found")
|
handleNextEvent("Call $callp that is verified is not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (aor == viewModel.selectedAor.value)
|
if (aor == viewModel.selectedAor.value) {
|
||||||
call.securityIconTint.value = call.security
|
call.securityIconTint.value = call.security
|
||||||
|
viewModel.triggerAccountUpdate(call)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"call transfer", "transfer show" -> {
|
"call transfer", "transfer show" -> {
|
||||||
if (!BaresipService.isMainVisible)
|
if (!BaresipService.isMainVisible)
|
||||||
@ -2560,7 +2557,7 @@ fun handleServiceEvent(ctx: Context, viewModel: ViewModel, event: String, params
|
|||||||
if (aor == viewModel.selectedAor.value) {
|
if (aor == viewModel.selectedAor.value) {
|
||||||
viewModel.dialerState.callButtonsEnabled.value = true
|
viewModel.dialerState.callButtonsEnabled.value = true
|
||||||
ua.account.resumeUri = ""
|
ua.account.resumeUri = ""
|
||||||
showCall(ctx, viewModel, ua)
|
viewModel.triggerAccountUpdate()
|
||||||
if (acc.missedCalls)
|
if (acc.missedCalls)
|
||||||
viewModel.triggerAccountUpdate()
|
viewModel.triggerAccountUpdate()
|
||||||
}
|
}
|
||||||
@ -2621,7 +2618,7 @@ fun handleIntent(ctx: Context, viewModel: ViewModel, intent: Intent, action: Str
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val ua = call.ua
|
val ua = call.ua
|
||||||
spinToAor(viewModel, ua.account.aor)
|
spinToAor(viewModel, ua.account.aor, call)
|
||||||
if (ev[0] == "call answer")
|
if (ev[0] == "call answer")
|
||||||
answer(ctx, call)
|
answer(ctx, call)
|
||||||
else
|
else
|
||||||
|
|||||||
@ -60,6 +60,9 @@ class ViewModel: ViewModel() {
|
|||||||
private val _accountUpdate = MutableStateFlow(0)
|
private val _accountUpdate = MutableStateFlow(0)
|
||||||
val accountUpdate = _accountUpdate.asStateFlow()
|
val accountUpdate = _accountUpdate.asStateFlow()
|
||||||
|
|
||||||
|
private val _focusedCall = MutableStateFlow<Call?>(null)
|
||||||
|
val focusedCall = _focusedCall.asStateFlow()
|
||||||
|
|
||||||
private val _micIcon = MutableStateFlow(Icons.Filled.Mic)
|
private val _micIcon = MutableStateFlow(Icons.Filled.Mic)
|
||||||
val micIcon = _micIcon.asStateFlow()
|
val micIcon = _micIcon.asStateFlow()
|
||||||
|
|
||||||
@ -78,6 +81,23 @@ class ViewModel: ViewModel() {
|
|||||||
private val _navigationCommand = MutableSharedFlow<NavigationCommand>()
|
private val _navigationCommand = MutableSharedFlow<NavigationCommand>()
|
||||||
val navigationCommand = _navigationCommand.asSharedFlow()
|
val navigationCommand = _navigationCommand.asSharedFlow()
|
||||||
|
|
||||||
|
private var lastRenderedAor = ""
|
||||||
|
private var lastRenderedCallp = 0L
|
||||||
|
private var lastRenderedStatus = ""
|
||||||
|
private var lastRenderedSecurity = -1
|
||||||
|
|
||||||
|
fun isUIRedundant(aor: String, callp: Long, status: String, security: Int): Boolean {
|
||||||
|
return aor == lastRenderedAor && callp == lastRenderedCallp &&
|
||||||
|
status == lastRenderedStatus && security == lastRenderedSecurity
|
||||||
|
}
|
||||||
|
|
||||||
|
fun markUIRendered(aor: String, callp: Long, status: String, security: Int) {
|
||||||
|
lastRenderedAor = aor
|
||||||
|
lastRenderedCallp = callp
|
||||||
|
lastRenderedStatus = status
|
||||||
|
lastRenderedSecurity = security
|
||||||
|
}
|
||||||
|
|
||||||
private var _selectedCallRow: CallRow? = null
|
private var _selectedCallRow: CallRow? = null
|
||||||
|
|
||||||
fun selectCallRow(callRow: CallRow) {
|
fun selectCallRow(callRow: CallRow) {
|
||||||
@ -104,7 +124,8 @@ class ViewModel: ViewModel() {
|
|||||||
_selectedAor.value = aor
|
_selectedAor.value = aor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun triggerAccountUpdate() {
|
fun triggerAccountUpdate(call: Call? = null) {
|
||||||
|
_focusedCall.value = call
|
||||||
_accountUpdate.value += 1
|
_accountUpdate.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user