diff --git a/build.gradle b/build.gradle index 9cb130ff5..9b06aef33 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ buildscript { // UI materialVersion = "1.6.1" browserVersion = "1.3.0" - constrainLayoutVersion = '2.1.4' + constrainLayoutVersion = '2.2.1' recyclerViewVersion = "1.2.1" glideVersion = '4.12.0' zxingVersion = '3.3.3' // Don't update. 3.3.3 is the maximum to support Android 6.x diff --git a/common/src/main/java/org/dash/wallet/common/data/WalletUIConfig.kt b/common/src/main/java/org/dash/wallet/common/data/WalletUIConfig.kt index 66787e1fd..48394f4f5 100644 --- a/common/src/main/java/org/dash/wallet/common/data/WalletUIConfig.kt +++ b/common/src/main/java/org/dash/wallet/common/data/WalletUIConfig.kt @@ -27,6 +27,7 @@ import org.dash.wallet.common.services.ExchangeRatesProvider import org.dash.wallet.common.util.Constants import javax.inject.Inject import javax.inject.Singleton +import androidx.core.content.edit @Singleton // Intended for the UI settings which affect what the user sees on the screen. @@ -66,6 +67,7 @@ open class WalletUIConfig @Inject constructor( val LAST_TOTAL_BALANCE = longPreferencesKey("last_total_balance") val LAST_MIXED_BALANCE = longPreferencesKey("last_mixed_balance") val CUSTOMIZED_SHORTCUTS = stringPreferencesKey("customized_shortcuts") + val IS_SHORTCUT_INFO_HIDDEN = booleanPreferencesKey("is_shortcut_info_hidden") } suspend fun getExchangeCurrencyCode(): String { @@ -112,7 +114,7 @@ class ExchangeCurrencyMigration( } else { otherName } - sharedPreferences.edit().putString(WalletUIConfig.SELECTED_CURRENCY.name, fixedValue).apply() + sharedPreferences.edit { putString(WalletUIConfig.SELECTED_CURRENCY.name, fixedValue) } } // The database might have obsolete currencies as well exchangeRates.cleanupObsoleteCurrencies() diff --git a/common/src/main/java/org/dash/wallet/common/ui/components/InfoPanel.kt b/common/src/main/java/org/dash/wallet/common/ui/components/InfoPanel.kt new file mode 100644 index 000000000..303a38a6c --- /dev/null +++ b/common/src/main/java/org/dash/wallet/common/ui/components/InfoPanel.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2024 Dash Core Group. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.dash.wallet.common.ui.components + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.dash.wallet.common.R + +@Composable +fun InfoPanel( + title: String, + description: String, + modifier: Modifier = Modifier, + @DrawableRes leftIconRes: Int? = null, + @DrawableRes actionIconRes: Int? = null, + onAction: (() -> Unit)? = null +) { + Box( + modifier = modifier + .fillMaxWidth() + .background(MyTheme.Colors.backgroundSecondary, RoundedCornerShape(16.dp)) + .shadow(elevation = 20.dp, spotColor = Color(0x1AB8C1CC), ambientColor = Color(0x1AB8C1CC)), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(14.dp, 15.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + leftIconRes?.let { + Box( + modifier = Modifier + .size(34.dp), + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = leftIconRes), + contentDescription = null, + tint = Color.Unspecified + ) + } + } + + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(2.dp) + ) { + Text( + text = title, + style = MyTheme.CaptionMedium + ) + + Text( + text = description, + style = MyTheme.Caption, + color = MyTheme.Colors.textSecondary + ) + } + + if (actionIconRes != null && onAction != null) { + Box( + modifier = Modifier + .size(28.dp) + .clickable { onAction() }, + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = actionIconRes), + contentDescription = "Close", + tint = MyTheme.Colors.gray + ) + } + } + } + } +} + +@Preview +@Composable +fun InfoPanelPreview() { + InfoPanel( + title = "Customize shortcut bar", + description = "Hold any button above to replace it with the function you need", + leftIconRes = R.drawable.ic_dash_blue_filled, + actionIconRes = R.drawable.ic_popup_close, + onAction = {} + ) +} \ No newline at end of file diff --git a/common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt b/common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt index 3df31e41c..43407fec0 100644 --- a/common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt +++ b/common/src/main/java/org/dash/wallet/common/ui/components/MenuItem.kt @@ -56,7 +56,7 @@ fun MenuItem( modifier = Modifier .fillMaxWidth() .padding(10.dp) - .background(Color.White, RoundedCornerShape(8.dp)) + .background(MyTheme.Colors.backgroundSecondary, RoundedCornerShape(8.dp)) .clickable { action?.invoke() } .padding(10.dp), verticalAlignment = Alignment.CenterVertically diff --git a/common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt b/common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt index 526c28762..204f33039 100644 --- a/common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt +++ b/common/src/main/java/org/dash/wallet/common/ui/components/MyTheme.kt @@ -28,19 +28,22 @@ import org.dash.wallet.common.R object MyTheme { val ToastBackground = Color(0xff191c1f).copy(alpha = 0.9f) - val InterFont = FontFamily(Font(R.font.inter)) + private val interRegular = FontFamily(Font(R.font.inter_regular)) + private val interMedium = FontFamily(Font(R.font.inter_medium)) + private val interSemibold = FontFamily(Font(R.font.inter_semibold)) + private val interBold = FontFamily(Font(R.font.inter_bold)) val Body2Regular = TextStyle( fontSize = 14.sp, lineHeight = 20.sp, - fontFamily = InterFont, + fontFamily = interRegular, fontWeight = FontWeight(400) ) val Overline = TextStyle( fontSize = 12.sp, lineHeight = 16.sp, - fontFamily = InterFont, + fontFamily = interMedium, fontWeight = FontWeight(500), textAlign = TextAlign.Center ) @@ -48,22 +51,36 @@ object MyTheme { val OverlineSemibold = TextStyle( fontSize = 12.sp, lineHeight = 16.sp, - fontFamily = InterFont, + fontFamily = interSemibold, fontWeight = FontWeight(600), textAlign = TextAlign.Center ) + val Caption = TextStyle( + fontSize = 13.sp, + lineHeight = 18.sp, + fontFamily = interRegular, + fontWeight = FontWeight(400) + ) + + val CaptionMedium = TextStyle( + fontSize = 13.sp, + lineHeight = 18.sp, + fontFamily = interMedium, + fontWeight = FontWeight(500) + ) + val SubtitleSemibold = TextStyle( fontSize = 16.sp, lineHeight = 22.sp, - fontFamily = InterFont, + fontFamily = interSemibold, fontWeight = FontWeight(600) ) val H6Bold = TextStyle( fontSize = 20.sp, lineHeight = 26.sp, - fontFamily = InterFont, + fontFamily = interBold, fontWeight = FontWeight(700) ) @@ -77,5 +94,6 @@ object MyTheme { val primary40 = Color(0x66191C1F) val dashBlue = Color(0xFF008DE4) val dashBlue5 = Color(0x0D008DE4) + val gray = Color(0xFFB0B6BC) } } diff --git a/wallet/build.gradle b/wallet/build.gradle index 63f0c0f54..4120d53da 100644 --- a/wallet/build.gradle +++ b/wallet/build.gradle @@ -100,6 +100,7 @@ dependencies { implementation("androidx.compose.ui:ui-tooling") implementation("androidx.compose.material3:material3") implementation("androidx.activity:activity-compose:1.7.2") + implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion" // Navigation implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion" diff --git a/wallet/res/drawable/ic_shortcuts.xml b/wallet/res/drawable/ic_shortcuts.xml new file mode 100644 index 000000000..271820bcb --- /dev/null +++ b/wallet/res/drawable/ic_shortcuts.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/wallet/res/layout/home_content.xml b/wallet/res/layout/home_content.xml index 54973581c..cd47a00ab 100644 --- a/wallet/res/layout/home_content.xml +++ b/wallet/res/layout/home_content.xml @@ -56,7 +56,7 @@ android:background="@color/background_primary" android:orientation="vertical" android:paddingStart="16dp" - android:paddingTop="54dp" + android:paddingTop="40dp" android:paddingEnd="16dp"> + diff --git a/wallet/res/values/strings.xml b/wallet/res/values/strings.xml index f5cf6eee7..adcb40020 100644 --- a/wallet/res/values/strings.xml +++ b/wallet/res/values/strings.xml @@ -423,4 +423,6 @@ Select option + Customize shortcut bar + Hold any button above to replace it with the function you need diff --git a/wallet/src/de/schildbach/wallet/ui/main/HeaderBalanceFragment.kt b/wallet/src/de/schildbach/wallet/ui/main/HeaderBalanceFragment.kt index b406bb17c..f9757a291 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/HeaderBalanceFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/HeaderBalanceFragment.kt @@ -31,6 +31,7 @@ import de.schildbach.wallet_test.databinding.HeaderBalanceFragmentBinding import org.bitcoinj.core.Coin import org.dash.wallet.common.ui.viewBinding import org.dash.wallet.common.util.GenericUtils +import org.dash.wallet.common.util.observe class HeaderBalanceFragment : Fragment(R.layout.header_balance_fragment) { private val viewModel by activityViewModels() @@ -66,7 +67,7 @@ class HeaderBalanceFragment : Fragment(R.layout.header_balance_fragment) { } viewModel.showTapToHideHint.observe(viewLifecycleOwner) { showHint -> - binding.hideBalanceHintText.isVisible = showHint ?: true + binding.hideBalanceHintText.isVisible = showHint != false } } diff --git a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt index ee560750c..8b63d5346 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt @@ -65,13 +65,17 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.bitcoinj.core.Coin import org.bitcoinj.core.Context @@ -220,9 +224,13 @@ class MainViewModel @Inject constructor( .combine(_temporaryHideBalance) { autoHide, temporaryHide -> temporaryHide ?: autoHide ?: false } - .asLiveData() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = false + ) - val showTapToHideHint = walletUIConfig.observe(WalletUIConfig.SHOW_TAP_TO_HIDE_HINT).asLiveData() + val showTapToHideHint = walletUIConfig.observe(WalletUIConfig.SHOW_TAP_TO_HIDE_HINT) private val _isNetworkUnavailable = MutableLiveData() val isNetworkUnavailable: LiveData @@ -418,8 +426,7 @@ class MainViewModel @Inject constructor( } fun triggerHideBalance() { - val isHiding = hideBalance.value ?: false - _temporaryHideBalance.value = !isHiding + _temporaryHideBalance.value = !hideBalance.value if (_temporaryHideBalance.value == true) { logEvent(AnalyticsConstants.Home.HIDE_BALANCE) @@ -468,7 +475,7 @@ class MainViewModel @Inject constructor( coinJoinService.updateTimeSkew(timeSkew) log.info("timeskew: {} ms", timeSkew) return Pair(abs(timeSkew) > maxAllowedTimeSkew, timeSkew) - } catch (ex: Exception) { + } catch (_: Exception) { // Ignore errors Pair(false, 0) } @@ -580,7 +587,7 @@ class MainViewModel @Inject constructor( } if (included && wrapper != null) { - itemId = wrapper!!.id + itemId = wrapper.id } else { this.crowdNodeWrapperFactory.tryInclude(tx).also { included = it.first @@ -588,7 +595,7 @@ class MainViewModel @Inject constructor( } if (included && wrapper != null) { - itemId = wrapper!!.id + itemId = wrapper.id } } } @@ -608,7 +615,7 @@ class MainViewModel @Inject constructor( ) } else { TransactionRowView.fromTransactionWrapper( - wrapper!!, + wrapper, walletData.transactionBag, Constants.CONTEXT, null, diff --git a/wallet/src/de/schildbach/wallet/ui/main/WalletFragment.kt b/wallet/src/de/schildbach/wallet/ui/main/WalletFragment.kt index ab2ffb610..42e5f39f2 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/WalletFragment.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/WalletFragment.kt @@ -18,45 +18,52 @@ package de.schildbach.wallet.ui.main import android.app.Activity -import androidx.fragment.app.activityViewModels import android.content.Intent import android.os.Bundle import android.view.View import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.net.toUri import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.Fragment -import androidx.fragment.app.viewModels +import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.NavOptions -import androidx.navigation.NavOptions.* import androidx.navigation.fragment.findNavController import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout.Behavior.DragCallback import com.google.android.material.transition.MaterialFadeThrough import dagger.hilt.android.AndroidEntryPoint import de.schildbach.wallet.data.PaymentIntent +import de.schildbach.wallet.data.ServiceType import de.schildbach.wallet.service.CoinJoinMode import de.schildbach.wallet.service.MixingStatus -import de.schildbach.wallet.ui.* +import de.schildbach.wallet.ui.EditProfileActivity +import de.schildbach.wallet.ui.LockScreenActivity import de.schildbach.wallet.ui.compose_views.ComposeBottomSheet -import de.schildbach.wallet.ui.util.InputParser.StringInputParser import de.schildbach.wallet.ui.dashpay.ContactsScreenMode import de.schildbach.wallet.ui.dashpay.NotificationsFragment import de.schildbach.wallet.ui.dashpay.utils.display +import de.schildbach.wallet.ui.main.shortcuts.ShortcutOption +import de.schildbach.wallet.ui.main.shortcuts.ShortcutsList +import de.schildbach.wallet.ui.main.shortcuts.ShortcutsPane +import de.schildbach.wallet.ui.main.shortcuts.ShortcutsViewModel import de.schildbach.wallet.ui.payments.PaymentsFragment import de.schildbach.wallet.ui.payments.SweepWalletActivity import de.schildbach.wallet.ui.scan.ScanActivity import de.schildbach.wallet.ui.send.SendCoinsActivity -import de.schildbach.wallet.ui.main.shortcuts.ShortcutOption -import de.schildbach.wallet.ui.main.shortcuts.ShortcutsViewModel -import de.schildbach.wallet.ui.main.shortcuts.ShortcutsList -import de.schildbach.wallet.ui.main.shortcuts.ShortcutsPane import de.schildbach.wallet.ui.staking.StakingActivity import de.schildbach.wallet.ui.transactions.TaxCategoryExplainerDialogFragment import de.schildbach.wallet.ui.transactions.TransactionDetailsDialogFragment +import de.schildbach.wallet.ui.util.InputParser.StringInputParser import de.schildbach.wallet.ui.verify.VerifySeedActivity import de.schildbach.wallet.util.WalletUtils import de.schildbach.wallet_test.R @@ -71,17 +78,16 @@ import org.dash.wallet.common.Configuration import org.dash.wallet.common.services.AuthenticationManager import org.dash.wallet.common.services.analytics.AnalyticsConstants import org.dash.wallet.common.ui.avatar.ProfilePictureDisplay +import org.dash.wallet.common.ui.components.InfoPanel import org.dash.wallet.common.ui.dialogs.AdaptiveDialog import org.dash.wallet.common.ui.viewBinding import org.dash.wallet.common.util.Constants import org.dash.wallet.common.util.observe +import org.dash.wallet.common.util.openCustomTab import org.dash.wallet.common.util.safeNavigate import org.dash.wallet.features.exploredash.ui.explore.ExploreTopic import org.slf4j.LoggerFactory import javax.inject.Inject -import androidx.core.net.toUri -import de.schildbach.wallet.data.ServiceType -import org.dash.wallet.common.util.openCustomTab @AndroidEntryPoint class WalletFragment : Fragment(R.layout.home_content) { @@ -91,7 +97,7 @@ class WalletFragment : Fragment(R.layout.home_content) { } private val viewModel: MainViewModel by activityViewModels() - private val shortcutViewModel: ShortcutsViewModel by viewModels() + private val shortcutViewModel: ShortcutsViewModel by activityViewModels() private val binding by viewBinding(HomeContentBinding::bind) private lateinit var mixingBinding: MixingStatusPaneBinding @Inject lateinit var configuration: Configuration @@ -153,6 +159,27 @@ class WalletFragment : Fragment(R.layout.home_content) { startActivity(Intent(requireContext(), EditProfileActivity::class.java)) } + binding.infoPanel.setViewCompositionStrategy( + ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed + ) + + binding.infoPanel.setContent { + if (shortcutViewModel.showShortcutInfo) { + InfoPanel( + stringResource(R.string.customize_shortcuts), + stringResource(R.string.customize_shortcuts_description), + modifier = Modifier + .wrapContentHeight() + .fillMaxWidth() + .padding(horizontal = 2.dp), + leftIconRes = R.drawable.ic_shortcuts, + actionIconRes = R.drawable.ic_popup_close + ) { + shortcutViewModel.hideShortcutInfo() + } + } + } + viewModel.transactions.observe(viewLifecycleOwner) { refreshShortcutBar() } viewModel.isBlockchainSynced.observe(viewLifecycleOwner) { updateSyncState() } viewModel.isBlockchainSyncFailed.observe(viewLifecycleOwner) { updateSyncState() } @@ -436,7 +463,7 @@ class WalletFragment : Fragment(R.layout.home_content) { findNavController().navigate( R.id.exploreFragment, bundleOf(), - Builder() + NavOptions.Builder() .setEnterAnim(R.anim.slide_in_bottom) .build() ) @@ -480,6 +507,8 @@ class WalletFragment : Fragment(R.layout.home_content) { dialog.dismiss() } }.show(requireActivity()) + + shortcutViewModel.hideShortcutInfo() // Assume user is aware of this feature already } private fun handleStakingNavigation() { diff --git a/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutProvider.kt b/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutProvider.kt index 3dcb38112..f00500777 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutProvider.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutProvider.kt @@ -23,7 +23,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach @@ -36,6 +35,7 @@ class ShortcutProvider @Inject constructor( private val config: WalletUIConfig ) { companion object { + // Normally, there should be at least 4 custom shortcuts saved private const val MINIMUM_SHORTCUTS = 4 } @@ -46,10 +46,15 @@ class ShortcutProvider @Inject constructor( init { config.observe(WalletUIConfig.CUSTOMIZED_SHORTCUTS) - .filterNotNull() .distinctUntilChanged() - .map { shortcutSet -> parseCustomShortcuts(shortcutSet) } + .map { shortcutSet -> if (shortcutSet == null) null else parseCustomShortcuts(shortcutSet) } .onEach { shortcuts -> + if (shortcuts == null) { + // DataStore was cleared out, probably due to a reset + _customShortcuts.value = emptyList() + return@onEach + } + var finalShortcuts = shortcuts.toMutableList() if (finalShortcuts.size < MINIMUM_SHORTCUTS) { diff --git a/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutsViewModel.kt b/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutsViewModel.kt index 1c09c0222..dfd035bb3 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutsViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/shortcuts/ShortcutsViewModel.kt @@ -16,6 +16,7 @@ */ package de.schildbach.wallet.ui.main.shortcuts +import android.util.Log import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue @@ -72,15 +73,34 @@ class ShortcutsViewModel @Inject constructor( } var shortcuts by mutableStateOf(getPresetShortcuts().take(maxShortcuts)) + var showShortcutInfo by mutableStateOf(false) val isCoinbaseAuthenticated: Boolean get() = coinBaseRepository.isAuthenticated init { shortcutProvider.customShortcuts + .onEach { Log.i("SHORTCUTS", "size: ${it.size}") } .filterNot { it.isEmpty() } .onEach { shortcuts = it.take(maxShortcuts) } .launchIn(viewModelScope) + + // Check if need to show the shortcut info panel + viewModelScope.launch { + val isHidden = walletUIConfig.get(WalletUIConfig.IS_SHORTCUT_INFO_HIDDEN) + showShortcutInfo = if (config.wasUpgraded()) { + // If upgraded, show immediately if not already hidden + isHidden != true + } else if (isHidden == null) { + // New install and the first time opening the app - don't show + // Update IS_SHORTCUT_INFO_HIDDEN to detect non-first launch next time + walletUIConfig.set(WalletUIConfig.IS_SHORTCUT_INFO_HIDDEN, false) + false + } else { + // New install, not the first time opening the app, show if not hidden + !isHidden + } + } } fun getAllShortcutOptions(replacingShortcut: ShortcutOption): List { @@ -120,6 +140,13 @@ class ShortcutsViewModel @Inject constructor( } } + fun hideShortcutInfo() { + viewModelScope.launch { + showShortcutInfo = false + walletUIConfig.set(WalletUIConfig.IS_SHORTCUT_INFO_HIDDEN, true) + } + } + private fun removeSecureNowShortcut() { val currentShortcuts = shortcuts.toMutableList() val index = currentShortcuts.indexOf(ShortcutOption.SECURE_NOW)