mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
Pop the "Create backup now" sheet after different instances of subscribing to backups.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.thoughtcrime.securesms.backup.v2.ui
|
||||
|
||||
import android.content.DialogInterface
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -24,26 +25,38 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import org.signal.core.ui.BottomSheets
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.core.ui.Icons
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
|
||||
|
||||
/**
|
||||
* Bottom sheet allowing the user to immediately start a backup or delay.
|
||||
*
|
||||
* If the result key is true, then the user has enqueued a backup and should be directed to the
|
||||
* remote backup settings screen.
|
||||
*/
|
||||
class CreateBackupBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
companion object {
|
||||
const val REQUEST_KEY = "CreateBackupBottomSheet"
|
||||
}
|
||||
|
||||
private var isResultSet = false
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
CreateBackupBottomSheetContent(
|
||||
onBackupNowClick = {
|
||||
BackupMessagesJob.enqueue()
|
||||
startActivity(AppSettingsActivity.remoteBackups(requireContext()))
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to Result.BACKUP_STARTED))
|
||||
isResultSet = true
|
||||
dismissAllowingStateLoss()
|
||||
},
|
||||
onBackupLaterClick = {
|
||||
@@ -51,6 +64,19 @@ class CreateBackupBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
enum class Result {
|
||||
BACKUP_STARTED,
|
||||
BACKUP_DELAYED
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface) {
|
||||
if (!isResultSet) {
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to Result.BACKUP_DELAYED))
|
||||
}
|
||||
|
||||
super.onDismiss(dialog)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -187,6 +187,12 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
if (state.screen == MessageBackupsScreen.PROCESS_FREE) {
|
||||
checkoutDelegate.setActivityResult(InAppPaymentProcessorAction.UPDATE_SUBSCRIPTION, InAppPaymentType.RECURRING_BACKUP)
|
||||
viewModel.goToNextScreen()
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
val routeScreen = MessageBackupsScreen.valueOf(route)
|
||||
if (routeScreen.isAfter(state.screen)) {
|
||||
navController.popBackStack()
|
||||
|
||||
@@ -76,6 +76,7 @@ class MessageBackupsFlowViewModel : ViewModel() {
|
||||
MessageBackupsScreen.CANCELLATION_DIALOG -> it.copy(screen = MessageBackupsScreen.PROCESS_CANCELLATION)
|
||||
MessageBackupsScreen.PROCESS_PAYMENT -> it.copy(screen = MessageBackupsScreen.COMPLETED)
|
||||
MessageBackupsScreen.PROCESS_CANCELLATION -> it.copy(screen = MessageBackupsScreen.COMPLETED)
|
||||
MessageBackupsScreen.PROCESS_FREE -> it.copy(screen = MessageBackupsScreen.COMPLETED)
|
||||
MessageBackupsScreen.COMPLETED -> error("Unsupported state transition from terminal state COMPLETED")
|
||||
}
|
||||
}
|
||||
@@ -95,6 +96,7 @@ class MessageBackupsFlowViewModel : ViewModel() {
|
||||
MessageBackupsScreen.CREATING_IN_APP_PAYMENT -> MessageBackupsScreen.TYPE_SELECTION
|
||||
MessageBackupsScreen.PROCESS_PAYMENT -> MessageBackupsScreen.TYPE_SELECTION
|
||||
MessageBackupsScreen.PROCESS_CANCELLATION -> MessageBackupsScreen.TYPE_SELECTION
|
||||
MessageBackupsScreen.PROCESS_FREE -> MessageBackupsScreen.TYPE_SELECTION
|
||||
MessageBackupsScreen.CANCELLATION_DIALOG -> MessageBackupsScreen.TYPE_SELECTION
|
||||
MessageBackupsScreen.COMPLETED -> error("Unsupported state transition from terminal state COMPLETED")
|
||||
}
|
||||
@@ -170,8 +172,7 @@ class MessageBackupsFlowViewModel : ViewModel() {
|
||||
SignalStore.backup.areBackupsEnabled = true
|
||||
SignalStore.backup.backupTier = MessageBackupTier.FREE
|
||||
|
||||
// TODO [message-backups] -- Trigger backup now?
|
||||
state.copy(screen = MessageBackupsScreen.COMPLETED)
|
||||
state.copy(screen = MessageBackupsScreen.PROCESS_FREE)
|
||||
}
|
||||
}
|
||||
MessageBackupTier.PAID -> state.copy(screen = MessageBackupsScreen.CHECKOUT_SHEET)
|
||||
|
||||
@@ -15,6 +15,7 @@ enum class MessageBackupsScreen {
|
||||
CREATING_IN_APP_PAYMENT,
|
||||
PROCESS_PAYMENT,
|
||||
PROCESS_CANCELLATION,
|
||||
PROCESS_FREE,
|
||||
COMPLETED;
|
||||
|
||||
fun isAfter(other: MessageBackupsScreen): Boolean = ordinal > other.ordinal
|
||||
|
||||
@@ -55,8 +55,8 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
|
||||
StartLocation.PROXY -> AppSettingsFragmentDirections.actionDirectToEditProxyFragment()
|
||||
StartLocation.NOTIFICATIONS -> AppSettingsFragmentDirections.actionDirectToNotificationsSettingsFragment()
|
||||
StartLocation.CHANGE_NUMBER -> AppSettingsFragmentDirections.actionDirectToChangeNumberFragment()
|
||||
StartLocation.SUBSCRIPTIONS -> AppSettingsFragmentDirections.actionDirectToCheckout(InAppPaymentType.RECURRING_DONATION)
|
||||
StartLocation.BOOST -> AppSettingsFragmentDirections.actionDirectToCheckout(InAppPaymentType.ONE_TIME_DONATION)
|
||||
StartLocation.SUBSCRIPTIONS -> AppSettingsFragmentDirections.actionDirectToManageDonations().setDirectToCheckoutType(InAppPaymentType.RECURRING_DONATION)
|
||||
StartLocation.BOOST -> AppSettingsFragmentDirections.actionDirectToManageDonations().setDirectToCheckoutType(InAppPaymentType.ONE_TIME_DONATION)
|
||||
StartLocation.MANAGE_SUBSCRIPTIONS -> AppSettingsFragmentDirections.actionDirectToManageDonations()
|
||||
StartLocation.NOTIFICATION_PROFILES -> AppSettingsFragmentDirections.actionDirectToNotificationProfiles()
|
||||
StartLocation.CREATE_NOTIFICATION_PROFILE -> AppSettingsFragmentDirections.actionDirectToCreateNotificationProfiles()
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.chats
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentCheckoutLauncher.createBackupsCheckoutLauncher
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
@@ -16,6 +18,7 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__chats) {
|
||||
|
||||
private lateinit var viewModel: ChatsSettingsViewModel
|
||||
private lateinit var checkoutLauncher: ActivityResultLauncher<InAppPaymentType>
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
@@ -24,6 +27,10 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch
|
||||
|
||||
@Suppress("ReplaceGetOrSet")
|
||||
override fun bindAdapter(adapter: MappingAdapter) {
|
||||
checkoutLauncher = createBackupsCheckoutLauncher {
|
||||
findNavController().safeNavigate(ChatsSettingsFragmentDirections.actionChatsSettingsFragmentToRemoteBackupsSettingsFragment().setBackupLaterSelected(it))
|
||||
}
|
||||
|
||||
viewModel = ViewModelProvider(this).get(ChatsSettingsViewModel::class.java)
|
||||
|
||||
viewModel.state.observe(viewLifecycleOwner) {
|
||||
@@ -92,7 +99,7 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch
|
||||
if (state.canAccessRemoteBackupsSettings) {
|
||||
Navigation.findNavController(requireView()).safeNavigate(R.id.action_chatsSettingsFragment_to_remoteBackupsSettingsFragment)
|
||||
} else {
|
||||
startActivity(CheckoutFlowActivity.createIntent(requireContext(), InAppPaymentType.RECURRING_BACKUP))
|
||||
checkoutLauncher.launch(InAppPaymentType.RECURRING_BACKUP)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.components.settings.app.chats.backups
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -44,7 +45,9 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@@ -65,7 +68,8 @@ import org.thoughtcrime.securesms.backup.v2.BackupFrequency
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupV2Event
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.chats.backups.type.BackupsTypeSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentCheckoutLauncher.createBackupsCheckoutLauncher
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.conversation.v2.registerForLifecycle
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
@@ -86,6 +90,10 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
||||
RemoteBackupsSettingsViewModel()
|
||||
}
|
||||
|
||||
private val args: RemoteBackupsSettingsFragmentArgs by navArgs()
|
||||
|
||||
private lateinit var checkoutLauncher: ActivityResultLauncher<InAppPaymentType>
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state.collectAsState()
|
||||
@@ -111,7 +119,7 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
||||
}
|
||||
|
||||
override fun onEnableBackupsClick() {
|
||||
startActivity(CheckoutFlowActivity.createIntent(requireContext(), InAppPaymentType.RECURRING_BACKUP))
|
||||
checkoutLauncher.launch(InAppPaymentType.RECURRING_BACKUP)
|
||||
}
|
||||
|
||||
override fun onBackUpUsingCellularClick(canUseCellular: Boolean) {
|
||||
@@ -163,6 +171,22 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
EventBus.getDefault().registerForLifecycle(subscriber = this, lifecycleOwner = viewLifecycleOwner)
|
||||
checkoutLauncher = createBackupsCheckoutLauncher { backUpLater ->
|
||||
if (backUpLater) {
|
||||
viewModel.requestSnackbar(RemoteBackupsSettingsState.Snackbar.BACKUP_WILL_BE_CREATED_OVERNIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
setFragmentResultListener(BackupsTypeSettingsFragment.REQUEST_KEY) { _, bundle ->
|
||||
val backUpLater = bundle.getBoolean(BackupsTypeSettingsFragment.REQUEST_KEY)
|
||||
if (backUpLater) {
|
||||
viewModel.requestSnackbar(RemoteBackupsSettingsState.Snackbar.BACKUP_WILL_BE_CREATED_OVERNIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState == null && args.backupLaterSelected) {
|
||||
viewModel.requestSnackbar(RemoteBackupsSettingsState.Snackbar.BACKUP_WILL_BE_CREATED_OVERNIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -346,6 +370,7 @@ private fun RemoteBackupsSettingsContent(
|
||||
RemoteBackupsSettingsState.Snackbar.BACKUP_TYPE_CHANGED_AND_SUBSCRIPTION_CANCELLED -> R.string.RemoteBackupsSettingsFragment__backup_type_changed_and_subcription_deleted
|
||||
RemoteBackupsSettingsState.Snackbar.SUBSCRIPTION_CANCELLED -> R.string.RemoteBackupsSettingsFragment__subscription_cancelled
|
||||
RemoteBackupsSettingsState.Snackbar.DOWNLOAD_COMPLETE -> R.string.RemoteBackupsSettingsFragment__download_complete
|
||||
RemoteBackupsSettingsState.Snackbar.BACKUP_WILL_BE_CREATED_OVERNIGHT -> R.string.RemoteBackupsSettingsFragment__backup_will_be_created_overnight
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,9 +384,9 @@ private fun RemoteBackupsSettingsContent(
|
||||
|
||||
else -> {
|
||||
snackbarHostState.showSnackbar(snackbarText)
|
||||
contentCallbacks.onSnackbarDismissed()
|
||||
}
|
||||
}
|
||||
contentCallbacks.onSnackbarDismissed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ data class RemoteBackupsSettingsState(
|
||||
BACKUP_DELETED_AND_TURNED_OFF,
|
||||
BACKUP_TYPE_CHANGED_AND_SUBSCRIPTION_CANCELLED,
|
||||
SUBSCRIPTION_CANCELLED,
|
||||
DOWNLOAD_COMPLETE
|
||||
DOWNLOAD_COMPLETE,
|
||||
BACKUP_WILL_BE_CREATED_OVERNIGHT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.chats.backups.type
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
@@ -18,6 +21,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.signal.core.ui.Previews
|
||||
@@ -30,7 +35,7 @@ import org.signal.donations.PaymentSourceType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentCheckoutLauncher.createBackupsCheckoutLauncher
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
@@ -45,10 +50,24 @@ import java.util.Locale
|
||||
*/
|
||||
class BackupsTypeSettingsFragment : ComposeFragment() {
|
||||
|
||||
companion object {
|
||||
const val REQUEST_KEY = "BackupsTypeSettingsFragment__result"
|
||||
}
|
||||
|
||||
private val viewModel: BackupsTypeSettingsViewModel by viewModel {
|
||||
BackupsTypeSettingsViewModel()
|
||||
}
|
||||
|
||||
private lateinit var checkoutLauncher: ActivityResultLauncher<InAppPaymentType>
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
checkoutLauncher = createBackupsCheckoutLauncher { backUpLater ->
|
||||
findNavController().popBackStack()
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to backUpLater))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val contentCallbacks = remember {
|
||||
@@ -73,7 +92,7 @@ class BackupsTypeSettingsFragment : ComposeFragment() {
|
||||
}
|
||||
|
||||
override fun onChangeOrCancelSubscriptionClick() {
|
||||
startActivity(CheckoutFlowActivity.createIntent(requireContext(), InAppPaymentType.RECURRING_BACKUP))
|
||||
checkoutLauncher.launch(InAppPaymentType.RECURRING_BACKUP)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.storage
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
@@ -35,7 +38,7 @@ import org.thoughtcrime.securesms.backup.v2.ui.BackupsIconColors
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsTypeBlock
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.subscription.testBackupTypes
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentCheckoutLauncher.createBackupsCheckoutLauncher
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
|
||||
/**
|
||||
@@ -47,13 +50,20 @@ class UpgradeToEnableOptimizedStorageSheet : ComposeBottomSheetDialogFragment()
|
||||
|
||||
private val viewModel: UpgradeToEnableOptimizedStorageViewModel by viewModels()
|
||||
|
||||
private lateinit var checkoutLauncher: ActivityResultLauncher<InAppPaymentType>
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
checkoutLauncher = createBackupsCheckoutLauncher()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
val type by viewModel.messageBackupsType
|
||||
UpgradeToEnableOptimizedStorageSheetContent(
|
||||
messageBackupsType = type,
|
||||
onUpgradeNowClick = {
|
||||
startActivity(CheckoutFlowActivity.createIntent(requireContext(), InAppPaymentType.RECURRING_BACKUP))
|
||||
checkoutLauncher.launch(InAppPaymentType.RECURRING_BACKUP)
|
||||
dismissAllowingStateLoss()
|
||||
},
|
||||
onCancelClick = {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.backup.v2.ui.CreateBackupBottomSheet
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.InAppPaymentProcessorAction
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
|
||||
object InAppPaymentCheckoutLauncher {
|
||||
|
||||
fun Fragment.createBackupsCheckoutLauncher(
|
||||
onCreateBackupBottomSheetResultListener: OnCreateBackupBottomSheetResultListener = {} as OnCreateBackupBottomSheetResultListener
|
||||
): ActivityResultLauncher<InAppPaymentType> {
|
||||
childFragmentManager.setFragmentResultListener(CreateBackupBottomSheet.REQUEST_KEY, viewLifecycleOwner) { requestKey, bundle ->
|
||||
if (requestKey == CreateBackupBottomSheet.REQUEST_KEY) {
|
||||
val result = bundle.getSerializableCompat(CreateBackupBottomSheet.REQUEST_KEY, CreateBackupBottomSheet.Result::class.java)
|
||||
onCreateBackupBottomSheetResultListener.onCreateBackupBottomSheetResult(result != CreateBackupBottomSheet.Result.BACKUP_STARTED)
|
||||
}
|
||||
}
|
||||
|
||||
return registerForActivityResult(CheckoutFlowActivity.Contract()) { result ->
|
||||
if (result?.action == InAppPaymentProcessorAction.PROCESS_NEW_IN_APP_PAYMENT || result?.action == InAppPaymentProcessorAction.UPDATE_SUBSCRIPTION) {
|
||||
CreateBackupBottomSheet().show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun interface OnCreateBackupBottomSheetResultListener {
|
||||
fun onCreateBackupBottomSheetResult(backUpLater: Boolean)
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ object RecurringInAppPaymentRepository {
|
||||
it.state == InAppPaymentTable.State.END
|
||||
}.take(1).map {
|
||||
if (it.data.error != null) {
|
||||
Log.d(TAG, "Failure during redemption chain.", true)
|
||||
Log.d(TAG, "Failure during redemption chain: ${it.data.error}", true)
|
||||
throw DonationError.genericBadgeRedemptionFailure(errorSource)
|
||||
}
|
||||
it
|
||||
|
||||
@@ -7,10 +7,14 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Parcelable
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.navArgs
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.signal.core.util.getParcelableExtraCompat
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.components.FragmentWrapperActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentComponent
|
||||
@@ -22,20 +26,23 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.StripeRep
|
||||
class CheckoutFlowActivity : FragmentWrapperActivity(), InAppPaymentComponent {
|
||||
|
||||
companion object {
|
||||
private const val ARG_IN_APP_PAYMENT_TYPE = "in_app_payment_type"
|
||||
const val RESULT_DATA = "result_data"
|
||||
|
||||
fun createIntent(context: Context, inAppPaymentType: InAppPaymentType): Intent {
|
||||
return Intent(context, CheckoutFlowActivity::class.java).putExtras(
|
||||
CheckoutFlowActivityArgs.Builder(inAppPaymentType).build().toBundle()
|
||||
)
|
||||
return Contract().createIntent(context, inAppPaymentType)
|
||||
}
|
||||
}
|
||||
|
||||
override val stripeRepository: StripeRepository by lazy { StripeRepository(this) }
|
||||
override val googlePayResultPublisher: Subject<InAppPaymentComponent.GooglePayResult> = PublishSubject.create()
|
||||
|
||||
private val args by navArgs<CheckoutFlowActivityArgs>()
|
||||
private val inAppPaymentType: InAppPaymentType by lazy {
|
||||
intent.extras!!.getSerializableCompat(ARG_IN_APP_PAYMENT_TYPE, InAppPaymentType::class.java)!!
|
||||
}
|
||||
|
||||
override fun getFragment(): Fragment {
|
||||
return CheckoutNavHostFragment.create(args.inAppPaymentType)
|
||||
return CheckoutNavHostFragment.create(inAppPaymentType)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@@ -43,4 +50,21 @@ class CheckoutFlowActivity : FragmentWrapperActivity(), InAppPaymentComponent {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
googlePayResultPublisher.onNext(InAppPaymentComponent.GooglePayResult(requestCode, resultCode, data))
|
||||
}
|
||||
|
||||
class Contract : ActivityResultContract<InAppPaymentType, Result?>() {
|
||||
|
||||
override fun createIntent(context: Context, input: InAppPaymentType): Intent {
|
||||
return Intent(context, CheckoutFlowActivity::class.java).putExtra(ARG_IN_APP_PAYMENT_TYPE, input)
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Result? {
|
||||
return intent?.getParcelableExtraCompat(RESULT_DATA, Result::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Result(
|
||||
val action: InAppPaymentProcessorAction,
|
||||
val inAppPaymentType: InAppPaymentType
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.setFragmentResultListener
|
||||
import androidx.fragment.app.viewModels
|
||||
@@ -114,6 +115,10 @@ class InAppPaymentCheckoutDelegate(
|
||||
}
|
||||
}
|
||||
|
||||
fun setActivityResult(action: InAppPaymentProcessorAction, inAppPaymentType: InAppPaymentType) {
|
||||
fragment.requireActivity().setResult(Activity.RESULT_OK, Intent().putExtra(CheckoutFlowActivity.RESULT_DATA, CheckoutFlowActivity.Result(action, inAppPaymentType)))
|
||||
}
|
||||
|
||||
private fun handleDonationProcessorActionResult(result: InAppPaymentProcessorActionResult) {
|
||||
when (result.status) {
|
||||
InAppPaymentProcessorActionResult.Status.SUCCESS -> handleSuccessfulDonationProcessorActionResult(result)
|
||||
@@ -124,10 +129,11 @@ class InAppPaymentCheckoutDelegate(
|
||||
}
|
||||
|
||||
private fun handleSuccessfulDonationProcessorActionResult(result: InAppPaymentProcessorActionResult) {
|
||||
setActivityResult(result.action, result.inAppPaymentType)
|
||||
|
||||
if (result.action == InAppPaymentProcessorAction.CANCEL_SUBSCRIPTION) {
|
||||
callback.onSubscriptionCancelled(result.inAppPaymentType)
|
||||
} else {
|
||||
fragment.requireActivity().setResult(Activity.RESULT_OK)
|
||||
callback.onPaymentComplete(result.inAppPayment!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.manage
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.signal.core.util.dp
|
||||
import org.signal.core.util.money.FiatMoney
|
||||
@@ -21,6 +23,7 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.DonationSerializationHelper.toFiatMoney
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.completed.InAppPaymentsBottomSheetDelegate
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.models.NetworkFailure
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.components.settings.models.IndeterminateLoadingCircle
|
||||
@@ -54,6 +57,9 @@ class ManageDonationsFragment :
|
||||
const val DONATE_TROUBLESHOOTING_URL = "https://support.signal.org/hc/articles/360031949872#fix"
|
||||
}
|
||||
|
||||
private val args: ManageDonationsFragmentArgs by navArgs()
|
||||
private lateinit var launcher: ActivityResultLauncher<InAppPaymentType>
|
||||
|
||||
private val supportTechSummary: CharSequence by lazy {
|
||||
SpannableStringBuilder(SpanUtil.color(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurfaceVariant), requireContext().getString(R.string.DonateToSignalFragment__private_messaging)))
|
||||
.append(" ")
|
||||
@@ -69,6 +75,13 @@ class ManageDonationsFragment :
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
viewLifecycleOwner.lifecycle.addObserver(InAppPaymentsBottomSheetDelegate(childFragmentManager, viewLifecycleOwner))
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val contract = CheckoutFlowActivity.Contract()
|
||||
launcher = registerForActivityResult(contract) { }
|
||||
|
||||
if (savedInstanceState == null && args.directToCheckoutType != InAppPaymentType.UNKNOWN) {
|
||||
launcher.launch(args.directToCheckoutType)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -159,7 +172,7 @@ class ManageDonationsFragment :
|
||||
primaryWrappedButton(
|
||||
text = DSLSettingsText.from(R.string.ManageDonationsFragment__donate_to_signal),
|
||||
onClick = {
|
||||
findNavController().safeNavigate(ManageDonationsFragmentDirections.actionManageDonationsFragmentToDonateToSignalFragment(InAppPaymentType.ONE_TIME_DONATION))
|
||||
launcher.launch(InAppPaymentType.ONE_TIME_DONATION)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -269,7 +282,7 @@ class ManageDonationsFragment :
|
||||
subscriberRequiresCancel = state.subscriberRequiresCancel,
|
||||
onRowClick = {
|
||||
if (it != ManageDonationsState.RedemptionState.IN_PROGRESS) {
|
||||
findNavController().safeNavigate(ManageDonationsFragmentDirections.actionManageDonationsFragmentToDonateToSignalFragment(InAppPaymentType.RECURRING_DONATION))
|
||||
launcher.launch(InAppPaymentType.RECURRING_DONATION)
|
||||
}
|
||||
},
|
||||
onPendingClick = {
|
||||
@@ -337,7 +350,7 @@ class ManageDonationsFragment :
|
||||
title = DSLSettingsText.from(R.string.ManageDonationsFragment__donate_for_a_friend),
|
||||
icon = DSLSettingsIcon.from(R.drawable.symbol_gift_24),
|
||||
onClick = {
|
||||
findNavController().safeNavigate(ManageDonationsFragmentDirections.actionManageDonationsFragmentToDonateToSignalFragment(InAppPaymentType.ONE_TIME_GIFT))
|
||||
launcher.launch(InAppPaymentType.ONE_TIME_GIFT)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -437,6 +450,6 @@ class ManageDonationsFragment :
|
||||
}
|
||||
|
||||
override fun onMakeAMonthlyDonation() {
|
||||
findNavController().safeNavigate(ManageDonationsFragmentDirections.actionManageDonationsFragmentToDonateToSignalFragment(InAppPaymentType.RECURRING_DONATION))
|
||||
launcher.launch(InAppPaymentType.ONE_TIME_DONATION)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +382,10 @@ class ConversationFragment :
|
||||
MessageRequestRepository(requireContext())
|
||||
}
|
||||
|
||||
private val checkoutLauncher by lazy {
|
||||
registerForActivityResult(CheckoutFlowActivity.Contract()) {}
|
||||
}
|
||||
|
||||
private val disposables = LifecycleDisposable()
|
||||
private val binding by ViewBinderDelegate(V2ConversationFragmentBinding::bind) { _binding ->
|
||||
_binding.conversationInputPanel.embeddedTextEditor.apply {
|
||||
@@ -2959,7 +2963,7 @@ class ConversationFragment :
|
||||
|
||||
override fun onCallToAction(action: String) {
|
||||
if ("gift_badge" == action) {
|
||||
startActivity(CheckoutFlowActivity.createIntent(requireContext(), InAppPaymentType.ONE_TIME_GIFT))
|
||||
checkoutLauncher.launch(InAppPaymentType.ONE_TIME_GIFT)
|
||||
} else if ("username_edit" == action) {
|
||||
startActivity(EditProfileActivity.getIntentForUsernameEdit(requireContext()))
|
||||
}
|
||||
|
||||
@@ -532,17 +532,13 @@
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit"
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
app:popUpToInclusive="true">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_direct_to_checkout"
|
||||
app:destination="@id/checkoutFlowActivity"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit"
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
<argument
|
||||
android:name="direct_to_checkout_type"
|
||||
android:defaultValue="UNKNOWN"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</action>
|
||||
|
||||
<action
|
||||
android:id="@+id/action_direct_to_notificationProfiles"
|
||||
@@ -741,13 +737,10 @@
|
||||
<action
|
||||
android:id="@+id/action_manageDonationsFragment_to_subscribeLearnMoreBottomSheetDialog"
|
||||
app:destination="@id/subscribeLearnMoreBottomSheetDialog" />
|
||||
<action
|
||||
android:id="@+id/action_manageDonationsFragment_to_donateToSignalFragment"
|
||||
app:destination="@id/checkoutFlowActivity"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<argument
|
||||
android:name="direct_to_checkout_type"
|
||||
android:defaultValue="UNKNOWN"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
@@ -985,6 +978,11 @@
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
|
||||
<argument
|
||||
android:name="backup_later_selected"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
@@ -1002,19 +1000,9 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/remoteBackupsPaymentHistoryFragment"
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.history.RemoteBackupsPaymentHistoryFragment"/>
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.history.RemoteBackupsPaymentHistoryFragment" />
|
||||
|
||||
<include app:graph="@navigation/username_link_settings" />
|
||||
<include app:graph="@navigation/story_privacy_settings" />
|
||||
|
||||
<activity
|
||||
android:id="@+id/checkoutFlowActivity"
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity"
|
||||
android:label="checkout_flow_activity">
|
||||
|
||||
<argument
|
||||
android:name="in_app_payment_type"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</activity>
|
||||
|
||||
</navigation>
|
||||
@@ -532,17 +532,13 @@
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit"
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
app:popUpToInclusive="true">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_direct_to_checkout"
|
||||
app:destination="@id/checkoutFlowActivity"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit"
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
<argument
|
||||
android:name="direct_to_checkout_type"
|
||||
android:defaultValue="UNKNOWN"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</action>
|
||||
|
||||
<action
|
||||
android:id="@+id/action_direct_to_notificationProfiles"
|
||||
@@ -741,13 +737,10 @@
|
||||
<action
|
||||
android:id="@+id/action_manageDonationsFragment_to_subscribeLearnMoreBottomSheetDialog"
|
||||
app:destination="@id/subscribeLearnMoreBottomSheetDialog" />
|
||||
<action
|
||||
android:id="@+id/action_manageDonationsFragment_to_donateToSignalFragment"
|
||||
app:destination="@id/checkoutFlowActivity"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<argument
|
||||
android:name="direct_to_checkout_type"
|
||||
android:defaultValue="UNKNOWN"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
@@ -985,12 +978,16 @@
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
|
||||
<argument
|
||||
android:name="backup_later_selected"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/remoteBackupsPaymentHistoryFragment"
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.history.RemoteBackupsPaymentHistoryFragment">
|
||||
</fragment>
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.history.RemoteBackupsPaymentHistoryFragment"></fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/backupsTypeSettingsFragment"
|
||||
@@ -1008,14 +1005,4 @@
|
||||
<include app:graph="@navigation/username_link_settings" />
|
||||
<include app:graph="@navigation/story_privacy_settings" />
|
||||
|
||||
<activity
|
||||
android:id="@+id/checkoutFlowActivity"
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity"
|
||||
android:label="checkout_flow_activity">
|
||||
|
||||
<argument
|
||||
android:name="in_app_payment_type"
|
||||
app:argType="org.signal.donations.InAppPaymentType" />
|
||||
</activity>
|
||||
|
||||
</navigation>
|
||||
@@ -7311,6 +7311,8 @@
|
||||
<string name="RemoteBackupsSettingsFragment__subscription_cancelled">Subscription cancelled</string>
|
||||
<!-- Snackbar text displayed when backup is successfully downloaded -->
|
||||
<string name="RemoteBackupsSettingsFragment__download_complete">Download complete</string>
|
||||
<!-- Snackbar text displayed when backup will be created overnight -->
|
||||
<string name="RemoteBackupsSettingsFragment__backup_will_be_created_overnight">Backup will be created overnight.</string>
|
||||
<!-- Title text in row detailing selected backup type -->
|
||||
<string name="RemoteBackupsSettingsFragment__backup_type">Backup type</string>
|
||||
<!-- Subtitle text in row detailing selected backup type displayed when backups are disabled -->
|
||||
|
||||
Reference in New Issue
Block a user