Fix camera-first qr scans.

This commit is contained in:
Michelle Tang 2024-06-07 09:58:14 -07:00 committed by Alex Hart
parent 7086709082
commit baaad0e475
6 changed files with 40 additions and 17 deletions

View file

@ -88,7 +88,7 @@ class LinkDeviceFragment : ComposeFragment() {
Scaffolds.Settings( Scaffolds.Settings(
title = stringResource(id = R.string.preferences__linked_devices), title = stringResource(id = R.string.preferences__linked_devices),
onNavigationClick = { navController.popBackStack() }, onNavigationClick = { findNavController().popOrFinish() },
navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24), navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24),
navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close) navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
) { contentPadding: PaddingValues -> ) { contentPadding: PaddingValues ->
@ -103,6 +103,12 @@ class LinkDeviceFragment : ComposeFragment() {
) )
} }
} }
private fun NavController.popOrFinish() {
if (!popBackStack()) {
requireActivity().finishAfterTransition()
}
}
} }
@Composable @Composable
@ -117,7 +123,7 @@ fun DeviceDescriptionScreen(
) { ) {
if (state.progressDialogMessage != -1) { if (state.progressDialogMessage != -1) {
if (navController?.currentDestination?.id == R.id.linkDeviceFinishedSheet) { if (navController?.currentDestination?.id == R.id.linkDeviceFinishedSheet) {
navController?.popBackStack() navController.popBackStack()
} }
Dialogs.IndeterminateProgressDialog(stringResource(id = state.progressDialogMessage)) Dialogs.IndeterminateProgressDialog(stringResource(id = state.progressDialogMessage))
} }

View file

@ -166,7 +166,8 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment {
this.controlsContainer = view.findViewById(R.id.camerax_controls_container); this.controlsContainer = view.findViewById(R.id.camerax_controls_container);
this.cameraXModePolicy = CameraXModePolicy.acquire(requireContext(), this.cameraXModePolicy = CameraXModePolicy.acquire(requireContext(),
controller.getMediaConstraints(), controller.getMediaConstraints(),
requireArguments().getBoolean(IS_VIDEO_ENABLED, true)); requireArguments().getBoolean(IS_VIDEO_ENABLED, true),
requireArguments().getBoolean(IS_QR_SCAN_ENABLED, false));
this.missingPermissionsContainer = view.findViewById(R.id.missing_permissions_container); this.missingPermissionsContainer = view.findViewById(R.id.missing_permissions_container);
this.missingPermissionsText = view.findViewById(R.id.missing_permissions_text); this.missingPermissionsText = view.findViewById(R.id.missing_permissions_text);
this.allowAccessButton = view.findViewById(R.id.allow_access_button); this.allowAccessButton = view.findViewById(R.id.allow_access_button);

View file

@ -15,8 +15,18 @@ sealed class CameraXModePolicy {
abstract val isVideoSupported: Boolean abstract val isVideoSupported: Boolean
abstract val isQrScanEnabled: Boolean
abstract fun initialize(cameraController: CameraXController) abstract fun initialize(cameraController: CameraXController)
open fun initialize(cameraController: CameraXController, useCaseFlags: Int) {
if (isQrScanEnabled) {
cameraController.setEnabledUseCases(useCaseFlags or CameraController.IMAGE_ANALYSIS)
} else {
cameraController.setEnabledUseCases(useCaseFlags)
}
}
open fun setToImage(cameraController: CameraXController) = Unit open fun setToImage(cameraController: CameraXController) = Unit
open fun setToVideo(cameraController: CameraXController) = Unit open fun setToVideo(cameraController: CameraXController) = Unit
@ -24,19 +34,19 @@ sealed class CameraXModePolicy {
/** /**
* The device supports having Image and Video enabled at the same time * The device supports having Image and Video enabled at the same time
*/ */
object Mixed : CameraXModePolicy() { data class Mixed(override val isQrScanEnabled: Boolean) : CameraXModePolicy() {
override val isVideoSupported: Boolean = true override val isVideoSupported: Boolean = true
override fun initialize(cameraController: CameraXController) { override fun initialize(cameraController: CameraXController) {
cameraController.setEnabledUseCases(CameraController.IMAGE_CAPTURE or CameraController.VIDEO_CAPTURE) super.initialize(cameraController, CameraController.IMAGE_CAPTURE or CameraController.VIDEO_CAPTURE)
} }
} }
/** /**
* The device supports image and video, but only one mode at a time. * The device supports image and video, but only one mode at a time.
*/ */
object Single : CameraXModePolicy() { data class Single(override val isQrScanEnabled: Boolean) : CameraXModePolicy() {
override val isVideoSupported: Boolean = true override val isVideoSupported: Boolean = true
@ -45,29 +55,29 @@ sealed class CameraXModePolicy {
} }
override fun setToImage(cameraController: CameraXController) { override fun setToImage(cameraController: CameraXController) {
cameraController.setEnabledUseCases(CameraController.IMAGE_CAPTURE) super.initialize(cameraController, CameraController.IMAGE_CAPTURE)
} }
override fun setToVideo(cameraController: CameraXController) { override fun setToVideo(cameraController: CameraXController) {
cameraController.setEnabledUseCases(CameraController.VIDEO_CAPTURE) super.initialize(cameraController, CameraController.VIDEO_CAPTURE)
} }
} }
/** /**
* The device supports taking images only. * The device supports taking images only.
*/ */
object ImageOnly : CameraXModePolicy() { data class ImageOnly(override val isQrScanEnabled: Boolean) : CameraXModePolicy() {
override val isVideoSupported: Boolean = false override val isVideoSupported: Boolean = false
override fun initialize(cameraController: CameraXController) { override fun initialize(cameraController: CameraXController) {
cameraController.setEnabledUseCases(CameraController.IMAGE_CAPTURE) super.initialize(cameraController, CameraController.IMAGE_CAPTURE)
} }
} }
companion object { companion object {
@JvmStatic @JvmStatic
fun acquire(context: Context, mediaConstraints: MediaConstraints, isVideoEnabled: Boolean): CameraXModePolicy { fun acquire(context: Context, mediaConstraints: MediaConstraints, isVideoEnabled: Boolean, isQrScanEnabled: Boolean): CameraXModePolicy {
val isVideoSupported = Build.VERSION.SDK_INT >= 26 && val isVideoSupported = Build.VERSION.SDK_INT >= 26 &&
isVideoEnabled && isVideoEnabled &&
MediaConstraints.isVideoTranscodeAvailable() && MediaConstraints.isVideoTranscodeAvailable() &&
@ -79,9 +89,9 @@ sealed class CameraXModePolicy {
!FeatureFlags.cameraXMixedModelBlocklist().asListContains(Build.MODEL) !FeatureFlags.cameraXMixedModelBlocklist().asListContains(Build.MODEL)
return when { return when {
isMixedModeSupported -> Mixed isMixedModeSupported -> Mixed(isQrScanEnabled)
isVideoSupported -> Single isVideoSupported -> Single(isQrScanEnabled)
else -> ImageOnly else -> ImageOnly(isQrScanEnabled)
} }
} }
} }

View file

@ -14,6 +14,7 @@ import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.DeviceActivity import org.thoughtcrime.securesms.DeviceActivity
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.mediasend.CameraFragment import org.thoughtcrime.securesms.mediasend.CameraFragment
import org.thoughtcrime.securesms.mediasend.Media import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.v2.HudCommand import org.thoughtcrime.securesms.mediasend.v2.HudCommand
@ -23,6 +24,7 @@ import org.thoughtcrime.securesms.mms.MediaConstraints
import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.stories.Stories import org.thoughtcrime.securesms.stories.Stories
import org.thoughtcrime.securesms.util.CommunicationActions import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
import java.io.FileDescriptor import java.io.FileDescriptor
import java.util.Optional import java.util.Optional
@ -92,7 +94,11 @@ class MediaCaptureFragment : Fragment(R.layout.fragment_container), CameraFragme
.setTitle(R.string.MediaCaptureFragment_device_link_dialog_title) .setTitle(R.string.MediaCaptureFragment_device_link_dialog_title)
.setMessage(R.string.MediaCaptureFragment_device_link_dialog_body) .setMessage(R.string.MediaCaptureFragment_device_link_dialog_body)
.setPositiveButton(R.string.MediaCaptureFragment_device_link_dialog_continue) { d, _ -> .setPositiveButton(R.string.MediaCaptureFragment_device_link_dialog_continue) { d, _ ->
startActivity(DeviceActivity.getIntentForScanner(requireContext())) if (FeatureFlags.linkedDevicesV2()) {
startActivity(AppSettingsActivity.linkedDevices(requireContext()))
} else {
startActivity(DeviceActivity.getIntentForScanner(requireContext()))
}
requireActivity().finish() requireActivity().finish()
} }
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)

View file

@ -591,7 +591,7 @@
<action <action
android:id="@+id/action_direct_to_devices" android:id="@+id/action_direct_to_devices"
app:destination="@id/deviceActivity" app:destination="@id/linkDeviceFragment"
app:enterAnim="@anim/fragment_open_enter" app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter" app:popEnterAnim="@anim/fragment_close_enter"

View file

@ -591,7 +591,7 @@
<action <action
android:id="@+id/action_direct_to_devices" android:id="@+id/action_direct_to_devices"
app:destination="@id/deviceActivity" app:destination="@id/linkDeviceFragment"
app:enterAnim="@anim/fragment_open_enter" app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter" app:popEnterAnim="@anim/fragment_close_enter"