Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-14 15:24:50 +03:00
parent bf329401a1
commit c826afb5c3
3 changed files with 88 additions and 99 deletions

View file

@ -5,12 +5,10 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.fragment.app.Fragment
import androidx.transition.TransitionInflater
import by.kirich1409.viewbindingdelegate.viewBinding
import com.google.accompanist.appcompattheme.AppCompatTheme
@ -22,6 +20,8 @@ import com.tangem.tap.common.extensions.dispatchNotification
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.getString
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.BaseFragment
import com.tangem.tap.features.addBackPressHandler
import com.tangem.tap.features.tokens.redux.ContractAddress
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
import com.tangem.tap.features.tokens.redux.TokensAction
@ -40,8 +40,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.rekotlin.StoreSubscriber
class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
StoreSubscriber<TokensState> {
class AddTokensFragment : BaseFragment(R.layout.fragment_add_tokens), StoreSubscriber<TokensState> {
private val binding: FragmentAddTokensBinding by viewBinding(FragmentAddTokensBinding::bind)
private var tokensState: MutableState<TokensState> = mutableStateOf(store.state.tokensState)
@ -51,33 +50,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
Analytics.send(ManageTokens.ScreenOpened())
activity?.onBackPressedDispatcher?.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
store.dispatch(NavigationAction.PopBackTo())
store.dispatch(TokensAction.ResetState)
}
},
)
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.slide_right)
exitTransition = inflater.inflateTransition(R.transition.fade)
}
override fun onStart() {
super.onStart()
store.subscribe(this) { state ->
state.skipRepeats { oldState, newState ->
oldState.tokensState == newState.tokensState
}.select { it.tokensState }
}
}
override fun onStop() {
super.onStop()
store.unsubscribe(this)
addBackPressHandler(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(binding) {
@ -96,11 +69,7 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
}
val onLoadMore = {
store.dispatch(
TokensAction.LoadMore(
scanResponse = store.state.globalState.scanResponse,
),
)
store.dispatch(TokensAction.LoadMore(scanResponse = store.state.globalState.scanResponse))
}
cvCurrencies.setContent {
@ -115,24 +84,23 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
}
}
override fun newState(state: TokensState) {
if (activity == null || view == null) return
val toolbarTitle =
if (state.allowToAdd) R.string.main_manage_tokens else R.string.search_tokens_title
tokensState.value = state
binding.toolbar.title = getString(toolbarTitle)
override fun onStart() {
super.onStart()
store.subscribe(this) { state ->
state
.skipRepeats { oldState, newState -> oldState.tokensState == newState.tokensState }
.select { it.tokensState }
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_search -> true
R.id.menu_navigate_add_custom_token -> {
Analytics.send(ManageTokens.ButtonCustomToken())
store.dispatch(TokensAction.PrepareAndNavigateToAddCustomToken)
true
}
else -> super.onOptionsItemSelected(item)
}
override fun onStop() {
super.onStop()
store.unsubscribe(this)
}
override fun onDestroy() {
store.dispatch(TokensAction.ResetState)
super.onDestroy()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -156,25 +124,50 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens),
return super.onCreateOptionsMenu(menu, inflater)
}
override fun onDestroy() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_search -> true
R.id.menu_navigate_add_custom_token -> {
Analytics.send(ManageTokens.ButtonCustomToken())
store.dispatch(TokensAction.PrepareAndNavigateToAddCustomToken)
true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun configureTransitions() {
super.configureTransitions()
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.slide_right)
exitTransition = inflater.inflateTransition(R.transition.fade)
}
override fun handleOnBackPressed() {
super.handleOnBackPressed()
store.dispatch(NavigationAction.PopBackTo())
store.dispatch(TokensAction.ResetState)
super.onDestroy()
}
override fun newState(state: TokensState) {
if (activity == null || view == null) return
val toolbarTitle =
if (state.allowToAdd) R.string.main_manage_tokens else R.string.search_tokens_title
tokensState.value = state
binding.toolbar.title = getString(toolbarTitle)
}
}
fun SearchView.inputtedTextAsFlow(): Flow<String> = callbackFlow {
val watcher =
setOnQueryTextListener(
object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
val watcher = setOnQueryTextListener(
object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean = false
override fun onQueryTextChange(newText: String?): Boolean {
trySend(newText ?: "")
return false
}
},
)
override fun onQueryTextChange(newText: String?): Boolean {
trySend(newText ?: "")
return false
}
},
)
awaitClose { (watcher) }
}

