Updated on 2026-08-14
This commit is contained in:
parent
15ba43b948
commit
9056c31bb6
43 changed files with 730 additions and 762 deletions
|
|
@ -3,10 +3,6 @@ package com.tangem.tangemtest._arch.structure
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface DataHolder<D> {
|
||||
var viewModel: D
|
||||
}
|
||||
|
||||
typealias Payload = MutableMap<String, Any?>
|
||||
|
||||
interface PayloadHolder {
|
||||
|
|
@ -17,12 +13,4 @@ interface PayloadHolder {
|
|||
fun set(key: String, value: Any?) {
|
||||
payload[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
interface ItemListHolder<I> {
|
||||
fun setItems(list: MutableList<I>)
|
||||
fun getItems(): MutableList<I>
|
||||
fun addItem(item: I)
|
||||
fun removeItem(item: I)
|
||||
fun clear()
|
||||
}
|
||||
|
|
@ -5,7 +5,9 @@ package com.tangem.tangemtest._arch.structure
|
|||
*/
|
||||
interface Id
|
||||
|
||||
class StringId(val name: String) : Id
|
||||
class StringId(val value: String) : Id
|
||||
|
||||
class StringResId(val value: Int) : Id
|
||||
|
||||
enum class Additional : Id {
|
||||
UNDEFINED,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import com.tangem.tangemtest._arch.structure.Id
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
fun List<Item>.findDataItem(id: Id): BaseItem<Any?>? {
|
||||
var foundItem: BaseItem<Any?>? = null
|
||||
fun List<Item>.findItem(id: Id): Item? {
|
||||
var foundItem: Item? = null
|
||||
iterate {
|
||||
if (it.id == id) {
|
||||
foundItem = it as? BaseItem<Any?>
|
||||
foundItem = it
|
||||
return@iterate
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,8 @@ fun List<Item>.findDataItem(id: Id): BaseItem<Any?>? {
|
|||
fun List<Item>.iterate(func: (Item) -> Unit) {
|
||||
forEach {
|
||||
when (it) {
|
||||
is BaseItem<*> -> func(it)
|
||||
is Block -> it.itemList.iterate(func)
|
||||
is BaseItem -> func(it)
|
||||
is ItemGroup -> it.itemList.iterate(func)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +1,39 @@
|
|||
package com.tangem.tangemtest._arch.structure.abstraction
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.DataHolder
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.Payload
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Item : PayloadHolder {
|
||||
interface Item {
|
||||
val id: Id
|
||||
var parent: Item?
|
||||
}
|
||||
var viewModel: ItemViewModel
|
||||
|
||||
abstract class BaseItem<D>(
|
||||
override var viewModel: ItemViewModel<D>
|
||||
) : Item, DataHolder<ItemViewModel<D>> {
|
||||
override var parent: Item? = null
|
||||
override val payload: Payload = mutableMapOf()
|
||||
fun added(parent: Item) {
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
fun getData(): D? = viewModel.data
|
||||
fun removed(parent: Item) {
|
||||
this.parent = null
|
||||
}
|
||||
|
||||
fun setData(value: D?) {
|
||||
fun <D> getData(): D? = viewModel.data as? D
|
||||
|
||||
fun setData(value: Any?) {
|
||||
viewModel.data = value
|
||||
}
|
||||
|
||||
fun restoreDefaultData() {
|
||||
setData(viewModel.defaultData)
|
||||
}
|
||||
}
|
||||
|
||||
open class BaseItem(
|
||||
override val id: Id,
|
||||
override var viewModel: ItemViewModel
|
||||
) : Item {
|
||||
|
||||
override var parent: Item? = null
|
||||
|
||||
}
|
||||
|
|
@ -2,45 +2,47 @@ package com.tangem.tangemtest._arch.structure.abstraction
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.ILog
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.ItemListHolder
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Block : Item {
|
||||
interface ItemGroup : Item {
|
||||
val itemList: MutableList<Item>
|
||||
|
||||
fun setItems(list: MutableList<Item>)
|
||||
fun getItems(): MutableList<Item>
|
||||
fun addItem(item: Item)
|
||||
fun removeItem(item: Item)
|
||||
fun clear()
|
||||
}
|
||||
|
||||
abstract class BaseBlock : Block {
|
||||
open class SimpleItemGroup(
|
||||
override val id: Id,
|
||||
override var viewModel: ItemViewModel = BaseItemViewModel()
|
||||
) : ItemGroup {
|
||||
|
||||
override var parent: Item? = null
|
||||
override val itemList: MutableList<Item> = mutableListOf()
|
||||
override val payload: MutableMap<String, Any?> = mutableMapOf()
|
||||
}
|
||||
|
||||
open class ListItemBlock(
|
||||
override val id: Id
|
||||
) : BaseBlock(), ItemListHolder<Item> {
|
||||
|
||||
override fun setItems(list: MutableList<Item>) {
|
||||
ILog.d(this, "setItems into: $id, count: ${list.size}")
|
||||
itemList.forEach { it.removed(this) }
|
||||
itemList.clear()
|
||||
itemList.addAll(list)
|
||||
itemList.forEach { it.parent = this }
|
||||
list.forEach { addItem(it) }
|
||||
}
|
||||
|
||||
override fun getItems(): MutableList<Item> {
|
||||
return itemList
|
||||
}
|
||||
override fun getItems(): MutableList<Item> = itemList
|
||||
|
||||
override fun addItem(item: Item) {
|
||||
ILog.d(this, "addItem into: $id, who: ${item.id}")
|
||||
item.parent = this
|
||||
itemList.add(item)
|
||||
item.added(this)
|
||||
}
|
||||
|
||||
override fun removeItem(item: Item) {
|
||||
ILog.d(this, "removeItem from: $id, which: ${item.id}")
|
||||
itemList.remove(item)
|
||||
item.removed(this)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
|
|
@ -11,54 +11,7 @@ import com.tangem.tangemtest._arch.structure.PayloadHolder
|
|||
typealias ValueChange<V> = (V?) -> Unit
|
||||
typealias SafeValueChange<V> = (V) -> Unit
|
||||
|
||||
interface ItemViewModel<D : Any?> : PayloadHolder {
|
||||
val viewState: ViewState
|
||||
var data: D?
|
||||
var defaultData: D?
|
||||
var onDataUpdated: ValueChange<D>?
|
||||
|
||||
fun updateDataByView(data: D?)
|
||||
}
|
||||
|
||||
open class BaseItemViewModel<D> : ItemViewModel<D> {
|
||||
|
||||
override val viewState: ViewState = ViewState()
|
||||
override val payload: Payload = mutableMapOf()
|
||||
|
||||
// Don't update it directly from a View. Use for it updateDataByView()
|
||||
override var data: D? = null
|
||||
set(value) {
|
||||
if (handleDataUpdates(value)) field = value
|
||||
}
|
||||
|
||||
// Data for restoring initial value
|
||||
override var defaultData: D? = null
|
||||
set(value) {
|
||||
field = value
|
||||
data = value
|
||||
}
|
||||
|
||||
// Use it for handling data updates in View
|
||||
override var onDataUpdated: ValueChange<D>? = null
|
||||
|
||||
// When data updates directly it invokes onDataUpdated
|
||||
// return true = data will update
|
||||
// return false = data won't update
|
||||
protected open fun handleDataUpdates(value: D?): Boolean {
|
||||
ILog.d(this, "handleDateUpdates: $value")
|
||||
onDataUpdated?.invoke(value)
|
||||
return true
|
||||
}
|
||||
|
||||
// Use it to update the data from a View. It disables onDataUpdated to prevent a callback loop
|
||||
override fun updateDataByView(data: D?) {
|
||||
ILog.d(this, "data changed: $data")
|
||||
val callback = onDataUpdated
|
||||
onDataUpdated = null
|
||||
this.data = data
|
||||
onDataUpdated = callback
|
||||
}
|
||||
}
|
||||
class KeyValue(val key: String, val value: Any)
|
||||
|
||||
class ViewState {
|
||||
var isHiddenField = false
|
||||
|
|
@ -70,4 +23,58 @@ class ViewState {
|
|||
}
|
||||
|
||||
var onDescriptionVisibilityChanged: SafeValueChange<Int>? = null
|
||||
}
|
||||
}
|
||||
|
||||
interface ItemViewModel : PayloadHolder {
|
||||
val viewState: ViewState
|
||||
var data: Any?
|
||||
var defaultData: Any?
|
||||
var onDataUpdated: ValueChange<Any?>?
|
||||
|
||||
fun updateDataByView(data: Any?)
|
||||
}
|
||||
|
||||
open class BaseItemViewModel(value: Any? = null) : ItemViewModel {
|
||||
|
||||
override val viewState: ViewState = ViewState()
|
||||
override val payload: Payload = mutableMapOf()
|
||||
|
||||
// Don't update it directly from a View. Use for it updateDataByView()
|
||||
override var data: Any? = value
|
||||
set(value) {
|
||||
if (handleDataUpdates(value)) field = value
|
||||
}
|
||||
|
||||
// Data for restoring initial value
|
||||
override var defaultData: Any? = value
|
||||
set(value) {
|
||||
field = value
|
||||
data = value
|
||||
}
|
||||
|
||||
// Use it for handling data updates in View
|
||||
override var onDataUpdated: ValueChange<Any?>? = null
|
||||
|
||||
// When data updates directly it invokes onDataUpdated
|
||||
// return true = data will update
|
||||
// return false = data won't update
|
||||
protected open fun handleDataUpdates(value: Any?): Boolean {
|
||||
ILog.d(this, "handleDateUpdates: $value")
|
||||
onDataUpdated?.invoke(value)
|
||||
return true
|
||||
}
|
||||
|
||||
// Use it to update the data from a View. It disables onDataUpdated to prevent a callback loop
|
||||
override fun updateDataByView(data: Any?) {
|
||||
ILog.d(this, "data changed: $data")
|
||||
val callback = onDataUpdated
|
||||
onDataUpdated = null
|
||||
this.data = data
|
||||
onDataUpdated = callback
|
||||
}
|
||||
}
|
||||
|
||||
class ListViewModel(
|
||||
var selectedItem: Any?,
|
||||
val itemList: List<KeyValue>
|
||||
) : BaseItemViewModel(selectedItem)
|
||||
|
|
@ -2,18 +2,24 @@ package com.tangem.tangemtest._arch.structure.impl
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItemViewModel
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.KeyValue
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ListViewModel
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class AnyItem(override val id: Id, value: Any? = null) : BaseItem<Any>(AnyViewModel(value))
|
||||
class TextItem(override val id: Id, value: String? = null) : BaseItem<String>(StringViewModel(value))
|
||||
class EditTextItem(override val id: Id, value: String? = null) : BaseItem<String>(StringViewModel(value))
|
||||
class NumberItem(override val id: Id, value: Number? = null) : BaseItem<Number>(NumberViewModel(value))
|
||||
class BoolItem(override val id: Id, value: Boolean? = null) : BaseItem<Boolean>(BoolViewModel(value))
|
||||
|
||||
class ListItem(override val id: Id, value: List<KeyValue>, selectedValue: Any?)
|
||||
: BaseItem<ListValueWrapper>(ListViewModel(ListValueWrapper(selectedValue, value))
|
||||
)
|
||||
open class TypedItem<D>(id: Id, value: D? = null) : BaseItem(id, BaseItemViewModel(value)) {
|
||||
open fun getTypedData(): D? = viewModel.data as? D
|
||||
}
|
||||
|
||||
inline fun <reified T> BaseItem<T>.getData(): T? = viewModel.data
|
||||
class TextItem(id: Id, value: String? = null) : TypedItem<String>(id, value)
|
||||
class NumberItem(id: Id, value: Number? = null) : TypedItem<Number>(id, value)
|
||||
class BoolItem(id: Id, value: Boolean? = null) : TypedItem<Boolean>(id, value)
|
||||
|
||||
class EditTextItem(id: Id, value: String? = null) : TypedItem<String>(id, value)
|
||||
|
||||
class SpinnerItem(id: Id, value: List<KeyValue>, selectedValue: Any?)
|
||||
: TypedItem<ListViewModel>(id, ListViewModel(selectedValue, value)
|
||||
)
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
package com.tangem.tangemtest._arch.structure.impl
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItemViewModel
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
open class TransitiveViewModel<D>(value: D?) : BaseItemViewModel<D>() {
|
||||
init {
|
||||
defaultData = value
|
||||
}
|
||||
}
|
||||
|
||||
class AnyViewModel(value: Any? = null) : TransitiveViewModel<Any>(value)
|
||||
class StringViewModel(value: String? = null) : TransitiveViewModel<String>(value)
|
||||
class NumberViewModel(value: Number? = null) : TransitiveViewModel<Number>(value)
|
||||
class BoolViewModel(value: Boolean? = null) : TransitiveViewModel<Boolean>(value)
|
||||
class ListViewModel(value: ListValueWrapper? = null) : TransitiveViewModel<ListValueWrapper>(value) {
|
||||
|
||||
override fun handleDataUpdates(value: ListValueWrapper?): Boolean {
|
||||
val newValue = value ?: return false
|
||||
if (newValue.selectedItem == data?.selectedItem) return false
|
||||
|
||||
return super.handleDataUpdates(value)
|
||||
}
|
||||
}
|
||||
|
||||
class KeyValue(val key: String, val value: Any)
|
||||
class ListValueWrapper(var selectedItem: Any?, val itemList: List<KeyValue>)
|
||||
|
|
@ -8,5 +8,5 @@ import com.tangem.tangemtest._arch.widget.abstraction.ViewWidget
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface ItemWidgetBuilder {
|
||||
fun build(item: BaseItem<*>, parent: ViewGroup): ViewWidget?
|
||||
fun build(item: BaseItem, parent: ViewGroup): ViewWidget?
|
||||
}
|
||||
|
|
@ -2,11 +2,10 @@ package com.tangem.tangemtest._arch.widget
|
|||
|
||||
import android.view.ViewGroup
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Block
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemGroup
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.ViewWidget
|
||||
import com.tangem.tangemtest._arch.widget.impl.LinearBlockWidget
|
||||
import com.tangem.tangemtest._arch.widget.impl.LinearGroupWidget
|
||||
import com.tangem.tangemtest._arch.widget.impl.StubWidget
|
||||
|
||||
/**
|
||||
|
|
@ -18,20 +17,20 @@ class WidgetBuilder(
|
|||
|
||||
fun build(item: Item, parent: ViewGroup): ViewWidget? {
|
||||
return when (item) {
|
||||
is Block -> buildBlock(item, parent)
|
||||
is BaseItem<*> -> itemBuilder.build(item, parent)
|
||||
else -> StubWidget(parent)
|
||||
is ItemGroup -> buildBlock(item, parent)
|
||||
is BaseItem -> itemBuilder.build(item, parent)
|
||||
else -> StubWidget(item.id, parent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildBlock(block: Block, parent: ViewGroup): ViewWidget {
|
||||
return when (block) {
|
||||
is ListItemBlock -> {
|
||||
val linearBlock = LinearBlockWidget(parent, block)
|
||||
block.getItems().forEach { build(it, linearBlock.view as ViewGroup) }
|
||||
private fun buildBlock(itemGroup: ItemGroup, parent: ViewGroup): ViewWidget {
|
||||
return when (itemGroup) {
|
||||
is ItemGroup -> {
|
||||
val linearBlock = LinearGroupWidget(parent, itemGroup)
|
||||
itemGroup.getItems().forEach { build(it, linearBlock.view as ViewGroup) }
|
||||
linearBlock
|
||||
}
|
||||
else -> StubWidget(parent)
|
||||
else -> StubWidget(itemGroup.id, parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,9 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.DataHolder
|
||||
import com.tangem.tangemtest._arch.structure.StringId
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
|
||||
import com.tangem.tangemtest.ucase.resources.MainResourceHolder
|
||||
import com.tangem.tangemtest.ucase.resources.Resources
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.stringFrom
|
||||
import com.tangem.tangemtest._arch.structure.StringResId
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder
|
||||
|
||||
/**
|
||||
|
|
@ -18,39 +14,31 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder
|
|||
*/
|
||||
interface ViewWidget : LayoutHolder {
|
||||
val view: View
|
||||
var item: Item
|
||||
|
||||
fun getName(): String
|
||||
}
|
||||
|
||||
interface DataWidget<D> : ViewWidget {
|
||||
var dataItem: BaseItem<D>
|
||||
}
|
||||
|
||||
interface BlockViewWidget : ViewWidget, DataHolder<List<ItemViewModel<*>>>
|
||||
|
||||
abstract class BaseWidget<D>(
|
||||
abstract class BaseViewWidget(
|
||||
parent: ViewGroup,
|
||||
override var dataItem: BaseItem<D>
|
||||
) : ViewWidget, DataWidget<D> {
|
||||
override var item: Item
|
||||
) : ViewWidget {
|
||||
|
||||
override val view: View = inflate(getLayoutId(), parent)
|
||||
|
||||
init {
|
||||
if (dataItem.viewModel.viewState.isHiddenField) {
|
||||
if (item.viewModel.viewState.isHiddenField) {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class BaseBlockWidget(parent: ViewGroup) : BlockViewWidget {
|
||||
override val view: View = inflate(getLayoutId(), parent)
|
||||
}
|
||||
|
||||
fun DataWidget<*>.getResNameId(): Int = MainResourceHolder.safeGet<Resources>(dataItem.id).resName
|
||||
|
||||
fun DataWidget<*>.getResDescription(): Int? = MainResourceHolder.safeGet<Resources>(dataItem.id).resDescription
|
||||
|
||||
fun DataWidget<*>.getName(): String {
|
||||
val id = dataItem.id
|
||||
return if (id is StringId) id.name else view.stringFrom(getResNameId())
|
||||
override fun getName(): String {
|
||||
return when (val id = item.id) {
|
||||
is StringId -> id.value
|
||||
is StringResId -> view.resources.getString(id.value)
|
||||
else -> view.resources.getString(R.string.unknown)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun inflate(id: Int, parent: ViewGroup): View {
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
package com.tangem.tangemtest._arch.widget.impl
|
||||
|
||||
import android.view.ViewGroup
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.iterate
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.BaseBlockWidget
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class LinearBlockWidget(
|
||||
parent: ViewGroup,
|
||||
private val children: ListItemBlock
|
||||
) : BaseBlockWidget(parent) {
|
||||
override fun getLayoutId(): Int = R.layout.w_personilize_block
|
||||
|
||||
override var viewModel: List<ItemViewModel<*>> = listOf()
|
||||
get() {
|
||||
val vmList = mutableListOf<ItemViewModel<*>>()
|
||||
children.itemList.iterate { item ->
|
||||
(item as? ItemViewModel<*>)?.let { vmList.add(it) }
|
||||
}
|
||||
return vmList.toList()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tangemtest._arch.widget.impl
|
||||
|
||||
import android.view.ViewGroup
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemGroup
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.BaseViewWidget
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class LinearGroupWidget(
|
||||
parent: ViewGroup,
|
||||
itemGroup: ItemGroup
|
||||
) : BaseViewWidget(parent, itemGroup) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_personilize_block
|
||||
|
||||
}
|
||||
|
|
@ -2,13 +2,14 @@ package com.tangem.tangemtest._arch.widget.impl
|
|||
|
||||
import android.view.ViewGroup
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.BaseBlockWidget
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItemViewModel
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.BaseViewWidget
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class StubWidget(parent: ViewGroup) : BaseBlockWidget(parent) {
|
||||
class StubWidget(id: Id, parent: ViewGroup) : BaseViewWidget(parent, BaseItem(id, BaseItemViewModel())) {
|
||||
override fun getLayoutId(): Int = R.layout.w_empty
|
||||
override var viewModel: List<ItemViewModel<*>> = listOf()
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.tangemtest.commons
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
fun <A, B> performAction(a: A?, b: B?, action: (A, B) -> Unit) {
|
||||
fun <A, B> performAction(a: A?, b: B?, action: (A, B) -> Unit, onFail: (() -> Unit)? = null) {
|
||||
if (a != null && b != null) action(a, b)
|
||||
else onFail?.invoke()
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.tangem.tangemtest.ucase.domain.actions
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import com.tangem.tangemtest.ucase.variants.TlvId
|
|||
*/
|
||||
class DepersonalizeAction : BaseAction() {
|
||||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val item = attrs.itemList.findDataItem(TlvId.CardId) ?: return
|
||||
val item = attrs.itemList.findItem(TlvId.CardId) ?: return
|
||||
val cardId = item.viewModel.data as? String ?: return
|
||||
|
||||
attrs.cardManager.depersonalize(cardId) { handleResult(payload, it, null, attrs, callback) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tangemtest.ucase.domain.actions
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.NumberItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
|
|
@ -11,7 +11,7 @@ import com.tangem.tangemtest.ucase.tunnel.ActionView
|
|||
import com.tangem.tangemtest.ucase.tunnel.ItemError
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.CardNumber
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizationConfigConverter
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizeConfigToCardConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.PersonalizationConfigToCardConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.DefaultPersonalizationParams
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
|
@ -38,7 +38,7 @@ class PersonalizeAction : BaseAction() {
|
|||
val manufacturer = DefaultPersonalizationParams.manufacturer()
|
||||
|
||||
val personalizeConfig = PersonalizationConfigConverter().convert(itemList, PersonalizationConfig())
|
||||
val cardConfig = PersonalizeConfigToCardConfig().convert(personalizeConfig)
|
||||
val cardConfig = PersonalizationConfigToCardConfig().convert(personalizeConfig)
|
||||
|
||||
attrs.cardManager.personalize(cardConfig, issuer, manufacturer, acquirer) {
|
||||
handleResult(payload, it, null, attrs, callback)
|
||||
|
|
@ -46,18 +46,18 @@ class PersonalizeAction : BaseAction() {
|
|||
}
|
||||
|
||||
private fun checkSeries(itemList: List<Item>): Boolean {
|
||||
val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val data = seriesItem.getData() ?: return false
|
||||
val seriesItem = itemList.findItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val data = seriesItem.getData() as? String ?: return false
|
||||
|
||||
seriesItem.setData(data.toUpperCase())
|
||||
return data.length == 2 || data.length == 4
|
||||
}
|
||||
|
||||
private fun checkNumber(itemList: List<Item>): Boolean {
|
||||
val seriesItem = itemList.findDataItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val numberItem = itemList.findDataItem(CardNumber.Number) as? NumberItem ?: return false
|
||||
val seriesData = seriesItem.getData() ?: return false
|
||||
val numberData = stringOf(numberItem.getData())
|
||||
val seriesItem = itemList.findItem(CardNumber.Series) as? EditTextItem ?: return false
|
||||
val numberItem = itemList.findItem(CardNumber.Number) as? NumberItem ?: return false
|
||||
val seriesData = seriesItem.getData() as? String ?: return false
|
||||
val numberData = stringOf(numberItem.getData() as? Number)
|
||||
|
||||
return if (seriesData.length == 2 && numberData.length > 13) false
|
||||
else !(seriesData.length == 4 && numberData.length > 11)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tangemtest.ucase.domain.actions
|
|||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
|
@ -12,9 +12,9 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
|||
*/
|
||||
class SignAction : BaseAction() {
|
||||
override fun executeMainAction(payload: PayloadHolder, attrs: AttrForAction, callback: ActionCallback) {
|
||||
val dataForHashing = attrs.itemList.findDataItem(TlvId.TransactionOutHash) ?: return
|
||||
val dataForHashing = attrs.itemList.findItem(TlvId.TransactionOutHash) ?: return
|
||||
val hash = dataForHashing.getData() as? ByteArray ?: return
|
||||
val cardId = attrs.itemList.findDataItem(TlvId.CardId)?.viewModel?.data ?: return
|
||||
val cardId = attrs.itemList.findItem(TlvId.CardId)?.viewModel?.data ?: return
|
||||
|
||||
attrs.cardManager.sign(arrayOf(hash), stringOf(cardId)) { handleResult(payload, it, null, attrs, callback) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.tangem.CardManager
|
|||
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.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest.ucase.domain.actions.Action
|
||||
import com.tangem.tangemtest.ucase.domain.actions.AttrForAction
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ActionCallback
|
||||
|
|
@ -30,7 +30,7 @@ open class BaseItemsManager(protected val action: Action) : ItemsManager, Lifecy
|
|||
|
||||
override fun itemChanged(id: Id, value: Any?, callback: AffectedItemsCallback?) {
|
||||
if (itemList.isEmpty()) return
|
||||
val foundItem = itemList.findDataItem(id) ?: return
|
||||
val foundItem = itemList.findItem(id) ?: return
|
||||
|
||||
foundItem.setData(value)
|
||||
applyChangesByAffectedItems(foundItem, callback)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.commands.Card
|
|||
import com.tangem.commands.CardStatus
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.tunnel.CardError
|
||||
|
|
@ -18,7 +18,7 @@ import ru.dev.gbixahue.eu4d.lib.android.global.threading.postUI
|
|||
*/
|
||||
class AfterScanModifier : AfterActionModification {
|
||||
override fun modify(payload: PayloadHolder, taskEvent: TaskEvent<*>, itemList: List<Item>): List<Item> {
|
||||
val foundItem = itemList.findDataItem(TlvId.CardId) ?: return listOf()
|
||||
val foundItem = itemList.findItem(TlvId.CardId) ?: return listOf()
|
||||
val card = smartCast(taskEvent)?.card ?: return listOf()
|
||||
val actionView = payload.get(PayloadKey.actionView) as? ActionView ?: return listOf()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.common.extensions.calculateSha256
|
|||
import com.tangem.common.extensions.calculateSha512
|
||||
import com.tangem.tangemtest._arch.structure.PayloadHolder
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findDataItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.findItem
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.tunnel.ActionView
|
||||
import com.tangem.tangemtest.ucase.variants.TlvId
|
||||
|
|
@ -27,7 +27,7 @@ class SignScanConsequence : ItemsChangeConsequence {
|
|||
override fun affectChanges(payload: PayloadHolder, changedItem: Item, itemList: List<Item>): List<Item>? {
|
||||
if (changedItem.id != TlvId.CardId) return null
|
||||
|
||||
val hashItem = itemList.findDataItem(TlvId.TransactionOutHash) ?: return null
|
||||
val hashItem = itemList.findItem(TlvId.TransactionOutHash) ?: return null
|
||||
val affectedItems = mutableListOf(hashItem)
|
||||
val card = payload.remove(PayloadKey.card) as Card?
|
||||
if (card == null) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.tangem.CardManager
|
|||
import com.tangem.tangemtest._arch.SingleLiveEvent
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.Payload
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.iterate
|
||||
import com.tangem.tangemtest.commons.performAction
|
||||
|
|
@ -55,11 +54,11 @@ class ActionViewModel(private val itemsManager: ItemsManager) : ViewModel(), Lif
|
|||
|
||||
//invokes Scan, Sign etc...
|
||||
fun invokeMainAction() {
|
||||
performAction(itemsManager, cardManager) { paramsManager, cardManager ->
|
||||
performAction(itemsManager, cardManager, { paramsManager, cardManager ->
|
||||
paramsManager.invokeMainAction(cardManager) { response, listOfChangedParams ->
|
||||
notifier.handleActionResult(response, listOfChangedParams)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getItemAction(id: Id): (() -> Unit)? {
|
||||
|
|
@ -74,8 +73,7 @@ class ActionViewModel(private val itemsManager: ItemsManager) : ViewModel(), Lif
|
|||
|
||||
fun toggleDescriptionVisibility(state: Boolean) {
|
||||
ldItemList.value?.iterate {
|
||||
val baseItem = it as? BaseItem<*> ?: return@iterate
|
||||
baseItem.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
it.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.CardManager
|
|||
import com.tangem.tangem_sdk_new.extensions.init
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._main.MainViewModel
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.ItemsManager
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
|
|
@ -106,9 +105,7 @@ abstract class BaseCardActionFragment : BaseFragment(), ActionView {
|
|||
protected open fun listenChangedItems() {
|
||||
actionVM.seChangedItems.observe(viewLifecycleOwner, Observer { itemList ->
|
||||
itemList.forEach { item ->
|
||||
Log.d(this, "item changed from VM - name: ${item.id}")
|
||||
val dataItem = item as? BaseItem<Any?> ?: return@Observer
|
||||
Log.d(this, "item changed from VM - name: ${dataItem.id}, value:${dataItem.viewModel.data}")
|
||||
Log.d(this, "item changed from VM - name: ${item.id}, value:${item.viewModel.data}")
|
||||
paramsWidgetList.firstOrNull { it.id == item.id }?.changeParamValue(item.viewModel.data)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ 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.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.impl.EditTextItem
|
||||
import com.tangem.tangemtest.ucase.resources.ActionType
|
||||
import com.tangem.tangemtest.ucase.resources.MainResourceHolder
|
||||
import com.tangem.tangemtest.ucase.resources.Resources
|
||||
|
|
@ -29,7 +29,7 @@ class ParameterWidget(
|
|||
) {
|
||||
|
||||
val id: Id = item.id
|
||||
val dataItem: BaseItem<Any> = item as BaseItem<Any>
|
||||
val typedItem = item as EditTextItem
|
||||
|
||||
var onValueChanged: ((Id, Any?) -> Unit)? = null
|
||||
var onActionBtnClickListener: (() -> Unit)? = null
|
||||
|
|
@ -47,11 +47,11 @@ class ParameterWidget(
|
|||
private val tvDescription: TextView? by lazy { descriptionContainer.findViewById<TextView>(R.id.tv_description) }
|
||||
|
||||
private var actionBtnVisibilityState: Int = btnAction.visibility
|
||||
private var value: Any? = dataItem.viewModel.data
|
||||
private var value: Any? = typedItem.viewModel.data
|
||||
|
||||
init {
|
||||
tilValue.hint = tilValue.context.getString(getResNameId())
|
||||
etValue.setText(stringOf(dataItem.viewModel.data))
|
||||
etValue.setText(stringOf(typedItem.viewModel.data))
|
||||
etValue.addTextChangedListener(valueWatcher)
|
||||
btnAction.setOnClickListener { onActionBtnClickListener?.invoke() }
|
||||
btnAction.setText(getResNameId(ActionType.Scan))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tangemtest.ucase.variants.personalize.converter
|
|||
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.impl.KeyValue
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.KeyValue
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemsToModel
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelConverter
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelToItems
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.ItemsToPersonalizationConfig
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo.PersonalizationConfigToItems
|
||||
import com.tangem.tangemtest._arch.structure.Additional
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.*
|
||||
import com.tangem.tangemtest._arch.structure.impl.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -23,4 +23,281 @@ class PersonalizationConfigConverter : ModelConverter<PersonalizationConfig> {
|
|||
override fun convert(from: PersonalizationConfig): List<Item> {
|
||||
return toItems.convert(from)
|
||||
}
|
||||
}
|
||||
|
||||
class ItemsToPersonalizationConfig : ItemsToModel<PersonalizationConfig> {
|
||||
protected val valuesHolder = ConfigValuesHolder()
|
||||
|
||||
override fun convert(from: List<Item>, default: PersonalizationConfig): PersonalizationConfig {
|
||||
valuesHolder.init(default)
|
||||
mapListItems(from)
|
||||
return createModel()
|
||||
}
|
||||
|
||||
private fun mapListItems(itemList: List<Item>) {
|
||||
itemList.iterate { item -> mapItemToHolder(item) }
|
||||
}
|
||||
|
||||
private fun mapItemToHolder(item: Item) {
|
||||
when (item) {
|
||||
is ItemGroup -> mapListItems(item.itemList)
|
||||
is BaseItem -> {
|
||||
val defValue = valuesHolder.get(item.id) ?: return
|
||||
defValue.set(item.viewModel.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createModel(): PersonalizationConfig {
|
||||
val export = PersonalizationConfig()
|
||||
export.series = getTyped(CardNumber.Series)
|
||||
export.startNumber = getTyped(CardNumber.Number)
|
||||
export.curveID = getTyped(Common.Curve)
|
||||
export.blockchain = getTyped(Common.Blockchain)
|
||||
export.blockchainCustom = getTyped(Common.BlockchainCustom)
|
||||
export.MaxSignatures = getTyped(Common.MaxSignatures)
|
||||
export.createWallet = getTyped(Common.CreateWallet)
|
||||
export.SigningMethod0 = getTyped(SigningMethod.SignTx)
|
||||
export.SigningMethod1 = getTyped(SigningMethod.SignTxRaw)
|
||||
export.SigningMethod2 = getTyped(SigningMethod.SignValidatedTx)
|
||||
export.SigningMethod3 = getTyped(SigningMethod.SignValidatedTxRaw)
|
||||
export.SigningMethod4 = getTyped(SigningMethod.SignValidatedTxIssuer)
|
||||
export.SigningMethod5 = getTyped(SigningMethod.SignValidatedTxRawIssuer)
|
||||
export.SigningMethod6 = getTyped(SigningMethod.SignExternal)
|
||||
export.pinLessFloorLimit = getTyped(SignHashExProp.PinLessFloorLimit)
|
||||
export.hexCrExKey = getTyped(SignHashExProp.CryptoExKey)
|
||||
export.requireTerminalCertSignature = getTyped(SignHashExProp.RequireTerminalCertSig)
|
||||
export.requireTerminalTxSignature = getTyped(SignHashExProp.RequireTerminalTxSig)
|
||||
export.checkPIN3onCard = getTyped(SignHashExProp.CheckPin3)
|
||||
export.writeOnPersonalization = getTyped(Denomination.WriteOnPersonalize)
|
||||
export.denomination = getTyped(Denomination.Denomination)
|
||||
export.itsToken = getTyped(Token.ItsToken)
|
||||
export.symbol = getTyped(Token.Symbol)
|
||||
export.contractAddress = getTyped(Token.ContractAddress)
|
||||
export.decimal = getTyped(Token.Decimal)
|
||||
export.cardData = export.cardData.apply { this.product_note = getTyped(ProductMask.Note) }
|
||||
export.cardData = export.cardData.apply { this.product_tag = getTyped(ProductMask.Tag) }
|
||||
export.cardData = export.cardData.apply { this.product_id_card = getTyped(ProductMask.IdCard) }
|
||||
export.cardData = export.cardData.apply { this.product_id_issuer = getTyped(ProductMask.IdIssuerCard) }
|
||||
export.isReusable = getTyped(SettingsMask.IsReusable)
|
||||
export.useActivation = getTyped(SettingsMask.NeedActivation)
|
||||
export.forbidPurgeWallet = getTyped(SettingsMask.ForbidPurge)
|
||||
export.allowSelectBlockchain = getTyped(SettingsMask.AllowSelectBlockchain)
|
||||
export.useBlock = getTyped(SettingsMask.UseBlock)
|
||||
export.oneApdu = getTyped(SettingsMask.OneApdu)
|
||||
export.useCVC = getTyped(SettingsMask.UseCvc)
|
||||
export.allowSwapPIN = getTyped(SettingsMask.AllowSwapPin)
|
||||
export.allowSwapPIN2 = getTyped(SettingsMask.AllowSwapPin2)
|
||||
export.forbidDefaultPIN = getTyped(SettingsMask.ForbidDefaultPin)
|
||||
export.smartSecurityDelay = getTyped(SettingsMask.SmartSecurityDelay)
|
||||
export.protectIssuerDataAgainstReplay = getTyped(SettingsMask.ProtectIssuerDataAgainstReplay)
|
||||
export.skipSecurityDelayIfValidatedByIssuer = getTyped(SettingsMask.SkipSecurityDelayIfValidated)
|
||||
export.skipCheckPIN2andCVCIfValidatedByIssuer = getTyped(SettingsMask.SkipPin2CvcIfValidated)
|
||||
export.skipSecurityDelayIfValidatedByLinkedTerminal = getTyped(SettingsMask.SkipSecurityDelayOnLinkedTerminal)
|
||||
export.restrictOverwriteIssuerDataEx = getTyped(SettingsMask.RestrictOverwriteExtraIssuerData)
|
||||
export.protocolAllowUnencrypted = getTyped(SettingsMaskProtocolEnc.AllowUnencrypted)
|
||||
export.protocolAllowStaticEncryption = getTyped(SettingsMaskProtocolEnc.AllowStaticEncryption)
|
||||
export.useNDEF = getTyped(SettingsMaskNdef.UseNdef)
|
||||
export.useDynamicNDEF = getTyped(SettingsMaskNdef.DynamicNdef)
|
||||
export.disablePrecomputedNDEF = getTyped(SettingsMaskNdef.DisablePrecomputedNdef)
|
||||
export.aar = getTyped(SettingsMaskNdef.Aar)
|
||||
export.aarCustom = getTyped(SettingsMaskNdef.AarCustom)
|
||||
export.uri = getTyped(SettingsMaskNdef.Uri)
|
||||
export.PIN = getTyped(Pins.Pin)
|
||||
export.PIN2 = getTyped(Pins.Pin2)
|
||||
export.PIN3 = getTyped(Pins.Pin3)
|
||||
export.CVC = getTyped(Pins.Cvc)
|
||||
export.pauseBeforePIN2 = getTyped(Pins.PauseBeforePin2)
|
||||
return export
|
||||
}
|
||||
|
||||
private inline fun <reified Type> getTyped(id: Id): Type {
|
||||
return getTypedBy<Type>(valuesHolder, id)!!
|
||||
}
|
||||
|
||||
private inline fun <reified Type> getTypedBy(holder: ConfigValuesHolder, id: Id): Type? {
|
||||
Log.d(this, "getTyped for id: $id")
|
||||
var typedValue = holder.get(id)?.get()
|
||||
|
||||
typedValue = when (typedValue) {
|
||||
is ListViewModel -> typedValue.selectedItem as Type
|
||||
else -> typedValue as? Type ?: null
|
||||
}
|
||||
return typedValue
|
||||
}
|
||||
}
|
||||
|
||||
class PersonalizationConfigToItems : ModelToItems<PersonalizationConfig> {
|
||||
private val valuesHolder = ConfigValuesHolder()
|
||||
private val itemTypes = ItemTypes()
|
||||
|
||||
override fun convert(from: PersonalizationConfig): List<Item> {
|
||||
valuesHolder.init(from)
|
||||
val blocList = mutableListOf<Item>()
|
||||
blocList.add(cardNumber())
|
||||
blocList.add(common())
|
||||
blocList.add(signingMethod())
|
||||
blocList.add(signHashExProperties())
|
||||
blocList.add(denomination())
|
||||
blocList.add(token())
|
||||
blocList.add(productMask())
|
||||
blocList.add(settingsMask())
|
||||
blocList.add(settingsMaskProtocolEnc())
|
||||
blocList.add(settingsMaskNdef())
|
||||
blocList.add(pins())
|
||||
blocList.iterate {
|
||||
if (itemTypes.hiddenList.contains(it.id)) {
|
||||
it.viewModel.viewState.isHiddenField = true
|
||||
}
|
||||
}
|
||||
return blocList
|
||||
}
|
||||
|
||||
private fun cardNumber(): ItemGroup {
|
||||
val block = createGroup(BlockId.CardNumber)
|
||||
mutableListOf(
|
||||
CardNumber.Series,
|
||||
CardNumber.Number,
|
||||
CardNumber.BatchId
|
||||
).forEach { createItem(block, it as Id) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun common(): ItemGroup {
|
||||
val block = createGroup(BlockId.Common)
|
||||
mutableListOf(
|
||||
Common.Curve,
|
||||
Common.Blockchain,
|
||||
Common.BlockchainCustom,
|
||||
Common.MaxSignatures,
|
||||
Common.CreateWallet
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signingMethod(): ItemGroup {
|
||||
val block = createGroup(BlockId.SigningMethod)
|
||||
mutableListOf(
|
||||
SigningMethod.SignTx,
|
||||
SigningMethod.SignTxRaw,
|
||||
SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw,
|
||||
SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer,
|
||||
SigningMethod.SignExternal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signHashExProperties(): ItemGroup {
|
||||
val block = createGroup(BlockId.SignHashExProp)
|
||||
mutableListOf(
|
||||
SignHashExProp.PinLessFloorLimit,
|
||||
SignHashExProp.CryptoExKey,
|
||||
SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig,
|
||||
SignHashExProp.CheckPin3
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun denomination(): ItemGroup {
|
||||
val block = createGroup(BlockId.Denomination)
|
||||
mutableListOf(
|
||||
Denomination.WriteOnPersonalize,
|
||||
Denomination.Denomination
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun token(): ItemGroup {
|
||||
val block = createGroup(BlockId.Token)
|
||||
mutableListOf(
|
||||
Token.ItsToken,
|
||||
Token.Symbol,
|
||||
Token.ContractAddress,
|
||||
Token.Decimal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun productMask(): ItemGroup {
|
||||
val block = createGroup(BlockId.ProdMask)
|
||||
mutableListOf(
|
||||
ProductMask.Note,
|
||||
ProductMask.Tag,
|
||||
ProductMask.IdCard,
|
||||
ProductMask.IdIssuerCard
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMask(): ItemGroup {
|
||||
val block = createGroup(BlockId.SettingsMask)
|
||||
mutableListOf(
|
||||
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
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskProtocolEnc(): ItemGroup {
|
||||
val block = createGroup(BlockId.SettingsMaskProtocolEnc)
|
||||
mutableListOf(
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted,
|
||||
SettingsMaskProtocolEnc.AllowStaticEncryption
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskNdef(): ItemGroup {
|
||||
val block = createGroup(BlockId.SettingsMaskNdef)
|
||||
mutableListOf(
|
||||
SettingsMaskNdef.UseNdef,
|
||||
SettingsMaskNdef.DynamicNdef,
|
||||
SettingsMaskNdef.DisablePrecomputedNdef,
|
||||
SettingsMaskNdef.Aar,
|
||||
SettingsMaskNdef.AarCustom,
|
||||
SettingsMaskNdef.Uri
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun pins(): ItemGroup {
|
||||
val block = createGroup(BlockId.Pins)
|
||||
mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2)
|
||||
.forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun createGroup(id: Id): ItemGroup {
|
||||
return SimpleItemGroup(id).apply { addItem(TextItem(id)) }
|
||||
}
|
||||
|
||||
private fun createItem(itemGroup: ItemGroup, id: Id) {
|
||||
val holder = valuesHolder.get(id) ?: return
|
||||
val item = when {
|
||||
itemTypes.blockIdList.contains(id) -> TextItem(id, holder.get() as? String)
|
||||
itemTypes.listItemList.contains(id) -> SpinnerItem(id, holder.list as List<KeyValue>, holder.get())
|
||||
itemTypes.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean)
|
||||
itemTypes.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String)
|
||||
itemTypes.numberList.contains(id) -> NumberItem(id, holder.get() as? Number)
|
||||
else -> SimpleItemGroup(Additional.UNDEFINED)
|
||||
}
|
||||
itemGroup.addItem(item)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter
|
||||
|
||||
import com.tangem.commands.CardData
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.commands.ProductMaskBuilder
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.commands.personalization.entities.NdefRecord
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
|
||||
import java.util.*
|
||||
|
||||
class PersonalizationConfigToCardConfig : Converter<PersonalizationConfig, CardConfig> {
|
||||
|
||||
override fun convert(from: PersonalizationConfig): CardConfig {
|
||||
val signingMethod = com.tangem.commands.SigningMethod.build(
|
||||
signHash = from.SigningMethod0,
|
||||
signRaw = from.SigningMethod1,
|
||||
signHashValidatedByIssuer = from.SigningMethod2,
|
||||
signRawValidatedByIssuer = from.SigningMethod3,
|
||||
signHashValidatedByIssuerAndWriteIssuerData = from.SigningMethod4,
|
||||
signRawValidatedByIssuerAndWriteIssuerData = from.SigningMethod5,
|
||||
signPos = from.SigningMethod6
|
||||
)
|
||||
|
||||
val isNote = from.cardData.product_note
|
||||
val isTag = from.cardData.product_tag
|
||||
val isIdCard = from.cardData.product_id_card
|
||||
val isIdIssuer = from.cardData.product_id_issuer
|
||||
|
||||
val productMaskBuilder = ProductMaskBuilder()
|
||||
if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note)
|
||||
if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag)
|
||||
if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard)
|
||||
if (isIdIssuer) productMaskBuilder.add(com.tangem.commands.ProductMask.idIssuer)
|
||||
val productMask = productMaskBuilder.build()
|
||||
|
||||
var tokenSymbol: String? = null
|
||||
var tokenContractAddress: String? = null
|
||||
var tokenDecimal: Int? = null
|
||||
if (from.itsToken) {
|
||||
tokenSymbol = from.symbol
|
||||
tokenContractAddress = from.contractAddress
|
||||
tokenDecimal = from.decimal.toInt()
|
||||
}
|
||||
|
||||
val blockchain = if (from.blockchain.isNotEmpty()) from.blockchain else from.blockchainCustom
|
||||
val cardData = CardData(
|
||||
blockchainName = blockchain,
|
||||
batchId = from.batchId,
|
||||
productMask = productMask,
|
||||
tokenSymbol = tokenSymbol,
|
||||
tokenContractAddress = tokenContractAddress,
|
||||
tokenDecimal = tokenDecimal,
|
||||
issuerName = null,
|
||||
manufactureDateTime = Calendar.getInstance().time,
|
||||
manufacturerSignature = null)
|
||||
|
||||
|
||||
val ndefs = mutableListOf<NdefRecord>()
|
||||
if (from.uri.isNotEmpty()) {
|
||||
ndefs.add(NdefRecord(NdefRecord.Type.URI, from.uri))
|
||||
}
|
||||
when (from.aar) {
|
||||
"None" -> null
|
||||
"--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom)
|
||||
else -> NdefRecord(NdefRecord.Type.AAR, from.aar)
|
||||
}?.let { ndefs.add(it) }
|
||||
|
||||
return CardConfig(
|
||||
"Tangem",
|
||||
"Tangem Test",
|
||||
from.series,
|
||||
from.startNumber,
|
||||
1000,
|
||||
from.PIN,
|
||||
from.PIN2,
|
||||
from.PIN3,
|
||||
from.hexCrExKey,
|
||||
from.CVC,
|
||||
from.pauseBeforePIN2.toInt(),
|
||||
from.smartSecurityDelay,
|
||||
EllipticCurve.byName(from.curveID) ?: EllipticCurve.Secp256k1,
|
||||
signingMethod,
|
||||
from.MaxSignatures.toInt(),
|
||||
from.isReusable,
|
||||
from.allowSwapPIN,
|
||||
from.allowSwapPIN2,
|
||||
from.useActivation,
|
||||
from.useCVC,
|
||||
from.useNDEF,
|
||||
from.useDynamicNDEF,
|
||||
from.oneApdu,
|
||||
from.useBlock,
|
||||
from.allowSelectBlockchain,
|
||||
from.forbidPurgeWallet,
|
||||
from.protocolAllowUnencrypted,
|
||||
from.protocolAllowStaticEncryption,
|
||||
from.protectIssuerDataAgainstReplay,
|
||||
from.forbidDefaultPIN,
|
||||
from.disablePrecomputedNDEF,
|
||||
from.skipSecurityDelayIfValidatedByIssuer,
|
||||
from.skipCheckPIN2andCVCIfValidatedByIssuer,
|
||||
from.skipSecurityDelayIfValidatedByLinkedTerminal,
|
||||
from.restrictOverwriteIssuerDataEx,
|
||||
from.requireTerminalTxSignature,
|
||||
from.requireTerminalCertSignature,
|
||||
from.checkPIN3onCard,
|
||||
from.createWallet,
|
||||
cardData,
|
||||
ndefs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.*
|
||||
import com.tangem.tangemtest._arch.structure.impl.ListValueWrapper
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.ConfigValuesHolder
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ItemsToPersonalizationConfig : ItemsToModel<PersonalizationConfig> {
|
||||
protected val valuesHolder = ConfigValuesHolder()
|
||||
|
||||
override fun convert(from: List<Item>, default: PersonalizationConfig): PersonalizationConfig {
|
||||
valuesHolder.init(default)
|
||||
mapListItems(from)
|
||||
return createModel()
|
||||
}
|
||||
|
||||
private fun mapListItems(itemList: List<Item>) {
|
||||
itemList.iterate { item -> mapItemToHolder(item) }
|
||||
}
|
||||
|
||||
private fun mapItemToHolder(item: Item) {
|
||||
when (item) {
|
||||
is Block -> mapListItems(item.itemList)
|
||||
is BaseItem<*> -> {
|
||||
val defValue = valuesHolder.get(item.id) ?: return
|
||||
defValue.set(item.viewModel.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createModel(): PersonalizationConfig {
|
||||
val export = PersonalizationConfig()
|
||||
export.series = getTyped(CardNumber.Series)
|
||||
export.startNumber = getTyped(CardNumber.Number)
|
||||
export.curveID = getTyped(Common.Curve)
|
||||
export.blockchain = getTyped(Common.Blockchain)
|
||||
export.blockchainCustom = getTyped(Common.BlockchainCustom)
|
||||
export.MaxSignatures = getTyped(Common.MaxSignatures)
|
||||
export.createWallet = getTyped(Common.CreateWallet)
|
||||
export.SigningMethod0 = getTyped(SigningMethod.SignTx)
|
||||
export.SigningMethod1 = getTyped(SigningMethod.SignTxRaw)
|
||||
export.SigningMethod2 = getTyped(SigningMethod.SignValidatedTx)
|
||||
export.SigningMethod3 = getTyped(SigningMethod.SignValidatedTxRaw)
|
||||
export.SigningMethod4 = getTyped(SigningMethod.SignValidatedTxIssuer)
|
||||
export.SigningMethod5 = getTyped(SigningMethod.SignValidatedTxRawIssuer)
|
||||
export.SigningMethod6 = getTyped(SigningMethod.SignExternal)
|
||||
export.pinLessFloorLimit = getTyped(SignHashExProp.PinLessFloorLimit)
|
||||
export.hexCrExKey = getTyped(SignHashExProp.CryptoExKey)
|
||||
export.requireTerminalCertSignature = getTyped(SignHashExProp.RequireTerminalCertSig)
|
||||
export.requireTerminalTxSignature = getTyped(SignHashExProp.RequireTerminalTxSig)
|
||||
export.checkPIN3onCard = getTyped(SignHashExProp.CheckPin3)
|
||||
export.writeOnPersonalization = getTyped(Denomination.WriteOnPersonalize)
|
||||
export.denomination = getTyped(Denomination.Denomination)
|
||||
export.itsToken = getTyped(Token.ItsToken)
|
||||
export.symbol = getTyped(Token.Symbol)
|
||||
export.contractAddress = getTyped(Token.ContractAddress)
|
||||
export.decimal = getTyped(Token.Decimal)
|
||||
export.cardData = export.cardData.apply { this.product_note = getTyped(ProductMask.Note) }
|
||||
export.cardData = export.cardData.apply { this.product_tag = getTyped(ProductMask.Tag) }
|
||||
export.cardData = export.cardData.apply { this.product_id_card = getTyped(ProductMask.IdCard) }
|
||||
export.cardData = export.cardData.apply { this.product_id_issuer = getTyped(ProductMask.IdIssuerCard) }
|
||||
export.isReusable = getTyped(SettingsMask.IsReusable)
|
||||
export.useActivation = getTyped(SettingsMask.NeedActivation)
|
||||
export.forbidPurgeWallet = getTyped(SettingsMask.ForbidPurge)
|
||||
export.allowSelectBlockchain = getTyped(SettingsMask.AllowSelectBlockchain)
|
||||
export.useBlock = getTyped(SettingsMask.UseBlock)
|
||||
export.oneApdu = getTyped(SettingsMask.OneApdu)
|
||||
export.useCVC = getTyped(SettingsMask.UseCvc)
|
||||
export.allowSwapPIN = getTyped(SettingsMask.AllowSwapPin)
|
||||
export.allowSwapPIN2 = getTyped(SettingsMask.AllowSwapPin2)
|
||||
export.forbidDefaultPIN = getTyped(SettingsMask.ForbidDefaultPin)
|
||||
export.smartSecurityDelay = getTyped(SettingsMask.SmartSecurityDelay)
|
||||
export.protectIssuerDataAgainstReplay = getTyped(SettingsMask.ProtectIssuerDataAgainstReplay)
|
||||
export.skipSecurityDelayIfValidatedByIssuer = getTyped(SettingsMask.SkipSecurityDelayIfValidated)
|
||||
export.skipCheckPIN2andCVCIfValidatedByIssuer = getTyped(SettingsMask.SkipPin2CvcIfValidated)
|
||||
export.skipSecurityDelayIfValidatedByLinkedTerminal = getTyped(SettingsMask.SkipSecurityDelayOnLinkedTerminal)
|
||||
export.restrictOverwriteIssuerDataEx = getTyped(SettingsMask.RestrictOverwriteExtraIssuerData)
|
||||
export.protocolAllowUnencrypted = getTyped(SettingsMaskProtocolEnc.AllowUnencrypted)
|
||||
export.protocolAllowStaticEncryption = getTyped(SettingsMaskProtocolEnc.AllowStaticEncryption)
|
||||
export.useNDEF = getTyped(SettingsMaskNdef.UseNdef)
|
||||
export.useDynamicNDEF = getTyped(SettingsMaskNdef.DynamicNdef)
|
||||
export.disablePrecomputedNDEF = getTyped(SettingsMaskNdef.DisablePrecomputedNdef)
|
||||
export.aar = getTyped(SettingsMaskNdef.Aar)
|
||||
export.aarCustom = getTyped(SettingsMaskNdef.AarCustom)
|
||||
export.uri = getTyped(SettingsMaskNdef.Uri)
|
||||
export.PIN = getTyped(Pins.Pin)
|
||||
export.PIN2 = getTyped(Pins.Pin2)
|
||||
export.PIN3 = getTyped(Pins.Pin3)
|
||||
export.CVC = getTyped(Pins.Cvc)
|
||||
export.pauseBeforePIN2 = getTyped(Pins.PauseBeforePin2)
|
||||
return export
|
||||
}
|
||||
|
||||
private inline fun <reified Type> getTyped(id: Id): Type {
|
||||
return getTypedBy<Type>(valuesHolder, id)!!
|
||||
}
|
||||
|
||||
private inline fun <reified Type> getTypedBy(holder: ConfigValuesHolder, id: Id): Type? {
|
||||
Log.d(this, "getTyped for id: $id")
|
||||
var typedValue = holder.get(id)?.get()
|
||||
|
||||
typedValue = when (typedValue) {
|
||||
is ListValueWrapper -> typedValue.selectedItem as Type
|
||||
else -> typedValue as? Type ?: null
|
||||
}
|
||||
return typedValue
|
||||
}
|
||||
}
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.converter.fromTo
|
||||
|
||||
import com.tangem.commands.CardData
|
||||
import com.tangem.commands.EllipticCurve
|
||||
import com.tangem.commands.ProductMaskBuilder
|
||||
import com.tangem.commands.personalization.entities.CardConfig
|
||||
import com.tangem.commands.personalization.entities.NdefRecord
|
||||
import com.tangem.tangemtest._arch.structure.Additional
|
||||
import com.tangem.tangemtest._arch.structure.Id
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.*
|
||||
import com.tangem.tangemtest._arch.structure.impl.*
|
||||
import com.tangem.tangemtest.ucase.domain.paramsManager.PayloadKey
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.*
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.converter.ConfigValuesHolder
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.dto.PersonalizationConfig
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizationConfigToItems : ModelToItems<PersonalizationConfig> {
|
||||
private val valuesHolder = ConfigValuesHolder()
|
||||
private val itemTypes = ItemTypes()
|
||||
|
||||
override fun convert(from: PersonalizationConfig): List<Item> {
|
||||
valuesHolder.init(from)
|
||||
val blocList = mutableListOf<Item>()
|
||||
blocList.add(cardNumber())
|
||||
blocList.add(common())
|
||||
blocList.add(signingMethod())
|
||||
blocList.add(signHashExProperties())
|
||||
blocList.add(denomination())
|
||||
blocList.add(token())
|
||||
blocList.add(productMask())
|
||||
blocList.add(settingsMask())
|
||||
blocList.add(settingsMaskProtocolEnc())
|
||||
blocList.add(settingsMaskNdef())
|
||||
blocList.add(pins())
|
||||
val payloadBlock = ListItemBlock(Additional.JSON_TAILS)
|
||||
addPayload(payloadBlock, from)
|
||||
blocList.add(payloadBlock)
|
||||
blocList.iterate {
|
||||
if (itemTypes.hiddenList.contains(it.id)) {
|
||||
(it as BaseItem<*>)?.viewModel.viewState.isHiddenField = true
|
||||
}
|
||||
}
|
||||
return blocList
|
||||
}
|
||||
|
||||
private fun cardNumber(): Block {
|
||||
val block = createBlock(BlockId.CardNumber)
|
||||
mutableListOf(
|
||||
CardNumber.Series,
|
||||
CardNumber.Number,
|
||||
CardNumber.BatchId
|
||||
).forEach { createItem(block, it as Id) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun common(): Block {
|
||||
val block = createBlock(BlockId.Common)
|
||||
mutableListOf(
|
||||
Common.Curve,
|
||||
Common.Blockchain,
|
||||
Common.BlockchainCustom,
|
||||
Common.MaxSignatures,
|
||||
Common.CreateWallet
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signingMethod(): Block {
|
||||
val block = createBlock(BlockId.SigningMethod)
|
||||
mutableListOf(
|
||||
SigningMethod.SignTx,
|
||||
SigningMethod.SignTxRaw,
|
||||
SigningMethod.SignValidatedTx,
|
||||
SigningMethod.SignValidatedTxRaw,
|
||||
SigningMethod.SignValidatedTxIssuer,
|
||||
SigningMethod.SignValidatedTxRawIssuer,
|
||||
SigningMethod.SignExternal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun signHashExProperties(): Block {
|
||||
val block = createBlock(BlockId.SignHashExProp)
|
||||
mutableListOf(
|
||||
SignHashExProp.PinLessFloorLimit,
|
||||
SignHashExProp.CryptoExKey,
|
||||
SignHashExProp.RequireTerminalCertSig,
|
||||
SignHashExProp.RequireTerminalTxSig,
|
||||
SignHashExProp.CheckPin3
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun denomination(): Block {
|
||||
val block = createBlock(BlockId.Denomination)
|
||||
mutableListOf(
|
||||
Denomination.WriteOnPersonalize,
|
||||
Denomination.Denomination
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun token(): Block {
|
||||
val block = createBlock(BlockId.Token)
|
||||
mutableListOf(
|
||||
Token.ItsToken,
|
||||
Token.Symbol,
|
||||
Token.ContractAddress,
|
||||
Token.Decimal
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun productMask(): Block {
|
||||
val block = createBlock(BlockId.ProdMask)
|
||||
mutableListOf(
|
||||
ProductMask.Note,
|
||||
ProductMask.Tag,
|
||||
ProductMask.IdCard,
|
||||
ProductMask.IdIssuerCard
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMask(): Block {
|
||||
val block = createBlock(BlockId.SettingsMask)
|
||||
mutableListOf(
|
||||
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
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskProtocolEnc(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskProtocolEnc)
|
||||
mutableListOf(
|
||||
SettingsMaskProtocolEnc.AllowUnencrypted,
|
||||
SettingsMaskProtocolEnc.AllowStaticEncryption
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun settingsMaskNdef(): Block {
|
||||
val block = createBlock(BlockId.SettingsMaskNdef)
|
||||
mutableListOf(
|
||||
SettingsMaskNdef.UseNdef,
|
||||
SettingsMaskNdef.DynamicNdef,
|
||||
SettingsMaskNdef.DisablePrecomputedNdef,
|
||||
SettingsMaskNdef.Aar,
|
||||
SettingsMaskNdef.AarCustom,
|
||||
SettingsMaskNdef.Uri
|
||||
).forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun pins(): Block {
|
||||
val block = createBlock(BlockId.Pins)
|
||||
mutableListOf(Pins.Pin, Pins.Pin2, Pins.Pin3, Pins.Cvc, Pins.PauseBeforePin2)
|
||||
.forEach { createItem(block, it) }
|
||||
return block
|
||||
}
|
||||
|
||||
private fun createBlock(id: Id): ListItemBlock {
|
||||
return ListItemBlock(id).apply { addItem(TextItem(id)) }
|
||||
}
|
||||
|
||||
private fun addPayload(block: Block, from: PersonalizationConfig) {
|
||||
block.payload[PayloadKey.incomingJson] = from
|
||||
}
|
||||
|
||||
private fun createItem(block: ListItemBlock, id: Id) {
|
||||
val holder = valuesHolder.get(id) ?: return
|
||||
val item = when {
|
||||
itemTypes.blockIdList.contains(id) -> TextItem(id, holder.get() as? String)
|
||||
itemTypes.listItemList.contains(id) -> ListItem(id, holder.list as List<KeyValue>, holder.get())
|
||||
itemTypes.boolList.contains(id) -> BoolItem(id, holder.get() as? Boolean)
|
||||
itemTypes.editTextList.contains(id) -> EditTextItem(id, holder.get() as? String)
|
||||
itemTypes.numberList.contains(id) -> NumberItem(id, holder.get() as? Number)
|
||||
else -> ListItemBlock(Additional.UNDEFINED)
|
||||
}
|
||||
block.addItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
class PersonalizeConfigToCardConfig : Converter<PersonalizationConfig, CardConfig> {
|
||||
|
||||
override fun convert(from: PersonalizationConfig): CardConfig {
|
||||
val signingMethod = com.tangem.commands.SigningMethod.build(
|
||||
signHash = from.SigningMethod0,
|
||||
signRaw = from.SigningMethod1,
|
||||
signHashValidatedByIssuer = from.SigningMethod2,
|
||||
signRawValidatedByIssuer = from.SigningMethod3,
|
||||
signHashValidatedByIssuerAndWriteIssuerData = from.SigningMethod4,
|
||||
signRawValidatedByIssuerAndWriteIssuerData = from.SigningMethod5,
|
||||
signPos = from.SigningMethod6
|
||||
)
|
||||
|
||||
val isNote = from.cardData.product_note
|
||||
val isTag = from.cardData.product_tag
|
||||
val isIdCard = from.cardData.product_id_card
|
||||
val isIdIssuer = from.cardData.product_id_issuer
|
||||
|
||||
val productMaskBuilder = ProductMaskBuilder()
|
||||
if (isNote) productMaskBuilder.add(com.tangem.commands.ProductMask.note)
|
||||
if (isTag) productMaskBuilder.add(com.tangem.commands.ProductMask.tag)
|
||||
if (isIdCard) productMaskBuilder.add(com.tangem.commands.ProductMask.idCard)
|
||||
if (isIdIssuer) productMaskBuilder.add(com.tangem.commands.ProductMask.idIssuer)
|
||||
val productMask = productMaskBuilder.build()
|
||||
|
||||
var tokenSymbol: String? = null
|
||||
var tokenContractAddress: String? = null
|
||||
var tokenDecimal: Int? = null
|
||||
if (from.itsToken) {
|
||||
tokenSymbol = from.symbol
|
||||
tokenContractAddress = from.contractAddress
|
||||
tokenDecimal = from.decimal.toInt()
|
||||
}
|
||||
|
||||
val blockchain = if (from.blockchain.isNotEmpty()) from.blockchain else from.blockchainCustom
|
||||
val cardData = CardData(
|
||||
blockchainName = blockchain,
|
||||
batchId = from.batchId,
|
||||
productMask = productMask,
|
||||
tokenSymbol = tokenSymbol,
|
||||
tokenContractAddress = tokenContractAddress,
|
||||
tokenDecimal = tokenDecimal,
|
||||
issuerName = null,
|
||||
manufactureDateTime = Calendar.getInstance().time,
|
||||
manufacturerSignature = null)
|
||||
|
||||
|
||||
val ndefs = mutableListOf<NdefRecord>()
|
||||
if (from.uri.isNotEmpty()) {
|
||||
ndefs.add(NdefRecord(NdefRecord.Type.URI, from.uri))
|
||||
}
|
||||
when (from.aar) {
|
||||
"None" -> null
|
||||
"--- CUSTOM ---" -> NdefRecord(NdefRecord.Type.AAR, from.aarCustom)
|
||||
else -> NdefRecord(NdefRecord.Type.AAR, from.aar)
|
||||
}?.let { ndefs.add(it) }
|
||||
|
||||
return CardConfig(
|
||||
"Tangem",
|
||||
"Tangem Test",
|
||||
from.series,
|
||||
from.startNumber,
|
||||
1000,
|
||||
from.PIN,
|
||||
from.PIN2,
|
||||
from.PIN3,
|
||||
from.hexCrExKey,
|
||||
from.CVC,
|
||||
from.pauseBeforePIN2.toInt(),
|
||||
from.smartSecurityDelay,
|
||||
EllipticCurve.byName(from.curveID) ?: EllipticCurve.Secp256k1,
|
||||
signingMethod,
|
||||
from.MaxSignatures.toInt(),
|
||||
from.isReusable,
|
||||
from.allowSwapPIN,
|
||||
from.allowSwapPIN2,
|
||||
from.useActivation,
|
||||
from.useCVC,
|
||||
from.useNDEF,
|
||||
from.useDynamicNDEF,
|
||||
from.oneApdu,
|
||||
from.useBlock,
|
||||
from.allowSelectBlockchain,
|
||||
from.forbidPurgeWallet,
|
||||
from.protocolAllowUnencrypted,
|
||||
from.protocolAllowStaticEncryption,
|
||||
from.protectIssuerDataAgainstReplay,
|
||||
from.forbidDefaultPIN,
|
||||
from.disablePrecomputedNDEF,
|
||||
from.skipSecurityDelayIfValidatedByIssuer,
|
||||
from.skipCheckPIN2andCVCIfValidatedByIssuer,
|
||||
from.skipSecurityDelayIfValidatedByLinkedTerminal,
|
||||
from.restrictOverwriteIssuerDataEx,
|
||||
from.requireTerminalTxSignature,
|
||||
from.requireTerminalCertSignature,
|
||||
from.checkPIN3onCard,
|
||||
from.createWallet,
|
||||
cardData,
|
||||
ndefs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.tangemtest.ucase.variants.personalize.ui.widgets
|
||||
|
||||
import android.view.ViewGroup
|
||||
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.widget.abstraction.BaseViewWidget
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.ViewWidget
|
||||
import com.tangem.tangemtest.ucase.resources.MainResourceHolder
|
||||
import com.tangem.tangemtest.ucase.resources.Resources
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.stringFrom
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
abstract class BaseAppWidget(parent: ViewGroup, item: Item): BaseViewWidget(parent, item) {
|
||||
override fun getName(): String {
|
||||
return when (val id = item.id) {
|
||||
is StringId -> id.value
|
||||
is StringResId -> view.stringFrom(id.value)
|
||||
else -> view.stringFrom(getResNameId())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ViewWidget.getResNameId(): Int = MainResourceHolder.safeGet<Resources>(item.id).resName
|
||||
|
||||
fun ViewWidget.getResDescription(): Int? = MainResourceHolder.safeGet<Resources>(item.id).resDescription
|
||||
|
|
@ -5,29 +5,27 @@ import android.widget.TextView
|
|||
import androidx.transition.AutoTransition
|
||||
import androidx.transition.TransitionManager
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.BaseWidget
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getResDescription
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
abstract class DescriptionWidget<D>(
|
||||
abstract class DescriptionWidget(
|
||||
parent: ViewGroup,
|
||||
data: BaseItem<D>
|
||||
) : BaseWidget<D>(parent, data) {
|
||||
item: Item
|
||||
) : BaseAppWidget(parent, item) {
|
||||
|
||||
private val descriptionContainer: ViewGroup by lazy { view.findViewById<ViewGroup>(R.id.container_description) }
|
||||
private val tvDescription: TextView? by lazy { descriptionContainer.findViewById<TextView>(R.id.tv_description) }
|
||||
|
||||
init {
|
||||
Log.d(this, "init id: ${dataItem.id}")
|
||||
Log.d(this, "init id: ${item.id}")
|
||||
initDescriptionWidget()
|
||||
}
|
||||
|
||||
private fun initDescriptionWidget() {
|
||||
dataItem.viewModel.viewState.onDescriptionVisibilityChanged = { changeDescriptionVisibility(it) }
|
||||
item.viewModel.viewState.onDescriptionVisibilityChanged = { changeDescriptionVisibility(it) }
|
||||
}
|
||||
|
||||
protected open fun changeDescriptionVisibility(state: Int) {
|
||||
|
|
|
|||
|
|
@ -7,14 +7,17 @@ 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.impl.EditTextItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget<String>(parent, data) {
|
||||
class EditTextWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: EditTextItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_edit_text
|
||||
|
||||
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
|
||||
|
|
@ -22,7 +25,7 @@ class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget<
|
|||
|
||||
private val watcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
dataItem.viewModel.updateDataByView(stringOf(s))
|
||||
typedItem.viewModel.updateDataByView(stringOf(s))
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
|
@ -31,9 +34,9 @@ class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget<
|
|||
|
||||
init {
|
||||
tilItem.hint = getName()
|
||||
etItem.setText(dataItem.getData())
|
||||
etItem.setText(typedItem.getTypedData())
|
||||
etItem.addTextChangedListener(watcher)
|
||||
dataItem.viewModel.onDataUpdated = { silentUpdate(it) }
|
||||
item.viewModel.onDataUpdated = { silentUpdate(it as? String) }
|
||||
}
|
||||
|
||||
private fun silentUpdate(value: String?) {
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.TextItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class BlockHeadWidget(parent: ViewGroup, data: TextItem) : DescriptionWidget<String>(parent, data) {
|
||||
class GroupTitleWidget(parent: ViewGroup, data: TextItem) : DescriptionWidget(parent, data) {
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_text
|
||||
|
||||
private val tvName = view.findViewById<TextView>(R.id.tv_name)
|
||||
|
|
@ -8,7 +8,6 @@ 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.impl.NumberItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.CardNumber
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.addInputFilter
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.moveCursorToEnd
|
||||
|
|
@ -17,7 +16,11 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
|||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Number>(parent, data) {
|
||||
class NumberWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: NumberItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_number
|
||||
|
||||
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
|
||||
|
|
@ -25,7 +28,7 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Numb
|
|||
|
||||
private val watcher = object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
dataItem.viewModel.updateDataByView(getValue(stringOf(s)))
|
||||
typedItem.viewModel.updateDataByView(getValue(stringOf(s)))
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
|
|
@ -36,11 +39,11 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Numb
|
|||
tilItem.hint = getName()
|
||||
|
||||
//TODO: remove from Widget
|
||||
if (dataItem.id == CardNumber.Number) etItem.addInputFilter(InputFilter.LengthFilter(13))
|
||||
if (item.id == CardNumber.Number) etItem.addInputFilter(InputFilter.LengthFilter(13))
|
||||
|
||||
etItem.setText(stringOf(dataItem.getData()))
|
||||
etItem.setText(stringOf(typedItem.getTypedData()))
|
||||
etItem.addTextChangedListener(watcher)
|
||||
dataItem.viewModel.onDataUpdated = { silentUpdate(it) }
|
||||
item.viewModel.onDataUpdated = { silentUpdate(it as? Number) }
|
||||
}
|
||||
|
||||
private fun silentUpdate(value: Number?) {
|
||||
|
|
@ -53,5 +56,4 @@ class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Numb
|
|||
private fun getValue(value: String): Long {
|
||||
return if (value.isEmpty()) 0L else value.toLong()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,13 +10,13 @@ import com.tangem.tangemtest._arch.widget.abstraction.ViewWidget
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class PersonalizationItemBuilder : ItemWidgetBuilder {
|
||||
override fun build(item: BaseItem<*>, parent: ViewGroup): ViewWidget? {
|
||||
override fun build(item: BaseItem, parent: ViewGroup): ViewWidget? {
|
||||
return when (item) {
|
||||
is TextItem -> BlockHeadWidget(parent, item)
|
||||
is TextItem -> GroupTitleWidget(parent, item)
|
||||
is EditTextItem -> EditTextWidget(parent, item)
|
||||
is NumberItem -> NumberWidget(parent, item)
|
||||
is BoolItem -> SwitchWidget(parent, item)
|
||||
is ListItem -> SpinnerWidget(parent, item)
|
||||
is SpinnerItem -> SpinnerWidget(parent, item)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,20 +7,23 @@ import android.widget.BaseAdapter
|
|||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.KeyValue
|
||||
import com.tangem.tangemtest._arch.structure.impl.ListItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.ListValueWrapper
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.KeyValue
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ListViewModel
|
||||
import com.tangem.tangemtest._arch.structure.impl.SpinnerItem
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate
|
||||
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SpinnerWidget(parent: ViewGroup, listItem: ListItem) : DescriptionWidget<ListValueWrapper>(parent, listItem) {
|
||||
class SpinnerWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: SpinnerItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_spinner
|
||||
|
||||
private val data: ListValueWrapper = listItem.getData()!!
|
||||
private val data: ListViewModel = typedItem.getTypedData()!!
|
||||
|
||||
private val spItem = view.findViewById<Spinner>(R.id.sp_item)
|
||||
private val spAdapter = SpItemAdapter(data.itemList)
|
||||
|
|
@ -30,7 +33,7 @@ class SpinnerWidget(parent: ViewGroup, listItem: ListItem) : DescriptionWidget<L
|
|||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
data.selectedItem = data.itemList[position].value
|
||||
dataItem.viewModel.updateDataByView(data)
|
||||
typedItem.viewModel.updateDataByView(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,15 +45,14 @@ class SpinnerWidget(parent: ViewGroup, listItem: ListItem) : DescriptionWidget<L
|
|||
spItem.setSelection(it)
|
||||
}
|
||||
spItem.onItemSelectedListener = onItemSelectedListener
|
||||
dataItem.viewModel.onDataUpdated = {
|
||||
it?.apply {
|
||||
spItem.onItemSelectedListener = null
|
||||
this.itemList.firstOrNull { item -> item.value == selectedItem }?.let {
|
||||
val position = itemList.indexOf(it)
|
||||
spItem.setSelection(position)
|
||||
}
|
||||
spItem.onItemSelectedListener = onItemSelectedListener
|
||||
typedItem.viewModel.onDataUpdated = {
|
||||
val selectedItem = it as? String
|
||||
spItem.onItemSelectedListener = null
|
||||
data.itemList.firstOrNull { item -> item.value == selectedItem }?.let { keyValue ->
|
||||
val position = data.itemList.indexOf(keyValue)
|
||||
spItem.setSelection(position)
|
||||
}
|
||||
spItem.onItemSelectedListener = onItemSelectedListener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,27 +5,30 @@ import android.widget.CompoundButton
|
|||
import androidx.appcompat.widget.SwitchCompat
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.BoolItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SwitchWidget(parent: ViewGroup, data: BoolItem) : DescriptionWidget<Boolean>(parent, data) {
|
||||
class SwitchWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: BoolItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_personalize_item_switch
|
||||
|
||||
private val switchItem = view.findViewById<SwitchCompat>(R.id.sw_item)
|
||||
|
||||
private val changeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
|
||||
dataItem.viewModel.updateDataByView(isChecked)
|
||||
typedItem.viewModel.updateDataByView(isChecked)
|
||||
}
|
||||
|
||||
init {
|
||||
switchItem.text = getName()
|
||||
switchItem.isChecked = dataItem.getData() ?: false
|
||||
switchItem.isChecked = typedItem.getTypedData() ?: false
|
||||
switchItem.setOnCheckedChangeListener(changeListener)
|
||||
dataItem.viewModel.onDataUpdated = {
|
||||
typedItem.viewModel.onDataUpdated = {
|
||||
switchItem.setOnCheckedChangeListener(null)
|
||||
switchItem.isChecked = it ?: false
|
||||
switchItem.isChecked = it as? Boolean ?: false
|
||||
switchItem.setOnCheckedChangeListener(changeListener)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.tangemtest.ucase.variants.responses
|
|||
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.Item
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelToItems
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.iterate
|
||||
|
|
@ -30,8 +29,7 @@ class ResponseViewModel : ViewModel() {
|
|||
|
||||
fun toggleDescriptionVisibility(state: Boolean) {
|
||||
itemList?.iterate {
|
||||
val baseItem = it as? BaseItem<*> ?: return@iterate
|
||||
baseItem.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
it.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ import com.tangem.commands.SettingsMask
|
|||
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.ListItemBlock
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ItemGroup
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.ModelToItems
|
||||
import com.tangem.tangemtest._arch.structure.abstraction.SimpleItemGroup
|
||||
import com.tangem.tangemtest._arch.structure.impl.BoolItem
|
||||
import com.tangem.tangemtest._arch.structure.impl.TextItem
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.BlockId
|
||||
|
|
@ -31,55 +32,53 @@ class CardConverter : ModelToItems<Card> {
|
|||
}
|
||||
|
||||
private fun simpleFields(from: Card): Item {
|
||||
val block = createBlock(BlockId.Common)
|
||||
block.addItem(TextItem(CardId.cardId, from.cardId))
|
||||
block.addItem(TextItem(CardId.manufacturerName, from.manufacturerName))
|
||||
block.addItem(TextItem(CardId.status, stringOf(from.status)))
|
||||
block.addItem(TextItem(CardId.firmwareVersion, from.firmwareVersion))
|
||||
block.addItem(TextItem(CardId.cardPublicKey, stringOf(from.cardPublicKey)))
|
||||
block.addItem(TextItem(CardId.issuerPublicKey, stringOf(from.issuerPublicKey)))
|
||||
block.addItem(TextItem(CardId.curve, stringOf(from.curve)))
|
||||
block.addItem(TextItem(CardId.maxSignatures, stringOf(from.maxSignatures)))
|
||||
block.addItem(TextItem(CardId.signingMethod, stringOf(from.signingMethod)))
|
||||
block.addItem(TextItem(CardId.pauseBeforePin2, stringOf(from.pauseBeforePin2)))
|
||||
block.addItem(TextItem(CardId.walletPublicKey, stringOf(from.walletPublicKey)))
|
||||
block.addItem(TextItem(CardId.walletRemainingSignatures, stringOf(from.walletRemainingSignatures)))
|
||||
block.addItem(TextItem(CardId.walletSignedHashes, stringOf(from.walletSignedHashes)))
|
||||
block.addItem(TextItem(CardId.health, stringOf(from.health)))
|
||||
block.addItem(TextItem(CardId.isActivated, stringOf(from.isActivated)))
|
||||
block.addItem(TextItem(CardId.activationSeed, stringOf(from.activationSeed)))
|
||||
block.addItem(TextItem(CardId.paymentFlowVersion, stringOf(from.paymentFlowVersion)))
|
||||
block.addItem(TextItem(CardId.userCounter, stringOf(from.userCounter)))
|
||||
val group = createGroup(BlockId.Common)
|
||||
group.addItem(TextItem(CardId.cardId, from.cardId))
|
||||
group.addItem(TextItem(CardId.manufacturerName, from.manufacturerName))
|
||||
group.addItem(TextItem(CardId.status, stringOf(from.status)))
|
||||
group.addItem(TextItem(CardId.firmwareVersion, from.firmwareVersion))
|
||||
group.addItem(TextItem(CardId.cardPublicKey, stringOf(from.cardPublicKey)))
|
||||
group.addItem(TextItem(CardId.issuerPublicKey, stringOf(from.issuerPublicKey)))
|
||||
group.addItem(TextItem(CardId.curve, stringOf(from.curve)))
|
||||
group.addItem(TextItem(CardId.maxSignatures, stringOf(from.maxSignatures)))
|
||||
group.addItem(TextItem(CardId.signingMethod, stringOf(from.signingMethod)))
|
||||
group.addItem(TextItem(CardId.pauseBeforePin2, stringOf(from.pauseBeforePin2)))
|
||||
group.addItem(TextItem(CardId.walletPublicKey, stringOf(from.walletPublicKey)))
|
||||
group.addItem(TextItem(CardId.walletRemainingSignatures, stringOf(from.walletRemainingSignatures)))
|
||||
group.addItem(TextItem(CardId.walletSignedHashes, stringOf(from.walletSignedHashes)))
|
||||
group.addItem(TextItem(CardId.health, stringOf(from.health)))
|
||||
group.addItem(TextItem(CardId.isActivated, stringOf(from.isActivated)))
|
||||
group.addItem(TextItem(CardId.activationSeed, stringOf(from.activationSeed)))
|
||||
group.addItem(TextItem(CardId.paymentFlowVersion, stringOf(from.paymentFlowVersion)))
|
||||
group.addItem(TextItem(CardId.userCounter, stringOf(from.userCounter)))
|
||||
// block.addItem(TextItem(CardId.UserProtectedCounter, stringOf(from.userProtectedCounter)))
|
||||
return block
|
||||
return group
|
||||
}
|
||||
|
||||
private fun cardData(from: Card): Item {
|
||||
val block = createBlock(BlockId.Common)
|
||||
val data = from.cardData ?: return block
|
||||
|
||||
val itemList = block.itemList
|
||||
itemList.add(TextItem(CardDataId.batchId, data.batchId))
|
||||
val group = createGroup(BlockId.Common)
|
||||
val data = from.cardData ?: return group
|
||||
group.addItem(TextItem(CardDataId.batchId, data.batchId))
|
||||
// Format: Year (2 bytes) | Month (1 byte) | Day (1 byte)
|
||||
itemList.add(TextItem(CardDataId.manufactureDateTime, stringOf(data.manufactureDateTime)))
|
||||
itemList.add(TextItem(CardDataId.issuerName, data.issuerName))
|
||||
itemList.add(TextItem(CardDataId.blockchainName, data.blockchainName))
|
||||
itemList.add(TextItem(CardDataId.manufacturerSignature, stringOf(data.manufacturerSignature)))
|
||||
itemList.add(TextItem(CardDataId.productMask, stringOf(data.productMask)))
|
||||
itemList.add(TextItem(CardDataId.tokenSymbol, data.tokenSymbol))
|
||||
itemList.add(TextItem(CardDataId.tokenContractAddress, data.tokenContractAddress))
|
||||
itemList.add(TextItem(CardDataId.tokenDecimal, data.tokenSymbol))
|
||||
group.addItem(TextItem(CardDataId.manufactureDateTime, stringOf(data.manufactureDateTime)))
|
||||
group.addItem(TextItem(CardDataId.issuerName, data.issuerName))
|
||||
group.addItem(TextItem(CardDataId.blockchainName, data.blockchainName))
|
||||
group.addItem(TextItem(CardDataId.manufacturerSignature, stringOf(data.manufacturerSignature)))
|
||||
group.addItem(TextItem(CardDataId.productMask, stringOf(data.productMask)))
|
||||
group.addItem(TextItem(CardDataId.tokenSymbol, data.tokenSymbol))
|
||||
group.addItem(TextItem(CardDataId.tokenContractAddress, data.tokenContractAddress))
|
||||
group.addItem(TextItem(CardDataId.tokenDecimal, data.tokenSymbol))
|
||||
|
||||
return block
|
||||
return group
|
||||
}
|
||||
|
||||
private fun settingsMask(from: SettingsMask?): Item {
|
||||
val block = createBlock(CardId.settingsMask)
|
||||
val data = from ?: return block
|
||||
val group = createGroup(CardId.settingsMask)
|
||||
val data = from ?: return group
|
||||
|
||||
Settings.values().forEach { block.addItem(BoolItem(StringId(it.name), data.contains(it))) }
|
||||
return block
|
||||
Settings.values().forEach { group.addItem(BoolItem(StringId(it.name), data.contains(it))) }
|
||||
return group
|
||||
}
|
||||
|
||||
private fun createBlock(id: Id): ListItemBlock = ListItemBlock(id).apply { addItem(TextItem(id)) }
|
||||
private fun createGroup(id: Id): ItemGroup = SimpleItemGroup(id).apply { addItem(TextItem(id)) }
|
||||
}
|
||||
|
|
@ -4,21 +4,24 @@ import android.view.ViewGroup
|
|||
import com.google.android.material.checkbox.MaterialCheckBox
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.BoolItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.DescriptionWidget
|
||||
import ru.dev.gbixahue.eu4d.lib.android._android.views.colorFrom
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CheckBoxWidget(parent: ViewGroup, private val boolItem: BoolItem) : DescriptionWidget<Boolean>(parent, boolItem) {
|
||||
class CheckBoxWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: BoolItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_response_item_checkbox
|
||||
|
||||
private val switchItem = view.findViewById<MaterialCheckBox>(R.id.sw_item)
|
||||
|
||||
init {
|
||||
switchItem.text = getName()
|
||||
switchItem.isChecked = dataItem.getData() ?: false
|
||||
switchItem.isChecked = typedItem.getData() ?: false
|
||||
switchItem.isEnabled = false
|
||||
switchItem.setTextColor(switchItem.colorFrom(R.color.action_name))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.tangemtest._arch.widget.abstraction.ViewWidget
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ResponseItemBuilder : ItemWidgetBuilder {
|
||||
override fun build(item: BaseItem<*>, parent: ViewGroup): ViewWidget? {
|
||||
override fun build(item: BaseItem, parent: ViewGroup): ViewWidget? {
|
||||
return when (item) {
|
||||
is TextItem -> ResponseTextWidget(parent, item)
|
||||
is BoolItem -> CheckBoxWidget(parent, item)
|
||||
|
|
|
|||
|
|
@ -8,13 +8,16 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import com.tangem.tangemtest.R
|
||||
import com.tangem.tangemtest._arch.structure.impl.TextItem
|
||||
import com.tangem.tangemtest._arch.widget.abstraction.getName
|
||||
import com.tangem.tangemtest.ucase.variants.personalize.ui.widgets.DescriptionWidget
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ResponseTextWidget(parent: ViewGroup, private val textItem: TextItem) : DescriptionWidget<String>(parent, textItem) {
|
||||
class ResponseTextWidget(
|
||||
parent: ViewGroup,
|
||||
private val typedItem: TextItem
|
||||
) : DescriptionWidget(parent, typedItem) {
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.w_response_item
|
||||
|
||||
private val tvName: TextView = view.findViewById(R.id.tv_name)
|
||||
|
|
@ -25,7 +28,7 @@ class ResponseTextWidget(parent: ViewGroup, private val textItem: TextItem) : De
|
|||
}
|
||||
|
||||
private fun initWidgets() {
|
||||
val data = textItem.getData()
|
||||
val data = typedItem.getData() as? String
|
||||
if (data == null || data.isEmpty()) {
|
||||
view.visibility = View.GONE
|
||||
return
|
||||
|
|
@ -38,7 +41,7 @@ class ResponseTextWidget(parent: ViewGroup, private val textItem: TextItem) : De
|
|||
val clipboard = view.context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
|
||||
?: return@setOnClickListener
|
||||
|
||||
val clip: ClipData = ClipData.newPlainText("FieldValue", "${dataItem.getData()}")
|
||||
val clip: ClipData = ClipData.newPlainText("FieldValue", "$data")
|
||||
clipboard.setPrimaryClip(clip)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue