Prevent launching multiple audio device dialogs during call.

This commit is contained in:
Nicholas
2023-05-03 16:14:30 -04:00
committed by Alex Hart
parent 855e194baa
commit ccdfa546b4
4 changed files with 26 additions and 10 deletions

View File

@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.components.webrtc package org.thoughtcrime.securesms.components.webrtc
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Bundle
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@@ -59,21 +58,26 @@ class WebRtcAudioOutputBottomSheet : ComposeBottomSheetDialogFragment(), DialogI
dismiss() dismiss()
} }
fun show(fm: FragmentManager, tag: String?, audioRoutes: List<AudioOutputOption>, selectedDeviceId: Int, onClick: (AudioOutputOption) -> Unit) { fun show(fm: FragmentManager, tag: String?, audioRoutes: List<AudioOutputOption>, selectedDeviceId: Int, onClick: (AudioOutputOption) -> Unit, onDismiss: (DialogInterface) -> Unit) {
super.showNow(fm, tag) super.showNow(fm, tag)
viewModel.audioRoutes = audioRoutes viewModel.audioRoutes = audioRoutes
viewModel.defaultDeviceId = selectedDeviceId viewModel.defaultDeviceId = selectedDeviceId
viewModel.onClick = onClick viewModel.onClick = onClick
viewModel.onDismiss = onDismiss
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
viewModel.onDismiss(dialog)
} }
companion object { companion object {
const val TAG = "WebRtcAudioOutputBottomSheet" const val TAG = "WebRtcAudioOutputBottomSheet"
@JvmStatic @JvmStatic
fun show(fragmentManager: FragmentManager, audioRoutes: List<AudioOutputOption>, selectedDeviceId: Int, onClick: (AudioOutputOption) -> Unit): WebRtcAudioOutputBottomSheet { fun show(fragmentManager: FragmentManager, audioRoutes: List<AudioOutputOption>, selectedDeviceId: Int, onClick: (AudioOutputOption) -> Unit, onDismiss: (DialogInterface) -> Unit): WebRtcAudioOutputBottomSheet {
val bottomSheet = WebRtcAudioOutputBottomSheet() val bottomSheet = WebRtcAudioOutputBottomSheet()
val args = Bundle() bottomSheet.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG, audioRoutes, selectedDeviceId, onClick, onDismiss)
bottomSheet.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG, audioRoutes, selectedDeviceId, onClick)
return bottomSheet return bottomSheet
} }
} }
@@ -134,6 +138,7 @@ class AudioOutputViewModel : ViewModel() {
var audioRoutes: List<AudioOutputOption> = emptyList() var audioRoutes: List<AudioOutputOption> = emptyList()
var defaultDeviceId: Int = -1 var defaultDeviceId: Int = -1
var onClick: (AudioOutputOption) -> Unit = {} var onClick: (AudioOutputOption) -> Unit = {}
var onDismiss: (DialogInterface) -> Unit = {}
} }
private fun getDrawableResourceForDeviceType(deviceType: SignalAudioManager.AudioDevice): Int { private fun getDrawableResourceForDeviceType(deviceType: SignalAudioManager.AudioDevice): Int {

View File

@@ -27,9 +27,14 @@ class WebRtcAudioOutputToggleButton @JvmOverloads constructor(context: Context,
private var picker: DialogInterface? = null private var picker: DialogInterface? = null
private val clickListenerLegacy: OnClickListener = OnClickListener { private val clickListenerLegacy: OnClickListener = OnClickListener {
if (picker != null) {
Log.d(TAG, "Tried to launch new audio device picker but one is already present.")
return@OnClickListener
}
val outputs = outputState.getOutputs() val outputs = outputState.getOutputs()
if (outputs.size >= SHOW_PICKER_THRESHOLD || !outputState.isEarpieceAvailable) { if (outputs.size >= SHOW_PICKER_THRESHOLD || !outputState.isEarpieceAvailable) {
picker = WebRtcAudioPickerLegacy(audioOutputChangedListener, outputState, this).showPicker(context, outputs) picker = WebRtcAudioPickerLegacy(audioOutputChangedListener, outputState, this).showPicker(context, outputs) { picker = null }
} else { } else {
val audioOutput = outputState.peekNext() val audioOutput = outputState.peekNext()
audioOutputChangedListener.audioOutputChanged(WebRtcAudioDevice(audioOutput, null)) audioOutputChangedListener.audioOutputChanged(WebRtcAudioDevice(audioOutput, null))
@@ -39,9 +44,14 @@ class WebRtcAudioOutputToggleButton @JvmOverloads constructor(context: Context,
@RequiresApi(31) @RequiresApi(31)
private val clickListener31 = OnClickListener { private val clickListener31 = OnClickListener {
if (picker != null) {
Log.d(TAG, "Tried to launch new audio device picker but one is already present.")
return@OnClickListener
}
val fragmentActivity = context.fragmentActivity() val fragmentActivity = context.fragmentActivity()
if (fragmentActivity != null) { if (fragmentActivity != null) {
picker = WebRtcAudioPicker31(audioOutputChangedListener, outputState, this).showPicker(fragmentActivity, SHOW_PICKER_THRESHOLD) picker = WebRtcAudioPicker31(audioOutputChangedListener, outputState, this).showPicker(fragmentActivity, SHOW_PICKER_THRESHOLD) { picker = null }
} else { } else {
Log.e(TAG, "WebRtcAudioOutputToggleButton instantiated from a context that does not inherit from FragmentActivity.") Log.e(TAG, "WebRtcAudioOutputToggleButton instantiated from a context that does not inherit from FragmentActivity.")
Toast.makeText(context, R.string.WebRtcAudioOutputToggleButton_fragment_activity_error, Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.WebRtcAudioOutputToggleButton_fragment_activity_error, Toast.LENGTH_LONG).show()

View File

@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager
@RequiresApi(31) @RequiresApi(31)
class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputChangedListener, private val outputState: ToggleButtonOutputState, private val stateUpdater: AudioStateUpdater) { class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputChangedListener, private val outputState: ToggleButtonOutputState, private val stateUpdater: AudioStateUpdater) {
fun showPicker(fragmentActivity: FragmentActivity, threshold: Int): DialogInterface? { fun showPicker(fragmentActivity: FragmentActivity, threshold: Int, onDismiss: (DialogInterface) -> Unit): DialogInterface? {
val am = ApplicationDependencies.getAndroidCallAudioManager() val am = ApplicationDependencies.getAndroidCallAudioManager()
if (am.availableCommunicationDevices.isEmpty()) { if (am.availableCommunicationDevices.isEmpty()) {
Toast.makeText(fragmentActivity, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show() Toast.makeText(fragmentActivity, R.string.WebRtcAudioOutputToggleButton_no_eligible_audio_i_o_detected, Toast.LENGTH_LONG).show()
@@ -36,7 +36,7 @@ class WebRtcAudioPicker31(private val audioOutputChangedListener: OnAudioOutputC
onAudioDeviceSelected(devices[(index + 1) % devices.size]) onAudioDeviceSelected(devices[(index + 1) % devices.size])
return null return null
} else { } else {
return WebRtcAudioOutputBottomSheet.show(fragmentActivity.supportFragmentManager, devices, currentDeviceId, onAudioDeviceSelected) return WebRtcAudioOutputBottomSheet.show(fragmentActivity.supportFragmentManager, devices, currentDeviceId, onAudioDeviceSelected, onDismiss)
} }
} }

View File

@@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.R
*/ */
class WebRtcAudioPickerLegacy(private val audioOutputChangedListener: OnAudioOutputChangedListener, private val outputState: ToggleButtonOutputState, private val stateUpdater: AudioStateUpdater) { class WebRtcAudioPickerLegacy(private val audioOutputChangedListener: OnAudioOutputChangedListener, private val outputState: ToggleButtonOutputState, private val stateUpdater: AudioStateUpdater) {
fun showPicker(context: Context, availableModes: List<WebRtcAudioOutput?>): DialogInterface? { fun showPicker(context: Context, availableModes: List<WebRtcAudioOutput?>, dismissListener: DialogInterface.OnDismissListener): DialogInterface? {
val rv = RecyclerView(context) val rv = RecyclerView(context)
val adapter = AudioOutputAdapter( val adapter = AudioOutputAdapter(
fun(audioDevice: WebRtcAudioDevice) { fun(audioDevice: WebRtcAudioDevice) {
@@ -30,6 +30,7 @@ class WebRtcAudioPickerLegacy(private val audioOutputChangedListener: OnAudioOut
.setTitle(R.string.WebRtcAudioOutputToggle__audio_output) .setTitle(R.string.WebRtcAudioOutputToggle__audio_output)
.setView(rv) .setView(rv)
.setCancelable(true) .setCancelable(true)
.setOnDismissListener(dismissListener)
.show() .show()
} }
} }