Updated on 2026-08-14
This commit is contained in:
parent
db178b206b
commit
b8c6c0471a
22 changed files with 191 additions and 165 deletions
|
|
@ -30,7 +30,6 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
|
|||
analyticsEvent: AnalyticsEvent?,
|
||||
cardId: String?,
|
||||
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
|
||||
onWalletNotCreated: suspend () -> Unit,
|
||||
disclaimerWillShow: () -> Unit,
|
||||
onFailure: suspend (error: TangemError) -> Unit,
|
||||
|
|
@ -41,7 +40,6 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
|
|||
analyticsEvent,
|
||||
cardId,
|
||||
onProgressStateChange,
|
||||
onScanStateChange,
|
||||
onWalletNotCreated,
|
||||
disclaimerWillShow,
|
||||
onFailure,
|
||||
|
|
@ -52,7 +50,6 @@ internal class DefaultScanCardProcessor : ScanCardProcessor {
|
|||
analyticsEvent,
|
||||
cardId,
|
||||
onProgressStateChange,
|
||||
onScanStateChange,
|
||||
onWalletNotCreated,
|
||||
disclaimerWillShow,
|
||||
onFailure,
|
||||
|
|
|
|||
|
|
@ -48,14 +48,12 @@ internal object LegacyScanProcessor {
|
|||
analyticsEvent: AnalyticsEvent?,
|
||||
cardId: String?,
|
||||
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
|
||||
onWalletNotCreated: suspend () -> Unit,
|
||||
disclaimerWillShow: () -> Unit,
|
||||
onFailure: suspend (error: TangemError) -> Unit,
|
||||
onSuccess: suspend (scanResponse: ScanResponse) -> Unit,
|
||||
) = withMainContext {
|
||||
onProgressStateChange(true)
|
||||
onScanStateChange(true)
|
||||
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(null)
|
||||
|
||||
|
|
@ -65,13 +63,11 @@ internal object LegacyScanProcessor {
|
|||
|
||||
result
|
||||
.doOnFailure { error ->
|
||||
onScanStateChange(false)
|
||||
onFailure(error)
|
||||
}
|
||||
.doOnSuccess { scanResponse ->
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
|
||||
|
||||
onScanStateChange(false)
|
||||
sendAnalytics(analyticsEvent, scanResponse)
|
||||
|
||||
showDisclaimerIfNeed(
|
||||
|
|
|
|||
|
|
@ -3,11 +3,15 @@ package com.tangem.tap.domain.scanCard
|
|||
import arrow.fx.coroutines.resourceScope
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.navigation.StateDialog
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.scanCard.chains.*
|
||||
|
|
@ -25,9 +29,15 @@ internal object UseCaseScanProcessor {
|
|||
allowsRequestAccessCodeFromRepository: Boolean = false,
|
||||
): CompletionResult<ScanResponse> {
|
||||
val scanCardUseCase = store.inject(DaggerGraphState::scanCardUseCase)
|
||||
|
||||
return scanCardUseCase(cardId, allowsRequestAccessCodeFromRepository)
|
||||
.fold(
|
||||
ifLeft = { CompletionResult.Failure(scanCardExceptionConverter.convertBack(it)) },
|
||||
ifLeft = {
|
||||
val error = scanCardExceptionConverter.convertBack(it)
|
||||
|
||||
Analytics.send(Basic.ScanError(error))
|
||||
CompletionResult.Failure(error)
|
||||
},
|
||||
ifRight = { CompletionResult.Success(it) },
|
||||
)
|
||||
}
|
||||
|
|
@ -37,17 +47,14 @@ internal object UseCaseScanProcessor {
|
|||
analyticsEvent: AnalyticsEvent?,
|
||||
cardId: String?,
|
||||
onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit,
|
||||
onWalletNotCreated: suspend () -> Unit,
|
||||
disclaimerWillShow: () -> Unit,
|
||||
onFailure: suspend (error: TangemError) -> Unit,
|
||||
onSuccess: suspend (scanResponse: ScanResponse) -> Unit,
|
||||
) = progressScope(onProgressStateChange) {
|
||||
onScanStateChange(true)
|
||||
|
||||
val scanCardUseCase = store.inject(DaggerGraphState::scanCardUseCase)
|
||||
val chains = buildList {
|
||||
add(ScanningFinishedChain { onScanStateChange(false) })
|
||||
add(FailedScansCounterChain(UseCaseScanProcessor::showMaxUnsuccessfulScansReachedDialog))
|
||||
if (analyticsEvent != null) {
|
||||
add(AnalyticsChain(analyticsEvent))
|
||||
}
|
||||
|
|
@ -55,9 +62,14 @@ internal object UseCaseScanProcessor {
|
|||
add(CheckForOnboardingChain(store, store.state.globalState.tapWalletManager))
|
||||
}
|
||||
|
||||
scanCardUseCase(cardId, afterScanChains = chains)
|
||||
.map { onSuccess(it) }
|
||||
.mapLeft { proceedWithException(it, onWalletNotCreated, onFailure) }
|
||||
scanCardUseCase(cardId, afterScanChains = chains).fold(
|
||||
ifLeft = { proceedWithException(it, onWalletNotCreated, onFailure) },
|
||||
ifRight = { onSuccess(it) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun showMaxUnsuccessfulScansReachedDialog() {
|
||||
store.dispatchDialogShow(StateDialog.ScanFailsDialog)
|
||||
}
|
||||
|
||||
private suspend fun proceedWithException(
|
||||
|
|
@ -75,7 +87,12 @@ internal object UseCaseScanProcessor {
|
|||
is ScanCardException.UserCancelled,
|
||||
is ScanCardException.WrongAccessCode,
|
||||
is ScanCardException.WrongCardId,
|
||||
-> onFailure(scanCardExceptionConverter.convertBack(exception))
|
||||
-> {
|
||||
val error = scanCardExceptionConverter.convertBack(exception)
|
||||
|
||||
Analytics.send(Basic.ScanError(error))
|
||||
onFailure(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,8 +106,9 @@ internal object UseCaseScanProcessor {
|
|||
navigateTo(exception.onboardingRoute)
|
||||
onWalletNotCreated()
|
||||
}
|
||||
is ScanChainException.DisclaimerWasCanceled,
|
||||
-> onFailure(scanCardExceptionConverter.convertBack(exception))
|
||||
is ScanChainException.DisclaimerWasCanceled -> {
|
||||
onFailure(scanCardExceptionConverter.convertBack(exception))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.core.chain.ResultChain
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor
|
||||
|
||||
|
|
@ -19,11 +19,9 @@ import com.tangem.tap.common.analytics.paramsInterceptor.CardContextInterceptor
|
|||
*/
|
||||
class AnalyticsChain(
|
||||
private val event: AnalyticsEvent,
|
||||
) : Chain<ScanCardException.ChainException, ScanResponse> {
|
||||
) : ResultChain<ScanCardException, ScanResponse>() {
|
||||
|
||||
override suspend fun invoke(
|
||||
previousChainResult: ScanResponse,
|
||||
): Either<ScanCardException.ChainException, ScanResponse> {
|
||||
override suspend fun launch(previousChainResult: ScanResponse): ScanChainResult {
|
||||
val interceptor = CardContextInterceptor(previousChainResult)
|
||||
val params = event.params.toMutableMap()
|
||||
interceptor.intercept(params)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.core.analytics.Analytics
|
||||
|
|
@ -9,6 +8,7 @@ import com.tangem.domain.card.ScanCardException
|
|||
import com.tangem.domain.common.TapWorkarounds.canSkipBackup
|
||||
import com.tangem.domain.common.util.twinsIsTwinned
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.core.chain.ResultChain
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.addContext
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -39,11 +39,9 @@ import org.rekotlin.Store
|
|||
class CheckForOnboardingChain(
|
||||
private val store: Store<AppState>,
|
||||
private val tapWalletManager: TapWalletManager,
|
||||
) : Chain<ScanCardException.ChainException, ScanResponse> {
|
||||
) : ResultChain<ScanCardException, ScanResponse>() {
|
||||
|
||||
override suspend fun invoke(
|
||||
previousChainResult: ScanResponse,
|
||||
): Either<ScanCardException.ChainException, ScanResponse> {
|
||||
override suspend fun launch(previousChainResult: ScanResponse): ScanChainResult {
|
||||
tapWalletManager.updateConfigManager(previousChainResult)
|
||||
store.dispatchOnMain(TwinCardsAction.IfTwinsPrepareState(previousChainResult))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.core.chain.ResultChain
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
@ -31,11 +31,9 @@ import kotlin.coroutines.resume
|
|||
internal class DisclaimerChain(
|
||||
private val store: Store<AppState>,
|
||||
private val disclaimerWillShow: () -> Unit = {},
|
||||
) : Chain<ScanCardException.ChainException, ScanResponse> {
|
||||
) : ResultChain<ScanCardException, ScanResponse>() {
|
||||
|
||||
override suspend fun invoke(
|
||||
previousChainResult: ScanResponse,
|
||||
): Either<ScanCardException.ChainException, ScanResponse> {
|
||||
override suspend fun launch(previousChainResult: ScanResponse): ScanChainResult {
|
||||
val disclaimer = previousChainResult.card.createDisclaimer()
|
||||
|
||||
return if (disclaimer.isAccepted()) {
|
||||
|
|
@ -46,10 +44,7 @@ internal class DisclaimerChain(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun showDisclaimer(
|
||||
disclaimer: Disclaimer,
|
||||
response: ScanResponse,
|
||||
): Either<ScanCardException.ChainException, ScanResponse> {
|
||||
private suspend fun showDisclaimer(disclaimer: Disclaimer, response: ScanResponse): ScanChainResult {
|
||||
store.dispatchOnMain(DisclaimerAction.SetDisclaimer(disclaimer))
|
||||
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
internal class FailedScansCounterChain(
|
||||
private val onMaxUnsuccessfulScansReached: () -> Unit,
|
||||
private val maxUnsuccessfulScans: Int = 3,
|
||||
) : Chain<ScanCardException, ScanResponse> {
|
||||
|
||||
override suspend fun launch(previousChainResult: ScanChainResult): ScanChainResult {
|
||||
if (previousChainResult.isLeft()) {
|
||||
unsuccessfulScansCounter = unsuccessfulScansCounter.inc().coerceAtMost(maxUnsuccessfulScans)
|
||||
if (unsuccessfulScansCounter == maxUnsuccessfulScans) {
|
||||
onMaxUnsuccessfulScansReached()
|
||||
}
|
||||
} else {
|
||||
unsuccessfulScansCounter = 0
|
||||
}
|
||||
|
||||
return previousChainResult
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
var unsuccessfulScansCounter = 0
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,11 @@ sealed class ScanChainException : ScanCardException.ChainException() {
|
|||
/**
|
||||
* May be returned from [DisclaimerChain]
|
||||
* */
|
||||
object DisclaimerWasCanceled : ScanChainException()
|
||||
data object DisclaimerWasCanceled : ScanChainException() {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun readResolve(): Any = DisclaimerWasCanceled
|
||||
}
|
||||
|
||||
/**
|
||||
* May be returned from [CheckForOnboardingChain]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
internal typealias ScanChainResult = Either<ScanCardException, ScanResponse>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.tap.domain.scanCard.chains
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.core.chain.Chain
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
/**
|
||||
* Responsible for invoking the callback at the end of the card scanning operation. Should be passed as last chain in
|
||||
* after card scanning chains. Always returns result of previous chain.
|
||||
*
|
||||
* @param onScanningFinished a suspending function to be called when the scanning process has finished.
|
||||
*
|
||||
* @see Chain for more information about the Chain interface.
|
||||
*/
|
||||
internal class ScanningFinishedChain(
|
||||
private val onScanningFinished: suspend () -> Unit,
|
||||
) : Chain<ScanCardException.ChainException, ScanResponse> {
|
||||
|
||||
override suspend fun invoke(previousChainResult: ScanResponse): Either<ScanChainException, ScanResponse> {
|
||||
onScanningFinished()
|
||||
return previousChainResult.right()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +1,27 @@
|
|||
package com.tangem.tap.domain.scanCard.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.card.ScanCardException
|
||||
import com.tangem.domain.card.repository.ScanCardRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.domain.TangemSdkManager
|
||||
import com.tangem.tap.domain.scanCard.utils.ScanCardExceptionConverter
|
||||
|
||||
// TODO: Move to the :data:card module
|
||||
internal class DefaultScanCardRepository(
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
) : ScanCardRepository {
|
||||
|
||||
private val exceptionConverter = ScanCardExceptionConverter()
|
||||
|
||||
override suspend fun scanCard(
|
||||
cardId: String?,
|
||||
allowRequestAccessCodeFromStorage: Boolean,
|
||||
): Either<ScanCardException, ScanResponse> = either {
|
||||
when (
|
||||
override suspend fun scanCard(cardId: String?, allowRequestAccessCodeFromStorage: Boolean): ScanResponse {
|
||||
return when (
|
||||
val result = tangemSdkManager.scanProduct(
|
||||
cardId = cardId,
|
||||
allowsRequestAccessCodeFromRepository = allowRequestAccessCodeFromStorage,
|
||||
)
|
||||
) {
|
||||
is CompletionResult.Success -> result.data
|
||||
is CompletionResult.Failure -> raise(exceptionConverter.convert(result.error))
|
||||
is CompletionResult.Failure -> throw exceptionConverter.convert(result.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.features.home.redux
|
|||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.Basic
|
||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.rekotlin.Action
|
||||
|
||||
|
|
@ -29,6 +28,4 @@ sealed class HomeAction : Action {
|
|||
data class GoToShop(val userCountryCode: String?) : HomeAction()
|
||||
|
||||
data class UpdateCountryCode(val userCountryCode: String) : HomeAction()
|
||||
|
||||
data class ChangeScanCardButtonState(val state: IndeterminateProgressButton) : HomeAction()
|
||||
}
|
||||
|
|
@ -13,12 +13,10 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL
|
||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||
import com.tangem.tap.features.signin.redux.SignInAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -31,6 +29,8 @@ import org.rekotlin.Action
|
|||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
|
||||
private const val HIDE_PROGRESS_DELAY = 400L
|
||||
|
||||
object HomeMiddleware {
|
||||
val handler = homeMiddleware
|
||||
|
||||
|
|
@ -84,17 +84,16 @@ private suspend fun readCard(analyticsEvent: AnalyticsEvent?) {
|
|||
analyticsEvent = analyticsEvent,
|
||||
onProgressStateChange = { showProgress ->
|
||||
if (showProgress) {
|
||||
changeButtonState(ButtonState.PROGRESS)
|
||||
store.dispatch(HomeAction.ScanInProgress(scanInProgress = true))
|
||||
} else {
|
||||
changeButtonState(ButtonState.ENABLED)
|
||||
delay(HIDE_PROGRESS_DELAY)
|
||||
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
|
||||
}
|
||||
},
|
||||
onScanStateChange = { scanInProgress ->
|
||||
store.dispatch(HomeAction.ScanInProgress(scanInProgress))
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Unable to scan card")
|
||||
changeButtonState(ButtonState.ENABLED)
|
||||
delay(HIDE_PROGRESS_DELAY)
|
||||
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
|
||||
},
|
||||
onSuccess = { scanResponse ->
|
||||
proceedWithScanResponse(scanResponse)
|
||||
|
|
@ -113,7 +112,7 @@ private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch {
|
|||
Timber.e(error, "Unable to save user wallet")
|
||||
}
|
||||
.doOnSuccess {
|
||||
scope.launch { store.onUserWalletSelected(userWallet = userWallet) }
|
||||
scope.launch { store.onUserWalletSelected(userWallet) }
|
||||
}
|
||||
.doOnResult {
|
||||
store.dispatchOnMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card))
|
||||
|
|
@ -123,10 +122,6 @@ private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch {
|
|||
|
||||
private suspend fun navigateTo(appScreen: AppScreen) {
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(appScreen))
|
||||
delay(timeMillis = 200)
|
||||
changeButtonState(ButtonState.ENABLED)
|
||||
}
|
||||
|
||||
private fun changeButtonState(state: ButtonState) {
|
||||
store.dispatchOnMain(HomeAction.ChangeScanCardButtonState(IndeterminateProgressButton(state)))
|
||||
delay(HIDE_PROGRESS_DELAY)
|
||||
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
|
||||
}
|
||||
|
|
@ -22,9 +22,6 @@ private fun internalReduce(action: Action, appState: AppState): HomeState {
|
|||
is HomeAction.ScanInProgress -> {
|
||||
state = state.copy(scanInProgress = action.scanInProgress)
|
||||
}
|
||||
is HomeAction.ChangeScanCardButtonState -> {
|
||||
state = state.copy(btnScanState = action.state)
|
||||
}
|
||||
is HomeAction.UpdateCountryCode -> {
|
||||
state.onCountryCodeUpdate(state, action.userCountryCode)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
package com.tangem.tap.features.home.redux
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.tangem.tap.common.entities.IndeterminateProgressButton
|
||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||
import org.rekotlin.StateType
|
||||
import java.util.Locale
|
||||
|
||||
@Immutable
|
||||
data class HomeState(
|
||||
val scanInProgress: Boolean = false,
|
||||
val btnScanState: IndeterminateProgressButton = IndeterminateProgressButton(ButtonState.ENABLED),
|
||||
val stories: List<Stories> = initDefaultStories(),
|
||||
) : StateType {
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue