Updated on 2026-08-14

This commit is contained in:
Tangem 2021-03-17 15:31:03 +03:00
parent 2cfb552d19
commit 8dacd12b74
153 changed files with 4393 additions and 1124 deletions

View file

@ -0,0 +1,6 @@
package com.tangem.tap.common.extensions
import android.content.res.AssetManager
fun AssetManager.readJsonFileToString(fileName: String): String =
this.open("$fileName.json").bufferedReader().readText()

View file

@ -0,0 +1,23 @@
package com.tangem.tap.common.extensions
import androidx.annotation.DrawableRes
import com.tangem.blockchain.common.Blockchain
import com.tangem.wallet.R
@DrawableRes
fun Blockchain.getIconRes(): Int {
return when (this) {
Blockchain.Unknown, Blockchain.Ducatus, Blockchain.BitcoinTestnet, Blockchain.EthereumTestnet,
Blockchain.BinanceTestnet -> 1
Blockchain.Bitcoin -> R.drawable.ic_btc
Blockchain.BitcoinCash -> R.drawable.ic_btc_cash
Blockchain.Litecoin -> R.drawable.ic_ltc
Blockchain.Ethereum -> R.drawable.ic_eth
Blockchain.RSK -> R.drawable.ic_rsk
Blockchain.Cardano, Blockchain.CardanoShelley -> R.drawable.ic_cardano
Blockchain.Binance -> R.drawable.ic_binance
Blockchain.Tezos -> R.drawable.ic_tezos
Blockchain.XRP -> R.drawable.ic_xrp
Blockchain.Stellar -> R.drawable.ic_stellar
}
}

View file

@ -12,6 +12,8 @@ import com.tangem.tap.features.details.ui.twins.TwinWalletWarningFragment
import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
import com.tangem.tap.features.home.HomeFragment
import com.tangem.tap.features.send.ui.SendFragment
import com.tangem.tap.features.tokens.ui.AddTokensFragment
import com.tangem.tap.features.wallet.ui.WalletDetailsFragment
import com.tangem.tap.features.wallet.ui.WalletFragment
import com.tangem.tap.features.wallet.ui.dialogs.TwinsOnboardingFragment
import com.tangem.wallet.R
@ -46,5 +48,7 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
AppScreen.CreateTwinWalletWarning -> TwinWalletWarningFragment()
AppScreen.CreateTwinWallet -> CreateTwinWalletFragment()
AppScreen.TwinsOnboarding -> TwinsOnboardingFragment()
AppScreen.AddTokens -> AddTokensFragment()
AppScreen.WalletDetails -> WalletDetailsFragment()
}
}

View file

@ -1,11 +1,5 @@
package com.tangem.tap.common.extensions
import android.graphics.Bitmap
import android.graphics.Color
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.network.coinmarketcap.FiatCurrency
@ -15,27 +9,6 @@ import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*
fun String.toQrCode(): Bitmap {
val hintMap = Hashtable<EncodeHintType, Any>()
hintMap[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.M // H = 30% damage
hintMap[EncodeHintType.MARGIN] = 2
val qrCodeWriter = QRCodeWriter()
val size = 256
val bitMatrix = qrCodeWriter.encode(this, BarcodeFormat.QR_CODE, size, size, hintMap)
val width = bitMatrix.width
val bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until width) {
bmp.setPixel(y, x, if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE)
}
}
return bmp
}
fun BigDecimal.toFormattedString(
decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN, locale: Locale = Locale.US
): String {

View file

@ -0,0 +1,62 @@
package com.tangem.tap.common.extensions
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.text.Spannable
import android.text.style.ForegroundColorSpan
import androidx.core.content.ContextCompat
import androidx.core.text.toSpannable
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import java.util.*
fun String?.ellipsizeBeforeSpace(allowedSize: Int): String {
if (this.isNullOrBlank()) return ""
val size = this.length
val sizeDifference = size - allowedSize
val endIndex = this.indexOf(" ")
val startIndex = endIndex - sizeDifference
val newString = this.removeRange(startIndex, endIndex)
return newString.substring(0 until startIndex) + "..." +
newString.substring(startIndex until newString.length)
}
fun String.colorSegment(
context: Context,
color: Int,
startIndex: Int = 0,
endIndex: Int = this.length
): Spannable {
return this.toSpannable()
.also { spannable ->
spannable.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, color)),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
fun String.toQrCode(): Bitmap {
val hintMap = Hashtable<EncodeHintType, Any>()
hintMap[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.M // H = 30% damage
hintMap[EncodeHintType.MARGIN] = 2
val qrCodeWriter = QRCodeWriter()
val size = 256
val bitMatrix = qrCodeWriter.encode(this, BarcodeFormat.QR_CODE, size, size, hintMap)
val width = bitMatrix.width
val bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until width) {
bmp.setPixel(y, x, if (bitMatrix.get(x, y)) Color.BLACK else Color.WHITE)
}
}
return bmp
}

View file

@ -56,4 +56,13 @@ fun TextInputLayout.enableError(enable: Boolean, errorMessage: String? = null) {
error = null
isErrorEnabled = false
}
}
fun TextView.isEllipsized(): Boolean {
val layout = this.layout
if (layout != null) {
val lines: Int = layout.lineCount
return (lines > 0) && (layout.getEllipsisCount(lines - 1) > 0)
}
return false
}

View file

@ -0,0 +1,11 @@
package com.tangem.tap.common.extensions
import androidx.annotation.ColorInt
import androidx.core.graphics.toColorInt
import com.tangem.blockchain.common.Token
@ColorInt
fun Token.getColor(): Int {
return ("#" + this.contractAddress.subSequence(2..7).toString())
.toColorInt()
}

View file

@ -8,8 +8,6 @@ import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.os.Build
import android.text.Spannable
import android.text.style.ForegroundColorSpan
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
@ -19,7 +17,6 @@ import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.core.text.toSpannable
import androidx.fragment.app.Fragment
import com.google.android.material.card.MaterialCardView
@ -106,24 +103,6 @@ fun Activity.setSystemBarTextColor(setTextDark: Boolean) {
}
}
fun String.colorSegment(
context: Context,
color: Int,
startIndex: Int = 0,
endIndex: Int = this.length
): Spannable {
return this.toSpannable()
.also { spannable ->
spannable.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context, color)),
startIndex,
endIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
fun View.hideKeyboard() {
val inputMethodManager = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? InputMethodManager
inputMethodManager?.hideSoftInputFromWindow(this.windowToken, 0)

View file

@ -6,6 +6,7 @@ import com.tangem.tap.features.details.redux.DetailsReducer
import com.tangem.tap.features.disclaimer.redux.DisclaimerReducer
import com.tangem.tap.features.home.redux.HomeReducer
import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
import com.tangem.tap.features.tokens.redux.TokensReducer
import com.tangem.tap.features.wallet.redux.WalletReducer
import org.rekotlin.Action
@ -20,7 +21,8 @@ fun appReducer(action: Action, state: AppState?): AppState {
walletState = WalletReducer.reduce(action, state),
sendState = SendScreenReducer.reduce(action, state.sendState),
detailsState = DetailsReducer.reduce(action, state),
disclaimerState = DisclaimerReducer.reduce(action, state)
disclaimerState = DisclaimerReducer.reduce(action, state),
tokensState = TokensReducer.reduce(action, state),
)
}

View file

@ -12,8 +12,10 @@ import com.tangem.tap.features.home.redux.HomeMiddleware
import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.send.redux.middlewares.sendMiddleware
import com.tangem.tap.features.send.redux.states.SendState
import com.tangem.tap.features.wallet.redux.WalletMiddleware
import com.tangem.tap.features.tokens.redux.TokensMiddleware
import com.tangem.tap.features.tokens.redux.TokensState
import com.tangem.tap.features.wallet.redux.WalletState
import com.tangem.tap.features.wallet.redux.middlewares.WalletMiddleware
import org.rekotlin.Middleware
import org.rekotlin.StateType
@ -24,7 +26,8 @@ data class AppState(
val walletState: WalletState = WalletState(),
val sendState: SendState = SendState(),
val detailsState: DetailsState = DetailsState(),
val disclaimerState: DisclaimerState = DisclaimerState()
val disclaimerState: DisclaimerState = DisclaimerState(),
val tokensState: TokensState = TokensState(),
) : StateType {
companion object {
@ -35,7 +38,8 @@ data class AppState(
WalletMiddleware().walletMiddleware,
sendMiddleware,
DetailsMiddleware().detailsMiddleware,
DisclaimerMiddleware().disclaimerMiddleware
DisclaimerMiddleware().disclaimerMiddleware,
TokensMiddleware().tokensMiddleware,
)
}
}

