Element Call ringing notifications (#2978)

- Add `ActiveCallManager` to handle incoming and ongoing calls.
- Add ringing call notifications with full screen intents and missed call ones as part of the 'conversation' notifications.

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2024-06-10 11:51:19 +02:00 committed by GitHub
parent b827b859dc
commit 6f8de0b2c6
186 changed files with 2686 additions and 330 deletions

View file

@ -24,7 +24,13 @@ android {
dependencies {
api(projects.libraries.push.api)
implementation(projects.libraries.push.impl)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.matrixui)
implementation(projects.libraries.pushproviders.api)
implementation(projects.tests.testutils)
implementation(libs.androidx.core)
implementation(libs.coil.compose)
implementation(libs.coil.test)
implementation(libs.test.robolectric)
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.test.notifications
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import coil.ImageLoader
import coil.annotation.ExperimentalCoilApi
import coil.test.FakeImageLoaderEngine
import org.robolectric.RuntimeEnvironment
@OptIn(ExperimentalCoilApi::class)
class FakeImageLoader {
private val coilRequests = mutableListOf<Any>()
private var cache: ImageLoader? = null
fun getImageLoader(): ImageLoader {
return cache ?: ImageLoader.Builder(RuntimeEnvironment.getApplication())
.components {
val engine = FakeImageLoaderEngine.Builder()
.intercept(
predicate = {
coilRequests.add(it)
true
},
drawable = ColorDrawable(Color.BLUE)
)
.build()
add(engine)
}
.build()
.also {
cache = it
}
}
fun getCoilRequests(): List<Any> {
return coilRequests.toList()
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.test.notifications
import coil.ImageLoader
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
class FakeImageLoaderHolder : ImageLoaderHolder {
private val fakeImageLoader = FakeImageLoader()
override fun get(client: MatrixClient): ImageLoader {
return fakeImageLoader.getImageLoader()
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.test.notifications
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.push.api.notifications.OnMissedCallNotificationHandler
class FakeOnMissedCallNotificationHandler(
var addMissedCallNotificationLambda: (SessionId, RoomId, EventId) -> Unit = { _, _, _ -> }
) : OnMissedCallNotificationHandler {
override suspend fun addMissedCallNotification(
sessionId: SessionId,
roomId: RoomId,
eventId: EventId,
) {
addMissedCallNotificationLambda(sessionId, roomId, eventId)
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.test.notifications.push
import android.graphics.Bitmap
import androidx.core.graphics.drawable.IconCompat
import coil.ImageLoader
import io.element.android.libraries.push.api.notifications.NotificationBitmapLoader
class FakeNotificationBitmapLoader(
var getRoomBitmapResult: (String?, ImageLoader) -> Bitmap? = { _, _ -> null },
var getUserIconResult: (String?, ImageLoader) -> IconCompat? = { _, _ -> null },
) : NotificationBitmapLoader {
override suspend fun getRoomBitmap(path: String?, imageLoader: ImageLoader): Bitmap? {
return getRoomBitmapResult(path, imageLoader)
}
override suspend fun getUserIcon(path: String?, imageLoader: ImageLoader): IconCompat? {
return getUserIconResult(path, imageLoader)
}
}