Skip to content

Commit 573767a

Browse files
committed
Let notifications use avatar fallback.
Extract code which handles Matrix image to its own api / impl / test modules.
1 parent 8603d54 commit 573767a

File tree

42 files changed

+410
-194
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+410
-194
lines changed

appnav/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dependencies {
3939
implementation(projects.libraries.pushproviders.api)
4040
implementation(projects.libraries.designsystem)
4141
implementation(projects.libraries.matrixui)
42+
implementation(projects.libraries.matrixmedia.api)
4243
implementation(projects.libraries.uiCommon)
4344
implementation(projects.libraries.uiStrings)
4445
implementation(projects.features.login.api)

appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import io.element.android.libraries.architecture.callback
3333
import io.element.android.libraries.architecture.inputs
3434
import io.element.android.libraries.designsystem.utils.ForceOrientationInMobileDevices
3535
import io.element.android.libraries.designsystem.utils.ScreenOrientation
36-
import io.element.android.libraries.matrix.ui.media.NotLoggedInImageLoaderFactory
36+
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
3737
import kotlinx.parcelize.Parcelize
3838

3939
@ContributesNode(AppScope::class)
@@ -42,7 +42,7 @@ class NotLoggedInFlowNode(
4242
@Assisted buildContext: BuildContext,
4343
@Assisted plugins: List<Plugin>,
4444
private val loginEntryPoint: LoginEntryPoint,
45-
private val notLoggedInImageLoaderFactory: NotLoggedInImageLoaderFactory,
45+
private val imageLoaderHolder: ImageLoaderHolder,
4646
) : BaseFlowNode<NotLoggedInFlowNode.NavTarget>(
4747
backstack = BackStack(
4848
initialElement = NavTarget.Root,
@@ -66,7 +66,7 @@ class NotLoggedInFlowNode(
6666
super.onBuilt()
6767
lifecycle.subscribe(
6868
onResume = {
69-
SingletonImageLoader.setUnsafe(notLoggedInImageLoaderFactory.newImageLoader())
69+
SingletonImageLoader.setUnsafe(imageLoaderHolder.get())
7070
},
7171
)
7272
}

features/call/impl/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ dependencies {
7474
implementation(projects.libraries.designsystem)
7575
implementation(projects.libraries.featureflag.api)
7676
implementation(projects.libraries.matrix.impl)
77-
implementation(projects.libraries.matrixui)
77+
implementation(projects.libraries.matrixmedia.api)
7878
implementation(projects.libraries.network)
7979
implementation(projects.libraries.preferences.api)
8080
implementation(projects.libraries.push.api)
@@ -94,7 +94,7 @@ dependencies {
9494
testImplementation(projects.libraries.featureflag.test)
9595
testImplementation(projects.libraries.preferences.test)
9696
testImplementation(projects.libraries.matrix.test)
97-
testImplementation(projects.libraries.matrixuiTest)
97+
testImplementation(projects.libraries.matrixmedia.test)
9898
testImplementation(projects.libraries.push.test)
9999
testImplementation(projects.services.analytics.test)
100100
testImplementation(projects.services.appnavstate.test)

features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import io.element.android.features.call.api.CallType
2222
import io.element.android.features.call.impl.receivers.DeclineCallBroadcastReceiver
2323
import io.element.android.features.call.impl.ui.IncomingCallActivity
2424
import io.element.android.features.call.impl.utils.IntentProvider
25+
import io.element.android.libraries.designsystem.components.avatar.AvatarData
26+
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
2527
import io.element.android.libraries.designsystem.utils.CommonDrawables
2628
import io.element.android.libraries.di.annotations.ApplicationContext
2729
import io.element.android.libraries.matrix.api.MatrixClientProvider
@@ -70,7 +72,15 @@ class RingingCallNotificationCreator(
7072
): Notification? {
7173
val matrixClient = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null
7274
val imageLoader = imageLoaderHolder.get(matrixClient)
73-
val largeIcon = notificationBitmapLoader.getUserIcon(roomAvatarUrl, imageLoader)
75+
val largeIcon = notificationBitmapLoader.getUserIcon(
76+
avatarData = AvatarData(
77+
id = roomId.value,
78+
name = roomName,
79+
url = roomAvatarUrl,
80+
size = AvatarSize.RoomDetailsHeader,
81+
),
82+
imageLoader = imageLoader,
83+
)
7484

7585
val caller = Person.Builder()
7686
.setName(senderDisplayName)

features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.test.platform.app.InstrumentationRegistry
1313
import coil3.ImageLoader
1414
import com.google.common.truth.Truth.assertThat
1515
import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator
16+
import io.element.android.libraries.designsystem.components.avatar.AvatarData
1617
import io.element.android.libraries.matrix.test.AN_EVENT_ID
1718
import io.element.android.libraries.matrix.test.A_ROOM_ID
1819
import io.element.android.libraries.matrix.test.A_SESSION_ID
@@ -53,7 +54,7 @@ class RingingCallNotificationCreatorTest {
5354

5455
@Test
5556
fun `createNotification - tries to load the avatar URL`() = runTest {
56-
val getUserIconLambda = lambdaRecorder<String?, ImageLoader, IconCompat?> { _, _ -> null }
57+
val getUserIconLambda = lambdaRecorder<AvatarData, ImageLoader, IconCompat?> { _, _ -> null }
5758
val notificationCreator = createRingingCallNotificationCreator(
5859
matrixClientProvider = FakeMatrixClientProvider(getClient = { Result.success(FakeMatrixClient()) }),
5960
notificationBitmapLoader = FakeNotificationBitmapLoader(getUserIconResult = getUserIconLambda)

features/messages/impl/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dependencies {
3939
implementation(projects.libraries.architecture)
4040
implementation(projects.libraries.matrix.api)
4141
implementation(projects.libraries.matrixui)
42+
implementation(projects.libraries.matrixmedia.api)
4243
implementation(projects.libraries.designsystem)
4344
implementation(projects.libraries.textcomposer.impl)
4445
implementation(projects.libraries.uiStrings)

libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/internal/ImageAvatar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ internal fun ImageAvatar(
4646
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
4747
is AsyncImagePainter.State.Error -> {
4848
SideEffect {
49-
Timber.Forest.e(
49+
Timber.e(
5050
state.result.throwable,
5151
"Error loading avatar $state\n${state.result}"
5252
)

libraries/matrixui-test/build.gradle.kts renamed to libraries/matrixmedia/api/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ plugins {
1111
}
1212

1313
android {
14-
namespace = "io.element.android.libraries.matrix.ui.test"
14+
namespace = "io.element.android.libraries.matrix.ui.media.api"
1515
}
1616

1717
dependencies {
18+
implementation(projects.libraries.designsystem)
1819
implementation(projects.libraries.matrix.api)
19-
implementation(projects.libraries.matrixui)
2020
implementation(libs.coil.compose)
2121
}
Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88

99
package io.element.android.libraries.matrix.ui.media
1010

11-
import io.element.android.libraries.designsystem.components.avatar.AvatarData
12-
import io.element.android.libraries.matrix.api.media.MediaSource
13-
1411
/**
1512
* The size in pixel of the thumbnail to generate for the avatar.
1613
* This is not the size of the avatar displayed in the UI but the size to get from the servers.
@@ -25,10 +22,3 @@ import io.element.android.libraries.matrix.api.media.MediaSource
2522
* Let's always use the same size so coil caching works properly.
2623
*/
2724
const val AVATAR_THUMBNAIL_SIZE_IN_PIXEL = 240L
28-
29-
internal fun AvatarData.toMediaRequestData(): MediaRequestData {
30-
return MediaRequestData(
31-
source = url?.let { MediaSource(it) },
32-
kind = MediaRequestData.Kind.Thumbnail(AVATAR_THUMBNAIL_SIZE_IN_PIXEL)
33-
)
34-
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2025 Element Creations Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.libraries.matrix.ui.media
9+
10+
import coil3.ImageLoader
11+
import io.element.android.libraries.matrix.api.MatrixClient
12+
import io.element.android.libraries.matrix.api.core.SessionId
13+
14+
interface ImageLoaderHolder {
15+
fun get(): ImageLoader
16+
fun get(client: MatrixClient): ImageLoader
17+
fun remove(sessionId: SessionId)
18+
}

0 commit comments

Comments
 (0)