Updated on 2026-08-14
This commit is contained in:
commit
6d0b295ca3
219 changed files with 3720 additions and 1687 deletions
|
|
@ -20,6 +20,7 @@ dependencies {
|
|||
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
implementation(deps.androidx.activity.compose)
|
||||
implementation(deps.lifecycle.compose)
|
||||
|
||||
/** Camera */
|
||||
implementation(deps.camera.camera2)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.qrscanning
|
|||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -13,14 +14,16 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.google.mlkit.vision.common.InputImage
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer
|
||||
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningContent
|
||||
import com.tangem.feature.qrscanning.viewmodel.QrScanningViewModel
|
||||
import com.tangem.feature.qrscanning.inner.MLKitBarcodeAnalyzer
|
||||
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
|
@ -49,12 +52,19 @@ internal class QrScanningFragment : ComposeFragment() {
|
|||
}
|
||||
|
||||
private val cameraPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||
if (!it) parentFragmentManager.popBackStack()
|
||||
if (!it) viewModel.onCameraDeniedState()
|
||||
}
|
||||
private val galleryLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
val selectedImage = it ?: Uri.EMPTY
|
||||
if (selectedImage != Uri.EMPTY) {
|
||||
val image = InputImage.fromFilePath(requireContext(), selectedImage)
|
||||
analyzer.analyze(image)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
viewModel.router = innerRouter
|
||||
viewModel.setRouter(innerRouter, galleryLauncher)
|
||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||
requestCameraPermission()
|
||||
}
|
||||
|
|
@ -71,7 +81,7 @@ internal class QrScanningFragment : ComposeFragment() {
|
|||
QrScanningContent(
|
||||
executor = { cameraExecutor },
|
||||
analyzer = { analyzer },
|
||||
uiState = viewModel.uiState,
|
||||
uiState = viewModel.uiState.collectAsStateWithLifecycle().value,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
|
||||
data class CameraDeniedBottomSheetConfig(
|
||||
val onGalleryClick: () -> Unit,
|
||||
val onCancelClick: () -> Unit,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.tangem.core.ui.components.SimpleSettingsRow
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.qrscanning.impl.R
|
||||
|
||||
@Composable
|
||||
fun CameraDeniedBottomSheet(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet(config) { content: CameraDeniedBottomSheetConfig ->
|
||||
CameraDeniedBottomSheet(content = content)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CameraDeniedBottomSheet(content: CameraDeniedBottomSheetConfig) {
|
||||
val context = LocalContext.current
|
||||
Column {
|
||||
CameraDeniedBottomSheetHeader()
|
||||
SimpleSettingsRow(
|
||||
title = stringResource(id = R.string.qr_scanner_camera_denied_settings_button),
|
||||
icon = R.drawable.ic_settings_24,
|
||||
onItemsClick = {
|
||||
val intent: Intent = Intent(
|
||||
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||
Uri.fromParts("package", context.packageName, null),
|
||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ContextCompat.startActivity(context, intent, null)
|
||||
},
|
||||
)
|
||||
SimpleSettingsRow(
|
||||
title = stringResource(id = R.string.qr_scanner_camera_denied_gallery_button),
|
||||
icon = R.drawable.ic_gallery_24,
|
||||
onItemsClick = content.onGalleryClick,
|
||||
)
|
||||
SimpleSettingsRow(
|
||||
title = stringResource(id = R.string.common_close),
|
||||
icon = R.drawable.ic_close,
|
||||
onItemsClick = content.onCancelClick,
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CameraDeniedBottomSheetHeader() {
|
||||
Text(
|
||||
text = stringResource(id = R.string.qr_scanner_camera_denied_title),
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing20,
|
||||
end = TangemTheme.dimens.spacing20,
|
||||
top = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.qr_scanner_camera_denied_text),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing20,
|
||||
end = TangemTheme.dimens.spacing20,
|
||||
top = TangemTheme.dimens.spacing3,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.*
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
|
|
@ -18,14 +19,12 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.graphics.PathEffect
|
||||
import androidx.compose.ui.graphics.StrokeJoin
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.drawText
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import com.google.mlkit.vision.common.InputImage
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIconContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
|
|
@ -44,15 +43,9 @@ internal fun QrScanningContent(
|
|||
analyzer: () -> MLKitBarcodeAnalyzer,
|
||||
uiState: QrScanningState,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var isFlash by remember { mutableStateOf(false) }
|
||||
val galleryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
val selectedImage = it ?: Uri.EMPTY
|
||||
if (selectedImage != Uri.EMPTY) {
|
||||
val image = InputImage.fromFilePath(context, selectedImage)
|
||||
analyzer().analyze(image)
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler(onBack = uiState.onBackClick)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -101,13 +94,16 @@ internal fun QrScanningContent(
|
|||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false),
|
||||
onClick = { galleryLauncher.launch("image/*") },
|
||||
onClick = uiState.onGalleryClick,
|
||||
),
|
||||
tint = TangemColorPalette.White,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
if (uiState.bottomSheetConfig != null) {
|
||||
CameraDeniedBottomSheet(uiState.bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
@Immutable
|
||||
|
|
@ -8,5 +9,6 @@ data class QrScanningState(
|
|||
val message: TextReference?,
|
||||
val onQrScanned: (String) -> Unit,
|
||||
val onBackClick: () -> Unit,
|
||||
val onGalleryClicked: () -> Unit,
|
||||
val onGalleryClick: () -> Unit,
|
||||
val bottomSheetConfig: TangemBottomSheetConfig? = null,
|
||||
)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
|
||||
import com.tangem.feature.qrscanning.presentation.transformers.QrScanningTransformer
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class QrScanningStateController @Inject constructor() {
|
||||
|
||||
val uiState: StateFlow<QrScanningState> get() = mutableUiState
|
||||
|
||||
val value: QrScanningState get() = uiState.value
|
||||
|
||||
private val mutableUiState: MutableStateFlow<QrScanningState> = MutableStateFlow(value = getInitialState())
|
||||
|
||||
fun update(function: (QrScanningState) -> QrScanningState) {
|
||||
mutableUiState.update(function = function)
|
||||
}
|
||||
|
||||
fun update(transformer: QrScanningTransformer) {
|
||||
mutableUiState.update(function = transformer::transform)
|
||||
}
|
||||
|
||||
private fun getInitialState(): QrScanningState {
|
||||
return QrScanningState(
|
||||
message = null,
|
||||
onBackClick = {},
|
||||
onQrScanned = {},
|
||||
onGalleryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.feature.qrscanning.presentation.transformers
|
||||
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
|
||||
internal class DismissBottomSheetTransformer : QrScanningTransformer {
|
||||
override fun transform(prevState: QrScanningState): QrScanningState {
|
||||
return prevState.copy(
|
||||
bottomSheetConfig = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
package com.tangem.feature.qrscanning.presentation
|
||||
package com.tangem.feature.qrscanning.presentation.transformers
|
||||
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.feature.qrscanning.viewmodel.QrScanningClickIntents
|
||||
import com.tangem.feature.qrscanning.SourceType
|
||||
import com.tangem.feature.qrscanning.impl.R
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
import com.tangem.feature.qrscanning.viewmodel.QrScanningClickIntents
|
||||
|
||||
internal class QrScanningStateFactory(
|
||||
val clickIntents: QrScanningClickIntents,
|
||||
) {
|
||||
internal class InitializeQrScanningStateTransformer(
|
||||
private val clickIntents: QrScanningClickIntents,
|
||||
private val source: SourceType,
|
||||
private val network: String?,
|
||||
) : QrScanningTransformer {
|
||||
|
||||
fun getInitialState(source: SourceType, network: String?): QrScanningState {
|
||||
override fun transform(prevState: QrScanningState): QrScanningState {
|
||||
val message = when (source) {
|
||||
SourceType.SEND -> network?.let { resourceReference(R.string.send_qrcode_scan_info, wrappedList(it)) }
|
||||
else -> null
|
||||
|
|
@ -20,7 +23,7 @@ internal class QrScanningStateFactory(
|
|||
message = message,
|
||||
onBackClick = clickIntents::onBackClick,
|
||||
onQrScanned = clickIntents::onQrScanned,
|
||||
onGalleryClicked = clickIntents::onGalleryClicked,
|
||||
onGalleryClick = clickIntents::onGalleryClicked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.feature.qrscanning.presentation.transformers
|
||||
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
|
||||
internal interface QrScanningTransformer {
|
||||
|
||||
fun transform(prevState: QrScanningState): QrScanningState
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.feature.qrscanning.presentation.transformers
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.feature.qrscanning.presentation.CameraDeniedBottomSheetConfig
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
import com.tangem.feature.qrscanning.viewmodel.QrScanningClickIntents
|
||||
|
||||
internal class ShowCameraDeniedBottomSheetTransformer(
|
||||
private val clickIntents: QrScanningClickIntents,
|
||||
) : QrScanningTransformer {
|
||||
|
||||
override fun transform(prevState: QrScanningState): QrScanningState {
|
||||
return prevState.copy(
|
||||
bottomSheetConfig = TangemBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = clickIntents::onBackClick,
|
||||
content = CameraDeniedBottomSheetConfig(
|
||||
onCancelClick = clickIntents::onBackClick,
|
||||
onGalleryClick = clickIntents::onGalleryClicked,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.feature.qrscanning.viewmodel
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import com.tangem.feature.qrscanning.SourceType
|
||||
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
internal open class BaseQrScanningClickIntents {
|
||||
|
||||
protected val router: QrScanningInnerRouter get() = _router
|
||||
protected val viewModelScope: CoroutineScope get() = _viewModelScope
|
||||
protected val source: SourceType get() = _source
|
||||
protected val galleryLauncher: ActivityResultLauncher<String> get() = _galleryLauncher
|
||||
|
||||
private var _router: QrScanningInnerRouter by Delegates.notNull()
|
||||
private var _viewModelScope: CoroutineScope by Delegates.notNull()
|
||||
private var _source: SourceType by Delegates.notNull()
|
||||
|
||||
private var _galleryLauncher: ActivityResultLauncher<String> by Delegates.notNull()
|
||||
|
||||
open fun initialize(
|
||||
router: QrScanningInnerRouter,
|
||||
source: SourceType,
|
||||
galleryLauncher: ActivityResultLauncher<String>,
|
||||
coroutineScope: CoroutineScope,
|
||||
) {
|
||||
_router = router
|
||||
_viewModelScope = coroutineScope
|
||||
_source = source
|
||||
_galleryLauncher = galleryLauncher
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,13 @@
|
|||
package com.tangem.feature.qrscanning.viewmodel
|
||||
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningStateController
|
||||
import com.tangem.feature.qrscanning.presentation.transformers.DismissBottomSheetTransformer
|
||||
import com.tangem.feature.qrscanning.usecase.EmitQrScannedEventUseCase
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
interface QrScanningClickIntents {
|
||||
|
||||
fun onBackClick()
|
||||
|
|
@ -7,4 +15,39 @@ interface QrScanningClickIntents {
|
|||
fun onQrScanned(qrCode: String)
|
||||
|
||||
fun onGalleryClicked()
|
||||
}
|
||||
|
||||
@ViewModelScoped
|
||||
internal class QrScanningClickIntentsImplementor @Inject constructor(
|
||||
private val stateHolder: QrScanningStateController,
|
||||
private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase,
|
||||
private val dispatcher: CoroutineDispatcherProvider,
|
||||
) : BaseQrScanningClickIntents(), QrScanningClickIntents {
|
||||
|
||||
private var isScanned = false
|
||||
|
||||
override fun onBackClick() = router.popBackStack()
|
||||
|
||||
override fun onQrScanned(qrCode: String) {
|
||||
if (qrCode.isNotBlank()) {
|
||||
if (!isScanned) {
|
||||
router.popBackStack()
|
||||
isScanned = true
|
||||
}
|
||||
viewModelScope.launch(dispatcher.main) {
|
||||
emitQrScannedEventUseCase.invoke(source, qrCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGalleryClicked() {
|
||||
galleryLauncher.launch(GALLERY_IMAGE_FILTER)
|
||||
if (stateHolder.value.bottomSheetConfig != null) {
|
||||
stateHolder.update(DismissBottomSheetTransformer())
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val GALLERY_IMAGE_FILTER = "image/*"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.feature.qrscanning.viewmodel
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
|
@ -11,50 +9,38 @@ import com.tangem.feature.qrscanning.QrScanningRouter.Companion.SOURCE_KEY
|
|||
import com.tangem.feature.qrscanning.SourceType
|
||||
import com.tangem.feature.qrscanning.navigation.QrScanningInnerRouter
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningState
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningStateFactory
|
||||
import com.tangem.feature.qrscanning.usecase.EmitQrScannedEventUseCase
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.feature.qrscanning.presentation.QrScanningStateController
|
||||
import com.tangem.feature.qrscanning.presentation.transformers.ShowCameraDeniedBottomSheetTransformer
|
||||
import com.tangem.feature.qrscanning.presentation.transformers.InitializeQrScanningStateTransformer
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@HiltViewModel
|
||||
internal class QrScanningViewModel @Inject constructor(
|
||||
private val emitQrScannedEventUseCase: EmitQrScannedEventUseCase,
|
||||
private val dispatcher: CoroutineDispatcherProvider,
|
||||
private val stateHolder: QrScanningStateController,
|
||||
private val clickIntents: QrScanningClickIntentsImplementor,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), QrScanningClickIntents {
|
||||
) : ViewModel() {
|
||||
|
||||
private val source: SourceType = savedStateHandle[SOURCE_KEY] ?: error("Source is mandatory")
|
||||
private val network: String? = savedStateHandle[NETWORK_KEY]
|
||||
|
||||
private val factory = QrScanningStateFactory(
|
||||
clickIntents = this,
|
||||
)
|
||||
val uiState: StateFlow<QrScanningState> = stateHolder.uiState
|
||||
|
||||
var router: QrScanningInnerRouter by Delegates.notNull()
|
||||
|
||||
var uiState: QrScanningState by mutableStateOf(factory.getInitialState(source, network))
|
||||
private set
|
||||
|
||||
private var isScanned = false
|
||||
|
||||
override fun onBackClick() = router.popBackStack()
|
||||
|
||||
override fun onQrScanned(qrCode: String) {
|
||||
if (qrCode.isNotBlank()) {
|
||||
if (!isScanned) {
|
||||
router.popBackStack()
|
||||
isScanned = true
|
||||
}
|
||||
viewModelScope.launch(dispatcher.main) {
|
||||
emitQrScannedEventUseCase.invoke(source, qrCode)
|
||||
}
|
||||
}
|
||||
fun setRouter(router: QrScanningInnerRouter, galleryLauncher: ActivityResultLauncher<String>) {
|
||||
clickIntents.initialize(
|
||||
router = router,
|
||||
source = source,
|
||||
galleryLauncher = galleryLauncher,
|
||||
coroutineScope = viewModelScope,
|
||||
)
|
||||
stateHolder.update(InitializeQrScanningStateTransformer(clickIntents, source, network))
|
||||
}
|
||||
|
||||
override fun onGalleryClicked() {
|
||||
// [REDACTED_JIRA]
|
||||
fun onQrScanned(qrCode: String) = clickIntents.onQrScanned(qrCode)
|
||||
|
||||
fun onCameraDeniedState() {
|
||||
stateHolder.update(ShowCameraDeniedBottomSheetTransformer(clickIntents))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue