mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-03 04:27:35 +01:00
DialPad: show dialerchoice dialog when supported
This commit is contained in:
parent
14502573bf
commit
1f96367286
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.call
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
|
||||
import im.vector.app.databinding.BottomSheetCallDialerChoiceBinding
|
||||
|
||||
class DialerChoiceBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetCallDialerChoiceBinding>() {
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): BottomSheetCallDialerChoiceBinding {
|
||||
return BottomSheetCallDialerChoiceBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
var onDialPadClicked: (() ->Unit)? = null
|
||||
var onVoiceCallClicked: (() ->Unit)? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
views.dialerChoiceDialPad.views.itemVerificationClickableZone.debouncedClicks {
|
||||
onDialPadClicked?.invoke()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
views.dialerChoiceVoiceCall.views.itemVerificationClickableZone.debouncedClicks {
|
||||
onVoiceCallClicked?.invoke()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onDialPadClicked()
|
||||
fun onVoiceCallClicked()
|
||||
}
|
||||
}
|
@ -29,8 +29,8 @@ class DialPadLookup(val session: Session,
|
||||
class Failure : Throwable()
|
||||
data class Result(val userId: String, val roomId: String)
|
||||
|
||||
suspend fun lookupPhoneNumber(phoneNumber: String): Result? {
|
||||
val supportedProtocolKey = callManager.supportedPSTNProtocol ?: return null
|
||||
suspend fun lookupPhoneNumber(phoneNumber: String): Result {
|
||||
val supportedProtocolKey = callManager.supportedPSTNProtocol ?: throw Failure()
|
||||
val thirdPartyUser = tryOrNull {
|
||||
session.getThirdPartyUser(supportedProtocolKey, fields = mapOf(
|
||||
"m.id.phone" to phoneNumber
|
||||
|
@ -265,6 +265,19 @@ class RoomDetailFragment @Inject constructor(
|
||||
pillsPostProcessorFactory.create(roomDetailArgs.roomId)
|
||||
}
|
||||
|
||||
private val callActionsHandler by lazy {
|
||||
StartCallActionsHandler(
|
||||
roomId = roomDetailArgs.roomId,
|
||||
fragment = this,
|
||||
vectorPreferences = vectorPreferences,
|
||||
roomDetailViewModel = roomDetailViewModel,
|
||||
sharedActiveCallViewModel = sharedCallActionViewModel,
|
||||
startCallActivityResultLauncher = startCallActivityResultLauncher,
|
||||
showDialogWithMessage = ::showDialogWithMessage,
|
||||
onTapToReturnToCall = ::onTapToReturnToCall
|
||||
)
|
||||
}
|
||||
|
||||
private val autoCompleter: AutoCompleter by lazy {
|
||||
autoCompleterFactory.create(roomDetailArgs.roomId)
|
||||
}
|
||||
@ -759,9 +772,12 @@ class RoomDetailFragment @Inject constructor(
|
||||
roomDetailViewModel.handle(RoomDetailAction.ManageIntegrations)
|
||||
true
|
||||
}
|
||||
R.id.voice_call,
|
||||
R.id.voice_call -> {
|
||||
callActionsHandler.onVoiceCallClicked()
|
||||
true
|
||||
}
|
||||
R.id.video_call -> {
|
||||
handleCallRequest(item)
|
||||
callActionsHandler.onVideoCallClicked()
|
||||
true
|
||||
}
|
||||
R.id.hangup_call -> {
|
||||
@ -784,76 +800,6 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCallRequest(item: MenuItem) = withState(roomDetailViewModel) { state ->
|
||||
val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState
|
||||
val isVideoCall = item.itemId == R.id.video_call
|
||||
when (roomSummary.joinedMembersCount) {
|
||||
1 -> {
|
||||
val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0
|
||||
if (pendingInvite) {
|
||||
// wait for other to join
|
||||
showDialogWithMessage(getString(R.string.cannot_call_yourself_with_invite))
|
||||
} else {
|
||||
// You cannot place a call with yourself.
|
||||
showDialogWithMessage(getString(R.string.cannot_call_yourself))
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
val activeCall = sharedCallActionViewModel.activeCall.value
|
||||
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()
|
||||
// safeStartCall(it, isVideoCall)
|
||||
// }
|
||||
} else if (!state.isAllowedToStartWebRTCCall) {
|
||||
showDialogWithMessage(getString(
|
||||
if (state.isDm()) {
|
||||
R.string.no_permissions_to_start_webrtc_call_in_direct_room
|
||||
} else {
|
||||
R.string.no_permissions_to_start_webrtc_call
|
||||
})
|
||||
)
|
||||
} else {
|
||||
safeStartCall(isVideoCall)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// it's jitsi call
|
||||
// can you add widgets??
|
||||
if (!state.isAllowedToManageWidgets) {
|
||||
// You do not have permission to start a conference call in this room
|
||||
showDialogWithMessage(getString(
|
||||
if (state.isDm()) {
|
||||
R.string.no_permissions_to_start_conf_call_in_direct_room
|
||||
} else {
|
||||
R.string.no_permissions_to_start_conf_call
|
||||
}
|
||||
))
|
||||
} else {
|
||||
if (state.activeRoomWidgets()?.filter { it.type == WidgetType.Jitsi }?.any() == true) {
|
||||
// A conference is already in progress!
|
||||
showDialogWithMessage(getString(R.string.conference_call_in_progress))
|
||||
} else {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(if (isVideoCall) R.string.video_meeting else R.string.audio_meeting)
|
||||
.setMessage(R.string.audio_video_meeting_description)
|
||||
.setPositiveButton(getString(R.string.create)) { _, _ ->
|
||||
// create the widget, then navigate to it..
|
||||
roomDetailViewModel.handle(RoomDetailAction.AddJitsiWidget(isVideoCall))
|
||||
}
|
||||
.setNegativeButton(getString(R.string.cancel), null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayDisabledIntegrationDialog() {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.disabled_integration_dialog_title)
|
||||
@ -865,54 +811,6 @@ class RoomDetailFragment @Inject constructor(
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun safeStartCall(isVideoCall: Boolean) {
|
||||
if (vectorPreferences.preventAccidentalCall()) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setMessage(if (isVideoCall) R.string.start_video_call_prompt_msg else R.string.start_voice_call_prompt_msg)
|
||||
.setPositiveButton(if (isVideoCall) R.string.start_video_call else R.string.start_voice_call) { _, _ ->
|
||||
safeStartCall2(isVideoCall)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
} else {
|
||||
safeStartCall2(isVideoCall)
|
||||
}
|
||||
}
|
||||
|
||||
private val startCallActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
} else {
|
||||
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}
|
||||
|
||||
private fun safeStartCall2(isVideoCall: Boolean) {
|
||||
val startCallAction = RoomDetailAction.StartCall(isVideoCall)
|
||||
roomDetailViewModel.pendingAction = startCallAction
|
||||
if (isVideoCall) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL,
|
||||
requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_camera_and_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
} else {
|
||||
if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL,
|
||||
requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_record_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRegularMode(text: String) {
|
||||
autoCompleter.exitSpecialMode()
|
||||
views.composerLayout.collapse()
|
||||
@ -1052,6 +950,18 @@ class RoomDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val startCallActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
} else {
|
||||
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}
|
||||
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
|
@ -119,7 +119,8 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
private val chatEffectManager: ChatEffectManager,
|
||||
private val directRoomHelper: DirectRoomHelper,
|
||||
timelineSettingsFactory: TimelineSettingsFactory
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState), Timeline.Listener, ChatEffectManager.Delegate {
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState),
|
||||
Timeline.Listener, ChatEffectManager.Delegate, WebRtcCallManager.PSTNSupportListener {
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
private val eventId = initialState.eventId
|
||||
@ -169,11 +170,13 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
observeMyRoomMember()
|
||||
observeActiveRoomWidgets()
|
||||
observePowerLevel()
|
||||
updateShowDialerOptionState()
|
||||
room.getRoomSummaryLive()
|
||||
room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT, NoOpMatrixCallback())
|
||||
room.rx().loadRoomMembersIfNeeded().subscribeLogError().disposeOnClear()
|
||||
// Inform the SDK that the room is displayed
|
||||
session.onRoomDisplayed(initialState.roomId)
|
||||
callManager.addPstnSupportListener(this)
|
||||
chatEffectManager.delegate = this
|
||||
}
|
||||
|
||||
@ -294,7 +297,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
private fun handleStartCallWithPhoneNumber(action: RoomDetailAction.StartCallWithPhoneNumber) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = DialPadLookup(session, directRoomHelper, callManager).lookupPhoneNumber(action.phoneNumber) ?: return@launch
|
||||
val result = DialPadLookup(session, directRoomHelper, callManager).lookupPhoneNumber(action.phoneNumber)
|
||||
callManager.startOutgoingCall(result.roomId, result.userId, action.videoCall)
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(RoomDetailViewEvents.ActionFailure(action, failure))
|
||||
@ -1431,6 +1434,16 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
_viewEvents.post(RoomDetailViewEvents.OnNewTimelineEvents(eventIds))
|
||||
}
|
||||
|
||||
override fun onPSTNSupportUpdated() {
|
||||
updateShowDialerOptionState()
|
||||
}
|
||||
|
||||
private fun updateShowDialerOptionState(){
|
||||
setState {
|
||||
copy(showDialerOption = callManager.supportsPSTNProtocol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
roomSummaryHolder.clear()
|
||||
timeline.dispose()
|
||||
@ -1440,6 +1453,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||
}
|
||||
chatEffectManager.delegate = null
|
||||
chatEffectManager.dispose()
|
||||
callManager.removePstnSupportListener(this)
|
||||
super.onCleared()
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,8 @@ data class RoomDetailViewState(
|
||||
val canSendMessage: Boolean = true,
|
||||
val canInvite: Boolean = true,
|
||||
val isAllowedToManageWidgets: Boolean = false,
|
||||
val isAllowedToStartWebRTCCall: Boolean = true
|
||||
val isAllowedToStartWebRTCCall: Boolean = true,
|
||||
val showDialerOption: Boolean = false
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomDetailArgs) : this(
|
||||
|
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.call.DialerChoiceBottomSheet
|
||||
import im.vector.app.features.call.SharedActiveCallViewModel
|
||||
import im.vector.app.features.call.dialpad.CallDialPadBottomSheet
|
||||
import im.vector.app.features.call.dialpad.DialPadFragment
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
|
||||
class StartCallActionsHandler(
|
||||
private val roomId: String,
|
||||
private val fragment: RoomDetailFragment,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val roomDetailViewModel: RoomDetailViewModel,
|
||||
private val sharedActiveCallViewModel: SharedActiveCallViewModel,
|
||||
private val startCallActivityResultLauncher: ActivityResultLauncher<Array<String>>,
|
||||
private val showDialogWithMessage: (String) -> Unit,
|
||||
private val onTapToReturnToCall: () -> Unit) {
|
||||
|
||||
fun onVideoCallClicked() {
|
||||
handleCallRequest(true)
|
||||
}
|
||||
|
||||
fun onVoiceCallClicked() = withState(roomDetailViewModel) {
|
||||
if (it.showDialerOption) {
|
||||
displayDialerChoiceBottomSheet()
|
||||
} else {
|
||||
handleCallRequest(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayDialerChoiceBottomSheet() {
|
||||
DialerChoiceBottomSheet().apply {
|
||||
onDialPadClicked = ::displayDialPadBottomSheet
|
||||
onVoiceCallClicked = { handleCallRequest(false) }
|
||||
}.show(fragment.parentFragmentManager, "DIALER_OPTION")
|
||||
}
|
||||
|
||||
private fun displayDialPadBottomSheet() {
|
||||
CallDialPadBottomSheet.newInstance(true).apply {
|
||||
callback = object : DialPadFragment.Callback {
|
||||
override fun onOkClicked(formatted: String?, raw: String?) {
|
||||
if (raw.isNullOrEmpty()) return
|
||||
roomDetailViewModel.handle(RoomDetailAction.StartCallWithPhoneNumber(raw, false))
|
||||
}
|
||||
}
|
||||
}.show(fragment.parentFragmentManager, "DIAL_PAD")
|
||||
}
|
||||
|
||||
private fun handleCallRequest(isVideoCall: Boolean) = withState(roomDetailViewModel) { state ->
|
||||
val roomSummary = state.asyncRoomSummary.invoke() ?: return@withState
|
||||
when (roomSummary.joinedMembersCount) {
|
||||
1 -> {
|
||||
val pendingInvite = roomSummary.invitedMembersCount ?: 0 > 0
|
||||
if (pendingInvite) {
|
||||
// wait for other to join
|
||||
showDialogWithMessage(fragment.getString(R.string.cannot_call_yourself_with_invite))
|
||||
} else {
|
||||
// You cannot place a call with yourself.
|
||||
showDialogWithMessage(fragment.getString(R.string.cannot_call_yourself))
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
val activeCall = sharedActiveCallViewModel.activeCall.value
|
||||
if (activeCall != null) {
|
||||
// resume existing if same room, if not prompt to kill and then restart new call?
|
||||
if (activeCall.roomId == roomId) {
|
||||
onTapToReturnToCall()
|
||||
}
|
||||
// else {
|
||||
// TODO might not work well, and should prompt
|
||||
// webRtcPeerConnectionManager.endCall()
|
||||
// safeStartCall(it, isVideoCall)
|
||||
// }
|
||||
} else if (!state.isAllowedToStartWebRTCCall) {
|
||||
showDialogWithMessage(fragment.getString(
|
||||
if (state.isDm()) {
|
||||
R.string.no_permissions_to_start_webrtc_call_in_direct_room
|
||||
} else {
|
||||
R.string.no_permissions_to_start_webrtc_call
|
||||
})
|
||||
)
|
||||
} else {
|
||||
safeStartCall(isVideoCall)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// it's jitsi call
|
||||
// can you add widgets??
|
||||
if (!state.isAllowedToManageWidgets) {
|
||||
// You do not have permission to start a conference call in this room
|
||||
showDialogWithMessage(fragment.getString(
|
||||
if (state.isDm()) {
|
||||
R.string.no_permissions_to_start_conf_call_in_direct_room
|
||||
} else {
|
||||
R.string.no_permissions_to_start_conf_call
|
||||
}
|
||||
))
|
||||
} else {
|
||||
if (state.activeRoomWidgets()?.filter { it.type == WidgetType.Jitsi }?.any() == true) {
|
||||
// A conference is already in progress!
|
||||
showDialogWithMessage(fragment.getString(R.string.conference_call_in_progress))
|
||||
} else {
|
||||
AlertDialog.Builder(fragment.requireContext())
|
||||
.setTitle(if (isVideoCall) R.string.video_meeting else R.string.audio_meeting)
|
||||
.setMessage(R.string.audio_video_meeting_description)
|
||||
.setPositiveButton(fragment.getString(R.string.create)) { _, _ ->
|
||||
// create the widget, then navigate to it..
|
||||
roomDetailViewModel.handle(RoomDetailAction.AddJitsiWidget(isVideoCall))
|
||||
}
|
||||
.setNegativeButton(fragment.getString(R.string.cancel), null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun safeStartCall(isVideoCall: Boolean) {
|
||||
if (vectorPreferences.preventAccidentalCall()) {
|
||||
AlertDialog.Builder(fragment.requireActivity())
|
||||
.setMessage(if (isVideoCall) R.string.start_video_call_prompt_msg else R.string.start_voice_call_prompt_msg)
|
||||
.setPositiveButton(if (isVideoCall) R.string.start_video_call else R.string.start_voice_call) { _, _ ->
|
||||
safeStartCall2(isVideoCall)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
} else {
|
||||
safeStartCall2(isVideoCall)
|
||||
}
|
||||
}
|
||||
|
||||
private fun safeStartCall2(isVideoCall: Boolean) {
|
||||
val startCallAction = RoomDetailAction.StartCall(isVideoCall)
|
||||
roomDetailViewModel.pendingAction = startCallAction
|
||||
if (isVideoCall) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL,
|
||||
fragment.requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_camera_and_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
} else {
|
||||
if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL,
|
||||
fragment.requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_record_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
app:actionTitle="@string/call_select_sound_device"
|
||||
app:leftIcon="@drawable/ic_call_speaker_default"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary"
|
||||
tools:actionDescription="Speaker" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
@ -24,6 +25,7 @@
|
||||
app:actionTitle="@string/call_switch_camera"
|
||||
app:leftIcon="@drawable/ic_video_flip"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary"
|
||||
tools:actionDescription="Front" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
@ -33,6 +35,7 @@
|
||||
app:actionTitle="@string/call_dial_pad_title"
|
||||
app:leftIcon="@drawable/ic_call_dial_pad"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary"
|
||||
tools:actionDescription="" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
@ -42,6 +45,7 @@
|
||||
app:actionTitle="@string/call_format_turn_hd_on"
|
||||
app:leftIcon="@drawable/ic_hd"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary"
|
||||
tools:actionDescription="Front" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
@ -51,6 +55,7 @@
|
||||
app:actionTitle="Hold/resume"
|
||||
app:leftIcon="@drawable/ic_call_hold_action"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary"
|
||||
tools:actionDescription="" />
|
||||
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/callControlsWrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_bottom_sheet_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
android:id="@+id/dialerChoiceDialPad"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:actionTitle="@string/call_dial_pad_title"
|
||||
app:leftIcon="@drawable/ic_call_dial_pad"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary" />
|
||||
|
||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||
android:id="@+id/dialerChoiceVoiceCall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:actionTitle="@string/action_voice_call"
|
||||
app:leftIcon="@drawable/ic_call_answer"
|
||||
app:tint="?attr/riotx_text_primary"
|
||||
app:titleTextColor="?attr/riotx_text_primary" />
|
||||
|
||||
|
||||
</LinearLayout>
|
Loading…
x
Reference in New Issue
Block a user