Updated on 2026-08-14
This commit is contained in:
commit
ec15925bce
225 changed files with 5402 additions and 3982 deletions
|
|
@ -26,5 +26,13 @@
|
|||
{
|
||||
"name": "alephium",
|
||||
"version": "5.21.0"
|
||||
},
|
||||
{
|
||||
"name": "scroll",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "zklink",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
@ -46,5 +46,9 @@
|
|||
{
|
||||
"name": "BALANCES_CACHING_ENABLED",
|
||||
"version": "5.21.0"
|
||||
},
|
||||
{
|
||||
"name": "NFT_ENABLED",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
package com.tangem.datasource.api.common.visa
|
||||
|
||||
interface TangemVisaAuthProvider {
|
||||
|
||||
suspend fun getAuthHeader(cardId: String): String
|
||||
}
|
||||
|
|
@ -5,9 +5,7 @@ import com.tangem.datasource.api.utils.ReadTimeout
|
|||
import com.tangem.datasource.api.visa.models.request.ActivationByCardWalletRequest
|
||||
import com.tangem.datasource.api.visa.models.request.ActivationByCustomerWalletRequest
|
||||
import com.tangem.datasource.api.visa.models.request.SetPinCodeRequest
|
||||
import com.tangem.datasource.api.visa.models.response.CardActivationRemoteStateResponse
|
||||
import com.tangem.datasource.api.visa.models.response.CardWalletDataToSignResponse
|
||||
import com.tangem.datasource.api.visa.models.response.CustomerWalletDataToSignResponse
|
||||
import com.tangem.datasource.api.visa.models.response.*
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
|
|
@ -71,4 +69,19 @@ interface TangemVisaApi {
|
|||
@Header("Authorization") authHeader: String,
|
||||
@Body body: SetPinCodeRequest,
|
||||
): ApiResponse<Unit>
|
||||
|
||||
@GET("customer/info")
|
||||
suspend fun getCustomerInfo(
|
||||
@Header("Authorization") authHeader: String,
|
||||
@Query("card_id") cardId: String,
|
||||
): ApiResponse<VisaCustomerInfo>
|
||||
|
||||
@GET("product_instance/transactions")
|
||||
suspend fun getTxHistory(
|
||||
@Header("Authorization") authHeader: String,
|
||||
@Query("customer_id") customerId: String,
|
||||
@Query("product_instance_id") productInstanceId: String,
|
||||
@Query("limit") limit: Int,
|
||||
@Query("offset") offset: Int,
|
||||
): ApiResponse<VisaTxHistoryResponse>
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.datasource.api.visa
|
||||
|
||||
import com.tangem.datasource.api.common.response.ApiResponse
|
||||
import com.tangem.datasource.api.visa.models.response.GenerateNonceResponse
|
||||
import com.tangem.datasource.api.visa.models.response.JWTResponse
|
||||
import retrofit2.http.Field
|
||||
|
|
@ -27,5 +28,5 @@ interface TangemVisaAuthApi {
|
|||
): JWTResponse
|
||||
|
||||
@POST("auth/refresh_token")
|
||||
suspend fun refreshAccessToken(@Field("refresh_token") refreshToken: String): JWTResponse
|
||||
suspend fun refreshAccessToken(@Field("refresh_token") refreshToken: String): ApiResponse<JWTResponse>
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.datasource.api.visa.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class VisaCustomerInfo(
|
||||
@Json(name = "payment_accounts") val paymentAccounts: List<PaymentAccount>,
|
||||
) {
|
||||
data class PaymentAccount(
|
||||
@Json(name = "id") val id: String,
|
||||
@Json(name = "customer_wallet_address") val customerWalletAddress: String,
|
||||
@Json(name = "payment_account_address") val paymentAccountAddress: String,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.tangem.datasource.api.visa.models.response
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.joda.time.DateTime
|
||||
import java.math.BigDecimal
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class VisaTxHistoryResponse(
|
||||
@Json(name = "card_wallet_address")
|
||||
val cardWalletAddress: String,
|
||||
@Json(name = "transactions")
|
||||
val transactions: List<Transaction>,
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Transaction(
|
||||
@Json(name = "auth_code")
|
||||
val authCode: String?,
|
||||
@Json(name = "billing_amount")
|
||||
val billingAmount: BigDecimal,
|
||||
@Json(name = "billing_currency_code")
|
||||
val billingCurrencyCode: Int,
|
||||
@Json(name = "blockchain_amount")
|
||||
val blockchainAmount: BigDecimal,
|
||||
@Json(name = "blockchain_coin_name")
|
||||
val blockchainCoinName: String,
|
||||
@Json(name = "blockchain_fee")
|
||||
val blockchainFee: BigDecimal,
|
||||
// @Json(name = "local_dt")
|
||||
// val localDate: DateTime?,
|
||||
@Json(name = "merchant_category_code")
|
||||
val merchantCategoryCode: String?,
|
||||
@Json(name = "merchant_city")
|
||||
val merchantCity: String?,
|
||||
@Json(name = "merchant_country_code")
|
||||
val merchantCountryCode: String?,
|
||||
@Json(name = "merchant_name")
|
||||
val merchantName: String?,
|
||||
@Json(name = "requests")
|
||||
val requests: List<Request>,
|
||||
@Json(name = "rrn")
|
||||
val rrn: String?,
|
||||
@Json(name = "transaction_amount")
|
||||
val transactionAmount: BigDecimal,
|
||||
@Json(name = "transaction_currency_code")
|
||||
val transactionCurrencyCode: Int,
|
||||
@Json(name = "transaction_dt")
|
||||
val transactionDt: DateTime,
|
||||
@Json(name = "transaction_id")
|
||||
val transactionId: Long,
|
||||
@Json(name = "transaction_status")
|
||||
val transactionStatus: String,
|
||||
@Json(name = "transaction_type")
|
||||
val transactionType: String,
|
||||
) {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Request(
|
||||
@Json(name = "billing_amount")
|
||||
val billingAmount: BigDecimal,
|
||||
@Json(name = "billing_currency_code")
|
||||
val billingCurrencyCode: Int,
|
||||
@Json(name = "blockchain_amount")
|
||||
val blockchainAmount: BigDecimal,
|
||||
@Json(name = "blockchain_fee")
|
||||
val blockchainFee: BigDecimal,
|
||||
@Json(name = "error_code")
|
||||
val errorCode: Int,
|
||||
@Json(name = "request_dt")
|
||||
val requestDt: DateTime,
|
||||
@Json(name = "request_status")
|
||||
val requestStatus: String,
|
||||
@Json(name = "request_type")
|
||||
val requestType: String,
|
||||
@Json(name = "transaction_amount")
|
||||
val transactionAmount: BigDecimal,
|
||||
@Json(name = "transaction_currency_code")
|
||||
val transactionCurrencyCode: Int,
|
||||
@Json(name = "transaction_request_id")
|
||||
val transactionRequestId: Long,
|
||||
@Json(name = "tx_hash")
|
||||
val txHash: String?,
|
||||
@Json(name = "tx_status")
|
||||
val txStatus: String?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -121,6 +121,8 @@ object PreferencesKeys {
|
|||
|
||||
val SEED_FIRST_NOTIFICATION_SHOW_TIME by lazy { longPreferencesKey("seedFirstNotificationTime") }
|
||||
|
||||
val WALLETS_WITH_NFT_ENABLED_KEY by lazy { stringSetPreferencesKey(name = "walletsWithNftEnabled") }
|
||||
|
||||
fun getShouldShowStoriesKey(storyId: String) = booleanPreferencesKey("shouldShowStories_$storyId")
|
||||
|
||||
// region Permission
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.decompose.ui.UiMessageSender
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper
|
||||
|
||||
/**
|
||||
* Abstract class for a component's model.
|
||||
|
|
@ -29,6 +30,7 @@ abstract class Model : InstanceKeeper.Instance {
|
|||
CoroutineScope(context = dispatchers.mainImmediate + SupervisorJob())
|
||||
}
|
||||
|
||||
@OverridingMethodsMustInvokeSuper
|
||||
override fun onDestroy() {
|
||||
runCatching { modelScope.cancel() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
/* Core */
|
||||
implementation(projects.core.decompose)
|
||||
|
||||
/* Libs - AndroidX */
|
||||
implementation(deps.lifecycle.runtime.ktx)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.tangem.core.deeplink
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
// TODO: Add tests
|
||||
/**
|
||||
|
|
@ -21,17 +19,11 @@ interface DeepLinksRegistry {
|
|||
|
||||
/**
|
||||
* Registers the given [deepLink].
|
||||
*
|
||||
* @see registerWithLifecycle
|
||||
* @see registerWithViewModel
|
||||
*/
|
||||
fun register(deepLink: DeepLink)
|
||||
|
||||
/**
|
||||
* Registers the given [deepLinks].
|
||||
*
|
||||
* @see registerWithLifecycle
|
||||
* @see registerWithViewModel
|
||||
*/
|
||||
fun register(deepLinks: Collection<DeepLink>)
|
||||
|
||||
|
|
@ -50,17 +42,6 @@ interface DeepLinksRegistry {
|
|||
* */
|
||||
fun unregisterByIds(ids: Collection<String>)
|
||||
|
||||
/**
|
||||
* Registers the [deepLinks] when the [owner] is resumed and ensures that they are unregistered when the [owner] is
|
||||
* stopped.
|
||||
*/
|
||||
fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection<DeepLink>)
|
||||
|
||||
/**
|
||||
* Registers the [deepLinks] and ensures that they are unregistered when the [ViewModel] is closed.
|
||||
*/
|
||||
fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection<DeepLink>)
|
||||
|
||||
/**
|
||||
* Triggers run last launched [Intent] with deeplink handlers that can handle delayed deeplink
|
||||
* after handle [Intent] clear that and second time no intent will be handled
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@ package com.tangem.core.deeplink.impl
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.tangem.core.deeplink.DeepLink
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
import com.tangem.core.deeplink.utils.DeepLinksLifecycleObserver
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultDeepLinksRegistry : DeepLinksRegistry {
|
||||
|
|
@ -103,19 +100,6 @@ internal class DefaultDeepLinksRegistry : DeepLinksRegistry {
|
|||
)
|
||||
}
|
||||
|
||||
override fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection<DeepLink>) {
|
||||
val observer = DeepLinksLifecycleObserver(deepLinksRegistry = this, deepLinks)
|
||||
owner.lifecycle.addObserver(observer)
|
||||
}
|
||||
|
||||
override fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection<DeepLink>) {
|
||||
viewModel.addCloseable {
|
||||
unregister(deepLinks)
|
||||
}
|
||||
|
||||
register(deepLinks)
|
||||
}
|
||||
|
||||
override fun triggerDelayedDeeplink() {
|
||||
if (lastIntent != null) {
|
||||
val intent = lastIntent
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.core.deeplink.utils
|
||||
|
||||
import com.arkivanov.essenty.lifecycle.subscribe
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.deeplink.DeepLink
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
|
||||
fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, vararg deepLinks: DeepLink) {
|
||||
registerDeepLinks(registry, deepLinks.toList())
|
||||
}
|
||||
|
||||
fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, deepLinks: Collection<DeepLink>) {
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
registry.register(deepLinks)
|
||||
},
|
||||
onDestroy = {
|
||||
registry.unregister(deepLinks)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
package com.tangem.core.deeplink.utils
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.tangem.core.deeplink.DeepLink
|
||||
import com.tangem.core.deeplink.DeepLinksRegistry
|
||||
|
||||
internal class DeepLinksLifecycleObserver(
|
||||
private val deepLinksRegistry: DeepLinksRegistry,
|
||||
private val deepLinks: Collection<DeepLink>,
|
||||
) : DefaultLifecycleObserver {
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
deepLinksRegistry.register(deepLinks)
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
deepLinksRegistry.unregister(deepLinks)
|
||||
}
|
||||
}
|
||||
|
|
@ -90,6 +90,9 @@ fun getActiveIconRes(blockchainId: String): Int {
|
|||
"bitrock", "bitrock/test" -> R.drawable.img_bitrock_22
|
||||
"sonic", "sonic/test" -> R.drawable.img_sonic_22
|
||||
"apechain", "apechain/test" -> R.drawable.img_apecoin_22
|
||||
"scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration
|
||||
"zklink", "zklink/test" -> R.drawable.img_zklink_22
|
||||
"vanar-chain", "vanar-chain/test" -> R.drawable.img_vanar_22
|
||||
else -> R.drawable.ic_alert_24
|
||||
}
|
||||
}
|
||||
|
|
@ -178,6 +181,9 @@ fun getActiveIconResByCoinId(coinId: String): Int {
|
|||
"bitrock", "bitrock/test" -> R.drawable.img_bitrock_22
|
||||
"sonic", "sonic/test" -> R.drawable.img_sonic_22
|
||||
"apechain", "apechain/test" -> R.drawable.img_apecoin_22
|
||||
"scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration
|
||||
"zklink", "zklink/test" -> R.drawable.img_zklink_22
|
||||
"vanar-chain", "vanar-chain/test" -> R.drawable.img_vanar_22
|
||||
else -> R.drawable.ic_alert_24
|
||||
}
|
||||
}
|
||||
|
|
@ -269,6 +275,9 @@ fun getGreyedOutIconRes(blockchainId: String): Int {
|
|||
"bitrock", "bitrock/test" -> R.drawable.ic_bitrock_22
|
||||
"sonic", "sonic/test" -> R.drawable.ic_sonic_22
|
||||
"apechain", "apechain/test" -> R.drawable.ic_apecoin_22
|
||||
"scroll", "scroll/test" -> R.drawable.ic_alert_24 // FIXME: add icon during full integration
|
||||
"zklink", "zklink/test" -> R.drawable.ic_zklink_22
|
||||
"vanar-chain", "vanar-chain/test" -> R.drawable.ic_vanar_22
|
||||
else -> R.drawable.ic_alert_24
|
||||
}
|
||||
}
|
||||
9
core/ui/src/main/res/drawable/ic_vanar_22.xml
Normal file
9
core/ui/src/main/res/drawable/ic_vanar_22.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="22"
|
||||
android:viewportHeight="22">
|
||||
<path
|
||||
android:pathData="M12.748,18L14.498,14.999L9.25,6H5.749L4,9H7.502L12.748,18ZM16.249,11.999L18,9L16.249,6H12.75L11.001,9H14.5L16.249,11.999Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
14
core/ui/src/main/res/drawable/ic_zklink_22.xml
Normal file
14
core/ui/src/main/res/drawable/ic_zklink_22.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="22"
|
||||
android:viewportHeight="22">
|
||||
<path
|
||||
android:pathData="M11.217,3.624L11.002,3.5L10.788,3.624L7.502,5.526L7.288,5.65V5.897V9.455L4.214,11.235L4,11.358V11.605V15.41V15.657L4.214,15.78L7.5,17.683L7.714,17.807L7.929,17.683L11,15.905L14.071,17.683L14.286,17.807L14.5,17.683L17.786,15.78L18,15.657V15.41V11.605V11.358L17.786,11.235L14.716,9.457V5.897V5.65L14.503,5.526L11.217,3.624ZM8.145,6.144L11.002,4.49L13.86,6.144V9.454L11.621,10.75C11.456,10.61 11.243,10.525 11.009,10.525C10.773,10.525 10.557,10.612 10.391,10.755L8.145,9.454V6.144ZM10.068,11.561L7.714,10.198L4.857,11.852V15.163L7.714,16.817L10.571,15.163V12.308C10.295,12.164 10.099,11.886 10.068,11.561ZM11.428,12.318V15.163L14.286,16.817L17.143,15.163V11.852L14.288,10.199L11.951,11.552C11.922,11.888 11.717,12.175 11.428,12.318Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M11.002,7.31L14.716,9.46V13.758L11.002,15.908L7.288,13.758V9.46L11.002,7.31ZM8.145,9.954V13.264L11.002,14.918L13.86,13.264V9.954L11.002,8.299L8.145,9.954Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
19
core/ui/src/main/res/drawable/img_vanar_22.xml
Normal file
19
core/ui/src/main/res/drawable/img_vanar_22.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="22"
|
||||
android:viewportHeight="22">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"/>
|
||||
<path
|
||||
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M0,0h22v22h-22z"
|
||||
android:fillColor="#080A0B"/>
|
||||
<path
|
||||
android:pathData="M12.748,18L14.498,14.999L9.25,6H5.749L4,9H7.502L12.748,18ZM16.249,11.999L18,9L16.249,6H12.75L11.001,9H14.5L16.249,11.999Z"
|
||||
android:fillColor="#03D9AF"/>
|
||||
</group>
|
||||
</vector>
|
||||
24
core/ui/src/main/res/drawable/img_zklink_22.xml
Normal file
24
core/ui/src/main/res/drawable/img_zklink_22.xml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="22dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="22"
|
||||
android:viewportHeight="22">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"/>
|
||||
<path
|
||||
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M0,0h22v22h-22z"
|
||||
android:fillColor="#080A0B"/>
|
||||
<path
|
||||
android:pathData="M11.217,3.624L11.002,3.5L10.788,3.624L7.502,5.526L7.288,5.65V5.897V9.455L4.214,11.235L4,11.358V11.605V15.41V15.657L4.214,15.78L7.5,17.683L7.714,17.807L7.929,17.683L11,15.905L14.071,17.683L14.286,17.807L14.5,17.683L17.786,15.78L18,15.657V15.41V11.605V11.358L17.786,11.235L14.716,9.457V5.897V5.65L14.503,5.526L11.217,3.624ZM8.145,6.144L11.002,4.49L13.86,6.144V9.454L11.621,10.75C11.456,10.61 11.243,10.525 11.009,10.525C10.773,10.525 10.557,10.612 10.391,10.755L8.145,9.454V6.144ZM10.068,11.561L7.714,10.198L4.857,11.852V15.163L7.714,16.817L10.571,15.163V12.308C10.295,12.164 10.099,11.886 10.068,11.561ZM11.428,12.318V15.163L14.286,16.817L17.143,15.163V11.852L14.288,10.199L11.951,11.552C11.922,11.888 11.717,12.175 11.428,12.318Z"
|
||||
android:fillColor="#03D498"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M11.002,7.31L14.716,9.46V13.758L11.002,15.908L7.288,13.758V9.46L11.002,7.31ZM8.145,9.954V13.264L11.002,14.918L13.86,13.264V9.954L11.002,8.299L8.145,9.954Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue