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)