mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-04-24 11:17:56 +00:00
Initial commit: Pezkuwi Wallet Android
Complete rebrand of Nova Wallet for Pezkuwichain ecosystem. ## Features - Full Pezkuwichain support (HEZ & PEZ tokens) - Polkadot ecosystem compatibility - Staking, Governance, DeFi, NFTs - XCM cross-chain transfers - Hardware wallet support (Ledger, Polkadot Vault) - WalletConnect v2 - Push notifications ## Languages - English, Turkish, Kurmanci (Kurdish), Spanish, French, German, Russian, Japanese, Chinese, Korean, Portuguese, Vietnamese Based on Nova Wallet by Novasama Technologies GmbH © Dijital Kurdistan Tech Institute 2026
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.data.datasource
|
||||
|
||||
import com.google.gson.Gson
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.common.utils.fromJson
|
||||
import io.novafoundation.nova.feature_currency_impl.R
|
||||
|
||||
class AssetsCurrencyRemoteDataSource(
|
||||
private val resourceManager: ResourceManager,
|
||||
private val gson: Gson
|
||||
) : CurrencyRemoteDataSource {
|
||||
|
||||
override suspend fun getCurrenciesRemote(): List<CurrencyRemote> {
|
||||
val rawCurrencies = resourceManager.loadRawString(R.raw.currencies)
|
||||
|
||||
return gson.fromJson(rawCurrencies)
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.data.datasource
|
||||
|
||||
import io.novafoundation.nova.core_db.model.CurrencyLocal
|
||||
|
||||
class CurrencyRemote(
|
||||
val code: String,
|
||||
val name: String,
|
||||
val symbol: String?,
|
||||
val category: String,
|
||||
val popular: Boolean,
|
||||
val id: Int,
|
||||
val coingeckoId: String,
|
||||
)
|
||||
|
||||
fun mapRemoteCurrencyToLocal(remote: CurrencyRemote, selected: Boolean): CurrencyLocal {
|
||||
return with(remote) {
|
||||
CurrencyLocal(
|
||||
code = code,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
category = mapRemoteCurrencyCategoryToLocal(category),
|
||||
popular = popular,
|
||||
id = id,
|
||||
coingeckoId = coingeckoId,
|
||||
selected = selected,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapRemoteCurrencyCategoryToLocal(remote: String): CurrencyLocal.Category {
|
||||
return when (remote) {
|
||||
"fiat" -> CurrencyLocal.Category.FIAT
|
||||
"crypto" -> CurrencyLocal.Category.CRYPTO
|
||||
else -> throw IllegalArgumentException("Unknown currency category: $remote")
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.data.datasource
|
||||
|
||||
interface CurrencyRemoteDataSource {
|
||||
|
||||
suspend fun getCurrenciesRemote(): List<CurrencyRemote>
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.data.repository
|
||||
|
||||
import io.novafoundation.nova.common.utils.CollectionDiffer
|
||||
import io.novafoundation.nova.core_db.dao.CurrencyDao
|
||||
import io.novafoundation.nova.feature_currency_impl.data.datasource.CurrencyRemoteDataSource
|
||||
import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository
|
||||
import io.novafoundation.nova.feature_currency_api.domain.model.Currency
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.mapper.mapCurrencyFromLocal
|
||||
import io.novafoundation.nova.feature_currency_impl.data.datasource.mapRemoteCurrencyToLocal
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class RealCurrencyRepository(
|
||||
private val currencyDao: CurrencyDao,
|
||||
private val currencyRemoteDataSource: CurrencyRemoteDataSource,
|
||||
) : CurrencyRepository {
|
||||
|
||||
override suspend fun syncCurrencies() {
|
||||
val selectedCurrency = currencyDao.getSelectedCurrency()
|
||||
val remoteCurrencies = currencyRemoteDataSource.getCurrenciesRemote()
|
||||
val newCurrencies = remoteCurrencies.map { mapRemoteCurrencyToLocal(it, selectedCurrency?.id == it.id) }
|
||||
val oldCurrencies = currencyDao.getCurrencies()
|
||||
val resultCurrencies = CollectionDiffer.findDiff(newCurrencies, oldCurrencies, false)
|
||||
currencyDao.updateCurrencies(resultCurrencies)
|
||||
}
|
||||
|
||||
override fun observeCurrencies(): Flow<List<Currency>> {
|
||||
return currencyDao.observeCurrencies()
|
||||
.map { currencyList -> currencyList.map { mapCurrencyFromLocal(it) } }
|
||||
}
|
||||
|
||||
override fun observeSelectCurrency(): Flow<Currency> {
|
||||
return currencyDao.observeSelectCurrency()
|
||||
.map { mapCurrencyFromLocal(it) }
|
||||
}
|
||||
|
||||
override suspend fun selectCurrency(currencyId: Int) {
|
||||
currencyDao.selectCurrency(currencyId)
|
||||
}
|
||||
|
||||
override suspend fun getSelectedCurrency(): Currency {
|
||||
val selectedCurrency = currencyDao.getSelectedCurrency()?.let { mapCurrencyFromLocal(it) }
|
||||
return selectedCurrency ?: throw IllegalArgumentException("No currency selected")
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
import io.novafoundation.nova.common.di.CommonApi
|
||||
import io.novafoundation.nova.common.di.scope.FeatureScope
|
||||
import io.novafoundation.nova.core_db.di.DbApi
|
||||
import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.CurrencyRouter
|
||||
import io.novafoundation.nova.runtime.di.RuntimeApi
|
||||
|
||||
@Component(
|
||||
dependencies = [
|
||||
CurrencyFeatureDependencies::class
|
||||
],
|
||||
modules = [
|
||||
CurrencyFeatureModule::class
|
||||
]
|
||||
)
|
||||
@FeatureScope
|
||||
interface CurrencyFeatureComponent : CurrencyFeatureApi {
|
||||
|
||||
fun selectCurrencyComponentFactory(): SelectCurrencyComponent.Factory
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
|
||||
fun create(
|
||||
@BindsInstance walletRouter: CurrencyRouter,
|
||||
deps: CurrencyFeatureDependencies
|
||||
): CurrencyFeatureComponent
|
||||
}
|
||||
|
||||
@Component(
|
||||
dependencies = [
|
||||
CommonApi::class,
|
||||
DbApi::class,
|
||||
RuntimeApi::class
|
||||
]
|
||||
)
|
||||
interface CurrencyFeatureDependenciesComponent : CurrencyFeatureDependencies
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import com.google.gson.Gson
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.core_db.dao.CurrencyDao
|
||||
|
||||
interface CurrencyFeatureDependencies {
|
||||
fun resourceManager(): ResourceManager
|
||||
|
||||
fun currencyDao(): CurrencyDao
|
||||
|
||||
fun jsonMapper(): Gson
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import io.novafoundation.nova.common.di.FeatureApiHolder
|
||||
import io.novafoundation.nova.common.di.FeatureContainer
|
||||
import io.novafoundation.nova.common.di.scope.ApplicationScope
|
||||
import io.novafoundation.nova.core_db.di.DbApi
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.CurrencyRouter
|
||||
import io.novafoundation.nova.runtime.di.RuntimeApi
|
||||
import javax.inject.Inject
|
||||
|
||||
@ApplicationScope
|
||||
class CurrencyFeatureHolder @Inject constructor(
|
||||
featureContainer: FeatureContainer,
|
||||
val currencyRouter: CurrencyRouter
|
||||
) : FeatureApiHolder(featureContainer) {
|
||||
|
||||
override fun initializeDependencies(): Any {
|
||||
val dependencies = DaggerCurrencyFeatureComponent_CurrencyFeatureDependenciesComponent.builder()
|
||||
.commonApi(commonApi())
|
||||
.dbApi(getFeature(DbApi::class.java))
|
||||
.runtimeApi(getFeature(RuntimeApi::class.java))
|
||||
.build()
|
||||
return DaggerCurrencyFeatureComponent.factory()
|
||||
.create(currencyRouter, dependencies)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import com.google.gson.Gson
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import io.novafoundation.nova.common.di.scope.FeatureScope
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.core_db.dao.CurrencyDao
|
||||
import io.novafoundation.nova.feature_currency_impl.data.datasource.CurrencyRemoteDataSource
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor
|
||||
import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository
|
||||
import io.novafoundation.nova.feature_currency_impl.data.datasource.AssetsCurrencyRemoteDataSource
|
||||
import io.novafoundation.nova.feature_currency_impl.data.repository.RealCurrencyRepository
|
||||
import io.novafoundation.nova.feature_currency_impl.domain.CurrencyInteractorImpl
|
||||
|
||||
@Module
|
||||
class CurrencyFeatureModule {
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideCurrencyRemoteDataSource(
|
||||
resourceManager: ResourceManager,
|
||||
gson: Gson
|
||||
): CurrencyRemoteDataSource {
|
||||
return AssetsCurrencyRemoteDataSource(resourceManager, gson)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideCurrencyRepository(
|
||||
currencyDao: CurrencyDao,
|
||||
currencyRemoteDataSource: CurrencyRemoteDataSource
|
||||
): CurrencyRepository {
|
||||
return RealCurrencyRepository(currencyDao, currencyRemoteDataSource)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FeatureScope
|
||||
fun provideCurrencyInteractor(currencyRepository: CurrencyRepository): CurrencyInteractor {
|
||||
return CurrencyInteractorImpl(currencyRepository)
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import dagger.BindsInstance
|
||||
import dagger.Subcomponent
|
||||
import io.novafoundation.nova.common.di.scope.ScreenScope
|
||||
import io.novafoundation.nova.feature_currency_impl.presentation.currency.SelectCurrencyFragment
|
||||
|
||||
@Subcomponent(
|
||||
modules = [
|
||||
SelectCurrencyModule::class
|
||||
]
|
||||
)
|
||||
@ScreenScope
|
||||
interface SelectCurrencyComponent {
|
||||
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
|
||||
fun create(
|
||||
@BindsInstance fragment: Fragment
|
||||
): SelectCurrencyComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: SelectCurrencyFragment)
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.di
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.IntoMap
|
||||
import io.novafoundation.nova.common.di.viewmodel.ViewModelKey
|
||||
import io.novafoundation.nova.common.di.viewmodel.ViewModelModule
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.CurrencyRouter
|
||||
import io.novafoundation.nova.feature_currency_impl.presentation.currency.SelectCurrencyViewModel
|
||||
|
||||
@Module(includes = [ViewModelModule::class])
|
||||
class SelectCurrencyModule {
|
||||
|
||||
@Provides
|
||||
@IntoMap
|
||||
@ViewModelKey(SelectCurrencyViewModel::class)
|
||||
fun provideViewModel(
|
||||
currencyInteractor: CurrencyInteractor,
|
||||
resourceManager: ResourceManager,
|
||||
walletRouter: CurrencyRouter
|
||||
): ViewModel {
|
||||
return SelectCurrencyViewModel(
|
||||
currencyInteractor,
|
||||
resourceManager,
|
||||
walletRouter
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideViewModelCreator(
|
||||
fragment: Fragment,
|
||||
viewModelFactory: ViewModelProvider.Factory
|
||||
): SelectCurrencyViewModel {
|
||||
return ViewModelProvider(fragment, viewModelFactory).get(SelectCurrencyViewModel::class.java)
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.domain
|
||||
|
||||
import io.novafoundation.nova.common.list.GroupedList
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyCategory
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor
|
||||
import io.novafoundation.nova.feature_currency_api.domain.interfaces.CurrencyRepository
|
||||
import io.novafoundation.nova.feature_currency_api.domain.model.Currency
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class CurrencyInteractorImpl(
|
||||
private val currencyRepository: CurrencyRepository
|
||||
) : CurrencyInteractor {
|
||||
override suspend fun syncCurrencies() {
|
||||
currencyRepository.syncCurrencies()
|
||||
}
|
||||
|
||||
override fun observeCurrencies(): Flow<GroupedList<CurrencyCategory, Currency>> {
|
||||
return currencyRepository.observeCurrencies().map { list ->
|
||||
list.groupBy { mapCurrencyCategory(it) }
|
||||
.toSortedMap(getCurrencyCategoryComparator())
|
||||
}
|
||||
}
|
||||
|
||||
override fun observeSelectCurrency(): Flow<Currency> {
|
||||
return currencyRepository.observeSelectCurrency()
|
||||
}
|
||||
|
||||
override suspend fun getSelectedCurrency(): Currency {
|
||||
return currencyRepository.getSelectedCurrency()
|
||||
}
|
||||
|
||||
override suspend fun selectCurrency(currencyId: Int) {
|
||||
currencyRepository.selectCurrency(currencyId)
|
||||
}
|
||||
|
||||
private fun getCurrencyCategoryComparator() = compareBy<CurrencyCategory> {
|
||||
when (it) {
|
||||
CurrencyCategory.CRYPTO -> 0
|
||||
CurrencyCategory.FIAT_POPULAR -> 1
|
||||
CurrencyCategory.FIAT -> 2
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapCurrencyCategory(category: Currency): CurrencyCategory {
|
||||
return when (category.category) {
|
||||
Currency.Category.CRYPTO -> CurrencyCategory.CRYPTO
|
||||
Currency.Category.FIAT -> {
|
||||
if (category.popular) {
|
||||
CurrencyCategory.FIAT_POPULAR
|
||||
} else {
|
||||
CurrencyCategory.FIAT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.presentation.currency
|
||||
|
||||
import android.view.ViewGroup
|
||||
import io.novafoundation.nova.common.list.BaseGroupedDiffCallback
|
||||
import io.novafoundation.nova.common.list.GroupedListAdapter
|
||||
import io.novafoundation.nova.common.list.GroupedListHolder
|
||||
import io.novafoundation.nova.common.list.headers.TextHeader
|
||||
import io.novafoundation.nova.common.utils.inflater
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.model.CurrencyModel
|
||||
import io.novafoundation.nova.feature_currency_impl.databinding.ItemCurrencyBinding
|
||||
import io.novafoundation.nova.feature_currency_impl.databinding.ItemCurrencyTypeBinding
|
||||
|
||||
class CurrencyAdapter(
|
||||
private val handler: Handler
|
||||
) : GroupedListAdapter<TextHeader, CurrencyModel>(DiffCallback) {
|
||||
|
||||
interface Handler {
|
||||
fun itemClicked(currency: CurrencyModel)
|
||||
}
|
||||
|
||||
override fun createGroupViewHolder(parent: ViewGroup): GroupedListHolder {
|
||||
return CurrencyTypeHolder(ItemCurrencyTypeBinding.inflate(parent.inflater(), parent, false))
|
||||
}
|
||||
|
||||
override fun createChildViewHolder(parent: ViewGroup): GroupedListHolder {
|
||||
return CurrencyHolder(ItemCurrencyBinding.inflate(parent.inflater(), parent, false), handler)
|
||||
}
|
||||
|
||||
override fun bindGroup(holder: GroupedListHolder, group: TextHeader) {
|
||||
(holder as CurrencyTypeHolder).bind(group)
|
||||
}
|
||||
|
||||
override fun bindChild(holder: GroupedListHolder, child: CurrencyModel) {
|
||||
(holder as CurrencyHolder).bind(child)
|
||||
}
|
||||
}
|
||||
|
||||
private object DiffCallback : BaseGroupedDiffCallback<TextHeader, CurrencyModel>(TextHeader::class.java) {
|
||||
|
||||
override fun areGroupItemsTheSame(oldItem: TextHeader, newItem: TextHeader): Boolean {
|
||||
return TextHeader.DIFF_CALLBACK.areItemsTheSame(oldItem, newItem)
|
||||
}
|
||||
|
||||
override fun areGroupContentsTheSame(oldItem: TextHeader, newItem: TextHeader): Boolean {
|
||||
return TextHeader.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||
}
|
||||
|
||||
override fun areChildItemsTheSame(oldItem: CurrencyModel, newItem: CurrencyModel): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areChildContentsTheSame(oldItem: CurrencyModel, newItem: CurrencyModel): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
||||
private class CurrencyTypeHolder(private val binder: ItemCurrencyTypeBinding) : GroupedListHolder(binder.root) {
|
||||
|
||||
fun bind(item: TextHeader) {
|
||||
binder.itemCurrencyType.text = item.content
|
||||
}
|
||||
}
|
||||
|
||||
private class CurrencyHolder(
|
||||
private val binder: ItemCurrencyBinding,
|
||||
private val itemHandler: CurrencyAdapter.Handler
|
||||
) : GroupedListHolder(binder.root) {
|
||||
|
||||
fun bind(item: CurrencyModel) = with(binder) {
|
||||
itemCurrencySign.text = item.displayCode
|
||||
|
||||
bindTitle(item)
|
||||
itemCurrencyAbbreviation.text = item.code
|
||||
|
||||
itemCurrencyName.text = item.name
|
||||
itemCurrencyCheck.isChecked = item.isSelected
|
||||
bindClick(item)
|
||||
}
|
||||
|
||||
fun bindTitle(item: CurrencyModel) = with(containerView) {
|
||||
binder.itemCurrencyName.text = item.name
|
||||
}
|
||||
|
||||
private fun bindClick(item: CurrencyModel) = with(containerView) {
|
||||
setOnClickListener { itemHandler.itemClicked(item) }
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.presentation.currency
|
||||
|
||||
import io.novafoundation.nova.common.base.BaseFragment
|
||||
import io.novafoundation.nova.common.di.FeatureUtils
|
||||
import io.novafoundation.nova.feature_currency_api.di.CurrencyFeatureApi
|
||||
import io.novafoundation.nova.feature_currency_impl.databinding.FragmentSelectCurrencyBinding
|
||||
import io.novafoundation.nova.feature_currency_impl.di.CurrencyFeatureComponent
|
||||
|
||||
class SelectCurrencyFragment : BaseFragment<SelectCurrencyViewModel, FragmentSelectCurrencyBinding>(), CurrencyAdapter.Handler {
|
||||
|
||||
override fun createBinding() = FragmentSelectCurrencyBinding.inflate(layoutInflater)
|
||||
|
||||
private val adapter = CurrencyAdapter(this)
|
||||
|
||||
override fun initViews() {
|
||||
binder.currencyList.adapter = adapter
|
||||
|
||||
binder.currencyToolbar.setHomeButtonListener {
|
||||
viewModel.backClicked()
|
||||
}
|
||||
}
|
||||
|
||||
override fun inject() {
|
||||
FeatureUtils.getFeature<CurrencyFeatureComponent>(
|
||||
requireContext(),
|
||||
CurrencyFeatureApi::class.java
|
||||
).selectCurrencyComponentFactory()
|
||||
.create(this)
|
||||
.inject(this)
|
||||
}
|
||||
|
||||
override fun subscribe(viewModel: SelectCurrencyViewModel) {
|
||||
viewModel.currencyModels.observe {
|
||||
adapter.submitList(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun itemClicked(currency: io.novafoundation.nova.feature_currency_api.presentation.model.CurrencyModel) {
|
||||
viewModel.selectCurrency(currency)
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package io.novafoundation.nova.feature_currency_impl.presentation.currency
|
||||
|
||||
import io.novafoundation.nova.common.base.BaseViewModel
|
||||
import io.novafoundation.nova.common.list.headers.TextHeader
|
||||
import io.novafoundation.nova.common.list.toListWithHeaders
|
||||
import io.novafoundation.nova.common.resources.ResourceManager
|
||||
import io.novafoundation.nova.common.utils.inBackground
|
||||
import io.novafoundation.nova.feature_currency_api.domain.CurrencyCategory
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.CurrencyRouter
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.mapper.mapCurrencyToUI
|
||||
import io.novafoundation.nova.feature_currency_api.presentation.model.CurrencyModel
|
||||
import io.novafoundation.nova.feature_currency_impl.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class SelectCurrencyViewModel(
|
||||
private val currencyInteractor: io.novafoundation.nova.feature_currency_api.domain.CurrencyInteractor,
|
||||
private val resourceManager: ResourceManager,
|
||||
private val router: CurrencyRouter,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val currencies = currencyInteractor.observeCurrencies()
|
||||
.inBackground()
|
||||
.share()
|
||||
|
||||
val currencyModels = currencies.map { groupedList ->
|
||||
groupedList.toListWithHeaders(
|
||||
keyMapper = { category, _ -> mapCurrencyCategoryToUI(category) },
|
||||
valueMapper = { mapCurrencyToUI(it) }
|
||||
)
|
||||
}
|
||||
.inBackground()
|
||||
.share()
|
||||
|
||||
private fun mapCurrencyCategoryToUI(category: CurrencyCategory): TextHeader {
|
||||
return TextHeader(
|
||||
when (category) {
|
||||
CurrencyCategory.CRYPTO -> resourceManager.getString(R.string.wallet_currency_category_cryptocurrencies)
|
||||
CurrencyCategory.FIAT -> resourceManager.getString(R.string.wallet_currency_category_fiat)
|
||||
CurrencyCategory.FIAT_POPULAR -> resourceManager.getString(R.string.wallet_currency_category_popular_fiat)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun selectCurrency(currency: CurrencyModel) {
|
||||
launch {
|
||||
withContext(Dispatchers.IO) { currencyInteractor.selectCurrency(currency.id) }
|
||||
router.returnToWallet()
|
||||
}
|
||||
}
|
||||
|
||||
fun backClicked() {
|
||||
router.back()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
android:orientation="vertical">
|
||||
|
||||
<io.novafoundation.nova.common.view.Toolbar
|
||||
android:id="@+id/currencyToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:dividerVisible="false"
|
||||
app:titleText="@string/wallet_currency_title" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/currencyList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="42dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
tools:background="@color/secondary_screen_background">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemCurrencySign"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_currency"
|
||||
android:ellipsize="none"
|
||||
android:gravity="center"
|
||||
android:lines="1"
|
||||
android:minWidth="40dp"
|
||||
android:minHeight="28dp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="$" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="9dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/itemCurrencyCheck"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemCurrencySign"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemCurrencyAbbreviation"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.SubHeadline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="@color/text_primary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="USD" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemCurrencyName"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.Footnote"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="United States Dollar" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/itemCurrencyCheck"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:buttonTint="@color/tint_radio_button"
|
||||
android:clickable="false"
|
||||
android:duplicateParentState="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/itemCurrencyType"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.Footnote"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="@color/text_secondary"
|
||||
tools:background="@color/secondary_screen_background"
|
||||
tools:text="Cryptocurrencies" />
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
[
|
||||
{
|
||||
"code": "USD",
|
||||
"name": "United States Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 0,
|
||||
"coingeckoId": "usd"
|
||||
},
|
||||
{
|
||||
"code": "EUR",
|
||||
"name": "Euro",
|
||||
"symbol": "€",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 1,
|
||||
"coingeckoId": "eur"
|
||||
},
|
||||
{
|
||||
"code": "JPY",
|
||||
"name": "Japanese Yen",
|
||||
"symbol": "¥",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 2,
|
||||
"coingeckoId": "jpy"
|
||||
},
|
||||
{
|
||||
"code": "CNY",
|
||||
"name": "Chinese Yuan",
|
||||
"symbol": "¥",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 3,
|
||||
"coingeckoId": "cny"
|
||||
},
|
||||
{
|
||||
"code": "TWD",
|
||||
"name": "New Taiwan dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 4,
|
||||
"coingeckoId": "twd"
|
||||
},
|
||||
{
|
||||
"code": "RUB",
|
||||
"name": "Russian Ruble",
|
||||
"symbol": "₽",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 5,
|
||||
"coingeckoId": "rub"
|
||||
},
|
||||
{
|
||||
"code": "AED",
|
||||
"name": "United Arab Emirates dirham",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 6,
|
||||
"coingeckoId": "aed"
|
||||
},
|
||||
{
|
||||
"code": "IDR",
|
||||
"name": "Indonesian Rupiah",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 7,
|
||||
"coingeckoId": "idr"
|
||||
},
|
||||
{
|
||||
"code": "KRW",
|
||||
"name": "South Korean won",
|
||||
"symbol": "₩",
|
||||
"category": "fiat",
|
||||
"popular": true,
|
||||
"id": 8,
|
||||
"coingeckoId": "krw"
|
||||
},
|
||||
{
|
||||
"code": "ARS",
|
||||
"name": "Argentine Peso",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 9,
|
||||
"coingeckoId": "ars"
|
||||
},
|
||||
{
|
||||
"code": "AUD",
|
||||
"name": "Australian Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 10,
|
||||
"coingeckoId": "aud"
|
||||
},
|
||||
{
|
||||
"code": "BDT",
|
||||
"name": "Bangladeshi Taka",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 11,
|
||||
"coingeckoId": "bdt"
|
||||
},
|
||||
{
|
||||
"code": "BHD",
|
||||
"name": "Bahraini Dinar",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 12,
|
||||
"coingeckoId": "bhd"
|
||||
},
|
||||
{
|
||||
"code": "BMD",
|
||||
"name": "Bermudan Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 13,
|
||||
"coingeckoId": "bmd"
|
||||
},
|
||||
{
|
||||
"code": "BRL",
|
||||
"name": "Brazilian Real",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 14,
|
||||
"coingeckoId": "brl"
|
||||
},
|
||||
{
|
||||
"code": "CAD",
|
||||
"name": "Canadian Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 15,
|
||||
"coingeckoId": "cad"
|
||||
},
|
||||
{
|
||||
"code": "CHF",
|
||||
"name": "Swiss Franc",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 16,
|
||||
"coingeckoId": "chf"
|
||||
},
|
||||
{
|
||||
"code": "CLP",
|
||||
"name": "Chilean Peso",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 17,
|
||||
"coingeckoId": "clp"
|
||||
},
|
||||
{
|
||||
"code": "CZK",
|
||||
"name": "Czech Koruna",
|
||||
"symbol": "Kč",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 18,
|
||||
"coingeckoId": "czk"
|
||||
},
|
||||
{
|
||||
"code": "DKK",
|
||||
"name": "Danish Krone",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 19,
|
||||
"coingeckoId": "dkk"
|
||||
},
|
||||
{
|
||||
"code": "GBP",
|
||||
"name": "British Pound Sterling",
|
||||
"symbol": "£",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 20,
|
||||
"coingeckoId": "gbp"
|
||||
},
|
||||
{
|
||||
"code": "HKD",
|
||||
"name": "Hong Kong Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 21,
|
||||
"coingeckoId": "hkd"
|
||||
},
|
||||
{
|
||||
"code": "HUF",
|
||||
"name": "Hungarian Forint",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 22,
|
||||
"coingeckoId": "huf"
|
||||
},
|
||||
{
|
||||
"code": "ILS",
|
||||
"name": "Israeli New Shekel",
|
||||
"symbol": "₪",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 23,
|
||||
"coingeckoId": "ils"
|
||||
},
|
||||
{
|
||||
"code": "INR",
|
||||
"name": "Indian Rupee",
|
||||
"symbol": "₹",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 24,
|
||||
"coingeckoId": "inr"
|
||||
},
|
||||
{
|
||||
"code": "LKR",
|
||||
"name": "Sri Lankan Rupee",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 26,
|
||||
"coingeckoId": "lkr"
|
||||
},
|
||||
{
|
||||
"code": "MMK",
|
||||
"name": "Myanmar Kyat",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 27,
|
||||
"coingeckoId": "mmk"
|
||||
},
|
||||
{
|
||||
"code": "MXN",
|
||||
"name": "Mexican Peso",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 28,
|
||||
"coingeckoId": "mxn"
|
||||
},
|
||||
{
|
||||
"code": "MYR",
|
||||
"name": "Malaysian Ringgit",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 29,
|
||||
"coingeckoId": "myr"
|
||||
},
|
||||
{
|
||||
"code": "NGN",
|
||||
"name": "Nigerian Naira",
|
||||
"symbol": "₦",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 30,
|
||||
"coingeckoId": "ngn"
|
||||
},
|
||||
{
|
||||
"code": "NOK",
|
||||
"name": "Norwegian Krone",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 31,
|
||||
"coingeckoId": "nok"
|
||||
},
|
||||
{
|
||||
"code": "NZD",
|
||||
"name": "New Zealand Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 32,
|
||||
"coingeckoId": "nzd"
|
||||
},
|
||||
{
|
||||
"code": "PHP",
|
||||
"name": "Philippine peso",
|
||||
"symbol": "₱",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 33,
|
||||
"coingeckoId": "php"
|
||||
},
|
||||
{
|
||||
"code": "PKR",
|
||||
"name": "Pakistani Rupee",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 34,
|
||||
"coingeckoId": "pkr"
|
||||
},
|
||||
{
|
||||
"code": "PLN",
|
||||
"name": "Poland złoty",
|
||||
"symbol": "zł",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 35,
|
||||
"coingeckoId": "pln"
|
||||
},
|
||||
{
|
||||
"code": "SAR",
|
||||
"name": "Saudi Riyal",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 36,
|
||||
"coingeckoId": "sar"
|
||||
},
|
||||
{
|
||||
"code": "SEK",
|
||||
"name": "Swedish Krona",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 37,
|
||||
"coingeckoId": "sek"
|
||||
},
|
||||
{
|
||||
"code": "SGD",
|
||||
"name": "Singapore Dollar",
|
||||
"symbol": "$",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 38,
|
||||
"coingeckoId": "sgd"
|
||||
},
|
||||
{
|
||||
"code": "THB",
|
||||
"name": "Thai Baht",
|
||||
"symbol": "฿",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 39,
|
||||
"coingeckoId": "thb"
|
||||
},
|
||||
{
|
||||
"code": "TRY",
|
||||
"name": "Turkish lira",
|
||||
"symbol": "₺",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 40,
|
||||
"coingeckoId": "try"
|
||||
},
|
||||
{
|
||||
"code": "UAH",
|
||||
"name": "Ukrainian hryvnia",
|
||||
"symbol": "₴",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 41,
|
||||
"coingeckoId": "uah"
|
||||
},
|
||||
{
|
||||
"code": "VEF",
|
||||
"name": "Venezuelan bolívar",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 42,
|
||||
"coingeckoId": "vef"
|
||||
},
|
||||
{
|
||||
"code": "VND",
|
||||
"name": "Vietnamese dong",
|
||||
"symbol": "₫",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 43,
|
||||
"coingeckoId": "vnd"
|
||||
},
|
||||
{
|
||||
"code": "ZAR",
|
||||
"name": "South African rand",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 44,
|
||||
"coingeckoId": "zar"
|
||||
},
|
||||
{
|
||||
"code": "XDR",
|
||||
"name": "IMF Special Drawing Rights",
|
||||
"category": "fiat",
|
||||
"popular": false,
|
||||
"id": 45,
|
||||
"coingeckoId": "xdr"
|
||||
},
|
||||
{
|
||||
"code": "DOT",
|
||||
"name": "Polkadot",
|
||||
"category": "crypto",
|
||||
"popular": true,
|
||||
"id": 46,
|
||||
"coingeckoId": "dot"
|
||||
},
|
||||
{
|
||||
"code": "BTC",
|
||||
"name": "Bitcoin",
|
||||
"symbol": "₿",
|
||||
"category": "crypto",
|
||||
"popular": true,
|
||||
"id": 47,
|
||||
"coingeckoId": "btc"
|
||||
},
|
||||
{
|
||||
"code": "ETH",
|
||||
"name": "Ether",
|
||||
"symbol": "Ξ",
|
||||
"category": "crypto",
|
||||
"popular": true,
|
||||
"id": 48,
|
||||
"coingeckoId": "eth"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user