Merge pull request #6649 from element-hq/feature/valere/call/decline_timeline_rendering
feat: Update call started timeline item + declined support
This commit is contained in:
commit
9ca0b9e898
16 changed files with 360 additions and 56 deletions
|
|
@ -54,6 +54,7 @@ class DefaultRoomLatestEventFormatter(
|
|||
private val roomMembershipContentFormatter: RoomMembershipContentFormatter,
|
||||
private val profileChangeContentFormatter: ProfileChangeContentFormatter,
|
||||
private val stateContentFormatter: StateContentFormatter,
|
||||
private val rtcNotificationContentFormatter: RtcNotificationContentFormatter,
|
||||
private val permalinkParser: PermalinkParser,
|
||||
) : RoomLatestEventFormatter {
|
||||
override fun format(
|
||||
|
|
@ -121,7 +122,7 @@ class DefaultRoomLatestEventFormatter(
|
|||
message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing)
|
||||
}
|
||||
is LegacyCallInviteContent -> sp.getString(CommonStrings.common_unsupported_call)
|
||||
is CallNotifyContent -> sp.getString(CommonStrings.common_call_started)
|
||||
is CallNotifyContent -> rtcNotificationContentFormatter.format(content, isDmRoom)
|
||||
}?.take(DEFAULT_SAFE_LENGTH)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.eventformatter.impl
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
|
||||
@Inject
|
||||
class RtcNotificationContentFormatter(
|
||||
private val matrixClient: MatrixClient,
|
||||
private val sp: StringProvider,
|
||||
) {
|
||||
fun format(
|
||||
content: CallNotifyContent,
|
||||
isDm: Boolean,
|
||||
): CharSequence {
|
||||
return if (isDm) {
|
||||
val isDeclined = content.declinedBy.isNotEmpty()
|
||||
val isDeclinedByMe = content.declinedBy.any { matrixClient.isMe(it) }
|
||||
if (isDeclinedByMe) {
|
||||
sp.getString(CommonStrings.common_call_you_declined)
|
||||
} else if (isDeclined) {
|
||||
sp.getString(CommonStrings.common_call_declined)
|
||||
} else {
|
||||
sp.getString(CommonStrings.common_call_started)
|
||||
}
|
||||
} else {
|
||||
sp.getString(CommonStrings.common_call_started)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +74,8 @@ class DefaultRoomLatestEventFormatterTest {
|
|||
roomMembershipContentFormatter = RoomMembershipContentFormatter(fakeMatrixClient, stringProvider),
|
||||
profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider),
|
||||
stateContentFormatter = StateContentFormatter(stringProvider),
|
||||
permalinkParser = FakePermalinkParser(),
|
||||
rtcNotificationContentFormatter = RtcNotificationContentFormatter(fakeMatrixClient, stringProvider),
|
||||
permalinkParser = FakePermalinkParser()
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.eventformatter.impl
|
||||
|
||||
import android.content.Context
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.notification.CallIntent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_3
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
import kotlin.toString
|
||||
|
||||
@Suppress("LargeClass")
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class RtcNotificationContentFormatterTest {
|
||||
private lateinit var context: Context
|
||||
private lateinit var fakeMatrixClient: FakeMatrixClient
|
||||
private lateinit var formatter: RtcNotificationContentFormatter
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
context = RuntimeEnvironment.getApplication() as Context
|
||||
fakeMatrixClient = FakeMatrixClient()
|
||||
val stringProvider = AndroidStringProvider(context.resources)
|
||||
formatter = RtcNotificationContentFormatter(
|
||||
fakeMatrixClient,
|
||||
stringProvider
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "en")
|
||||
fun `Should not display declined info in rooms`() {
|
||||
val result = formatter.format(
|
||||
CallNotifyContent(
|
||||
CallIntent.VIDEO,
|
||||
declinedBy = listOf(A_USER_ID_2, A_USER_ID_3)
|
||||
),
|
||||
false
|
||||
)
|
||||
val expected = "Call started"
|
||||
assertThat(result.toString()).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "en")
|
||||
fun `Declined by me variant`() {
|
||||
val result = formatter.format(
|
||||
CallNotifyContent(
|
||||
CallIntent.VIDEO,
|
||||
declinedBy = listOf(fakeMatrixClient.sessionId)
|
||||
),
|
||||
true
|
||||
)
|
||||
val expected = "You declined a call"
|
||||
assertThat(result.toString()).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "en")
|
||||
fun `Declined by other variant`() {
|
||||
val result = formatter.format(
|
||||
CallNotifyContent(
|
||||
CallIntent.VIDEO,
|
||||
declinedBy = listOf(A_USER_ID_2)
|
||||
),
|
||||
true
|
||||
)
|
||||
val expected = "Call declined"
|
||||
assertThat(result.toString()).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "en")
|
||||
fun `Call started in DM`() {
|
||||
val result = formatter.format(
|
||||
CallNotifyContent(
|
||||
CallIntent.AUDIO,
|
||||
declinedBy = listOf()
|
||||
),
|
||||
true
|
||||
)
|
||||
val expected = "Call started"
|
||||
assertThat(result.toString()).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +119,8 @@ data class LiveLocationContent(
|
|||
data object LegacyCallInviteContent : EventContent
|
||||
|
||||
data class CallNotifyContent(
|
||||
val callIntent: CallIntent
|
||||
val callIntent: CallIntent,
|
||||
val declinedBy: List<UserId>
|
||||
) : EventContent
|
||||
|
||||
data object UnknownContent : EventContent
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@ class TimelineEventContentMapper(
|
|||
CallIntent.AUDIO
|
||||
} else {
|
||||
CallIntent.VIDEO
|
||||
}
|
||||
},
|
||||
declinedBy = it.declinedBy.map(::UserId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class DefaultEventItemFactoryTest {
|
|||
fun `create check all null cases`() {
|
||||
val factory = createEventItemFactory()
|
||||
val contents = listOf(
|
||||
CallNotifyContent(callIntent = CallIntent.VIDEO),
|
||||
CallNotifyContent(callIntent = CallIntent.VIDEO, emptyList()),
|
||||
FailedToParseMessageLikeContent("", ""),
|
||||
FailedToParseStateContent("", "", ""),
|
||||
LegacyCallInviteContent,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue