mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-04-22 05:38:02 +00:00
Initial commit: Pezkuwi Wallet Android
Security hardened release: - Code obfuscation enabled (minifyEnabled=true, shrinkResources=true) - Sensitive files excluded (google-services.json, keystores) - Branch.io key moved to BuildConfig placeholder - Updated dependencies: OkHttp 4.12.0, Gson 2.10.1, BouncyCastle 1.77 - Comprehensive ProGuard rules for crypto wallet - Navigation 2.7.7, Lifecycle 2.7.0, ConstraintLayout 2.1.4
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,23 @@
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
|
||||
android {
|
||||
namespace 'io.novafoundation.nova.feature_dapp_api'
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':feature-account-api')
|
||||
implementation project(":feature-external-sign-api")
|
||||
implementation project(':common')
|
||||
implementation project(':feature-deep-linking')
|
||||
|
||||
implementation shimmerDep
|
||||
|
||||
implementation coroutinesDep
|
||||
|
||||
testImplementation jUnitDep
|
||||
testImplementation mockitoDep
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.model
|
||||
|
||||
class BrowserHostSettings(
|
||||
val hostUrl: String,
|
||||
val isDesktopModeEnabled: Boolean
|
||||
)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.model
|
||||
|
||||
import io.novafoundation.nova.common.list.GroupedList
|
||||
|
||||
class DApp(
|
||||
val name: String,
|
||||
val description: String,
|
||||
val iconLink: String?,
|
||||
val url: String,
|
||||
val isFavourite: Boolean,
|
||||
val favoriteIndex: Int?
|
||||
)
|
||||
|
||||
data class DAppGroupedCatalog(
|
||||
val popular: List<DApp>,
|
||||
val categoriesWithDApps: GroupedList<DappCategory, DApp>
|
||||
)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.model
|
||||
|
||||
typealias DAppUrl = String
|
||||
|
||||
class DappCatalog(
|
||||
val popular: List<DAppUrl>,
|
||||
val categories: List<DappCategory>,
|
||||
val dApps: List<DappMetadata>
|
||||
)
|
||||
|
||||
class DappMetadata(
|
||||
val name: String,
|
||||
val iconLink: String,
|
||||
val url: DAppUrl,
|
||||
val baseUrl: String,
|
||||
val categories: Set<DappCategory>
|
||||
)
|
||||
|
||||
data class DappCategory(
|
||||
val iconUrl: String?,
|
||||
val name: String,
|
||||
val id: String
|
||||
)
|
||||
|
||||
private const val STAKING_CATEGORY_ID = "staking"
|
||||
|
||||
fun DappCategory.isStaking(): Boolean {
|
||||
return id == STAKING_CATEGORY_ID
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.model
|
||||
|
||||
class SimpleTabModel(
|
||||
val tabId: String,
|
||||
val title: String?,
|
||||
val knownDAppIconUrl: String?,
|
||||
val faviconPath: String?
|
||||
)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.repository
|
||||
|
||||
import io.novafoundation.nova.feature_dapp_api.data.model.BrowserHostSettings
|
||||
|
||||
interface BrowserHostSettingsRepository {
|
||||
|
||||
suspend fun getBrowserHostSettings(url: String): BrowserHostSettings?
|
||||
|
||||
suspend fun saveBrowserHostSettings(settings: BrowserHostSettings)
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.repository
|
||||
|
||||
import io.novafoundation.nova.feature_dapp_api.data.model.SimpleTabModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface BrowserTabExternalRepository {
|
||||
|
||||
fun observeTabsWithNames(metaId: Long): Flow<List<SimpleTabModel>>
|
||||
|
||||
suspend fun removeTabsForMetaAccount(metaId: Long): List<String>
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.data.repository
|
||||
|
||||
import io.novafoundation.nova.feature_dapp_api.data.model.DappCatalog
|
||||
import io.novafoundation.nova.feature_dapp_api.data.model.DappMetadata
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DAppMetadataRepository {
|
||||
|
||||
suspend fun isDAppsSynced(): Boolean
|
||||
|
||||
suspend fun syncDAppMetadatas()
|
||||
|
||||
suspend fun syncAndGetDapp(baseUrl: String): DappMetadata?
|
||||
|
||||
suspend fun getDAppMetadata(baseUrl: String): DappMetadata?
|
||||
|
||||
suspend fun findDAppMetadataByExactUrlMatch(fullUrl: String): DappMetadata?
|
||||
|
||||
suspend fun findDAppMetadatasByBaseUrlMatch(baseUrl: String): List<DappMetadata>
|
||||
|
||||
suspend fun getDAppCatalog(): DappCatalog
|
||||
|
||||
fun observeDAppCatalog(): Flow<DappCatalog>
|
||||
}
|
||||
|
||||
suspend fun DAppMetadataRepository.getDAppIfSyncedOrSync(baseUrl: String): DappMetadata? {
|
||||
return if (isDAppsSynced()) {
|
||||
getDAppMetadata(baseUrl)
|
||||
} else {
|
||||
syncAndGetDapp(baseUrl)
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.di
|
||||
|
||||
import io.novafoundation.nova.feature_dapp_api.data.repository.BrowserTabExternalRepository
|
||||
import io.novafoundation.nova.feature_dapp_api.data.repository.DAppMetadataRepository
|
||||
import io.novafoundation.nova.feature_dapp_api.di.deeplinks.DAppDeepLinks
|
||||
|
||||
interface DAppFeatureApi {
|
||||
|
||||
val dappMetadataRepository: DAppMetadataRepository
|
||||
|
||||
val browserTabsRepository: BrowserTabExternalRepository
|
||||
|
||||
val dAppDeepLinks: DAppDeepLinks
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.di.deeplinks
|
||||
|
||||
import io.novafoundation.nova.feature_deep_linking.presentation.handling.DeepLinkHandler
|
||||
|
||||
class DAppDeepLinks(val deepLinkHandlers: List<DeepLinkHandler>)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.presentation.addToFavorites
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class AddToFavouritesPayload(
|
||||
val url: String,
|
||||
val label: String?,
|
||||
val iconLink: String?
|
||||
) : Parcelable
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.presentation.browser.main
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
interface DAppBrowserPayload : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
class Tab(val id: String) : DAppBrowserPayload
|
||||
|
||||
@Parcelize
|
||||
class Address(val address: String) : DAppBrowserPayload
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package io.novafoundation.nova.feature_dapp_api.presentation.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import coil.ImageLoader
|
||||
import coil.clear
|
||||
import io.novafoundation.nova.common.di.FeatureUtils
|
||||
import io.novafoundation.nova.common.utils.inflater
|
||||
import io.novafoundation.nova.common.utils.makeVisible
|
||||
import io.novafoundation.nova.common.utils.setImageTintRes
|
||||
import io.novafoundation.nova.common.utils.setVisible
|
||||
import io.novafoundation.nova.common.utils.updatePadding
|
||||
import io.novafoundation.nova.feature_dapp_api.R
|
||||
import io.novafoundation.nova.feature_dapp_api.databinding.ViewDappBinding
|
||||
import io.novafoundation.nova.feature_external_sign_api.presentation.dapp.showDAppIcon
|
||||
|
||||
class DAppView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0,
|
||||
) : ConstraintLayout(context, attrs, defStyle) {
|
||||
|
||||
private val binder = ViewDappBinding.inflate(inflater(), this)
|
||||
|
||||
companion object {
|
||||
fun createUsingMathParentWidth(context: Context): DAppView {
|
||||
return DAppView(context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val imageLoader: ImageLoader by lazy(LazyThreadSafetyMode.NONE) {
|
||||
FeatureUtils.getCommonApi(context).imageLoader()
|
||||
}
|
||||
|
||||
init {
|
||||
setBackgroundResource(R.drawable.bg_primary_list_item)
|
||||
}
|
||||
|
||||
fun setTitle(name: String?) {
|
||||
binder.itemDAppTitle.text = name
|
||||
}
|
||||
|
||||
fun showTitle(show: Boolean) {
|
||||
binder.itemDAppTitle.setVisible(show)
|
||||
}
|
||||
|
||||
fun setSubtitle(url: String?) {
|
||||
binder.itemDAppSubtitle.text = url
|
||||
}
|
||||
|
||||
fun showSubtitle(show: Boolean) {
|
||||
binder.itemDAppSubtitle.setVisible(show)
|
||||
}
|
||||
|
||||
fun setIconUrl(iconUrl: String?) {
|
||||
binder.itemDAppIcon.showDAppIcon(iconUrl, imageLoader)
|
||||
}
|
||||
|
||||
fun setFavoriteIconVisible(visible: Boolean) {
|
||||
binder.itemDappFavorite.setVisible(visible)
|
||||
}
|
||||
|
||||
fun enableSubtitleIcon(): ImageView {
|
||||
return binder.itemDAppSubtitleIcon.also { icon -> icon.makeVisible() }
|
||||
}
|
||||
|
||||
fun setOnActionClickListener(listener: OnClickListener?) {
|
||||
binder.itemDappAction.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
fun setActionResource(@DrawableRes iconRes: Int?, @ColorRes colorRes: Int? = null) {
|
||||
if (iconRes == null) {
|
||||
binder.itemDappAction.setImageDrawable(null)
|
||||
} else {
|
||||
binder.itemDappAction.setImageResource(iconRes)
|
||||
binder.itemDappAction.setImageTintRes(colorRes)
|
||||
}
|
||||
}
|
||||
|
||||
fun setActionTintRes(@ColorRes color: Int?) {
|
||||
binder.itemDappAction.setImageTintRes(color)
|
||||
}
|
||||
|
||||
fun setActionEndPadding(rightPadding: Int) {
|
||||
binder.itemDappAction.updatePadding(end = rightPadding)
|
||||
}
|
||||
|
||||
fun clearIcon() {
|
||||
binder.itemDAppIcon.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:color="@color/text_primary_on_content"/>
|
||||
<item android:color="@color/button_text" />
|
||||
</selector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape android:shape="rectangle"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<corners android:radius="@dimen/border_radius" />
|
||||
|
||||
<solid android:color="@color/block_background" />
|
||||
|
||||
<stroke android:color="@color/container_border" android:width="0.5dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="10dp" />
|
||||
|
||||
<solid android:color="@color/button_background_secondary" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="10dp" />
|
||||
|
||||
<solid android:color="@color/selected_dapp_category" />
|
||||
</shape>
|
||||
@@ -0,0 +1,22 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="44dp"
|
||||
android:height="44dp"
|
||||
android:viewportWidth="44"
|
||||
android:viewportHeight="44">
|
||||
<path
|
||||
android:pathData="M22,44C34.1503,44 44,34.1503 44,22C44,9.8497 34.1503,0 22,0C9.8497,0 0,9.8497 0,22C0,34.1503 9.8497,44 22,44ZM9.2784,31.9733H14.2913V11.1192H9.2784V31.9733ZM19.2529,11.1192V31.9733H26.1136C27.9183,31.9638 29.551,31.5341 31.0119,30.6843C32.4824,29.825 33.6188,28.6409 34.4209,27.1322C35.2324,25.614 35.6382,23.8999 35.6382,21.9903V21.0307C35.6287,19.14 35.2087,17.4356 34.3779,15.9173C33.5567,14.3896 32.4108,13.2103 30.9404,12.3796C29.4699,11.5393 27.8131,11.1192 25.9703,11.1192H19.2529ZM24.2802,28.1062V15.0006H25.9703C27.4503,15.0006 28.5771,15.5115 29.3505,16.5333C30.124,17.555 30.5106,19.0731 30.5106,21.0879V21.9903C30.5106,24.0146 30.124,25.5423 29.3505,26.5737C28.5771,27.5953 27.4695,28.1062 26.0276,28.1062H24.2802Z"
|
||||
android:fillType="evenOdd">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="0"
|
||||
android:startX="22"
|
||||
android:endY="44"
|
||||
android:endX="22"
|
||||
android:type="linear">
|
||||
<item android:offset="0" android:color="#FFF50083"/>
|
||||
<item android:offset="1" android:color="#FF720497"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<View
|
||||
android:id="@+id/itemDappShimerringIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_shimmering"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/itemDappShimerringTitle"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/bg_shimmering"
|
||||
app:layout_constraintBottom_toTopOf="@+id/itemDappShimerringSubTitle"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemDappShimerringIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<View
|
||||
android:id="@id/itemDappShimerringSubTitle"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/bg_shimmering"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemDappShimerringIcon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemDappShimerringTitle" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.facebook.shimmer.ShimmerFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@drawable/bg_shimmering" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||
|
||||
<com.facebook.shimmer.ShimmerFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="34dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="88dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="@drawable/bg_shimmering" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<include
|
||||
layout="@layout/item_dapp_shimmering"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge 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:background="@drawable/bg_primary_list_item"
|
||||
tools:background="@color/block_background"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemDAppIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/dapp_icon_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:src="@drawable/ic_sub_id" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemDAppTitle"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.Body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_primary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/itemDAppSubtitle"
|
||||
app:layout_constraintEnd_toStartOf="@+id/itemDappAction"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@id/itemDAppIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/itemDAppIcon"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Astar" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemDAppSubtitleIcon"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@+id/itemDAppTitle"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemDAppTitle"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemDAppSubtitle"
|
||||
style="@style/TextAppearance.NovaFoundation.Regular.Footnote"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/text_secondary"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/itemDAppIcon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/itemDappAction"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/itemDAppSubtitleIcon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemDAppTitle"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:text="Staking" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemDappFavorite"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginStart="40dp"
|
||||
android:layout_marginBottom="38dp"
|
||||
android:src="@drawable/ic_favorite_heart_filled_20"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/itemDAppIcon"
|
||||
app:layout_constraintStart_toStartOf="@+id/itemDAppIcon"
|
||||
app:tint="@color/mimi_icon_favorite"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemDappAction"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="20dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_close" />
|
||||
</merge>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Widget.Nova.DappCategory.Shimmering" parent="">
|
||||
<item name="android:layout_width">48dp</item>
|
||||
<item name="android:layout_height">10dp</item>
|
||||
<item name="android:background">@drawable/bg_shimmering</item>
|
||||
<item name="android:layout_marginEnd">32dp</item>
|
||||
</style>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user