diff --git a/Gemfile.lock b/Gemfile.lock index ec4ff4f59..cdda94139 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -107,7 +107,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-sentry (1.17.0) + fastlane-plugin-sentry (1.19.0) os (~> 1.1, >= 1.1.4) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.54.0) diff --git a/app/build.gradle b/app/build.gradle index 6f9170611..8e9f615bb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,6 +42,7 @@ android { flavorDimensions.add("privacy-mode") buildTypes { + loadSentryProps() def secretProperties = loadSecretProps() debug { @@ -57,8 +58,9 @@ android { debugSymbolLevel "FULL" } sentry { - autoUpload.set(false) - autoUploadProguardMapping.set(false) + autoUpload.set(true) + uploadNativeSymbols.set(true) + includeNativeSources.set(true) } } } @@ -288,8 +290,10 @@ dependencies { implementation "com.dropbox.core:dropbox-core-sdk:5.4.6" -// implementation "com.github.yat-labs:yat-lib-android:0.1.42" - implementation project(":yatlib") + // It's recommended to use the latest version of the library from the JitPack repository, + // but you can also use a locally build version of the library by using the ":yatlib" module and `yat-lib-debug-snapshot.aar` file with your build + implementation "com.github.tari-project:yat-lib-android:0.4.1" +// implementation project(":yatlib") // custom libraries region // flex layout diff --git a/app/src/main/java/com/tari/android/wallet/application/securityStage/StagedWalletSecurityManager.kt b/app/src/main/java/com/tari/android/wallet/application/securityStage/StagedWalletSecurityManager.kt index 32597528a..1faa031b9 100644 --- a/app/src/main/java/com/tari/android/wallet/application/securityStage/StagedWalletSecurityManager.kt +++ b/app/src/main/java/com/tari/android/wallet/application/securityStage/StagedWalletSecurityManager.kt @@ -1,93 +1,86 @@ package com.tari.android.wallet.application.securityStage -import android.text.SpannableString -import android.text.Spanned -import com.tari.android.wallet.R +import com.tari.android.wallet.application.securityStage.StagedWalletSecurityManager.StagedSecurityEffect.NoStagedSecurityPopUp +import com.tari.android.wallet.application.securityStage.StagedWalletSecurityManager.StagedSecurityEffect.ShowStagedSecurityPopUp import com.tari.android.wallet.data.sharedPrefs.securityStages.DisabledTimestampsDto import com.tari.android.wallet.data.sharedPrefs.securityStages.SecurityStagesRepository import com.tari.android.wallet.data.sharedPrefs.securityStages.WalletSecurityStage -import com.tari.android.wallet.data.sharedPrefs.securityStages.modules.SecurityStageHeadModule -import com.tari.android.wallet.event.EventBus -import com.tari.android.wallet.extension.addTo +import com.tari.android.wallet.data.sharedPrefs.tariSettings.TariSettingsSharedRepository +import com.tari.android.wallet.extension.isAfterNow import com.tari.android.wallet.model.BalanceInfo import com.tari.android.wallet.model.MicroTari -import com.tari.android.wallet.ui.common.CommonViewModel -import com.tari.android.wallet.ui.dialog.modular.DialogArgs -import com.tari.android.wallet.ui.dialog.modular.ModularDialogArgs -import com.tari.android.wallet.ui.dialog.modular.modules.body.BodyModule -import com.tari.android.wallet.ui.dialog.modular.modules.button.ButtonModule -import com.tari.android.wallet.ui.dialog.modular.modules.button.ButtonStyle -import com.tari.android.wallet.ui.dialog.modular.modules.space.SpaceModule -import com.tari.android.wallet.ui.fragment.settings.backup.backupOnboarding.item.BackupOnboardingArgs -import com.tari.android.wallet.ui.fragment.settings.backup.backupOnboarding.module.BackupOnboardingFlowItemModule import com.tari.android.wallet.ui.fragment.settings.backup.data.BackupSettingsRepository -import yat.android.ui.extension.HtmlHelper import java.math.BigDecimal import java.util.Calendar import javax.inject.Inject - -class StagedWalletSecurityManager : CommonViewModel() { - - @Inject - lateinit var securityStagesRepository: SecurityStagesRepository - - @Inject - lateinit var backupPrefsRepository: BackupSettingsRepository - - init { - component.inject(this) - - EventBus.balanceUpdates.publishSubject.subscribe { handleChange(it) }.addTo(compositeDisposable) - } - - val hasVerifiedSeedPhrase +import javax.inject.Singleton + +val MINIMUM_STAGE_ONE_BALANCE = MicroTari((BigDecimal.valueOf(10_000) * MicroTari.precisionValue).toBigInteger()) +val STAGE_TWO_THRESHOLD_BALANCE = MicroTari((BigDecimal.valueOf(100_000) * MicroTari.precisionValue).toBigInteger()) +val SAFE_HOT_WALLET_BALANCE = MicroTari((BigDecimal.valueOf(500_000_000) * MicroTari.precisionValue).toBigInteger()) +val MAX_HOT_WALLET_BALANCE = MicroTari((BigDecimal.valueOf(1_000_000_000) * MicroTari.precisionValue).toBigInteger()) + +@Singleton +class StagedWalletSecurityManager @Inject constructor( + private val securityStagesRepository: SecurityStagesRepository, + private val backupPrefsRepository: BackupSettingsRepository, + private val tariSettingsSharedRepository: TariSettingsSharedRepository, +) { + private val hasVerifiedSeedPhrase get() = tariSettingsSharedRepository.hasVerifiedSeedWords - val isBackupOn + private val isBackupOn get() = backupPrefsRepository.getOptionList.any { it.isEnable } - val isBackupPasswordSet + private val isBackupPasswordSet get() = !backupPrefsRepository.backupPassword.isNullOrEmpty() - val disabledTimestampSinceNow + private val disabledTimestampSinceNow: Calendar get() = Calendar.getInstance().also { it.add(Calendar.DAY_OF_YEAR, 7) } - var disabledTimestamps: MutableMap + private var disabledTimestamps: MutableMap get() = securityStagesRepository.disabledTimestamps?.timestamps ?: DisabledTimestampsDto(mutableMapOf()).timestamps set(value) { securityStagesRepository.disabledTimestamps = DisabledTimestampsDto(value) } - private fun updateTimestamp(securityStage: WalletSecurityStage) { - val newTimestamp = disabledTimestampSinceNow - disabledTimestamps = disabledTimestamps.also { it[securityStage] = newTimestamp } - } - - private fun handleChange(balance: BalanceInfo) { - val securityStage = getSecurityStages(balance) ?: return + /** + * Check the current security stage based on the balance and the user's security settings. + */ + fun handleBalanceChange(balance: BalanceInfo): StagedSecurityEffect { + val securityStage = checkSecurityStage(balance) ?: return NoStagedSecurityPopUp //todo Stage 3 is currently disabled - if (securityStage == WalletSecurityStage.Stage3) return - if (isActionDisabled(securityStage)) return + if (securityStage == WalletSecurityStage.Stage3) return NoStagedSecurityPopUp + if (isActionDisabled(securityStage)) return NoStagedSecurityPopUp updateTimestamp(securityStage) - showPopUp(securityStage) + + return ShowStagedSecurityPopUp(securityStage) } - private fun getSecurityStages(balanceInfo: BalanceInfo): WalletSecurityStage? { + private fun updateTimestamp(securityStage: WalletSecurityStage) { + val newTimestamp = disabledTimestampSinceNow + disabledTimestamps = disabledTimestamps.also { it[securityStage] = newTimestamp } + } + + /** + * Returns null if no security stage is required. + */ + private fun checkSecurityStage(balanceInfo: BalanceInfo): WalletSecurityStage? { val balance = balanceInfo.availableBalance return when { - balance >= minimumStageOneBalance && !hasVerifiedSeedPhrase -> WalletSecurityStage.Stage1A - balance >= minimumStageOneBalance && !isBackupOn -> WalletSecurityStage.Stage1B - balance >= stageTwoThresholdBalance && !isBackupPasswordSet -> WalletSecurityStage.Stage2 - balance >= safeHotWalletBalance -> WalletSecurityStage.Stage3 + balance >= MINIMUM_STAGE_ONE_BALANCE && !hasVerifiedSeedPhrase -> WalletSecurityStage.Stage1A + balance >= MINIMUM_STAGE_ONE_BALANCE && !isBackupOn -> WalletSecurityStage.Stage1B + balance >= STAGE_TWO_THRESHOLD_BALANCE && !isBackupPasswordSet -> WalletSecurityStage.Stage2 + balance >= SAFE_HOT_WALLET_BALANCE -> WalletSecurityStage.Stage3 else -> null } } private fun isActionDisabled(securityStage: WalletSecurityStage): Boolean { val timestamp = disabledTimestamps[securityStage] ?: return false - if (timestamp < Calendar.getInstance()) { + if (timestamp.isAfterNow()) { return true } @@ -95,119 +88,8 @@ class StagedWalletSecurityManager : CommonViewModel() { return false } - fun showPopUp(securityStage: WalletSecurityStage) { - when (securityStage) { - WalletSecurityStage.Stage1A -> showStage1APopUp() - WalletSecurityStage.Stage1B -> showStage1BPopUp() - WalletSecurityStage.Stage2 -> showStage2PopUp() - WalletSecurityStage.Stage3 -> showStage3PopUp() - } - } - - private fun showStage1APopUp() { - showPopup( - BackupOnboardingArgs.StageOne(resourceManager, this::openStage1), - resourceManager.getString(R.string.staged_wallet_security_stages_1a_title), - resourceManager.getString(R.string.staged_wallet_security_stages_1a_subtitle), - null, - resourceManager.getString(R.string.staged_wallet_security_stages_1a_buttons_positive), - HtmlHelper.getSpannedText(resourceManager.getString(R.string.staged_wallet_security_stages_1a_message)) - ) { openStage1() } - } - - private fun openStage1() { - dismissDialog.postValue(Unit) - tariNavigator?.let { - it.toAllSettings() - it.toBackupSettings(false) - it.toWalletBackupWithRecoveryPhrase() - } - } - - private fun showStage1BPopUp() { - showPopup( - BackupOnboardingArgs.StageTwo(resourceManager, this::openStage1B), - resourceManager.getString(R.string.staged_wallet_security_stages_1b_title), - resourceManager.getString(R.string.staged_wallet_security_stages_1b_subtitle), - resourceManager.getString(R.string.staged_wallet_security_stages_1b_message), - resourceManager.getString(R.string.staged_wallet_security_stages_1b_buttons_positive), - ) { openStage1() } - } - - private fun openStage1B() { - dismissDialog.postValue(Unit) - tariNavigator?.let { - it.toAllSettings() - it.toBackupSettings(true) - } - } - - private fun showStage2PopUp() { - showPopup( - BackupOnboardingArgs.StageThree(resourceManager, this::openStage2), - resourceManager.getString(R.string.staged_wallet_security_stages_2_title), - resourceManager.getString(R.string.staged_wallet_security_stages_2_subtitle), - resourceManager.getString(R.string.staged_wallet_security_stages_2_message), - resourceManager.getString(R.string.staged_wallet_security_stages_2_buttons_positive), - ) { openStage2() } - } - - private fun openStage2() { - dismissDialog.postValue(Unit) - tariNavigator?.let { - it.toAllSettings() - it.toBackupSettings(false) - it.toChangePassword() - } - } - - private fun showStage3PopUp() { - showPopup( - BackupOnboardingArgs.StageFour(resourceManager, this::openStage3), - resourceManager.getString(R.string.staged_wallet_security_stages_3_title), - resourceManager.getString(R.string.staged_wallet_security_stages_3_subtitle), - resourceManager.getString(R.string.staged_wallet_security_stages_3_message), - resourceManager.getString(R.string.staged_wallet_security_stages_3_buttons_positive), - ) { openStage3() } - } - - private fun openStage3() { - dismissDialog.postValue(Unit) - //todo for future - } - - private fun showPopup( - stage: BackupOnboardingArgs, - titleEmoji: String, - title: String, - body: String?, - positiveButtonTitle: String, - bodyHtml: Spanned? = null, - positiveAction: () -> Unit = {}, - ) { - val args = ModularDialogArgs( - DialogArgs(), listOf( - SecurityStageHeadModule(titleEmoji, title) { showBackupInfo(stage) }, - BodyModule(body, bodyHtml?.let { SpannableString(it) }), - ButtonModule(positiveButtonTitle, ButtonStyle.Normal) { positiveAction.invoke() }, - ButtonModule(resourceManager.getString(R.string.staged_wallet_security_buttons_remind_me_later), ButtonStyle.Close) - ) - ) - modularDialog.postValue(args) - } - - private fun showBackupInfo(stage: BackupOnboardingArgs) { - val args = ModularDialogArgs(DialogArgs(), listOf( - BackupOnboardingFlowItemModule(stage), - SpaceModule(20) - )) - modularDialog.postValue(args) - } - - companion object { - val minimumStageOneBalance = MicroTari((BigDecimal.valueOf(10_000) * MicroTari.precisionValue).toBigInteger()) - val stageTwoThresholdBalance = MicroTari((BigDecimal.valueOf(100_000) * MicroTari.precisionValue).toBigInteger()) - val safeHotWalletBalance = MicroTari((BigDecimal.valueOf(500_000_000) * MicroTari.precisionValue).toBigInteger()) - val maxHotWalletBalance = MicroTari((BigDecimal.valueOf(1_000_000_000) * MicroTari.precisionValue).toBigInteger()) + sealed class StagedSecurityEffect { + data class ShowStagedSecurityPopUp(val stage: WalletSecurityStage) : StagedSecurityEffect() + object NoStagedSecurityPopUp : StagedSecurityEffect() } } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/data/sharedPrefs/tariSettings/TariSettingsSharedRepository.kt b/app/src/main/java/com/tari/android/wallet/data/sharedPrefs/tariSettings/TariSettingsSharedRepository.kt index 91711bc84..25808a5d8 100644 --- a/app/src/main/java/com/tari/android/wallet/data/sharedPrefs/tariSettings/TariSettingsSharedRepository.kt +++ b/app/src/main/java/com/tari/android/wallet/data/sharedPrefs/tariSettings/TariSettingsSharedRepository.kt @@ -50,19 +50,22 @@ class TariSettingsSharedRepository @Inject constructor(sharedPrefs: SharedPrefer const val isRestoredWallet = "tari_is_restored_wallet" const val hasVerifiedSeedWords = "tari_has_verified_seed_words" const val backgroundServiceTurnedOnKey = "tari_background_service_turned_on" + const val screenRecordingTurnedOnKey = "tari_screen_recording_turned_on" const val isOneSidePaymentEnabledKey = "is_one_side_payment_enabled" const val themeKey = "tari_theme_key" } - var isRestoredWallet: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.isRestoredWallet)) + var isRestoredWallet: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.isRestoredWallet)) - var hasVerifiedSeedWords: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.hasVerifiedSeedWords)) + var hasVerifiedSeedWords: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.hasVerifiedSeedWords)) - var backgroundServiceTurnedOn: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.backgroundServiceTurnedOnKey), true) + var backgroundServiceTurnedOn: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.backgroundServiceTurnedOnKey), true) - var isOneSidePaymentEnabled: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.isOneSidePaymentEnabledKey), false) + var screenRecordingTurnedOn: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.screenRecordingTurnedOnKey), false) - var currentTheme: TariTheme? by SharedPrefGsonDelegate(sharedPrefs, this, Key.themeKey, TariTheme::class.java, TariTheme.AppBased) + var isOneSidePaymentEnabled: Boolean by SharedPrefBooleanDelegate(sharedPrefs, this, formatKey(Key.isOneSidePaymentEnabledKey), false) + + var currentTheme: TariTheme? by SharedPrefGsonDelegate(sharedPrefs, this, Key.themeKey, TariTheme::class.java, TariTheme.AppBased) fun clear() { isRestoredWallet = false diff --git a/app/src/main/java/com/tari/android/wallet/di/ApplicationComponent.kt b/app/src/main/java/com/tari/android/wallet/di/ApplicationComponent.kt index d893f09d9..0cf28a390 100644 --- a/app/src/main/java/com/tari/android/wallet/di/ApplicationComponent.kt +++ b/app/src/main/java/com/tari/android/wallet/di/ApplicationComponent.kt @@ -97,6 +97,7 @@ import com.tari.android.wallet.ui.fragment.settings.logs.LogFilesManager import com.tari.android.wallet.ui.fragment.settings.logs.logFiles.LogFilesViewModel import com.tari.android.wallet.ui.fragment.settings.logs.logs.LogsViewModel import com.tari.android.wallet.ui.fragment.settings.networkSelection.NetworkSelectionViewModel +import com.tari.android.wallet.ui.fragment.settings.screenRecording.ScreenRecordingSettingsViewModel import com.tari.android.wallet.ui.fragment.settings.themeSelector.ThemeSelectorViewModel import com.tari.android.wallet.ui.fragment.settings.torBridges.TorBridgesSelectionViewModel import com.tari.android.wallet.ui.fragment.settings.torBridges.customBridges.CustomTorBridgesViewModel @@ -147,6 +148,7 @@ interface ApplicationComponent { fun inject(viewModel: ThumbnailGIFsViewModel) fun inject(viewModel: GIFViewModel) fun inject(viewModel: BackgroundServiceSettingsViewModel) + fun inject(viewModel: ScreenRecordingSettingsViewModel) fun inject(viewModel: ConnectionIndicatorViewModel) fun inject(viewModel: ChooseRestoreOptionViewModel) fun inject(viewModel: EnterRestorationPasswordViewModel) diff --git a/app/src/main/java/com/tari/android/wallet/event/EffectChannelFlow.kt b/app/src/main/java/com/tari/android/wallet/event/EffectChannelFlow.kt new file mode 100644 index 000000000..81458f025 --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/event/EffectChannelFlow.kt @@ -0,0 +1,14 @@ +package com.tari.android.wallet.event + +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.receiveAsFlow + +class EffectChannelFlow { + private val channel: Channel = Channel(Channel.CONFLATED) + val flow: Flow = channel.receiveAsFlow() + + suspend fun send(effect: Effect) { + channel.send(effect) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/event/EventBus.kt b/app/src/main/java/com/tari/android/wallet/event/EventBus.kt index 47996ea9e..17c31e9f2 100644 --- a/app/src/main/java/com/tari/android/wallet/event/EventBus.kt +++ b/app/src/main/java/com/tari/android/wallet/event/EventBus.kt @@ -69,8 +69,6 @@ object EventBus : GeneralEventBus() { val walletRestorationState = BehaviorEventBus() - val balanceUpdates = BehaviorEventBus() - init { baseNodeSyncState.post(BaseNodeSyncState.Syncing) } diff --git a/app/src/main/java/com/tari/android/wallet/extension/AnyExtensions.kt b/app/src/main/java/com/tari/android/wallet/extension/AnyExtensions.kt new file mode 100644 index 000000000..640bc8f5f --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/extension/AnyExtensions.kt @@ -0,0 +1,12 @@ +package com.tari.android.wallet.extension + +/** + * These extensions can be used to write casts in a chained way. + * E.g. something.castTo().doSomething() instead of (something as Other).doSomething() + */ +@Suppress("UNCHECKED_CAST") +fun Any.castTo(): T = this as T + +// Simply returning `this as? T` does not work because the Kotlin compiler internally +// then still just casts it to the other type without checks +inline fun Any.safeCastTo(): T? = if (this is T) this else null diff --git a/app/src/main/java/com/tari/android/wallet/extension/DateExtensions.kt b/app/src/main/java/com/tari/android/wallet/extension/DateExtensions.kt index 1d9f21a4d..566d1e3c2 100644 --- a/app/src/main/java/com/tari/android/wallet/extension/DateExtensions.kt +++ b/app/src/main/java/com/tari/android/wallet/extension/DateExtensions.kt @@ -55,3 +55,7 @@ fun Date.txFormattedDate(): String { return SimpleDateFormat("MMMM d'$indicator' yyyy 'at' h:mm a", Locale.ENGLISH) .format(this) } + +fun Calendar.isAfterNow(): Boolean { + return this.after(Calendar.getInstance()) +} diff --git a/app/src/main/java/com/tari/android/wallet/extension/FlowExtensions.kt b/app/src/main/java/com/tari/android/wallet/extension/FlowExtensions.kt new file mode 100644 index 000000000..ea6e9478c --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/extension/FlowExtensions.kt @@ -0,0 +1,13 @@ +package com.tari.android.wallet.extension + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +inline fun LifecycleOwner.launchAndRepeatOnLifecycle( + state: Lifecycle.State, + crossinline block: suspend CoroutineScope.() -> Unit, +) = lifecycleScope.launch { repeatOnLifecycle(state) { block() } } diff --git a/app/src/main/java/com/tari/android/wallet/ui/common/CommonActivity.kt b/app/src/main/java/com/tari/android/wallet/ui/common/CommonActivity.kt index ef287ddfd..5b66e7628 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/common/CommonActivity.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/common/CommonActivity.kt @@ -18,6 +18,7 @@ import androidx.viewbinding.ViewBinding import com.squareup.seismic.ShakeDetector import com.tari.android.wallet.R import com.tari.android.wallet.extension.observe +import com.tari.android.wallet.extension.safeCastTo import com.tari.android.wallet.ui.component.networkStateIndicator.ConnectionIndicatorViewModel import com.tari.android.wallet.ui.component.tari.toast.TariToast import com.tari.android.wallet.ui.component.tari.toast.TariToastArgs @@ -38,7 +39,7 @@ import com.tari.android.wallet.ui.fragment.settings.logs.activity.DebugNavigatio import com.tari.android.wallet.ui.fragment.settings.themeSelector.TariTheme import yat.android.lib.YatIntegration -abstract class CommonActivity : AppCompatActivity(), ShakeDetector.Listener { +abstract class CommonActivity : AppCompatActivity(), ShakeDetector.Listener, FragmentPoppedListener { private val dialogManager = DialogManager() private var containerId: Int? = null @@ -161,7 +162,7 @@ abstract class CommonActivity : App containerId = id } - fun addFragment(fragment: Fragment, bundle: Bundle? = null, isRoot: Boolean = false, withAnimation: Boolean = true) { + fun addFragment(fragment: CommonFragment<*, *>, bundle: Bundle? = null, isRoot: Boolean = false, withAnimation: Boolean = true) { bundle?.let { fragment.arguments = it } if (supportFragmentManager.isDestroyed) return val transaction = supportFragmentManager.beginTransaction() @@ -172,6 +173,7 @@ abstract class CommonActivity : App if (!isRoot) { transaction.addToBackStack(null) } + fragment.setFragmentPoppedListener(this) transaction.commit() } @@ -185,6 +187,12 @@ abstract class CommonActivity : App } } + override fun onFragmentPopped(fragmentClass: Class) { + supportFragmentManager.fragments + .mapNotNull { it.safeCastTo>() } + .forEach { fragment -> fragment.onFragmentPopped(fragmentClass) } + } + override fun hearShake() = showDebugDialog() fun showDebugDialog() { diff --git a/app/src/main/java/com/tari/android/wallet/ui/common/CommonFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/common/CommonFragment.kt index a40f15d4a..47a3ab559 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/common/CommonFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/common/CommonFragment.kt @@ -10,11 +10,13 @@ import android.provider.Settings import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.WindowManager import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.viewbinding.ViewBinding +import com.tari.android.wallet.BuildConfig import com.tari.android.wallet.R import com.tari.android.wallet.di.DiContainer import com.tari.android.wallet.extension.observe @@ -25,9 +27,9 @@ import com.tari.android.wallet.ui.dialog.modular.InputModularDialog import com.tari.android.wallet.ui.dialog.modular.ModularDialog import com.tari.android.wallet.ui.extension.string -abstract class CommonFragment : Fragment() { +abstract class CommonFragment : Fragment(), FragmentPoppedListener { - lateinit var clipboardManager: ClipboardManager + private lateinit var clipboardManager: ClipboardManager private val dialogManager = DialogManager() @@ -37,18 +39,27 @@ abstract class CommonFragment : Fra lateinit var viewModel: VM - val launcher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { - if (it.all { it.value }) { + //TODO make viewModel not lateinit. Sometimes it's not initialized in time and causes crashes, so we need to check if it's initialized + private val blockScreenRecording + get() = !BuildConfig.DEBUG && + (screenRecordingAlwaysDisable() || !(this::viewModel.isInitialized) || !viewModel.tariSettingsSharedRepository.screenRecordingTurnedOn) + + private var fragmentPoppedListener: FragmentPoppedListener? = null + + private val launcher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { results -> + if (results.all { it.value }) { viewModel.permissionManager.grantedAction() } else { - viewModel.permissionManager.showPermissionRequiredDialog(it.filter { !it.value }.map { it.key }) + viewModel.permissionManager.showPermissionRequiredDialog(results.filter { !it.value }.map { it.key }) } } + protected open fun screenRecordingAlwaysDisable() = false + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - //to eliminate click throuhg fragments + //to eliminate click through fragments view.isClickable = true view.isFocusable = true @@ -66,12 +77,37 @@ abstract class CommonFragment : Fra return super.onCreateView(inflater, container, savedInstanceState) } + override fun onResume() { + super.onResume() + + if (blockScreenRecording) { + requireActivity().window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) + } else { + requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) + } + } + fun bindViewModel(viewModel: VM) = with(viewModel) { this@CommonFragment.viewModel = this subscribeVM(viewModel) } + override fun onDetach() { + super.onDetach() + + fragmentPoppedListener?.onFragmentPopped(javaClass) + } + + override fun onFragmentPopped(fragmentClass: Class) { + // implement in subclass + } + + fun setFragmentPoppedListener(listener: FragmentPoppedListener) { + fragmentPoppedListener = listener + } + + fun subscribeVM(viewModel: VM) = with(viewModel) { observe(backPressed) { requireActivity().onBackPressed() } @@ -147,3 +183,9 @@ abstract class CommonFragment : Fra } } +/** + * Interface for listening to fragment pop events and performing actions once a fragment is popped. + */ +interface FragmentPoppedListener { + fun onFragmentPopped(fragmentClass: Class) +} diff --git a/app/src/main/java/com/tari/android/wallet/ui/common/CommonViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/common/CommonViewModel.kt index c0a20135d..4d384d22a 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/common/CommonViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/common/CommonViewModel.kt @@ -167,7 +167,7 @@ open class CommonViewModel : ViewModel() { fun runWithAuthorization(action: () -> Unit) { authorizedAction = action - navigation.postValue(Navigation.FeatureAuth()) + navigation.postValue(Navigation.FeatureAuth) } fun checkAuthorization() { diff --git a/app/src/main/java/com/tari/android/wallet/ui/component/loadingSwitch/TariLoadingSwitchState.kt b/app/src/main/java/com/tari/android/wallet/ui/component/loadingSwitch/TariLoadingSwitchState.kt index 3d135a3ca..2473d7e8e 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/component/loadingSwitch/TariLoadingSwitchState.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/component/loadingSwitch/TariLoadingSwitchState.kt @@ -1,3 +1,9 @@ package com.tari.android.wallet.ui.component.loadingSwitch -data class TariLoadingSwitchState(val isChecked: Boolean, val isLoading: Boolean) \ No newline at end of file +data class TariLoadingSwitchState( + val isChecked: Boolean = false, + val isLoading: Boolean = false, +) { + fun startLoading() = this.copy(isLoading = true) + fun stopLoading() = this.copy(isLoading = false) +} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/biometrics/ChangeBiometricsFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/biometrics/ChangeBiometricsFragment.kt index e39fa7441..76355cc6e 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/biometrics/ChangeBiometricsFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/biometrics/ChangeBiometricsFragment.kt @@ -14,7 +14,7 @@ import com.tari.android.wallet.extension.observe import com.tari.android.wallet.infrastructure.security.biometric.BiometricAuthenticationException import com.tari.android.wallet.ui.common.CommonFragment import com.tari.android.wallet.ui.extension.string -import com.tari.android.wallet.util.TariBuild.MOCKED +import com.tari.android.wallet.util.DebugConfig import kotlinx.coroutines.launch class ChangeBiometricsFragment : CommonFragment() { @@ -45,7 +45,7 @@ class ChangeBiometricsFragment : CommonFragment() { TitleViewHolder.getBuilder(), ContactProfileViewHolder.getBuilder(), SettingsDividerViewHolder.getBuilder(), - ButtonViewHolder.getBuilder(), + SettingsRowViewHolder.getBuilder(), SettingsTitleViewHolder.getBuilder(), SpaceVerticalViewHolder.getBuilder(), ContactTypeViewHolder.getBuilder(), diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/link/ContactLinkViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/link/ContactLinkViewModel.kt index 9dd0d6943..9e56f8293 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/link/ContactLinkViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/link/ContactLinkViewModel.kt @@ -184,7 +184,7 @@ class ContactLinkViewModel : CommonViewModel() { ButtonModule(resourceManager.getString(common_close), ButtonStyle.Close) ) modularDialog.postValue(ModularDialogArgs(DialogArgs { - navigation.value = Navigation.ContactBookNavigation.BackToContactBook() + navigation.value = Navigation.ContactBookNavigation.BackToContactBook }, modules)) } } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/root/action_menu/ContactBookActionMenuViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/root/action_menu/ContactBookActionMenuViewModel.kt index 0fdfc2f49..682def97b 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/root/action_menu/ContactBookActionMenuViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/contact_book/root/action_menu/ContactBookActionMenuViewModel.kt @@ -89,7 +89,7 @@ class ContactBookActionMenuViewModel : CommonViewModel() { ButtonModule(resourceManager.getString(R.string.common_cancel), ButtonStyle.Close) ) modularDialog.postValue(ModularDialogArgs(DialogArgs { - navigation.value = Navigation.ContactBookNavigation.BackToContactBook() + navigation.value = Navigation.ContactBookNavigation.BackToContactBook }, modules)) } } diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/HomeActivity.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/HomeActivity.kt index 77f56f6e6..b8c589847 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/HomeActivity.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/HomeActivity.kt @@ -90,7 +90,7 @@ import com.tari.android.wallet.ui.fragment.splash.SplashActivity import com.tari.android.wallet.ui.fragment.store.StoreFragment import com.tari.android.wallet.ui.fragment.tx.HomeFragment import com.tari.android.wallet.util.Constants -import com.tari.android.wallet.util.TariBuild +import com.tari.android.wallet.util.DebugConfig import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -263,13 +263,13 @@ class HomeActivity : CommonActivity() { } private fun setupUi() { - ui.sendTariButton.setOnClickListener { viewModel.navigation.postValue(Navigation.TxListNavigation.ToTransfer()) } + ui.sendTariButton.setOnClickListener { viewModel.navigation.postValue(Navigation.TxListNavigation.ToTransfer) } setupBottomNavigation() } private fun setupBottomNavigation() { enableNavigationView(ui.homeImageView) - ui.viewPager.adapter = if (TariBuild.isChat) HomeChatAdapter(supportFragmentManager, this.lifecycle) + ui.viewPager.adapter = if (DebugConfig.isChatEnabled) HomeChatAdapter(supportFragmentManager, this.lifecycle) else HomeStoreAdapter(supportFragmentManager, this.lifecycle) ui.viewPager.isUserInputEnabled = false ui.viewPager.offscreenPageLimit = 3 @@ -277,12 +277,12 @@ class HomeActivity : CommonActivity() { ui.viewPager.setCurrentItem(INDEX_HOME, NO_SMOOTH_SCROLL) enableNavigationView(ui.homeImageView) } - ui.storeImageView.setImageResource(if (TariBuild.isChat) R.drawable.vector_home_book else R.drawable.vector_ttl_store_icon) + ui.storeImageView.setImageResource(if (DebugConfig.isChatEnabled) R.drawable.vector_home_book else R.drawable.vector_ttl_store_icon) ui.storeView.setOnClickListener { ui.viewPager.setCurrentItem(INDEX_CONTACT_BOOK, NO_SMOOTH_SCROLL) enableNavigationView(ui.storeImageView) } - ui.chatImageView.setImageResource(if (TariBuild.isChat) R.drawable.vector_home_chat else R.drawable.vector_home_book) + ui.chatImageView.setImageResource(if (DebugConfig.isChatEnabled) R.drawable.vector_home_chat else R.drawable.vector_home_book) ui.chatView.setOnClickListener { ui.viewPager.setCurrentItem(INDEX_CHAT, NO_SMOOTH_SCROLL) enableNavigationView(ui.chatImageView) diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/Navigation.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/Navigation.kt index 2b428a343..ccd5aee35 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/Navigation.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/Navigation.kt @@ -12,29 +12,22 @@ import com.tari.android.wallet.ui.fragment.send.common.TransactionData sealed class Navigation { class EnterPinCodeNavigation(val behavior: PinCodeScreenBehavior, val stashedPin: String? = null): Navigation() - - class ChangeBiometrics(): Navigation() - - class FeatureAuth(): Navigation() + object ChangeBiometrics : Navigation() + object FeatureAuth : Navigation() sealed class CustomBridgeNavigation : Navigation() { object UploadQrCode : CustomBridgeNavigation() } sealed class BackupSettingsNavigation : Navigation() { - object ToLearnMore : BackupSettingsNavigation() - object ToWalletBackupWithRecoveryPhrase : BackupSettingsNavigation() - object ToChangePassword : BackupSettingsNavigation() - object ToConfirmPassword : BackupSettingsNavigation() } sealed class VerifySeedPhraseNavigation : Navigation() { object ToSeedPhraseVerificationComplete : VerifySeedPhraseNavigation() - class ToSeedPhraseVerification(val seedWords: List) : VerifySeedPhraseNavigation() } @@ -47,36 +40,25 @@ sealed class Navigation { } sealed class TxListNavigation : Navigation() { - object ToSplashScreen : TxListNavigation() - class ToTxDetails(val tx: Tx) : TxListNavigation() - object ToChat : TxListNavigation() - object ToAllSettings : TxListNavigation() - object ToUtxos : TxListNavigation() - class ToSendTariToUser(val contact: ContactDto, val amount: MicroTari? = null) : TxListNavigation() class ToSendWithDeeplink(val sendDeeplink: DeepLink.Send) : TxListNavigation() - object HomeTransactionHistory : TxListNavigation() - - class ToTransfer : TxListNavigation() + object ToTransfer : TxListNavigation() } sealed class ChatNavigation : Navigation() { object ToAddChat : ChatNavigation() - class ToChat(val walletAddress: TariWalletAddress, val isNew: Boolean) : ChatNavigation() } sealed class AddAmountNavigation : Navigation() { object OnAmountExceedsActualAvailableBalance : AddAmountNavigation() - class ContinueToAddNote(val transactionData: TransactionData) : AddAmountNavigation() - class ContinueToFinalizing(val transactionData: TransactionData) : AddAmountNavigation() } @@ -93,6 +75,7 @@ sealed class Navigation { object ToBackupSettings : AllSettingsNavigation() object ToDeleteWallet : AllSettingsNavigation() object ToBackgroundService : AllSettingsNavigation() + object ToScreenRecording : AllSettingsNavigation() object ToBluetoothSettings : AllSettingsNavigation() object ToThemeSelection : AllSettingsNavigation() object ToTorBridges : AllSettingsNavigation() @@ -112,34 +95,21 @@ sealed class Navigation { sealed class ChooseRestoreOptionNavigation : Navigation() { object ToEnterRestorePassword : ChooseRestoreOptionNavigation() - object ToRestoreWithRecoveryPhrase : ChooseRestoreOptionNavigation() - object OnRestoreCompleted : ChooseRestoreOptionNavigation() } - sealed class ContactBookNavigation : Navigation() { - class ToContactDetails(val contact: ContactDto) : ContactBookNavigation() - object ToAddContact : ContactBookNavigation() - object ToAddPhoneContact : ContactBookNavigation() - class ToSendTari(val contact: ContactDto) : ContactBookNavigation() - - class ToSelectTariUser : ContactBookNavigation() - + object ToSelectTariUser : ContactBookNavigation() class ToRequestTari(val contact: ContactDto) : ContactBookNavigation() - class ToExternalWallet(val connectedWallet: YatDto.ConnectedWallet) : ContactBookNavigation() - class ToLinkContact(val contact: ContactDto) : ContactBookNavigation() - class ToContactTransactionHistory(val contact: ContactDto) : ContactBookNavigation() - - class BackToContactBook : ContactBookNavigation() + object BackToContactBook : ContactBookNavigation() } } diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/TariNavigator.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/TariNavigator.kt index 6f07a5f3d..fd2648a8c 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/TariNavigator.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/home/navigation/TariNavigator.kt @@ -4,7 +4,6 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.ContactsContract -import androidx.fragment.app.Fragment import com.tari.android.wallet.R import com.tari.android.wallet.application.deeplinks.DeepLink import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository @@ -22,6 +21,7 @@ import com.tari.android.wallet.model.TxId import com.tari.android.wallet.network.NetworkConnectionState import com.tari.android.wallet.service.TariWalletService import com.tari.android.wallet.ui.common.CommonActivity +import com.tari.android.wallet.ui.common.CommonFragment import com.tari.android.wallet.ui.dialog.modular.DialogArgs import com.tari.android.wallet.ui.dialog.modular.ModularDialog import com.tari.android.wallet.ui.dialog.modular.ModularDialogArgs @@ -46,8 +46,20 @@ import com.tari.android.wallet.ui.fragment.contact_book.root.ContactBookFragment import com.tari.android.wallet.ui.fragment.contact_book.transactionHistory.TransactionHistoryFragment import com.tari.android.wallet.ui.fragment.home.HomeActivity import com.tari.android.wallet.ui.fragment.home.homeTransactionHistory.HomeTransactionHistoryFragment +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.AddAmountNavigation import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.AllSettingsNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.BackupSettingsNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.BaseNodeNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.ChatNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.ChooseRestoreOptionNavigation import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.ContactBookNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.CustomBridgeNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.EnterRestorationPasswordNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.InputSeedWordsNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.TorBridgeNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.TxListNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.VerifySeedPhraseNavigation +import com.tari.android.wallet.ui.fragment.home.navigation.Navigation.WalletRestoringFromSeedWordsNavigation import com.tari.android.wallet.ui.fragment.onboarding.activity.OnboardingFlowActivity import com.tari.android.wallet.ui.fragment.onboarding.localAuth.LocalAuthFragment import com.tari.android.wallet.ui.fragment.pinCode.EnterPinCodeFragment @@ -79,6 +91,7 @@ import com.tari.android.wallet.ui.fragment.settings.deleteWallet.DeleteWalletFra import com.tari.android.wallet.ui.fragment.settings.logs.activity.DebugActivity import com.tari.android.wallet.ui.fragment.settings.logs.activity.DebugNavigation import com.tari.android.wallet.ui.fragment.settings.networkSelection.NetworkSelectionFragment +import com.tari.android.wallet.ui.fragment.settings.screenRecording.ScreenRecordingSettingsFragment import com.tari.android.wallet.ui.fragment.settings.themeSelector.ThemeSelectorFragment import com.tari.android.wallet.ui.fragment.settings.torBridges.TorBridgesSelectionFragment import com.tari.android.wallet.ui.fragment.settings.torBridges.customBridges.CustomTorBridgesFragment @@ -89,7 +102,7 @@ import java.math.BigInteger import javax.inject.Inject import javax.inject.Singleton - +// TODO: move navigation logic to only the navigate() method and make all navigation methods private @Singleton class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val tariSettingsSharedRepository: TariSettingsSharedRepository) { @@ -110,53 +123,54 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta is ContactBookNavigation.ToContactTransactionHistory -> toContactTransactionHistory(navigation.contact) is ContactBookNavigation.ToAddPhoneContact -> toAddPhoneContact() is ContactBookNavigation.ToSelectTariUser -> addFragment(SelectUserContactFragment.newInstance()) - Navigation.ChooseRestoreOptionNavigation.ToEnterRestorePassword -> toEnterRestorePassword() - Navigation.ChooseRestoreOptionNavigation.OnRestoreCompleted -> onRestoreCompleted() - Navigation.ChooseRestoreOptionNavigation.ToRestoreWithRecoveryPhrase -> toRestoreWithRecoveryPhrase() - AllSettingsNavigation.ToBugReporting -> DebugActivity.launch(activity, DebugNavigation.BugReport) - AllSettingsNavigation.ToMyProfile -> toMyProfile() - AllSettingsNavigation.ToAbout -> toAbout() - AllSettingsNavigation.ToBackgroundService -> toBackgroundService() - AllSettingsNavigation.ToBluetoothSettings -> addFragment(BluetoothSettingsFragment()) - AllSettingsNavigation.ToBackupSettings -> toBackupSettings(true) - AllSettingsNavigation.ToBaseNodeSelection -> toBaseNodeSelection() - AllSettingsNavigation.ToDeleteWallet -> toDeleteWallet() - AllSettingsNavigation.ToNetworkSelection -> toNetworkSelection() - AllSettingsNavigation.ToTorBridges -> toTorBridges() - AllSettingsNavigation.ToDataCollection -> addFragment(DataCollectionFragment()) - AllSettingsNavigation.ToThemeSelection -> toThemeSelection() - AllSettingsNavigation.ToRequestTari -> addFragment(RequestTariFragment.newInstance()) - Navigation.EnterRestorationPasswordNavigation.OnRestore -> onRestoreCompleted() - Navigation.InputSeedWordsNavigation.ToRestoreFormSeedWordsInProgress -> toRestoreFromSeedWordsInProgress() - Navigation.InputSeedWordsNavigation.ToBaseNodeSelection -> toBaseNodeSelection() - Navigation.WalletRestoringFromSeedWordsNavigation.OnRestoreCompleted -> onRestoreCompleted() - Navigation.WalletRestoringFromSeedWordsNavigation.OnRestoreFailed -> { + is ChooseRestoreOptionNavigation.ToEnterRestorePassword -> toEnterRestorePassword() + is ChooseRestoreOptionNavigation.OnRestoreCompleted -> onRestoreCompleted() + is ChooseRestoreOptionNavigation.ToRestoreWithRecoveryPhrase -> toRestoreWithRecoveryPhrase() + is AllSettingsNavigation.ToBugReporting -> DebugActivity.launch(activity, DebugNavigation.BugReport) + is AllSettingsNavigation.ToMyProfile -> toMyProfile() + is AllSettingsNavigation.ToAbout -> toAbout() + is AllSettingsNavigation.ToBackgroundService -> toBackgroundService() + is AllSettingsNavigation.ToScreenRecording -> toScreenRecording() + is AllSettingsNavigation.ToBluetoothSettings -> addFragment(BluetoothSettingsFragment()) + is AllSettingsNavigation.ToBackupSettings -> toBackupSettings(true) + is AllSettingsNavigation.ToBaseNodeSelection -> toBaseNodeSelection() + is AllSettingsNavigation.ToDeleteWallet -> toDeleteWallet() + is AllSettingsNavigation.ToNetworkSelection -> toNetworkSelection() + is AllSettingsNavigation.ToTorBridges -> toTorBridges() + is AllSettingsNavigation.ToDataCollection -> addFragment(DataCollectionFragment()) + is AllSettingsNavigation.ToThemeSelection -> toThemeSelection() + is AllSettingsNavigation.ToRequestTari -> addFragment(RequestTariFragment.newInstance()) + is EnterRestorationPasswordNavigation.OnRestore -> onRestoreCompleted() + is InputSeedWordsNavigation.ToRestoreFormSeedWordsInProgress -> toRestoreFromSeedWordsInProgress() + is InputSeedWordsNavigation.ToBaseNodeSelection -> toBaseNodeSelection() + is WalletRestoringFromSeedWordsNavigation.OnRestoreCompleted -> onRestoreCompleted() + is WalletRestoringFromSeedWordsNavigation.OnRestoreFailed -> { // changeOnBackPressed(false) onBackPressed() } - Navigation.AddAmountNavigation.OnAmountExceedsActualAvailableBalance -> onAmountExceedsActualAvailableBalance() - is Navigation.AddAmountNavigation.ContinueToAddNote -> continueToAddNote(navigation.transactionData) - is Navigation.AddAmountNavigation.ContinueToFinalizing -> continueToFinalizeSendTx(navigation.transactionData) - Navigation.TxListNavigation.ToChat -> toChat() - is Navigation.TxListNavigation.ToTxDetails -> toTxDetails(navigation.tx, null) - is Navigation.TxListNavigation.ToSendTariToUser -> toSendTari(navigation.contact, navigation.amount) - is Navigation.TxListNavigation.ToSendWithDeeplink -> toSendWithDeeplink(navigation.sendDeeplink) - Navigation.TxListNavigation.ToUtxos -> toUtxos() - Navigation.TxListNavigation.ToAllSettings -> toAllSettings() - Navigation.TxListNavigation.ToSplashScreen -> toSplash() - is Navigation.TxListNavigation.ToTransfer -> addFragment(TransferFragment()) - is Navigation.TxListNavigation.HomeTransactionHistory -> addFragment(HomeTransactionHistoryFragment()) - Navigation.TorBridgeNavigation.ToCustomBridges -> toCustomTorBridges() - Navigation.BaseNodeNavigation.ToAddCustomBaseNode -> toAddCustomBaseNode() - Navigation.VerifySeedPhraseNavigation.ToSeedPhraseVerificationComplete -> onSeedPhraseVerificationComplete() - is Navigation.VerifySeedPhraseNavigation.ToSeedPhraseVerification -> toSeedPhraseVerification(navigation.seedWords) - Navigation.BackupSettingsNavigation.ToChangePassword -> toChangePassword() - Navigation.BackupSettingsNavigation.ToConfirmPassword -> toConfirmPassword() - Navigation.BackupSettingsNavigation.ToWalletBackupWithRecoveryPhrase -> toWalletBackupWithRecoveryPhrase() - Navigation.BackupSettingsNavigation.ToLearnMore -> toBackupOnboardingFlow() - Navigation.CustomBridgeNavigation.UploadQrCode -> Unit - is Navigation.ChatNavigation.ToChat -> { + is AddAmountNavigation.OnAmountExceedsActualAvailableBalance -> onAmountExceedsActualAvailableBalance() + is AddAmountNavigation.ContinueToAddNote -> continueToAddNote(navigation.transactionData) + is AddAmountNavigation.ContinueToFinalizing -> continueToFinalizeSendTx(navigation.transactionData) + is TxListNavigation.ToChat -> toChat() + is TxListNavigation.ToTxDetails -> toTxDetails(navigation.tx, null) + is TxListNavigation.ToSendTariToUser -> toSendTari(navigation.contact, navigation.amount) + is TxListNavigation.ToSendWithDeeplink -> toSendWithDeeplink(navigation.sendDeeplink) + is TxListNavigation.ToUtxos -> toUtxos() + is TxListNavigation.ToAllSettings -> toAllSettings() + is TxListNavigation.ToSplashScreen -> toSplash() + is TxListNavigation.ToTransfer -> addFragment(TransferFragment()) + is TxListNavigation.HomeTransactionHistory -> addFragment(HomeTransactionHistoryFragment()) + is TorBridgeNavigation.ToCustomBridges -> toCustomTorBridges() + is BaseNodeNavigation.ToAddCustomBaseNode -> toAddCustomBaseNode() + is VerifySeedPhraseNavigation.ToSeedPhraseVerificationComplete -> onSeedPhraseVerificationComplete() + is VerifySeedPhraseNavigation.ToSeedPhraseVerification -> toSeedPhraseVerification(navigation.seedWords) + is BackupSettingsNavigation.ToChangePassword -> toChangePassword() + is BackupSettingsNavigation.ToConfirmPassword -> toConfirmPassword() + is BackupSettingsNavigation.ToWalletBackupWithRecoveryPhrase -> toWalletBackupWithRecoveryPhrase() + is BackupSettingsNavigation.ToLearnMore -> toBackupOnboardingFlow() + is CustomBridgeNavigation.UploadQrCode -> Unit + is ChatNavigation.ToChat -> { if (navigation.isNew) { onBackPressed() } @@ -164,8 +178,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta addFragment(ChatFragment.newInstance(navigation.walletAddress)) } - Navigation.ChatNavigation.ToAddChat -> addFragment(AddChatFragment()) - else -> Unit + is ChatNavigation.ToAddChat -> addFragment(AddChatFragment()) } } @@ -176,18 +189,18 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta activity.finishAffinity() } - fun toAddPhoneContact() { + private fun toAddPhoneContact() { val intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI) activity.startActivity(intent) } - fun toEnterRestorePassword() = addFragment(EnterRestorationPasswordFragment.newInstance()) + private fun toEnterRestorePassword() = addFragment(EnterRestorationPasswordFragment.newInstance()) - fun toRestoreWithRecoveryPhrase() = addFragment(InputSeedWordsFragment.newInstance()) + private fun toRestoreWithRecoveryPhrase() = addFragment(InputSeedWordsFragment.newInstance()) - fun toRestoreFromSeedWordsInProgress() = addFragment(WalletRestoringFromSeedWordsFragment.newInstance()) + private fun toRestoreFromSeedWordsInProgress() = addFragment(WalletRestoringFromSeedWordsFragment.newInstance()) - fun onRestoreCompleted() { + private fun onRestoreCompleted() { // wallet restored, setup shared prefs accordingly prefs.onboardingCompleted = true prefs.onboardingStarted = true @@ -211,60 +224,62 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta } }) - fun toChat() = (activity as HomeActivity).ui.viewPager.setCurrentItem(INDEX_CHAT, NO_SMOOTH_SCROLL) + private fun toChat() = (activity as HomeActivity).ui.viewPager.setCurrentItem(INDEX_CHAT, NO_SMOOTH_SCROLL) fun toAllSettings() = (activity as HomeActivity).ui.viewPager.setCurrentItem(INDEX_SETTINGS, NO_SMOOTH_SCROLL) fun toBackupSettings(withAnimation: Boolean) = addFragment(BackupSettingsFragment(), withAnimation = withAnimation) - fun toDeleteWallet() = addFragment(DeleteWalletFragment()) + private fun toDeleteWallet() = addFragment(DeleteWalletFragment()) + + private fun toBackgroundService() = addFragment(BackgroundServiceSettingsFragment()) - fun toBackgroundService() = addFragment(BackgroundServiceSettingsFragment()) + private fun toScreenRecording() = addFragment(ScreenRecordingSettingsFragment()) - fun toMyProfile() = addFragment(WalletInfoFragment()) + private fun toMyProfile() = addFragment(WalletInfoFragment()) - fun toAbout() = addFragment(TariAboutFragment()) + private fun toAbout() = addFragment(TariAboutFragment()) - fun toBackupOnboardingFlow() = addFragment(BackupOnboardingFlowFragment()) + private fun toBackupOnboardingFlow() = addFragment(BackupOnboardingFlowFragment()) - fun toBaseNodeSelection() = addFragment(ChangeBaseNodeFragment()) + private fun toBaseNodeSelection() = addFragment(ChangeBaseNodeFragment()) - fun toTorBridges() = addFragment(TorBridgesSelectionFragment()) + private fun toTorBridges() = addFragment(TorBridgesSelectionFragment()) - fun toThemeSelection() = addFragment(ThemeSelectorFragment()) + private fun toThemeSelection() = addFragment(ThemeSelectorFragment()) - fun toUtxos() = addFragment(UtxosListFragment()) + private fun toUtxos() = addFragment(UtxosListFragment()) - fun toCustomTorBridges() = addFragment(CustomTorBridgesFragment()) + private fun toCustomTorBridges() = addFragment(CustomTorBridgesFragment()) - fun toNetworkSelection() = addFragment(NetworkSelectionFragment()) + private fun toNetworkSelection() = addFragment(NetworkSelectionFragment()) - fun toAddCustomBaseNode() = addFragment(AddCustomBaseNodeFragment()) + private fun toAddCustomBaseNode() = addFragment(AddCustomBaseNodeFragment()) fun toWalletBackupWithRecoveryPhrase() = addFragment(WriteDownSeedPhraseFragment()) - fun toSeedPhraseVerification(seedWords: List) = addFragment(VerifySeedPhraseFragment.newInstance(seedWords)) + private fun toSeedPhraseVerification(seedWords: List) = addFragment(VerifySeedPhraseFragment.newInstance(seedWords)) - fun toConfirmPassword() = addFragment(EnterCurrentPasswordFragment()) + private fun toConfirmPassword() = addFragment(EnterCurrentPasswordFragment()) fun toChangePassword() = addFragment(ChangeSecurePasswordFragment()) - fun toSendTari(user: ContactDto, amount: MicroTari?) = sendToUser(user, amount) + private fun toSendTari(user: ContactDto, amount: MicroTari?) = sendToUser(user, amount) - fun toSendWithDeeplink(deeplink: DeepLink.Send) { + private fun toSendWithDeeplink(deeplink: DeepLink.Send) { popUpTo(HomeFragment::class.java.simpleName) sendToUserByDeeplink(deeplink) } - fun toAddContact() = addFragment(AddContactFragment()) + private fun toAddContact() = addFragment(AddContactFragment()) - fun toContactDetails(contact: ContactDto) = addFragment(ContactDetailsFragment.createFragment(contact)) + private fun toContactDetails(contact: ContactDto) = addFragment(ContactDetailsFragment.createFragment(contact)) - fun toRequestTariFromContact(contact: ContactDto) = sendToUser(contact) + private fun toRequestTariFromContact(contact: ContactDto) = sendToUser(contact) - fun toSendTariToContact(contact: ContactDto) = sendToUser(contact) + private fun toSendTariToContact(contact: ContactDto) = sendToUser(contact) - fun backToContactBook() = popUpTo(ContactBookFragment::class.java.simpleName) + private fun backToContactBook() = popUpTo(ContactBookFragment::class.java.simpleName) fun backToAllSettings() = popUpTo(AllSettingsFragment::class.java.simpleName) @@ -276,12 +291,11 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta } } - fun toLinkContact(contact: ContactDto) = addFragment(ContactLinkFragment.createFragment(contact)) - - fun toContactTransactionHistory(contact: ContactDto) = addFragment(TransactionHistoryFragment.createFragment(contact)) + private fun toLinkContact(contact: ContactDto) = addFragment(ContactLinkFragment.createFragment(contact)) - fun toExternalWallet(connectedWallet: YatDto.ConnectedWallet) { + private fun toContactTransactionHistory(contact: ContactDto) = addFragment(TransactionHistoryFragment.createFragment(contact)) + private fun toExternalWallet(connectedWallet: YatDto.ConnectedWallet) { try { val externalAddress = connectedWallet.getExternalLink() val intent = Intent(Intent.ACTION_VIEW, Uri.parse(externalAddress)) @@ -296,7 +310,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta } } - fun onAmountExceedsActualAvailableBalance() { + private fun onAmountExceedsActualAvailableBalance() { val args = ModularDialogArgs( DialogArgs(), listOf( HeadModule(activity.string(R.string.error_balance_exceeded_title)), @@ -307,7 +321,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta ModularDialog(activity, args).show() } - fun continueToAddNote(transactionData: TransactionData) { + private fun continueToAddNote(transactionData: TransactionData) { if (EventBus.networkConnectionState.publishSubject.value != NetworkConnectionState.CONNECTED) { showInternetConnectionErrorDialog(this.activity) return @@ -352,7 +366,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta popUpTo(BackupSettingsFragment::class.java.simpleName) } - fun onSeedPhraseVerificationComplete() { + private fun onSeedPhraseVerificationComplete() { popUpTo(BackupSettingsFragment::class.java.simpleName) } @@ -361,7 +375,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta sendToUser((activity as HomeActivity).viewModel.contactsRepository.ffiBridge.getContactByAddress(walletAddress)) } - fun sendToUserByDeeplink(deeplink: DeepLink.Send) { + private fun sendToUserByDeeplink(deeplink: DeepLink.Send) { FFIWallet.instance?.getWalletAddress() val address = FFITariWalletAddress(HexString(deeplink.walletAddressHex)).runWithDestroy { walletAddressFromFFI(it) @@ -378,7 +392,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta private fun walletAddressFromFFI(ffiTariWalletAddress: FFITariWalletAddress): TariWalletAddress = TariWalletAddress(ffiTariWalletAddress.toString(), ffiTariWalletAddress.getEmojiId()) - fun sendToUser(recipientUser: ContactDto, amount: MicroTari? = null) { + private fun sendToUser(recipientUser: ContactDto, amount: MicroTari? = null) { val bundle = Bundle().apply { putSerializable(PARAMETER_CONTACT, recipientUser) val innerAmount = (activity.intent.getDoubleExtra(PARAMETER_AMOUNT, Double.MIN_VALUE)) @@ -391,7 +405,7 @@ class TariNavigator @Inject constructor(val prefs: SharedPrefsRepository, val ta } - private fun addFragment(fragment: Fragment, bundle: Bundle? = null, isRoot: Boolean = false, withAnimation: Boolean = true) = + private fun addFragment(fragment: CommonFragment<*, *>, bundle: Bundle? = null, isRoot: Boolean = false, withAnimation: Boolean = true) = activity.addFragment(fragment, bundle, isRoot, withAnimation) //popup fragment diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsFragment.kt index 202795333..2f98ab128 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/restore/inputSeedWords/InputSeedWordsFragment.kt @@ -34,6 +34,8 @@ class InputSeedWordsFragment : CommonFragment balanceInfo.availableBalance && !TariBuild.MOCKED) { + if (amount > balanceInfo.availableBalance && !DebugConfig.mockedDataEnabled) { lifecycleScope.launch(Dispatchers.Main) { actualBalanceExceeded() } } else { lifecycleScope.launch(Dispatchers.Main) { - if (fee > amount && !TariBuild.MOCKED) { + if (fee > amount && !DebugConfig.mockedDataEnabled) { val args = ErrorDialogArgs( string(error_fee_more_than_amount_title), string(error_fee_more_than_amount_description) @@ -292,7 +292,7 @@ class AddAmountFragment : CommonFragment availableBalance) { + if (!DebugConfig.mockedDataEnabled && (keyboardController.currentAmount + viewModel.selectedFeeData?.calculatedFee!!) > availableBalance) { showErrorState() } else { showSuccessState() diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/send/finalize/YatFinalizeSendTxActivity.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/send/finalize/YatFinalizeSendTxActivity.kt index fa01a234a..7285a921f 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/send/finalize/YatFinalizeSendTxActivity.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/send/finalize/YatFinalizeSendTxActivity.kt @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope import com.google.gson.Gson +import com.orhanobut.logger.Logger import com.tari.android.wallet.extension.observe import com.tari.android.wallet.extension.observeOnLoad import com.tari.android.wallet.ui.fragment.send.common.TransactionData @@ -17,18 +18,27 @@ class YatFinalizeSendTxActivity : YatLibOutcomingTransactionActivity() { val viewModel: FinalizeSendTxViewModel by viewModels() + private val logger + get() = Logger.t(YatFinalizeSendTxActivity::class.simpleName) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val gson = intent.getStringExtra(FinalizeSendTxViewModel.transactionDataKey)!! - val entity = Gson().fromJson(gson, TransactionData::class.java) - - viewModel.transactionData = entity + intent.getStringExtra(FinalizeSendTxViewModel.transactionDataKey) + ?.let { Gson().fromJson(it, TransactionData::class.java) } + ?.let { entity -> + viewModel.transactionData = entity - subscribeOnUI() - launchObserver() + subscribeOnUI() + launchObserver() + } ?: run { + logger.e("Transaction data is null. Finishing activity.") + finish() + return + } } + private fun subscribeOnUI() = with(viewModel) { observe(txFailureReason) { setTransactionState(TransactionState.Failed) } @@ -52,6 +62,6 @@ class YatFinalizeSendTxActivity : YatLibOutcomingTransactionActivity() { super.onStop() viewModel.sentTxId.value?.let { viewModel.tariNavigator.onSendTxSuccessful(true, it) } - viewModel.txFailureReason.value?.let {viewModel.tariNavigator.onSendTxFailure(true, it) } + viewModel.txFailureReason.value?.let { viewModel.tariNavigator.onSendTxFailure(true, it) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsFragment.kt index 7044051e1..11bd5a3b0 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsFragment.kt @@ -36,6 +36,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import com.tari.android.wallet.databinding.FragmentAllSettingsBinding @@ -65,6 +66,15 @@ class AllSettingsFragment : CommonFragment) { + super.onFragmentPopped(fragmentClass) + + // We need to refresh options when we come back to this fragment from some settings screens + // and also disable or enable screen recording calling the onResume method + viewModel.updateOptions() + onResume() + } + private fun setupUI() { ui.optionsList.layoutManager = LinearLayoutManager(requireContext()) ui.optionsList.adapter = optionsAdapter diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsOptionAdapter.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsOptionAdapter.kt index 85af3112c..e11eda820 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsOptionAdapter.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsOptionAdapter.kt @@ -4,16 +4,15 @@ import com.tari.android.wallet.ui.common.recyclerView.CommonAdapter import com.tari.android.wallet.ui.common.recyclerView.CommonViewHolderItem import com.tari.android.wallet.ui.common.recyclerView.ViewHolderBuilder import com.tari.android.wallet.ui.fragment.settings.allSettings.backupOptions.SettingsBackupOptionViewHolder -import com.tari.android.wallet.ui.fragment.settings.allSettings.button.ButtonViewHolder +import com.tari.android.wallet.ui.fragment.settings.allSettings.row.SettingsRowViewHolder import com.tari.android.wallet.ui.fragment.settings.allSettings.divider.SettingsDividerViewHolder -import com.tari.android.wallet.ui.fragment.contact_book.details.adapter.profile.ContactProfileViewHolder import com.tari.android.wallet.ui.fragment.settings.allSettings.myProfile.MyProfileViewHolder import com.tari.android.wallet.ui.fragment.settings.allSettings.title.SettingsTitleViewHolder import com.tari.android.wallet.ui.fragment.settings.allSettings.version.SettingsVersionViewHolder class AllSettingsOptionAdapter: CommonAdapter() { override var viewHolderBuilders: List = mutableListOf( - ButtonViewHolder.getBuilder(), + SettingsRowViewHolder.getBuilder(), SettingsTitleViewHolder.getBuilder(), SettingsDividerViewHolder.getBuilder(), SettingsVersionViewHolder.getBuilder(), diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsViewModel.kt index f0ea57b2d..d67be388e 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/AllSettingsViewModel.kt @@ -16,6 +16,7 @@ import com.tari.android.wallet.R.drawable.vector_all_settings_disclaimer_icon import com.tari.android.wallet.R.drawable.vector_all_settings_passcode import com.tari.android.wallet.R.drawable.vector_all_settings_privacy_policy_icon import com.tari.android.wallet.R.drawable.vector_all_settings_report_bug_icon +import com.tari.android.wallet.R.drawable.vector_all_settings_screen_recording_icon import com.tari.android.wallet.R.drawable.vector_all_settings_select_base_node_icon import com.tari.android.wallet.R.drawable.vector_all_settings_select_network_icon import com.tari.android.wallet.R.drawable.vector_all_settings_select_theme_icon @@ -58,6 +59,7 @@ import com.tari.android.wallet.R.string.tari_about_title import com.tari.android.wallet.R.string.tari_url import com.tari.android.wallet.R.string.ttl_store_url import com.tari.android.wallet.R.string.user_agreement_url +import com.tari.android.wallet.R.string.all_settings_screen_recording import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository import com.tari.android.wallet.event.EventBus import com.tari.android.wallet.extension.addTo @@ -77,8 +79,8 @@ import com.tari.android.wallet.ui.fragment.settings.allSettings.PresentationBack import com.tari.android.wallet.ui.fragment.settings.allSettings.PresentationBackupState.BackupStateStatus.Success import com.tari.android.wallet.ui.fragment.settings.allSettings.PresentationBackupState.BackupStateStatus.Warning import com.tari.android.wallet.ui.fragment.settings.allSettings.backupOptions.SettingsBackupOptionViewHolderItem -import com.tari.android.wallet.ui.fragment.settings.allSettings.button.ButtonStyle -import com.tari.android.wallet.ui.fragment.settings.allSettings.button.ButtonViewDto +import com.tari.android.wallet.ui.fragment.settings.allSettings.row.SettingsRowStyle +import com.tari.android.wallet.ui.fragment.settings.allSettings.row.SettingsRowViewDto import com.tari.android.wallet.ui.fragment.settings.allSettings.myProfile.MyProfileViewHolderItem import com.tari.android.wallet.ui.fragment.settings.allSettings.title.SettingsTitleViewHolderItem import com.tari.android.wallet.ui.fragment.settings.allSettings.version.SettingsVersionViewHolderItem @@ -125,6 +127,10 @@ class AllSettingsViewModel : CommonViewModel() { settingsRepository.updateNotifier.subscribe { initOptions() }.addTo(compositeDisposable) } + fun updateOptions() { + initOptions() + } + private fun initOptions() { val versionText = TariVersionModel(networkRepository).versionInfo val versionArgs = ClipboardArgs( @@ -140,65 +146,65 @@ class AllSettingsViewModel : CommonViewModel() { navigation.postValue(AllSettingsNavigation.ToMyProfile) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_connect_yats), vector_all_settings_yat_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_connect_yats), vector_all_settings_yat_icon) { _openYatOnboarding.postValue(Unit) }, SettingsTitleViewHolderItem(resourceManager.getString(all_settings_security_label)), backupOption, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_data_collection), vector_all_settings_data_collection) { + SettingsRowViewDto(resourceManager.getString(all_settings_data_collection), vector_all_settings_data_collection) { navigation.postValue(AllSettingsNavigation.ToDataCollection) }, DividerViewHolderItem(), if (pinCode != null) { - ButtonViewDto(resourceManager.getString(all_settings_pin_code), vector_all_settings_passcode) { + SettingsRowViewDto(resourceManager.getString(all_settings_pin_code), vector_all_settings_passcode) { runWithAuthorization { navigation.postValue(Navigation.EnterPinCodeNavigation(PinCodeScreenBehavior.ChangeNew)) } } } else { - ButtonViewDto(resourceManager.getString(all_settings_create_pin_code), vector_all_settings_passcode) { + SettingsRowViewDto(resourceManager.getString(all_settings_create_pin_code), vector_all_settings_passcode) { runWithAuthorization { navigation.postValue(Navigation.EnterPinCodeNavigation(PinCodeScreenBehavior.Create)) } } }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_biometrics), vector_fingerprint) { + SettingsRowViewDto(resourceManager.getString(all_settings_biometrics), vector_fingerprint) { runWithAuthorization { - navigation.postValue(Navigation.ChangeBiometrics()) + navigation.postValue(Navigation.ChangeBiometrics) } }, SettingsTitleViewHolderItem(resourceManager.getString(all_settings_secondary_settings_label)), - ButtonViewDto(resourceManager.getString(all_settings_store), vector_all_settings_cart) { + SettingsRowViewDto(resourceManager.getString(all_settings_store), vector_all_settings_cart) { _openLink.postValue(resourceManager.getString(ttl_store_url)) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(tari_about_title), vector_all_settings_about_icon) { + SettingsRowViewDto(resourceManager.getString(tari_about_title), vector_all_settings_about_icon) { navigation.postValue(AllSettingsNavigation.ToAbout) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_report_a_bug), vector_all_settings_report_bug_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_report_a_bug), vector_all_settings_report_bug_icon) { navigation.postValue(AllSettingsNavigation.ToBugReporting) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_visit_site), vector_all_settings_visit_tari_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_visit_site), vector_all_settings_visit_tari_icon) { _openLink.postValue(resourceManager.getString(tari_url)) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_contribute), vector_all_settings_contribute_to_tari_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_contribute), vector_all_settings_contribute_to_tari_icon) { _openLink.postValue(resourceManager.getString(github_repo_url)) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_user_agreement), vector_all_settings_user_agreement_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_user_agreement), vector_all_settings_user_agreement_icon) { _openLink.postValue(resourceManager.getString(user_agreement_url)) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_privacy_policy), vector_all_settings_privacy_policy_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_privacy_policy), vector_all_settings_privacy_policy_icon) { _openLink.postValue(resourceManager.getString(privacy_policy_url)) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_disclaimer), vector_all_settings_disclaimer_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_disclaimer), vector_all_settings_disclaimer_icon) { _openLink.postValue(resourceManager.getString(disclaimer_url)) }, DividerViewHolderItem(), @@ -206,33 +212,44 @@ class AllSettingsViewModel : CommonViewModel() { // _openLink.postValue(resourceManager.getString(explorer_url)) // }, SettingsTitleViewHolderItem(resourceManager.getString(all_settings_advanced_settings_label)), - ButtonViewDto(resourceManager.getString(all_settings_select_theme), vector_all_settings_select_theme_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_select_theme), vector_all_settings_select_theme_icon) { navigation.postValue(AllSettingsNavigation.ToThemeSelection) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_background_service), vector_all_settings_background_service_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_background_service), vector_all_settings_background_service_icon) { navigation.postValue(AllSettingsNavigation.ToBackgroundService) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_bluetooth_settings), vector_all_settings_bluetooth) { + SettingsRowViewDto( + title = resourceManager.getString(all_settings_screen_recording), + leftIconId = vector_all_settings_screen_recording_icon, + warning = tariSettingsSharedRepository.screenRecordingTurnedOn, + ) { + navigation.postValue(AllSettingsNavigation.ToScreenRecording) + }, + DividerViewHolderItem(), + SettingsRowViewDto(resourceManager.getString(all_settings_bluetooth_settings), vector_all_settings_bluetooth) { navigation.postValue(AllSettingsNavigation.ToBluetoothSettings) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_bridge_configuration), vector_all_settings_bridge_configuration_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_bridge_configuration), vector_all_settings_bridge_configuration_icon) { navigation.postValue(AllSettingsNavigation.ToTorBridges) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_select_network), vector_all_settings_select_network_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_select_network), vector_all_settings_select_network_icon) { navigation.postValue(AllSettingsNavigation.ToNetworkSelection) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_select_base_node), vector_all_settings_select_base_node_icon) { + SettingsRowViewDto(resourceManager.getString(all_settings_select_base_node), vector_all_settings_select_base_node_icon) { navigation.postValue(AllSettingsNavigation.ToBaseNodeSelection) }, DividerViewHolderItem(), - ButtonViewDto(resourceManager.getString(all_settings_delete_wallet), vector_all_settings_delete_button_icon, null, ButtonStyle.Warning) { - navigation.postValue(AllSettingsNavigation.ToDeleteWallet) - }, + SettingsRowViewDto( + title = resourceManager.getString(all_settings_delete_wallet), + leftIconId = vector_all_settings_delete_button_icon, + iconId = null, + style = SettingsRowStyle.Warning, + ) { navigation.postValue(AllSettingsNavigation.ToDeleteWallet) }, DividerViewHolderItem(), SettingsVersionViewHolderItem(versionText) { _copyToClipboard.postValue(versionArgs) } ) diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewHolder.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewHolder.kt deleted file mode 100644 index 64dad8c98..000000000 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewHolder.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.tari.android.wallet.ui.fragment.settings.allSettings.button - -import com.tari.android.wallet.databinding.ItemButtonBinding -import com.tari.android.wallet.ui.common.recyclerView.CommonViewHolder -import com.tari.android.wallet.ui.common.recyclerView.ViewHolderBuilder - -class ButtonViewHolder(view: ItemButtonBinding) : CommonViewHolder(view) { - - override fun bind(item: ButtonViewDto) { - super.bind(item) - ui.button.initDto(item) - } - - companion object { - fun getBuilder(): ViewHolderBuilder = ViewHolderBuilder(ItemButtonBinding::inflate, ButtonViewDto::class.java) { - ButtonViewHolder(it as ItemButtonBinding) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonStyle.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowStyle.kt similarity index 72% rename from app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonStyle.kt rename to app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowStyle.kt index 156802c9f..c0a0c5df1 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonStyle.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowStyle.kt @@ -1,6 +1,6 @@ -package com.tari.android.wallet.ui.fragment.settings.allSettings.button +package com.tari.android.wallet.ui.fragment.settings.allSettings.row -enum class ButtonStyle { +enum class SettingsRowStyle { Normal, Warning, } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonView.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowView.kt similarity index 71% rename from app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonView.kt rename to app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowView.kt index e91f700a0..cdf98e3ad 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonView.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowView.kt @@ -1,16 +1,16 @@ -package com.tari.android.wallet.ui.fragment.settings.allSettings.button +package com.tari.android.wallet.ui.fragment.settings.allSettings.row import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.ViewGroup import com.tari.android.wallet.R -import com.tari.android.wallet.databinding.ViewButtonBinding +import com.tari.android.wallet.databinding.ViewSettingsRowBinding import com.tari.android.wallet.ui.common.CommonViewModel import com.tari.android.wallet.ui.component.common.CommonView import com.tari.android.wallet.ui.extension.setVisible -class ButtonView : CommonView { +class SettingsRowView : CommonView { constructor(context: Context) : super(context, null) @@ -18,12 +18,12 @@ class ButtonView : CommonView { constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - override fun bindingInflate(layoutInflater: LayoutInflater, parent: ViewGroup?, attachToRoot: Boolean): ViewButtonBinding = - ViewButtonBinding.inflate(layoutInflater, parent, attachToRoot) + override fun bindingInflate(layoutInflater: LayoutInflater, parent: ViewGroup?, attachToRoot: Boolean): ViewSettingsRowBinding = + ViewSettingsRowBinding.inflate(layoutInflater, parent, attachToRoot) override fun setup() = Unit - fun initDto(dto: ButtonViewDto) { + fun initDto(dto: SettingsRowViewDto) { ui.leftIcon.setVisible(dto.leftIconId != null) dto.leftIconId?.let { ui.leftIcon.setImageResource(it) } ui.title.text = dto.title @@ -35,14 +35,16 @@ class ButtonView : CommonView { } val color = when (dto.style) { - ButtonStyle.Normal -> paletteManager.getTextHeading(context) - ButtonStyle.Warning -> paletteManager.getRed(context) + SettingsRowStyle.Normal -> paletteManager.getTextHeading(context) + SettingsRowStyle.Warning -> paletteManager.getRed(context) } ui.title.setTextColor(color) ui.icon.setColorFilter(color) ui.leftIcon.setColorFilter(color) + ui.warning.setVisible(dto.warning) + ui.root.setOnClickListener { dto.action.invoke() } } } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewDto.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewDto.kt similarity index 66% rename from app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewDto.kt rename to app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewDto.kt index ed6d877c3..ffd8f2169 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/button/ButtonViewDto.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewDto.kt @@ -1,13 +1,14 @@ -package com.tari.android.wallet.ui.fragment.settings.allSettings.button +package com.tari.android.wallet.ui.fragment.settings.allSettings.row import com.tari.android.wallet.ui.common.recyclerView.CommonViewHolderItem -class ButtonViewDto( +class SettingsRowViewDto( val title: String, val leftIconId: Int? = null, val iconId: Int? = null, - val style: ButtonStyle = ButtonStyle.Normal, - val action: () -> Unit + val warning: Boolean = false, + val style: SettingsRowStyle = SettingsRowStyle.Normal, + val action: () -> Unit, ) : CommonViewHolderItem() { override val viewHolderUUID: String = title } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewHolder.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewHolder.kt new file mode 100644 index 000000000..c7eb0b952 --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/allSettings/row/SettingsRowViewHolder.kt @@ -0,0 +1,19 @@ +package com.tari.android.wallet.ui.fragment.settings.allSettings.row + +import com.tari.android.wallet.databinding.ItemSettingsRowBinding +import com.tari.android.wallet.ui.common.recyclerView.CommonViewHolder +import com.tari.android.wallet.ui.common.recyclerView.ViewHolderBuilder + +class SettingsRowViewHolder(view: ItemSettingsRowBinding) : CommonViewHolder(view) { + + override fun bind(item: SettingsRowViewDto) { + super.bind(item) + ui.button.initDto(item) + } + + companion object { + fun getBuilder(): ViewHolderBuilder = ViewHolderBuilder(ItemSettingsRowBinding::inflate, SettingsRowViewDto::class.java) { + SettingsRowViewHolder(it as ItemSettingsRowBinding) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/backupOnboarding/item/BackupOnboardingArgs.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/backupOnboarding/item/BackupOnboardingArgs.kt index b0de96d0f..74cacee69 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/backupOnboarding/item/BackupOnboardingArgs.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/backupOnboarding/item/BackupOnboardingArgs.kt @@ -3,7 +3,7 @@ package com.tari.android.wallet.ui.fragment.settings.backup.backupOnboarding.ite import android.graphics.Typeface import android.text.SpannableString import com.tari.android.wallet.R -import com.tari.android.wallet.application.securityStage.StagedWalletSecurityManager +import com.tari.android.wallet.application.securityStage.STAGE_TWO_THRESHOLD_BALANCE import com.tari.android.wallet.extension.applyCenterAlignment import com.tari.android.wallet.extension.applyColorStyle import com.tari.android.wallet.extension.applyTypefaceStyle @@ -108,7 +108,7 @@ sealed class BackupOnboardingArgs( 0 -> resourceManager.getString(R.string.onboarding_staged_wallet_security_footer_part3_any_funds) else -> resourceManager.getString( R.string.onboarding_staged_wallet_security_footer_part3_threshold, - StagedWalletSecurityManager.stageTwoThresholdBalance.formattedTariValue + STAGE_TWO_THRESHOLD_BALANCE.formattedTariValue, ) } val spannable = SpannableString("$firstPart $highlighted$part3") diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/SeedPhrase.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/SeedPhrase.kt index 8b96c8eb8..a4968c77a 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/SeedPhrase.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/SeedPhrase.kt @@ -1,12 +1,12 @@ package com.tari.android.wallet.ui.fragment.settings.backup.verifySeedPhrase -import com.tari.android.wallet.util.TariBuild +import com.tari.android.wallet.util.DebugConfig class SeedPhrase(private val seedWords: List) : Iterable { val length get() = seedWords.size - private fun sorted(): SeedPhrase = SeedPhrase(if (TariBuild.MOCKED) seedWords else seedWords.sorted()) + private fun sorted(): SeedPhrase = SeedPhrase(if (DebugConfig.mockedDataEnabled) seedWords else seedWords.sorted()) fun consistsOf(result: List): Boolean = seedWords == result diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/VerifySeedPhraseFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/VerifySeedPhraseFragment.kt index ffd64f063..4c0529fed 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/VerifySeedPhraseFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/verifySeedPhrase/VerifySeedPhraseFragment.kt @@ -53,6 +53,8 @@ import com.tari.android.wallet.ui.extension.visible class VerifySeedPhraseFragment : CommonFragment() { + override fun screenRecordingAlwaysDisable() = true + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = FragmentVerifySeedPhraseBinding.inflate(inflater, container, false).also { ui = it }.root diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/writeDownSeedWords/WriteDownSeedPhraseFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/writeDownSeedWords/WriteDownSeedPhraseFragment.kt index 9bb6f63fb..12de2c76b 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/writeDownSeedWords/WriteDownSeedPhraseFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/backup/writeDownSeedWords/WriteDownSeedPhraseFragment.kt @@ -60,6 +60,8 @@ class WriteDownSeedPhraseFragment : CommonFragment(view) { +class LogFileViewHolder(view: ItemSettingsRowBinding) : CommonViewHolder(view) { override fun bind(item: LogFileViewHolderItem) { super.bind(item) - ui.button.initDto(ButtonViewDto(item.filename) { item.action(item) }) + ui.button.initDto(SettingsRowViewDto(item.filename) { item.action(item) }) ui.button.ui.title.text = item.filename } companion object { fun getBuilder() = ViewHolderBuilder( - ItemButtonBinding::inflate, + ItemSettingsRowBinding::inflate, LogFileViewHolderItem::class.java - ) { view -> LogFileViewHolder(view as ItemButtonBinding) } + ) { view -> LogFileViewHolder(view as ItemSettingsRowBinding) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsFragment.kt new file mode 100644 index 000000000..8ddbb9b0f --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsFragment.kt @@ -0,0 +1,76 @@ +/** + * Copyright 2020 The Tari Project + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.tari.android.wallet.ui.fragment.settings.screenRecording + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle +import com.tari.android.wallet.databinding.FragmentScreenRecordingSettingsBinding +import com.tari.android.wallet.extension.launchAndRepeatOnLifecycle +import com.tari.android.wallet.ui.common.CommonFragment +import kotlinx.coroutines.launch + +class ScreenRecordingSettingsFragment : CommonFragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = + FragmentScreenRecordingSettingsBinding.inflate(inflater, container, false).also { ui = it }.root + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val viewModel: ScreenRecordingSettingsViewModel by viewModels() + bindViewModel(viewModel) + + setupViews() + + observeUI() + } + + private fun setupViews() = with(ui) { + loadingSwitchView.setOnCheckedChangeListener { viewModel.toggleScreenRecordingEnable(it) } + } + + private fun observeUI() = with(viewModel) { + viewLifecycleOwner.launchAndRepeatOnLifecycle(Lifecycle.State.STARTED) { + launch { + switchState.collect { state -> + ui.loadingSwitchView.setState(state) + } + } + } + } +} + diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsViewModel.kt new file mode 100644 index 000000000..b25d8fd1a --- /dev/null +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/settings/screenRecording/ScreenRecordingSettingsViewModel.kt @@ -0,0 +1,40 @@ +package com.tari.android.wallet.ui.fragment.settings.screenRecording + +import com.tari.android.wallet.R +import com.tari.android.wallet.ui.common.CommonViewModel +import com.tari.android.wallet.ui.component.loadingSwitch.TariLoadingSwitchState +import com.tari.android.wallet.ui.dialog.confirm.ConfirmDialogArgs +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update + +class ScreenRecordingSettingsViewModel : CommonViewModel() { + + private val _switchState = MutableStateFlow(TariLoadingSwitchState(isChecked = tariSettingsSharedRepository.screenRecordingTurnedOn)) + val switchState = _switchState.asStateFlow() + + init { + component.inject(this) + } + + fun toggleScreenRecordingEnable(isChecked: Boolean) { + if (!isChecked) { + turnSwitcher(false) + } else { + _switchState.update { it.startLoading() } + modularDialog.value = ConfirmDialogArgs( + resourceManager.getString(R.string.screen_recording_button_confirmation_title), + resourceManager.getString(R.string.screen_recording_button_confirmation_description), + onConfirm = { turnSwitcher(true) }, + onCancel = { _switchState.update { it.stopLoading() } }, + onDismiss = { _switchState.update { it.stopLoading() } } + ).getModular(resourceManager) + } + } + + private fun turnSwitcher(isTurnedOn: Boolean) { + tariSettingsSharedRepository.screenRecordingTurnedOn = isTurnedOn + _switchState.update { TariLoadingSwitchState(isTurnedOn, false) } + dismissDialog.postValue(Unit) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragment.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragment.kt index b127f1a9a..7b93dc863 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragment.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragment.kt @@ -90,7 +90,6 @@ class HomeFragment : CommonFragment( viewModel.serviceConnection.reconnectToService() - subscribeVM(viewModel.stagedWalletSecurityManager) subscribeVM(deeplinkViewModel) checkPermission() diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragmentViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragmentViewModel.kt index 4e701df57..43f37a3f2 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragmentViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/HomeFragmentViewModel.kt @@ -1,6 +1,8 @@ package com.tari.android.wallet.ui.fragment.tx +import android.text.SpannableString +import android.text.Spanned import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData @@ -12,12 +14,16 @@ import com.tari.android.wallet.R.string.error_no_connection_title import com.tari.android.wallet.R.string.error_node_unreachable_description import com.tari.android.wallet.R.string.error_node_unreachable_title import com.tari.android.wallet.application.securityStage.StagedWalletSecurityManager +import com.tari.android.wallet.application.securityStage.StagedWalletSecurityManager.StagedSecurityEffect import com.tari.android.wallet.data.sharedPrefs.SharedPrefsRepository +import com.tari.android.wallet.data.sharedPrefs.securityStages.WalletSecurityStage +import com.tari.android.wallet.data.sharedPrefs.securityStages.modules.SecurityStageHeadModule import com.tari.android.wallet.data.sharedPrefs.sentry.SentryPrefRepository import com.tari.android.wallet.event.Event import com.tari.android.wallet.event.EventBus import com.tari.android.wallet.extension.addTo import com.tari.android.wallet.extension.getWithError +import com.tari.android.wallet.extension.safeCastTo import com.tari.android.wallet.model.BalanceInfo import com.tari.android.wallet.service.service.WalletServiceLauncher import com.tari.android.wallet.ui.common.CommonViewModel @@ -30,15 +36,19 @@ import com.tari.android.wallet.ui.dialog.modular.modules.body.BodyModule import com.tari.android.wallet.ui.dialog.modular.modules.button.ButtonModule import com.tari.android.wallet.ui.dialog.modular.modules.button.ButtonStyle import com.tari.android.wallet.ui.dialog.modular.modules.head.HeadModule +import com.tari.android.wallet.ui.dialog.modular.modules.space.SpaceModule import com.tari.android.wallet.ui.fragment.contact_book.data.ContactsRepository import com.tari.android.wallet.ui.fragment.home.navigation.Navigation import com.tari.android.wallet.ui.fragment.send.finalize.TxFailureReason +import com.tari.android.wallet.ui.fragment.settings.backup.backupOnboarding.item.BackupOnboardingArgs +import com.tari.android.wallet.ui.fragment.settings.backup.backupOnboarding.module.BackupOnboardingFlowItemModule import com.tari.android.wallet.ui.fragment.settings.backup.data.BackupSettingsRepository import com.tari.android.wallet.ui.fragment.tx.adapter.TransactionItem import com.tari.android.wallet.util.extractEmojis import io.reactivex.BackpressureStrategy import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import yat.android.ui.extension.HtmlHelper import javax.inject.Inject @@ -62,7 +72,8 @@ class HomeFragmentViewModel : CommonViewModel() { @Inject lateinit var sentryPrefRepository: SentryPrefRepository - val stagedWalletSecurityManager = StagedWalletSecurityManager() + @Inject + lateinit var stagedWalletSecurityManager: StagedWalletSecurityManager private val _balanceInfo = MutableLiveData() val balanceInfo: LiveData = _balanceInfo @@ -132,9 +143,19 @@ class HomeFragmentViewModel : CommonViewModel() { } private fun fetchBalanceInfoData() { - walletService.getWithError { error, service -> service.getBalanceInfo(error) }?.let { - EventBus.balanceUpdates.post(it) - _balanceInfo.postValue(it) + walletService.getWithError { error, service -> service.getBalanceInfo(error) }?.let { balanceInfo -> + _balanceInfo.postValue(balanceInfo) + + stagedWalletSecurityManager.handleBalanceChange(balanceInfo) + .safeCastTo() + ?.let { effect -> + when (effect.stage) { + WalletSecurityStage.Stage1A -> showStagePopUp1A() + WalletSecurityStage.Stage1B -> showStagePopUp1B() + WalletSecurityStage.Stage2 -> showStagePopUp2() + WalletSecurityStage.Stage3 -> showStagePopUp3() + } + } } } @@ -195,6 +216,117 @@ class HomeFragmentViewModel : CommonViewModel() { modularDialog.postValue(errorDialogArgs.getModular(resourceManager)) } + /** + * Show staged security popups + */ + + private fun showStagePopUp1A() { + showPopup( + stage = BackupOnboardingArgs.StageOne(resourceManager, this::openStage1), + titleEmoji = resourceManager.getString(R.string.staged_wallet_security_stages_1a_title), + title = resourceManager.getString(R.string.staged_wallet_security_stages_1a_subtitle), + body = null, + positiveButtonTitle = resourceManager.getString(R.string.staged_wallet_security_stages_1a_buttons_positive), + bodyHtml = HtmlHelper.getSpannedText(resourceManager.getString(R.string.staged_wallet_security_stages_1a_message)), + positiveAction = { openStage1() }, + ) + } + + private fun showStagePopUp1B() { + showPopup( + stage = BackupOnboardingArgs.StageTwo(resourceManager, this::openStage1B), + titleEmoji = resourceManager.getString(R.string.staged_wallet_security_stages_1b_title), + title = resourceManager.getString(R.string.staged_wallet_security_stages_1b_subtitle), + body = resourceManager.getString(R.string.staged_wallet_security_stages_1b_message), + positiveButtonTitle = resourceManager.getString(R.string.staged_wallet_security_stages_1b_buttons_positive), + positiveAction = { openStage1() }, + ) + } + + private fun showStagePopUp2() { + showPopup( + stage = BackupOnboardingArgs.StageThree(resourceManager, this::openStage2), + titleEmoji = resourceManager.getString(R.string.staged_wallet_security_stages_2_title), + title = resourceManager.getString(R.string.staged_wallet_security_stages_2_subtitle), + body = resourceManager.getString(R.string.staged_wallet_security_stages_2_message), + positiveButtonTitle = resourceManager.getString(R.string.staged_wallet_security_stages_2_buttons_positive), + positiveAction = { openStage2() }, + ) + } + + private fun showStagePopUp3() { + showPopup( + stage = BackupOnboardingArgs.StageFour(resourceManager, this::openStage3), + titleEmoji = resourceManager.getString(R.string.staged_wallet_security_stages_3_title), + title = resourceManager.getString(R.string.staged_wallet_security_stages_3_subtitle), + body = resourceManager.getString(R.string.staged_wallet_security_stages_3_message), + positiveButtonTitle = resourceManager.getString(R.string.staged_wallet_security_stages_3_buttons_positive), + positiveAction = { openStage3() }, + ) + } + + private fun openStage1() { + dismissDialog.postValue(Unit) + tariNavigator.let { + it.toAllSettings() + it.toBackupSettings(false) + it.toWalletBackupWithRecoveryPhrase() + } + } + + private fun openStage1B() { + dismissDialog.postValue(Unit) + tariNavigator.let { + it.toAllSettings() + it.toBackupSettings(true) + } + } + + private fun openStage2() { + dismissDialog.postValue(Unit) + tariNavigator.let { + it.toAllSettings() + it.toBackupSettings(false) + it.toChangePassword() + } + } + + private fun openStage3() { + dismissDialog.postValue(Unit) + //todo for future + } + + private fun showPopup( + stage: BackupOnboardingArgs, + titleEmoji: String, + title: String, + body: String?, + positiveButtonTitle: String, + bodyHtml: Spanned? = null, + positiveAction: () -> Unit = {}, + ) { + val args = ModularDialogArgs( + DialogArgs(), listOf( + SecurityStageHeadModule(titleEmoji, title) { showBackupInfo(stage) }, + BodyModule(body, bodyHtml?.let { SpannableString(it) }), + ButtonModule(positiveButtonTitle, ButtonStyle.Normal) { positiveAction.invoke() }, + ButtonModule(resourceManager.getString(R.string.staged_wallet_security_buttons_remind_me_later), ButtonStyle.Close) + ) + ) + modularDialog.postValue(args) + } + + private fun showBackupInfo(stage: BackupOnboardingArgs) { + modularDialog.postValue( + ModularDialogArgs( + DialogArgs(), listOf( + BackupOnboardingFlowItemModule(stage), + SpaceModule(20), + ) + ) + ) + } + companion object { val amountOfTransactions = 2 } diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/TransactionRepository.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/TransactionRepository.kt index b8f702d90..760d850df 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/TransactionRepository.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/tx/TransactionRepository.kt @@ -29,8 +29,8 @@ import com.tari.android.wallet.ui.common.recyclerView.CommonViewHolderItem import com.tari.android.wallet.ui.common.recyclerView.items.TitleViewHolderItem import com.tari.android.wallet.ui.fragment.contact_book.data.ContactsRepository import com.tari.android.wallet.ui.fragment.tx.adapter.TransactionItem -import com.tari.android.wallet.util.TariBuild -import com.tari.android.wallet.util.TariBuild.MOCKED +import com.tari.android.wallet.util.DebugConfig +import com.tari.android.wallet.util.MockDataStub import io.reactivex.BackpressureStrategy import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -173,7 +173,7 @@ class TransactionRepository @Inject constructor() : CommonViewModel() { }) } - if (MOCKED) { + if (DebugConfig.mockedDataEnabled) { val title = TitleViewHolderItem("Mocked Transactions", true) val messageGiphy = " https://giphy.com/embed/5885nYOgBHdCw" @@ -187,7 +187,7 @@ class TransactionRepository @Inject constructor() : CommonViewModel() { message = messageGiphy timestamp = BigInteger.valueOf(System.currentTimeMillis()) id = BigInteger.valueOf(1) - tariContact = TariContact(TariBuild.moched_zero_contact, "test1") + tariContact = TariContact(MockDataStub.WALLET_ADDRESS_ZERO, "test1") }, contactsRepository.ffiBridge.getContactForTx(CompletedTx()), 0, @@ -203,7 +203,7 @@ class TransactionRepository @Inject constructor() : CommonViewModel() { timestamp = BigInteger.valueOf(System.currentTimeMillis()) id = BigInteger.valueOf(1) message = messageGiphy - tariContact = TariContact(TariBuild.moched_zero_contact, "test2") + tariContact = TariContact(MockDataStub.WALLET_ADDRESS_ZERO, "test2") } val item2 = TransactionItem( tx2, @@ -221,7 +221,7 @@ class TransactionRepository @Inject constructor() : CommonViewModel() { fee = MicroTari(BigInteger.valueOf(1000)) timestamp = BigInteger.valueOf(System.currentTimeMillis()) id = BigInteger.valueOf(1) - tariContact = TariContact(TariBuild.mocked_wallet_address, "test3") + tariContact = TariContact(MockDataStub.WALLET_ADDRESS, "test3") } val item3 = TransactionItem( diff --git a/app/src/main/java/com/tari/android/wallet/ui/fragment/utxos/list/UtxosListViewModel.kt b/app/src/main/java/com/tari/android/wallet/ui/fragment/utxos/list/UtxosListViewModel.kt index 5b10da750..a1d04999f 100644 --- a/app/src/main/java/com/tari/android/wallet/ui/fragment/utxos/list/UtxosListViewModel.kt +++ b/app/src/main/java/com/tari/android/wallet/ui/fragment/utxos/list/UtxosListViewModel.kt @@ -28,7 +28,7 @@ import com.tari.android.wallet.ui.fragment.utxos.list.module.DetailItemModule import com.tari.android.wallet.ui.fragment.utxos.list.module.ListItemModule import com.tari.android.wallet.ui.fragment.utxos.list.module.UtxoAmountModule import com.tari.android.wallet.ui.fragment.utxos.list.module.UtxoSplitModule -import com.tari.android.wallet.util.TariBuild +import com.tari.android.wallet.util.DebugConfig import java.math.BigInteger import kotlin.random.Random @@ -165,7 +165,7 @@ class UtxosListViewModel : CommonViewModel() { wallet.getAllUtxos(error) }.itemsList.map { UtxosViewHolderItem(it) }.filter { it.isShowingStatus }.toMutableList() - if (TariBuild.MOCKED && allItems.isEmpty()) { + if (DebugConfig.mockedDataEnabled && allItems.isEmpty()) { for (i in 0 until 20) { allItems.add(0, UtxosViewHolderItem(TariUtxo().apply { value = MicroTari(BigInteger.valueOf(Random.nextLong(1, 100000) * 10000)) diff --git a/app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt b/app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt deleted file mode 100644 index fa82651b8..000000000 --- a/app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2020 The Tari Project - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.tari.android.wallet.util - -import com.tari.android.wallet.BuildConfig -import com.tari.android.wallet.model.TariWalletAddress - -object TariBuild { - - private val _mockedTurned = true - val MOCKED = _mockedTurned && BuildConfig.BUILD_TYPE == "debug" - - val mocked_emojiId = - "\uD83C\uDFB9\uD83C\uDFA4\uD83C\uDF20\uD83C\uDFAA\uD83D\uDC16\uD83C\uDF5A\uD83D\uDE08\uD83C\uDF73\uD83C\uDFED\uD83D\uDC2F\uD83D\uDC29\uD83D\uDC33\uD83D\uDC2D\uD83D\uDC35\uD83D\uDC11\uD83C\uDF4E\uD83D\uDE02\uD83C\uDFB3\uD83C\uDF34\uD83C\uDF6D\uD83D\uDC0D\uD83C\uDF1F\uD83D\uDCBC\uD83C\uDFB9\uD83D\uDC3A\uD83D\uDC79\uD83C\uDF77\uD83D\uDC3B\uD83D\uDEAB\uD83D\uDE92\uD83D\uDCB3\uD83C\uDFAE\uD83D\uDD2A" - val mocked_hex = "5A4A0A4F7427E33469858088838A721FE1560C316F09C55A8EA6388FFBF1C152DA" - - val mocked_zero_emojiId = (0..25).map { "\uD83C\uDF00" }.joinToString("") - val mocked_zero_hex = TariWalletAddress.zero66Hex - - val mocked_wallet_address -// get() = TariWalletAddress(mocked_hex, mocked_emojiId) - get() = TariWalletAddress( - "C05575BE00EF016A209B1F493D9027B0E330F3E25FE89BBE6FA66D966EE5B6356", - "\uD83C\uDF34\uD83C\uDF0D\uD83C\uDFB5\uD83C\uDFBA\uD83D\uDDFD\uD83C\uDF37\uD83D\uDE91\uD83C\uDF45\uD83D\uDC60\uD83C\uDF1F\uD83D\uDC8C\uD83D\uDE97\uD83D\uDC40\uD83D\uDD29\uD83C\uDF08\uD83D\uDC1D\uD83C\uDF37\uD83C\uDF70\uD83C\uDF38\uD83C\uDF81\uD83C\uDF55\uD83D\uDEBF\uD83D\uDC34\uD83D\uDCA6\uD83D\uDE0E\uD83D\uDEAA\uD83C\uDFE0\uD83D\uDD29\uD83C\uDFE0\uD83D\uDE82\uD83C\uDFBA\uD83C\uDFC6\uD83C\uDFB3") - - val moched_zero_contact - get() = TariWalletAddress(mocked_zero_hex, mocked_zero_emojiId) - - val isChat = false -} \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt.orig b/app/src/main/java/com/tari/android/wallet/util/DebugConfig.kt similarity index 51% rename from app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt.orig rename to app/src/main/java/com/tari/android/wallet/util/DebugConfig.kt index a873fd5c1..9e1655dd3 100644 --- a/app/src/main/java/com/tari/android/wallet/util/BuildUtil.kt.orig +++ b/app/src/main/java/com/tari/android/wallet/util/DebugConfig.kt @@ -34,31 +34,37 @@ package com.tari.android.wallet.util import com.tari.android.wallet.BuildConfig import com.tari.android.wallet.model.TariWalletAddress +import yat.android.lib.YatIntegration -object TariBuild { +/** + * Constants used for developing and debugging. + */ +object DebugConfig { + + private const val _mockedTurned = false + val mockedDataEnabled = _mockedTurned && isDebug() // TODO split this flag to multiple different types of mocked data - private val _mockedTurned = true - val MOCKED = _mockedTurned && BuildConfig.BUILD_TYPE == "debug" + val isChatEnabled = false - val mocked_emojiId = - "\uD83C\uDFB9\uD83C\uDFA4\uD83C\uDF20\uD83C\uDFAA\uD83D\uDC16\uD83C\uDF5A\uD83D\uDE08\uD83C\uDF73\uD83C\uDFED\uD83D\uDC2F\uD83D\uDC29\uD83D\uDC33\uD83D\uDC2D\uD83D\uDC35\uD83D\uDC11\uD83C\uDF4E\uD83D\uDE02\uD83C\uDFB3\uD83C\uDF34\uD83C\uDF6D\uD83D\uDC0D\uD83C\uDF1F\uD83D\uDCBC\uD83C\uDFB9\uD83D\uDC3A\uD83D\uDC79\uD83C\uDF77\uD83D\uDC3B\uD83D\uDEAB\uD83D\uDE92\uD83D\uDCB3\uD83C\uDFAE\uD83D\uDD2A" -<<<<<<< HEAD - val mocked_hex = "5A4A0A4F7427E33469858088838A721FE1560C316F09C55A8EA6388FFBF1C152DA" + private const val _useYatSandbox = false + val yatEnvironment = if (_useYatSandbox && isDebug()) YatEnvironment.SANDBOX else YatEnvironment.PRODUCTION - val mocked_zero_emojiId = (0..25).map { "\uD83C\uDF00" }.joinToString("") - val mocked_zero_hex = TariWalletAddress.zero66Hex + private fun isDebug() = BuildConfig.BUILD_TYPE == "debug" +} - val mocked_wallet_address - get() = TariWalletAddress(mocked_hex, mocked_emojiId) +object MockDataStub { + private const val EMOJI_ID = + "\uD83C\uDF34\uD83C\uDF0D\uD83C\uDFB5\uD83C\uDFBA\uD83D\uDDFD\uD83C\uDF37\uD83D\uDE91\uD83C\uDF45\uD83D\uDC60\uD83C\uDF1F\uD83D\uDC8C\uD83D\uDE97\uD83D\uDC40\uD83D\uDD29\uD83C\uDF08\uD83D\uDC1D\uD83C\uDF37\uD83C\uDF70\uD83C\uDF38\uD83C\uDF81\uD83C\uDF55\uD83D\uDEBF\uD83D\uDC34\uD83D\uDCA6\uD83D\uDE0E\uD83D\uDEAA\uD83C\uDFE0\uD83D\uDD29\uD83C\uDFE0\uD83D\uDE82\uD83C\uDFBA\uD83C\uDFC6\uD83C\uDFB3" + private const val HEX = "C05575BE00EF016A209B1F493D9027B0E330F3E25FE89BBE6FA66D966EE5B6356" - val moched_zero_contact - get() = TariWalletAddress(mocked_zero_hex, mocked_zero_emojiId) + private val EMOJI_ID_ZERO = (0..25).map { "\uD83C\uDF00" }.joinToString("") + private const val HEX_ZERO = TariWalletAddress.zero66Hex - val isChat = false -======= - val moched_hex = "5A4A0A4F7427E33469858088838A721FE1560C316F09C55A8EA6388FFBF1C152DA" + val WALLET_ADDRESS = TariWalletAddress(hexString = HEX, emojiId = EMOJI_ID) + val WALLET_ADDRESS_ZERO = TariWalletAddress(HEX_ZERO, EMOJI_ID_ZERO) +} - val mocked_wallet_address - get() = TariWalletAddress(moched_hex, mocked_emojiId) ->>>>>>> cb06ea1bc7c0b86add6505cb8e8235be91f6dd50 +object YatEnvironment { + val SANDBOX = YatIntegration.Environment("https://a.yat.fyi/", "https://yat.fyi/") + val PRODUCTION = YatIntegration.Environment("https://a.y.at/", "https://y.at/") } \ No newline at end of file diff --git a/app/src/main/java/com/tari/android/wallet/yat/YatAdapter.kt b/app/src/main/java/com/tari/android/wallet/yat/YatAdapter.kt index ebafbc166..3b258badd 100644 --- a/app/src/main/java/com/tari/android/wallet/yat/YatAdapter.kt +++ b/app/src/main/java/com/tari/android/wallet/yat/YatAdapter.kt @@ -13,6 +13,7 @@ import com.tari.android.wallet.data.sharedPrefs.network.NetworkRepository import com.tari.android.wallet.ui.fragment.send.common.TransactionData import com.tari.android.wallet.ui.fragment.send.finalize.FinalizeSendTxViewModel import com.tari.android.wallet.ui.fragment.send.finalize.YatFinalizeSendTxActivity +import com.tari.android.wallet.util.DebugConfig import yat.android.data.YatRecord import yat.android.data.YatRecordType import yat.android.lib.YatConfiguration @@ -32,8 +33,18 @@ class YatAdapter( get() = Logger.t(YatAdapter::class.simpleName) fun initYat(application: Application) { - val config = YatConfiguration(BuildConfig.YAT_ORGANIZATION_RETURN_URL, BuildConfig.YAT_ORGANIZATION_NAME, BuildConfig.YAT_ORGANIZATION_KEY) - YatIntegration.setup(application, config, YatIntegration.ColorMode.LIGHT, this, environment = YatIntegration.Environment.Production) + val config = YatConfiguration( + appReturnLink = BuildConfig.YAT_ORGANIZATION_RETURN_URL, + organizationName = BuildConfig.YAT_ORGANIZATION_NAME, + organizationKey = BuildConfig.YAT_ORGANIZATION_KEY, + ) + YatIntegration.setup( + context = application, + config = config, + colorMode = YatIntegration.ColorMode.LIGHT, + delegate = this, + environment = DebugConfig.yatEnvironment, + ) } fun searchTariYats(query: String): PaymentAddressResponse? = diff --git a/app/src/main/res/drawable/vector_all_settings_screen_recording_icon.xml b/app/src/main/res/drawable/vector_all_settings_screen_recording_icon.xml new file mode 100644 index 000000000..ef4dbf0e5 --- /dev/null +++ b/app/src/main/res/drawable/vector_all_settings_screen_recording_icon.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/layout/fragment_screen_recording_settings.xml b/app/src/main/res/layout/fragment_screen_recording_settings.xml new file mode 100644 index 000000000..74d3237ea --- /dev/null +++ b/app/src/main/res/layout/fragment_screen_recording_settings.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_settings_backup_option.xml b/app/src/main/res/layout/item_settings_backup_option.xml index 528a2be1b..08b6b1dd6 100644 --- a/app/src/main/res/layout/item_settings_backup_option.xml +++ b/app/src/main/res/layout/item_settings_backup_option.xml @@ -14,6 +14,7 @@ android:id="@+id/back_up_wallet_cta_view" android:layout_width="match_parent" android:layout_height="@dimen/menu_item_height" + android:foreground="?attr/selectableItemBackground" android:gravity="center_vertical" android:orientation="horizontal" android:paddingHorizontal="@dimen/common_horizontal_margin"> diff --git a/app/src/main/res/layout/item_button.xml b/app/src/main/res/layout/item_settings_row.xml similarity index 52% rename from app/src/main/res/layout/item_button.xml rename to app/src/main/res/layout/item_settings_row.xml index b64f9c5ca..34cda9b3d 100644 --- a/app/src/main/res/layout/item_button.xml +++ b/app/src/main/res/layout/item_settings_row.xml @@ -1,5 +1,5 @@ - \ No newline at end of file diff --git a/app/src/main/res/layout/view_button.xml b/app/src/main/res/layout/view_settings_row.xml similarity index 79% rename from app/src/main/res/layout/view_button.xml rename to app/src/main/res/layout/view_settings_row.xml index d23588576..d3bf5a305 100644 --- a/app/src/main/res/layout/view_button.xml +++ b/app/src/main/res/layout/view_settings_row.xml @@ -7,12 +7,14 @@ android:layout_height="@dimen/menu_item_height" android:clickable="true" android:focusable="true" + android:foreground="?attr/selectableItemBackground" android:orientation="horizontal" android:paddingHorizontal="@dimen/common_horizontal_margin"> + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3f3c51f94..58b3984a4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -433,6 +433,7 @@ Disclaimer Block Explorer Background Service + Screen recording Bluetooth Settings Bridge Configuration Connect Yats @@ -453,6 +454,13 @@ Background service will be turned off You will not get any notifications and updates. Are you sure you want to proceed? + + Screen recording + Screen recording and taking screenshots can capture your wallet data and transactions. To keep your wallet data private, you can disable this setting.\n\nNote: Screen recording and screenshots will always be disabled for the Seed Phrase screen. + Allow screen recording + Screen recording will be enabled + You will be able to record your screen. Are you sure you want to proceed? + Bluetooth Settings Other users can share their contacts using Bluetooth Low Energy (BLE) by moving their devices near your device. Your device will be visible to nearby Bluetooth devices when it\'s turned on.\n \n Choose an option below. BLE should be: diff --git a/build.gradle b/build.gradle index db5fff7ae..6b519af00 100644 --- a/build.gradle +++ b/build.gradle @@ -6,12 +6,12 @@ buildscript { ext.lifecycle_version = '2.6.2' // build & version - ext.buildNumber = 285 - ext.versionNumber = "0.25.0" + ext.buildNumber = 288 + ext.versionNumber = "0.25.2" // JNI libs ext.libwalletHostURL = "https://github.com/tari-project/tari/releases/download/" - ext.libwalletVersion = "v1.0.0-rc.3" + ext.libwalletVersion = "v1.0.0-rc.5" ext.libwalletx64A = "libminotari_wallet_ffi.android_x86_64.a" ext.libwalletArmA = "libminotari_wallet_ffi.android_aarch64.a" ext.libwalletHeader = "libminotari_wallet_ffi.h" @@ -32,17 +32,6 @@ plugins { id "de.undercouch.download" version "4.1.0" } -allprojects { - repositories { - // for yat - google() - mavenCentral() - maven { url "https://jitpack.io" } - maven { url "https://giphy.bintray.com/giphy-sdk" } - maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" } - } -} - tasks.register('clean', Delete) { delete rootProject.buildDir } diff --git a/settings.gradle b/settings.gradle index dce872de3..a6d705726 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,13 @@ include ':app', ':yatlib' rootProject.name='Tari Wallet' + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url "https://giphy.bintray.com/giphy-sdk" } + maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" } + maven { url "https://jitpack.io" } + } +} diff --git a/yatlib/build.gradle b/yatlib/build.gradle index ba2553622..0003b7dbc 100644 --- a/yatlib/build.gradle +++ b/yatlib/build.gradle @@ -1,2 +1,2 @@ configurations.maybeCreate("default") -artifacts.add("default", file('yat-lib-release.aar')) \ No newline at end of file +artifacts.add("default", file('yat-lib-development-snapshot.aar')) \ No newline at end of file diff --git a/yatlib/yat-lib-development-snapshot.aar b/yatlib/yat-lib-development-snapshot.aar new file mode 100644 index 000000000..91390dab4 Binary files /dev/null and b/yatlib/yat-lib-development-snapshot.aar differ diff --git a/yatlib/yat-lib-release.aar b/yatlib/yat-lib-release.aar deleted file mode 100644 index c5766f6c2..000000000 Binary files a/yatlib/yat-lib-release.aar and /dev/null differ