View file

@ -83,25 +83,21 @@ fun CurrenciesScreen(
Scaffold(
floatingActionButton = {
if (tokensState.value.allowToAdd) SaveChangesButton(isKeyboardOpen) {
onSaveChanges(addedTokensState.value, addedBlockchainsState.value)
if (tokensState.value.allowToAdd) {
SaveChangesButton(isKeyboardOpen) {
onSaveChanges(addedTokensState.value, addedBlockchainsState.value)
}
}
},
floatingActionButtonPosition = FabPosition.Center,
) {
AnimatedVisibility(
visible = tokensState.value.loadCoinsState == LoadCoinsState.LOADING,
enter = fadeIn(),
exit = fadeOut(),
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize(),
) {
CircularProgressIndicator(
color = Color(0xFF1ACE80),
)
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator(color = Color(0xFF1ACE80))
}
}
AnimatedVisibility(
@ -148,21 +144,19 @@ private fun toggleBlockchain(
currencySymbol = blockchain.currency,
),
)
} else if (isAddedOnMainScreen) {
store.dispatchDialogShow(
WalletDialog.RemoveWalletDialog(
currencyTitle = blockchain.name,
onOk = {
analyticsCurrencyTypeParam.sendOn()
addedBlockchainsState.removeAndNotify(blockchain)
},
),
)
} else {
if (isAddedOnMainScreen) {
store.dispatchDialogShow(
WalletDialog.RemoveWalletDialog(
currencyTitle = blockchain.name,
onOk = {
analyticsCurrencyTypeParam.sendOn()
addedBlockchainsState.removeAndNotify(blockchain)
},
),
)
} else {
analyticsCurrencyTypeParam.sendOff()
addedBlockchainsState.removeAndNotify(blockchain)
}
analyticsCurrencyTypeParam.sendOff()
addedBlockchainsState.removeAndNotify(blockchain)
}
} else {
analyticsCurrencyTypeParam.sendOn()

View file

@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.blockchain.common.Blockchain
import com.tangem.tap.domain.tokens.Contract
import com.tangem.tap.domain.tokens.Currency
import com.tangem.tap.features.tokens.redux.ContractAddress
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
@ -30,22 +31,20 @@ fun CurrencyExpandedContent(
exit = fadeOut() + shrinkVertically(),
) {
val blockchains = currency.contracts.map { it.blockchain }
Column(
modifier = Modifier
.fillMaxWidth(),
) {
Column(modifier = Modifier.fillMaxWidth()) {
blockchains.mapIndexed { index, blockchain ->
val contract = currency.contracts.firstOrNull { it.blockchain == blockchain }
val currencyContract = currency.contracts
.firstOrNull { it.blockchain == blockchain }
?: return@mapIndexed
val added = if (contract.address != null) {
addedTokens.map { it.token.contractAddress }.contains(contract.address)
val added = if (currencyContract.address != null) {
addedTokens.any(currencyContract::isInclude)
} else {
addedBlockchains.contains(blockchain)
}
NetworkItem(
currency = currency,
contract = contract,
contract = currencyContract,
blockchain = blockchain,
allowToAdd = allowToAdd,
added = added,
@ -57,4 +56,7 @@ fun CurrencyExpandedContent(
}
}
}
}
}
private fun Contract.isInclude(addedToken: TokenWithBlockchain): Boolean =
address == addedToken.token.contractAddress && blockchain == addedToken.blockchain