From 261c7de06f5c1dafa2d140066b11354874195348 Mon Sep 17 00:00:00 2001 From: HashEngineering Date: Tue, 19 Nov 2024 23:26:49 -0800 Subject: [PATCH] fix(dashpay): fix username UI crashes and support recovery during username creation (#1326) * fix: eliminate cast exception in BlockInfoActivity * fix: remove unused fragments in Username Navigation * fix: prevent NPE's * chore: remove unnecessary code in UsernameRegistrationFragment * chore: use dpp v1.5.1-SNAPSHOT * fix: allow 128 char links for verification * fix: simplify coinjoin system notification status updates * fix: cancel work if databased are cleared * fix: more screen fixes * fix: allow credits to be used on WelcomeToDashPayFragment * fix: use a double for mixing status * fix: handle failed restore after failed request * fix: CreateIdentityService fixes --- build.gradle | 2 +- .../res/layout/fragment_verfiy_identity.xml | 2 +- wallet/res/navigation/nav_username.xml | 34 +------------- wallet/res/values-de/strings-dashpay.xml | 1 - wallet/res/values-el/strings-dashpay.xml | 1 - wallet/res/values-es/strings-dashpay.xml | 1 - wallet/res/values-fa/strings-dashpay.xml | 1 - wallet/res/values-fil/strings-dashpay.xml | 1 - wallet/res/values-fr/strings-dashpay.xml | 1 - wallet/res/values-id/strings-dashpay.xml | 1 - wallet/res/values-it/strings-dashpay.xml | 1 - wallet/res/values-ja/strings-dashpay.xml | 1 - wallet/res/values-ko/strings-dashpay.xml | 1 - wallet/res/values-nl/strings-dashpay.xml | 1 - wallet/res/values-pl/strings-dashpay.xml | 1 - wallet/res/values-pt/strings-dashpay.xml | 1 - wallet/res/values-ru/strings-dashpay.xml | 1 - wallet/res/values-sk/strings-dashpay.xml | 1 - wallet/res/values-tr/strings-dashpay.xml | 1 - wallet/res/values-uk/strings-dashpay.xml | 1 - wallet/res/values-zh-rTW/strings-dashpay.xml | 1 - wallet/res/values-zh/strings-dashpay.xml | 1 - wallet/res/values/strings-dashpay.xml | 2 +- .../schildbach/wallet/WalletApplicationExt.kt | 4 +- .../wallet/service/BlockchainServiceImpl.java | 4 +- .../schildbach/wallet/ui/BlockInfoActivity.kt | 2 +- .../ui/dashpay/CreateIdentityService.kt | 8 +++- .../wallet/ui/dashpay/HistoryHeaderAdapter.kt | 3 +- .../ui/main/WalletTransactionsFragment.kt | 13 ++++-- .../schildbach/wallet/ui/more/MoreFragment.kt | 10 +++- .../username/UsernameRegistrationFragment.kt | 39 ++-------------- .../voting/RequestUserNameViewModel.kt | 46 +++++++++++++++---- .../voting/WelcomeToDashPayFragment.kt | 35 ++++++++------ 33 files changed, 99 insertions(+), 124 deletions(-) diff --git a/build.gradle b/build.gradle index a6664eb071..72ec030a17 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { coroutinesVersion = '1.6.4' ok_http_version = '4.9.1' dashjVersion = '21.1.2' - dppVersion = "1.3.1-SNAPSHOT" + dppVersion = "1.5.1-SNAPSHOT" hiltVersion = '2.51' hiltCompilerVersion = '1.2.0' hiltWorkVersion = '1.0.0' diff --git a/wallet/res/layout/fragment_verfiy_identity.xml b/wallet/res/layout/fragment_verfiy_identity.xml index e28520f963..3d0a932033 100644 --- a/wallet/res/layout/fragment_verfiy_identity.xml +++ b/wallet/res/layout/fragment_verfiy_identity.xml @@ -141,7 +141,7 @@ android:ellipsize="middle" android:gravity="center_vertical" android:imeOptions="actionNext" - android:maxLength="75" + android:maxLength="128" tools:visibility="visible" /> diff --git a/wallet/res/navigation/nav_username.xml b/wallet/res/navigation/nav_username.xml index ff19d1e070..fa2a8251e1 100644 --- a/wallet/res/navigation/nav_username.xml +++ b/wallet/res/navigation/nav_username.xml @@ -2,39 +2,9 @@ - - - - - - - - - - - - + tools:layout="@layout/fragment_username_registration"> diff --git a/wallet/res/values-de/strings-dashpay.xml b/wallet/res/values-de/strings-dashpay.xml index 9786edcd11..46635bdd75 100644 --- a/wallet/res/values-de/strings-dashpay.xml +++ b/wallet/res/values-de/strings-dashpay.xml @@ -379,7 +379,6 @@ Benutzernamen Mixing Mixing pausiert Nicht gestartet - %s (%d%%) %s von %s %1$s von %2$s Vollständig gemixt Möchtest du die Einstellung der Privatsphäre wirklich ändern\? diff --git a/wallet/res/values-el/strings-dashpay.xml b/wallet/res/values-el/strings-dashpay.xml index 8bc0157011..9c5fa912dd 100644 --- a/wallet/res/values-el/strings-dashpay.xml +++ b/wallet/res/values-el/strings-dashpay.xml @@ -378,7 +378,6 @@ Ανάμιξη Ανάμειξη σε παύση Δεν ξεκίνησε - %s (%d%%) %s από %s %1$s από%2$s Πλήρως αναμεμειγμένα Είστε σίγουροι ότι θέλετε να αλλάξετε το επίπεδο απορρήτου; diff --git a/wallet/res/values-es/strings-dashpay.xml b/wallet/res/values-es/strings-dashpay.xml index a26b717f51..035f1a3296 100644 --- a/wallet/res/values-es/strings-dashpay.xml +++ b/wallet/res/values-es/strings-dashpay.xml @@ -413,7 +413,6 @@ de Dash Mezclando Mezcla en pausa No iniciado - %s (%d%%) %s of %s %1$s de %2$s Completamente mezclado ¿Estás seguro de que deseas cambiar el nivel de privacidad\? diff --git a/wallet/res/values-fa/strings-dashpay.xml b/wallet/res/values-fa/strings-dashpay.xml index 89589b43ea..1cec9b7fa0 100644 --- a/wallet/res/values-fa/strings-dashpay.xml +++ b/wallet/res/values-fa/strings-dashpay.xml @@ -377,7 +377,6 @@ در حال ترکیب توقف موقت ترکیب شروع نشده - %s(%d%%) %s از %s %1$s از %2$s کاملا ترکیب شده آیا مطمئن هستید که می‌خواهید سطح محرمانگی را تغییر دهید؟ diff --git a/wallet/res/values-fil/strings-dashpay.xml b/wallet/res/values-fil/strings-dashpay.xml index e13121cca2..299961fca1 100644 --- a/wallet/res/values-fil/strings-dashpay.xml +++ b/wallet/res/values-fil/strings-dashpay.xml @@ -380,7 +380,6 @@ Username Paghahalo Nakahinto ang Paghahalo Hindi Nagsimula - %s (%d%%) %s ng %s %1$s ng %2$s Ganap na Nahalo Sigurado ka bang gusto mong baguhin ang antas ng privacy\? diff --git a/wallet/res/values-fr/strings-dashpay.xml b/wallet/res/values-fr/strings-dashpay.xml index 295617e09d..a5d7d8c93c 100644 --- a/wallet/res/values-fr/strings-dashpay.xml +++ b/wallet/res/values-fr/strings-dashpay.xml @@ -412,7 +412,6 @@ Mélange Mélange mis en pause Non démarré - %s (%d%%) %s de %s %1$s de %2$s Entièrement mélangé Souhaitez-vous vraiment modifier le niveau de confidentialité \? diff --git a/wallet/res/values-id/strings-dashpay.xml b/wallet/res/values-id/strings-dashpay.xml index 0b31164413..a8b832963d 100644 --- a/wallet/res/values-id/strings-dashpay.xml +++ b/wallet/res/values-id/strings-dashpay.xml @@ -380,7 +380,6 @@ Dash anda Pencampuran Pencampuran Dijeda Tidak Dimulai - %s (%d%%) %s dari %s %1$s dari %2$s Tercampur Sepenuhnya Apakah Anda yakin ingin mengubah tingkat privasi\? diff --git a/wallet/res/values-it/strings-dashpay.xml b/wallet/res/values-it/strings-dashpay.xml index 65749f111f..3e4a99d1d0 100644 --- a/wallet/res/values-it/strings-dashpay.xml +++ b/wallet/res/values-it/strings-dashpay.xml @@ -413,7 +413,6 @@ Username Miscelazione Miscelazione in pausa Non iniziato - %s (%d %% ) %s di %s %1$s di %2$s Completamente Miscelato Sei sicuro di voler modificare il livello di privacy\? diff --git a/wallet/res/values-ja/strings-dashpay.xml b/wallet/res/values-ja/strings-dashpay.xml index f9b871367d..09f406d6b3 100644 --- a/wallet/res/values-ja/strings-dashpay.xml +++ b/wallet/res/values-ja/strings-dashpay.xml @@ -377,7 +377,6 @@ ミキシング中 ミキシングを一時停止しました 開始していません - %sの%s (%d%%) と%s %2$sの%1$s ミキシング完了しました プライバシーレベルを変更してよろしいですか。 diff --git a/wallet/res/values-ko/strings-dashpay.xml b/wallet/res/values-ko/strings-dashpay.xml index a1154a5d7a..59d3a86b1d 100644 --- a/wallet/res/values-ko/strings-dashpay.xml +++ b/wallet/res/values-ko/strings-dashpay.xml @@ -378,7 +378,6 @@ 믹싱 믹싱이 멈춰짐 시작되지 않음 - %s 중 %s (%d%%) %s %2$s 중 %1$s 완전히 믹싱됨 정말 프라이버시 수준을 변경하시겠습니까\? diff --git a/wallet/res/values-nl/strings-dashpay.xml b/wallet/res/values-nl/strings-dashpay.xml index 325e05dcd0..ed9f32d3b8 100644 --- a/wallet/res/values-nl/strings-dashpay.xml +++ b/wallet/res/values-nl/strings-dashpay.xml @@ -379,7 +379,6 @@ gebruikersnaam Aan het mixen mixen gepauzeerd Niet gestart - %s (%d%%) %s van %s %1$s van %2$s Volledig gemixt Weet je zeker dat je het privacy niveau wilt wijzigen\? diff --git a/wallet/res/values-pl/strings-dashpay.xml b/wallet/res/values-pl/strings-dashpay.xml index 65a5d74ae8..c7e5d9d32e 100644 --- a/wallet/res/values-pl/strings-dashpay.xml +++ b/wallet/res/values-pl/strings-dashpay.xml @@ -414,7 +414,6 @@ Miksowanie Miksowanie zostało zatrzywame Nie rozpoczęto - %s (%d%%) %s lub %s %1$s z %2$s Całkowicie wymieszane Czy na pewno chcesz zmienić poziom prywatności\? diff --git a/wallet/res/values-pt/strings-dashpay.xml b/wallet/res/values-pt/strings-dashpay.xml index c9b0abb98d..cef2aa1be0 100644 --- a/wallet/res/values-pt/strings-dashpay.xml +++ b/wallet/res/values-pt/strings-dashpay.xml @@ -413,7 +413,6 @@ Dash Misturando Mistura Pausada Não iniciado - %s (%d%%) %s de %s %1$s de %2$s Totalmente Misturado Tem certeza de que deseja mudar o nível de privacidade\? diff --git a/wallet/res/values-ru/strings-dashpay.xml b/wallet/res/values-ru/strings-dashpay.xml index af280f6f9a..5527d495f2 100644 --- a/wallet/res/values-ru/strings-dashpay.xml +++ b/wallet/res/values-ru/strings-dashpay.xml @@ -415,7 +415,6 @@ Dash Перемешивание Перемешивание на паузе Не начато - %s (%d %%) %s из %s %1$s из %2$s Полностью перемешано Уверены, что хотите изменить уровень приватности\? diff --git a/wallet/res/values-sk/strings-dashpay.xml b/wallet/res/values-sk/strings-dashpay.xml index dbeec27250..7b506e9b97 100644 --- a/wallet/res/values-sk/strings-dashpay.xml +++ b/wallet/res/values-sk/strings-dashpay.xml @@ -378,7 +378,6 @@ používateľské meno Miešanie Miešanie pozastavené Nespustené - %s (%d%%) %s z %s %1$s z %2$s Plne zmiešané Naozaj chcete zmeniť úroveň ochrany osobných údajov\? diff --git a/wallet/res/values-tr/strings-dashpay.xml b/wallet/res/values-tr/strings-dashpay.xml index e5c105bc89..7e9aeac3eb 100644 --- a/wallet/res/values-tr/strings-dashpay.xml +++ b/wallet/res/values-tr/strings-dashpay.xml @@ -365,7 +365,6 @@ Karıştırma Karıştırma Duraklatıldı Başlamadı - %s (%d%%) %s / %s %1$s / %2$s Tamamen Karıştırılmış Gizlilik düzeyini değiştirmek istediğinizden emin misiniz\? diff --git a/wallet/res/values-uk/strings-dashpay.xml b/wallet/res/values-uk/strings-dashpay.xml index f7f3962449..1dc85c5bdb 100644 --- a/wallet/res/values-uk/strings-dashpay.xml +++ b/wallet/res/values-uk/strings-dashpay.xml @@ -367,7 +367,6 @@ Змішування Змішування на паузі Не розпачато - %s(%d%%)%s з %s %1$s з %2$s Повністю змішано Ви впевнені, що бажаєте змінити рівень конфіденційності\? diff --git a/wallet/res/values-zh-rTW/strings-dashpay.xml b/wallet/res/values-zh-rTW/strings-dashpay.xml index 615aea58ec..39258c5db5 100644 --- a/wallet/res/values-zh-rTW/strings-dashpay.xml +++ b/wallet/res/values-zh-rTW/strings-dashpay.xml @@ -379,7 +379,6 @@ 混合 混合暫停 尚未開始 - %s (%d%%) %s of %s %1$s of %2$s 充分混合 您確定要變更隱私等級嗎? diff --git a/wallet/res/values-zh/strings-dashpay.xml b/wallet/res/values-zh/strings-dashpay.xml index e99ee78fea..a04e60509d 100644 --- a/wallet/res/values-zh/strings-dashpay.xml +++ b/wallet/res/values-zh/strings-dashpay.xml @@ -409,7 +409,6 @@ 混币 混币暂停 尚未开始 - %s中的 %s (%d%%) %s %2$s中的%1$s 完全混币 您确定要改变隐私级别吗\? diff --git a/wallet/res/values/strings-dashpay.xml b/wallet/res/values/strings-dashpay.xml index bdce7d94cd..36d64e6c9c 100644 --- a/wallet/res/values/strings-dashpay.xml +++ b/wallet/res/values/strings-dashpay.xml @@ -410,7 +410,7 @@ Mixing Mixing Paused Not Started - %s (%d%%) %s of %s + %s (%.1f%%) %s / %s %1$s of %2$s Fully Mixed Are you sure you want to change the privacy level? diff --git a/wallet/src/de/schildbach/wallet/WalletApplicationExt.kt b/wallet/src/de/schildbach/wallet/WalletApplicationExt.kt index abb700b3a0..429e10b849 100644 --- a/wallet/src/de/schildbach/wallet/WalletApplicationExt.kt +++ b/wallet/src/de/schildbach/wallet/WalletApplicationExt.kt @@ -19,6 +19,7 @@ package de.schildbach.wallet +import androidx.work.WorkManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asCoroutineDispatcher @@ -33,13 +34,14 @@ object WalletApplicationExt { */ fun WalletApplication.clearDatabases(isWalletWipe: Boolean) { val scope = CoroutineScope(Dispatchers.IO) - + val context = this scope.launch { platformSyncService.clearDatabases() if (isWalletWipe) { transactionMetadataProvider.clear() } platformRepo.clearDatabase(isWalletWipe) + WorkManager.getInstance(context).cancelAllWork() } } } \ No newline at end of file diff --git a/wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.java b/wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.java index 23856e6725..a323d46469 100644 --- a/wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.java +++ b/wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.java @@ -224,7 +224,7 @@ public class BlockchainServiceImpl extends LifecycleService implements Blockchai private final Executor executor = Executors.newSingleThreadExecutor(); private int syncPercentage = 0; // 0 to 100% private MixingStatus mixingStatus = MixingStatus.NOT_STARTED; - private Double mixingProgress = 0.0; + private double mixingProgress = 0.0; private ForegroundService foregroundService = ForegroundService.NONE; // Risk Analyser for Transactions that is PeerGroup Aware @@ -1088,7 +1088,7 @@ private Notification createCoinJoinNotification() { final String message = getString( R.string.coinjoin_progress, getString(statusStringId), - mixingProgress.intValue(), + mixingProgress, decimalFormat.format(MonetaryExtKt.toBigDecimal(mixedBalance)), decimalFormat.format(MonetaryExtKt.toBigDecimal(totalBalance)) ); diff --git a/wallet/src/de/schildbach/wallet/ui/BlockInfoActivity.kt b/wallet/src/de/schildbach/wallet/ui/BlockInfoActivity.kt index 8fc45320d8..0526a14747 100644 --- a/wallet/src/de/schildbach/wallet/ui/BlockInfoActivity.kt +++ b/wallet/src/de/schildbach/wallet/ui/BlockInfoActivity.kt @@ -20,7 +20,7 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle -import android.widget.Toolbar +import androidx.appcompat.widget.Toolbar import dagger.hilt.android.AndroidEntryPoint import de.schildbach.wallet.data.BlockInfo import de.schildbach.wallet_test.R diff --git a/wallet/src/de/schildbach/wallet/ui/dashpay/CreateIdentityService.kt b/wallet/src/de/schildbach/wallet/ui/dashpay/CreateIdentityService.kt index 6e28c8b780..afdda1c89a 100644 --- a/wallet/src/de/schildbach/wallet/ui/dashpay/CreateIdentityService.kt +++ b/wallet/src/de/schildbach/wallet/ui/dashpay/CreateIdentityService.kt @@ -337,6 +337,9 @@ class CreateIdentityService : LifecycleService() { if (blockchainIdentityData.creationStateErrorMessage?.contains("preorderDocument was not found with a salted domain hash") == true) { blockchainIdentityData.creationState = CreationState.PREORDER_REGISTERING platformRepo.updateBlockchainIdentityData(blockchainIdentityData) + } else if (blockchainIdentityData.creationStateErrorMessage?.contains("missing domain document for") == true) { + blockchainIdentityData.creationState = CreationState.PREORDER_REGISTERING + platformRepo.updateBlockchainIdentityData(blockchainIdentityData) } else if (retryWithNewUserName) { // lets rewind the state to allow for a new username registration or request // it may have failed later in the process @@ -776,6 +779,9 @@ class CreateIdentityService : LifecycleService() { } } + /** + * restores an identity using information from the wallet and platform + */ private suspend fun restoreIdentity(identity: ByteArray) { log.info("Restoring identity and username") try { @@ -863,7 +869,7 @@ class CreateIdentityService : LifecycleService() { platformRepo.updateIdentityCreationState(blockchainIdentityData, CreationState.REQUESTED_NAME_CHECKING) // check if the network has this name in the queue for voting - val contestedNames = platformRepo.platform.names.getContestedNames() + val contestedNames = platformRepo.platform.names.getAllContestedNames() contestedNames.forEach { name -> val voteContenders = platformRepo.getVoteContenders(name) diff --git a/wallet/src/de/schildbach/wallet/ui/dashpay/HistoryHeaderAdapter.kt b/wallet/src/de/schildbach/wallet/ui/dashpay/HistoryHeaderAdapter.kt index 55ccd69218..ba2b043424 100644 --- a/wallet/src/de/schildbach/wallet/ui/dashpay/HistoryHeaderAdapter.kt +++ b/wallet/src/de/schildbach/wallet/ui/dashpay/HistoryHeaderAdapter.kt @@ -103,7 +103,8 @@ class HistoryHeaderAdapter( if (blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.USERNAME_REGISTERING && (blockchainIdentityData.creationStateErrorMessage.contains("Document transitions with duplicate unique properties") || blockchainIdentityData.creationStateErrorMessage.contains("Document Contest for vote_poll ContestedDocumentResourceVotePoll")) || - blockchainIdentityData.creationStateErrorMessage.contains(Regex("does not have .* as a contender")) + blockchainIdentityData.creationStateErrorMessage.contains(Regex("does not have .* as a contender")) || + blockchainIdentityData.creationStateErrorMessage.contains("missing domain document for ") ) { binding.identityCreation.title.text = binding.root.context.getString(R.string.processing_username_unavailable_title) binding.identityCreation.subtitle.visibility = View.VISIBLE diff --git a/wallet/src/de/schildbach/wallet/ui/main/WalletTransactionsFragment.kt b/wallet/src/de/schildbach/wallet/ui/main/WalletTransactionsFragment.kt index b485ff29a6..8f3265a626 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/WalletTransactionsFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/WalletTransactionsFragment.kt @@ -261,15 +261,22 @@ class WalletTransactionsFragment : Fragment(R.layout.wallet_transactions_fragmen private fun openIdentityCreation() { viewModel.blockchainIdentity.value?.let { blockchainIdentityData -> if (blockchainIdentityData.creationStateErrorMessage != null) { - if (blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.USERNAME_REGISTERING || - blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.REQUESTED_NAME_CHECKING) { + // Do we need to have the user request a new username + val errorMessage = blockchainIdentityData.creationStateErrorMessage + val needsNewUsername = blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.USERNAME_REGISTERING && + (errorMessage.contains("Document transitions with duplicate unique properties") || + errorMessage.contains("missing domain document for")) + if (needsNewUsername || + // do we need this, cause the error could be due to a stale node + blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.REQUESTED_NAME_CHECKING && + !errorMessage.contains("invalid quorum: quorum not found")) { startActivity(CreateUsernameActivity.createIntentReuseTransaction(requireActivity(), blockchainIdentityData)) } else { Toast.makeText(requireContext(), blockchainIdentityData.creationStateErrorMessage, Toast.LENGTH_LONG).show() } } else if (blockchainIdentityData.creationState == BlockchainIdentityData.CreationState.DONE) { startActivity(Intent(requireActivity(), SearchUserActivity::class.java)) - //hide "Hello Card" after first click + // hide "Hello Card" after first click viewModel.dismissUsernameCreatedCard() } } diff --git a/wallet/src/de/schildbach/wallet/ui/more/MoreFragment.kt b/wallet/src/de/schildbach/wallet/ui/more/MoreFragment.kt index f16df916e7..4fefc975a9 100644 --- a/wallet/src/de/schildbach/wallet/ui/more/MoreFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/more/MoreFragment.kt @@ -244,7 +244,13 @@ class MoreFragment : Fragment(R.layout.fragment_more) { } ?: "Voting Period not found" when (it.usernameRequested) { UsernameRequestStatus.SUBMITTING, - UsernameRequestStatus.SUBMITTED, + UsernameRequestStatus.SUBMITTED -> { + binding.requestedUsernameTitle.text = mainActivityViewModel.getRequestedUsername() + binding.requestedUsernameSubtitleTwo.isVisible = false + binding.retryRequestButton.isVisible = false + binding.requestedUsernameIcon.setImageResource(R.drawable.ic_join_dashpay) + binding.requestedUsernameArrow.isVisible = true + } UsernameRequestStatus.VOTING -> { binding.requestedUsernameTitle.text = mainActivityViewModel.getRequestedUsername() binding.requestedUsernameSubtitleTwo.text = @@ -414,7 +420,7 @@ class MoreFragment : Fragment(R.layout.fragment_more) { } } else { binding.editUpdateSwitcher.isVisible = false - binding.invite.isVisible = true + binding.invite.isVisible = Constants.SUPPORTS_INVITES } } diff --git a/wallet/src/de/schildbach/wallet/ui/username/UsernameRegistrationFragment.kt b/wallet/src/de/schildbach/wallet/ui/username/UsernameRegistrationFragment.kt index 85f697a973..e55307078c 100644 --- a/wallet/src/de/schildbach/wallet/ui/username/UsernameRegistrationFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/username/UsernameRegistrationFragment.kt @@ -21,22 +21,14 @@ import android.annotation.SuppressLint import android.graphics.Typeface import android.graphics.drawable.AnimationDrawable import android.os.Bundle -import android.os.Handler -import android.os.Parcelable -import android.text.Editable import android.text.SpannableString -import android.text.TextWatcher import android.text.style.StyleSpan import android.view.View import android.view.animation.AnimationUtils import android.widget.TextView -import androidx.core.content.res.ResourcesCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController import dagger.hilt.android.AndroidEntryPoint -import de.schildbach.wallet.Constants import de.schildbach.wallet.WalletApplication import de.schildbach.wallet.database.entity.BlockchainIdentityData import de.schildbach.wallet.ui.dashpay.DashPayViewModel @@ -46,6 +38,7 @@ import de.schildbach.wallet_test.R import de.schildbach.wallet_test.databinding.FragmentUsernameRegistrationBinding import kotlinx.coroutines.ExperimentalCoroutinesApi import org.dash.wallet.common.ui.viewBinding +import org.dashj.platform.sdk.platform.Names @AndroidEntryPoint @@ -81,30 +74,6 @@ class UsernameRegistrationFragment : Fragment(R.layout.fragment_username_registr initViewModel() walletApplication = requireActivity().application as WalletApplication - - // TODO: we probably don't need this - createUsernameArgs = arguments?.getParcelable(CREATE_USER_NAME_ARGS) - // why are the args not passed via the nav graph? - // TODO: fix the passing of arguments or just use the dashPayViewModel - if (createUsernameArgs == null) - createUsernameArgs = dashPayViewModel.createUsernameArgs - when (createUsernameArgs?.actions) { - CreateUsernameActions.DISPLAY_COMPLETE -> { - this.completeUsername = createUsernameArgs?.userName!! - showCompleteState() - doneAndDismiss() - } - CreateUsernameActions.REUSE_TRANSACTION -> { - reuseTransaction = true - } - CreateUsernameActions.FROM_INVITE -> { - // don't show the keyboard if launched from invite - useInvite = true - } - else -> { - // not sure what we need to do here - } - } } @SuppressLint("ResourceType") @@ -120,6 +89,7 @@ class UsernameRegistrationFragment : Fragment(R.layout.fragment_username_registr private fun initViewModel() { dashPayViewModel.blockchainIdentity.observe(viewLifecycleOwner) { + completeUsername = it?.username ?: "" when { it?.creationStateErrorMessage != null -> { requireActivity().finish() @@ -127,7 +97,6 @@ class UsernameRegistrationFragment : Fragment(R.layout.fragment_username_registr it?.creationState == BlockchainIdentityData.CreationState.DONE || it?.creationState == BlockchainIdentityData.CreationState.VOTING -> { - completeUsername = it.username ?: "" showCompleteState() } @@ -151,7 +120,7 @@ class UsernameRegistrationFragment : Fragment(R.layout.fragment_username_registr binding.orbitView.findViewById(R.id.username_1st_letter).text = completeUsername[0].toString() val text = getString( - if (requestUsernameViewModel.isUsernameContestable()) { + if (Names.isUsernameContestable(completeUsername)) { R.string.request_complete_message } else { R.string.identity_complete_message @@ -170,7 +139,7 @@ class UsernameRegistrationFragment : Fragment(R.layout.fragment_username_registr private fun showProcessingState() { if (!isProcessing) { val username = requestUsernameViewModel.requestedUserName!! - val text = getString(if (requestUsernameViewModel.isUsernameContestable()) { + val text = getString(if (Names.isUsernameContestable(completeUsername)) { R.string.username_being_requested } else { R.string.username_being_created diff --git a/wallet/src/de/schildbach/wallet/ui/username/voting/RequestUserNameViewModel.kt b/wallet/src/de/schildbach/wallet/ui/username/voting/RequestUserNameViewModel.kt index fe7c60bd12..7c892f8521 100644 --- a/wallet/src/de/schildbach/wallet/ui/username/voting/RequestUserNameViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/username/voting/RequestUserNameViewModel.kt @@ -92,6 +92,7 @@ class RequestUserNameViewModel @Inject constructor( ) : ViewModel() { companion object { private val log = LoggerFactory.getLogger(RequestUserNameViewModel::class.java) + private val CONTEST_DOCUMENT_FEE = Coin.valueOf(0, 20).value * 1000 } private val workerJob = SupervisorJob() private val viewModelWorkerScope = CoroutineScope(Dispatchers.IO + workerJob) @@ -103,7 +104,10 @@ class RequestUserNameViewModel @Inject constructor( var identity: BlockchainIdentityData? = null var requestedUserName: String? = null - var identityBalance: Long = 0L + + private val _identityBalance = MutableStateFlow(0L) + val identityBalance: StateFlow + get() = _identityBalance private val _walletBalance = MutableStateFlow(Coin.ZERO) val walletBalance: StateFlow @@ -130,8 +134,22 @@ class RequestUserNameViewModel @Inject constructor( suspend fun hasUserCancelledVerification(): Boolean = identityConfig.get(BlockchainIdentityConfig.CANCELED_REQUESTED_USERNAME_LINK) ?: false - fun canAffordNonContestedUsername(): Boolean = _walletBalance.value >= Constants.DASH_PAY_FEE - fun canAffordContestedUsername(): Boolean = _walletBalance.value >= Constants.DASH_PAY_FEE_CONTESTED + fun canAffordNonContestedUsername(): Boolean { + return if (identity?.userId != null) { + val credits = _identityBalance.value + credits > Constants.DASH_PAY_FEE.value/10 * 1000 + } else { + _walletBalance.value >= Constants.DASH_PAY_FEE + } + } + fun canAffordContestedUsername(): Boolean { + return if (identity?.userId != null) { + val credits = _identityBalance.value + credits > CONTEST_DOCUMENT_FEE + } else { + _walletBalance.value >= Constants.DASH_PAY_FEE_CONTESTED + } + } val myUsernameRequest: Flow get() = _myUsernameRequest @@ -147,19 +165,24 @@ class RequestUserNameViewModel @Inject constructor( .filterNotNull() .onEach { identity = identityConfig.load() - identityBalance = identity?.let { identity -> - platformRepo.getIdentityBalance(Identifier.from(identity.userId)).balance + _identityBalance.value = identity?.let { identity -> + try { + platformRepo.getIdentityBalance(Identifier.from(identity.userId)).balance + } catch (e: Exception) { + // need to try again later + -1 + } } ?: 0 log.info("identity balance: {}", identityBalance) if (requestedUserName == null) { requestedUserName = identityConfig.get(USERNAME) } } - .flatMapLatest { usernameRequestDao.observeRequest(UsernameRequest.getRequestId(it, requestedUserName!!)) } + .flatMapLatest { usernameRequestDao.observeRequest(UsernameRequest.getRequestId(it, requestedUserName ?: "")) } .onEach { if (it != null) { _myUsernameRequest.value = it - } else { + } else if (requestedUserName != null) { identity?.let { identityData -> _myUsernameRequest.value = UsernameRequest( UsernameRequest.getRequestId(identityData.userId!!, requestedUserName!!), @@ -173,6 +196,8 @@ class RequestUserNameViewModel @Inject constructor( false ) } + } else { + _myUsernameRequest.value = null } } .launchIn(viewModelWorkerScope) @@ -355,9 +380,9 @@ class RequestUserNameViewModel @Inject constructor( // if we have an identity, then we must use our identity balance val enoughIdentityBalance = if (contestable) { - identityBalance >= Constants.DASH_PAY_FEE_CONTESTED.value * 1000 + _identityBalance.value >= CONTEST_DOCUMENT_FEE } else { - identityBalance >= Constants.DASH_PAY_FEE.value / 3 * 1000 + _identityBalance.value >= Constants.DASH_PAY_FEE.value / 3 * 1000 } val enoughBalance = if (contestable) { _walletBalance.value >= Constants.DASH_PAY_FEE_CONTESTED @@ -369,7 +394,7 @@ class RequestUserNameViewModel @Inject constructor( usernameLengthValid = validLength, usernameCharactersValid = validCharacters && !startOrEndWithHyphen, usernameContestable = contestable, - enoughBalance = if (identityBalance > 0) enoughIdentityBalance else enoughBalance, + enoughBalance = if (identityBalance.value > 0) enoughIdentityBalance else enoughBalance, usernameTooShort = username.isEmpty(), usernameSubmittedError = false, usernameCheckSuccess = false, @@ -378,6 +403,7 @@ class RequestUserNameViewModel @Inject constructor( return validCharacters && validLength } + @Throws(NullPointerException::class) fun isUsernameContestable(): Boolean { return Names.isUsernameContestable(requestedUserName!!) } diff --git a/wallet/src/de/schildbach/wallet/ui/username/voting/WelcomeToDashPayFragment.kt b/wallet/src/de/schildbach/wallet/ui/username/voting/WelcomeToDashPayFragment.kt index d32281adf5..28e1347dd6 100644 --- a/wallet/src/de/schildbach/wallet/ui/username/voting/WelcomeToDashPayFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/username/voting/WelcomeToDashPayFragment.kt @@ -27,20 +27,27 @@ class WelcomeToDashPayFragment : Fragment(R.layout.fragment_welcome_to_dashpay) } requestUserNameViewModel.walletBalance.observe(viewLifecycleOwner) { - if (!requestUserNameViewModel.canAffordNonContestedUsername()) { - binding.balanceRequirementDisclaimer.text = getString( - R.string.welcome_request_username_min_balance_disclaimer_noncontested, - Constants.DASH_PAY_FEE.toPlainString() - ) - } else if (!requestUserNameViewModel.canAffordContestedUsername()) { - binding.balanceRequirementDisclaimer.text = getString( - R.string.welcome_request_username_min_balance_disclaimer_all, - requestUserNameViewModel.walletBalance.value.toPlainString(), - Constants.DASH_PAY_FEE_CONTESTED.toPlainString() - ) - } - binding.balanceRequirementDisclaimer.isVisible = !requestUserNameViewModel.canAffordContestedUsername() - binding.welcomeDashpayContinueBtn.isEnabled = requestUserNameViewModel.canAffordNonContestedUsername() + updateView() } + requestUserNameViewModel.identityBalance.observe(viewLifecycleOwner) { + updateView() + } + } + + fun updateView() { + if (!requestUserNameViewModel.canAffordNonContestedUsername()) { + binding.balanceRequirementDisclaimer.text = getString( + R.string.welcome_request_username_min_balance_disclaimer_noncontested, + Constants.DASH_PAY_FEE.toPlainString() + ) + } else if (!requestUserNameViewModel.canAffordContestedUsername()) { + binding.balanceRequirementDisclaimer.text = getString( + R.string.welcome_request_username_min_balance_disclaimer_all, + requestUserNameViewModel.walletBalance.value.toPlainString(), + Constants.DASH_PAY_FEE_CONTESTED.toPlainString() + ) + } + binding.balanceRequirementDisclaimer.isVisible = !requestUserNameViewModel.canAffordContestedUsername() + binding.welcomeDashpayContinueBtn.isEnabled = requestUserNameViewModel.canAffordNonContestedUsername() } }