Fix camera-first qr scans.
This commit is contained in:
parent
7086709082
commit
baaad0e475
6 changed files with 40 additions and 17 deletions
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue