Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-03 18:28:14 +05:00
commit 808210b23b
21 changed files with 591 additions and 117 deletions

View file

@ -34,6 +34,12 @@ dependencies {
implementation(projects.domain.appTheme.models)
implementation(projects.domain.card)
implementation(projects.domain.feedback)
implementation(projects.domain.markets.models)
implementation(projects.domain.markets)
implementation(projects.domain.manageTokens.models)
implementation(projects.domain.manageTokens)
implementation(projects.domain.wallets.models)
implementation(projects.domain.wallets)
/** Other libraries */
implementation(deps.arrow.core)
@ -46,9 +52,12 @@ dependencies {
implementation(projects.core.ui)
implementation(projects.core.utils)
implementation(projects.core.navigation)
implementation(projects.core.deepLinks)
implementation(projects.core.pagination)
/** Feature Apis */
implementation(projects.features.tester.api)
implementation(projects.features.pushNotifications.api)
/* SDK */
implementation(tangemDeps.blockchain)

View file

@ -5,9 +5,14 @@ import androidx.compose.ui.text.input.TextFieldValue
interface TestPushClickIntents {
fun onTitleChange(value: TextFieldValue)
fun onMessageChange(value: TextFieldValue)
fun onDataKeyChange(index: Int, value: TextFieldValue)
fun onDataValueChange(index: Int, value: TextFieldValue)
fun onDataAdd()
fun onDataRemove(index: Int)
fun onDeeplinkParamMenu()
fun onBackClick()
fun onSendPush()
}

View file

@ -0,0 +1,13 @@
package com.tangem.feature.tester.presentation.testpush.entity
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.domain.markets.TokenMarket
import kotlinx.collections.immutable.ImmutableList
internal data class TestPushMarketsTokenConfigUM(
val itemList: ImmutableList<TokenMarket>,
val onItemClick: (TokenMarket) -> Unit,
val searchValue: TextFieldValue,
val onSearchValueEdit: (TextFieldValue) -> Unit,
) : TangemBottomSheetConfigContent

View file

@ -0,0 +1,13 @@
package com.tangem.feature.tester.presentation.testpush.entity
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import kotlinx.collections.immutable.ImmutableList
internal data class TestPushMenuConfigUM(
val itemList: ImmutableList<PushMenu>,
val onItemClick: (PushMenu) -> Unit,
) : TangemBottomSheetConfigContent {
enum class PushMenu {
MarketTokenDetails,
}
}

View file

@ -0,0 +1,14 @@
package com.tangem.feature.tester.presentation.testpush.entity
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
import com.tangem.domain.models.network.Network
import kotlinx.collections.immutable.ImmutableList
internal data class TestPushTokenConfigUM(
val itemList: ImmutableList<ManagedCryptoCurrency>,
val onItemClick: (ManagedCryptoCurrency, Network) -> Unit,
val searchValue: TextFieldValue,
val onSearchValueEdit: (TextFieldValue) -> Unit,
) : TangemBottomSheetConfigContent

View file

@ -1,10 +1,12 @@
package com.tangem.feature.tester.presentation.testpush.entity
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
internal data class TestPushUM(
val fcmToken: String,
val title: TextFieldValue,
val message: TextFieldValue,
val data: List<Pair<TextFieldValue, TextFieldValue>>,
val bottomSheetConfig: TangemBottomSheetConfig?,
)

View file

@ -0,0 +1,92 @@
package com.tangem.feature.tester.presentation.testpush.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.OutlineTextField
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMarketsTokenConfigUM
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMenuConfigUM
@Composable
internal fun TestPushDeeplinkBottomSheet(config: TangemBottomSheetConfig?) {
when (config?.content) {
is TestPushMenuConfigUM -> TestPushMenuDeepLinkBottomSheetContent(config)
is TestPushMarketsTokenConfigUM -> TestPushMarketsTokenBottomSheetContent(config)
}
}
@Composable
private fun TestPushMenuDeepLinkBottomSheetContent(config: TangemBottomSheetConfig) {
TangemBottomSheet<TestPushMenuConfigUM>(config) { content ->
LazyColumn {
items(
items = content.itemList.toList(),
key = { it },
itemContent = { item ->
Text(
text = item.name,
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
.fillMaxWidth()
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),
onClick = { content.onItemClick(item) },
)
.padding(16.dp),
)
},
)
}
}
}
@Composable
private fun TestPushMarketsTokenBottomSheetContent(config: TangemBottomSheetConfig) {
TangemBottomSheet<TestPushMarketsTokenConfigUM>(config) { content ->
LazyColumn {
item(key = "Markets Search") {
OutlineTextField(
label = "Title",
value = content.searchValue,
onValueChange = content.onSearchValueEdit,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
items(
items = content.itemList.toList(),
key = { it.id.value },
itemContent = { item ->
Text(
text = "${item.id}: ${item.symbol}",
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
modifier = Modifier
.fillMaxWidth()
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),
onClick = { content.onItemClick(item) },
)
.padding(16.dp),
)
},
)
}
}
}

