diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemViewModel.kt index 8c548ee17c..a542a3be4d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemViewModel.kt @@ -8,30 +8,46 @@ import com.tangem.tangemtest._arch.structure.PayloadHolder /** [REDACTED_AUTHOR] */ -typealias ValueChange = (V?) -> Unit -typealias SafeValueChange = (V) -> Unit +typealias ValueChanged = (V?) -> Unit +typealias SafeValueChanged = (V) -> Unit class KeyValue(val key: String, val value: Any) class ViewState( - var isHidden: Boolean = false, - var backgroundColor: Int? = -1 + isVisible: Boolean? = null, + bgColor: Int? = -1 ) { - var descriptionVisibility: Int = 0x00000008 - set(value) { - field = value - onDescriptionVisibilityChanged?.invoke(value) - } + class State( + stateValue: T, + var onValueChanged: SafeValueChanged? = null + ) { + var value = stateValue + set(value) { + if (preventSameChanges && field == value) return - var onDescriptionVisibilityChanged: SafeValueChange? = null + field = value + onValueChanged?.invoke(value) + } + + internal var preventSameChanges = true + } + + var isVisibleState = State(isVisible) + var backgroundColor = State(bgColor) + var descriptionVisibility = State(0x00000008) + + internal fun preventSameChanges(isPrevented: Boolean) { + val states = listOf(isVisibleState, backgroundColor, descriptionVisibility) + states.forEach { it.preventSameChanges = isPrevented } + } } interface ItemViewModel : PayloadHolder { val viewState: ViewState var data: Any? var defaultData: Any? - var onDataUpdated: ValueChange? + var onDataUpdated: ValueChanged? fun updateDataByView(data: Any?) } @@ -57,7 +73,7 @@ open class BaseItemViewModel( } // Use it for handling data updates in View - override var onDataUpdated: ValueChange? = null + override var onDataUpdated: ValueChanged? = null // When data updates directly it invokes onDataUpdated // return true = data will update diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/widget/abstraction/ViewWidget.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/widget/abstraction/ViewWidget.kt index 20fcb7f37f..9b6c5f9d2c 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/widget/abstraction/ViewWidget.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/widget/abstraction/ViewWidget.kt @@ -10,6 +10,7 @@ import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.StringId import com.tangem.tangemtest._arch.structure.StringResId import com.tangem.tangemtest._arch.structure.abstraction.Item +import com.tangem.tangemtest._arch.structure.abstraction.ViewState import ru.dev.gbixahue.eu4d.lib.android._android.views.colorFrom import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder @@ -34,11 +35,22 @@ abstract class BaseViewWidget( private var defaultBackground: Drawable? = view.background init { - if (item.viewModel.viewState.isHidden) { - view.visibility = View.GONE - } else { - setBackgroundColor(item.viewModel.viewState.backgroundColor) + subscribeToViewStateChanges(item.viewModel.viewState) + initViewState(item.viewModel.viewState) + } + + protected open fun subscribeToViewStateChanges(viewState: ViewState) { + viewState.isVisibleState.onValueChanged = { state -> + state?.let { view.visibility = if (it) View.VISIBLE else View.GONE } } + viewState.backgroundColor.onValueChanged = { setBackgroundColor(it) } + } + + protected open fun initViewState(viewState: ViewState) { + viewState.preventSameChanges(false) + viewState.isVisibleState.value = viewState.isVisibleState.value + if (viewState.backgroundColor.value != -1) setBackgroundColor(viewState.backgroundColor.value) + viewState.preventSameChanges(true) } override fun getName(): String { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/commons/view/MultiActionView.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/view/MultiActionView.kt new file mode 100644 index 0000000000..1586f00232 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/view/MultiActionView.kt @@ -0,0 +1,85 @@ +package com.tangem.tangemtest.commons.view + +import android.widget.TextView +import androidx.annotation.StringRes +import com.tangem.tangemtest._arch.structure.Id +import com.tangem.tangemtest._arch.structure.StringId +import com.tangem.tangemtest._arch.structure.abstraction.SafeValueChanged +import ru.dev.gbixahue.eu4d.lib.android.global.log.Log +import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf + +/** +[REDACTED_AUTHOR] + */ +open class MultiActionView( + stateList: MutableList, + val child: V +) { + + interface State { + val id: Id + + fun getAction(): StateButtonAction + fun getResNameId(): Int + } + + var afterAction: SafeValueChanged? = null + + var state: Id = DefaultId.default + set(value) { + if (field == value) return + + field = value + Log.d(this, "state changed to: ${getKey(value)}") + btnState = stateHolder[getKey(value)] + } + + init { + child.setOnClickListener { + val state = btnState ?: return@setOnClickListener + + Log.d(this, "child handled OnClick for: ${getKey(state.id)}") + state.getAction().invoke() + afterAction?.invoke(state.id) + } + } + + protected var btnState: State? = null + set(value) { + if (value == null) return + + field = value + Log.d(this, "btnState changed to: ${getKey(value.id)}") + child.setText(value.getResNameId()) + } + + protected val stateHolder: MutableMap = stateList.associateBy { getKey(it.id) }.toMutableMap() + + fun performAction(id: Id) { + Log.d(this, "performAction ${getKey(id)}") + state = id + child.performClick() + } + + protected open fun getKey(id: Id): String { + return when (id) { + is StringId -> id.value + else -> stringOf(id) + } + } +} + +enum class DefaultId : Id { default } + +typealias StateButtonAction = () -> Unit + +class ButtonState( + override val id: Id, + @StringRes val name: Int, + private val action: StateButtonAction +) : MultiActionView.State { + + override fun getAction(): StateButtonAction = action + + override fun getResNameId(): Int = name +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/ActionViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/ActionViewModel.kt index a44367f98c..fc4956bb70 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/ActionViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/ActionViewModel.kt @@ -13,7 +13,9 @@ import com.tangem.tangemtest._arch.structure.abstraction.iterate import com.tangem.tangemtest.commons.performAction import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager import com.tangem.tangemtest.ucase.domain.responses.ResponseJsonConverter +import com.tangem.tangemtest.ucase.resources.ActionType import com.tangem.tangemtest.ucase.tunnel.ViewScreen +import com.tangem.tangemtest.ucase.variants.personalize.converter.ItemTypes import com.tangem.tasks.ScanEvent import com.tangem.tasks.TaskError import com.tangem.tasks.TaskEvent @@ -73,7 +75,7 @@ class ActionViewModel(private val itemsManager: ItemsManager) : ViewModel(), Lif fun toggleDescriptionVisibility(state: Boolean) { ldItemList.value?.iterate { - it.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE + it.viewModel.viewState.descriptionVisibility.value = if (state) View.VISIBLE else View.GONE } } @@ -87,6 +89,41 @@ class ActionViewModel(private val itemsManager: ItemsManager) : ViewModel(), Lif itemsManager.payload.filterValues { it is ViewScreen }.forEach { keyList.add(it.key) } keyList.forEach { itemsManager.payload.remove(it) } } + + fun showFields(type: ActionType) { + toggleFieldsVisibility(type, true) + } + + fun hideFields(type: ActionType) { + toggleFieldsVisibility(type, false) + } + + private fun toggleFieldsVisibility(type: ActionType, show: Boolean) { + val oftenUsed = getItemsForTogglingVisibilityState(type) + val hidden = getItemIdsWhichWontShows(type) + itemsManager.getItems().iterate { + if (!hidden.contains(it.id)) { + if (!oftenUsed.contains(it.id)) { + it.viewModel.viewState.isVisibleState.value = show + } + } + + } + } + + private fun getItemsForTogglingVisibilityState(type: ActionType): List { + return when (type) { + ActionType.Personalize -> ItemTypes().oftenUsedList + else -> emptyList() + } + } + + private fun getItemIdsWhichWontShows(type: ActionType): List { + return when (type) { + ActionType.Personalize -> ItemTypes().hiddenList + else -> emptyList() + } + } } internal class Notifier(private val vm: ActionViewModel) { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt index b9186f495a..7148be7ee5 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/BaseCardActionFragment.kt @@ -47,9 +47,14 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { actionVM.attachToPayload(mutableMapOf(PayloadKey.actionView to this as ActionView)) initFab() - createWidgets { subscribeToViewModelChanges() } + createWidgets { + widgetsWasCreated() + subscribeToViewModelChanges() + } } + protected open fun widgetsWasCreated() {} + protected open fun bindViews() { itemContainer = mainView.findViewById(R.id.ll_container) actionFab = mainView.findViewById(R.id.fab_action) diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ItemTypes.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ItemTypes.kt index 238a0aeaa0..b1013de610 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ItemTypes.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/ItemTypes.kt @@ -1,5 +1,6 @@ package com.tangem.tangemtest.ucase.variants.personalize.converter +import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest.ucase.variants.personalize.* class ItemTypes { @@ -36,11 +37,81 @@ class ItemTypes { CardNumber.Number, Common.MaxSignatures, SignHashExProp.PinLessFloorLimit, Denomination.Denomination, Token.Decimal ) - val hiddenList = mutableListOf( + val hiddenList = mutableListOf( CardNumber.Series, CardNumber.BatchId, Pins.Pin3, SigningMethod.SignExternal, SignHashExProp.CryptoExKey, SignHashExProp.CheckPin3, SettingsMask.OneApdu, SettingsMask.UseBlock, SettingsMask.ProtectIssuerDataAgainstReplay, SignHashExProp.RequireTerminalCertSig, SignHashExProp.RequireTerminalTxSig ) -} \ No newline at end of file + val oftenUsedList = listOf( +// BlockId.CardNumber, + BlockId.Common, +// BlockId.SigningMethod, +// BlockId.SignHashExProp, +// BlockId.Denomination, +// BlockId.Token, + BlockId.ProdMask, +// BlockId.SettingsMask, +// BlockId.SettingsMaskProtocolEnc, + BlockId.SettingsMaskNdef, +// BlockId.Pins, + Common.Curve, + Common.Blockchain, + Common.BlockchainCustom, +// Common.MaxSignatures, + Common.CreateWallet, +// SigningMethod.SignTx, +// SigningMethod.SignTxRaw, +// SigningMethod.SignValidatedTx, +// SigningMethod.SignValidatedTxRaw, +// SigningMethod.SignValidatedTxIssuer, +// SigningMethod.SignValidatedTxRawIssuer, +// SigningMethod.SignExternal, +// SignHashExProp.PinLessFloorLimit, +// SignHashExProp.CryptoExKey, +// SignHashExProp.RequireTerminalCertSig, +// SignHashExProp.RequireTerminalTxSig, +// SignHashExProp.CheckPin3, +// Denomination.WriteOnPersonalize, +// Denomination.Denomination, +// Token.ItsToken, +// Token.Symbol, +// Token.ContractAddress, +// Token.Decimal, + ProductMask.Note, + ProductMask.Tag, + ProductMask.IdCard, + ProductMask.IdIssuerCard, +// SettingsMask.IsReusable, +// SettingsMask.NeedActivation, +// SettingsMask.ForbidPurge, +// SettingsMask.AllowSelectBlockchain, +// SettingsMask.UseBlock, +// SettingsMask.OneApdu, +// SettingsMask.UseCvc, +// SettingsMask.AllowSwapPin, +// SettingsMask.AllowSwapPin2, +// SettingsMask.ForbidDefaultPin, +// SettingsMask.SmartSecurityDelay, +// SettingsMask.ProtectIssuerDataAgainstReplay, +// SettingsMask.SkipSecurityDelayIfValidated, +// SettingsMask.SkipPin2CvcIfValidated, +// SettingsMask.SkipSecurityDelayOnLinkedTerminal, +// SettingsMask.RestrictOverwriteExtraIssuerData, +// SettingsMaskProtocolEnc.AllowUnencrypted, +// SettingsMaskProtocolEnc.AllowStaticEncryption, +// SettingsMaskNdef.UseNdef, +// SettingsMaskNdef.DynamicNdef, +// SettingsMaskNdef.DisablePrecomputedNdef, + SettingsMaskNdef.Aar, + SettingsMaskNdef.AarCustom, + SettingsMaskNdef.Uri, +// Pins.Pin, +// Pins.Pin2, +// Pins.Pin3, +// Pins.Cvc, + Pins.PauseBeforePin2 + ) + +} diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizationConfigConverter.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizationConfigConverter.kt index b5c7250462..d450ab54d9 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizationConfigConverter.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/PersonalizationConfigConverter.kt @@ -147,7 +147,7 @@ class PersonalizationConfigToItems : ModelToItems { blocList.add(pins()) blocList.iterate { if (itemTypes.hiddenList.contains(it.id)) { - it.viewModel.viewState.isHidden = true + it.viewModel.viewState.isVisibleState.value = false } } return blocList diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizationFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizationFragment.kt index d0216c725b..97d152d51b 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizationFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/ui/PersonalizationFragment.kt @@ -2,19 +2,26 @@ package com.tangem.tangemtest.ucase.variants.personalize.ui import android.os.Bundle import android.view.View +import android.view.ViewGroup +import android.widget.Button import androidx.lifecycle.Observer import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.Id +import com.tangem.tangemtest._arch.structure.StringId import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest._arch.widget.WidgetBuilder +import com.tangem.tangemtest.commons.view.ButtonState +import com.tangem.tangemtest.commons.view.MultiActionView import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey import com.tangem.tangemtest.ucase.domain.paramsManager.managers.PersonalizationItemsManager +import com.tangem.tangemtest.ucase.resources.ActionType import com.tangem.tangemtest.ucase.tunnel.ActionView import com.tangem.tangemtest.ucase.tunnel.ItemError import com.tangem.tangemtest.ucase.ui.BaseCardActionFragment import com.tangem.tangemtest.ucase.variants.personalize.PersonalizationConfigStore import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.PersonalizationItemBuilder +import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate import ru.dev.gbixahue.eu4d.lib.android.global.log.Log /** @@ -31,6 +38,25 @@ class PersonalizationFragment : BaseCardActionFragment() { lifecycle.addObserver(itemsManager as PersonalizationItemsManager) } + override fun widgetsWasCreated() { + super.widgetsWasCreated() + + val btnContainer = itemContainer.inflate(R.layout.view_simple_button) + val btn = btnContainer.findViewById