Updated on 2026-08-14

This commit is contained in:
Tangem 2020-03-25 22:43:14 +03:00
parent 0ff14ccd51
commit 0b575b8e91
41 changed files with 607 additions and 547 deletions

View file

@ -1,8 +1,8 @@
package com.tangem.tangemtest
import android.app.Application
import com.tangem.tangemtest._arch.structure.base.ULog
import com.tangem.tangemtest._arch.structure.base.UnitLogger
import com.tangem.tangemtest._arch.structure.ILog
import com.tangem.tangemtest._arch.structure.ItemLogger
import com.tangem.tangemtest.commons.TangemLogger
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
@ -20,7 +20,7 @@ class AppTangemDemo : Application() {
private fun setupLoggers() {
Log.setLogger(TangemLogger())
ULog.setLogger(UnitLogger())
ILog.setLogger(ItemLogger())
}
companion object {

View file

@ -1,10 +1,10 @@
package com.tangem.tangemtest._arch.structure.base
package com.tangem.tangemtest._arch.structure
/**
[REDACTED_AUTHOR]
*/
interface DataHolder<D> {
var viewModel: D?
var viewModel: D
}
interface Payload {

View file

@ -1,4 +1,4 @@
package com.tangem.tangemtest._arch.structure.base
package com.tangem.tangemtest._arch.structure
/**
[REDACTED_AUTHOR]

View file

@ -1,4 +1,4 @@
package com.tangem.tangemtest._arch.structure.base
package com.tangem.tangemtest._arch.structure
import ru.dev.gbixahue.eu4d.lib.android.global.log.Logger
import ru.dev.gbixahue.eu4d.lib.android.global.log.TagLogger
@ -8,12 +8,12 @@ import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
/**
[REDACTED_AUTHOR]
*/
object ULog {
object ILog {
private var logger: Logger? = null
fun setLogger(logger: Logger) {
ULog.logger = logger
ILog.logger = logger
}
fun d(from: Any, msg: Any?, value: Any? = null) {
@ -29,7 +29,7 @@ object ULog {
}
}
class UnitLogger : TagLogger("UNIT") {
class ItemLogger : TagLogger("ITEM") {
init {
msProfiler = SimpleLogProfiler()
}

View file

@ -0,0 +1,50 @@
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 {
val itemList: MutableList<Item>
}
abstract class BaseBlock : Block {
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.clear()
itemList.addAll(list)
itemList.forEach { it.parent = this }
}
override fun getItems(): MutableList<Item> {
return itemList
}
override fun addItem(item: Item) {
ILog.d(this, "addItem into: $id, who: ${item.id}")
item.parent = this
itemList.add(item)
}
override fun removeItem(item: Item) {
ILog.d(this, "removeItem from: $id, which: ${item.id}")
itemList.remove(item)
}
override fun clear() {
ILog.d(this, "clear $id")
itemList.clear()
}
}

View file

@ -0,0 +1,20 @@
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
/**
[REDACTED_AUTHOR]
*/
interface Item : Payload {
val id: Id
var parent: Item?
}
abstract class BaseItem<D>(
override var viewModel: ItemViewModel<D>
) : Item, DataHolder<ItemViewModel<D>> {
override var parent: Item? = null
override val payload: MutableMap<String, Any?> = mutableMapOf()
}

View file

@ -0,0 +1,10 @@
package com.tangem.tangemtest._arch.structure.abstraction
/**
[REDACTED_AUTHOR]
*/
typealias PluginCallBackResult = (Any?) -> Item
interface Plugin : Item {
fun invoke(data: Any?, asyncCallback: PluginCallBackResult? = null): Any?
}

View file

@ -1,13 +1,16 @@
package com.tangem.tangemtest._arch.structure.base
package com.tangem.tangemtest._arch.structure.abstraction
import com.tangem.tangemtest._arch.structure.ILog
import com.tangem.tangemtest._arch.structure.Payload
/**
[REDACTED_AUTHOR]
*/
typealias ValueChange<V> = (V?) -> kotlin.Unit
typealias SafeValueChange<V> = (V) -> kotlin.Unit
typealias ValueChange<V> = (V?) -> Unit
typealias SafeValueChange<V> = (V) -> Unit
interface UnitViewModel<D> : Payload {
interface ItemViewModel<D> : Payload {
val viewState: ViewState
var data: D?
var onDataUpdated: ValueChange<D>?
@ -15,7 +18,7 @@ interface UnitViewModel<D> : Payload {
fun updateDataByView(data: D?)
}
open class BaseUnitViewModel<D> : UnitViewModel<D> {
open class BaseItemViewModel<D> : ItemViewModel<D> {
override val viewState: ViewState = ViewState()
override val payload: MutableMap<String, Any?> = mutableMapOf()
@ -28,13 +31,13 @@ open class BaseUnitViewModel<D> : UnitViewModel<D> {
override var onDataUpdated: ValueChange<D>? = null
protected open fun handleDataUpdates(value: D?): Boolean {
ULog.d(this, "handleDateUpdates: $value")
ILog.d(this, "handleDateUpdates: $value")
onDataUpdated?.invoke(value)
return true
}
override fun updateDataByView(data: D?) {
ULog.d(this, "data changed: $data")
ILog.d(this, "data changed: $data")
val callback = onDataUpdated
onDataUpdated = null
this.data = data

View file

@ -1,18 +0,0 @@
package com.tangem.tangemtest._arch.structure.base
/**
[REDACTED_AUTHOR]
*/
interface Unit : Payload {
val id: Id
var parent: Unit?
}
abstract class BaseUnit : Unit {
override var parent: Unit? = null
override val payload: MutableMap<String, Any?> = mutableMapOf()
}
abstract class DataUnit<D>(
override var viewModel: UnitViewModel<D>?
) : BaseUnit(), DataHolder<UnitViewModel<D>>

View file

@ -1,54 +0,0 @@
package com.tangem.tangemtest._arch.structure.base
/**
[REDACTED_AUTHOR]
*/
typealias BlockModified = () -> Unit
interface Block : Unit {
val unitList: MutableList<Unit>
var blockModified: BlockModified?
}
abstract class BaseBlock : Block {
override var parent: Unit? = null
override val unitList: MutableList<Unit> = mutableListOf()
override val payload: MutableMap<String, Any?> = mutableMapOf()
override var blockModified: BlockModified? = null
}
open class ListUnitBlock(
override val id: Id
) : BaseBlock(), ItemListHolder<Unit> {
override fun setItems(list: MutableList<Unit>) {
ULog.d(this, "setItems into: $id, count: ${list.size}")
unitList.clear()
unitList.addAll(list)
unitList.forEach { it.parent = this }
blockModified?.invoke()
}
override fun getItems(): MutableList<Unit> {
return unitList
}
override fun addItem(item: Unit) {
ULog.d(this, "addIte into: $id, who: ${item.id}")
item.parent = this
unitList.add(item)
blockModified?.invoke()
}
override fun removeItem(item: Unit) {
ULog.d(this, "removeItem from: $id, which: ${item.id}")
unitList.remove(item)
blockModified?.invoke()
}
override fun clear() {
ULog.d(this, "clear $id")
unitList.clear()
blockModified?.invoke()
}
}

View file

@ -1,10 +0,0 @@
package com.tangem.tangemtest._arch.structure.base
/**
[REDACTED_AUTHOR]
*/
typealias PluginCallBackResult = (Any?) -> Unit
interface Plugin : Unit {
fun invoke(data: Any?, asyncCallback: PluginCallBackResult? = null): Any?
}

View file

@ -0,0 +1,15 @@
package com.tangem.tangemtest._arch.structure.impl
import com.tangem.tangemtest._arch.structure.Id
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
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))
)

View file

@ -0,0 +1,30 @@
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 {
data = 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
onDataUpdated?.invoke(value)
return true
}
}
class KeyValue(val key: String, val value: Any)
class ListValueWrapper(var selectedItem: Any, val itemList: List<KeyValue>)

View file

@ -1,9 +0,0 @@
package com.tangem.tangemtest._arch.structure.impl
import com.tangem.tangemtest._arch.structure.base.Id
import com.tangem.tangemtest._arch.structure.base.ListUnitBlock
/**
[REDACTED_AUTHOR]
*/
class LinearBlock(id: Id) : ListUnitBlock(id)

View file

@ -1,14 +0,0 @@
package com.tangem.tangemtest._arch.structure.impl
import com.tangem.tangemtest._arch.structure.base.DataUnit
import com.tangem.tangemtest._arch.structure.base.Id
class TextUnit(override val id: Id, value: String? = null) : DataUnit<String>(StringViewModel(value))
class EditTextUnit(override val id: Id, value: String? = null) : DataUnit<String>(StringViewModel(value))
class NumberUnit(override val id: Id, value: Number? = null) : DataUnit<Number>(NumberViewModel(value))
class BoolUnit(override val id: Id, value: Boolean? = null) : DataUnit<Boolean>(BoolViewModel(value))
class ListUnit(override val id: Id, value: List<KeyValue>, selectedValue: Any)
: DataUnit<ListValueWrapper>(ListViewModel(ListValueWrapper(selectedValue, value))
)

View file

@ -1,29 +0,0 @@
package com.tangem.tangemtest._arch.structure.impl
import com.tangem.tangemtest._arch.structure.base.BaseUnitViewModel
/**
[REDACTED_AUTHOR]
*/
open class TransitiveViewModel<D>(value: D?) : BaseUnitViewModel<D>() {
init {
data = value
}
}
class StringViewModel(value: String?) : TransitiveViewModel<String>(value)
class NumberViewModel(value: Number?) : TransitiveViewModel<Number>(value)
class BoolViewModel(value: Boolean?) : TransitiveViewModel<Boolean>(value)
class ListViewModel(value: ListValueWrapper?) : TransitiveViewModel<ListValueWrapper>(value) {
override fun handleDataUpdates(value: ListValueWrapper?): Boolean {
val newValue = value ?: return false
if (newValue.selectedItem == data?.selectedItem) return false
onDataUpdated?.invoke(value)
return true
}
}
class KeyValue(val key: String, val value: Any)
class ListValueWrapper(var selectedItem: Any, val itemList: List<KeyValue>)

View file

@ -79,7 +79,7 @@ class SignAction : BaseCardAction() {
class PersonalizeAction : BaseCardAction() {
override fun executeMainAction(attrs: AttrForAction, callback: ActionCallback) {
ScanAction().executeMainAction(attrs) { response, b ->
when(response){
when (response) {
is TaskEvent.Event -> {
val taskEvent = response as TaskEvent.Event
val cardId = handleDataEvent(taskEvent.data)

View file

@ -98,7 +98,7 @@ class PersonalizeParamsManager : BaseParamsManager(PersonalizeAction()) {
}
}
class DepersonalizeParamsManager: BaseParamsManager(DepesonalizeAction()){
class DepersonalizeParamsManager : BaseParamsManager(DepesonalizeAction()) {
override fun createParamsList(): List<IncomingParameter> {
return listOf(IncomingParameter(TlvTag.CardId, null))
}

View file

@ -1,11 +1,11 @@
package com.tangem.tangemtest.card_use_cases.resources
import com.tangem.tangemtest._arch.structure.base.Id
import com.tangem.tangemtest._arch.structure.Id
/**
[REDACTED_AUTHOR]
*/
enum class ActionType: Id {
enum class ActionType : Id {
Scan,
Sign,
CreateWallet,

View file

@ -1,7 +1,7 @@
package com.tangem.tangemtest.card_use_cases.resources
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.base.Id
import com.tangem.tangemtest._arch.structure.Id
import com.tangem.tangemtest.card_use_cases.resources.initializers.ActionResources
import com.tangem.tangemtest.card_use_cases.resources.initializers.PersonalizeResources
import ru.dev.gbixahue.eu4d.lib.kotlin.common.BaseTypedHolder

View file

@ -1,7 +1,7 @@
package com.tangem.tangemtest.card_use_cases.resources.initializers
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.base.Id
import com.tangem.tangemtest._arch.structure.Id
import com.tangem.tangemtest.card_use_cases.resources.ActionRes
import com.tangem.tangemtest.card_use_cases.resources.ActionType
import com.tangem.tangemtest.card_use_cases.resources.ResourceHolder

View file

@ -1,7 +1,7 @@
package com.tangem.tangemtest.card_use_cases.resources.initializers
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.base.*
import com.tangem.tangemtest._arch.structure.*
import com.tangem.tangemtest.card_use_cases.resources.ResourceHolder
import com.tangem.tangemtest.card_use_cases.resources.Resources
import ru.dev.gbixahue.eu4d.lib.kotlin.common.TypedHolder

View file

@ -5,12 +5,12 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.google.gson.Gson
import com.tangem.tangemtest._arch.structure.base.Block
import com.tangem.tangemtest._arch.structure.base.DataUnit
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
import com.tangem.tangemtest._arch.structure.abstraction.Block
import com.tangem.tangemtest.card_use_cases.ui.personalize.converter.BlockToJsonConverter
import com.tangem.tangemtest.card_use_cases.ui.personalize.converter.JsonBlockEnDe
import com.tangem.tangemtest.card_use_cases.ui.personalize.converter.JsonToBlockConverter
import com.tangem.tangemtest.card_use_cases.ui.personalize.converter.TestJsonDto
import com.tangem.tangemtest.card_use_cases.ui.personalize.dto.TestJsonDto
/**
[REDACTED_AUTHOR]
@ -31,9 +31,9 @@ class PersonalizeViewModel(private val jsonPersonalizeString: String) : ViewMode
fun toggleDescriptionVisibility(state: Boolean) {
ldBlockList.value?.forEach { block ->
block.unitList.forEach { unit ->
val vm = unit as? DataUnit<*> ?: return@forEach
vm.viewModel?.viewState?.descriptionVisibility = if (state) View.VISIBLE else View.GONE
block.itemList.forEach { item ->
val vm = item as? BaseItem<*> ?: return@forEach
vm.viewModel.viewState.descriptionVisibility = if (state) View.VISIBLE else View.GONE
}
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.converter
import com.tangem.tangemtest._arch.structure.base.Block
import com.tangem.tangemtest._arch.structure.abstraction.Block
import com.tangem.tangemtest.card_use_cases.ui.personalize.dto.TestJsonDto
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
class BlockToJsonConverter : Converter<List<Block>, TestJsonDto> {

View file

@ -1,6 +1,7 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.converter
import com.tangem.tangemtest._arch.structure.base.Block
import com.tangem.tangemtest._arch.structure.abstraction.Block
import com.tangem.tangemtest.card_use_cases.ui.personalize.dto.TestJsonDto
/**
[REDACTED_AUTHOR]

View file

@ -1,7 +1,11 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.converter
import com.tangem.tangemtest._arch.structure.base.*
import com.tangem.tangemtest._arch.structure.*
import com.tangem.tangemtest._arch.structure.abstraction.Block
import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock
import com.tangem.tangemtest._arch.structure.impl.*
import com.tangem.tangemtest.card_use_cases.ui.personalize.dto.Ndef
import com.tangem.tangemtest.card_use_cases.ui.personalize.dto.TestJsonDto
import ru.dev.gbixahue.eu4d.lib.kotlin.common.Converter
class JsonToBlockConverter : Converter<TestJsonDto, List<Block>> {
@ -19,130 +23,130 @@ class JsonToBlockConverter : Converter<TestJsonDto, List<Block>> {
blocList.add(settingsMaskProtocolEnc(from))
blocList.add(settingsMaskNdef(from))
blocList.add(pins(from))
val payloadBlock = LinearBlock(Additional.JSON_TAILS)
val payloadBlock = ListItemBlock(Additional.JSON_TAILS)
addPayload(payloadBlock, from)
blocList.add(payloadBlock)
return blocList
}
private fun cardNumber(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.CARD_NUMBER)
block.addItem(TextUnit(BlockId.CARD_NUMBER))
block.addItem(EditTextUnit(CardNumber.SERIES, from.series))
block.addItem(NumberUnit(CardNumber.NUMBER, from.startNumber))
val block = ListItemBlock(BlockId.CARD_NUMBER)
block.addItem(TextItem(BlockId.CARD_NUMBER))
block.addItem(EditTextItem(CardNumber.SERIES, from.series))
block.addItem(NumberItem(CardNumber.NUMBER, from.startNumber))
return block
}
private fun common(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.COMMON)
block.addItem(TextUnit(BlockId.COMMON))
block.addItem(ListUnit(Common.CURVE, Helper.listOfCurves(), from.curveID))
block.addItem(ListUnit(Common.BLOCKCHAIN, Helper.listOfBlockchain(), from.blockchain.name))
block.addItem(EditTextUnit(Common.BLOCKCHAIN_CUSTOM, from.blockchain.customName))
block.addItem(NumberUnit(Common.MAX_SIGNATURES, from.MaxSignatures))
block.addItem(BoolUnit(Common.CREATE_WALLET, from.createWalletB))
val block = ListItemBlock(BlockId.COMMON)
block.addItem(TextItem(BlockId.COMMON))
block.addItem(ListItem(Common.CURVE, Helper.listOfCurves(), from.curveID))
block.addItem(ListItem(Common.BLOCKCHAIN, Helper.listOfBlockchain(), from.blockchain.name))
block.addItem(EditTextItem(Common.BLOCKCHAIN_CUSTOM, from.blockchain.customName))
block.addItem(NumberItem(Common.MAX_SIGNATURES, from.MaxSignatures))
block.addItem(BoolItem(Common.CREATE_WALLET, from.createWalletB))
return block
}
private fun signingMethod(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.SIGNING_METHOD)
block.addItem(TextUnit(BlockId.SIGNING_METHOD))
block.addItem(BoolUnit(SigningMethod.SIGN_TX, from.SigningMethod0))
block.addItem(BoolUnit(SigningMethod.SIGN_TX_RAW, from.SigningMethod1))
block.addItem(BoolUnit(SigningMethod.SIGN_VALIDATED_TX, from.SigningMethod2))
block.addItem(BoolUnit(SigningMethod.SIGN_VALIDATED_TX_RAW, from.SigningMethod3))
block.addItem(BoolUnit(SigningMethod.SIGN_VALIDATED_TX_ISSUER, from.SigningMethod4))
block.addItem(BoolUnit(SigningMethod.SIGN_VALIDATED_TX_RAW_ISSUER, from.SigningMethod5))
block.addItem(BoolUnit(SigningMethod.SIGN_EXTERNAL, from.SigningMethod6))
val block = ListItemBlock(BlockId.SIGNING_METHOD)
block.addItem(TextItem(BlockId.SIGNING_METHOD))
block.addItem(BoolItem(SigningMethod.SIGN_TX, from.SigningMethod0))
block.addItem(BoolItem(SigningMethod.SIGN_TX_RAW, from.SigningMethod1))
block.addItem(BoolItem(SigningMethod.SIGN_VALIDATED_TX, from.SigningMethod2))
block.addItem(BoolItem(SigningMethod.SIGN_VALIDATED_TX_RAW, from.SigningMethod3))
block.addItem(BoolItem(SigningMethod.SIGN_VALIDATED_TX_ISSUER, from.SigningMethod4))
block.addItem(BoolItem(SigningMethod.SIGN_VALIDATED_TX_RAW_ISSUER, from.SigningMethod5))
block.addItem(BoolItem(SigningMethod.SIGN_EXTERNAL, from.SigningMethod6))
return block
}
private fun signHashExProperties(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.SIGN_HASH_EX_PROP)
block.addItem(TextUnit(BlockId.SIGN_HASH_EX_PROP))
block.addItem(NumberUnit(SignHashExProp.PIN_LESS_FLOOR_LIMIT, from.pinLessFloorLimit))
block.addItem(EditTextUnit(SignHashExProp.CRYPTO_EXTRACT_KEY, from.hexCrExKey))
block.addItem(BoolUnit(SignHashExProp.REQUIRE_TERMINAL_CERT_SIG, from.requireTerminalCertSignature))
block.addItem(BoolUnit(SignHashExProp.REQUIRE_TERMINAL_TX_SIG, from.requireTerminalTxSignature))
block.addItem(BoolUnit(SignHashExProp.CHECK_PIN3, from.checkPIN3onCard))
val block = ListItemBlock(BlockId.SIGN_HASH_EX_PROP)
block.addItem(TextItem(BlockId.SIGN_HASH_EX_PROP))
block.addItem(NumberItem(SignHashExProp.PIN_LESS_FLOOR_LIMIT, from.pinLessFloorLimit))
block.addItem(EditTextItem(SignHashExProp.CRYPTO_EXTRACT_KEY, from.hexCrExKey))
block.addItem(BoolItem(SignHashExProp.REQUIRE_TERMINAL_CERT_SIG, from.requireTerminalCertSignature))
block.addItem(BoolItem(SignHashExProp.REQUIRE_TERMINAL_TX_SIG, from.requireTerminalTxSignature))
block.addItem(BoolItem(SignHashExProp.CHECK_PIN3, from.checkPIN3onCard))
return block
}
private fun denomination(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.DENOMINATION)
block.addItem(TextUnit(BlockId.DENOMINATION))
block.addItem(BoolUnit(Denomination.WRITE_ON_PERSONALIZE, from.writeOnPersonalization))
block.addItem(NumberUnit(Denomination.DENOMINATION, from.denomination))
val block = ListItemBlock(BlockId.DENOMINATION)
block.addItem(TextItem(BlockId.DENOMINATION))
block.addItem(BoolItem(Denomination.WRITE_ON_PERSONALIZE, from.writeOnPersonalization))
block.addItem(NumberItem(Denomination.DENOMINATION, from.denomination))
return block
}
private fun token(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.TOKEN)
block.addItem(TextUnit(BlockId.TOKEN))
block.addItem(BoolUnit(Token.ITS_TOKEN, from.itsToken))
block.addItem(EditTextUnit(Token.SYMBOL, from.symbol))
block.addItem(EditTextUnit(Token.CONTRACT_ADDRESS, from.contractAddress))
block.addItem(NumberUnit(Token.DECIMAL, from.decimal))
val block = ListItemBlock(BlockId.TOKEN)
block.addItem(TextItem(BlockId.TOKEN))
block.addItem(BoolItem(Token.ITS_TOKEN, from.itsToken))
block.addItem(EditTextItem(Token.SYMBOL, from.symbol))
block.addItem(EditTextItem(Token.CONTRACT_ADDRESS, from.contractAddress))
block.addItem(NumberItem(Token.DECIMAL, from.decimal))
return block
}
private fun productMask(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.PROD_MASK)
block.addItem(TextUnit(BlockId.PROD_MASK))
block.addItem(BoolUnit(ProductMask.NOTE, from.cardData.product_note))
block.addItem(BoolUnit(ProductMask.TAG, from.cardData.product_tag))
block.addItem(BoolUnit(ProductMask.ID_CARD, from.cardData.product_id_card))
val block = ListItemBlock(BlockId.PROD_MASK)
block.addItem(TextItem(BlockId.PROD_MASK))
block.addItem(BoolItem(ProductMask.NOTE, from.cardData.product_note))
block.addItem(BoolItem(ProductMask.TAG, from.cardData.product_tag))
block.addItem(BoolItem(ProductMask.ID_CARD, from.cardData.product_id_card))
return block
}
private fun settingsMask(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.SETTINGS_MASK)
block.addItem(TextUnit(BlockId.SETTINGS_MASK))
block.addItem(BoolUnit(SettingsMask.IS_REUSABLE, from.isReusable))
block.addItem(BoolUnit(SettingsMask.NEED_ACTIVATION, from.useActivation))
block.addItem(BoolUnit(SettingsMask.FORBID_PURGE, from.forbidPurgeWallet))
block.addItem(BoolUnit(SettingsMask.ALLOW_SELECT_BLOCKCHAIN, from.allowSelectBlockchain))
block.addItem(BoolUnit(SettingsMask.USE_BLOCK, from.useBlock))
block.addItem(BoolUnit(SettingsMask.ONE_APDU, from.useOneCommandAtTime))
block.addItem(BoolUnit(SettingsMask.USE_CVC, from.useCVC))
block.addItem(BoolUnit(SettingsMask.ALLOW_SWAP_PIN, from.allowSwapPIN))
block.addItem(BoolUnit(SettingsMask.ALLOW_SWAP_PIN2, from.allowSwapPIN2))
block.addItem(BoolUnit(SettingsMask.FORBID_DEFAULT_PIN, from.forbidDefaultPIN))
block.addItem(BoolUnit(SettingsMask.SMART_SECURITY_DELAY, from.smartSecurityDelay))
block.addItem(BoolUnit(SettingsMask.PROTECT_ISSUER_DATA_AGAINST_REPLAY, from.protectIssuerDataAgainstReplay))
block.addItem(BoolUnit(SettingsMask.SKIP_SECURITY_DELAY_IF_VALIDATED, from.skipSecurityDelayIfValidatedByIssuer))
block.addItem(BoolUnit(SettingsMask.SKIP_PIN2_CVC_IF_VALIDATED, from.skipCheckPIN2andCVCIfValidatedByIssuer))
block.addItem(BoolUnit(SettingsMask.SKIP_SECURITY_DELAY_ON_LINKED_TERMINAL, from.skipSecurityDelayIfValidatedByLinkedTerminal))
block.addItem(BoolUnit(SettingsMask.RESTRICT_OVERWRITE_EXTRA_ISSUER_DATA, from.restrictOverwriteIssuerDataEx))
val block = ListItemBlock(BlockId.SETTINGS_MASK)
block.addItem(TextItem(BlockId.SETTINGS_MASK))
block.addItem(BoolItem(SettingsMask.IS_REUSABLE, from.isReusable))
block.addItem(BoolItem(SettingsMask.NEED_ACTIVATION, from.useActivation))
block.addItem(BoolItem(SettingsMask.FORBID_PURGE, from.forbidPurgeWallet))
block.addItem(BoolItem(SettingsMask.ALLOW_SELECT_BLOCKCHAIN, from.allowSelectBlockchain))
block.addItem(BoolItem(SettingsMask.USE_BLOCK, from.useBlock))
block.addItem(BoolItem(SettingsMask.ONE_APDU, from.useOneCommandAtTime))
block.addItem(BoolItem(SettingsMask.USE_CVC, from.useCVC))
block.addItem(BoolItem(SettingsMask.ALLOW_SWAP_PIN, from.allowSwapPIN))
block.addItem(BoolItem(SettingsMask.ALLOW_SWAP_PIN2, from.allowSwapPIN2))
block.addItem(BoolItem(SettingsMask.FORBID_DEFAULT_PIN, from.forbidDefaultPIN))
block.addItem(BoolItem(SettingsMask.SMART_SECURITY_DELAY, from.smartSecurityDelay))
block.addItem(BoolItem(SettingsMask.PROTECT_ISSUER_DATA_AGAINST_REPLAY, from.protectIssuerDataAgainstReplay))
block.addItem(BoolItem(SettingsMask.SKIP_SECURITY_DELAY_IF_VALIDATED, from.skipSecurityDelayIfValidatedByIssuer))
block.addItem(BoolItem(SettingsMask.SKIP_PIN2_CVC_IF_VALIDATED, from.skipCheckPIN2andCVCIfValidatedByIssuer))
block.addItem(BoolItem(SettingsMask.SKIP_SECURITY_DELAY_ON_LINKED_TERMINAL, from.skipSecurityDelayIfValidatedByLinkedTerminal))
block.addItem(BoolItem(SettingsMask.RESTRICT_OVERWRITE_EXTRA_ISSUER_DATA, from.restrictOverwriteIssuerDataEx))
return block
}
private fun settingsMaskProtocolEnc(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.SETTINGS_MASK_PROTOCOL_ENC)
block.addItem(TextUnit(BlockId.SETTINGS_MASK_PROTOCOL_ENC))
block.addItem(BoolUnit(SettingsMaskProtocolEnc.ALLOW_UNENCRYPTED, from.protocolAllowUnencrypted))
block.addItem(BoolUnit(SettingsMaskProtocolEnc.ALLOW_FAST_ENCRYPTION, false))
val block = ListItemBlock(BlockId.SETTINGS_MASK_PROTOCOL_ENC)
block.addItem(TextItem(BlockId.SETTINGS_MASK_PROTOCOL_ENC))
block.addItem(BoolItem(SettingsMaskProtocolEnc.ALLOW_UNENCRYPTED, from.protocolAllowUnencrypted))
block.addItem(BoolItem(SettingsMaskProtocolEnc.ALLOW_FAST_ENCRYPTION, false))
return block
}
private fun settingsMaskNdef(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.SETTINGS_MASK_NDEF)
block.addItem(TextUnit(BlockId.SETTINGS_MASK_NDEF))
block.addItem(BoolUnit(SettingsMaskNdef.USE_NDEF, from.useNDEF))
block.addItem(BoolUnit(SettingsMaskNdef.DYNAMIC_NDEF, from.useDynamicNDEF))
block.addItem(BoolUnit(SettingsMaskNdef.DISABLE_PRECOMPUTED_NDEF, from.disablePrecomputedNDEF))
block.addItem(ListUnit(SettingsMaskNdef.AAR, Helper.aarList(), from.NDEF[0].type))
val block = ListItemBlock(BlockId.SETTINGS_MASK_NDEF)
block.addItem(TextItem(BlockId.SETTINGS_MASK_NDEF))
block.addItem(BoolItem(SettingsMaskNdef.USE_NDEF, from.useNDEF))
block.addItem(BoolItem(SettingsMaskNdef.DYNAMIC_NDEF, from.useDynamicNDEF))
block.addItem(BoolItem(SettingsMaskNdef.DISABLE_PRECOMPUTED_NDEF, from.disablePrecomputedNDEF))
block.addItem(ListItem(SettingsMaskNdef.AAR, Helper.aarList(), from.NDEF[0].type))
return block
}
private fun pins(from: TestJsonDto): Block {
val block = LinearBlock(BlockId.PINS)
block.addItem(TextUnit(BlockId.PINS))
block.addItem(EditTextUnit(Pins.PIN, from.PIN))
block.addItem(EditTextUnit(Pins.PIN2, from.PIN2))
block.addItem(EditTextUnit(Pins.PIN3, from.PIN3))
block.addItem(EditTextUnit(Pins.CVC, from.CVC))
block.addItem(ListUnit(Pins.PAUSE_BEFORE_PIN2, Helper.pauseBeforePin(), from.pauseBeforePIN2))
val block = ListItemBlock(BlockId.PINS)
block.addItem(TextItem(BlockId.PINS))
block.addItem(EditTextItem(Pins.PIN, from.PIN))
block.addItem(EditTextItem(Pins.PIN2, from.PIN2))
block.addItem(EditTextItem(Pins.PIN3, from.PIN3))
block.addItem(EditTextItem(Pins.CVC, from.CVC))
block.addItem(ListItem(Pins.PAUSE_BEFORE_PIN2, Helper.pauseBeforePin(), from.pauseBeforePIN2))
return block
}

View file

@ -1,4 +1,4 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.converter
package com.tangem.tangemtest.card_use_cases.ui.personalize.dto
class TestJsonDto {

View file

@ -1,44 +1,44 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets
import android.view.ViewGroup
import com.tangem.tangemtest._arch.structure.base.Block
import com.tangem.tangemtest._arch.structure.base.DataUnit
import com.tangem.tangemtest._arch.structure.base.Unit
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.impl.*
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.BlockWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.EmptyWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.UnitWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.ViewWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.*
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.abstraction.ViewWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.StubWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.block.LinearBlockWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item.*
class WidgetBuilder {
fun build(unit: Unit, parent: ViewGroup): ViewWidget? {
return when (unit) {
is Block -> buildBlock(unit, parent)
is DataUnit<*> -> buildUnitItem(unit, parent)
else -> EmptyWidget(parent)
fun build(item: Item, parent: ViewGroup): ViewWidget? {
return when (item) {
is Block -> buildBlock(item, parent)
is BaseItem<*> -> buildUnitItem(item, parent)
else -> StubWidget(parent)
}
}
private fun buildBlock(block: Block, parent: ViewGroup): BlockWidget {
private fun buildBlock(block: Block, parent: ViewGroup): ViewWidget {
return when (block) {
is LinearBlock -> {
val linearBlock = LinearBlockWidget(block, parent)
is ListItemBlock -> {
val linearBlock = LinearBlockWidget(parent, block)
block.getItems().forEach { build(it, linearBlock.view as ViewGroup) }
linearBlock
}
else -> EmptyWidget(parent)
else -> StubWidget(parent)
}
}
private fun buildUnitItem(unit: DataUnit<*>, parent: ViewGroup): UnitWidget<*>? {
return when (unit) {
is TextUnit -> TextWidget(parent, unit)
is EditTextUnit -> EditTextWidget(parent, unit)
is NumberUnit -> NumberWidget(parent, unit)
is BoolUnit -> SwitchWidget(parent, unit)
is ListUnit -> SpinnerWidget(parent, unit)
private fun buildUnitItem(item: BaseItem<*>, parent: ViewGroup): ViewWidget? {
return when (item) {
is TextItem -> TextWidget(parent, item)
is EditTextItem -> EditTextWidget(parent, item)
is NumberItem -> NumberWidget(parent, item)
is BoolItem -> SwitchWidget(parent, item)
is ListItem -> SpinnerWidget(parent, item)
else -> null
}
}

View file

@ -0,0 +1,48 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.abstraction
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.abstraction.BaseItem
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
import com.tangem.tangemtest.card_use_cases.resources.MainResourceHolder
import com.tangem.tangemtest.card_use_cases.resources.Resources
import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder
/**
[REDACTED_AUTHOR]
*/
interface ViewWidget : LayoutHolder {
val view: View
}
interface DataWidget<D> : ViewWidget {
var dataItem: BaseItem<D>
}
interface BlockViewWidget : ViewWidget, DataHolder<List<ItemViewModel<*>>>
abstract class BaseWidget<D>(
parent: ViewGroup,
override var dataItem: BaseItem<D>
) : ViewWidget, DataWidget<D> {
override val view: View = inflate(getLayoutId(), parent)
}
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
internal fun inflate(id: Int, parent: ViewGroup): View {
val layoutId = if (id <= 0) R.layout.w_empty else id
val inflatedView = LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
parent.addView(inflatedView)
return inflatedView
}

View file

@ -1,18 +0,0 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base
import android.view.View
import android.view.ViewGroup
import com.tangem.tangemtest.R
import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate
/**
[REDACTED_AUTHOR]
*/
interface BlockWidget : ViewWidget
class EmptyWidget(parent: ViewGroup) : BlockWidget {
override val view: View = parent.inflate(getLayoutId(), parent, false)
override fun getLayoutId(): Int = R.layout.w_empty
}
abstract class BaseBlockWidget<D>(parent: ViewGroup) : BaseViewWidget(parent), BlockWidget

View file

@ -1,37 +0,0 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.base.DataUnit
import com.tangem.tangemtest.card_use_cases.resources.MainResourceHolder
import com.tangem.tangemtest.card_use_cases.resources.Resources
import ru.dev.gbixahue.eu4d.lib.kotlin.common.LayoutHolder
/**
[REDACTED_AUTHOR]
*/
interface ViewWidget : LayoutHolder {
val view: View
}
interface UnitWidget<D> : ViewWidget {
val unit: DataUnit<D>
}
abstract class BaseViewWidget(parent: ViewGroup) : ViewWidget {
override val view: View = inflateView(parent)
private fun inflateView(parent: ViewGroup): View {
var id = getLayoutId()
if (id == -1) id = R.layout.w_empty
val inflatedView = LayoutInflater.from(parent.context).inflate(id, parent, false)
parent.addView(inflatedView)
return inflatedView
}
}
fun UnitWidget<*>.getResNameId(): Int = MainResourceHolder.safeGet<Resources>(unit.id).resName
fun UnitWidget<*>.getResDescription(): Int? = MainResourceHolder.safeGet<Resources>(unit.id).resDescription

View file

@ -1,17 +0,0 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl
import android.view.ViewGroup
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.impl.LinearBlock
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.BaseBlockWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.UnitWidget
/**
[REDACTED_AUTHOR]
*/
class LinearBlockWidget(
private val linearBlock: LinearBlock,
parent: ViewGroup
) : BaseBlockWidget<List<UnitWidget<*>>>(parent) {
override fun getLayoutId(): Int = R.layout.w_personilize_block
}

View file

@ -0,0 +1,11 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl
import android.view.ViewGroup
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.abstraction.BaseBlockWidget
class StubWidget(parent: ViewGroup) : BaseBlockWidget(parent) {
override fun getLayoutId(): Int = R.layout.w_empty
override var viewModel: List<ItemViewModel<*>> = listOf()
}

View file

@ -1,205 +0,0 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.appcompat.widget.SwitchCompat
import androidx.transition.AutoTransition
import androidx.transition.TransitionManager
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.base.DataUnit
import com.tangem.tangemtest._arch.structure.impl.*
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.BaseViewWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.UnitWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.getResDescription
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.base.getResNameId
import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
/**
[REDACTED_AUTHOR]
*/
abstract class BaseUnitWidget<D>(
parent: ViewGroup,
override val unit: DataUnit<D>
) : BaseViewWidget(parent), UnitWidget<D> {
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: ${unit.id}")
getResDescription()?.let { tvDescription?.setText(it) }
unit.viewModel?.viewState?.onDescriptionVisibilityChanged = { changeDescriptionVisibility(it) }
}
private fun changeDescriptionVisibility(state: Int) {
TransitionManager.beginDelayedTransition(view.parent as ViewGroup, AutoTransition())
descriptionContainer.visibility = state
}
}
class TextWidget(parent: ViewGroup, private val textUnit: TextUnit) : BaseUnitWidget<String>(parent, textUnit) {
private val tvName = view.findViewById<TextView>(R.id.tv_name)
init {
tvName.setText(getResNameId())
}
override fun getLayoutId(): Int = R.layout.w_personalize_item_text
}
class EditTextWidget(parent: ViewGroup, private val editTextUnit: EditTextUnit) : BaseUnitWidget<String>(parent, editTextUnit) {
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
private val etItem = view.findViewById<TextInputEditText>(R.id.et_item)
private val watcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
editTextUnit.viewModel?.updateDataByView(stringOf(s))
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
init {
tilItem.hint = tilItem.context.getString(getResNameId())
etItem.setText(editTextUnit.viewModel?.data)
etItem.addTextChangedListener(watcher)
editTextUnit.viewModel?.onDataUpdated = {
etItem.removeTextChangedListener(watcher)
etItem.setText(it)
etItem.addTextChangedListener(watcher)
}
}
override fun getLayoutId(): Int = R.layout.w_personalize_item_edit_text
}
class NumberWidget(parent: ViewGroup, private val numberUnit: NumberUnit) : BaseUnitWidget<Number>(parent, numberUnit) {
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
private val etItem = view.findViewById<TextInputEditText>(R.id.et_item)
private val watcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
numberUnit.viewModel?.updateDataByView(getIntValue(stringOf(s)))
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
init {
tilItem.hint = tilItem.context.getString(getResNameId())
etItem.setText(stringOf(numberUnit.viewModel?.data))
etItem.addTextChangedListener(watcher)
numberUnit.viewModel?.onDataUpdated = {
etItem.removeTextChangedListener(watcher)
etItem.setText(stringOf(it))
etItem.addTextChangedListener(watcher)
}
}
private fun getIntValue(value: String): Number? {
return if (value.isEmpty()) null else value.toInt()
}
override fun getLayoutId(): Int = R.layout.w_personalize_item_number
}
class SwitchWidget(parent: ViewGroup, private val boolUnit: BoolUnit) : BaseUnitWidget<Boolean>(parent, boolUnit) {
private val switchItem = view.findViewById<SwitchCompat>(R.id.sw_item)
private val changeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
boolUnit.viewModel?.updateDataByView(isChecked)
}
init {
switchItem.setText(getResNameId())
switchItem.isChecked = boolUnit.viewModel?.data ?: false
switchItem.setOnCheckedChangeListener(changeListener)
boolUnit.viewModel?.onDataUpdated = {
switchItem.setOnCheckedChangeListener(null)
switchItem.isChecked = it ?: false
switchItem.setOnCheckedChangeListener(changeListener)
}
}
override fun getLayoutId(): Int = R.layout.w_personalize_item_switch
}
class SpinnerWidget(parent: ViewGroup, private val listUnit: ListUnit) : BaseUnitWidget<ListValueWrapper>(parent, listUnit) {
private val spItem = view.findViewById<Spinner>(R.id.sp_item)
private val spAdapter = SpItemAdapter(listUnit.viewModel?.data?.itemList)
private val onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val data = listUnit.viewModel?.data ?: return
data.selectedItem = data.itemList[position]
listUnit.viewModel?.updateDataByView(data)
}
}
init {
val name = view.findViewById<TextView>(R.id.tv_name)
name.setText(getResNameId())
spItem.adapter = spAdapter
spItem.onItemSelectedListener = onItemSelectedListener
listUnit.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
}
}
}
override fun getLayoutId(): Int = R.layout.w_personalize_item_spinner
}
class SpItemAdapter(list: List<KeyValue>?) : BaseAdapter() {
private val itemList: List<KeyValue> = list ?: listOf()
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: parent.inflate(R.layout.vh_sp_item)
val tv = view.findViewById<TextView>(R.id.tv_sp_item)
tv.text = extractData(itemList[position])
return view
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: parent.inflate(R.layout.vh_sp_dropdown_item)
val tv = view.findViewById<TextView>(R.id.tv_sp_item)
tv.text = extractData(itemList[position])
return view
}
private fun extractData(item: KeyValue): String? = item.key
override fun getItem(position: Int): String = stringOf(itemList[position])
override fun getItemId(position: Int): Long = position.toLong()
override fun getCount(): Int = itemList.size
}

View file

@ -0,0 +1,21 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.block
import android.view.ViewGroup
import com.tangem.tangemtest.R
import com.tangem.tangemtest._arch.structure.abstraction.BaseItem
import com.tangem.tangemtest._arch.structure.abstraction.ItemViewModel
import com.tangem.tangemtest._arch.structure.abstraction.ListItemBlock
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.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() = children.itemList.map { it as BaseItem<*> }.map { it.viewModel }
}

View file

@ -0,0 +1,49 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
import android.view.ViewGroup
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.card_use_cases.ui.personalize.widgets.abstraction.BaseWidget
import com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.abstraction.getResDescription
import ru.dev.gbixahue.eu4d.lib.android.global.log.Log
/**
[REDACTED_AUTHOR]
*/
abstract class DescriptionWidget<D>(
parent: ViewGroup,
data: BaseItem<D>
) : BaseWidget<D>(parent, data) {
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}")
initDescriptionWidget()
}
private fun initDescriptionWidget() {
getResDescription()?.let { tvDescription?.setText(it) }
dataItem.viewModel.viewState.onDescriptionVisibilityChanged = { changeDescriptionVisibility(it) }
}
protected fun changeDescriptionVisibility(state: Int) {
TransitionManager.beginDelayedTransition(view.parent as ViewGroup, AutoTransition())
descriptionContainer.visibility = state
}
}

View file

@ -0,0 +1,38 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
import android.text.Editable
import android.text.TextWatcher
import android.view.ViewGroup
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.card_use_cases.ui.personalize.widgets.abstraction.getResNameId
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class EditTextWidget(parent: ViewGroup, data: EditTextItem) : DescriptionWidget<String>(parent, data) {
override fun getLayoutId(): Int = R.layout.w_personalize_item_edit_text
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
private val etItem = view.findViewById<TextInputEditText>(R.id.et_item)
private val watcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
dataItem.viewModel.updateDataByView(stringOf(s))
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
init {
tilItem.hint = tilItem.context.getString(getResNameId())
etItem.setText(dataItem.viewModel.data)
etItem.addTextChangedListener(watcher)
dataItem.viewModel.onDataUpdated = {
etItem.removeTextChangedListener(watcher)
etItem.setText(it)
etItem.addTextChangedListener(watcher)
}
}
}

View file

@ -0,0 +1,43 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
import android.text.Editable
import android.text.TextWatcher
import android.view.ViewGroup
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.card_use_cases.ui.personalize.widgets.abstraction.getResNameId
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class NumberWidget(parent: ViewGroup, data: NumberItem) : DescriptionWidget<Number>(parent, data) {
override fun getLayoutId(): Int = R.layout.w_personalize_item_number
private val tilItem = view.findViewById<TextInputLayout>(R.id.til_item)
private val etItem = view.findViewById<TextInputEditText>(R.id.et_item)
private val watcher = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
dataItem.viewModel.updateDataByView(getIntValue(stringOf(s)))
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
}
init {
tilItem.hint = tilItem.context.getString(getResNameId())
etItem.setText(stringOf(dataItem.viewModel.data))
etItem.addTextChangedListener(watcher)
dataItem.viewModel.onDataUpdated = {
etItem.removeTextChangedListener(watcher)
etItem.setText(stringOf(it))
etItem.addTextChangedListener(watcher)
}
}
private fun getIntValue(value: String): Number? {
return if (value.isEmpty()) null else value.toInt()
}
}

View file

@ -0,0 +1,81 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
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.card_use_cases.ui.personalize.widgets.abstraction.getResNameId
import ru.dev.gbixahue.eu4d.lib.android._android.views.inflate
import ru.dev.gbixahue.eu4d.lib.kotlin.stringOf
class SpinnerWidget(parent: ViewGroup, data: ListItem) : DescriptionWidget<ListValueWrapper>(parent, data) {
override fun getLayoutId(): Int = R.layout.w_personalize_item_spinner
private val spItem = view.findViewById<Spinner>(R.id.sp_item)
private val spAdapter = SpItemAdapter(dataItem.viewModel.data?.itemList)
private val onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val vmData = dataItem.viewModel.data ?: return
vmData.selectedItem = vmData.itemList[position]
dataItem.viewModel.updateDataByView(vmData)
}
}
init {
val name = view.findViewById<TextView>(R.id.tv_name)
name.setText(getResNameId())
spItem.adapter = spAdapter
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
}
}
}
}
class SpItemAdapter(list: List<KeyValue>?) : BaseAdapter() {
private val itemList: List<KeyValue> = list ?: listOf()
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: parent.inflate(R.layout.vh_sp_item)
val tv = view.findViewById<TextView>(R.id.tv_sp_item)
tv.text = extractData(itemList[position])
return view
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: parent.inflate(R.layout.vh_sp_dropdown_item)
val tv = view.findViewById<TextView>(R.id.tv_sp_item)
tv.text = extractData(itemList[position])
return view
}
private fun extractData(item: KeyValue): String? = item.key
override fun getItem(position: Int): String = stringOf(itemList[position])
override fun getItemId(position: Int): Long = position.toLong()
override fun getCount(): Int = itemList.size
}

View file

@ -0,0 +1,29 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
import android.view.ViewGroup
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.card_use_cases.ui.personalize.widgets.abstraction.getResNameId
class SwitchWidget(parent: ViewGroup, data: BoolItem) : DescriptionWidget<Boolean>(parent, data) {
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)
}
init {
switchItem.setText(getResNameId())
switchItem.isChecked = dataItem.viewModel.data ?: false
switchItem.setOnCheckedChangeListener(changeListener)
dataItem.viewModel.onDataUpdated = {
switchItem.setOnCheckedChangeListener(null)
switchItem.isChecked = it ?: false
switchItem.setOnCheckedChangeListener(changeListener)
}
}
}

View file

@ -0,0 +1,17 @@
package com.tangem.tangemtest.card_use_cases.ui.personalize.widgets.impl.item
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.card_use_cases.ui.personalize.widgets.abstraction.getResNameId
class TextWidget(parent: ViewGroup, data: TextItem) : DescriptionWidget<String>(parent, data) {
override fun getLayoutId(): Int = R.layout.w_personalize_item_text
private val tvName = view.findViewById<TextView>(R.id.tv_name)
init {
tvName?.setText(getResNameId())
}
}