View file

@ -1,12 +1,6 @@
package com.tangem.feature.tester.presentation.testpush.ui
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context.NOTIFICATION_SERVICE
import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@ -24,7 +18,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.input.TextFieldValue
@ -32,8 +25,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import com.tangem.core.ui.R
import com.tangem.core.ui.components.OutlineTextField
import com.tangem.core.ui.components.PrimaryButton
@ -53,18 +44,27 @@ internal fun TestPushScreen(testPushUM: TestPushUM, testPushClickIntents: TestPu
AppBarWithBackButton(onBackClick = testPushClickIntents::onBackClick)
},
bottomBar = {
SendLocalPushButton(testPushUM)
PrimaryButton(
text = "Send test push",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
onClick = testPushClickIntents::onSendPush,
)
},
containerColor = TangemTheme.colors.background.secondary,
) {
LazyColumn(
modifier = Modifier
.padding(it)
.fillMaxSize(),
) {
tokenData(fcmToken = testPushUM.fcmToken)
contentData(testPushUM = testPushUM, testPushClickIntents = testPushClickIntents)
extraData(testPushUM = testPushUM, testPushClickIntents = testPushClickIntents)
Column {
LazyColumn(
modifier = Modifier
.padding(it)
.fillMaxSize(),
) {
tokenData(fcmToken = testPushUM.fcmToken)
contentData(testPushUM = testPushUM, testPushClickIntents = testPushClickIntents)
extraData(testPushUM = testPushUM, testPushClickIntents = testPushClickIntents)
}
TestPushDeeplinkBottomSheet(testPushUM.bottomSheetConfig)
}
}
}
@ -192,12 +192,23 @@ private fun LazyListScope.extraData(testPushUM: TestPushUM, testPushClickIntents
.padding(top = 8.dp, bottom = 16.dp, start = 16.dp, end = 16.dp)
.animateItem(),
) {
PrimaryButton(
text = "Add param",
onClick = testPushClickIntents::onDataAdd,
size = TangemButtonSize.Action,
Row(
modifier = Modifier.align(Alignment.CenterEnd),
)
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
PrimaryButton(
text = "Get deeplink param",
onClick = testPushClickIntents::onDeeplinkParamMenu,
size = TangemButtonSize.Action,
modifier = Modifier.weight(1f),
)
PrimaryButton(
text = "Add param",
onClick = testPushClickIntents::onDataAdd,
size = TangemButtonSize.Action,
modifier = Modifier.weight(1f),
)
}
}
}
}
@ -275,65 +286,6 @@ private fun EnterPushData(
}
}
@Composable
private fun SendLocalPushButton(testPushUM: TestPushUM) {
val context = LocalContext.current
PrimaryButton(
text = "Send test push",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
onClick = {
val channelId = "Test Tangem Channel"
val intent = Intent(context, Class.forName("com.tangem.tap.MainActivity")).apply {
testPushUM.data.forEach { (key, value) ->
putExtra(key.text, value.text)
}
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
val pendingIntent = PendingIntent.getActivity(
/* context = */ context,
/* requestCode = */ 1,
/* intent = */ intent,
/* flags = */ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,
)
val notificationBuilder =
NotificationCompat.Builder(context.applicationContext, channelId)
.setSmallIcon(com.tangem.feature.tester.impl.R.drawable.ic_tangem_24)
.setContentTitle(testPushUM.title.text)
.setContentText(testPushUM.message.text)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
val notificationManager =
context.applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId,
ContextCompat.getString(
context.applicationContext,
R.string.common_tangem_wallet,
),
NotificationManager.IMPORTANCE_HIGH,
)
notificationManager.createNotificationChannel(notificationChannel)
}
// Generating unique notification id
val uniqueId = (System.currentTimeMillis() % Integer.MAX_VALUE).toInt()
notificationManager.notify(
/* id = */ uniqueId,
/* notification = */ notificationBuilder.build(),
)
},
)
}
// region Preview
@Composable
@Preview(showBackground = true, widthDp = 360)
@ -349,7 +301,9 @@ private fun TestPushScreen_Preview(@PreviewParameter(TestPushScreenPreviewProvid
override fun onDataValueChange(index: Int, value: TextFieldValue) {}
override fun onDataAdd() {}
override fun onDataRemove(index: Int) {}
override fun onDeeplinkParamMenu() {}
override fun onBackClick() {}
override fun onSendPush() {}
},
)
}
@ -366,6 +320,7 @@ private class TestPushScreenPreviewProvider : PreviewParameterProvider<TestPushU
TextFieldValue("deeplink") to TextFieldValue("tangem://main"),
TextFieldValue("") to TextFieldValue(""),
),
bottomSheetConfig = null,
),
)
}

