diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
index 28524f6a91..4294358ae0 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
@@ -79,7 +79,7 @@ fun TextView.setLeftDrawable(@DrawableRes iconRes: Int, @ColorRes tintColor: Int
val icon = if(tintColor != null){
val tint = ContextCompat.getColor(context, tintColor)
ContextCompat.getDrawable(context, iconRes)?.also {
- DrawableCompat.setTint(it, tint)
+ DrawableCompat.setTint(it.mutate(), tint)
}
}else {
ContextCompat.getDrawable(context, iconRes)
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index c6a5af5843..355bd64380 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -339,12 +339,12 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
const val INCOMING_RINGING = "INCOMING_RINGING"
const val INCOMING_ACCEPT = "INCOMING_ACCEPT"
- fun newIntent(context: Context, mxCall: MxCallDetail): Intent {
+ fun newIntent(context: Context, mxCall: MxCallDetail, mode: String?): Intent {
return Intent(context, VectorCallActivity::class.java).apply {
// what could be the best flags?
flags = Intent.FLAG_ACTIVITY_NEW_TASK
putExtra(MvRx.KEY_ARG, CallArgs(mxCall.roomId, mxCall.callId, mxCall.opponentUserId, !mxCall.isOutgoing, mxCall.isVideoCall))
- putExtra(EXTRA_MODE, OUTGOING_CREATED)
+ putExtra(EXTRA_MODE, mode)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
index c67abb3d72..7a7a6110a1 100644
--- a/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
+++ b/vector/src/main/java/im/vector/app/features/call/webrtc/WebRtcCallManager.kt
@@ -203,7 +203,7 @@ class WebRtcCallManager @Inject constructor(
callId = mxCall.callId)
// start the activity now
- context.startActivity(VectorCallActivity.newIntent(context, mxCall))
+ context.startActivity(VectorCallActivity.newIntent(context, mxCall, VectorCallActivity.OUTGOING_CREATED))
}
override fun onCallIceCandidateReceived(mxCall: MxCall, iceCandidatesContent: CallCandidatesContent) {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
index 8891218a11..cf2683e68f 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
@@ -19,6 +19,8 @@ package im.vector.app.features.home.room.detail
import android.net.Uri
import android.view.View
import im.vector.app.core.platform.VectorViewModelAction
+import im.vector.app.features.call.webrtc.WebRtcCall
+import im.vector.app.features.home.room.detail.timeline.item.CallTileTimelineItem
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
@@ -73,6 +75,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
object ResendAll : RoomDetailAction()
data class StartCall(val isVideo: Boolean) : RoomDetailAction()
+ data class AcceptCall(val callId: String): RoomDetailAction()
object EndCall : RoomDetailAction()
data class AcceptVerificationRequest(val transactionId: String, val otherUserId: String) : RoomDetailAction()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index 8dc85bd8af..a9b309a218 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -368,6 +368,7 @@ class RoomDetailFragment @Inject constructor(
is RoomDetailViewEvents.DisplayEnableIntegrationsWarning -> displayDisabledIntegrationDialog()
is RoomDetailViewEvents.OpenIntegrationManager -> openIntegrationManager()
is RoomDetailViewEvents.OpenFile -> startOpenFileIntent(it)
+ is RoomDetailViewEvents.DisplayAndAcceptCall -> acceptIncomingCall(it)
RoomDetailViewEvents.OpenActiveWidgetBottomSheet -> onViewWidgetsClicked()
is RoomDetailViewEvents.ShowInfoOkDialog -> showDialogWithMessage(it.message)
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
@@ -381,6 +382,7 @@ class RoomDetailFragment @Inject constructor(
is RoomDetailViewEvents.ShowRoomAvatarFullScreen -> it.matrixItem?.let { item ->
navigator.openBigImageViewer(requireActivity(), it.view, item)
}
+
}.exhaustive
}
@@ -389,6 +391,15 @@ class RoomDetailFragment @Inject constructor(
}
}
+ private fun acceptIncomingCall(event: RoomDetailViewEvents.DisplayAndAcceptCall) {
+ val intent = VectorCallActivity.newIntent(
+ context = vectorBaseActivity,
+ mxCall = event.call.mxCall,
+ mode = VectorCallActivity.INCOMING_ACCEPT
+ )
+ startActivity(intent)
+ }
+
override fun onImageReady(uri: Uri?) {
uri ?: return
roomDetailViewModel.handle(
@@ -836,6 +847,8 @@ class RoomDetailFragment @Inject constructor(
}
}
+
+
private fun safeStartCall2(isVideoCall: Boolean) {
val startCallAction = RoomDetailAction.StartCall(isVideoCall)
roomDetailViewModel.pendingAction = startCallAction
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
index d5d94a0ca5..a22f315082 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
@@ -20,6 +20,7 @@ import android.net.Uri
import android.view.View
import androidx.annotation.StringRes
import im.vector.app.core.platform.VectorViewEvents
+import im.vector.app.features.call.webrtc.WebRtcCall
import im.vector.app.features.command.Command
import org.matrix.android.sdk.api.session.widgets.model.Widget
import org.matrix.android.sdk.api.util.MatrixItem
@@ -73,6 +74,8 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
abstract class SendMessageResult : RoomDetailViewEvents()
+ data class DisplayAndAcceptCall(val call: WebRtcCall): RoomDetailViewEvents()
+
object DisplayPromptForIntegrationManager : RoomDetailViewEvents()
object DisplayEnableIntegrationsWarning : RoomDetailViewEvents()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
index 27cd1b24ae..cbd14093c5 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewModel.kt
@@ -269,6 +269,7 @@ class RoomDetailViewModel @AssistedInject constructor(
is RoomDetailAction.SelectStickerAttachment -> handleSelectStickerAttachment()
is RoomDetailAction.OpenIntegrationManager -> handleOpenIntegrationManager()
is RoomDetailAction.StartCall -> handleStartCall(action)
+ is RoomDetailAction.AcceptCall -> handleAcceptCall(action)
is RoomDetailAction.EndCall -> handleEndCall()
is RoomDetailAction.ManageIntegrations -> handleManageIntegrations()
is RoomDetailAction.AddJitsiWidget -> handleAddJitsiConference(action)
@@ -289,6 +290,12 @@ class RoomDetailViewModel @AssistedInject constructor(
}.exhaustive
}
+ private fun handleAcceptCall(action: RoomDetailAction.AcceptCall) {
+ callManager.getCallById(action.callId)?.also {
+ _viewEvents.post(RoomDetailViewEvents.DisplayAndAcceptCall(it))
+ }
+ }
+
private fun handleSetNewAvatar(action: RoomDetailAction.SetAvatarAction) {
viewModelScope.launch(Dispatchers.IO) {
try {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
index 20fbe52731..4221bd5015 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
@@ -30,10 +30,12 @@ import im.vector.app.core.date.VectorDateFormatter
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.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.RoomDetailViewState
import im.vector.app.features.home.room.detail.UnreadState
import im.vector.app.features.home.room.detail.timeline.factory.MergedHeaderItemFactory
+import im.vector.app.features.home.room.detail.timeline.factory.NoticeItemFactory
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactory
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
@@ -47,6 +49,7 @@ import im.vector.app.features.home.room.detail.timeline.item.CallTileTimelineIte
import im.vector.app.features.home.room.detail.timeline.item.DaySeparatorItem
import im.vector.app.features.home.room.detail.timeline.item.DaySeparatorItem_
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
+import im.vector.app.features.home.room.detail.timeline.item.NoticeItemBuilder
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
import im.vector.app.features.home.room.detail.timeline.item.TimelineReadMarkerItem_
import im.vector.app.features.media.ImageContentRenderer
@@ -73,6 +76,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,
+ private val noticeItemFactory: NoticeItemFactory,
@TimelineEventControllerHandler
private val backgroundHandler: Handler
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener, EpoxyController.Interceptor {
@@ -187,12 +192,17 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
adapterPositionMapping.clear()
val callIds = mutableSetOf()
val modelsIterator = models.listIterator()
+ val showHiddenEvents = vectorPreferences.shouldShowHiddenEvents()
modelsIterator.withIndex().forEach {
val index = it.index
val epoxyModel = it.value
if (epoxyModel is CallTileTimelineItem) {
val callId = epoxyModel.attributes.callId
- if (callIds.contains(callId)) {
+ val call = callManager.getCallById(callId)
+ // We should remove the call tile if we already have one for this call or
+ // if this is an active call tile without an actual call (which can happen with permalink)
+ val shouldRemoveCallItem = callIds.contains(callId) || (call == null && epoxyModel.attributes.callStatus.isActive())
+ if (shouldRemoveCallItem && !showHiddenEvents) {
modelsIterator.remove()
return@forEach
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/CallItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/CallItemFactory.kt
index 36acf5d766..42f1542bf6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/CallItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/CallItemFactory.kt
@@ -63,25 +63,25 @@ class CallItemFactory @Inject constructor(
}
return when (event.root.getClearType()) {
EventType.CALL_ANSWER -> {
- if (call == null) return null
createCallTileTimelineItem(
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.IN_CALL,
callKind = callKind,
callback = callback,
highlight = highlight,
- informationData = informationData
+ informationData = informationData,
+ isStillActive = call != null
)
}
EventType.CALL_INVITE -> {
- if (call == null) return null
createCallTileTimelineItem(
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.INVITED,
callKind = callKind,
callback = callback,
highlight = highlight,
- informationData = informationData
+ informationData = informationData,
+ isStillActive = call != null
)
}
EventType.CALL_REJECT -> {
@@ -91,7 +91,8 @@ class CallItemFactory @Inject constructor(
callKind = callKind,
callback = callback,
highlight = highlight,
- informationData = informationData
+ informationData = informationData,
+ isStillActive = false
)
}
EventType.CALL_HANGUP -> {
@@ -101,7 +102,8 @@ class CallItemFactory @Inject constructor(
callKind = callKind,
callback = callback,
highlight = highlight,
- informationData = informationData
+ informationData = informationData,
+ isStillActive = false
)
}
else -> null
@@ -124,6 +126,7 @@ class CallItemFactory @Inject constructor(
callStatus: CallTileTimelineItem.CallStatus,
informationData: MessageInformationData,
highlight: Boolean,
+ isStillActive: Boolean,
callback: TimelineEventController.Callback?
): CallTileTimelineItem? {
@@ -140,7 +143,9 @@ class CallItemFactory @Inject constructor(
itemLongClickListener = it.itemLongClickListener,
reactionPillCallback = it.reactionPillCallback,
readReceiptsCallback = it.readReceiptsCallback,
- userOfInterest = userOfInterest
+ userOfInterest = userOfInterest,
+ callback = callback,
+ isStillActive = isStillActive
)
}
return CallTileTimelineItem_()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
index 85f093bfec..06fbb37c55 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/CallTileTimelineItem.kt
@@ -15,31 +15,26 @@
*/
package im.vector.app.features.home.room.detail.timeline.item
-import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
-import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
-import androidx.core.content.ContextCompat
-import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.extensions.setLeftDrawable
-import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.extensions.setTextWithColoredPart
import im.vector.app.features.home.AvatarRenderer
+import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import org.matrix.android.sdk.api.util.MatrixItem
-import timber.log.Timber
@EpoxyModelClass(layout = R.layout.item_timeline_event_base_state)
abstract class CallTileTimelineItem : AbsBaseMessageItem() {
@@ -62,14 +57,14 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem if (attributes.informationData.sentByMe) {
setText(R.string.call_tile_you_started_call)
+ }else {
+ text = context.getString(R.string.call_tile_other_started_call, attributes.userOfInterest.getBestName())
}
CallStatus.IN_CALL -> setText(R.string.call_tile_in_call)
CallStatus.REJECTED -> if (attributes.informationData.sentByMe) {
@@ -133,6 +130,8 @@ abstract class CallTileTimelineItem : AbsBaseMessageItemMatrix Link
You started a call
+ %1$s started a call
You\'re currently in this call
You declined this call %1$s
%1$s declined this call