mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-27 12:00:03 +03:00
VoIP: continue working on call tiles in timeline (add actions)
This commit is contained in:
parent
24de6c0101
commit
139c3fdd19
11 changed files with 65 additions and 22 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<String>()
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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_()
|
||||
|
|
|
@ -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<CallTileTimelineItem.Holder>() {
|
||||
|
@ -62,14 +57,14 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
attributes.avatarRenderer.render(attributes.userOfInterest, holder.creatorAvatarView)
|
||||
holder.callKindView.setText(attributes.callKind.title)
|
||||
holder.callKindView.setLeftDrawable(attributes.callKind.icon)
|
||||
if (attributes.callStatus == CallStatus.INVITED && !attributes.informationData.sentByMe) {
|
||||
if (attributes.callStatus == CallStatus.INVITED && !attributes.informationData.sentByMe && attributes.isStillActive) {
|
||||
holder.acceptRejectViewGroup.isVisible = true
|
||||
holder.acceptView.setOnClickListener {
|
||||
Timber.v("On accept call: $attributes.callId ")
|
||||
attributes.callback?.onTimelineItemAction(RoomDetailAction.AcceptCall(callId = attributes.callId))
|
||||
}
|
||||
holder.rejectView.setLeftDrawable(R.drawable.ic_call_hangup, R.color.riotx_notice)
|
||||
holder.rejectView.setOnClickListener {
|
||||
Timber.v("On reject call: $attributes.callId")
|
||||
attributes.callback?.onTimelineItemAction(RoomDetailAction.EndCall)
|
||||
}
|
||||
holder.statusView.isVisible = false
|
||||
when (attributes.callKind) {
|
||||
|
@ -101,6 +96,8 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
when (attributes.callStatus) {
|
||||
CallStatus.INVITED -> 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 : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
val callKind: CallKind,
|
||||
val callStatus: CallStatus,
|
||||
val userOfInterest: MatrixItem,
|
||||
val isStillActive: Boolean,
|
||||
val callback: TimelineEventController.Callback? = null,
|
||||
override val informationData: MessageInformationData,
|
||||
override val avatarRenderer: AvatarRenderer,
|
||||
override val messageColorProvider: MessageColorProvider,
|
||||
|
@ -152,6 +151,8 @@ abstract class CallTileTimelineItem : AbsBaseMessageItem<CallTileTimelineItem.Ho
|
|||
INVITED,
|
||||
IN_CALL,
|
||||
REJECTED,
|
||||
ENDED
|
||||
ENDED;
|
||||
|
||||
fun isActive() = this == INVITED || this == IN_CALL
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2749,6 +2749,7 @@
|
|||
<string name="matrix_to_card_title">Matrix Link</string>
|
||||
|
||||
<string name="call_tile_you_started_call">You started a call</string>
|
||||
<string name="call_tile_other_started_call">%1$s started a call</string>
|
||||
<string name="call_tile_in_call">You\'re currently in this call</string>
|
||||
<string name="call_tile_you_declined">You declined this call %1$s</string>
|
||||
<string name="call_tile_other_declined">%1$s declined this call</string>
|
||||
|
|
Loading…
Reference in a new issue