View file

@ -1,40 +1,81 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Context.NOTIFICATION_SERVICE
import android.content.Intent
import android.os.Build
import androidx.compose.ui.text.input.TextFieldValue
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.core.ui.R
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.markets.GetMarketsTokenListFlowUseCase
import com.tangem.domain.markets.TokenListBatchingContext
import com.tangem.domain.markets.TokenMarketListConfig
import com.tangem.domain.markets.TokenMarketUpdateRequest
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
import com.tangem.feature.tester.presentation.testpush.entity.TestPushClickIntents
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMenuConfigUM
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.*
import com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens.TestPushMarketTokenBottomSheetTransformer
import com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens.TestPushMarketTokenClickBottomSheetTransformer
import com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens.TestPushMarketTokenSearchBottomSheetTransformer
import com.tangem.pagination.BatchAction
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import com.tangem.utils.notifications.PushNotificationsTokenProvider
import com.tangem.utils.transformer.update
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
internal class TestPushViewModel @Inject constructor(
private val pushNotificationsTokenProvider: PushNotificationsTokenProvider,
@ApplicationContext private val applicationContext: Context,
private val dispatchers: CoroutineDispatcherProvider,
getMarketsTokenListFlowUseCase: GetMarketsTokenListFlowUseCase,
) : ViewModel(), TestPushClickIntents {
val uiState: StateFlow<TestPushUM>
field = MutableStateFlow(
private val _uiState = MutableStateFlow(
TestPushUM(
fcmToken = "",
title = TextFieldValue(""),
message = TextFieldValue(""),
data = listOf(TextFieldValue("") to TextFieldValue("")),
data = emptyList(),
bottomSheetConfig = null,
),
)
val uiState: StateFlow<TestPushUM>
get() = _uiState.asStateFlow()
private var router: InnerTesterRouter? = null
private val marketsJobHolder = JobHolder()
private val marketsFlow = MutableSharedFlow<BatchAction<Int, TokenMarketListConfig, TokenMarketUpdateRequest>>()
private val marketsLoader = getMarketsTokenListFlowUseCase(
batchingContext = TokenListBatchingContext(
actionsFlow = marketsFlow,
coroutineScope = viewModelScope,
),
batchFlowType = GetMarketsTokenListFlowUseCase.BatchFlowType.Main,
)
init {
viewModelScope.launch {
val fcmToken = pushNotificationsTokenProvider.getToken()
uiState.update { it.copy(fcmToken = fcmToken) }
_uiState.update(TestPushChangeFCMTokenTransformer(fcmToken))
}
}
@ -43,52 +84,159 @@ internal class TestPushViewModel @Inject constructor(
}
override fun onTitleChange(value: TextFieldValue) {
uiState.update { it.copy(title = value) }
_uiState.update(TestPushChangeTitleTransformer(value))
}
override fun onMessageChange(value: TextFieldValue) {
uiState.update { it.copy(message = value) }
_uiState.update(TestPushChangeMessageTransformer(value))
}
override fun onDataKeyChange(index: Int, value: TextFieldValue) {
val mutableData = uiState.value.data.toMutableList()
val updated = mutableData[index].copy(first = value)
mutableData.set(index = index, updated)
uiState.update {
it.copy(data = mutableData)
}
_uiState.update(TestPushAddKeyDataTransformer(index, value))
}
override fun onDataValueChange(index: Int, value: TextFieldValue) {
val mutableData = uiState.value.data.toMutableList()
val updated = mutableData[index].copy(second = value)
mutableData.set(index = index, updated)
uiState.update {
it.copy(data = mutableData)
}
_uiState.update(TestPushAddValueDataTransformer(index, value))
}
override fun onDataAdd() {
uiState.update {
it.copy(
data = it.data.plus(TextFieldValue("") to TextFieldValue("")),
)
}
_uiState.update(TestPushAddDataTransformer)
}
override fun onDataRemove(index: Int) {
uiState.update {
it.copy(
data = it.data.toMutableList().apply {
removeAt(index = index)
},
)
}
_uiState.update(TestPushRemoveDataTransformer(index))
}
override fun onDeeplinkParamMenu() {
_uiState.update(
TestPushMenuTransformer(
dismissBottomSheet = ::dismissBottomSheet,
onDeepLinkParamClick = ::onDeepLinkParamClick,
),
)
}
override fun onBackClick() {
router?.back()
}
override fun onSendPush() {
val value = uiState.value
val channelId = "Test Tangem Channel"
val intent = Intent(applicationContext, Class.forName("com.tangem.tap.MainActivity")).apply {
value.data.forEach { (key, value) ->
putExtra(key.text, value.text)
}
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
val pendingIntent = PendingIntent.getActivity(
/* context = */ applicationContext,
/* requestCode = */ 1,
/* intent = */ intent,
/* flags = */ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,
)
val notificationBuilder =
NotificationCompat.Builder(applicationContext, channelId)
.setSmallIcon(com.tangem.feature.tester.impl.R.drawable.ic_tangem_24)
.setContentTitle(value.title.text)
.setContentText(value.message.text)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
val notificationManager =
applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
channelId,
ContextCompat.getString(
applicationContext,
R.string.common_tangem_wallet,
),
NotificationManager.IMPORTANCE_HIGH,
)
notificationManager.createNotificationChannel(notificationChannel)
}
// Generating unique notification id
val uniqueId = (System.currentTimeMillis() % Integer.MAX_VALUE).toInt()
notificationManager.notify(
/* id = */ uniqueId,
/* notification = */ notificationBuilder.build(),
)
}
private fun dismissBottomSheet() {
marketsJobHolder.cancel()
_uiState.update(TestPushDismissBottomSheetTransformer)
}
private fun onDeepLinkParamClick(item: TestPushMenuConfigUM.PushMenu) {
when (item) {
TestPushMenuConfigUM.PushMenu.MarketTokenDetails -> onMarketsTokenDetailsSheet()
}
}
private fun subscribeMarketTokensList() {
marketsLoader.state.onEach { item ->
_uiState.update(
TestPushMarketTokenBottomSheetTransformer(
item = item.data.flatMap { it.data }.toPersistentList(),
onDismissBottomSheet = ::dismissBottomSheet,
onSearchEdit = {
_uiState.update(
TestPushMarketTokenSearchBottomSheetTransformer(
it,
),
)
onMarketsBatchReload(it.text)
},
onItemClick = {
_uiState.update(
TestPushMarketTokenClickBottomSheetTransformer(
it,
),
)
marketsJobHolder.cancel()
dismissBottomSheet()
},
),
)
}
.flowOn(dispatchers.default)
.launchIn(viewModelScope)
.saveIn(marketsJobHolder)
}
private fun onMarketsTokenDetailsSheet() {
_uiState.update(
TestPushMarketTokenBottomSheetTransformer(
item = persistentListOf(),
onDismissBottomSheet = ::dismissBottomSheet,
onSearchEdit = {},
onItemClick = {},
),
)
subscribeMarketTokensList()
onMarketsBatchReload(searchValue = "")
}
private fun onMarketsBatchReload(searchValue: String) {
viewModelScope.launch {
marketsFlow.emit(
BatchAction.Reload(
requestParams = TokenMarketListConfig(
fiatPriceCurrency = AppCurrency.Default.code,
searchText = searchValue,
priceChangeInterval = TokenMarketListConfig.Interval.H24,
order = TokenMarketListConfig.Order.ByRating,
),
),
)
}
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal object TestPushAddDataTransformer : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(
data = prevState.data.plus(TextFieldValue("") to TextFieldValue("")),
)
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushAddKeyDataTransformer(
private val index: Int,
private val value: TextFieldValue,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
val mutableData = prevState.data.toMutableList()
val updated = mutableData[index].copy(first = value)
mutableData.set(index = index, updated)
return prevState.copy(data = mutableData)
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushAddValueDataTransformer(
private val index: Int,
private val value: TextFieldValue,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
val mutableData = prevState.data.toMutableList()
val updated = mutableData[index].copy(second = value)
mutableData.set(index = index, updated)
return prevState.copy(data = mutableData)
}
}

View file

@ -0,0 +1,12 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushChangeFCMTokenTransformer(
val fcmToken: String,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(fcmToken = fcmToken)
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushChangeMessageTransformer(
val message: TextFieldValue,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(message = message)
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushChangeTitleTransformer(
val title: TextFieldValue,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(title = title)
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal object TestPushDismissBottomSheetTransformer : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(bottomSheetConfig = null)
}
}

View file

@ -0,0 +1,27 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMenuConfigUM
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.persistentListOf
internal class TestPushMenuTransformer(
private val dismissBottomSheet: () -> Unit,
private val onDeepLinkParamClick: (TestPushMenuConfigUM.PushMenu) -> Unit,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(
bottomSheetConfig = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = dismissBottomSheet,
content = TestPushMenuConfigUM(
itemList = persistentListOf(
TestPushMenuConfigUM.PushMenu.MarketTokenDetails,
),
onItemClick = onDeepLinkParamClick,
),
),
)
}
}

View file

@ -0,0 +1,16 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushRemoveDataTransformer(
private val index: Int,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(
data = prevState.data.toMutableList().apply {
removeAt(index = index)
},
)
}
}

