mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-10-20 18:56:25 +00:00
feat: add Start Tracking button for StakingScore on dashboard
Query StakingScore::StakingStartBlock from People Chain to check tracking status. Show "Start Tracking" button for approved citizens who haven't opted in yet. Submits start_score_tracking() extrinsic with loading state and error handling to prevent duplicate calls.
This commit is contained in:
1 parent
6939dfd4c3
commit
91f2b5d254
10 files changed
+114
-9
No files matched your search
@@ -2766,6 +2766,8 @@
|
|||||||
<string name="pezkuwi_dashboard_trust_score">Trust Score</string>
|
<string name="pezkuwi_dashboard_trust_score">Trust Score</string>
|
||||||
<string name="pezkuwi_dashboard_basvuru">Apply & Actions</string>
|
<string name="pezkuwi_dashboard_basvuru">Apply & Actions</string>
|
||||||
<string name="pezkuwi_dashboard_info">Use our Telegram MiniApp for Digital Kurdistan citizenship services.\n\nTo earn PEZ rewards, you must hold a Welatî ticket and stake at least 10 HEZ.\n\nNon-citizens can only benefit from HEZ rewards.</string>
|
<string name="pezkuwi_dashboard_info">Use our Telegram MiniApp for Digital Kurdistan citizenship services.\n\nTo earn PEZ rewards, you must hold a Welatî ticket and stake at least 10 HEZ.\n\nNon-citizens can only benefit from HEZ rewards.</string>
|
||||||
|
<string name="pezkuwi_dashboard_start_tracking">Start Tracking</string>
|
||||||
|
<string name="pezkuwi_dashboard_tracking_success">Score tracking started!</string>
|
||||||
<string name="pezkuwi_dashboard_kurds_title">Hejmara Kurd Le Cihane</string>
|
<string name="pezkuwi_dashboard_kurds_title">Hejmara Kurd Le Cihane</string>
|
||||||
|
|
||||||
<!-- Citizenship Application -->
|
<!-- Citizenship Application -->
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ dependencies {
|
|||||||
implementation insetterDep
|
implementation insetterDep
|
||||||
|
|
||||||
implementation shimmerDep
|
implementation shimmerDep
|
||||||
implementation flexBoxDep
|
api flexBoxDep
|
||||||
|
|
||||||
implementation chartsDep
|
implementation chartsDep
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -7,5 +7,6 @@ data class PezkuwiDashboardData(
|
|||||||
val roles: List<String>,
|
val roles: List<String>,
|
||||||
val trustScore: BigInteger,
|
val trustScore: BigInteger,
|
||||||
val welatiCount: Int,
|
val welatiCount: Int,
|
||||||
val citizenshipStatus: CitizenshipStatus = CitizenshipStatus.NOT_STARTED
|
val citizenshipStatus: CitizenshipStatus = CitizenshipStatus.NOT_STARTED,
|
||||||
|
val isTrackingScore: Boolean = false
|
||||||
)
|
)
|
||||||
+12
-1
@@ -36,12 +36,14 @@ class PezkuwiDashboardRepository(
|
|||||||
val trustScore = queryTrustScore(chainId, accountId)
|
val trustScore = queryTrustScore(chainId, accountId)
|
||||||
val welatiCount = fetchWelatiCount()
|
val welatiCount = fetchWelatiCount()
|
||||||
val kycStatus = runCatching { queryKycStatus(chainId, accountId) }.getOrDefault(CitizenshipStatus.NOT_STARTED)
|
val kycStatus = runCatching { queryKycStatus(chainId, accountId) }.getOrDefault(CitizenshipStatus.NOT_STARTED)
|
||||||
|
val isTrackingScore = queryIsTrackingScore(chainId, accountId)
|
||||||
|
|
||||||
return PezkuwiDashboardData(
|
return PezkuwiDashboardData(
|
||||||
roles = roles.ifEmpty { listOf("Non-Citizen") },
|
roles = roles.ifEmpty { listOf("Non-Citizen") },
|
||||||
trustScore = trustScore,
|
trustScore = trustScore,
|
||||||
welatiCount = welatiCount,
|
welatiCount = welatiCount,
|
||||||
citizenshipStatus = kycStatus
|
citizenshipStatus = kycStatus,
|
||||||
|
isTrackingScore = isTrackingScore
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +75,15 @@ class PezkuwiDashboardRepository(
|
|||||||
}
|
}
|
||||||
}.getOrDefault(BigInteger.ZERO)
|
}.getOrDefault(BigInteger.ZERO)
|
||||||
|
|
||||||
|
suspend fun queryIsTrackingScore(chainId: String, accountId: AccountId): Boolean = runCatching {
|
||||||
|
remoteStorageDataSource.query(chainId) {
|
||||||
|
val module = runtime.metadata.moduleOrNull("StakingScore") ?: return@query false
|
||||||
|
module.storage("StakingStartBlock").query(accountId, binding = { decoded ->
|
||||||
|
decoded != null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}.getOrDefault(false)
|
||||||
|
|
||||||
suspend fun queryFreeBalance(chainId: String, accountId: AccountId): BigInteger = runCatching {
|
suspend fun queryFreeBalance(chainId: String, accountId: AccountId): BigInteger = runCatching {
|
||||||
remoteStorageDataSource.query(chainId) {
|
remoteStorageDataSource.query(chainId) {
|
||||||
val systemModule = runtime.metadata.moduleOrNull("System") ?: return@query BigInteger.ZERO
|
val systemModule = runtime.metadata.moduleOrNull("System") ?: return@query BigInteger.ZERO
|
||||||
|
|||||||
+13
@@ -33,6 +33,7 @@ import io.novafoundation.nova.feature_assets.presentation.balance.list.view.Asse
|
|||||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.ManageAssetsAdapter
|
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.ManageAssetsAdapter
|
||||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.ManageAssetsHolder
|
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.ManageAssetsHolder
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.widget.Toast
|
||||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardAdapter
|
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardAdapter
|
||||||
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardHolder
|
import io.novafoundation.nova.feature_assets.presentation.balance.list.view.PezkuwiDashboardHolder
|
||||||
import io.novafoundation.nova.feature_assets.presentation.citizenship.CitizenshipBottomSheet
|
import io.novafoundation.nova.feature_assets.presentation.citizenship.CitizenshipBottomSheet
|
||||||
@@ -189,6 +190,14 @@ class BalanceListFragment :
|
|||||||
}
|
}
|
||||||
startActivity(Intent.createChooser(intent, null))
|
startActivity(Intent.createChooser(intent, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.showTrackingSuccessEvent.observeEvent {
|
||||||
|
Toast.makeText(requireContext(), R.string.pezkuwi_dashboard_tracking_success, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.trackingLoading.observe(viewLifecycleOwner) { loading ->
|
||||||
|
pezkuwiDashboardAdapter.setTrackingLoading(loading)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun assetClicked(asset: Chain.Asset) {
|
override fun assetClicked(asset: Chain.Asset) {
|
||||||
@@ -278,6 +287,10 @@ class BalanceListFragment :
|
|||||||
viewModel.shareReferralClicked()
|
viewModel.shareReferralClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingClicked() {
|
||||||
|
viewModel.startTrackingClicked()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupRecyclerViewSpacing() {
|
private fun setupRecyclerViewSpacing() {
|
||||||
binder.balanceListAssets.addSpaceItemDecoration {
|
binder.balanceListAssets.addSpaceItemDecoration {
|
||||||
add(SpaceBetween(AssetsHeaderHolder, PezkuwiDashboardHolder, spaceDp = 8))
|
add(SpaceBetween(AssetsHeaderHolder, PezkuwiDashboardHolder, spaceDp = 8))
|
||||||
|
|||||||
+41
-2
@@ -65,7 +65,12 @@ import io.novafoundation.nova.feature_wallet_api.presentation.formatters.amount.
|
|||||||
import io.novafoundation.nova.feature_wallet_api.presentation.model.FractionPartStyling
|
import io.novafoundation.nova.feature_wallet_api.presentation.model.FractionPartStyling
|
||||||
import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase
|
import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase
|
||||||
import io.novafoundation.nova.feature_wallet_connect_api.presentation.mapNumberOfActiveSessionsToUi
|
import io.novafoundation.nova.feature_wallet_connect_api.presentation.mapNumberOfActiveSessionsToUi
|
||||||
|
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService
|
||||||
|
import io.novafoundation.nova.feature_account_api.data.ethereum.transaction.TransactionOrigin
|
||||||
|
import io.novafoundation.nova.runtime.ext.ChainGeneses
|
||||||
|
import io.novafoundation.nova.runtime.multiNetwork.ChainRegistry
|
||||||
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain
|
||||||
|
import io.novasama.substrate_sdk_android.runtime.extrinsic.call
|
||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
@@ -104,7 +109,9 @@ class BalanceListViewModel(
|
|||||||
private val novaCardRestrictionCheckMixin: NovaCardRestrictionCheckMixin,
|
private val novaCardRestrictionCheckMixin: NovaCardRestrictionCheckMixin,
|
||||||
private val maskingModeUseCase: MaskingModeUseCase,
|
private val maskingModeUseCase: MaskingModeUseCase,
|
||||||
private val giftsRestrictionCheckMixin: GiftsRestrictionCheckMixin,
|
private val giftsRestrictionCheckMixin: GiftsRestrictionCheckMixin,
|
||||||
private val pezkuwiDashboardInteractor: PezkuwiDashboardInteractor
|
private val pezkuwiDashboardInteractor: PezkuwiDashboardInteractor,
|
||||||
|
private val extrinsicService: ExtrinsicService,
|
||||||
|
private val chainRegistry: ChainRegistry
|
||||||
) : BaseViewModel(), Browserable.Presentation by Browserable() {
|
) : BaseViewModel(), Browserable.Presentation by Browserable() {
|
||||||
|
|
||||||
private val maskableAmountFormatterFlow = maskableValueFormatterProvider.provideFormatter()
|
private val maskableAmountFormatterFlow = maskableValueFormatterProvider.provideFormatter()
|
||||||
@@ -122,6 +129,12 @@ class BalanceListViewModel(
|
|||||||
private val _shareReferralEvent = MutableLiveData<Event<String>>()
|
private val _shareReferralEvent = MutableLiveData<Event<String>>()
|
||||||
val shareReferralEvent: LiveData<Event<String>> = _shareReferralEvent
|
val shareReferralEvent: LiveData<Event<String>> = _shareReferralEvent
|
||||||
|
|
||||||
|
private val _showTrackingSuccessEvent = MutableLiveData<Event<Unit>>()
|
||||||
|
val showTrackingSuccessEvent: LiveData<Event<Unit>> = _showTrackingSuccessEvent
|
||||||
|
|
||||||
|
private val _trackingLoading = MutableLiveData(false)
|
||||||
|
val trackingLoading: LiveData<Boolean> = _trackingLoading
|
||||||
|
|
||||||
val bannersMixin = promotionBannersMixinFactory.create(bannerSourceFactory.assetsSource(), viewModelScope)
|
val bannersMixin = promotionBannersMixinFactory.create(bannerSourceFactory.assetsSource(), viewModelScope)
|
||||||
|
|
||||||
private val selectedCurrency = currencyInteractor.observeSelectCurrency()
|
private val selectedCurrency = currencyInteractor.observeSelectCurrency()
|
||||||
@@ -239,7 +252,8 @@ class BalanceListViewModel(
|
|||||||
roles = data.roles,
|
roles = data.roles,
|
||||||
trustScore = data.trustScore.toString(),
|
trustScore = data.trustScore.toString(),
|
||||||
welatiCount = NumberFormat.getIntegerInstance().format(data.welatiCount),
|
welatiCount = NumberFormat.getIntegerInstance().format(data.welatiCount),
|
||||||
citizenshipStatus = data.citizenshipStatus
|
citizenshipStatus = data.citizenshipStatus,
|
||||||
|
isTrackingScore = data.isTrackingScore
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
@@ -425,6 +439,31 @@ class BalanceListViewModel(
|
|||||||
_shareReferralEvent.postValue(Event(shareText))
|
_shareReferralEvent.postValue(Event(shareText))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun startTrackingClicked() {
|
||||||
|
if (_trackingLoading.value == true) return
|
||||||
|
_trackingLoading.value = true
|
||||||
|
|
||||||
|
launchUnit {
|
||||||
|
try {
|
||||||
|
val chain = chainRegistry.getChain(ChainGeneses.PEZKUWI_PEOPLE)
|
||||||
|
val result = extrinsicService.submitExtrinsic(chain, TransactionOrigin.SelectedWallet) {
|
||||||
|
call(
|
||||||
|
moduleName = "StakingScore",
|
||||||
|
callName = "start_score_tracking",
|
||||||
|
arguments = emptyMap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
result.getOrThrow()
|
||||||
|
_showTrackingSuccessEvent.postValue(Event(Unit))
|
||||||
|
fullSync()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showError(e.message ?: "Score tracking failed")
|
||||||
|
} finally {
|
||||||
|
_trackingLoading.postValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun novaCardClicked() = launchUnit {
|
fun novaCardClicked() = launchUnit {
|
||||||
novaCardRestrictionCheckMixin.checkRestrictionAndDo {
|
novaCardRestrictionCheckMixin.checkRestrictionAndDo {
|
||||||
router.openNovaCard()
|
router.openNovaCard()
|
||||||
|
|||||||
+6
-1
@@ -42,6 +42,7 @@ import io.novafoundation.nova.feature_wallet_api.presentation.formatters.amount.
|
|||||||
import io.novafoundation.nova.feature_wallet_api.presentation.formatters.amount.FiatFormatter
|
import io.novafoundation.nova.feature_wallet_api.presentation.formatters.amount.FiatFormatter
|
||||||
import io.novafoundation.nova.common.presentation.masking.formatter.MaskableValueFormatterProvider
|
import io.novafoundation.nova.common.presentation.masking.formatter.MaskableValueFormatterProvider
|
||||||
import io.novafoundation.nova.feature_assets.presentation.balance.common.gifts.GiftsRestrictionCheckMixin
|
import io.novafoundation.nova.feature_assets.presentation.balance.common.gifts.GiftsRestrictionCheckMixin
|
||||||
|
import io.novafoundation.nova.feature_account_api.data.extrinsic.ExtrinsicService
|
||||||
import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase
|
import io.novafoundation.nova.feature_wallet_connect_api.domain.sessions.WalletConnectSessionsUseCase
|
||||||
|
|
||||||
@Module(includes = [ViewModelModule::class])
|
@Module(includes = [ViewModelModule::class])
|
||||||
@@ -127,6 +128,8 @@ class BalanceListModule {
|
|||||||
fiatFormatter: FiatFormatter,
|
fiatFormatter: FiatFormatter,
|
||||||
giftsRestrictionCheckMixin: GiftsRestrictionCheckMixin,
|
giftsRestrictionCheckMixin: GiftsRestrictionCheckMixin,
|
||||||
pezkuwiDashboardInteractor: PezkuwiDashboardInteractor,
|
pezkuwiDashboardInteractor: PezkuwiDashboardInteractor,
|
||||||
|
extrinsicService: ExtrinsicService,
|
||||||
|
chainRegistry: ChainRegistry,
|
||||||
): ViewModel {
|
): ViewModel {
|
||||||
return BalanceListViewModel(
|
return BalanceListViewModel(
|
||||||
promotionBannersMixinFactory = promotionBannersMixinFactory,
|
promotionBannersMixinFactory = promotionBannersMixinFactory,
|
||||||
@@ -149,7 +152,9 @@ class BalanceListModule {
|
|||||||
maskingModeUseCase = maskingModeUseCase,
|
maskingModeUseCase = maskingModeUseCase,
|
||||||
fiatFormatter = fiatFormatter,
|
fiatFormatter = fiatFormatter,
|
||||||
giftsRestrictionCheckMixin = giftsRestrictionCheckMixin,
|
giftsRestrictionCheckMixin = giftsRestrictionCheckMixin,
|
||||||
pezkuwiDashboardInteractor = pezkuwiDashboardInteractor
|
pezkuwiDashboardInteractor = pezkuwiDashboardInteractor,
|
||||||
|
extrinsicService = extrinsicService,
|
||||||
|
chainRegistry = chainRegistry
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -6,5 +6,6 @@ data class PezkuwiDashboardModel(
|
|||||||
val roles: List<String>,
|
val roles: List<String>,
|
||||||
val trustScore: String,
|
val trustScore: String,
|
||||||
val welatiCount: String,
|
val welatiCount: String,
|
||||||
val citizenshipStatus: CitizenshipStatus = CitizenshipStatus.NOT_STARTED
|
val citizenshipStatus: CitizenshipStatus = CitizenshipStatus.NOT_STARTED,
|
||||||
|
val isTrackingScore: Boolean = false
|
||||||
)
|
)
|
||||||
+19
-2
@@ -23,22 +23,29 @@ class PezkuwiDashboardAdapter(
|
|||||||
fun onBasvuruClicked()
|
fun onBasvuruClicked()
|
||||||
fun onSignClicked()
|
fun onSignClicked()
|
||||||
fun onShareReferralClicked()
|
fun onShareReferralClicked()
|
||||||
|
fun onStartTrackingClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var model: PezkuwiDashboardModel? = null
|
private var model: PezkuwiDashboardModel? = null
|
||||||
|
private var trackingLoading: Boolean = false
|
||||||
|
|
||||||
fun setModel(model: PezkuwiDashboardModel) {
|
fun setModel(model: PezkuwiDashboardModel) {
|
||||||
this.model = model
|
this.model = model
|
||||||
notifyChangedIfShown()
|
notifyChangedIfShown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setTrackingLoading(loading: Boolean) {
|
||||||
|
this.trackingLoading = loading
|
||||||
|
notifyChangedIfShown()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PezkuwiDashboardHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PezkuwiDashboardHolder {
|
||||||
val binding = ItemPezkuwiDashboardBinding.inflate(parent.inflater(), parent, false)
|
val binding = ItemPezkuwiDashboardBinding.inflate(parent.inflater(), parent, false)
|
||||||
return PezkuwiDashboardHolder(binding, handler)
|
return PezkuwiDashboardHolder(binding, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: PezkuwiDashboardHolder, position: Int) {
|
override fun onBindViewHolder(holder: PezkuwiDashboardHolder, position: Int) {
|
||||||
model?.let { holder.bind(it) }
|
model?.let { holder.bind(it, trackingLoading) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
@@ -59,13 +66,23 @@ class PezkuwiDashboardHolder(
|
|||||||
binder.pezkuwiDashboardBasvuruButton.setOnClickListener { handler.onBasvuruClicked() }
|
binder.pezkuwiDashboardBasvuruButton.setOnClickListener { handler.onBasvuruClicked() }
|
||||||
binder.pezkuwiDashboardSignButton.setOnClickListener { handler.onSignClicked() }
|
binder.pezkuwiDashboardSignButton.setOnClickListener { handler.onSignClicked() }
|
||||||
binder.pezkuwiDashboardShareButton.setOnClickListener { handler.onShareReferralClicked() }
|
binder.pezkuwiDashboardShareButton.setOnClickListener { handler.onShareReferralClicked() }
|
||||||
|
binder.pezkuwiDashboardStartTrackingButton.setOnClickListener { handler.onStartTrackingClicked() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bind(model: PezkuwiDashboardModel) {
|
fun bind(model: PezkuwiDashboardModel, trackingLoading: Boolean = false) {
|
||||||
bindRoles(model.roles)
|
bindRoles(model.roles)
|
||||||
binder.pezkuwiDashboardTrustValue.text = model.trustScore
|
binder.pezkuwiDashboardTrustValue.text = model.trustScore
|
||||||
binder.pezkuwiDashboardWelatiCount.text = model.welatiCount
|
binder.pezkuwiDashboardWelatiCount.text = model.welatiCount
|
||||||
bindButtons(model.citizenshipStatus)
|
bindButtons(model.citizenshipStatus)
|
||||||
|
|
||||||
|
val showTracking = !model.isTrackingScore && model.citizenshipStatus == CitizenshipStatus.APPROVED
|
||||||
|
binder.pezkuwiDashboardStartTrackingButton.visibility = if (showTracking) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
if (showTracking) {
|
||||||
|
binder.pezkuwiDashboardStartTrackingButton.isEnabled = !trackingLoading
|
||||||
|
binder.pezkuwiDashboardStartTrackingButton.text = if (trackingLoading) "..." else
|
||||||
|
binder.root.context.getString(R.string.pezkuwi_dashboard_start_tracking)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindButtons(status: CitizenshipStatus) {
|
private fun bindButtons(status: CitizenshipStatus) {
|
||||||
|
|||||||
@@ -69,6 +69,22 @@
|
|||||||
android:textColor="#FFD54F"
|
android:textColor="#FFD54F"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/pezkuwiDashboardStartTrackingButton"
|
||||||
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:minWidth="0dp"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:text="@string/pezkuwi_dashboard_start_tracking"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:backgroundTint="#FF9800"
|
||||||
|
app:cornerRadius="8dp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user