Update add linked devices screen.
This commit is contained in:
parent
ac52b5b992
commit
d3eb480d31
19 changed files with 1429 additions and 28 deletions
|
@ -540,6 +540,7 @@ dependencies {
|
|||
}
|
||||
implementation(libs.stream)
|
||||
implementation(libs.lottie)
|
||||
implementation(libs.lottie.compose)
|
||||
implementation(libs.signal.android.database.sqlcipher)
|
||||
implementation(libs.androidx.sqlite)
|
||||
implementation(libs.google.ez.vcard) {
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.PermissionState
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.Scaffolds
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.BiometricDeviceAuthentication
|
||||
import org.thoughtcrime.securesms.BiometricDeviceLockContract
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
/**
|
||||
* Fragment that allows users to scan a QR code from their camera to link a device
|
||||
*/
|
||||
class AddLinkDeviceFragment : ComposeFragment() {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(AddLinkDeviceFragment::class)
|
||||
}
|
||||
|
||||
private val viewModel: LinkDeviceViewModel by activityViewModels()
|
||||
private lateinit var biometricAuth: BiometricDeviceAuthentication
|
||||
private lateinit var biometricDeviceLockLauncher: ActivityResultLauncher<String>
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
biometricDeviceLockLauncher = registerForActivityResult(BiometricDeviceLockContract()) { result: Int ->
|
||||
if (result == BiometricDeviceAuthentication.AUTHENTICATED) {
|
||||
viewModel.addDevice()
|
||||
} else {
|
||||
viewModel.clearBiometrics()
|
||||
}
|
||||
}
|
||||
|
||||
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||
.setAllowedAuthenticators(BiometricDeviceAuthentication.ALLOWED_AUTHENTICATORS)
|
||||
.setTitle(requireContext().getString(R.string.BiometricDeviceAuthentication__signal))
|
||||
.setConfirmationRequired(true)
|
||||
.build()
|
||||
biometricAuth = BiometricDeviceAuthentication(
|
||||
BiometricManager.from(requireActivity()),
|
||||
BiometricPrompt(requireActivity(), BiometricAuthenticationListener()),
|
||||
promptInfo
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
viewModel.clearBiometrics()
|
||||
biometricAuth.cancelAuthentication()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val navController: NavController by remember { mutableStateOf(findNavController()) }
|
||||
val cameraPermissionState: PermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)
|
||||
|
||||
if (!state.seenIntroSheet) {
|
||||
navController.safeNavigate(R.id.action_addLinkDeviceFragment_to_linkDeviceIntroBottomSheet)
|
||||
viewModel.markIntroSheetSeen()
|
||||
}
|
||||
|
||||
if ((state.qrCodeFound || state.qrCodeInvalid) && navController.currentDestination?.id == R.id.linkDeviceIntroBottomSheet) {
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
MainScreen(
|
||||
state = state,
|
||||
navController = navController,
|
||||
hasPermissions = cameraPermissionState.status.isGranted,
|
||||
onRequestPermissions = { askPermissions() },
|
||||
onShowFrontCamera = { viewModel.showFrontCamera() },
|
||||
onQrCodeScanned = { data -> viewModel.onQrCodeScanned(data) },
|
||||
onQrCodeApproved = {
|
||||
viewModel.onQrCodeApproved()
|
||||
biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.BiometricDeviceAuthentication__signal)) }
|
||||
},
|
||||
onQrCodeDismissed = { viewModel.onQrCodeDismissed() },
|
||||
onQrCodeRetry = { viewModel.onQrCodeScanned(state.url) },
|
||||
onLinkDeviceSuccess = {
|
||||
viewModel.onLinkDeviceResult(true)
|
||||
navController.popBackStack()
|
||||
},
|
||||
onLinkDeviceFailure = { viewModel.onLinkDeviceResult(false) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun askPermissions() {
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withPermanentDenialDialog(getString(R.string.CameraXFragment_signal_needs_camera_access_scan_qr_code), null, R.string.CameraXFragment_allow_access_camera, R.string.CameraXFragment_to_scan_qr_codes, parentFragmentManager)
|
||||
.onAnyDenied { Toast.makeText(requireContext(), R.string.CameraXFragment_signal_needs_camera_access_scan_qr_code, Toast.LENGTH_LONG).show() }
|
||||
.execute()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingSuperCall")
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
private inner class BiometricAuthenticationListener : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationError(errorCode: Int, errorString: CharSequence) {
|
||||
Log.w(TAG, "Linked device authentication error: $errorCode")
|
||||
viewModel.clearBiometrics()
|
||||
onAuthenticationFailed()
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||
Log.i(TAG, "Linked device authentication succeeded")
|
||||
viewModel.addDevice()
|
||||
}
|
||||
|
||||
override fun onAuthenticationFailed() {
|
||||
Log.w(TAG, "Linked device unable to authenticate")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MainScreen(
|
||||
state: LinkDeviceSettingsState,
|
||||
navController: NavController? = null,
|
||||
hasPermissions: Boolean = false,
|
||||
onRequestPermissions: () -> Unit = {},
|
||||
onShowFrontCamera: () -> Unit = {},
|
||||
onQrCodeScanned: (String) -> Unit = {},
|
||||
onQrCodeApproved: () -> Unit = {},
|
||||
onQrCodeDismissed: () -> Unit = {},
|
||||
onQrCodeRetry: () -> Unit = {},
|
||||
onLinkDeviceSuccess: () -> Unit = {},
|
||||
onLinkDeviceFailure: () -> Unit = {}
|
||||
) {
|
||||
Scaffolds.Settings(
|
||||
title = "",
|
||||
onNavigationClick = { navController?.popBackStack() },
|
||||
navigationIconPainter = painterResource(id = R.drawable.ic_x),
|
||||
navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close),
|
||||
actions = {
|
||||
IconButton(onClick = { onShowFrontCamera() }) {
|
||||
Icon(painterResource(id = R.drawable.symbol_switch_24), contentDescription = null)
|
||||
}
|
||||
}
|
||||
) { contentPadding: PaddingValues ->
|
||||
LinkDeviceQrScanScreen(
|
||||
hasPermission = hasPermissions,
|
||||
onRequestPermissions = onRequestPermissions,
|
||||
showFrontCamera = state.showFrontCamera,
|
||||
qrCodeFound = state.qrCodeFound,
|
||||
qrCodeInvalid = state.qrCodeInvalid,
|
||||
onQrCodeScanned = onQrCodeScanned,
|
||||
onQrCodeAccepted = onQrCodeApproved,
|
||||
onQrCodeDismissed = onQrCodeDismissed,
|
||||
onQrCodeRetry = onQrCodeRetry,
|
||||
pendingBiometrics = state.pendingBiometrics,
|
||||
linkDeviceResult = state.linkDeviceResult,
|
||||
onLinkDeviceSuccess = onLinkDeviceSuccess,
|
||||
onLinkDeviceFailure = onLinkDeviceFailure,
|
||||
modifier = Modifier.padding(contentPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
private fun LinkDeviceAddScreenPreview() {
|
||||
Previews.Preview {
|
||||
MainScreen(
|
||||
state = LinkDeviceSettingsState()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.signal.core.ui.BottomSheets
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
|
||||
/**
|
||||
* Bottom sheet dialog prompting users to name their newly linked device
|
||||
*/
|
||||
class LinkDeviceFinishedSheet : ComposeBottomSheetDialogFragment() {
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
FinishedSheet(this::dismissAllowingStateLoss)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FinishedSheet(onClick: () -> Unit) {
|
||||
return Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
BottomSheets.Handle()
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_devices),
|
||||
contentDescription = null,
|
||||
tint = Color.Unspecified
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.AddLinkDeviceFragment__finish_linking_on_other_device),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(vertical = 12.dp, horizontal = 12.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.AddLinkDeviceFragment__finish_linking_signal),
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(horizontal = 12.dp)
|
||||
)
|
||||
Buttons.LargeTonal(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.defaultMinSize(minWidth = 220.dp).padding(vertical = 20.dp, horizontal = 12.dp)
|
||||
) {
|
||||
Text(stringResource(id = R.string.AddLinkDeviceFragment__okay))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun FinishedSheetSheetPreview() {
|
||||
Previews.BottomSheetPreview {
|
||||
FinishedSheet(onClick = {})
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import androidx.compose.material3.MaterialTheme
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -34,7 +35,7 @@ import androidx.compose.ui.text.AnnotatedString
|
|||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.core.ui.Dialogs
|
||||
|
@ -42,11 +43,11 @@ import org.signal.core.ui.Dividers
|
|||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.Scaffolds
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.thoughtcrime.securesms.DeviceActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
|
@ -54,11 +55,11 @@ import java.util.Locale
|
|||
*/
|
||||
class LinkDeviceFragment : ComposeFragment() {
|
||||
|
||||
private val viewModel: LinkDeviceViewModel by viewModels()
|
||||
private val viewModel: LinkDeviceViewModel by activityViewModels()
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
LaunchedEffect(state.toastDialog) {
|
||||
if (state.toastDialog.isNotEmpty()) {
|
||||
|
@ -66,6 +67,12 @@ class LinkDeviceFragment : ComposeFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(state.showFinishedSheet) {
|
||||
if (state.showFinishedSheet) {
|
||||
onShowFinishedSheet()
|
||||
}
|
||||
}
|
||||
|
||||
Scaffolds.Settings(
|
||||
title = stringResource(id = R.string.preferences__linked_devices),
|
||||
onNavigationClick = { findNavController().popBackStack() },
|
||||
|
@ -93,9 +100,7 @@ class LinkDeviceFragment : ComposeFragment() {
|
|||
}
|
||||
|
||||
private fun openLinkNewDevice() {
|
||||
// TODO(Michelle): Use linkDeviceAddFragment
|
||||
startActivity(DeviceActivity.getIntentForScanner(requireContext()))
|
||||
// findNavController().safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceAddFragment)
|
||||
findNavController().safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment)
|
||||
}
|
||||
|
||||
private fun setDeviceToRemove(device: Device?) {
|
||||
|
@ -105,6 +110,11 @@ class LinkDeviceFragment : ComposeFragment() {
|
|||
private fun onRemoveDevice(device: Device) {
|
||||
viewModel.removeDevice(requireContext(), device)
|
||||
}
|
||||
|
||||
private fun onShowFinishedSheet() {
|
||||
LinkDeviceFinishedSheet().show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
viewModel.markFinishedSheetSeen()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.airbnb.lottie.compose.LottieAnimation
|
||||
import com.airbnb.lottie.compose.LottieCompositionSpec
|
||||
import com.airbnb.lottie.compose.LottieConstants
|
||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||
import org.signal.core.ui.BottomSheets
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
|
||||
/**
|
||||
* Bottom sheet dialog displayed when users click 'Link a device'
|
||||
*/
|
||||
class LinkDeviceIntroBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
override val peekHeightPercentage: Float = 0.8f
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
EducationSheet(this::dismissAllowingStateLoss)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EducationSheet(onClick: () -> Unit) {
|
||||
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.linking_device))
|
||||
|
||||
return Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
BottomSheets.Handle()
|
||||
Box(modifier = Modifier.size(150.dp)) {
|
||||
LottieAnimation(composition, iterations = LottieConstants.IterateForever, modifier = Modifier.matchParentSize())
|
||||
}
|
||||
Text(
|
||||
text = stringResource(R.string.AddLinkDeviceFragment__scan_qr_code),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.AddLinkDeviceFragment__use_this_device_to_scan_qr_code),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
)
|
||||
Buttons.LargeTonal(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.defaultMinSize(minWidth = 220.dp)
|
||||
) {
|
||||
Text(stringResource(id = R.string.AddLinkDeviceFragment__okay))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
fun EducationSheetPreview() {
|
||||
Previews.BottomSheetPreview {
|
||||
EducationSheet(onClick = {})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.signal.core.ui.Dialogs
|
||||
import org.signal.qr.QrScannerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.mediasend.camerax.CameraXModelBlocklist
|
||||
import org.thoughtcrime.securesms.qr.QrScanScreens
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* A screen that allows you to scan a QR code to link a device
|
||||
*/
|
||||
@Composable
|
||||
fun LinkDeviceQrScanScreen(
|
||||
hasPermission: Boolean,
|
||||
onRequestPermissions: () -> Unit,
|
||||
showFrontCamera: Boolean?,
|
||||
qrCodeFound: Boolean,
|
||||
qrCodeInvalid: Boolean,
|
||||
onQrCodeScanned: (String) -> Unit,
|
||||
onQrCodeAccepted: () -> Unit,
|
||||
onQrCodeDismissed: () -> Unit,
|
||||
onQrCodeRetry: () -> Unit,
|
||||
pendingBiometrics: Boolean,
|
||||
linkDeviceResult: LinkDeviceRepository.LinkDeviceResult,
|
||||
onLinkDeviceSuccess: () -> Unit,
|
||||
onLinkDeviceFailure: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val context = LocalContext.current
|
||||
|
||||
if (qrCodeFound) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(id = R.string.DeviceProvisioningActivity_link_this_device),
|
||||
body = stringResource(id = R.string.AddLinkDeviceFragment__this_device_will_see_your_groups_contacts),
|
||||
confirm = stringResource(id = R.string.device_list_fragment__link_new_device),
|
||||
onConfirm = onQrCodeAccepted,
|
||||
dismiss = stringResource(id = android.R.string.cancel),
|
||||
onDismiss = onQrCodeDismissed
|
||||
)
|
||||
} else if (qrCodeInvalid) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(id = R.string.AddLinkDeviceFragment__linking_device_failed),
|
||||
body = stringResource(id = R.string.AddLinkDeviceFragment__this_qr_code_not_valid),
|
||||
confirm = stringResource(id = R.string.AddLinkDeviceFragment__retry),
|
||||
onConfirm = onQrCodeRetry,
|
||||
dismiss = stringResource(id = android.R.string.cancel),
|
||||
onDismiss = onQrCodeDismissed
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(linkDeviceResult) {
|
||||
when (linkDeviceResult) {
|
||||
LinkDeviceRepository.LinkDeviceResult.SUCCESS -> onLinkDeviceSuccess()
|
||||
LinkDeviceRepository.LinkDeviceResult.NO_DEVICE -> makeToast(context, R.string.DeviceProvisioningActivity_content_progress_no_device, onLinkDeviceFailure)
|
||||
LinkDeviceRepository.LinkDeviceResult.NETWORK_ERROR -> makeToast(context, R.string.DeviceProvisioningActivity_content_progress_network_error, onLinkDeviceFailure)
|
||||
LinkDeviceRepository.LinkDeviceResult.KEY_ERROR -> makeToast(context, R.string.DeviceProvisioningActivity_content_progress_key_error, onLinkDeviceFailure)
|
||||
LinkDeviceRepository.LinkDeviceResult.LIMIT_EXCEEDED -> makeToast(context, R.string.DeviceProvisioningActivity_sorry_you_have_too_many_devices_linked_already, onLinkDeviceFailure)
|
||||
LinkDeviceRepository.LinkDeviceResult.BAD_CODE -> makeToast(context, R.string.DeviceActivity_sorry_this_is_not_a_valid_device_link_qr_code, onLinkDeviceFailure)
|
||||
LinkDeviceRepository.LinkDeviceResult.UNKNOWN -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f, true)
|
||||
) {
|
||||
QrScanScreens.QrScanScreen(
|
||||
factory = { factoryContext ->
|
||||
val view = QrScannerView(factoryContext)
|
||||
view.qrData
|
||||
.throttleFirst(3000, TimeUnit.MILLISECONDS)
|
||||
.subscribe { data ->
|
||||
onQrCodeScanned(data)
|
||||
}
|
||||
view
|
||||
},
|
||||
update = { view: QrScannerView ->
|
||||
if (pendingBiometrics) {
|
||||
view.destroy()
|
||||
} else {
|
||||
view.start(lifecycleOwner = lifecycleOwner, forceLegacy = CameraXModelBlocklist.isBlocklisted())
|
||||
if (showFrontCamera != null) {
|
||||
view.toggleCamera()
|
||||
}
|
||||
}
|
||||
},
|
||||
hasPermission = hasPermission,
|
||||
onRequestPermissions = onRequestPermissions,
|
||||
qrString = stringResource(R.string.AddLinkDeviceFragment__scan_the_qr_code)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeToast(context: Context, messageId: Int, onLinkDeviceFailure: () -> Unit) {
|
||||
Toast.makeText(context, messageId, Toast.LENGTH_LONG).show()
|
||||
onLinkDeviceFailure()
|
||||
}
|
|
@ -1,15 +1,23 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import android.net.Uri
|
||||
import org.signal.core.util.Base64.decode
|
||||
import org.signal.core.util.isNotNullOrBlank
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.libsignal.protocol.ecc.Curve
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.devicelist.protos.DeviceName
|
||||
import org.thoughtcrime.securesms.jobs.LinkedDeviceInactiveCheckJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.registration.secondary.DeviceNameCipher
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException
|
||||
import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException
|
||||
import java.io.IOException
|
||||
import java.security.InvalidKeyException
|
||||
|
||||
/**
|
||||
* Repository for linked devices and its various actions (linking, unlinking, listing).
|
||||
|
@ -71,4 +79,49 @@ object LinkDeviceRepository {
|
|||
}
|
||||
return defaultDevice
|
||||
}
|
||||
|
||||
fun isValidQr(uri: Uri): Boolean {
|
||||
val ephemeralId: String? = uri.getQueryParameter("uuid")
|
||||
val publicKeyEncoded: String? = uri.getQueryParameter("pub_key")
|
||||
return ephemeralId.isNotNullOrBlank() && publicKeyEncoded.isNotNullOrBlank()
|
||||
}
|
||||
|
||||
fun addDevice(uri: Uri): LinkDeviceResult {
|
||||
return try {
|
||||
val accountManager = AppDependencies.signalServiceAccountManager
|
||||
val verificationCode = accountManager.getNewDeviceVerificationCode()
|
||||
if (!isValidQr(uri)) {
|
||||
LinkDeviceResult.BAD_CODE
|
||||
} else {
|
||||
val ephemeralId: String? = uri.getQueryParameter("uuid")
|
||||
val publicKeyEncoded: String? = uri.getQueryParameter("pub_key")
|
||||
val publicKey = Curve.decodePoint(publicKeyEncoded?.let { decode(it) }, 0)
|
||||
val aciIdentityKeyPair = SignalStore.account().aciIdentityKey
|
||||
val pniIdentityKeyPair = SignalStore.account().pniIdentityKey
|
||||
val profileKey = ProfileKeyUtil.getSelfProfileKey()
|
||||
|
||||
accountManager.addDevice(ephemeralId, publicKey, aciIdentityKeyPair, pniIdentityKeyPair, profileKey, SignalStore.svr().getOrCreateMasterKey(), verificationCode)
|
||||
TextSecurePreferences.setMultiDevice(AppDependencies.application, true)
|
||||
LinkDeviceResult.SUCCESS
|
||||
}
|
||||
} catch (e: NotFoundException) {
|
||||
LinkDeviceResult.NO_DEVICE
|
||||
} catch (e: DeviceLimitExceededException) {
|
||||
LinkDeviceResult.LIMIT_EXCEEDED
|
||||
} catch (e: IOException) {
|
||||
LinkDeviceResult.NETWORK_ERROR
|
||||
} catch (e: InvalidKeyException) {
|
||||
LinkDeviceResult.KEY_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
enum class LinkDeviceResult {
|
||||
SUCCESS,
|
||||
NO_DEVICE,
|
||||
NETWORK_ERROR,
|
||||
KEY_ERROR,
|
||||
LIMIT_EXCEEDED,
|
||||
BAD_CODE,
|
||||
UNKNOWN
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,5 +9,13 @@ data class LinkDeviceSettingsState(
|
|||
val devices: List<Device> = emptyList(),
|
||||
val deviceToRemove: Device? = null,
|
||||
@StringRes val progressDialogMessage: Int = -1,
|
||||
val toastDialog: String = ""
|
||||
val toastDialog: String = "",
|
||||
val showFrontCamera: Boolean? = null,
|
||||
val qrCodeFound: Boolean = false,
|
||||
val qrCodeInvalid: Boolean = false,
|
||||
val url: String = "",
|
||||
val linkDeviceResult: LinkDeviceRepository.LinkDeviceResult = LinkDeviceRepository.LinkDeviceResult.UNKNOWN,
|
||||
val showFinishedSheet: Boolean = false,
|
||||
val seenIntroSheet: Boolean = false,
|
||||
val pendingBiometrics: Boolean = false
|
||||
)
|
||||
|
|
|
@ -1,35 +1,33 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.jobs.LinkedDeviceInactiveCheckJob
|
||||
|
||||
/**
|
||||
* Maintains the state of the [LinkDeviceFragment]
|
||||
*/
|
||||
class LinkDeviceViewModel : ViewModel() {
|
||||
|
||||
private val _state = mutableStateOf(LinkDeviceSettingsState())
|
||||
val state: State<LinkDeviceSettingsState> = _state
|
||||
|
||||
fun onResume() {
|
||||
_state.value = _state.value.copy()
|
||||
}
|
||||
private val _state = MutableStateFlow(LinkDeviceSettingsState())
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
fun setDeviceToRemove(device: Device?) {
|
||||
_state.value = _state.value.copy(deviceToRemove = device)
|
||||
_state.update { it.copy(deviceToRemove = device) }
|
||||
}
|
||||
|
||||
fun removeDevice(context: Context, device: Device) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_state.value = _state.value.copy(
|
||||
progressDialogMessage = R.string.DeviceListActivity_unlinking_device
|
||||
)
|
||||
_state.update { it.copy(progressDialogMessage = R.string.DeviceListActivity_unlinking_device) }
|
||||
|
||||
val success = LinkDeviceRepository.removeDevice(device.id)
|
||||
if (success) {
|
||||
loadDevices(context)
|
||||
|
@ -38,9 +36,9 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
progressDialogMessage = -1
|
||||
)
|
||||
} else {
|
||||
_state.value = _state.value.copy(
|
||||
progressDialogMessage = -1
|
||||
)
|
||||
_state.update {
|
||||
it.copy(progressDialogMessage = -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,11 +52,120 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
progressDialogMessage = -1
|
||||
)
|
||||
} else {
|
||||
_state.value = _state.value.copy(
|
||||
devices = devices,
|
||||
progressDialogMessage = -1
|
||||
_state.update {
|
||||
it.copy(
|
||||
toastDialog = "",
|
||||
devices = devices,
|
||||
progressDialogMessage = -1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showFrontCamera() {
|
||||
_state.update {
|
||||
val frontCamera = it.showFrontCamera
|
||||
it.copy(
|
||||
showFrontCamera = if (frontCamera == null) true else !frontCamera,
|
||||
pendingBiometrics = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun markIntroSheetSeen() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
seenIntroSheet = true,
|
||||
showFrontCamera = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onQrCodeScanned(url: String) {
|
||||
if (_state.value.qrCodeFound || _state.value.qrCodeInvalid) {
|
||||
return
|
||||
}
|
||||
|
||||
val uri = Uri.parse(url)
|
||||
if (LinkDeviceRepository.isValidQr(uri)) {
|
||||
_state.update {
|
||||
it.copy(
|
||||
qrCodeFound = true,
|
||||
qrCodeInvalid = false,
|
||||
url = url,
|
||||
showFrontCamera = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
_state.update {
|
||||
it.copy(
|
||||
qrCodeFound = false,
|
||||
qrCodeInvalid = true,
|
||||
url = url,
|
||||
showFrontCamera = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onQrCodeApproved() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
qrCodeFound = false,
|
||||
qrCodeInvalid = false,
|
||||
pendingBiometrics = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onQrCodeDismissed() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
qrCodeFound = false,
|
||||
qrCodeInvalid = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun clearBiometrics() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
pendingBiometrics = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun addDevice() {
|
||||
val uri = Uri.parse(_state.value.url)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val result = LinkDeviceRepository.addDevice(uri)
|
||||
_state.update {
|
||||
it.copy(
|
||||
pendingBiometrics = false,
|
||||
linkDeviceResult = result,
|
||||
url = ""
|
||||
)
|
||||
}
|
||||
LinkedDeviceInactiveCheckJob.enqueue()
|
||||
}
|
||||
}
|
||||
|
||||
fun onLinkDeviceResult(showSheet: Boolean) {
|
||||
_state.update {
|
||||
it.copy(
|
||||
showFinishedSheet = showSheet,
|
||||
linkDeviceResult = LinkDeviceRepository.LinkDeviceResult.UNKNOWN,
|
||||
toastDialog = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun markFinishedSheetSeen() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
showFinishedSheet = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
140
app/src/main/java/org/thoughtcrime/securesms/qr/QrScanScreens.kt
Normal file
140
app/src/main/java/org/thoughtcrime/securesms/qr/QrScanScreens.kt
Normal file
|
@ -0,0 +1,140 @@
|
|||
package org.thoughtcrime.securesms.qr
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.PathEffect
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.viewinterop.NoOpUpdate
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.qr.QrScannerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
object QrScanScreens {
|
||||
/**
|
||||
* Full-screen qr scanning screen with permission-asking UI
|
||||
*/
|
||||
@Composable
|
||||
fun QrScanScreen(
|
||||
factory: (Context) -> QrScannerView,
|
||||
update: (QrScannerView) -> Unit = NoOpUpdate,
|
||||
hasPermission: Boolean,
|
||||
onRequestPermissions: () -> Unit = {},
|
||||
qrString: String
|
||||
) {
|
||||
val path = remember { Path() }
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f, true)
|
||||
) {
|
||||
AndroidView(
|
||||
factory = factory,
|
||||
update = update,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.drawWithContent {
|
||||
drawContent()
|
||||
if (hasPermission) {
|
||||
drawQrCrosshair(path)
|
||||
}
|
||||
}
|
||||
)
|
||||
if (!hasPermission) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.align(Alignment.Center).padding(48.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.CameraXFragment_to_scan_qr_code_allow_camera),
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = Color.White
|
||||
)
|
||||
Buttons.MediumTonal(
|
||||
colors = ButtonDefaults.filledTonalButtonColors(),
|
||||
onClick = onRequestPermissions
|
||||
) {
|
||||
Text(stringResource(R.string.CameraXFragment_allow_access))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
text = qrString,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = Color.White,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(top = 24.dp).fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DrawScope.drawQrCrosshair(path: Path) {
|
||||
val crosshairWidth: Float = size.minDimension * 0.6f
|
||||
val crosshairLineLength = crosshairWidth * 0.125f
|
||||
|
||||
val topLeft = center - Offset(crosshairWidth / 2, crosshairWidth / 2)
|
||||
val topRight = center + Offset(crosshairWidth / 2, -crosshairWidth / 2)
|
||||
val bottomRight = center + Offset(crosshairWidth / 2, crosshairWidth / 2)
|
||||
val bottomLeft = center + Offset(-crosshairWidth / 2, crosshairWidth / 2)
|
||||
|
||||
path.reset()
|
||||
|
||||
drawPath(
|
||||
path = path.apply {
|
||||
moveTo(topLeft.x, topLeft.y + crosshairLineLength)
|
||||
lineTo(topLeft.x, topLeft.y)
|
||||
lineTo(topLeft.x + crosshairLineLength, topLeft.y)
|
||||
|
||||
moveTo(topRight.x - crosshairLineLength, topRight.y)
|
||||
lineTo(topRight.x, topRight.y)
|
||||
lineTo(topRight.x, topRight.y + crosshairLineLength)
|
||||
|
||||
moveTo(bottomRight.x, bottomRight.y - crosshairLineLength)
|
||||
lineTo(bottomRight.x, bottomRight.y)
|
||||
lineTo(bottomRight.x - crosshairLineLength, bottomRight.y)
|
||||
|
||||
moveTo(bottomLeft.x + crosshairLineLength, bottomLeft.y)
|
||||
lineTo(bottomLeft.x, bottomLeft.y)
|
||||
lineTo(bottomLeft.x, bottomLeft.y - crosshairLineLength)
|
||||
},
|
||||
color = Color.White,
|
||||
style = Stroke(
|
||||
width = 3.dp.toPx(),
|
||||
pathEffect = PathEffect.cornerPathEffect(10.dp.toPx())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -235,7 +235,26 @@
|
|||
<fragment
|
||||
android:id="@+id/linkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceFragment"
|
||||
android:label="link_device_fragment" />
|
||||
android:label="link_device_fragment">
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_addLinkDeviceFragment"
|
||||
app:destination="@id/addLinkDeviceFragment"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/addLinkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.AddLinkDeviceFragment"
|
||||
android:label="link_device_add_fragment">
|
||||
<action
|
||||
android:id="@+id/action_addLinkDeviceFragment_to_linkDeviceIntroBottomSheet"
|
||||
app:destination="@id/linkDeviceIntroBottomSheet" />
|
||||
</fragment>
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceIntroBottomSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceIntroBottomSheet" />
|
||||
|
||||
<!-- Payments -->
|
||||
<activity
|
||||
|
|
|
@ -235,7 +235,26 @@
|
|||
<fragment
|
||||
android:id="@+id/linkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceFragment"
|
||||
android:label="link_device_fragment" />
|
||||
android:label="link_device_fragment">
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_addLinkDeviceFragment"
|
||||
app:destination="@id/addLinkDeviceFragment"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/addLinkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.AddLinkDeviceFragment"
|
||||
android:label="link_device_add_fragment">
|
||||
<action
|
||||
android:id="@+id/action_addLinkDeviceFragment_to_linkDeviceIntroBottomSheet"
|
||||
app:destination="@id/linkDeviceIntroBottomSheet" />
|
||||
</fragment>
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceIntroBottomSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceIntroBottomSheet" />
|
||||
|
||||
<!-- Payments -->
|
||||
<activity
|
||||
|
|
|
@ -882,6 +882,28 @@
|
|||
<!-- Toast message indicating a device has been unlinked where %s is the name of the device -->
|
||||
<string name="LinkDeviceFragment__s_unlinked">%s unlinked</string>
|
||||
|
||||
<!-- AddLinkDeviceFragment -->
|
||||
<!-- Description text shown on the QR code scanner when linking a device -->
|
||||
<string name="AddLinkDeviceFragment__scan_the_qr_code">Scan the QR code displayed on the device to link.</string>
|
||||
<!-- Bottom sheet title telling users to scan a qr code -->
|
||||
<string name="AddLinkDeviceFragment__scan_qr_code">Scan QR code</string>
|
||||
<!-- Bottom sheet description telling users how to scan a qr code -->
|
||||
<string name="AddLinkDeviceFragment__use_this_device_to_scan_qr_code">Use this device to scan the QR code displayed on the device you want to link</string>
|
||||
<!-- Confirmation button to dismiss bottom sheet dialog -->
|
||||
<string name="AddLinkDeviceFragment__okay">Okay</string>
|
||||
<!-- Dialog text describing the consequences of linking a device -->
|
||||
<string name="AddLinkDeviceFragment__this_device_will_see_your_groups_contacts">This device will be able to see your groups and contacts, access your chats, and send messages in your name.</string>
|
||||
<!-- Bottom sheet title telling users to complete the linking process on the other device -->
|
||||
<string name="AddLinkDeviceFragment__finish_linking_on_other_device">Finish linking on your other device</string>
|
||||
<!-- Bottom sheet description telling users to complete the linking process -->
|
||||
<string name="AddLinkDeviceFragment__finish_linking_signal">Finish linking Signal on your other device.</string>
|
||||
<!-- Title of dialog when the QR code being scanned is invalid -->
|
||||
<string name="AddLinkDeviceFragment__linking_device_failed">Linking device failed</string>
|
||||
<!-- Text shown in a dialog when the QR code being scanned is invalid -->
|
||||
<string name="AddLinkDeviceFragment__this_qr_code_not_valid">This QR code is not valid. Please make sure you are scanning the QR code that is displayed on the device you want to link.</string>
|
||||
<!-- Button in dialog to retry linking a device with a qr code -->
|
||||
<string name="AddLinkDeviceFragment__retry">Retry</string>
|
||||
|
||||
<!-- DeviceListActivity -->
|
||||
<string name="DeviceListActivity_unlink_s">Unlink \'%s\'?</string>
|
||||
<string name="DeviceListActivity_by_unlinking_this_device_it_will_no_longer_be_able_to_send_or_receive">By unlinking this device, it will no longer be able to send or receive messages.</string>
|
||||
|
|
|
@ -148,6 +148,7 @@ dependencyResolutionManagement {
|
|||
library("android-tooltips", "com.tomergoldst.android:tooltips:1.0.6")
|
||||
library("stream", "com.annimon:stream:1.1.8")
|
||||
library("lottie", "com.airbnb.android:lottie:5.2.0")
|
||||
library("lottie-compose", "com.airbnb.android:lottie-compose:6.4.0")
|
||||
library("dnsjava", "dnsjava:dnsjava:2.1.9")
|
||||
library("nanohttpd-webserver", "org.nanohttpd", "nanohttpd-webserver").versionRef("nanohttpd")
|
||||
library("nanohttpd-websocket", "org.nanohttpd", "nanohttpd-websocket").versionRef("nanohttpd")
|
||||
|
|
|
@ -142,6 +142,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="fbc64f5c44a7added8b6eab517cf7d70555e25153bf5d44a6ed9b0e5312f7de9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.annotation" name="annotation" version="1.7.0">
|
||||
<artifact name="annotation-1.7.0.module">
|
||||
<sha256 value="530708656d380605077ea8bca9ae1372fbd1af38e375f411d4e43263bd510c3c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.annotation" name="annotation-experimental" version="1.0.0">
|
||||
<artifact name="annotation-experimental-1.0.0.aar">
|
||||
<sha256 value="b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11" origin="Generated by Gradle"/>
|
||||
|
@ -171,6 +176,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="9b6974a7dfe26d3c209dd63e16f8ee2461b57a091789160ca1eb492bb1bf3f84" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.annotation" name="annotation-experimental" version="1.4.0">
|
||||
<artifact name="annotation-experimental-1.4.0.aar">
|
||||
<sha256 value="c6eb7e676011ec65b32428373d450debdfc45179c4f8b3a752174fb87c17b08a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="annotation-experimental-1.4.0.module">
|
||||
<sha256 value="5930ea7f21fcb6d0deb2ba32748a0ef7c8fd2c42384860582ba7cd20deb90379" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.annotation" name="annotation-jvm" version="1.6.0">
|
||||
<artifact name="annotation-jvm-1.6.0.jar">
|
||||
<sha256 value="60b10b5ef5769b79570172e015b8159405c92f034ba88b9391a977589c9deb4e" origin="Generated by Gradle"/>
|
||||
|
@ -179,6 +192,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="3f5a8faa19de667e63dca9730ff8ef0e478e4bafb5feeb8258e5c086246dc90c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.annotation" name="annotation-jvm" version="1.7.0">
|
||||
<artifact name="annotation-jvm-1.7.0.jar">
|
||||
<sha256 value="e36b8e4b8393a4adc74e3d4ab22ad5a36396f0cea2e40b5734eae14937dfd224" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="annotation-jvm-1.7.0.module">
|
||||
<sha256 value="07ce60c377ab94e47c8c902589b9776030064fd1a7e4d5a01a38d700e35e5db4" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.appcompat" name="appcompat" version="1.6.1">
|
||||
<artifact name="appcompat-1.6.1.aar">
|
||||
<sha256 value="7ea5573b93ababd3bd32312451c6ea48a662b03a140dda81aebe75776a20a422" origin="Generated by Gradle"/>
|
||||
|
@ -379,11 +400,32 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="6c4c0f9e7dab6d983858e67dd99a93af9d9f7d02ac1f8f648ce1fecc84afffa2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.collection" name="collection" version="1.4.0">
|
||||
<artifact name="collection-1.4.0.module">
|
||||
<sha256 value="2fd3b523e8276c0254c417b66d8e7fecc5b0b975af5d178afa7f5b813812cfab" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.collection" name="collection-jvm" version="1.4.0">
|
||||
<artifact name="collection-jvm-1.4.0.jar">
|
||||
<sha256 value="d5cf7b72647c7995071588fe870450ff9c8f127f253d2d4851e161b800f67ae0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="collection-jvm-1.4.0.module">
|
||||
<sha256 value="21b0b02ea68abe418f3dd4e4d42876ecf3bd9a1cada458b460cae1cd9d58ef6d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.collection" name="collection-ktx" version="1.1.0">
|
||||
<artifact name="collection-ktx-1.1.0.jar">
|
||||
<sha256 value="2bfc54475c047131913361f56d0f7f019c6e5bee53eeb0eb7d94a7c499a05227" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.collection" name="collection-ktx" version="1.4.0">
|
||||
<artifact name="collection-ktx-1.4.0.jar">
|
||||
<sha256 value="c6deada2fac53b8ea6523dbda77597b128006674616f140f04df23264c6d1aa3" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="collection-ktx-1.4.0.module">
|
||||
<sha256 value="3770999ec32d1c082d1a34cf1d64d16d9eca9b6b1263c979954407f461fba82b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation" version="1.1.1">
|
||||
<artifact name="animation-1.1.1.module">
|
||||
<sha256 value="078b4dcd5f09689281415d9ea0e09d2775d80f016041dacbcee22d54c43a5fa1" origin="Generated by Gradle"/>
|
||||
|
@ -405,6 +447,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="28a43ab8fba64e55bcd20126b8ed55f5ab4e8f927f749d46b6fbd1f75af04d7e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation" version="1.6.2">
|
||||
<artifact name="animation-1.6.2.module">
|
||||
<sha256 value="1e929c6fdb8ec509a5584e52d3fa11f53353ac204b777790201449aeb9d81e57" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-android" version="1.5.1">
|
||||
<artifact name="animation-android-1.5.1.module">
|
||||
<sha256 value="bff0f739876b4ccc9a6add1f5314ae39811a4663613e887b3bfda9eda1f50960" origin="Generated by Gradle"/>
|
||||
|
@ -421,6 +468,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="428538775ea55529b953fbb7a6000ccfddc89722c69c7a30431a630fa2fe74f2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-android" version="1.6.2">
|
||||
<artifact name="animation-android-1.6.2.module">
|
||||
<sha256 value="2c1f3a50e0d185fdf882c6516254e2d67561ae639bb243a10a77d02c0e7e5f84" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="animation-release.aar">
|
||||
<sha256 value="6d620e937f2aa422d5a18595d39b001d9149f6fc0af97d7bed1b1c4dd3a2cae2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-core" version="1.5.1">
|
||||
<artifact name="animation-core-1.5.1.module">
|
||||
<sha256 value="cd280d3b8dbf85f251153129cc67f928bc928dfe7e9e410f1858ad331da48b68" origin="Generated by Gradle"/>
|
||||
|
@ -437,6 +492,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="747b658ee320f6d55a8d40727d6c6b0d78c1dc899ed66fe8b65adefd783976cb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-core" version="1.6.2">
|
||||
<artifact name="animation-core-1.6.2.module">
|
||||
<sha256 value="2512e23a51f86a9f51894b9317e3250ee0a0b77eab57e17640ae96b2117bb372" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-core-android" version="1.5.1">
|
||||
<artifact name="animation-core-android-1.5.1.module">
|
||||
<sha256 value="dd8fc6cd7d0c0adff3221a007da1ca258510858bbf0b67a61a49da8465009ba4" origin="Generated by Gradle"/>
|
||||
|
@ -453,6 +513,30 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="d7e85fb4fb36db15eb15134ffec8363fda8517ee944af1441815131029f960c8" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-core-android" version="1.6.2">
|
||||
<artifact name="animation-core-android-1.6.2.module">
|
||||
<sha256 value="58b0948d1ea50b3df8ec1ba7f86355676b715c8f1bb75ac9548eed7709fedd27" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="animation-core-release.aar">
|
||||
<sha256 value="d266ed93de86885d2d53017868d9d0e29238663d0f599ef1f094783a0fcbcd26" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-core-desktop" version="1.6.2">
|
||||
<artifact name="animation-core-desktop-1.6.2.jar">
|
||||
<sha256 value="791fbb5b90f1db2e128a134d5fb5dfe13b6aa4b184300f351b1466470bff78cc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="animation-core-desktop-1.6.2.module">
|
||||
<sha256 value="78843578abf9d0613ea37e4f1cc7f4c549513c57eaac3cc1eb1dc72af0f7e4e1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.animation" name="animation-desktop" version="1.6.2">
|
||||
<artifact name="animation-desktop-1.6.2.jar">
|
||||
<sha256 value="6eb162e32fb6b44cdc50cf3e4ad9906163e35f933cd54f0c03677ce240fe9d7e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="animation-desktop-1.6.2.module">
|
||||
<sha256 value="7ff8993c1c012e1ac273f244b939f7d58d23af80eafc97ed644e3fce0fca94b9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.compiler" name="compiler" version="1.3.2">
|
||||
<artifact name="compiler-1.3.2.jar">
|
||||
<sha256 value="d19beb5fc48395e1730acad2f654daa49a17f6b44a2a45a2e23a0dec806a6931" origin="Generated by Gradle"/>
|
||||
|
@ -506,6 +590,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="84ba53af9fd289476e76b74216d43ee54006cc587c0fdbec51c8cdf717ab5e7f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation" version="1.6.2">
|
||||
<artifact name="foundation-1.6.2.module">
|
||||
<sha256 value="a5c3acf77034297fccadb22af2dadf1f65fc4a4df4381f778ef4133ce241bfd6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-android" version="1.5.1">
|
||||
<artifact name="foundation-android-1.5.1.module">
|
||||
<sha256 value="ac397138d4c01416189eea4d519c6b8190eabe96558656fd0ec5f4af7a581708" origin="Generated by Gradle"/>
|
||||
|
@ -522,6 +611,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="74075b7f5de082f77ce27b80b8787c59ac3ec86d0a66bf5754377211f2894072" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-android" version="1.6.2">
|
||||
<artifact name="foundation-android-1.6.2.module">
|
||||
<sha256 value="f1e3344f6a263ea1db81fb3ebdaa1776fd76a8bba12d06e97f610905fa5e80ce" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="foundation-release.aar">
|
||||
<sha256 value="185f6b2cc5a777dc23a6164f5cea08cf9b9089e83754226441ab65b48b19f4dc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-desktop" version="1.6.2">
|
||||
<artifact name="foundation-desktop-1.6.2.jar">
|
||||
<sha256 value="1eda12bee5a9660ba703ebb3bb38a2ef57011fdc8f4cbcce0d0d7da02cd0a8d0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="foundation-desktop-1.6.2.module">
|
||||
<sha256 value="a450f21a355c979768f1ca745a687f66cddbb69bddc91031f0207bbfe638f2b5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-layout" version="1.5.1">
|
||||
<artifact name="foundation-layout-1.5.1.module">
|
||||
<sha256 value="9efbdd7abb8bdf1625266a42a560168032d1c0df7046c35b205c2668a57271c7" origin="Generated by Gradle"/>
|
||||
|
@ -538,6 +643,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="f8cbd92d3585570dce2541aefef0d59b4c591ae225d98921058e484e9abf3e42" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-layout" version="1.6.2">
|
||||
<artifact name="foundation-layout-1.6.2.module">
|
||||
<sha256 value="43f1ce3e2fc8a510b2aaf20439e9e67b416205a61993955cbae8ea618d732cfb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-layout-android" version="1.5.1">
|
||||
<artifact name="foundation-layout-android-1.5.1.module">
|
||||
<sha256 value="4622a385fd5ef110d1cc55e65cf45f3fc98ff63aa2f2c329a35750bf3be4cab0" origin="Generated by Gradle"/>
|
||||
|
@ -554,6 +664,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="63d6b3832034e6f187213970f42d82d0ce136d6c6061748f34f05cf2ba1d4364" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-layout-android" version="1.6.2">
|
||||
<artifact name="foundation-layout-android-1.6.2.module">
|
||||
<sha256 value="e6771358144019af6576f2b93479c7635a640a9a20388e815c571a24d8328fad" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="foundation-layout-release.aar">
|
||||
<sha256 value="c17f97ecfa5df6020e5b3b6e89c5b617e0ea66cc22ee9a824303fa426a7bc52b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.foundation" name="foundation-layout-desktop" version="1.6.2">
|
||||
<artifact name="foundation-layout-desktop-1.6.2.jar">
|
||||
<sha256 value="8bb898232e0d9a8c56de51671769b73ea0a5ab526f9005de5deff34dddf5cbed" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="foundation-layout-desktop-1.6.2.module">
|
||||
<sha256 value="a64b0b241ff2ad1c6b1bfffb8a66aa7c5d681f5bc4cc1d71f34b1a5b138f2c30" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material" version="1.5.1">
|
||||
<artifact name="material-1.5.1.module">
|
||||
<sha256 value="e409e658869f7923b2f4a9e2963d6727a598489d73a276d1ad26bf082b235826" origin="Generated by Gradle"/>
|
||||
|
@ -564,6 +690,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="8efb57b6aac3eed66afac34e61facc0795ea1e48ff7b5562cd509fe1496d5a41" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material" version="1.6.2">
|
||||
<artifact name="material-1.6.2.module">
|
||||
<sha256 value="873eb66028dac3a9f2cf1a74ab3599cbe4fe6e76d8aae010e4ac63c6c7213bc7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-android" version="1.5.1">
|
||||
<artifact name="material-android-1.5.1.module">
|
||||
<sha256 value="04ca13bc09df6e513407c21abb214275d410a3c05c4ee31fabf71981b32c1c16" origin="Generated by Gradle"/>
|
||||
|
@ -580,6 +711,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="6ff3b19950724e44348fd122765efdb7f9f58e4c607ca0439f0e15048766b993" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-android" version="1.6.2">
|
||||
<artifact name="material-android-1.6.2.module">
|
||||
<sha256 value="6dd6c2ecf69c46162ea244474fb1c0a344462b198ac404a9202c47af9df416fe" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material-release.aar">
|
||||
<sha256 value="ccc622c03a793a5b0244b44469c939ac6286c78760a4d1af503fec9af5074d27" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-icons-core" version="1.5.1">
|
||||
<artifact name="material-icons-core-1.5.1.module">
|
||||
<sha256 value="bdeafaa32a4cee70b43cf368b570c11e2786cec5ed83a39b270fcfd2fc5873f6" origin="Generated by Gradle"/>
|
||||
|
@ -596,6 +735,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="f8cbd92d3585570dce2541aefef0d59b4c591ae225d98921058e484e9abf3e42" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-icons-core" version="1.6.2">
|
||||
<artifact name="material-icons-core-1.6.2.module">
|
||||
<sha256 value="8e6968839e23734d5d0375445c23dd9cfe5d9a0fbedc6325ab08e3979f77b503" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-icons-core-android" version="1.5.1">
|
||||
<artifact name="material-icons-core-android-1.5.1.module">
|
||||
<sha256 value="2f51667a317486ccc524b4e2e957dde79d267bb86dc71ca5f8e812ca7593538d" origin="Generated by Gradle"/>
|
||||
|
@ -612,6 +756,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="fc2bc75dcd539599a773e3a86dbb3a9899fdc58b65e919751f4a2d77bebbd187" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-icons-core-android" version="1.6.2">
|
||||
<artifact name="material-icons-core-android-1.6.2.module">
|
||||
<sha256 value="9df684d497b70b0b0ebdb643540d5910e26c26a9084cba864947279a134d5aea" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material-icons-core-release.aar">
|
||||
<sha256 value="2440a3afd96b7af29965f23dc497844360ba1258c09e39cce3a258140a3209f2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-icons-core-desktop" version="1.6.2">
|
||||
<artifact name="material-icons-core-desktop-1.6.2.jar">
|
||||
<sha256 value="9ba0b869bf23bd64187c14a72303d604c287d189b095acf2ddd9e772d608f028" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material-icons-core-desktop-1.6.2.module">
|
||||
<sha256 value="224dbceb384a927f973ddbd0973e454cee06c7c0b4b63bb03ca76fc3965e0d99" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-ripple" version="1.5.1">
|
||||
<artifact name="material-ripple-1.5.1.module">
|
||||
<sha256 value="0a66c343a196e90c8c4f6338fc93c574090d1e56d88a2bd05c426b196bdd355e" origin="Generated by Gradle"/>
|
||||
|
@ -628,6 +788,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="aa1bc0c3320609a2a87a689584e21897b5d7dc971b13b656302ba9caa5b2b5df" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-ripple" version="1.6.2">
|
||||
<artifact name="material-ripple-1.6.2.module">
|
||||
<sha256 value="cf3f1909c7d91168fca47bf90ac1546430b6dcc2fb3046dcec9f7a7d23eb2952" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-ripple-android" version="1.5.1">
|
||||
<artifact name="material-ripple-android-1.5.1.module">
|
||||
<sha256 value="0ec0d0dd2cab195b1186c8e4df2a61acb2f9f476d84f40823c904977bf6b0e88" origin="Generated by Gradle"/>
|
||||
|
@ -644,6 +809,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="8a6c8b4bfc8cae9dc7e79653a5de3a482cb9b96d290f6bbdc6d3002b91ed48cb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-ripple-android" version="1.6.2">
|
||||
<artifact name="material-ripple-android-1.6.2.module">
|
||||
<sha256 value="6869707a87beec8e0d15a305eaed7e843c13098807fe2d9cb79cd1d97dcf2f37" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material-ripple-release.aar">
|
||||
<sha256 value="bf79ee469b54fdf07a594206895791a3d2feafc8d0d1d968482b4c917aee7e4e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material" name="material-ripple-desktop" version="1.6.2">
|
||||
<artifact name="material-ripple-desktop-1.6.2.jar">
|
||||
<sha256 value="cd56fbe60dfd619b2990194fe69c711562eae151b7c3e92802878d25088873d0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material-ripple-desktop-1.6.2.module">
|
||||
<sha256 value="e59f78b136a7eda27cfcccba4c0b2db248bfc35064682526668c5cf41bb62760" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material3" name="material3" version="1.1.2">
|
||||
<artifact name="material3-1.1.2.aar">
|
||||
<sha256 value="fd9f8fe91d6661afcaf0e9c9cef30b5a196b4def5b28a370f13f2c259c26e482" origin="Generated by Gradle"/>
|
||||
|
@ -652,6 +833,27 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="c99a42a1546e37872d9a3843b4f9738f66aa93c08a66c54c84f775b3da3e5d97" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material3" name="material3" version="1.2.0">
|
||||
<artifact name="material3-1.2.0.module">
|
||||
<sha256 value="911db8ed8cd7175beff3ea4f69aab68b5ee6c564959a8a27244c27dbd61d1deb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material3" name="material3-android" version="1.2.0">
|
||||
<artifact name="material3-android-1.2.0.module">
|
||||
<sha256 value="c2e180d82471b2ff0b3cc0a0ec9f0eed13467ca609f046c9daca8747aa212840" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material3-release.aar">
|
||||
<sha256 value="10facde8f66f91d61a48c8dfece3b493d630822f311cd20643a23416e4f1ea0c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.material3" name="material3-desktop" version="1.2.0">
|
||||
<artifact name="material3-desktop-1.2.0.jar">
|
||||
<sha256 value="a94d9a46ce014f0166f4875cd30c55bd6d54733266ce281e0e1ed3028bf8ec45" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="material3-desktop-1.2.0.module">
|
||||
<sha256 value="cb5a777ab08f3d0081b12e9f3044e1bcb476d0e09e77d5aae61ea78eef0b90fc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime" version="1.0.1">
|
||||
<artifact name="runtime-1.0.1.module">
|
||||
<sha256 value="2543a8c7edc16bde91f140286b4fd3773d7204a283a4ec99f6e5e286aa92c0c3" origin="Generated by Gradle"/>
|
||||
|
@ -681,6 +883,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="1dd30ce8cca076140ed92ee748c1d35a4ac46b9da435406e353208a07267996d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime" version="1.6.2">
|
||||
<artifact name="runtime-1.6.2.module">
|
||||
<sha256 value="f201d15cc15e7af4720940328bbdc75aa85d9f25b1a97c2eef7b39767f60e831" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-android" version="1.5.1">
|
||||
<artifact name="runtime-android-1.5.1.module">
|
||||
<sha256 value="63d09bac1fe7e3db9a399416e4788dbe0a6b5f79c60b4aa30fec93425ffba9d8" origin="Generated by Gradle"/>
|
||||
|
@ -697,6 +904,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="a7df39bcc1327fa5a7ea5dca2976e11b87feea4ca89d1968cbbb6914f983cd4c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-android" version="1.6.2">
|
||||
<artifact name="runtime-android-1.6.2.module">
|
||||
<sha256 value="c1fe49667f293b6edba6e93b7465ced8b3f518646ff25e0f7daf089efb4501f7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-release.aar">
|
||||
<sha256 value="0363fcf31f147a7d07925818375fc47210676e428c51d168d6bbb4c4f99b0e1a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-desktop" version="1.6.2">
|
||||
<artifact name="runtime-desktop-1.6.2.jar">
|
||||
<sha256 value="5bb2381d819e6b79478ed086ef8fa1be595b16c253ae9774691a4575e4bbcc4a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-desktop-1.6.2.module">
|
||||
<sha256 value="3cfc02c617e773d2449b74634dd1c66c14d1ebac3aca4c1dee2a92b59f876d06" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-livedata" version="1.4.2">
|
||||
<artifact name="runtime-livedata-1.4.2.aar">
|
||||
<sha256 value="caa5f34b824f0df6fbf55cc2a55ffff371d365dbc8383a5faa9f2b57b63276cb" origin="Generated by Gradle"/>
|
||||
|
@ -721,6 +944,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="eac600dec9b802388ccf1d22dc32e2496af99f02fc1ab47c2de3fbf2829226b9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-livedata" version="1.6.2">
|
||||
<artifact name="runtime-livedata-1.6.2.aar">
|
||||
<sha256 value="b58992a123e984aaf6e8e314360b94c57de66fbe85017bdcc3419f3e8eff4011" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-livedata-1.6.2.module">
|
||||
<sha256 value="6f80e019de1986716a805403775e91f92bb6a0142211ff7cd0ba579135c9e110" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-rxjava3" version="1.4.2">
|
||||
<artifact name="runtime-rxjava3-1.4.2.aar">
|
||||
<sha256 value="685877e672f95cf7368ada6e3af07eee107529b6962bf2272b4b1c8d22da7200" origin="Generated by Gradle"/>
|
||||
|
@ -745,6 +976,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="b1770a31b297982f21a01d1f2c243c7a1872cf4eccec7b314aa5d4a00fad9ed5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-rxjava3" version="1.6.2">
|
||||
<artifact name="runtime-rxjava3-1.6.2.aar">
|
||||
<sha256 value="2f326425ffe251bc6b60e764cd890e78cc0eae82012f87f9dfd2237c19d3599f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-rxjava3-1.6.2.module">
|
||||
<sha256 value="3108e86599972b2ecb8a24c263f2426dbb577e24c9f449713f171a1749128bc5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-saveable" version="1.0.1">
|
||||
<artifact name="runtime-saveable-1.0.1.module">
|
||||
<sha256 value="c0d6f142542d8d74f65481ef6526d2be265f01f812a112948fcde87a458f4fb6" origin="Generated by Gradle"/>
|
||||
|
@ -774,6 +1013,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="473560f012448c5ffda939c3b43dd806428d0dfa77b53fe80018942f4555eb4f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-saveable" version="1.6.2">
|
||||
<artifact name="runtime-saveable-1.6.2.module">
|
||||
<sha256 value="616baf3a8570bdb15febe1d9921656fb2bbabb25fa5e8b89fd349a80b415d617" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-saveable-android" version="1.5.1">
|
||||
<artifact name="runtime-saveable-android-1.5.1.module">
|
||||
<sha256 value="173be33938c899999629cd3ab49502fbd8e807454381297bdc0da50bb23afc29" origin="Generated by Gradle"/>
|
||||
|
@ -790,6 +1034,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="5e834c12d7d226a1057e6e70b341cc27414afa2e9d0007660b9dffec6b7673ed" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-saveable-android" version="1.6.2">
|
||||
<artifact name="runtime-saveable-android-1.6.2.module">
|
||||
<sha256 value="9f4d6d7da7fbed7b4213e9285d40e7fdb0e964ffbb6246240c2e2934b974598b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-saveable-release.aar">
|
||||
<sha256 value="2c32aa4864f373996bc035e8efce7b337591b4b42c4b6a0079519f00fe487fe6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.runtime" name="runtime-saveable-desktop" version="1.6.2">
|
||||
<artifact name="runtime-saveable-desktop-1.6.2.jar">
|
||||
<sha256 value="55064d4bd481d67a2840e52c594fc9cbbbf15c9a48f224199bbda005da705df4" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="runtime-saveable-desktop-1.6.2.module">
|
||||
<sha256 value="79c1cb4cd3998d08f145ed2424013c0c69ddf22112b8011e764664f5b20822e5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui" version="1.0.1">
|
||||
<artifact name="ui-1.0.1.aar">
|
||||
<sha256 value="1943daa4a3412861b9a2bdc1a7c8c2ff05d9b8191c1d3e56ebb223d2eb4a8526" origin="Generated by Gradle"/>
|
||||
|
@ -814,6 +1074,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="16047bacd8b5409b6b2c57a4761789dff9e6e93e6d35921846c364fcf3dfa1de" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui" version="1.6.2">
|
||||
<artifact name="ui-1.6.2.module">
|
||||
<sha256 value="af19eba05e4b1e56b1e61373c823a548782dc7bfadbc04fb43f13157214a5a28" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-android" version="1.5.1">
|
||||
<artifact name="ui-android-1.5.1.module">
|
||||
<sha256 value="a682e72c4f1a27387eaaf269679e62dc35e7398aae48fe099cf20b4f6cc1c04e" origin="Generated by Gradle"/>
|
||||
|
@ -830,6 +1095,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="13f39a8f0bfaf621ab57f77ad022d482b5f2b14803a5623cc4fdca2ef905ca26" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-android" version="1.6.2">
|
||||
<artifact name="ui-android-1.6.2.module">
|
||||
<sha256 value="56694bbe7c44c15bdc2bdece7e6441becc7bab708877b4eca11c845b95471755" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-release.aar">
|
||||
<sha256 value="9cd47d5634c08497920151d687942d11e4fe2a365255f089612d1cff724cb67a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-desktop" version="1.6.2">
|
||||
<artifact name="ui-desktop-1.6.2.jar">
|
||||
<sha256 value="45c06c1d10faad5fbe32fbd89e3d084281ccb8ae3d1318392410782e741ab948" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-desktop-1.6.2.module">
|
||||
<sha256 value="0c544e4a8b68d8a0a1188525a5e6d4fcd702f152c51ad4bf9f51176075ff3425" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-geometry" version="1.0.1">
|
||||
<artifact name="ui-geometry-1.0.1.aar">
|
||||
<sha256 value="04dcea79de0af8347f4517bec20578d4240ae5ee40191020ca07d7a38e640033" origin="Generated by Gradle"/>
|
||||
|
@ -854,6 +1135,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="1dd30ce8cca076140ed92ee748c1d35a4ac46b9da435406e353208a07267996d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-geometry" version="1.6.2">
|
||||
<artifact name="ui-geometry-1.6.2.module">
|
||||
<sha256 value="13e4ecec3172d7751115804d7121bd895357a33f8703e690b33677f062b13fbc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-geometry-android" version="1.5.1">
|
||||
<artifact name="ui-geometry-android-1.5.1.module">
|
||||
<sha256 value="1550bbf0c36e52e60ec9fbb896221115213ccd68296cacdfe62a4d3ea951b0f5" origin="Generated by Gradle"/>
|
||||
|
@ -870,6 +1156,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="2ecd05d0c033325304834a361d3e5f2c01395bfc5da2402641cfcee4981a01a9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-geometry-android" version="1.6.2">
|
||||
<artifact name="ui-geometry-android-1.6.2.module">
|
||||
<sha256 value="13edbe112aa62e29223d4583f4cfe5aef1a0b939de370c2a48cf65a594aae312" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-geometry-release.aar">
|
||||
<sha256 value="74ed23d23fe42cc75a5619575c188ddbe552272d8308c58a864b6e75d8063bdb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-geometry-desktop" version="1.6.2">
|
||||
<artifact name="ui-geometry-desktop-1.6.2.jar">
|
||||
<sha256 value="c5ca7579c17710fac77ed93137411531298cca559c8514c9076bc0f2683da350" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-geometry-desktop-1.6.2.module">
|
||||
<sha256 value="eba16975cac4719f4af6945c61d7cd84ad8072a667c49a0193d887bca3a838de" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-graphics" version="1.0.1">
|
||||
<artifact name="ui-graphics-1.0.1.aar">
|
||||
<sha256 value="6b7f5d0c944483ea390b3d6da8438e7a69e0cfe310bd16c3c5e78ac0015b1663" origin="Generated by Gradle"/>
|
||||
|
@ -894,6 +1196,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="1f0880be97e83fd8e86ce0374937cd6947d3380a2df5ff4bb7cac47587dd601a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-graphics" version="1.6.2">
|
||||
<artifact name="ui-graphics-1.6.2.module">
|
||||
<sha256 value="a54e070d593f2f41c362e800c79ce5664ad795b7e0fb7e9c4c2f25ff234bfa12" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-graphics-android" version="1.5.1">
|
||||
<artifact name="ui-graphics-android-1.5.1.module">
|
||||
<sha256 value="6334183295fc3bf67230dad0b7fee097429ff61df500ee62fdaf22e82eaa11b7" origin="Generated by Gradle"/>
|
||||
|
@ -910,6 +1217,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="8f7811d34f178e2de66399e8b0fd747db3502a9b844a4e2d946a711e75655cbc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-graphics-android" version="1.6.2">
|
||||
<artifact name="ui-graphics-android-1.6.2.module">
|
||||
<sha256 value="bd3787bfb69eae61dafa93eb689e7eb68bb8154be7ca23bac37f36bfe9a22efc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-graphics-release.aar">
|
||||
<sha256 value="5a2b95861592e9f698d7ce9c6acb1eca008401802f75567efd609b628840970a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-graphics-desktop" version="1.6.2">
|
||||
<artifact name="ui-graphics-desktop-1.6.2.jar">
|
||||
<sha256 value="7d6f9ffc9804cdec9c270abe37c06dbb847fe42b8d316caa73b8135752b7dd66" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-graphics-desktop-1.6.2.module">
|
||||
<sha256 value="0e6e228fb9ca8304e2b537b01d5a3968f1740064359d16805a155f7bdc9f8e62" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-test-manifest" version="1.5.1">
|
||||
<artifact name="ui-test-manifest-1.5.1.aar">
|
||||
<sha256 value="449a954b2b9908c0fb6faeada91e54749ce2cbb794e4bb0c03d5d27ae1115281" origin="Generated by Gradle"/>
|
||||
|
@ -955,6 +1278,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="56968bd3be7d2bac45fd75252ac9b5f390601b44243d2a410926e6c0cd4f151f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-text" version="1.6.2">
|
||||
<artifact name="ui-text-1.6.2.module">
|
||||
<sha256 value="1e16728e46acba7422c668bb43c65103d11a3f03d338e4bab8148123ddf30c13" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-text-android" version="1.5.1">
|
||||
<artifact name="ui-text-android-1.5.1.module">
|
||||
<sha256 value="b6e932a918a9344d8f7e2f086a6b962d031d733678d6bbf6f6be4bd4a15f5259" origin="Generated by Gradle"/>
|
||||
|
@ -971,6 +1299,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="1633dd54142169a5066580f9a580d2660c790fc1b68c2e533c36a9c0f8b10abb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-text-android" version="1.6.2">
|
||||
<artifact name="ui-text-android-1.6.2.module">
|
||||
<sha256 value="f292c95185b433eb4b5a15a561002ab078ce835aa341ddbc625c2c9ddef0df0c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-text-release.aar">
|
||||
<sha256 value="398cc1df7c583e48bae632b94573c509a134a8184af1ff4e7bc2e457e13fe513" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-text-desktop" version="1.6.2">
|
||||
<artifact name="ui-text-desktop-1.6.2.jar">
|
||||
<sha256 value="098ae9f6453b9a1b1fa5f77b8db2f0d0b372fe83ebcab5e5975f737946cc8ea1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-text-desktop-1.6.2.module">
|
||||
<sha256 value="f79fa0346d1a12aeacf9c854330b92c122b95fc28b59d1f9a69db1dd59801d11" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling" version="1.5.1">
|
||||
<artifact name="ui-tooling-1.5.1.module">
|
||||
<sha256 value="c217d8b53be36c3562f01bd2474c0244d1924ba6130f6bc5abf42ab277309087" origin="Generated by Gradle"/>
|
||||
|
@ -987,6 +1331,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="5180afdae77bb0f37b309c31a457641919ebb84012dde2abe93951fe070de3d7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling" version="1.6.2">
|
||||
<artifact name="ui-tooling-1.6.2.module">
|
||||
<sha256 value="0af4130b88c1acf0cd7a4bab8e616d02aa8c786caa44ad3fdf676a86f1b27654" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-android" version="1.5.1">
|
||||
<artifact name="ui-tooling-android-1.5.1.module">
|
||||
<sha256 value="f6559c93178b465f2fb8250f1cdf9dbf5f4845957f87b72a84a62d31b65f1ab3" origin="Generated by Gradle"/>
|
||||
|
@ -1003,6 +1352,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="d7459ec30b27d1bd3e922fc69db1e27206a0721d825df44ffc7ef15842124264" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-android" version="1.6.2">
|
||||
<artifact name="ui-tooling-android-1.6.2.module">
|
||||
<sha256 value="6741e075c9ad6b02439bc25b362055d9859da51c38fcdfacb0e5def5435a3862" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-release.aar">
|
||||
<sha256 value="dfef530da1a4f809fb58471e2d0f39801ee2f5426a992adf164e687ffc43de1e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-data" version="1.5.1">
|
||||
<artifact name="ui-tooling-data-1.5.1.module">
|
||||
<sha256 value="7a6133f6aed027d45a8fd51d8f90c971b0f97f5893a5d720d994a903dab86d82" origin="Generated by Gradle"/>
|
||||
|
@ -1019,6 +1376,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="d13169117f6de9a39383c21087cc3a2a2c68f83b5d3d75f5e35bc91996662d66" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-data" version="1.6.2">
|
||||
<artifact name="ui-tooling-data-1.6.2.module">
|
||||
<sha256 value="e28c62dc2ee0d24f80246df240edcafd607bbac71af5953bb0a814692a1e00c5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-data-android" version="1.5.1">
|
||||
<artifact name="ui-tooling-data-android-1.5.1.module">
|
||||
<sha256 value="41a1a7e6603302598e1c28535ce7fdf7d66218057f4d8f1ddadd4b7a1bd7e444" origin="Generated by Gradle"/>
|
||||
|
@ -1035,6 +1397,30 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="d8185c38707f10d094458ab5b8026de93916d925876b32ac53278b1113f66bf1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-data-android" version="1.6.2">
|
||||
<artifact name="ui-tooling-data-android-1.6.2.module">
|
||||
<sha256 value="521e06044f639b015125383d23121caa6adfc37d5607a00b848cd8b4553e9829" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-data-release.aar">
|
||||
<sha256 value="6a04bac6a0636f3838ac30abf6bd509f4318c934e5ff796830a0c46b2d02e8dd" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-data-desktop" version="1.6.2">
|
||||
<artifact name="ui-tooling-data-desktop-1.6.2.jar">
|
||||
<sha256 value="e217a177e64d450f68c43964d221afe92bee3b096bb02e9a9644bf23c210aae7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-data-desktop-1.6.2.module">
|
||||
<sha256 value="f9b6072ea7378c710e7f9bd488c5b063774262df7cbc1c1d8730bead15303c22" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-desktop" version="1.6.2">
|
||||
<artifact name="ui-tooling-desktop-1.6.2.jar">
|
||||
<sha256 value="b1fafbd90b0a84b22082e8cebd7761d52b1ce8db6c6cf28fcc76204ee1cfb909" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-desktop-1.6.2.module">
|
||||
<sha256 value="bd95a0db3fbb9a66b91793dfafebc83f6f976a3d970905a15ddde9783c2fd784" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-preview" version="1.5.1">
|
||||
<artifact name="ui-tooling-preview-1.5.1.module">
|
||||
<sha256 value="7c0fd4f5a53604092325e58eb735002d16f94e6c646ba26b9e5e7496f444c7b9" origin="Generated by Gradle"/>
|
||||
|
@ -1051,6 +1437,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="473560f012448c5ffda939c3b43dd806428d0dfa77b53fe80018942f4555eb4f" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-preview" version="1.6.2">
|
||||
<artifact name="ui-tooling-preview-1.6.2.module">
|
||||
<sha256 value="27a950500f7ad19d930c2d4efb1ffd2768f9e1febc4b0ba6cb71900aefabea2c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-preview-android" version="1.5.1">
|
||||
<artifact name="ui-tooling-preview-android-1.5.1.module">
|
||||
<sha256 value="f5c9fc4eb46a414f55f1e6ba39ca0af84a6399b7ac4f8ff77efcf52cbc2da38e" origin="Generated by Gradle"/>
|
||||
|
@ -1067,6 +1458,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="1263288480372dbfb54d63234e9cabfa7f94b13a5ba108d06c4aa1976dbbaade" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-preview-android" version="1.6.2">
|
||||
<artifact name="ui-tooling-preview-android-1.6.2.module">
|
||||
<sha256 value="bb08b9adb59b2f4bd8beea04778500d5ea6408c5166f8ff70a81ed51222ad1a7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-preview-release.aar">
|
||||
<sha256 value="ee041736f6830ac77b1ded08071d679b45306325f6dd4c5426bbea31fddca3c6" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-tooling-preview-desktop" version="1.6.2">
|
||||
<artifact name="ui-tooling-preview-desktop-1.6.2.jar">
|
||||
<sha256 value="1b531c5ec345d60ff880895988e065c39b4d42c3e2cf57f811c2daa7fb2c7322" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-tooling-preview-desktop-1.6.2.module">
|
||||
<sha256 value="e9d2f5a1edaed9a048d0a7c83ed34c7c3b44c700b3fe1bfa5e64fe7df3cf2617" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-unit" version="1.0.1">
|
||||
<artifact name="ui-unit-1.0.1.aar">
|
||||
<sha256 value="75b13e2a15da8a31acf75d81c4277ff2820b1bf58291b4688ac55200cdc18072" origin="Generated by Gradle"/>
|
||||
|
@ -1091,6 +1498,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="a122255bc8f3d7fe1ad1aa4d971508ae552a0c60d05b9c82400f05e579984df1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-unit" version="1.6.2">
|
||||
<artifact name="ui-unit-1.6.2.module">
|
||||
<sha256 value="cde1d8e6671e4f1a14f8c737a63dbdd91fe0232e240f145b3c29c297bdf76dd9" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-unit-android" version="1.5.1">
|
||||
<artifact name="ui-unit-android-1.5.1.module">
|
||||
<sha256 value="59b1f7938cd9ef40fa13550be3798e6466849460386d2b00a9489442690e544b" origin="Generated by Gradle"/>
|
||||
|
@ -1107,6 +1519,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="ac753ab129b70bab79cfea691ed6bc8ec20fde278db7269b94f50227a712302e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-unit-android" version="1.6.2">
|
||||
<artifact name="ui-unit-android-1.6.2.module">
|
||||
<sha256 value="47bb7662d40774f8aa095b3e73021e1be126a8b9b458c028f29e0c710012a9ec" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-unit-release.aar">
|
||||
<sha256 value="4294337fae5c9eb06b75439093f4d39a3c4a4e3f708c15ee2535790a070d5a64" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-unit-desktop" version="1.6.2">
|
||||
<artifact name="ui-unit-desktop-1.6.2.jar">
|
||||
<sha256 value="eed875aeb6593f2c2548184957f612a3c971c61f4f26ed23893e74dffe4cccc0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-unit-desktop-1.6.2.module">
|
||||
<sha256 value="376c2a185177a53cd28c9f90f1feeb16e8315bb695ded62502166ad5cb6dfe6c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-util" version="1.0.0">
|
||||
<artifact name="ui-util-1.0.0.module">
|
||||
<sha256 value="a09871728e5a9d050d2fdcb99a875ef2120dc6deea808f5a6d443dd887e081ca" origin="Generated by Gradle"/>
|
||||
|
@ -1122,6 +1550,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="18b8add303065a8c078fc908584a1a9fe9887df49025e15eb64ee6251d306e4e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-util" version="1.6.2">
|
||||
<artifact name="ui-util-1.6.2.module">
|
||||
<sha256 value="d9c2cb14d2882994f4451da34c1efe81568278ffb5bd9dd37ec7c75f8a2be934" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-util-android" version="1.5.1">
|
||||
<artifact name="ui-util-android-1.5.1.module">
|
||||
<sha256 value="d6574ccd75f47ac2b2733095ab06c683ec23eb0cbe2e842c9a9bc3a62a825a6c" origin="Generated by Gradle"/>
|
||||
|
@ -1138,6 +1571,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="02cd59abbccf95fef2825ba4c0871255380c6f5ba3eaea85b1892de24b4e6b50" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-util-android" version="1.6.2">
|
||||
<artifact name="ui-util-android-1.6.2.module">
|
||||
<sha256 value="86e955e15e2ac19f886bca2be157f04bdf60b716211f6a376823e02a6a0f7944" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-util-release.aar">
|
||||
<sha256 value="05eb30cd374cdf91a69b2a1ab5a1ee41cae9f2576918adc5e0e20f6c42f4142e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.compose.ui" name="ui-util-desktop" version="1.6.2">
|
||||
<artifact name="ui-util-desktop-1.6.2.jar">
|
||||
<sha256 value="0cb9f941d92bb60e2c8deaac1ec8312d9484dce01eacec33003675525ae5915c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="ui-util-desktop-1.6.2.module">
|
||||
<sha256 value="0c29231f79c66100409d3202ef8fe1e942feda555ae2be8ff91710491b14c1ca" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.concurrent" name="concurrent-futures" version="1.0.0">
|
||||
<artifact name="concurrent-futures-1.0.0.jar">
|
||||
<sha256 value="5595a40e278a7b39fa78a09490e3d7f3faa95c7b01447148bd38b5ade0605c35" origin="Generated by Gradle"/>
|
||||
|
@ -1357,6 +1806,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="9d1996cca03777baa1f27cd15531db983a633dae37b90f85bd53501acb56699d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.emoji2" name="emoji2" version="1.3.0">
|
||||
<artifact name="emoji2-1.3.0.aar">
|
||||
<sha256 value="2bf23818b23a996ddaa1b5fd5bb32129daff6bbb2dce15166e2fccdd2010b1a5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="emoji2-1.3.0.module">
|
||||
<sha256 value="ddc851edba65fd15a7a1bc3ad18648e2f732dd5ad8ef3602224bce0647f5b4d1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.emoji2" name="emoji2" version="1.4.0">
|
||||
<artifact name="emoji2-1.4.0.aar">
|
||||
<sha256 value="433febd3434a45667176c76a64f3f205ca6335a6b544c5b5d57f25a38a375242" origin="Generated by Gradle"/>
|
||||
|
@ -1373,6 +1830,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="a3a9db581abf1787b01ff15c40f059530e8e64f3937caa2d788f42eb39893268" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.emoji2" name="emoji2-views-helper" version="1.3.0">
|
||||
<artifact name="emoji2-views-helper-1.3.0.aar">
|
||||
<sha256 value="9a1351295a4f739df0efe8344adaa9afb34856c3af584d4a9afbec105a45b90b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="emoji2-views-helper-1.3.0.module">
|
||||
<sha256 value="09974bb5ef9780de9d56715d71171a35c78fb2e17fd865773b0c83a3acac039c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.emoji2" name="emoji2-views-helper" version="1.4.0">
|
||||
<artifact name="emoji2-views-helper-1.4.0.aar">
|
||||
<sha256 value="ed5d3ed772a5fbf0d570f7526f585cd61a180e60f9372584c328a68e2cff3375" origin="Generated by Gradle"/>
|
||||
|
@ -2464,6 +2929,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="48f6b212e8f566a50b7188ce80a2648777c1624350975335cda139be0f34f720" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.airbnb.android" name="lottie" version="6.4.0">
|
||||
<artifact name="lottie-6.4.0.aar">
|
||||
<sha256 value="d6cf3be2c56fa250c96a86eb0baf8a7dfc3cc92b7e728a74f8851f9ad9fec2ba" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="lottie-6.4.0.module">
|
||||
<sha256 value="5c1d2787b267c5a023b13d252f9a9ab1b6aa3b86f083ae7ce2ccfec13a10290d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.airbnb.android" name="lottie-compose" version="6.4.0">
|
||||
<artifact name="lottie-compose-6.4.0.aar">
|
||||
<sha256 value="0db0405db586246750b3c2139dc840697623f0a0a3dff68041f41ca2ff408509" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="lottie-compose-6.4.0.module">
|
||||
<sha256 value="036310ba164264e7603dd050c25dc1b4b40e40672e2748573a7527da571a4844" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.almworks.sqlite4java" name="sqlite4java" version="1.0.392">
|
||||
<artifact name="sqlite4java-1.0.392.jar">
|
||||
<sha256 value="243a64470fda0e86a6fddeb0af4c7aa9426ce84e68cbfe18d75ee5da4b7e0b92" origin="Generated by Gradle"/>
|
||||
|
@ -6948,6 +7429,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.9.22">
|
||||
<artifact name="kotlin-stdlib-1.9.22-all.jar">
|
||||
<sha256 value="cec38bc3302e72a8aaf9cde436b5a9071ee0331e2ad05e84d8bb897334d7e9d4" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="kotlin-stdlib-1.9.22.jar">
|
||||
<sha256 value="6abe146c27864138b874ccccfe5f534e3eb923c99a1b7b5d45494ee5694f3e0a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
|
@ -7326,6 +7810,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="2eb0b5c00791576c33079a0750ef3ded335c180f60043d51a19c799f8b737bc5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-swing" version="1.8.1">
|
||||
<artifact name="kotlinx-coroutines-swing-1.8.1.jar">
|
||||
<sha256 value="0c809e79dc64ab5bc9b790389fe491cc19d3574345a431276966fbc09994a659" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="kotlinx-coroutines-swing-1.8.1.module">
|
||||
<sha256 value="2915188bf6dde89157cccb480bfa1249f010917a8e1fad340c9dbef6d7e0229b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core" version="1.0.1">
|
||||
<artifact name="kotlinx-serialization-core-1.0.1.module">
|
||||
<sha256 value="9d0f1f6db25e394c89d58838eaebf3eabe360ef8ceb98aa3b9a4283532a54077" origin="Generated by Gradle"/>
|
||||
|
@ -7391,6 +7883,19 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
|
|||
<sha256 value="c8fbfde4b5ee1e41a69175165e839991d1501665a7590e23162326501ac6122c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.skiko" name="skiko" version="0.7.7">
|
||||
<artifact name="skiko-0.7.7.module">
|
||||
<sha256 value="96b0bc4f70cc6c9dcace55897019eac065c56ab334b615832b23b7babdbf2cbb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.skiko" name="skiko-awt" version="0.7.7">
|
||||
<artifact name="skiko-awt-0.7.7.jar">
|
||||
<sha256 value="93c02a8d773e38d8081d565f83dc14c7e9c9e1607ae4f8791811dbd636711ce3" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="skiko-awt-0.7.7.module">
|
||||
<sha256 value="aa18d148903a8057e0cefc0a2ade4df408ea757a19c467ea68b826edcfcd7d5c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jlleitschuh.gradle" name="ktlint-gradle" version="11.1.0">
|
||||
<artifact name="ktlint-gradle-11.1.0.jar">
|
||||
<sha256 value="f2114379e18faca0f9bd90bdf4936e6484d0b4a85a3a94bcd12d5c102a339281" origin="Generated by Gradle"/>
|
||||
|
|
|
@ -23,6 +23,7 @@ class QrScannerView @JvmOverloads constructor(
|
|||
|
||||
private var scannerView: ScannerView? = null
|
||||
private val qrDataPublish: PublishSubject<String> = PublishSubject.create()
|
||||
private var forceLegacy: Boolean = false
|
||||
|
||||
val qrData: Observable<String> = qrDataPublish
|
||||
|
||||
|
@ -37,12 +38,14 @@ class QrScannerView @JvmOverloads constructor(
|
|||
addView(scannerView)
|
||||
|
||||
this.scannerView = (scannerView as ScannerView)
|
||||
this.forceLegacy = forceLegacy
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun start(lifecycleOwner: LifecycleOwner, forceLegacy: Boolean = false) {
|
||||
if (scannerView != null) {
|
||||
Log.w(TAG, "Attempt to start scanning that has already started")
|
||||
scannerView?.resume()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -61,6 +64,14 @@ class QrScannerView @JvmOverloads constructor(
|
|||
scannerView?.toggleCamera()
|
||||
}
|
||||
|
||||
// Biometrics require use of camera so we disable when needed
|
||||
fun destroy() {
|
||||
scannerView?.destroy()
|
||||
if (!forceLegacy) {
|
||||
scannerView = null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(QrScannerView::class.java)
|
||||
}
|
||||
|
|
|
@ -8,4 +8,6 @@ import androidx.lifecycle.LifecycleOwner
|
|||
interface ScannerView {
|
||||
fun start(lifecycleOwner: LifecycleOwner)
|
||||
fun toggleCamera()
|
||||
fun resume()
|
||||
fun destroy()
|
||||
}
|
||||
|
|
|
@ -59,4 +59,16 @@ internal class ScannerView19 constructor(
|
|||
lifecycleObserver.onResume(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resume() {
|
||||
lifecycleOwner?.let {
|
||||
lifecycleObserver.onResume(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun destroy() {
|
||||
lifecycleOwner?.let {
|
||||
lifecycleObserver.onPause(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ internal class ScannerView21 constructor(
|
|||
|
||||
private val lifecycleObserver: DefaultLifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
cameraProvider?.unbindAll()
|
||||
cameraProvider = null
|
||||
camera = null
|
||||
analyzerExecutor.shutdown()
|
||||
|
@ -78,6 +79,14 @@ internal class ScannerView21 constructor(
|
|||
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
|
||||
}
|
||||
|
||||
override fun resume() = Unit
|
||||
|
||||
override fun destroy() {
|
||||
lifecyleOwner?.let {
|
||||
lifecycleObserver.onDestroy(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCameraProvider(lifecycle: LifecycleOwner, cameraProvider: ProcessCameraProvider?) {
|
||||
if (cameraProvider == null) {
|
||||
Log.w(TAG, "Camera provider is null")
|
||||
|
|
Loading…
Add table
Reference in a new issue