View file

@ -0,0 +1,31 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.domain.markets.TokenMarket
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMarketsTokenConfigUM
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.ImmutableList
internal class TestPushMarketTokenBottomSheetTransformer(
private val item: ImmutableList<TokenMarket>,
private val onDismissBottomSheet: () -> Unit,
private val onSearchEdit: (TextFieldValue) -> Unit,
private val onItemClick: (TokenMarket) -> Unit,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(
bottomSheetConfig = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = onDismissBottomSheet,
content = TestPushMarketsTokenConfigUM(
itemList = item,
searchValue = TextFieldValue(""),
onSearchValueEdit = onSearchEdit,
onItemClick = onItemClick,
),
),
)
}
}

View file

@ -0,0 +1,29 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.common.routing.DeepLinkRoute
import com.tangem.core.deeplink.DEEPLINK_KEY
import com.tangem.domain.markets.TokenMarket
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushMarketTokenClickBottomSheetTransformer(
private val tokenMarket: TokenMarket,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
return prevState.copy(
data = prevState.data.plus(
TextFieldValue(DEEPLINK_KEY) to TextFieldValue(
buildString {
append("tangem://")
append(DeepLinkRoute.MarketTokenDetail.host)
append("?token_id=")
append(tokenMarket.id)
append("&token_symbol=")
append(tokenMarket.symbol)
},
),
),
)
}
}

View file

@ -0,0 +1,23 @@
package com.tangem.feature.tester.presentation.testpush.viewmodel.transformers.markettokens
import androidx.compose.ui.text.input.TextFieldValue
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.feature.tester.presentation.testpush.entity.TestPushMarketsTokenConfigUM
import com.tangem.feature.tester.presentation.testpush.entity.TestPushUM
import com.tangem.utils.transformer.Transformer
internal class TestPushMarketTokenSearchBottomSheetTransformer(
private val searchValue: TextFieldValue,
) : Transformer<TestPushUM> {
override fun transform(prevState: TestPushUM): TestPushUM {
val content = prevState.bottomSheetConfig?.content as? TestPushMarketsTokenConfigUM
return prevState.copy(
bottomSheetConfig = prevState.bottomSheetConfig?.copy(
content = content?.copy(
searchValue = searchValue,
) ?: content as TangemBottomSheetConfigContent,
),
)
}
}