mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Ask for permission before starting call
This commit is contained in:
parent
b27eead016
commit
25fe56116c
4 changed files with 63 additions and 17 deletions
|
@ -567,7 +567,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun startOutgoingCall(context: Context, signalingRoomId: String, otherUserId: String, isVideoCall: Boolean) {
|
||||
fun startOutgoingCall(signalingRoomId: String, otherUserId: String, isVideoCall: Boolean) {
|
||||
executor.execute {
|
||||
if (peerConnectionFactory == null) {
|
||||
createPeerConnectionFactory()
|
||||
|
@ -584,7 +584,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
val name = sessionHolder.getSafeActiveSession()?.getUser(createdCall.otherUserId)?.getBestName()
|
||||
?: createdCall.otherUserId
|
||||
CallService.onOutgoingCallRinging(
|
||||
context = context,
|
||||
context = context.applicationContext,
|
||||
isVideo = createdCall.isVideoCall,
|
||||
roomName = name,
|
||||
roomId = createdCall.roomId,
|
||||
|
@ -596,7 +596,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
}
|
||||
|
||||
// start the activity now
|
||||
context.startActivity(VectorCallActivity.newIntent(context, createdCall))
|
||||
context.applicationContext.startActivity(VectorCallActivity.newIntent(context, createdCall))
|
||||
}
|
||||
|
||||
override fun onCallIceCandidateReceived(mxCall: MxCall, iceCandidatesContent: CallCandidatesContent) {
|
||||
|
|
|
@ -68,7 +68,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
|||
|
||||
object ClearSendQueue : RoomDetailAction()
|
||||
object ResendAll : RoomDetailAction()
|
||||
object StartCall : RoomDetailAction()
|
||||
data class StartCall(val isVideo: Boolean) : RoomDetailAction()
|
||||
|
||||
data class AcceptVerificationRequest(val transactionId: String, val otherUserId: String) : RoomDetailAction()
|
||||
data class DeclineVerificationRequest(val transactionId: String, val otherUserId: String) : RoomDetailAction()
|
||||
|
|
|
@ -107,6 +107,8 @@ import im.vector.riotx.core.ui.views.JumpToReadMarkerView
|
|||
import im.vector.riotx.core.ui.views.NotificationAreaView
|
||||
import im.vector.riotx.core.utils.Debouncer
|
||||
import im.vector.riotx.core.utils.KeyboardStateUtils
|
||||
import im.vector.riotx.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
|
||||
import im.vector.riotx.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL
|
||||
import im.vector.riotx.core.utils.PERMISSIONS_FOR_WRITING_FILES
|
||||
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_DOWNLOAD_FILE
|
||||
import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_INCOMING_URI
|
||||
|
@ -120,6 +122,8 @@ import im.vector.riotx.core.utils.createJSonViewerStyleProvider
|
|||
import im.vector.riotx.core.utils.createUIHandler
|
||||
import im.vector.riotx.core.utils.getColorFromUserId
|
||||
import im.vector.riotx.core.utils.isValidUrl
|
||||
import im.vector.riotx.core.utils.onPermissionResultAudioIpCall
|
||||
import im.vector.riotx.core.utils.onPermissionResultVideoIpCall
|
||||
import im.vector.riotx.core.utils.openUrlInExternalBrowser
|
||||
import im.vector.riotx.core.utils.saveMedia
|
||||
import im.vector.riotx.core.utils.shareMedia
|
||||
|
@ -132,7 +136,6 @@ import im.vector.riotx.features.attachments.preview.AttachmentsPreviewArgs
|
|||
import im.vector.riotx.features.attachments.toGroupedContentAttachmentData
|
||||
import im.vector.riotx.features.call.SharedActiveCallViewModel
|
||||
import im.vector.riotx.features.call.VectorCallActivity
|
||||
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
|
||||
import im.vector.riotx.features.command.Command
|
||||
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreActivity
|
||||
import im.vector.riotx.features.crypto.util.toImageRes
|
||||
|
@ -202,8 +205,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
val roomDetailViewModelFactory: RoomDetailViewModel.Factory,
|
||||
private val eventHtmlRenderer: EventHtmlRenderer,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager) :
|
||||
private val colorProvider: ColorProvider) :
|
||||
VectorBaseFragment(),
|
||||
TimelineEventController.Callback,
|
||||
VectorInviteView.Callback,
|
||||
|
@ -215,6 +217,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
companion object {
|
||||
|
||||
private const val AUDIO_CALL_PERMISSION_REQUEST_CODE = 1
|
||||
private const val VIDEO_CALL_PERMISSION_REQUEST_CODE = 2
|
||||
|
||||
/**
|
||||
* Sanitize the display name.
|
||||
*
|
||||
|
@ -503,22 +508,22 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
R.id.voice_call,
|
||||
R.id.video_call -> {
|
||||
roomDetailViewModel.getOtherUserIds()?.firstOrNull()?.let {
|
||||
// TODO CALL We should check/ask for permission here first
|
||||
val activeCall = sharedCallActionViewModel.activeCall.value
|
||||
val isVideoCall = item.itemId == R.id.video_call
|
||||
if (activeCall != null) {
|
||||
// resume existing if same room, if not prompt to kill and then restart new call?
|
||||
if (activeCall.roomId == roomDetailArgs.roomId) {
|
||||
onTapToReturnToCall()
|
||||
} else {
|
||||
// TODO might not work well, and should prompt
|
||||
webRtcPeerConnectionManager.endCall()
|
||||
webRtcPeerConnectionManager.startOutgoingCall(requireContext(), roomDetailArgs.roomId, it, item.itemId == R.id.video_call)
|
||||
}
|
||||
// else {
|
||||
// TODO might not work well, and should prompt
|
||||
// webRtcPeerConnectionManager.endCall()
|
||||
// safeStartCall(it, isVideoCall)
|
||||
// }
|
||||
} else {
|
||||
webRtcPeerConnectionManager.startOutgoingCall(requireContext(), roomDetailArgs.roomId, it, item.itemId == R.id.video_call)
|
||||
safeStartCall(isVideoCall)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
|
@ -536,6 +541,22 @@ class RoomDetailFragment @Inject constructor(
|
|||
.show()
|
||||
}
|
||||
|
||||
private fun safeStartCall(isVideoCall: Boolean) {
|
||||
val startCallAction = RoomDetailAction.StartCall(isVideoCall)
|
||||
roomDetailViewModel.pendingAction = startCallAction
|
||||
if (isVideoCall) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, this, VIDEO_CALL_PERMISSION_REQUEST_CODE, R.string.permissions_rationale_msg_camera_and_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
} else {
|
||||
if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, this, AUDIO_CALL_PERMISSION_REQUEST_CODE, R.string.permissions_rationale_msg_record_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRegularMode(text: String) {
|
||||
autoCompleter.exitSpecialMode()
|
||||
composerLayout.collapse()
|
||||
|
@ -1130,6 +1151,22 @@ class RoomDetailFragment @Inject constructor(
|
|||
launchAttachmentProcess(pendingType)
|
||||
}
|
||||
}
|
||||
AUDIO_CALL_PERMISSION_REQUEST_CODE -> {
|
||||
if (onPermissionResultAudioIpCall(requireContext(), grantResults)) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
VIDEO_CALL_PERMISSION_REQUEST_CODE -> {
|
||||
if (onPermissionResultVideoIpCall(requireContext(), grantResults)) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reset all pending data
|
||||
|
|
|
@ -67,6 +67,7 @@ import im.vector.riotx.core.platform.VectorViewModel
|
|||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.core.resources.UserPreferencesProvider
|
||||
import im.vector.riotx.core.utils.subscribeLogError
|
||||
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
|
||||
import im.vector.riotx.features.command.CommandParser
|
||||
import im.vector.riotx.features.command.ParsedCommand
|
||||
import im.vector.riotx.features.crypto.verification.SupportedVerificationMethodsProvider
|
||||
|
@ -97,7 +98,8 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
private val rainbowGenerator: RainbowGenerator,
|
||||
private val session: Session,
|
||||
private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider,
|
||||
private val stickerPickerActionHandler: StickerPickerActionHandler
|
||||
private val stickerPickerActionHandler: StickerPickerActionHandler,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState), Timeline.Listener {
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
|
@ -255,13 +257,20 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
is RoomDetailAction.ResumeVerification -> handleResumeRequestVerification(action)
|
||||
is RoomDetailAction.ReRequestKeys -> handleReRequestKeys(action)
|
||||
is RoomDetailAction.SelectStickerAttachment -> handleSelectStickerAttachment()
|
||||
}
|
||||
is RoomDetailAction.StartCall -> handleStartCall(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSendSticker(action: RoomDetailAction.SendSticker) {
|
||||
room.sendEvent(EventType.STICKER, action.stickerContent.toContent())
|
||||
}
|
||||
|
||||
private fun handleStartCall(action: RoomDetailAction.StartCall) {
|
||||
room.roomSummary()?.otherMemberIds?.firstOrNull()?.let {
|
||||
webRtcPeerConnectionManager.startOutgoingCall(room.roomId, it, action.isVideo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSelectStickerAttachment() {
|
||||
viewModelScope.launch {
|
||||
val viewEvent = stickerPickerActionHandler.handle()
|
||||
|
@ -369,7 +378,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
fun isMenuItemVisible(@IdRes itemId: Int) = when (itemId) {
|
||||
R.id.clear_message_queue ->
|
||||
R.id.clear_message_queue ->
|
||||
// For now always disable when not in developer mode, worker cancellation is not working properly
|
||||
timeline.pendingEventCount() > 0 && vectorPreferences.developerMode()
|
||||
R.id.resend_all -> timeline.failedToDeliverEventCount() > 0
|
||||
|
|
Loading…
Reference in a new issue