From 39ad8347c751be62d09c30b7a24606c233a452a9 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 28 Aug 2023 15:57:14 +0200 Subject: [PATCH] Started playing around with alerts --- app/src/main/assets/linphonerc_factory | 3 + .../org/linphone/contacts/ContactLoader.kt | 17 +++-- .../java/org/linphone/ui/voip/VoipActivity.kt | 33 ++++++++++ .../ui/voip/viewmodel/CallsViewModel.kt | 38 ++++++++++- .../org/linphone/utils/AnimationsUtils.kt | 6 +- .../res/drawable/shape_toast_red_shadow.xml | 17 +++++ app/src/main/res/drawable/wifi_high.xml | 9 +++ app/src/main/res/drawable/wifi_low.xml | 9 +++ app/src/main/res/layout/toast_red.xml | 64 +++++++++++++++++++ app/src/main/res/layout/voip_activity.xml | 28 ++++++++ 10 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 app/src/main/res/drawable/shape_toast_red_shadow.xml create mode 100644 app/src/main/res/drawable/wifi_high.xml create mode 100644 app/src/main/res/drawable/wifi_low.xml create mode 100644 app/src/main/res/layout/toast_red.xml diff --git a/app/src/main/assets/linphonerc_factory b/app/src/main/assets/linphonerc_factory index bc4a6334e..045de9d44 100644 --- a/app/src/main/assets/linphonerc_factory +++ b/app/src/main/assets/linphonerc_factory @@ -53,4 +53,7 @@ url=https://subscribe.linphone.org/api/ [lime] lime_update_threshold=86400 +[alerts] +alerts_enabled=1 + ## End of factory rc diff --git a/app/src/main/java/org/linphone/contacts/ContactLoader.kt b/app/src/main/java/org/linphone/contacts/ContactLoader.kt index f9d6d86ad..0520793fb 100644 --- a/app/src/main/java/org/linphone/contacts/ContactLoader.kt +++ b/app/src/main/java/org/linphone/contacts/ContactLoader.kt @@ -26,6 +26,7 @@ import android.net.Uri import android.os.Bundle import android.provider.ContactsContract import android.util.Patterns +import androidx.annotation.MainThread import androidx.loader.app.LoaderManager import androidx.loader.content.CursorLoader import androidx.loader.content.Loader @@ -50,6 +51,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { ) } + @MainThread override fun onCreateLoader(id: Int, args: Bundle?): Loader { val mimeType = ContactsContract.Data.MIMETYPE val mimeSelection = "$mimeType = ? OR $mimeType = ? OR $mimeType = ? OR $mimeType = ?" @@ -72,6 +74,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { ) } + @MainThread override fun onLoadFinished(loader: Loader, cursor: Cursor?) { if (cursor == null) { Log.e("[Contacts Loader] Cursor is null!") @@ -79,15 +82,14 @@ class ContactLoader : LoaderManager.LoaderCallbacks { } Log.i("[Contacts Loader] Load finished, found ${cursor.count} entries in cursor") - val state = coreContext.core.globalState - if (state == GlobalState.Shutdown || state == GlobalState.Off) { - Log.w("[Contacts Loader] Core is being stopped or already destroyed, abort") - return - } - coreContext.postOnCoreThread { core -> - val friends = HashMap() + val state = coreContext.core.globalState + if (state == GlobalState.Shutdown || state == GlobalState.Off) { + Log.w("[Contacts Loader] Core is being stopped or already destroyed, abort") + return@postOnCoreThread + } + val friends = HashMap() try { // Cursor can be null now that we are on a different dispatcher according to Crashlytics val friendsPhoneNumbers = arrayListOf() @@ -315,6 +317,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks { } } + @MainThread override fun onLoaderReset(loader: Loader) { Log.i("[Contacts Loader] Loader reset") } diff --git a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt index 2b4170147..8a755406c 100644 --- a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt +++ b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt @@ -45,6 +45,7 @@ import org.linphone.ui.voip.model.AudioDeviceModel import org.linphone.ui.voip.viewmodel.CallsViewModel import org.linphone.ui.voip.viewmodel.CurrentCallViewModel import org.linphone.ui.voip.viewmodel.SharedCallViewModel +import org.linphone.utils.slideInToastFromTop import org.linphone.utils.slideInToastFromTopForDuration @UiThread @@ -132,6 +133,17 @@ class VoipActivity : AppCompatActivity() { } } + callsViewModel.showLowSignalEvent.observe(this) { + it.consume { show -> + if (show) { + showRedToast("Low Wi-Fi signal!", R.drawable.wifi_low) + } else { + hideRedToast() + showGreenToast("Wi-Fi signal no longer low", R.drawable.wifi_high) + } + } + } + sharedViewModel.toggleFullScreenEvent.observe(this) { it.consume { hide -> hideUI(hide) @@ -147,6 +159,27 @@ class VoipActivity : AppCompatActivity() { target.slideInToastFromTopForDuration(binding.root as ViewGroup, lifecycleScope) } + private fun showRedToast(message: String, @DrawableRes icon: Int) { + binding.redToast.message = message + binding.redToast.icon = icon + + val target = binding.redToast.root + target.slideInToastFromTop(binding.root as ViewGroup, true) + } + + private fun hideRedToast() { + val target = binding.redToast.root + target.slideInToastFromTop(binding.root as ViewGroup, false) + } + + private fun showGreenToast(message: String, @DrawableRes icon: Int) { + binding.greenToast.message = message + binding.greenToast.icon = icon + + val target = binding.greenToast.root + target.slideInToastFromTopForDuration(binding.root as ViewGroup, lifecycleScope, 2000) + } + private fun hideUI(hide: Boolean) { Log.i("$TAG Switching full screen mode to ${if (hide) "ON" else "OFF"}") val windowInsetsCompat = WindowInsetsControllerCompat(window, window.decorView) diff --git a/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt b/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt index e6625895d..62b09d52e 100644 --- a/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/voip/viewmodel/CallsViewModel.kt @@ -24,6 +24,8 @@ import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.core.Alert +import org.linphone.core.AlertListenerStub import org.linphone.core.Call import org.linphone.core.Core import org.linphone.core.CoreListenerStub @@ -31,6 +33,10 @@ import org.linphone.core.tools.Log import org.linphone.utils.Event class CallsViewModel @UiThread constructor() : ViewModel() { + companion object { + private const val TAG = "[Calls ViewModel]" + } + val goToActiveCallEvent = MutableLiveData>() val showIncomingCallEvent = MutableLiveData>() @@ -39,10 +45,25 @@ class CallsViewModel @UiThread constructor() : ViewModel() { val noMoreCallEvent = MutableLiveData>() + val showLowSignalEvent = MutableLiveData>() + + private val alertListener = object : AlertListenerStub() { + @WorkerThread + override fun onOnTerminated(alert: Alert) { + val remote = alert.call.remoteAddress.asStringUriOnly() + Log.w("$TAG Alert of type [${alert.type}] dismissed for call from [$remote]") + alert.removeListener(this) + + if (alert.type == Alert.Type.QoSLowSignal) { + showLowSignalEvent.postValue(Event(false)) + } + } + } + private val coreListener = object : CoreListenerStub() { @WorkerThread override fun onLastCallEnded(core: Core) { - Log.i("[Calls ViewModel] No more call, leaving VoIP activity") + Log.i("$TAG No more call, leaving VoIP activity") noMoreCallEvent.postValue(Event(true)) } @@ -63,6 +84,17 @@ class CallsViewModel @UiThread constructor() : ViewModel() { } } } + + @WorkerThread + override fun onOnAlert(core: Core, alert: Alert) { + val remote = alert.call.remoteAddress.asStringUriOnly() + Log.w("$TAG Alert of type [${alert.type}] triggered for call from [$remote]") + alert.addListener(alertListener) + + if (alert.type == Alert.Type.QoSLowSignal) { + showLowSignalEvent.postValue(Event(true)) + } + } } init { @@ -82,10 +114,10 @@ class CallsViewModel @UiThread constructor() : ViewModel() { Call.State.IncomingReceived, Call.State.IncomingEarlyMedia -> { showIncomingCallEvent.postValue(Event(true)) } - else -> { - } + else -> {} } } else { + Log.w("$TAG No call found, leaving VoIP activity") noMoreCallEvent.postValue(Event(true)) } } diff --git a/app/src/main/java/org/linphone/utils/AnimationsUtils.kt b/app/src/main/java/org/linphone/utils/AnimationsUtils.kt index 522c3e0d5..daeee5d20 100644 --- a/app/src/main/java/org/linphone/utils/AnimationsUtils.kt +++ b/app/src/main/java/org/linphone/utils/AnimationsUtils.kt @@ -38,6 +38,10 @@ fun View.slideInToastFromTop( visible: Boolean ) { val view = this + if (visible && view.visibility == View.VISIBLE) { + // Toast is already visible, hide existing one first + view.visibility = View.GONE + } val transition: Transition = Slide(Gravity.TOP) transition.duration = 600 @@ -51,7 +55,7 @@ fun View.slideInToastFromTop( fun View.slideInToastFromTopForDuration( root: ViewGroup, lifecycleScope: LifecycleCoroutineScope, - duration: Long = 5000 + duration: Long = 4000 ) { val view = this diff --git a/app/src/main/res/drawable/shape_toast_red_shadow.xml b/app/src/main/res/drawable/shape_toast_red_shadow.xml new file mode 100644 index 000000000..49899cc01 --- /dev/null +++ b/app/src/main/res/drawable/shape_toast_red_shadow.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/wifi_high.xml b/app/src/main/res/drawable/wifi_high.xml new file mode 100644 index 000000000..f5f9f6c77 --- /dev/null +++ b/app/src/main/res/drawable/wifi_high.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/wifi_low.xml b/app/src/main/res/drawable/wifi_low.xml new file mode 100644 index 000000000..6717b505a --- /dev/null +++ b/app/src/main/res/drawable/wifi_low.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/toast_red.xml b/app/src/main/res/layout/toast_red.xml new file mode 100644 index 000000000..05621252f --- /dev/null +++ b/app/src/main/res/layout/toast_red.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/voip_activity.xml b/app/src/main/res/layout/voip_activity.xml index a6d56acf4..549018b70 100644 --- a/app/src/main/res/layout/voip_activity.xml +++ b/app/src/main/res/layout/voip_activity.xml @@ -37,6 +37,34 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> + + + +