VoIP: introduce priority for in-app notification

This commit is contained in:
ganfra 2020-12-09 11:48:44 +01:00
parent 76ed775f6f
commit 40446c7a31
4 changed files with 33 additions and 20 deletions

View file

@ -158,10 +158,6 @@ class CallService : VectorService(), WiredHeadsetStateReceiver.HeadsetEventListe
/** /**
* Display a permanent notification when there is an incoming call. * Display a permanent notification when there is an incoming call.
* *
* @param session the session
* @param isVideo true if this is a video call, false for voice call
* @param room the room
* @param callId the callId
*/ */
private fun displayIncomingCallNotification(intent: Intent) { private fun displayIncomingCallNotification(intent: Intent) {
Timber.v("## VOIP displayIncomingCallNotification $intent") Timber.v("## VOIP displayIncomingCallNotification $intent")

View file

@ -29,6 +29,7 @@ class IncomingCallAlert(uid: String,
override val shouldBeDisplayedIn: ((Activity) -> Boolean) = { true } override val shouldBeDisplayedIn: ((Activity) -> Boolean) = { true }
) : DefaultVectorAlert(uid, "", "", 0, shouldBeDisplayedIn) { ) : DefaultVectorAlert(uid, "", "", 0, shouldBeDisplayedIn) {
override val priority = PopupAlertManager.INCOMING_CALL_PRIORITY
override val layoutRes = R.layout.alerter_incoming_call_layout override val layoutRes = R.layout.alerter_incoming_call_layout
override var colorAttribute: Int? = R.attr.riotx_alerter_background override var colorAttribute: Int? = R.attr.riotx_alerter_background

View file

@ -35,19 +35,25 @@ import javax.inject.Singleton
/** /**
* Responsible of displaying important popup alerts on top of the screen. * Responsible of displaying important popup alerts on top of the screen.
* Alerts are stacked and will be displayed sequentially * Alerts are stacked and will be displayed sequentially but sorted by priority.
* So if a new alert is posted with a higher priority than the current one it will show it instead and the current one
* will be back in the queue in first position.
*/ */
@Singleton @Singleton
class PopupAlertManager @Inject constructor() { class PopupAlertManager @Inject constructor() {
companion object {
const val INCOMING_CALL_PRIORITY = Int.MAX_VALUE
}
private var weakCurrentActivity: WeakReference<Activity>? = null private var weakCurrentActivity: WeakReference<Activity>? = null
private var currentAlerter: VectorAlert? = null private var currentAlerter: VectorAlert? = null
private val alertFiFo = mutableListOf<VectorAlert>() private val alertQueue = mutableListOf<VectorAlert>()
fun postVectorAlert(alert: VectorAlert) { fun postVectorAlert(alert: VectorAlert) {
synchronized(alertFiFo) { synchronized(alertQueue) {
alertFiFo.add(alert) alertQueue.add(alert)
} }
weakCurrentActivity?.get()?.runOnUiThread { weakCurrentActivity?.get()?.runOnUiThread {
displayNextIfPossible() displayNextIfPossible()
@ -55,8 +61,8 @@ class PopupAlertManager @Inject constructor() {
} }
fun cancelAlert(uid: String) { fun cancelAlert(uid: String) {
synchronized(alertFiFo) { synchronized(alertQueue) {
alertFiFo.listIterator().apply { alertQueue.listIterator().apply {
while (this.hasNext()) { while (this.hasNext()) {
val next = this.next() val next = this.next()
if (next.uid == uid) { if (next.uid == uid) {
@ -79,8 +85,8 @@ class PopupAlertManager @Inject constructor() {
* Cancel all alerts, after a sign out for instance * Cancel all alerts, after a sign out for instance
*/ */
fun cancelAll() { fun cancelAll() {
synchronized(alertFiFo) { synchronized(alertQueue) {
alertFiFo.clear() alertQueue.clear()
} }
// Cancel any displayed alert // Cancel any displayed alert
@ -126,15 +132,21 @@ class PopupAlertManager @Inject constructor() {
} }
private fun displayNextIfPossible() { private fun displayNextIfPossible() {
val currentActivity = weakCurrentActivity?.get() val currentActivity = weakCurrentActivity?.get() ?: return
if (Alerter.isShowing || currentActivity == null) {
// will retry later
return
}
val next: VectorAlert? val next: VectorAlert?
synchronized(alertFiFo) { synchronized(alertQueue) {
next = alertFiFo.firstOrNull() next = alertQueue.maxByOrNull { it.priority }
if (next != null) alertFiFo.remove(next) // If next alert with highest priority is higher than the current one, we should display it
// and add the current one to queue again.
if (next != null && next.priority > currentAlerter?.priority ?: Int.MIN_VALUE) {
alertQueue.remove(next)
currentAlerter?.also {
alertQueue.add(0, it)
}
} else {
// otherwise, we don't do anything
return
}
} }
currentAlerter = next currentAlerter = next
next?.let { next?.let {

View file

@ -34,6 +34,7 @@ interface VectorAlert {
val title: String val title: String
val description: String val description: String
val iconId: Int? val iconId: Int?
val priority: Int
val shouldBeDisplayedIn: ((Activity) -> Boolean) val shouldBeDisplayedIn: ((Activity) -> Boolean)
data class Button(val title: String, val action: Runnable, val autoClose: Boolean) data class Button(val title: String, val action: Runnable, val autoClose: Boolean)
@ -83,6 +84,7 @@ open class DefaultVectorAlert(
override val shouldBeDisplayedIn: ((Activity) -> Boolean) = { true }, override val shouldBeDisplayedIn: ((Activity) -> Boolean) = { true },
) : VectorAlert { ) : VectorAlert {
// will be set by manager, and accessible by actions at runtime // will be set by manager, and accessible by actions at runtime
override var weakCurrentActivity: WeakReference<Activity>? = null override var weakCurrentActivity: WeakReference<Activity>? = null
@ -97,6 +99,8 @@ open class DefaultVectorAlert(
@LayoutRes @LayoutRes
override val layoutRes = R.layout.alerter_alert_default_layout override val layoutRes = R.layout.alerter_alert_default_layout
override val priority: Int = 0
@ColorRes @ColorRes
override var colorRes: Int? = null override var colorRes: Int? = null