View file

@ -6,14 +6,10 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.features.details.redux.SecurityOption
import org.rekotlin.Action
import java.math.BigDecimal
sealed class GlobalAction : Action {
data class SaveScanNoteResponse(val scanNoteResponse: ScanNoteResponse) : GlobalAction()
data class SetFiatRate(
val fiatRates: Pair<CryptoCurrencyName, BigDecimal>
) : GlobalAction()
data class ChangeAppCurrency(val appCurrency: FiatCurrencyName) : GlobalAction()
object RestoreAppCurrency : GlobalAction() {
data class Success(val appCurrency: FiatCurrencyName) : GlobalAction()

View file

@ -23,7 +23,7 @@ val globalMiddleware: Middleware<AppState> = { dispatch, appState ->
if (it.hideWarning(action.warning)) {
if (WarningMessagesManager.isAlreadySignedHashesWarning(action.warning)) {
//TODO: No appropriate warningMessage identification. Make it better later
store.dispatch(WalletAction.SaveCardId)
store.dispatch(WalletAction.CheckSignedHashes.SaveCardId)
}
store.dispatch(WalletAction.SetWarnings(it.getWarnings(WarningMessage.Location.MainScreen)))

View file

@ -13,16 +13,11 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
return when (action) {
is GlobalAction.SaveScanNoteResponse ->
globalState.copy(scanNoteResponse = action.scanNoteResponse)
is GlobalAction.SetFiatRate -> {
val rates = globalState.conversionRates.rates.toMutableMap()
rates[action.fiatRates.first] = action.fiatRates.second
globalState.copy(conversionRates = ConversionRates(rates))
}
is GlobalAction.ChangeAppCurrency -> {
globalState.copy(appCurrency = action.appCurrency, conversionRates = ConversionRates(mapOf()))
globalState.copy(appCurrency = action.appCurrency)
}
is GlobalAction.RestoreAppCurrency.Success -> {
globalState.copy(appCurrency = action.appCurrency, conversionRates = ConversionRates(mapOf()))
globalState.copy(appCurrency = action.appCurrency)
}
is GlobalAction.UpdateWalletSignedHashes -> {
val card = globalState.scanNoteResponse?.card?.copy(

View file

@ -9,7 +9,6 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
import org.rekotlin.StateType
import java.math.BigDecimal
data class GlobalState(
val scanNoteResponse: ScanNoteResponse? = null,
@ -17,21 +16,11 @@ data class GlobalState(
val payIdManager: PayIdManager = PayIdManager(),
val coinMarketCapService: CoinMarketCapService = CoinMarketCapService(),
val tangemService: TangemService = TangemService(),
val conversionRates: ConversionRates = ConversionRates(emptyMap()),
val configManager: ConfigManager? = null,
val warningManager: WarningMessagesManager? = null,
val appCurrency: FiatCurrencyName = DEFAULT_FIAT_CURRENCY
) : StateType
data class ConversionRates(
val rates: Map<CryptoCurrencyName, BigDecimal>,
) {
fun getRate(cryptoCurrency: CryptoCurrencyName): BigDecimal? {
return rates[cryptoCurrency]
}
}
typealias CryptoCurrencyName = String
typealias FiatCurrencyName = String

View file

@ -10,6 +10,6 @@ data class NavigationState(
) : StateType
enum class AppScreen {
Home, Wallet, Send, Details, DetailsConfirm, DetailsSecurity, Disclaimer,
CreateTwinWalletWarning, CreateTwinWallet, TwinsOnboarding
Home, Wallet, WalletDetails, Send, Details, DetailsConfirm, DetailsSecurity, Disclaimer,
CreateTwinWalletWarning, CreateTwinWallet, TwinsOnboarding, AddTokens
}