Updated on 2026-08-14
This commit is contained in:
parent
3bcb5280fb
commit
7916caacb2
21 changed files with 591 additions and 117 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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?,
|
||||
)
|
||||
|
|
@ -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),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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("")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue