Timeline call tiles: refact grouping events and fix some issues
This commit is contained in:
parent
bcc9a75bdb
commit
0d56707fd3
|
@ -31,8 +31,6 @@ import im.vector.app.core.epoxy.LoadingItem_
|
|||
import im.vector.app.core.extensions.localDateTime
|
||||
import im.vector.app.core.extensions.nextOrNull
|
||||
import im.vector.app.core.extensions.prevOrNull
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||
import im.vector.app.features.home.room.detail.JitsiState
|
||||
import im.vector.app.features.home.room.detail.RoomDetailAction
|
||||
import im.vector.app.features.home.room.detail.RoomDetailViewState
|
||||
|
@ -41,7 +39,7 @@ import im.vector.app.features.home.room.detail.timeline.factory.MergedHeaderItem
|
|||
import im.vector.app.features.home.room.detail.timeline.factory.ReadReceiptsItemFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactoryParams
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.CallEventGrouper
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.TimelineEventsGroups
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.TimelineControllerInterceptorHelper
|
||||
|
@ -81,10 +79,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
|||
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
||||
private val mergedHeaderItemFactory: MergedHeaderItemFactory,
|
||||
private val session: Session,
|
||||
private val callManager: WebRtcCallManager,
|
||||
@TimelineEventControllerHandler
|
||||
private val backgroundHandler: Handler,
|
||||
private val userPreferencesProvider: UserPreferencesProvider,
|
||||
private val timelineEventVisibilityHelper: TimelineEventVisibilityHelper,
|
||||
private val readReceiptsItemFactory: ReadReceiptsItemFactory
|
||||
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener, EpoxyController.Interceptor {
|
||||
|
@ -166,7 +162,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
|||
|
||||
// Map eventId to adapter position
|
||||
private val adapterPositionMapping = HashMap<String, Int>()
|
||||
private val callEventGroupers = HashMap<String, CallEventGrouper>()
|
||||
private val timelineEventsGroups = TimelineEventsGroups()
|
||||
private val receiptsByEvent = HashMap<String, MutableList<ReadReceipt>>()
|
||||
private val modelCache = arrayListOf<CacheItemData?>()
|
||||
private var currentSnapshot: List<TimelineEvent> = emptyList()
|
||||
|
@ -366,11 +362,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
|||
}
|
||||
// Should be build if not cached or if model should be refreshed
|
||||
if (modelCache[position] == null || modelCache[position]?.isCacheable == false) {
|
||||
val callEventGrouper = if (EventType.isCallEvent(event.root.getClearType())) {
|
||||
(event.root.getClearContent()?.get("call_id") as? String)?.let { callId -> callEventGroupers[callId] }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val timelineEventsGroup = timelineEventsGroups.getOrNull(event)
|
||||
val params = TimelineItemFactoryParams(
|
||||
event = event,
|
||||
prevEvent = prevEvent,
|
||||
|
@ -379,7 +371,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
|||
partialState = partialState,
|
||||
lastSentEventIdWithoutReadReceipts = lastSentEventWithoutReadReceipts,
|
||||
callback = callback,
|
||||
callEventGrouper = callEventGrouper
|
||||
eventsGroup = timelineEventsGroup
|
||||
)
|
||||
modelCache[position] = buildCacheItem(params)
|
||||
}
|
||||
|
@ -460,16 +452,12 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
|||
|
||||
private fun preprocessReverseEvents() {
|
||||
receiptsByEvent.clear()
|
||||
callEventGroupers.clear()
|
||||
timelineEventsGroups.clear()
|
||||
val itr = currentSnapshot.listIterator(currentSnapshot.size)
|
||||
var lastShownEventId: String? = null
|
||||
while (itr.hasPrevious()) {
|
||||
val event = itr.previous()
|
||||
if (EventType.isCallEvent(event.root.getClearType())) {
|
||||
(event.root.getClearContent()?.get("call_id") as? String)?.also { callId ->
|
||||
callEventGroupers.getOrPut(callId) { CallEventGrouper(session.myUserId, callId) }.add(event)
|
||||
}
|
||||
}
|
||||
timelineEventsGroups.addOrIgnore(event)
|
||||
val currentReadReceipts = ArrayList(event.readReceipts).filter {
|
||||
it.user.userId != session.myUserId
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import im.vector.app.features.call.vectorCallService
|
|||
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.CallSignalingEventsGroup
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.RoomSummariesHolder
|
||||
|
@ -45,7 +46,7 @@ class CallItemFactory @Inject constructor(
|
|||
val event = params.event
|
||||
if (event.root.eventId == null) return null
|
||||
val showHiddenEvents = userPreferencesProvider.shouldShowHiddenEvents()
|
||||
val callEventGrouper = params.callEventGrouper ?: return null
|
||||
val callEventGrouper = params.eventsGroup?.let { CallSignalingEventsGroup(it) } ?: return null
|
||||
val roomId = event.roomId
|
||||
val informationData = messageInformationDataFactory.create(params)
|
||||
val callKind = if (callEventGrouper.isVideo()) CallTileTimelineItem.CallKind.VIDEO else CallTileTimelineItem.CallKind.AUDIO
|
||||
|
@ -60,7 +61,8 @@ class CallItemFactory @Inject constructor(
|
|||
callback = params.callback,
|
||||
highlight = params.isHighlighted,
|
||||
informationData = informationData,
|
||||
isStillActive = callEventGrouper.isInCall()
|
||||
isStillActive = callEventGrouper.isInCall(),
|
||||
formattedDuration = callEventGrouper.formattedDuration()
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
@ -76,7 +78,8 @@ class CallItemFactory @Inject constructor(
|
|||
callback = params.callback,
|
||||
highlight = params.isHighlighted,
|
||||
informationData = informationData,
|
||||
isStillActive = callEventGrouper.isRinging()
|
||||
isStillActive = callEventGrouper.isRinging(),
|
||||
formattedDuration = callEventGrouper.formattedDuration()
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
@ -91,7 +94,8 @@ class CallItemFactory @Inject constructor(
|
|||
callback = params.callback,
|
||||
highlight = params.isHighlighted,
|
||||
informationData = informationData,
|
||||
isStillActive = false
|
||||
isStillActive = false,
|
||||
formattedDuration = callEventGrouper.formattedDuration()
|
||||
)
|
||||
}
|
||||
EventType.CALL_HANGUP -> {
|
||||
|
@ -103,7 +107,8 @@ class CallItemFactory @Inject constructor(
|
|||
callback = params.callback,
|
||||
highlight = params.isHighlighted,
|
||||
informationData = informationData,
|
||||
isStillActive = false
|
||||
isStillActive = false,
|
||||
formattedDuration = callEventGrouper.formattedDuration()
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
|
@ -118,6 +123,7 @@ class CallItemFactory @Inject constructor(
|
|||
informationData: MessageInformationData,
|
||||
highlight: Boolean,
|
||||
isStillActive: Boolean,
|
||||
formattedDuration: String,
|
||||
callback: TimelineEventController.Callback?
|
||||
): CallTileTimelineItem? {
|
||||
val correctedRoomId = session.vectorCallService.userMapper.nativeRoomForVirtualRoom(roomId) ?: roomId
|
||||
|
@ -129,6 +135,7 @@ class CallItemFactory @Inject constructor(
|
|||
callStatus = callStatus,
|
||||
informationData = informationData,
|
||||
avatarRenderer = it.avatarRenderer,
|
||||
formattedDuration = formattedDuration,
|
||||
messageColorProvider = messageColorProvider,
|
||||
itemClickListener = it.itemClickListener,
|
||||
itemLongClickListener = it.itemLongClickListener,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package im.vector.app.features.home.room.detail.timeline.factory
|
||||
|
||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.CallEventGrouper
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.TimelineEventsGroup
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
|
||||
data class TimelineItemFactoryParams(
|
||||
|
@ -28,7 +28,7 @@ data class TimelineItemFactoryParams(
|
|||
val partialState: TimelineEventController.PartialState = TimelineEventController.PartialState(),
|
||||
val lastSentEventIdWithoutReadReceipts: String? = null,
|
||||
val callback: TimelineEventController.Callback? = null,
|
||||
val callEventGrouper: CallEventGrouper?= null
|
||||
val eventsGroup: TimelineEventsGroup? = null
|
||||
) {
|
||||
|
||||
val highlightedEventId: String?
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
package im.vector.app.features.home.room.detail.timeline.factory
|
||||
|
||||
import im.vector.app.ActiveSessionDataSource
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.JitsiWidgetEventsGroup
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.RoomSummariesHolder
|
||||
import im.vector.app.features.home.room.detail.timeline.item.CallTileTimelineItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.CallTileTimelineItem_
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
|
@ -38,6 +38,7 @@ class WidgetItemFactory @Inject constructor(
|
|||
private val avatarSizeProvider: AvatarSizeProvider,
|
||||
private val messageColorProvider: MessageColorProvider,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val userPreferencesProvider: UserPreferencesProvider,
|
||||
private val roomSummariesHolder: RoomSummariesHolder
|
||||
) {
|
||||
|
||||
|
@ -58,8 +59,12 @@ class WidgetItemFactory @Inject constructor(
|
|||
val event = params.event
|
||||
val roomId = event.roomId
|
||||
val userOfInterest = roomSummariesHolder.get(roomId)?.toMatrixItem() ?: return null
|
||||
val isActive = widgetContent.isActive()
|
||||
val callStatus = if (isActive && widgetContent.id == params.partialState.jitsiState.widgetId) {
|
||||
val isActiveTile = widgetContent.isActive()
|
||||
val jitsiWidgetEventsGroup = params.eventsGroup?.let { JitsiWidgetEventsGroup(it) } ?: return null
|
||||
val isCallStillActive = jitsiWidgetEventsGroup.isStillActive()
|
||||
val showHiddenEvents = userPreferencesProvider.shouldShowHiddenEvents()
|
||||
if (isActiveTile && !isCallStillActive && !showHiddenEvents) return null
|
||||
val callStatus = if (isActiveTile && widgetContent.id == params.partialState.jitsiState.widgetId) {
|
||||
if (params.partialState.jitsiState.hasJoined) {
|
||||
CallTileTimelineItem.CallStatus.IN_CALL
|
||||
} else {
|
||||
|
@ -68,7 +73,6 @@ class WidgetItemFactory @Inject constructor(
|
|||
} else {
|
||||
CallTileTimelineItem.CallStatus.ENDED
|
||||
}
|
||||
|
||||
val fakeCallId = widgetContent.id ?: prevWidgetContent?.id ?: return null
|
||||
val attributes = CallTileTimelineItem.Attributes(
|
||||
callId = fakeCallId,
|
||||
|
@ -83,7 +87,8 @@ class WidgetItemFactory @Inject constructor(
|
|||
readReceiptsCallback = params.callback,
|
||||
userOfInterest = userOfInterest,
|
||||
callback = params.callback,
|
||||
isStillActive = isActive
|
||||
isStillActive = isCallStillActive,
|
||||
formattedDuration = ""
|
||||
)
|
||||
return CallTileTimelineItem_()
|
||||
.attributes(attributes)
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.home.room.detail.timeline.helper
|
||||
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
|
||||
class CallEventGrouper(private val myUserId: String, val callId: String) {
|
||||
|
||||
private val events = HashSet<TimelineEvent>()
|
||||
|
||||
fun add(timelineEvent: TimelineEvent) {
|
||||
events.add(timelineEvent)
|
||||
}
|
||||
|
||||
fun isVideo(): Boolean {
|
||||
val invite = getInvite() ?: return false
|
||||
return invite.root.getClearContent().toModel<CallInviteContent>()?.isVideo().orFalse()
|
||||
}
|
||||
|
||||
fun isRinging(): Boolean {
|
||||
return getAnswer() == null && getHangup() == null && getReject() == null
|
||||
}
|
||||
|
||||
fun isInCall(): Boolean{
|
||||
return getHangup() == null && getReject() == null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are only events from one side.
|
||||
*/
|
||||
fun callWasMissed(): Boolean {
|
||||
return events.distinctBy { it.senderInfo.userId }.size == 1
|
||||
}
|
||||
|
||||
private fun getAnswer(): TimelineEvent? {
|
||||
return events.firstOrNull { it.root.getClearType() == EventType.CALL_ANSWER }
|
||||
}
|
||||
|
||||
private fun getInvite(): TimelineEvent? {
|
||||
return events.firstOrNull { it.root.getClearType() == EventType.CALL_INVITE }
|
||||
}
|
||||
|
||||
private fun getHangup(): TimelineEvent? {
|
||||
return events.firstOrNull { it.root.getClearType() == EventType.CALL_HANGUP }
|
||||
}
|
||||
|
||||
private fun getReject(): TimelineEvent? {
|
||||
return events.firstOrNull { it.root.getClearType() == EventType.CALL_REJECT }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.home.room.detail.timeline.helper
|
||||
|
||||
import im.vector.app.core.utils.TextUtils
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
import org.threeten.bp.Duration
|
||||
|
||||
class TimelineEventsGroup(val groupId: String) {
|
||||
|
||||
val events: Set<TimelineEvent>
|
||||
get() = _events
|
||||
|
||||
private val _events = HashSet<TimelineEvent>()
|
||||
|
||||
fun add(timelineEvent: TimelineEvent) {
|
||||
_events.add(timelineEvent)
|
||||
}
|
||||
}
|
||||
|
||||
class TimelineEventsGroups {
|
||||
|
||||
private val groups = HashMap<String, TimelineEventsGroup>()
|
||||
|
||||
fun addOrIgnore(event: TimelineEvent) {
|
||||
val groupId = event.getGroupIdOrNull() ?: return
|
||||
groups.getOrPut(groupId) { TimelineEventsGroup(groupId) }.add(event)
|
||||
}
|
||||
|
||||
fun getOrNull(event: TimelineEvent): TimelineEventsGroup? {
|
||||
val groupId = event.getGroupIdOrNull() ?: return null
|
||||
return groups[groupId]
|
||||
}
|
||||
|
||||
private fun TimelineEvent.getGroupIdOrNull(): String? {
|
||||
val type = root.getClearType()
|
||||
val content = root.getClearContent()
|
||||
return if (EventType.isCallEvent(type)) {
|
||||
(content?.get("call_id") as? String)
|
||||
} else {
|
||||
val widgetContent: WidgetContent = root.getClearContent().toModel() ?: return null
|
||||
val isJitsi = WidgetType.fromString(widgetContent.type ?: "") == WidgetType.Jitsi
|
||||
if (isJitsi) {
|
||||
widgetContent.id
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
groups.clear()
|
||||
}
|
||||
}
|
||||
|
||||
class JitsiWidgetEventsGroup(private val group: TimelineEventsGroup) {
|
||||
|
||||
fun isStillActive(): Boolean {
|
||||
return group.events.none {
|
||||
it.root.getClearContent().toModel<WidgetContent>()?.isActive() == false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CallSignalingEventsGroup(private val group: TimelineEventsGroup) {
|
||||
|
||||
val callId: String = group.groupId
|
||||
|
||||
fun isVideo(): Boolean {
|
||||
val invite = getInvite() ?: return false
|
||||
return invite.root.getClearContent().toModel<CallInviteContent>()?.isVideo().orFalse()
|
||||
}
|
||||
|
||||
fun isRinging(): Boolean {
|
||||
return getAnswer() == null && getHangup() == null && getReject() == null
|
||||
}
|
||||
|
||||
fun isInCall(): Boolean {
|
||||
return getHangup() == null && getReject() == null
|
||||
}
|
||||
|
||||
fun formattedDuration(): String {
|
||||
val start = getAnswer()?.root?.originServerTs
|
||||
val end = getHangup()?.root?.originServerTs
|
||||
return if (start == null || end == null) {
|
||||
""
|
||||
} else {
|
||||
val durationInMillis = (end - start).coerceAtLeast(0L)
|
||||
val duration = Duration.ofMillis(durationInMillis)
|
||||
TextUtils.formatDuration(duration)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are only events from one side.
|
||||
*/
|
||||
fun callWasMissed(): Boolean {
|
||||
return group.events.distinctBy { it.senderInfo.userId }.size == 1
|
||||
}
|
||||
|
||||
private fun getAnswer(): TimelineEvent? {
|
||||
return group.events.firstOrNull { it.root.getClearType() == EventType.CALL_ANSWER }
|
||||
}
|
||||
|
||||
private fun getInvite(): TimelineEvent? {
|
||||
return group.events.firstOrNull { it.root.getClearType() == EventType.CALL_INVITE }
|
||||
}
|
||||
|
||||
private fun getHangup(): TimelineEvent? {
|
||||
return group.events.firstOrNull { it.root.getClearType() == EventType.CALL_HANGUP }
|
||||
}
|
||||
|
||||
private fun getReject(): TimelineEvent? {
|
||||
return group.events.firstOrNull { it.root.getClearType() == EventType.CALL_REJECT }
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
package im.vector.app.features.home.room.detail.timeline.item
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.telecom.Call
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
|
@ -95,7 +96,19 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
|
||||
private fun renderEndedStatus(holder: Holder) {
|
||||
holder.acceptRejectViewGroup.isVisible = false
|
||||
holder.statusView.setStatus(R.string.call_tile_ended)
|
||||
when (attributes.callKind) {
|
||||
CallKind.VIDEO -> {
|
||||
val endCallStatus = holder.resources.getString(R.string.call_tile_video_call_has_ended, attributes.formattedDuration)
|
||||
holder.statusView.setStatus(endCallStatus)
|
||||
}
|
||||
CallKind.AUDIO -> {
|
||||
val endCallStatus = holder.resources.getString(R.string.call_tile_voice_call_has_ended, attributes.formattedDuration)
|
||||
holder.statusView.setStatus(endCallStatus)
|
||||
}
|
||||
CallKind.CONFERENCE -> {
|
||||
holder.statusView.setStatus(R.string.call_tile_ended)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRejectedStatus(holder: Holder) {
|
||||
|
@ -194,6 +207,10 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
}
|
||||
}
|
||||
when {
|
||||
// Invite state for conference should show as InCallStatus
|
||||
attributes.callKind == CallKind.CONFERENCE -> {
|
||||
holder.statusView.setStatus(R.string.call_tile_video_active)
|
||||
}
|
||||
attributes.informationData.sentByMe -> {
|
||||
holder.statusView.setStatus(R.string.call_ringing)
|
||||
}
|
||||
|
@ -207,8 +224,13 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
}
|
||||
|
||||
private fun TextView.setStatus(@StringRes statusRes: Int, @DrawableRes drawableRes: Int? = null) {
|
||||
val status = resources.getString(statusRes)
|
||||
setStatus(status, drawableRes)
|
||||
}
|
||||
|
||||
private fun TextView.setStatus(status: String, @DrawableRes drawableRes: Int? = null) {
|
||||
setLeftDrawable(drawableRes ?: attributes.callKind.icon)
|
||||
setText(statusRes)
|
||||
text = status
|
||||
}
|
||||
|
||||
class Holder : AbsBaseMessageItem.Holder(STUB_ID) {
|
||||
|
@ -235,6 +257,7 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
val callStatus: CallStatus,
|
||||
val userOfInterest: MatrixItem,
|
||||
val isStillActive: Boolean,
|
||||
val formattedDuration: String,
|
||||
val callback: TimelineEventController.Callback? = null,
|
||||
override val informationData: MessageInformationData,
|
||||
override val avatarRenderer: AvatarRenderer,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:drawablePadding="6dp"
|
||||
android:gravity="center"
|
||||
android:textColor="?vctr_content_primary"
|
||||
|
|
Loading…
Reference in New Issue