mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Started playing around with alerts
This commit is contained in:
parent
294410bfd2
commit
39ad8347c7
10 changed files with 213 additions and 11 deletions
|
|
@ -53,4 +53,7 @@ url=https://subscribe.linphone.org/api/
|
|||
[lime]
|
||||
lime_update_threshold=86400
|
||||
|
||||
[alerts]
|
||||
alerts_enabled=1
|
||||
|
||||
## End of factory rc
|
||||
|
|
|
|||
|
|
@ -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<Cursor> {
|
|||
)
|
||||
}
|
||||
|
||||
@MainThread
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
|
||||
val mimeType = ContactsContract.Data.MIMETYPE
|
||||
val mimeSelection = "$mimeType = ? OR $mimeType = ? OR $mimeType = ? OR $mimeType = ?"
|
||||
|
|
@ -72,6 +74,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
|
|||
)
|
||||
}
|
||||
|
||||
@MainThread
|
||||
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor?) {
|
||||
if (cursor == null) {
|
||||
Log.e("[Contacts Loader] Cursor is null!")
|
||||
|
|
@ -79,15 +82,14 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
|
|||
}
|
||||
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<String, Friend>()
|
||||
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<String, Friend>()
|
||||
try {
|
||||
// Cursor can be null now that we are on a different dispatcher according to Crashlytics
|
||||
val friendsPhoneNumbers = arrayListOf<String>()
|
||||
|
|
@ -315,6 +317,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
|
|||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
override fun onLoaderReset(loader: Loader<Cursor>) {
|
||||
Log.i("[Contacts Loader] Loader reset")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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<Event<Boolean>>()
|
||||
|
||||
val showIncomingCallEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
|
@ -39,10 +45,25 @@ class CallsViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val noMoreCallEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
val showLowSignalEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
17
app/src/main/res/drawable/shape_toast_red_shadow.xml
Normal file
17
app/src/main/res/drawable/shape_toast_red_shadow.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="50dp" />
|
||||
<solid android:color="@color/red_danger"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:bottom="2dp">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="50dp" />
|
||||
<solid
|
||||
android:color="@color/white" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
9
app/src/main/res/drawable/wifi_high.xml
Normal file
9
app/src/main/res/drawable/wifi_high.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="96dp"
|
||||
android:height="96dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M140,204a12,12 0,1 1,-12 -12A12,12 0,0 1,140 204ZM237.08,87A172,172 0,0 0,18.92 87,8 8,0 0,0 29.08,99.37a156,156 0,0 1,197.84 0A8,8 0,0 0,237.08 87ZM205,122.77a124,124 0,0 0,-153.94 0A8,8 0,0 0,61 135.31a108,108 0,0 1,134.06 0,8 8,0 0,0 11.24,-1.3A8,8 0,0 0,205 122.77ZM172.74,158.53a76.05,76.05 0,0 0,-89.42 0,8 8,0 0,0 9.42,12.94 60,60 0,0 1,70.58 0,8 8,0 1,0 9.42,-12.94Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/wifi_low.xml
Normal file
9
app/src/main/res/drawable/wifi_low.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="96dp"
|
||||
android:height="96dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M140,204a12,12 0,1 1,-12 -12A12,12 0,0 1,140 204ZM172.71,158.53a76.05,76.05 0,0 0,-89.42 0,8 8,0 0,0 9.42,12.94 60,60 0,0 1,70.58 0,8 8,0 1,0 9.42,-12.94Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
64
app/src/main/res/layout/toast_red.xml
Normal file
64
app/src/main/res/layout/toast_red.xml
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="android.graphics.Typeface" />
|
||||
<variable
|
||||
name="icon"
|
||||
type="Integer" />
|
||||
<variable
|
||||
name="message"
|
||||
type="String" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="17dp"
|
||||
android:layout_marginEnd="17dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toast_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:src="@drawable/shape_toast_red_shadow"
|
||||
app:layout_constraintBottom_toBottomOf="@id/toast_message"
|
||||
app:layout_constraintEnd_toEndOf="@id/toast_message"
|
||||
app:layout_constraintStart_toStartOf="@id/toast_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/toast_message" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toast_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@{icon, default=@drawable/wifi_low}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/toast_message"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:tint="@color/red_danger" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/toast_message"
|
||||
style="@style/default_text_style"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@{message, default=`Low Wi-Fi signal!`}"
|
||||
android:textColor="@color/red_danger"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/toast_icon"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -37,6 +37,34 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/green_toast"
|
||||
android:visibility="gone"
|
||||
layout="@layout/toast_green"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/toast_top_margin"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
app:layout_constraintWidth_max="@dimen/toast_max_width"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/red_toast"
|
||||
android:visibility="gone"
|
||||
layout="@layout/toast_red"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/toast_top_margin"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
app:layout_constraintWidth_max="@dimen/toast_max_width"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue