Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PERA-1707 :: Create recovery hd address loading animation #167

Open
wants to merge 10 commits into
base: PERA-1353-bottomsheet-hd-wallet
Choose a base branch
from
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ dependencies {

implementation libs.room.runtime
implementation libs.room.ktx
debugImplementation libs.androidx.ui.tooling
ksp libs.room.compiler

implementation libs.navigation.fragment.ktx
Expand Down Expand Up @@ -300,6 +301,7 @@ dependencies {
ksp libs.glide.compiler

implementation libs.lottie
implementation libs.lottie.compose

implementation libs.retrofit
implementation libs.converter.gson
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.algorand.android.R
import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import com.algorand.android.ui.compose.widget.PeraSecondaryButton
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -40,7 +40,7 @@ class VerifyLedgerInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_check),
contentDescription = stringResource(id = R.string.check),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ package com.algorand.android.modules.onboarding.recoverypassphrase.enterpassphra

import android.os.Bundle
import android.view.View
import androidx.compose.foundation.layout.Box
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.navArgs
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.algorand.android.MainNavigationDirections
import com.algorand.android.R
import com.algorand.android.core.DaggerBaseFragment
Expand All @@ -32,6 +38,8 @@ import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.models.ToolbarConfiguration
import com.algorand.android.modules.onboarding.recoverypassphrase.options.ui.RecoverOptionsBottomSheet
import com.algorand.android.modules.onboarding.recoverypassphrase.options.ui.RecoverOptionsBottomSheet.Companion.RESULT_KEY
import com.algorand.android.ui.compose.theme.PeraTheme
import com.algorand.android.ui.compose.widget.AnimationLoader
import com.algorand.android.utils.Event
import com.algorand.android.utils.delegation.keyboardvisibility.KeyboardHandlerDelegation
import com.algorand.android.utils.delegation.keyboardvisibility.KeyboardHandlerDelegationImpl
Expand All @@ -48,23 +56,23 @@ import kotlinx.coroutines.flow.map

@AndroidEntryPoint
class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recover_with_passphrase),
KeyboardHandlerDelegation by KeyboardHandlerDelegationImpl(), LoadingDialogFragment.DismissListener {
KeyboardHandlerDelegation by KeyboardHandlerDelegationImpl(),
LoadingDialogFragment.DismissListener {

private val toolbarConfiguration = ToolbarConfiguration(
startIconResId = R.drawable.ic_left_arrow,
startIconClick = ::navBack
)

override val fragmentConfiguration = FragmentConfiguration(toolbarConfiguration = toolbarConfiguration)
override val fragmentConfiguration =
FragmentConfiguration(toolbarConfiguration = toolbarConfiguration)

private val args by navArgs<RecoverWithPassphraseFragmentArgs>()

private val recoverWithPassphraseViewModel: RecoverWithPassphraseViewModel by viewModels()

private val binding by viewBinding(FragmentRecoverWithPassphraseBinding::bind)

private var loadingDialogFragment: LoadingDialogFragment? = null

private val recoverPassphraseTitleHeight by lazy { binding.recoverPassphraseTitle.height }

private val passphraseInputGroupListener = object : Listener {
Expand Down Expand Up @@ -93,6 +101,20 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
}
}

private fun hideComposeAnimationLoader() {
binding.scrollView.visibility = View.VISIBLE
binding.passphraseWordSuggestor.visibility = View.VISIBLE
binding.recoverButton.visibility = View.VISIBLE
binding.loadingAnimationCompose.visibility = View.GONE
}

private fun showComposeAnimationLoader() {
binding.scrollView.visibility = View.GONE
binding.passphraseWordSuggestor.visibility = View.GONE
binding.recoverButton.visibility = View.GONE
binding.loadingAnimationCompose.visibility = View.VISIBLE
}

private val wordSuggestorListener = PassphraseWordSuggestor.Listener { word ->
recoverWithPassphraseViewModel.onFocusedInputChanged(value = word)
binding.passphraseInputGroup.focusNextItem()
Expand All @@ -118,9 +140,10 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
if (it != null) binding.passphraseInputGroup.updatePassphraseInputsConfiguration(it)
}

private val unfocusedPassphraseItemCollector: suspend (PassphraseInputConfiguration?) -> Unit = {
if (it != null) binding.passphraseInputGroup.updatePassphraseInputsConfiguration(it)
}
private val unfocusedPassphraseItemCollector: suspend (PassphraseInputConfiguration?) -> Unit =
{
if (it != null) binding.passphraseInputGroup.updatePassphraseInputsConfiguration(it)
}

private val globalErrorEventCollector: suspend (Event<Int>?) -> Unit = {
it?.consume()?.run {
Expand All @@ -142,9 +165,10 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
}
}

private val navToNameRegistrationScreenEventCollector: suspend (Event<AccountCreation>?) -> Unit = {
it?.consume()?.run { navigateToSuccess(this) }
}
private val navToNameRegistrationScreenEventCollector: suspend (Event<AccountCreation>?) -> Unit =
{
it?.consume()?.run { navigateToSuccess(this) }
}

private val navToImportRekeyedAccountEventCollector: suspend (
Event<Pair<AccountCreation, List<String>>>?
Expand All @@ -163,7 +187,23 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
registerKeyboardHandlerDelegation(baseFragment = this, onKeyboardOpenedListener = onKeyboardOpenedListener)
registerKeyboardHandlerDelegation(
baseFragment = this,
onKeyboardOpenedListener = onKeyboardOpenedListener
)
binding.loadingAnimationCompose.setContent {
PeraTheme {
Box {
AnimationLoader(
modifier = Modifier.align(alignment = Alignment.Center),
start = ImageVector.vectorResource(R.drawable.ic_ledger_old_export),
end = ImageVector.vectorResource(R.drawable.ic_phone_new),
lottie = LottieCompositionSpec.RawRes(resId = R.raw.loading_dots),
description = "Searching your accounts"
)
}
}
}
initUi()
loadData()
initObservers()
Expand All @@ -180,7 +220,9 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
with(binding) {
passphraseInputGroup.setListener(passphraseInputGroupListener)
passphraseWordSuggestor.listener = wordSuggestorListener
recoverButton.setOnClickListener { recoverWithPassphraseViewModel.onRecoverButtonClick() }
recoverButton.setOnClickListener {
recoverWithPassphraseViewModel.onRecoverButtonClick()
}
}
}

Expand Down Expand Up @@ -255,7 +297,12 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
}

private fun customizeToolbar() {
getAppToolbar()?.setEndButton(button = IconButton(R.drawable.ic_more, onClick = ::onOptionsClick))
getAppToolbar()?.setEndButton(
button = IconButton(
R.drawable.ic_more,
onClick = ::onOptionsClick
)
)
}

private fun pasteClipboard() {
Expand All @@ -266,7 +313,9 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
private fun navigateToSuccess(accountCreation: AccountCreation) {
nav(
RecoverWithPassphraseFragmentDirections
.actionRecoverWithPassphraseFragmentToRecoverAccountNameRegistrationFragment(accountCreation)
.actionRecoverWithPassphraseFragmentToRecoverAccountNameRegistrationFragment(
accountCreation
)
)
}

Expand All @@ -289,7 +338,10 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov
private fun scrollToFocusedInput() {
with(binding) {
val focusedInput = passphraseInputGroup.focusedChild ?: return
scrollView.smoothScrollTo(0, (focusedInput.y - focusedInput.height + recoverPassphraseTitleHeight).toInt())
scrollView.smoothScrollTo(
0,
(focusedInput.y - focusedInput.height + recoverPassphraseTitleHeight).toInt()
)
}
}

Expand All @@ -312,19 +364,17 @@ class RecoverWithPassphraseFragment : DaggerBaseFragment(R.layout.fragment_recov

private fun showLoadingFragment() {
hideLoadingFragment()
loadingDialogFragment = LoadingDialogFragment.show(
childFragmentManager = childFragmentManager,
descriptionResId = R.string.fetching_rekeyed_accounts,
isCancellable = true
)
showComposeAnimationLoader()
}

private fun hideLoadingFragment() {
loadingDialogFragment?.dismissAllowingStateLoss()
loadingDialogFragment = null
hideComposeAnimationLoader()
}

private fun navToImportRekeyedAccount(accountCreation: AccountCreation, rekeyedAccountAddresses: List<String>) {
private fun navToImportRekeyedAccount(
accountCreation: AccountCreation,
rekeyedAccountAddresses: List<String>
) {
nav(
RecoverWithPassphraseFragmentDirections
.actionRecoverWithPassphraseFragmentToRekeyedAccountSelectionFragment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.algorand.android.utils.splitMnemonic
import com.algorand.android.utils.toShortenedAddress
import com.algorand.wallet.account.detail.domain.model.AccountType
import com.algorand.wallet.account.detail.domain.model.AccountType.Companion.wordCount
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import java.util.Locale
import javax.inject.Inject
Expand Down Expand Up @@ -126,9 +127,14 @@ class RecoverWithPassphrasePreviewUseCase @Inject constructor(
)
}

@SuppressWarnings("MagicNumber")
fun validateEnteredMnemonics(preview: RecoverWithPassphrasePreview) = flow {
try {
emit(preview.copy(showLoadingDialogEvent = Event(Unit)))
// faking the duration of this process for some time before moving forward
// so the loading animation is effective.
// After deleting it delete also the @SuppressWarnings("MagicNumber")
delay(2500L)
val mnemonics = passphraseInputConfigurationUtil.getOrderedInput(preview.passphraseInputGroupConfiguration)
val privateKey = Sdk.mnemonicToPrivateKey(mnemonics.lowercase(Locale.ENGLISH))
if (privateKey == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraCard
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import com.algorand.android.ui.compose.widget.PeraTitleText
import com.algorand.wallet.account.detail.domain.model.AccountType
Expand All @@ -67,7 +67,7 @@ class RecoverAccountInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_key),
contentDescription = stringResource(id = R.string.key),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import com.algorand.android.ui.compose.widget.PeraSecondaryButton
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -37,7 +37,7 @@ class RecoverAccountResultInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_check),
contentDescription = stringResource(id = R.string.check),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -38,7 +38,7 @@ class RekeyToLedgerAccountVerifyInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_check),
contentDescription = stringResource(id = R.string.check),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -52,7 +52,7 @@ class RekeyToStandardAccountVerifyInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_check),
contentDescription = stringResource(id = R.string.check),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.algorand.android.models.FragmentConfiguration
import com.algorand.android.ui.common.BaseInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -51,7 +51,7 @@ class UndoRekeyVerifyInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_check),
contentDescription = stringResource(id = R.string.check),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import com.algorand.android.ui.common.warningconfirmation.BackupInfoFragmentDire
import com.algorand.android.ui.common.warningconfirmation.BackupInfoFragmentDirections.Companion.actionBackupInfoFragmentToWriteDownInfoFragment
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import com.algorand.android.ui.compose.widget.PeraSecondaryButton
import com.algorand.android.utils.browser.openRecoveryPassphraseSupportUrl
Expand Down Expand Up @@ -60,7 +60,7 @@ class BackupInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_shield),
contentDescription = stringResource(R.string.shield),
modifier = modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import com.algorand.android.ui.common.warningconfirmation.WriteDownInfoFragmentD
import com.algorand.android.ui.common.warningconfirmation.WriteDownInfoFragmentDirections.Companion.actionWriteDownInfoFragmentToBackupPassphrasesNavigation
import com.algorand.android.ui.compose.widget.PeraBodyText
import com.algorand.android.ui.compose.widget.PeraHeadlineText
import com.algorand.android.ui.compose.widget.PeraIconBig
import com.algorand.android.ui.compose.widget.PeraIcon
import com.algorand.android.ui.compose.widget.PeraPrimaryButton
import com.algorand.android.ui.compose.widget.PeraSecondaryButton
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -54,7 +54,7 @@ class WriteDownInfoFragment : BaseInfoFragment() {

@Composable
override fun Icon(modifier: Modifier) =
PeraIconBig(
PeraIcon(
painter = painterResource(id = R.drawable.ic_pen),
contentDescription = stringResource(R.string.pen),
modifier = modifier
Expand Down
Loading
Loading