diff --git a/tangem-demo/build.gradle b/tangem-demo/build.gradle index fa9e64d58f..fd56546bed 100644 --- a/tangem-demo/build.gradle +++ b/tangem-demo/build.gradle @@ -46,10 +46,11 @@ dependencies { implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4" implementation "androidx.navigation:navigation-fragment-ktx:2.2.1" implementation "androidx.navigation:navigation-ui-ktx:2.2.1" - implementation "androidx.recyclerview:recyclerview:1.2.0-alpha01" + implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02" + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" implementation "com.google.android.material:material:1.2.0-alpha05" implementation "androidx.viewpager2:viewpager2:1.0.0" implementation 'com.google.code.gson:gson:2.8.6' - implementation 'com.github.gbIxaHue:eu4d:0.3.7' + implementation 'com.github.gbIxaHue:eu4d:0.3.8' } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt index 76b43ce50a..2aa3fb6af5 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Extension.kt @@ -20,7 +20,10 @@ fun List.iterate(func: (Item) -> Unit) { forEach { when (it) { is BaseItem -> func(it) - is ItemGroup -> it.itemList.iterate(func) + is ItemGroup -> { + func(it) + it.itemList.iterate(func) + } } } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Item.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Item.kt index eaf3d7afa4..7800192199 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Item.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/Item.kt @@ -5,7 +5,12 @@ import com.tangem.tangemtest._arch.structure.Id /** [REDACTED_AUTHOR] */ -interface Item { + +interface UpdateBy{ + fun update(value: B) +} + +interface Item: UpdateBy { val id: Id var parent: Item? var viewModel: ItemViewModel @@ -36,4 +41,7 @@ open class BaseItem( override var parent: Item? = null + override fun update(value: Item) { + viewModel.update(value.viewModel) + } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemGroup.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemGroup.kt index 61a43a0d1c..20a8def0e6 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemGroup.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/abstraction/ItemGroup.kt @@ -49,4 +49,8 @@ open class SimpleItemGroup( ILog.d(this, "clear $id") itemList.clear() } + + override fun update(value: Item) { + // nothing to do + } } \ No newline at end of file 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 a542a3be4d..fc106588e6 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 @@ -16,7 +16,7 @@ class KeyValue(val key: String, val value: Any) class ViewState( isVisible: Boolean? = null, bgColor: Int? = -1 -) { +) : UpdateBy { class State( stateValue: T, @@ -41,9 +41,15 @@ class ViewState( val states = listOf(isVisibleState, backgroundColor, descriptionVisibility) states.forEach { it.preventSameChanges = isPrevented } } + + override fun update(value: ViewState) { +// isVisibleState.update(value.isVisibleState) +// backgroundColor.update(value.backgroundColor) +// descriptionVisibility.update(value.descriptionVisibility) + } } -interface ItemViewModel : PayloadHolder { +interface ItemViewModel : PayloadHolder, UpdateBy { val viewState: ViewState var data: Any? var defaultData: Any? @@ -92,6 +98,14 @@ open class BaseItemViewModel( this.data = data onDataUpdated = callback } + + override fun update(value: ItemViewModel) { + viewState.update(value.viewState) + defaultData = value.defaultData + data = value.data + payload.clear() + payload.putAll(value.payload) + } } class ListViewModel( diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/impl/Items.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/impl/Items.kt index e402650802..d4e4dde775 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/impl/Items.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_arch/structure/impl/Items.kt @@ -11,29 +11,29 @@ open class TypedItem(id: Id, viewModel: ItemViewModel) : BaseItem(id, viewMod open fun getTypedData(): D? = viewModel.data as? D } -class TextItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { +open class TextItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { constructor(id: Id, value: String? = null, viewState: ViewState = ViewState()) : this(id, BaseItemViewModel(value, viewState)) } -class NumberItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { +open class NumberItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { constructor(id: Id, value: Number? = null, viewState: ViewState = ViewState()) : this(id, BaseItemViewModel(value, viewState)) } -class BoolItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { +open class BoolItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { constructor(id: Id, value: Boolean? = null, viewState: ViewState = ViewState()) : this(id, BaseItemViewModel(value, viewState)) } -class EditTextItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { +open class EditTextItem(id: Id, viewModel: ItemViewModel) : TypedItem(id, viewModel) { constructor(id: Id, value: String? = null, viewState: ViewState = ViewState()) : this(id, BaseItemViewModel(value, viewState)) } -class SpinnerItem(id: Id, viewModel: ListViewModel) : TypedItem(id, viewModel) { +open class SpinnerItem(id: Id, viewModel: ListViewModel) : TypedItem(id, viewModel) { constructor(id: Id, list: List, selectedValue: Any?, viewState: ViewState = ViewState()) : this(id, ListViewModel(list, selectedValue, viewState)) } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainActivity.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainActivity.kt index 92e093d2c8..c47ac39601 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainActivity.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainActivity.kt @@ -3,9 +3,9 @@ package com.tangem.tangemtest._main import android.content.res.Resources import android.os.Bundle import android.view.Menu +import android.view.MenuItem import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.Toolbar import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment @@ -20,7 +20,7 @@ import ru.dev.gbixahue.eu4d.lib.android.global.log.Log */ class MainActivity : AppCompatActivity() { - private val vm: MainViewModel by viewModels() + private val mainVM: MainViewModel by viewModels() private lateinit var appBarConfiguration: AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { @@ -52,11 +52,24 @@ class MainActivity : AppCompatActivity() { } override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.main_menu, menu) - val switchMenu = menu.findItem(R.id.action_favorite) - (switchMenu.actionView as? SwitchCompat)?.let { - it.setOnCheckedChangeListener { buttonView, isChecked -> vm.switchToggled(isChecked) } + menuInflater.inflate(R.menu.menu_activity_main, menu) + return true + } + + override fun onPrepareOptionsMenu(menu: Menu): Boolean { + val switchItem = menu.findItem(R.id.action_toggle_description_visibility) + switchItem.isChecked = mainVM.descriptionSwitchState + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val result = when (item.itemId) { + R.id.action_toggle_description_visibility -> { + item.isChecked = !item.isChecked + mainVM.switchToggled(item.isChecked) + } + else -> null } - return super.onCreateOptionsMenu(menu) + return if (result == null) super.onOptionsItemSelected(item) else true } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainViewModel.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainViewModel.kt index a50da93a68..3900d86530 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainViewModel.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/MainViewModel.kt @@ -10,10 +10,12 @@ import ru.dev.gbixahue.eu4d.lib.android.global.log.Log */ class MainViewModel : ViewModel() { val ldDescriptionSwitch = MutableLiveData(false) + var descriptionSwitchState = false var commandResponse: CommandResponse? = null fun switchToggled(state: Boolean) { + descriptionSwitchState = state ldDescriptionSwitch.postValue(state) } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/ActionListFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/ActionListFragment.kt index ea17194439..4e10211223 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/ActionListFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/ActionListFragment.kt @@ -2,16 +2,14 @@ package com.tangem.tangemtest._main.entryPoint import android.os.Bundle import android.view.View -import android.view.ViewGroup import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.transition.AutoTransition -import androidx.transition.TransitionManager import com.tangem.tangemtest.R import com.tangem.tangemtest._main.MainViewModel +import com.tangem.tangemtest.extensions.view.beginDelayedTransition import com.tangem.tangemtest.ucase.getDefaultNavigationOptions import com.tangem.tangemtest.ucase.resources.ActionType import com.tangem.tangemtest.ucase.resources.MainResourceHolder @@ -47,7 +45,7 @@ class ActionListFragment : BaseFragment() { } mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer { vhDataWrapper.descriptionIsVisible = it - TransitionManager.beginDelayedTransition(rvActions as ViewGroup, AutoTransition()) + rvActions.beginDelayedTransition() rvActions.adapter?.notifyDataSetChanged() }) } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/RvActions.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/RvActions.kt index df045a572d..5433027e92 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/RvActions.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/_main/entryPoint/RvActions.kt @@ -59,8 +59,6 @@ class RvActionsVH( containerDescription.visibility = if (wrapper.descriptionIsVisible) View.VISIBLE else View.GONE } - - override fun onDataBound(data: ActionType) {} } fun RecyclerView.ViewHolder.getString(@StringRes id: Int?, ifNull: String = ""): String { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/commons/Abstractions.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/Abstractions.kt index f5f02c0ace..6c3b1abc26 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/commons/Abstractions.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/Abstractions.kt @@ -4,6 +4,13 @@ package com.tangem.tangemtest.commons [REDACTED_AUTHOR] */ interface Store { - fun save(config: M) + fun save(value: M) fun restore(): M +} + +interface KeyedStore { + fun save(key: String, value: M) + fun restore(key: String): M + fun restoreAll(): MutableMap + fun delete(key: String) } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/commons/DialogController.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/DialogController.kt new file mode 100644 index 0000000000..de7db7ae3e --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/commons/DialogController.kt @@ -0,0 +1,76 @@ +package com.tangem.tangemtest.commons + +import android.app.Activity +import android.app.Dialog +import android.view.LayoutInflater +import android.view.View +import androidx.appcompat.app.AlertDialog + +class DialogController { + var onDismissCallback: (() -> Unit)? = null + var onShowCallback: (() -> Unit)? = null + var view: View? = null + + private var rawDialog: Dialog? = null + + private var inShowingProcess = false + private var inDismissingProcess = false + private var autoReleaseOnDismiss = false + + fun createAlert(context: Activity, resLayout: Int): AlertDialog { + view = LayoutInflater.from(context).inflate(resLayout, null) + rawDialog = AlertDialog.Builder(context).setView(view).create().apply { + setOnShowListener { onShow() } + setOnDismissListener { onDismiss() } + } + return rawDialog as AlertDialog + } + + fun set(dialog: Dialog) { + rawDialog = dialog + dialog.setOnShowListener { onShow() } + dialog.setOnDismissListener { onDismiss() } + } + + private fun onShow() { + inShowingProcess = false + onShowCallback?.invoke() + } + + private fun onDismiss() { + inDismissingProcess = false + if (autoReleaseOnDismiss) release() + onDismissCallback?.invoke() + } + + fun show() { + val dialog = rawDialog ?: return + if (inShowingProcess) return + if (dialog.isShowing) return + + inShowingProcess = true + dialog.show() + } + + fun dismiss(autoRelease: Boolean = true) { + val dialog = rawDialog ?: return + if (inDismissingProcess) return + if (!dialog.isShowing) return + + autoReleaseOnDismiss = autoRelease + inDismissingProcess = true + dialog.dismiss() + } + + fun release() { + onDismissCallback = null + onShowCallback = null + + inShowingProcess = false + inDismissingProcess = false + autoReleaseOnDismiss = false + + view = null + rawDialog = null + } +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/view/Transitions.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/view/Transitions.kt new file mode 100644 index 0000000000..d58f12aa97 --- /dev/null +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/extensions/view/Transitions.kt @@ -0,0 +1,13 @@ +package com.tangem.tangemtest.extensions.view + +import android.view.ViewGroup +import androidx.transition.AutoTransition +import androidx.transition.Transition +import androidx.transition.TransitionManager + +/** +[REDACTED_AUTHOR] + */ +fun ViewGroup.beginDelayedTransition(transition: Transition = AutoTransition()) { + TransitionManager.beginDelayedTransition(this, transition) +} \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt index 612b728c24..457b4baac3 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/PersonalizeAction.kt @@ -37,7 +37,7 @@ class PersonalizeAction : BaseAction() { val acquirer = DefaultPersonalizationParams.acquirer() val manufacturer = DefaultPersonalizationParams.manufacturer() - val personalizeConfig = PersonalizationConfigConverter().convert(itemList, PersonalizationConfig()) + val personalizeConfig = PersonalizationConfigConverter().convert(itemList, PersonalizationConfig.default()) val cardConfig = PersonalizationConfigToCardConfig().convert(personalizeConfig) attrs.tangemSdk.personalize(cardConfig, issuer, manufacturer, acquirer) { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt index 375c2ce9a7..f44f36d1ee 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/actions/SignAction.kt @@ -13,10 +13,10 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf class SignAction : BaseAction() { override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) { val dataForHashing = attrs.itemList.findItem(TlvId.TransactionOutHash) ?: return - val hash = dataForHashing.getData() as? ByteArray ?: return + val hash = dataForHashing.getData() as? String ?: return val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return - attrs.tangemSdk.sign(arrayOf(hash), stringOf(cardId)) { handleResult(payload, it, null, attrs, callback) } + attrs.tangemSdk.sign(arrayOf(hash.toByteArray()), stringOf(cardId)) { handleResult(payload, it, null, attrs, callback) } } override fun getActionByTag(payload: PayloadHolder, id: Id, attrs: AttrForAction): ((ActionCallback) -> Unit)? { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt index a43809684b..20d2ed3eb8 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/ItemsManager.kt @@ -25,6 +25,7 @@ interface ItemsManager : PayloadHolder { fun invokeMainAction(tangemSdk: TangemSdk, callback: ActionCallback) fun getActionByTag(id: Id, tangemSdk: TangemSdk): ((ActionCallback) -> Unit)? fun attachPayload(payload: Payload) + fun updateByItemList(list: List) } interface PayloadKey { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt index 6ddbc6a916..a3308d623d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/BaseItemsManager.kt @@ -6,6 +6,7 @@ import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.Payload import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest._arch.structure.abstraction.findItem +import com.tangem.tangemtest._arch.structure.abstraction.iterate import com.tangem.tangemtest.ucase.domain.actions.Action import com.tangem.tangemtest.ucase.domain.actions.AttrForAction import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback @@ -47,6 +48,10 @@ open class BaseItemsManager(protected val action: Action) : ItemsManager, Lifecy this.changeConsequence = consequence } + override fun updateByItemList(list: List) { + list.iterate { itemList.findItem(it.id)?.update(it) } + } + override fun invokeMainAction(tangemSdk: TangemSdk, callback: ActionCallback) { action.executeMainAction(this, getAttrsForAction(tangemSdk), callback) } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt index 1652cd2833..4a9c0b0572 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/managers/PersonalizationItemsManager.kt @@ -29,7 +29,7 @@ class PersonalizationItemsManager( @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onDestroy() { - val config = converter.convert(itemList, PersonalizationConfig()) + val config = converter.convert(itemList, PersonalizationConfig.default()) store.save(config) } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt index 730c570be6..bb771e86f6 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/paramsManager/triggers/changeConsequence/ParamChangeConsequence.kt @@ -4,6 +4,7 @@ import com.tangem.commands.Card import com.tangem.commands.EllipticCurve import com.tangem.common.extensions.calculateSha256 import com.tangem.common.extensions.calculateSha512 +import com.tangem.common.extensions.toHexString import com.tangem.tangemtest._arch.structure.PayloadHolder import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest._arch.structure.abstraction.findItem @@ -40,7 +41,7 @@ class SignScanConsequence : ItemsChangeConsequence { EllipticCurve.Ed25519 -> dataForHashing.calculateSha512() else -> return null } - hashItem.setData(hashedData) + hashItem.setData(hashedData.toHexString()) } return affectedItems.toList() } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/ResponseJsonConverter.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/ResponseJsonConverter.kt index 444f2bd35a..5533c3682d 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/ResponseJsonConverter.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/domain/responses/ResponseJsonConverter.kt @@ -3,6 +3,7 @@ package com.tangem.tangemtest.ucase.domain.responses import com.google.gson.* import com.tangem.commands.* import com.tangem.common.extensions.toHexString +import com.tangem.tangemtest.extensions.print import java.lang.reflect.Type import java.text.DateFormat import java.util.* @@ -11,14 +12,17 @@ import java.util.* [REDACTED_AUTHOR] */ class ResponseJsonConverter { + val gson: Gson by lazy { init() } + private val fieldConverter = ResponseFieldConverter() + private fun init(): Gson { val builder = GsonBuilder().apply { - registerTypeAdapter(ByteArray::class.java, ByteTypeAdapter()) - registerTypeAdapter(SigningMethodMask::class.java, SigningMethodTypeAdapter()) - registerTypeAdapter(SettingsMask::class.java, SettingsMaskTypeAdapter()) - registerTypeAdapter(ProductMask::class.java, ProductMaskTypeAdapter()) + registerTypeAdapter(ByteArray::class.java, ByteTypeAdapter(fieldConverter)) + registerTypeAdapter(SigningMethodMask::class.java, SigningMethodTypeAdapter(fieldConverter)) + registerTypeAdapter(SettingsMask::class.java, SettingsMaskTypeAdapter(fieldConverter)) + registerTypeAdapter(ProductMask::class.java, ProductMaskTypeAdapter(fieldConverter)) registerTypeAdapter(Date::class.java, DateTypeAdapter()) } builder.setPrettyPrinting() @@ -28,31 +32,41 @@ class ResponseJsonConverter { fun convertResponse(response: CommandResponse?): String = gson.toJson(response) } -class ByteTypeAdapter : JsonSerializer { +class ByteTypeAdapter( + private val fieldConverter: ResponseFieldConverter +) : JsonSerializer { override fun serialize(src: ByteArray, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - return JsonPrimitive(src.toHexString()) + return JsonPrimitive(fieldConverter.byteArray(src)) } } -class SettingsMaskTypeAdapter : JsonSerializer { +class SettingsMaskTypeAdapter( + private val fieldConverter: ResponseFieldConverter +) : JsonSerializer { override fun serialize(src: SettingsMask, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - val arrayElement = JsonArray() - Settings.values() - .filter { src.contains(it) } - .forEach { arrayElement.add(it.name) } - return arrayElement + return JsonArray().apply { + fieldConverter.settingsMaskList(src).forEach { add(it) } + } } } -class ProductMaskTypeAdapter : JsonSerializer { +class ProductMaskTypeAdapter( + private val fieldConverter: ResponseFieldConverter +) : JsonSerializer { override fun serialize(src: ProductMask, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - return JsonPrimitive(src.rawValue.toString()) + return JsonArray().apply { + fieldConverter.productMaskList(src).forEach { add(it) } + } } } -class SigningMethodTypeAdapter : JsonSerializer { +class SigningMethodTypeAdapter( + private val fieldConverter: ResponseFieldConverter +) : JsonSerializer { override fun serialize(src: SigningMethodMask, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - return JsonPrimitive(src.rawValue.toString()) + return JsonArray().apply { + fieldConverter.signingMethodList(src).forEach { add(it) } + } } } @@ -61,4 +75,41 @@ class DateTypeAdapter : JsonSerializer { val formatter = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale("en_US")) return JsonPrimitive(formatter.format(src).toString()) } +} + +class ResponseFieldConverter { + + fun productMask(productMask: ProductMask?): String { + return productMaskList(productMask).print(wrap = false) + } + + fun productMaskList(productMask: ProductMask?): List { + val mask = productMask ?: return emptyList() + + return Product.values().filter { mask.contains(it) }.map { it.name } + } + + fun signingMethod(signingMask: SigningMethodMask?): String { + return signingMethodList(signingMask).print(wrap = false) + } + + fun signingMethodList(signingMask: SigningMethodMask?): List { + val mask = signingMask ?: return emptyList() + + return SigningMethod.values().filter { mask.contains(it) }.map { it.name } + } + + fun settingsMask(settingsMask: SettingsMask?): String { + return settingsMaskList(settingsMask).print(wrap = false) + } + + fun settingsMaskList(settingsMask: SettingsMask?): List { + val masks = settingsMask ?: return emptyList() + + return Settings.values().filter { masks.contains(it) }.map { it.name } + } + + fun byteArray(byteArray: ByteArray?): String? { + return byteArray?.toHexString() + } } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/ResponseResources.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/ResponseResources.kt index a9ad0a3d69..a199a04a26 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/ResponseResources.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/resources/initializers/ResponseResources.kt @@ -5,6 +5,8 @@ import com.tangem.tangemtest.ucase.resources.MainResourceHolder import com.tangem.tangemtest.ucase.resources.Resources import com.tangem.tangemtest.ucase.variants.responses.CardDataId import com.tangem.tangemtest.ucase.variants.responses.CardId +import com.tangem.tangemtest.ucase.variants.responses.DepersonalizeId +import com.tangem.tangemtest.ucase.variants.responses.SignId /** [REDACTED_AUTHOR] @@ -13,6 +15,8 @@ class ResponseResources { fun init(holder: MainResourceHolder) { initCard(holder) initCardData(holder) + initSignResponse(holder) + initDepersonalizeResponse(holder) } private fun initCard(holder: MainResourceHolder) { @@ -26,7 +30,7 @@ class ResponseResources { holder.register(CardId.issuerPublicKey, Resources(R.string.response_card_issuer_data_public_key, R.string.info_response_card_issuer_data_public_key)) holder.register(CardId.curve, Resources(R.string.response_card_curve, R.string.info_response_card_curve)) holder.register(CardId.maxSignatures, Resources(R.string.response_card_max_signatures, R.string.info_response_card_max_signatures)) - holder.register(CardId.signingMethod, Resources(R.string.response_card_signing_method, R.string.response_card_signing_method)) + holder.register(CardId.signingMethod, Resources(R.string.response_card_signing_method, R.string.info_response_card_signing_method)) holder.register(CardId.pauseBeforePin2, Resources(R.string.response_card_pause_before_pin2, R.string.info_response_card_allow_pin2)) holder.register(CardId.walletPublicKey, Resources(R.string.response_card_wallet_public_key, R.string.info_response_card_wallet_public_key)) holder.register(CardId.walletRemainingSignatures, Resources(R.string.response_card_wallet_remaining_signatures, R.string.info_response_card_wallet_remaining_signatures)) @@ -50,4 +54,15 @@ class ResponseResources { holder.register(CardDataId.tokenContractAddress, Resources(R.string.response_card_card_data_token_contract_address, R.string.info_response_card_card_data_token_contract_address)) holder.register(CardDataId.tokenDecimal, Resources(R.string.response_card_card_data_token_decimal, R.string.info_response_card_card_data_token_decimal)) } + + private fun initSignResponse(holder: MainResourceHolder) { + holder.register(SignId.cid, Resources(R.string.response_sign_cid, R.string.info_response_sign_cid)) + holder.register(SignId.walletSignedHashes, Resources(R.string.response_sign_wallet_signed_hashes, R.string.info_response_sign_wallet_signed_hashes)) + holder.register(SignId.walletRemainingSignatures, Resources(R.string.response_sign_wallet_remaining_signatures, R.string.info_response_sign_wallet_remaining_signatures)) + holder.register(SignId.signature, Resources(R.string.response_sign_signature, R.string.info_response_sign_signature)) + } + + private fun initDepersonalizeResponse(holder: MainResourceHolder) { + holder.register(DepersonalizeId.isSuccess, Resources(R.string.response_depersonalize_is_success, R.string.info_response_depersonalize_is_success)) + } } \ No newline at end of file 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 e9916b33f0..32c0746431 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 @@ -8,9 +8,11 @@ import androidx.core.view.plusAssign import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.Observer +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.google.android.material.floatingactionbutton.FloatingActionButton import com.tangem.TangemSdk import com.tangem.commands.Card +import com.tangem.commands.CommandResponse import com.tangem.tangem_sdk_new.extensions.init import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.Id @@ -28,7 +30,8 @@ import ru.dev.gbixahue.eu4d.lib.android.global.log.Log */ abstract class BaseCardActionFragment : BaseFragment(), ActionView { - protected lateinit var itemContainer: ViewGroup + protected lateinit var swrLayout: SwipeRefreshLayout + protected lateinit var contentContainer: ViewGroup protected lateinit var actionFab: FloatingActionButton protected abstract val itemsManager: ItemsManager @@ -38,6 +41,8 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { private val paramsWidgetList = mutableListOf() + override fun getLayoutId(): Int = R.layout.fg_base_action_layout + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) Log.d(this, "onViewCreated") @@ -47,7 +52,7 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { actionVM.setCardManager(TangemSdk.init(requireActivity())) actionVM.attachToPayload(mutableMapOf(PayloadKey.actionView to this as ActionView)) - initFab() + initViews() createWidgets { widgetsWasCreated() subscribeToViewModelChanges() @@ -57,11 +62,13 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { protected open fun widgetsWasCreated() {} protected open fun bindViews() { - itemContainer = mainView.findViewById(R.id.ll_container) + swrLayout = mainView.findViewById(R.id.swr_layout) + contentContainer = mainView.findViewById(R.id.ll_content_container) actionFab = mainView.findViewById(R.id.fab_action) } - protected open fun initFab() { + protected open fun initViews() { + swrLayout.isEnabled = false enableActionFab(false) actionFab.setOnClickListener { actionVM.invokeMainAction() } } @@ -70,7 +77,7 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { Log.d(this, "createWidgets") actionVM.ldItemList.observe(viewLifecycleOwner, Observer { itemList -> itemList.forEach { param -> - val widget = ParameterWidget(inflateParamView(itemContainer), param) + val widget = ParameterWidget(inflateParamView(contentContainer), param) widget.onValueChanged = { id, value -> actionVM.userChangedItem(id, value) } widget.onActionBtnClickListener = actionVM.getItemAction(param.id) paramsWidgetList.add(widget) @@ -81,39 +88,46 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { protected open fun subscribeToViewModelChanges() { Log.d(this, "subscribeToViewModelChanges") - listenResponse() - listenResponseData() - listenResponseCardData() - listenError() - listenChangedItems() - listenDescriptionSwitchChanges() - } - - private fun listenResponse() { actionVM.seResponse.observe(viewLifecycleOwner, Observer { - Log.d(this, "listen response: $it") - mainActivityVM.changeResponseEvent(it) + Log.d(this, "handle response: $it") + handleResponse(it) }) - } - - protected open fun listenResponseData() { actionVM.seResponseData.observe(viewLifecycleOwner, Observer { - Log.d(this, "listen responseData: $it") - navigateTo(R.id.action_nav_card_action_to_response_screen) + Log.d(this, "handle responseData: $it") + handleResponseData(it) }) - } - - protected open fun listenResponseCardData() { actionVM.seResponseCardData.observe(viewLifecycleOwner, Observer { - Log.d(this, "listen responseCardData: $it") - responseCardDataHandled(it) + Log.d(this, "handle responseCardData: $it") + handleResponseCardData(it) }) + actionVM.seError.observe(viewLifecycleOwner, Observer { + Log.d(this, "handle error: $it") + handleError(it) + }) + mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer { + Log.d(this, "handle descriptionVisibilityState: $it") + handleDescriptionSwitchChanges(it) + }) + listenChangedItems() } - protected open fun responseCardDataHandled(card: Card?) {} + protected open fun handleResponse(response: CommandResponse) { + mainActivityVM.changeResponseEvent(response) + } - protected open fun listenError() { - actionVM.seError.observe(viewLifecycleOwner, Observer { showSnackbar(it) }) + protected open fun handleResponseData(response: CommandResponse) { + navigateTo(R.id.action_nav_card_action_to_response_screen, options = null) + } + + protected open fun handleResponseCardData(card: Card) {} + + protected open fun handleError(error: String) { + showSnackbar(error) + } + + protected open fun handleDescriptionSwitchChanges(descriptionVisibilityState: Boolean) { + actionVM.toggleDescriptionVisibility(descriptionVisibilityState) + paramsWidgetList.forEach { it.toggleDescriptionVisibility(descriptionVisibilityState) } } @Deprecated("Start to use itemViewModel") @@ -126,12 +140,6 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView { }) } - protected open fun listenDescriptionSwitchChanges() { - mainActivityVM.ldDescriptionSwitch.observe(viewLifecycleOwner, Observer { - actionVM.toggleDescriptionVisibility(it) - }) - } - private fun inflateParamView(where: ViewGroup): ViewGroup { val inflater = LayoutInflater.from(where.context) val view = inflater.inflate(R.layout.w_card_incoming_param, where, false) diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/widgets/ParameterWidget.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/widgets/ParameterWidget.kt index 96037984ea..ab01e1a692 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/widgets/ParameterWidget.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/ui/widgets/ParameterWidget.kt @@ -6,14 +6,13 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView -import androidx.transition.AutoTransition -import androidx.transition.TransitionManager import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import com.tangem.tangemtest.R import com.tangem.tangemtest._arch.structure.Id import com.tangem.tangemtest._arch.structure.abstraction.Item import com.tangem.tangemtest._arch.structure.impl.EditTextItem +import com.tangem.tangemtest.extensions.view.beginDelayedTransition import com.tangem.tangemtest.ucase.resources.ActionType import com.tangem.tangemtest.ucase.resources.MainResourceHolder import com.tangem.tangemtest.ucase.resources.Resources @@ -73,7 +72,7 @@ class ParameterWidget( } fun toggleDescriptionVisibility(state: Boolean) { - TransitionManager.beginDelayedTransition(parent.parent as ViewGroup, AutoTransition()) + (parent.parent as ViewGroup).beginDelayedTransition() descriptionContainer.visibility = if (state) View.VISIBLE else View.GONE } @@ -95,7 +94,7 @@ class ParameterWidget( private fun toggleActionBtnVisibility() { fun switchVisibilityState(newState: Int) { actionBtnVisibilityState = newState - TransitionManager.beginDelayedTransition(parent, AutoTransition()) + parent.beginDelayedTransition() btnAction.visibility = actionBtnVisibilityState } when { diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/depersonalize/ui/DepersonalizeActionFragment.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/depersonalize/ui/DepersonalizeActionFragment.kt index e2ae9cdbdd..107ab9b3b3 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/depersonalize/ui/DepersonalizeActionFragment.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/depersonalize/ui/DepersonalizeActionFragment.kt @@ -1,6 +1,5 @@ package com.tangem.tangemtest.ucase.variants.depersonalize.ui -import com.tangem.tangemtest.R import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager import com.tangem.tangemtest.ucase.domain.paramsManager.managers.DepersonalizeItemsManager import com.tangem.tangemtest.ucase.ui.BaseCardActionFragment @@ -11,6 +10,4 @@ import com.tangem.tangemtest.ucase.ui.BaseCardActionFragment class DepersonalizeActionFragment : BaseCardActionFragment() { override val itemsManager: ItemsManager by lazy { DepersonalizeItemsManager() } - - override fun getLayoutId(): Int = R.layout.fg_depersonalize } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/PersonalizationConfigStore.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/PersonalizationConfigStore.kt index 77a68278f8..9c774a8071 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/PersonalizationConfigStore.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/PersonalizationConfigStore.kt @@ -5,22 +5,49 @@ import android.content.SharedPreferences import androidx.core.content.edit import com.google.gson.Gson import com.tangem.tangemtest.AppTangemDemo +import com.tangem.tangemtest.commons.KeyedStore import com.tangem.tangemtest.commons.Store import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig -class PersonalizationConfigStore(context: Context) : Store { +class PersonalizationConfigStore(context: Context) : Store, KeyedStore { - private val key = "personalization_config" + companion object { + val defaultKey = "default" + } - private val sp: SharedPreferences = (context.applicationContext as AppTangemDemo).sharedPreferences() + private val sharedPreferencesKey = "personalization_presets" + + private val sp: SharedPreferences = (context.applicationContext as AppTangemDemo).sharedPreferences(sharedPreferencesKey) private val gson: Gson = Gson() - override fun save(config: PersonalizationConfig) { - sp.edit(true) { putString(key, gson.toJson(config)) } + override fun save(value: PersonalizationConfig) { + save(defaultKey, value) } - override fun restore(): PersonalizationConfig { - val json = sp.getString(key, gson.toJson(PersonalizationConfig())) - return gson.fromJson(json, PersonalizationConfig::class.java) + override fun restore(): PersonalizationConfig = restore(defaultKey) + + override fun save(key: String, value: PersonalizationConfig) { + sp.edit(true) { putString(key, toJson(value)) } } + + override fun restore(key: String): PersonalizationConfig { + val json = sp.getString(key, toJson(getDefaultConfig())) + return fromJson(json!!) + } + + override fun restoreAll(): MutableMap { + val map = mutableMapOf() + sp.all.forEach { map[it.key] = fromJson(it.value as String) } + return map.toSortedMap() + } + + override fun delete(key: String) { + sp.edit(true) { remove(key) } + } + + private fun getDefaultConfig(): PersonalizationConfig = PersonalizationConfig.default() + + private fun toJson(value: PersonalizationConfig): String = gson.toJson(value) + + private fun fromJson(json: String): PersonalizationConfig = gson.fromJson(json, PersonalizationConfig::class.java) } \ No newline at end of file diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt index 37364a0f8a..2f406d98c3 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/converter/DefaultValues.kt @@ -19,7 +19,7 @@ class ConfigValuesHolder : BaseTypedHolder() { register(CardNumber.BatchId, Value(default.batchId)) register(Common.Curve, Value(default.curveID, Helper.listOfCurves())) register(Common.Blockchain, Value(default.blockchain, Helper.listOfBlockchain())) - register(Common.BlockchainCustom, Value("")) + register(Common.BlockchainCustom, Value(default.blockchainCustom)) register(Common.MaxSignatures, Value(default.MaxSignatures)) register(Common.CreateWallet, Value(default.createWallet)) register(SigningMethod.SignTx, Value(default.SigningMethod0)) @@ -66,7 +66,7 @@ class ConfigValuesHolder : BaseTypedHolder() { register(SettingsMaskNdef.DynamicNdef, Value(default.useDynamicNDEF)) register(SettingsMaskNdef.DisablePrecomputedNdef, Value(default.disablePrecomputedNDEF)) register(SettingsMaskNdef.Aar, Value(default.aar, Helper.aarList())) - register(SettingsMaskNdef.AarCustom, Value(default.aar)) + register(SettingsMaskNdef.AarCustom, Value(default.aarCustom)) register(SettingsMaskNdef.Uri, Value(default.uri)) register(Pins.Pin, Value(default.PIN)) register(Pins.Pin2, Value(default.PIN2)) 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 d450ab54d9..3d7fb1e3d1 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 @@ -52,6 +52,7 @@ class ItemsToPersonalizationConfig : ItemsToModel { val export = PersonalizationConfig() export.series = getTyped(CardNumber.Series) export.startNumber = getTyped(CardNumber.Number) + export.batchId = getTyped(CardNumber.BatchId) export.curveID = getTyped(Common.Curve) export.blockchain = getTyped(Common.Blockchain) export.blockchainCustom = getTyped(Common.BlockchainCustom) diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizationConfig.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizationConfig.kt index 2bfd50514c..ebb7daea63 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizationConfig.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/ucase/variants/personalize/dto/PersonalizationConfig.kt @@ -1,25 +1,26 @@ package com.tangem.tangemtest.ucase.variants.personalize.dto +import com.tangem.commands.EllipticCurve + /** [REDACTED_AUTHOR] */ class PersonalizationConfig { // Card number - var series = "BB" - var startNumber: Long = 300000000000 - var batchId = "ffff" - + var series = "" + var startNumber: Long = 0 + var batchId = "" // Common - var curveID = "ed25519" - var blockchain = "BTC/test" + var curveID = "" + var blockchain = "" var blockchainCustom = "" - var MaxSignatures: Long = 999999 - var createWallet = true + var MaxSignatures: Long = 0 + var createWallet = false // Signing method - var SigningMethod0 = true + var SigningMethod0 = false var SigningMethod1 = false var SigningMethod2 = false var SigningMethod3 = false @@ -27,19 +28,16 @@ class PersonalizationConfig { var SigningMethod5 = false var SigningMethod6 = false - // Sign hash external properties - var pinLessFloorLimit: Long = 100000 - var hexCrExKey = "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211000000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF" + var pinLessFloorLimit: Long = 0 + var hexCrExKey = "" var requireTerminalTxSignature = false var requireTerminalCertSignature = false - var checkPIN3onCard = true - + var checkPIN3onCard = false // Denomination var writeOnPersonalization = false - var denomination: Long = 1000000 - + var denomination: Long = 0 // Token var itsToken = false @@ -47,49 +45,125 @@ class PersonalizationConfig { var contractAddress = "" var decimal: Long = 0 - var cardData = CardData() - // Settings mask - var isReusable = true + var isReusable = false var useActivation = false var forbidPurgeWallet = false var allowSelectBlockchain = false var useBlock = false var oneApdu = false var useCVC = false - var allowSwapPIN = true - var allowSwapPIN2 = true + var allowSwapPIN = false + var allowSwapPIN2 = false var forbidDefaultPIN = false - var smartSecurityDelay = true - var protectIssuerDataAgainstReplay = true - var skipSecurityDelayIfValidatedByIssuer = true - var skipCheckPIN2andCVCIfValidatedByIssuer = true - var skipSecurityDelayIfValidatedByLinkedTerminal = true + var smartSecurityDelay = false + var protectIssuerDataAgainstReplay = false + var skipSecurityDelayIfValidatedByIssuer = false + var skipCheckPIN2andCVCIfValidatedByIssuer = false + var skipSecurityDelayIfValidatedByLinkedTerminal = false var restrictOverwriteIssuerDataEx = false - // Settings mask - protocol encryption - var protocolAllowUnencrypted = true - var protocolAllowStaticEncryption = true + var protocolAllowUnencrypted = false + var protocolAllowStaticEncryption = false - - var useNDEF = true - var useDynamicNDEF = true + var useNDEF = false + var useDynamicNDEF = false var disablePrecomputedNDEF = false - var aar = "com.tangem.wallet" + var aar = "" var aarCustom = "" - var uri = "https://tangem.com" - + var uri = "" // Pins - var PIN = "000000" - var PIN2 = "000" + var PIN = "" + var PIN2 = "" var PIN3 = "" - var CVC = "000" - var pauseBeforePIN2: Long = 5000L + var CVC = "" + var pauseBeforePIN2: Long = 0 + companion object { + fun default(): PersonalizationConfig { + return PersonalizationConfig().apply { + // Card number + series = "BB" + startNumber = 300000000000L + batchId = "ffff" + + // Common + curveID = EllipticCurve.Secp256k1.curve + blockchain = "ETH" + blockchainCustom = "" + MaxSignatures = 999999L + createWallet = true + + // Signing method + SigningMethod0 = true + SigningMethod1 = false + SigningMethod2 = false + SigningMethod3 = false + SigningMethod4 = false + SigningMethod5 = false + SigningMethod6 = false + + // Sign hash external properties + pinLessFloorLimit = 100000L + hexCrExKey = "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211000000111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF" + requireTerminalTxSignature = false + requireTerminalCertSignature = false + checkPIN3onCard = true + + // Denomination + writeOnPersonalization = false + denomination = 1000000L + + // Token + itsToken = false + symbol = "" + contractAddress = "" + decimal = 0L + + cardData = CardData() + + // Settings mask + isReusable = true + useActivation = false + forbidPurgeWallet = false + allowSelectBlockchain = false + useBlock = false + oneApdu = false + useCVC = false + allowSwapPIN = true + allowSwapPIN2 = true + forbidDefaultPIN = false + smartSecurityDelay = true + protectIssuerDataAgainstReplay = true + skipSecurityDelayIfValidatedByIssuer = true + skipCheckPIN2andCVCIfValidatedByIssuer = true + skipSecurityDelayIfValidatedByLinkedTerminal = true + restrictOverwriteIssuerDataEx = false + + // Settings mask - protocol encryption + protocolAllowUnencrypted = true + protocolAllowStaticEncryption = true + + useNDEF = true + useDynamicNDEF = true + disablePrecomputedNDEF = false + aar = "com.tangem.wallet" + aarCustom = "" + uri = "https://tangem.com" + + // Pins + PIN = "000000" + PIN2 = "000" + PIN3 = "" + CVC = "000" + pauseBeforePIN2 = 5000L + } + } + } } class CardData { 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 40133ebfd6..cab78e4834 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 @@ -1,18 +1,30 @@ package com.tangem.tangemtest.ucase.variants.personalize.ui +import android.content.DialogInterface import android.os.Bundle -import android.view.View -import android.view.ViewGroup +import android.view.* +import android.view.inputmethod.InputMethodManager import android.widget.Button +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat.getSystemService import androidx.lifecycle.Observer +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.transition.Fade import com.tangem.commands.Card 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.structure.abstraction.SafeValueChanged import com.tangem.tangemtest._arch.widget.WidgetBuilder +import com.tangem.tangemtest.commons.DialogController import com.tangem.tangemtest.commons.view.MultiActionView import com.tangem.tangemtest.commons.view.ViewAction +import com.tangem.tangemtest.extensions.view.beginDelayedTransition 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 @@ -21,28 +33,80 @@ 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.presets.PersonalizationPresetManager +import com.tangem.tangemtest.ucase.variants.personalize.ui.presets.PersonalizationPresetView +import com.tangem.tangemtest.ucase.variants.personalize.ui.presets.RvPresetNamesAdapter import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.PersonalizationItemBuilder +import com.tangem.tangemtest.ucase.variants.responses.ui.ResponseFragment import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate import ru.dev.gbixahue.eu4d.lib.android.global.log.Log +import ru.dev.gbixahue.eu4d.lib.android.global.threading.post +import ru.dev.gbixahue.eu4d.lib.android.global.threading.postUI +import ru.dev.gbixahue.eu4d.lib.android.global.threading.postWork + /** [REDACTED_AUTHOR] */ -class PersonalizationFragment : BaseCardActionFragment() { +class PersonalizationFragment : BaseCardActionFragment(), PersonalizationPresetView { override val itemsManager: ItemsManager by lazy { PersonalizationItemsManager(PersonalizationConfigStore(requireContext())) } - override fun getLayoutId(): Int = R.layout.fg_personalization + override fun getLayoutId(): Int = R.layout.fg_base_action_layout + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) lifecycle.addObserver(itemsManager as PersonalizationItemsManager) } + override fun bindViews() { + super.bindViews() + swrLayout.isRefreshing = true + } + + override fun initViews() { + actionFab.setOnClickListener { actionVM.invokeMainAction() } + } + + override fun createWidgets(widgetCreatedCallback: () -> Unit) { + Log.d(this, "createWidgets") + val itemList = mutableListOf() + + val maxDelay = 500 + val timeStart = System.currentTimeMillis() + actionVM.ldItemList.observe(viewLifecycleOwner, Observer { list -> + Log.d(this, "ldBlockList size: ${list.size}") + itemList.addAll(list) + val llContainer = LinearLayout(requireContext()).apply { orientation = LinearLayout.VERTICAL } + postWork { + val builder = WidgetBuilder(PersonalizationItemBuilder()) + itemList.forEach { builder.build(it, llContainer) } + actionVM.attachToPayload(mutableMapOf( + PayloadKey.actionView to this as ActionView, + PayloadKey.itemList to itemList + )) + val timeEnd = System.currentTimeMillis() + val diff = timeEnd - timeStart + postUI(maxDelay - diff) { + contentContainer.beginDelayedTransition(Fade()) + contentContainer.addView(llContainer) + widgetCreatedCallback() + swrLayout.isRefreshing = false + swrLayout.isEnabled = false + } + } + }) + } + override fun widgetsWasCreated() { super.widgetsWasCreated() - val btnContainer = itemContainer.inflate(R.layout.view_simple_button) + val btnContainer = contentContainer.inflate(R.layout.view_simple_button) val btn = btnContainer.findViewById