Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface ElementCallEntryPoint {
* @param senderName The name of the sender of the event that started the call.
* @param avatarUrl The avatar url of the room or DM.
* @param timestamp The timestamp of the event that started the call.
* @param expirationTimestamp The timestamp at which the call should stop ringing.
* @param notificationChannelId The id of the notification channel to use for the call notification.
* @param textContent The text content of the notification. If null the default content from the system will be used.
*/
Expand All @@ -40,6 +41,7 @@ interface ElementCallEntryPoint {
senderName: String?,
avatarUrl: String?,
timestamp: Long,
expirationTimestamp: Long,
notificationChannelId: String,
textContent: String?,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class DefaultElementCallEntryPoint(
senderName: String?,
avatarUrl: String?,
timestamp: Long,
expirationTimestamp: Long,
notificationChannelId: String,
textContent: String?,
) {
Expand All @@ -55,6 +56,7 @@ class DefaultElementCallEntryPoint(
senderName = senderName,
avatarUrl = avatarUrl,
timestamp = timestamp,
expirationTimestamp = expirationTimestamp,
notificationChannelId = notificationChannelId,
textContent = textContent,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ data class CallNotificationData(
val notificationChannelId: String,
val timestamp: Long,
val textContent: String?,
val expirationTimestamp: Long,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class RingingCallNotificationCreator(
roomAvatarUrl: String?,
notificationChannelId: String,
timestamp: Long,
expirationTimestamp: Long,
textContent: String?,
): Notification? {
val matrixClient = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null
Expand All @@ -88,6 +89,7 @@ class RingingCallNotificationCreator(
notificationChannelId = notificationChannelId,
timestamp = timestamp,
textContent = textContent,
expirationTimestamp = expirationTimestamp,
)

val declineIntent = PendingIntentCompat.getBroadcast(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ internal fun IncomingCallScreenPreview() = ElementPreview {
notificationChannelId = "incoming_call",
timestamp = 0L,
textContent = null,
expirationTimestamp = 1000L,
),
onAnswer = {},
onCancel = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import timber.log.Timber
import kotlin.time.Duration.Companion.seconds
import kotlin.math.min

/**
* Manages the active call state.
Expand Down Expand Up @@ -118,8 +118,20 @@ class DefaultActiveCallManager(

override suspend fun registerIncomingCall(notificationData: CallNotificationData) {
mutex.withLock {
val ringDuration =
min(
notificationData.expirationTimestamp - System.currentTimeMillis(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to use SystemClock here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx.

ElementCallConfig.RINGING_CALL_DURATION_SECONDS * 1000L
)

if (ringDuration < 0) {
// Should already have stopped ringing, ignore.
Timber.tag(tag).d("Received timed-out incoming ringing call for room id: ${notificationData.roomId}, cancel ringing")
return
}

appForegroundStateService.updateHasRingingCall(true)
Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}")
Timber.tag(tag).d("Received incoming call for room id: ${notificationData.roomId}, ringDuration: $ringDuration")
if (activeCall.value != null) {
displayMissedCallNotification(notificationData)
Timber.tag(tag).w("Already have an active call, ignoring incoming call: $notificationData")
Expand All @@ -138,14 +150,14 @@ class DefaultActiveCallManager(
showIncomingCallNotification(notificationData)

// Wait for the ringing call to time out
delay(ElementCallConfig.RINGING_CALL_DURATION_SECONDS.seconds)
delay(timeMillis = ringDuration)
incomingCallTimedOut(displayMissedCallNotification = true)
}

// Acquire a wake lock to keep the device awake during the incoming call, so we can process the room info data
if (activeWakeLock?.isHeld == false) {
Timber.tag(tag).d("Acquiring partial wakelock")
activeWakeLock.acquire(ElementCallConfig.RINGING_CALL_DURATION_SECONDS * 1000L)
activeWakeLock.acquire(ringDuration)
}
}
}
Expand Down Expand Up @@ -236,6 +248,7 @@ class DefaultActiveCallManager(
notificationChannelId = notificationData.notificationChannelId,
timestamp = notificationData.timestamp,
textContent = notificationData.textContent,
expirationTimestamp = notificationData.expirationTimestamp,
) ?: return
runCatchingExceptions {
notificationManagerCompat.notify(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ import io.element.android.features.messages.impl.actionlist.model.TimelineItemAc
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure
import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentWithAttachment
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.canBeCopied
import io.element.android.features.messages.impl.timeline.model.event.canBeForwarded
Expand Down Expand Up @@ -242,7 +242,7 @@ class DefaultActionListPresenter(
private fun Iterable<TimelineItemAction>.postFilter(content: TimelineItemEventContent): Iterable<TimelineItemAction> {
return filter { action ->
when (content) {
is TimelineItemCallNotifyContent,
is TimelineItemRtcNotificationContent,
is TimelineItemLegacyCallInviteContent,
is TimelineItemStateContent -> action == TimelineItemAction.ViewSource
is TimelineItemRedactedContent -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ import io.element.android.features.messages.impl.timeline.a11y.a11yReactionActio
import io.element.android.features.messages.impl.timeline.components.MessageShieldView
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
Expand Down Expand Up @@ -306,7 +306,7 @@ private fun MessageSummary(
is TimelineItemLegacyCallInviteContent -> {
content = { ContentForBody(textContent) }
}
is TimelineItemCallNotifyContent -> {
is TimelineItemRtcNotificationContent -> {
content = { ContentForBody(stringResource(CommonStrings.common_call_started)) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomcall.api.RoomCallStateProvider
import io.element.android.libraries.designsystem.components.avatar.Avatar
Expand Down Expand Up @@ -119,7 +119,7 @@ internal fun TimelineItemCallNotifyViewPreview() = ElementPreview {
.filter { it !is RoomCallState.Unavailable }
.forEach { roomCallState ->
TimelineItemCallNotifyView(
event = aTimelineItemEvent(content = TimelineItemCallNotifyContent()),
event = aTimelineItemEvent(content = TimelineItemRtcNotificationContent()),
roomCallState = roomCallState,
onLongClick = {},
onJoinCallClick = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import io.element.android.features.messages.impl.timeline.TimelineRoomInfo
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionEvent
Expand Down Expand Up @@ -123,7 +123,7 @@ internal fun TimelineItemRow(
eventSink = eventSink,
)
}
is TimelineItemCallNotifyContent -> {
is TimelineItemRtcNotificationContent -> {
TimelineItemCallNotifyView(
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp),
event = timelineItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import io.element.android.features.messages.impl.timeline.components.layout.Cont
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.di.rememberPresenter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
Expand All @@ -23,6 +22,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
Expand Down Expand Up @@ -133,6 +133,6 @@ fun TimelineItemEventContentView(
modifier = modifier
)
}
is TimelineItemCallNotifyContent -> error("This shouldn't be rendered as the content of a bubble")
is TimelineItemRtcNotificationContent -> error("This shouldn't be rendered as the content of a bubble")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
package io.element.android.features.messages.impl.timeline.factories.event

import dev.zacsweers.metro.Inject
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
Expand Down Expand Up @@ -61,7 +61,7 @@ class TimelineItemContentFactory(
is StickerContent -> stickerFactory.create(itemContent)
is PollContent -> pollFactory.create(eventTimelineItem, itemContent)
is UnableToDecryptContent -> utdFactory.create(itemContent)
is CallNotifyContent -> TimelineItemCallNotifyContent()
is CallNotifyContent -> TimelineItemRtcNotificationContent()
is UnknownContent -> TimelineItemUnknownContent
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl.timeline.groups

import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
Expand All @@ -19,6 +18,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent
Expand Down Expand Up @@ -60,7 +60,7 @@ internal fun TimelineItem.Event.canBeGrouped(): Boolean {
TimelineItemRedactedContent,
TimelineItemUnknownContent,
is TimelineItemLegacyCallInviteContent,
is TimelineItemCallNotifyContent -> false
is TimelineItemRtcNotificationContent -> false
is TimelineItemProfileChangeContent,
is TimelineItemRoomMembershipContent,
is TimelineItemStateEventContent -> true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fun TimelineItemEventContent.canReact(): Boolean =
is TimelineItemStateContent,
is TimelineItemRedactedContent,
is TimelineItemLegacyCallInviteContent,
is TimelineItemCallNotifyContent,
is TimelineItemRtcNotificationContent,
TimelineItemUnknownContent -> false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

package io.element.android.features.messages.impl.timeline.model.event

class TimelineItemCallNotifyContent : TimelineItemEventContent {
override val type: String = "m.call.notify"
class TimelineItemRtcNotificationContent : TimelineItemEventContent {
override val type: String = "org.matrix.msc4075.rtc.notification"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl.timeline.protection

import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEmoteContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
Expand All @@ -21,6 +20,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemProfileChangeContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRoomMembershipContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
Expand All @@ -38,7 +38,7 @@ fun TimelineItem.mustBeProtected(): Boolean {
is TimelineItemVideoContent,
is TimelineItemStickerContent -> true
is TimelineItemAudioContent,
is TimelineItemCallNotifyContent,
is TimelineItemRtcNotificationContent,
is TimelineItemEncryptedContent,
is TimelineItemFileContent,
TimelineItemLegacyCallInviteContent,
Expand Down
Loading
Loading