Add screen for managing backup type.

This commit is contained in:
Alex Hart
2024-04-19 15:05:03 -03:00
committed by Cody Henthorne
parent 04fb459acd
commit b771a21518
6 changed files with 264 additions and 5 deletions

View File

@@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
import org.thoughtcrime.securesms.compose.ComposeFragment import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.payments.FiatMoneyUtil import org.thoughtcrime.securesms.payments.FiatMoneyUtil
import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.navigation.safeNavigate
import org.thoughtcrime.securesms.util.viewModel import org.thoughtcrime.securesms.util.viewModel
import java.math.BigDecimal import java.math.BigDecimal
import java.util.Currency import java.util.Currency
@@ -130,8 +131,8 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
viewModel.turnOffAndDeleteBackups() viewModel.turnOffAndDeleteBackups()
} }
override fun onChangeBackupsTypeClick() { override fun onBackupsTypeClick() {
// TODO - launch flow at appropriate point findNavController().safeNavigate(R.id.action_remoteBackupsSettingsFragment_to_backupsTypeSettingsFragment)
} }
} }
} }
@@ -142,7 +143,7 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
private interface ContentCallbacks { private interface ContentCallbacks {
fun onNavigationClick() = Unit fun onNavigationClick() = Unit
fun onEnableBackupsClick() = Unit fun onEnableBackupsClick() = Unit
fun onChangeBackupsTypeClick() = Unit fun onBackupsTypeClick() = Unit
fun onBackUpUsingCellularClick(canUseCellular: Boolean) = Unit fun onBackUpUsingCellularClick(canUseCellular: Boolean) = Unit
fun onViewPaymentHistory() = Unit fun onViewPaymentHistory() = Unit
fun onBackupNowClick() = Unit fun onBackupNowClick() = Unit
@@ -184,7 +185,7 @@ private fun RemoteBackupsSettingsContent(
BackupTypeRow( BackupTypeRow(
messageBackupsType = messageBackupsType, messageBackupsType = messageBackupsType,
onEnableBackupsClick = contentCallbacks::onEnableBackupsClick, onEnableBackupsClick = contentCallbacks::onEnableBackupsClick,
onChangeBackupsTypeClick = contentCallbacks::onChangeBackupsTypeClick onChangeBackupsTypeClick = contentCallbacks::onBackupsTypeClick
) )
} }

View File

@@ -0,0 +1,197 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.chats.backups.type
import android.content.Intent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
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.navigation.fragment.findNavController
import kotlinx.collections.immutable.persistentListOf
import org.signal.core.ui.Previews
import org.signal.core.ui.Rows
import org.signal.core.ui.Scaffolds
import org.signal.core.ui.SignalPreview
import org.signal.core.util.money.FiatMoney
import org.signal.donations.PaymentSourceType
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsFlowActivity
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.viewModel
import java.math.BigDecimal
import java.util.Currency
import java.util.Locale
/**
* Allows the user to modify their backup plan
*/
class BackupsTypeSettingsFragment : ComposeFragment() {
private val viewModel: BackupsTypeSettingsViewModel by viewModel {
BackupsTypeSettingsViewModel()
}
@Composable
override fun FragmentContent() {
val contentCallbacks = remember {
Callbacks()
}
val state by viewModel.state
BackupsTypeSettingsContent(
state = state,
contentCallbacks = contentCallbacks
)
}
private inner class Callbacks : ContentCallbacks {
override fun onNavigationClick() {
findNavController().popBackStack()
}
override fun onPaymentHistoryClick() {
// TODO [message-backups] Navigate to payment history
}
override fun onChangeOrCancelSubscriptionClick() {
startActivity(Intent(requireContext(), MessageBackupsFlowActivity::class.java))
}
}
}
private interface ContentCallbacks {
fun onNavigationClick() = Unit
fun onPaymentHistoryClick() = Unit
fun onChangeOrCancelSubscriptionClick() = Unit
}
@Composable
private fun BackupsTypeSettingsContent(
state: BackupsTypeSettingsState,
contentCallbacks: ContentCallbacks
) {
if (state.backupsType == null) {
return
}
Scaffolds.Settings(
title = "Backup Type",
onNavigationClick = contentCallbacks::onNavigationClick,
navigationIconPainter = painterResource(id = R.drawable.symbol_arrow_left_24)
) {
LazyColumn(
modifier = Modifier.padding(it)
) {
item {
BackupsTypeRow(
backupsType = state.backupsType,
nextRenewalTimestamp = state.nextRenewalTimestamp
)
}
item {
PaymentSourceRow(
paymentSourceType = state.paymentSourceType
)
}
item {
Rows.TextRow(
text = "Change or cancel subscription", // TODO [message-backups] final copy
onClick = contentCallbacks::onChangeOrCancelSubscriptionClick
)
}
item {
Rows.TextRow(
text = "Payment history", // TODO [message-backups] final copy
onClick = contentCallbacks::onPaymentHistoryClick
)
}
}
}
}
@Composable
private fun BackupsTypeRow(
backupsType: MessageBackupsType,
nextRenewalTimestamp: Long
) {
val resources = LocalContext.current.resources
val formattedAmount = remember(backupsType.pricePerMonth) {
FiatMoneyUtil.format(resources, backupsType.pricePerMonth, FiatMoneyUtil.formatOptions().trimZerosAfterDecimal())
}
val renewal = remember(nextRenewalTimestamp) {
DateUtils.formatDateWithoutDayOfWeek(Locale.getDefault(), nextRenewalTimestamp)
}
Rows.TextRow(text = {
Column {
Text(text = backupsType.title)
Text(
text = "$formattedAmount/month . Renews $renewal", // TODO [message-backups] final copy
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
})
}
@Composable
private fun PaymentSourceRow(paymentSourceType: PaymentSourceType) {
val paymentSourceTextResId = remember(paymentSourceType) {
when (paymentSourceType) {
is PaymentSourceType.Stripe.CreditCard -> R.string.BackupsTypeSettingsFragment__credit_or_debit_card
is PaymentSourceType.Stripe.IDEAL -> R.string.BackupsTypeSettingsFragment__iDEAL
is PaymentSourceType.Stripe.GooglePay -> R.string.BackupsTypeSettingsFragment__google_pay
is PaymentSourceType.Stripe.SEPADebit -> R.string.BackupsTypeSettingsFragment__bank_transfer
is PaymentSourceType.PayPal -> R.string.BackupsTypeSettingsFragment__paypal
is PaymentSourceType.Unknown -> R.string.BackupsTypeSettingsFragment__unknown
}
}
Rows.TextRow(text = {
Column {
Text(text = "Payment method") // TOD [message-backups] Final copy
Text(
text = stringResource(id = paymentSourceTextResId),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
})
}
@SignalPreview
@Composable
private fun BackupsTypeSettingsContentPreview() {
Previews.Preview {
BackupsTypeSettingsContent(
state = BackupsTypeSettingsState(
backupsType = MessageBackupsType(
pricePerMonth = FiatMoney(BigDecimal.valueOf(3), Currency.getInstance("USD")),
title = "Text + all media",
features = persistentListOf()
)
),
contentCallbacks = object : ContentCallbacks {}
)
}
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.chats.backups.type
import androidx.compose.runtime.Stable
import org.signal.donations.PaymentSourceType
import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
@Stable
data class BackupsTypeSettingsState(
val backupsType: MessageBackupsType? = null,
val paymentSourceType: PaymentSourceType = PaymentSourceType.Unknown,
val nextRenewalTimestamp: Long = 0
)

View File

@@ -0,0 +1,16 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.chats.backups.type
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class BackupsTypeSettingsViewModel : ViewModel() {
private val internalState = mutableStateOf(BackupsTypeSettingsState())
val state: State<BackupsTypeSettingsState> = internalState
}

View File

@@ -930,7 +930,20 @@
<fragment <fragment
android:id="@+id/remoteBackupsSettingsFragment" android:id="@+id/remoteBackupsSettingsFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.RemoteBackupsSettingsFragment" /> android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.RemoteBackupsSettingsFragment">
<action
android:id="@+id/action_remoteBackupsSettingsFragment_to_backupsTypeSettingsFragment"
app:destination="@id/backupsTypeSettingsFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/backupsTypeSettingsFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.chats.backups.type.BackupsTypeSettingsFragment" />
<include app:graph="@navigation/username_link_settings" /> <include app:graph="@navigation/username_link_settings" />
<include app:graph="@navigation/story_privacy_settings" /> <include app:graph="@navigation/story_privacy_settings" />

View File

@@ -6751,5 +6751,20 @@
<!-- Notification title shown while downloading backup restore data --> <!-- Notification title shown while downloading backup restore data -->
<string name="BackupProgressService_title_downloading">Downloading backup data…</string> <string name="BackupProgressService_title_downloading">Downloading backup data…</string>
<!-- BackupsTypeSettingsFragment -->
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__credit_or_debit_card">Credit or debit card</string>
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__iDEAL">iDEAL</string>
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__google_pay">Google Pay</string>
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__bank_transfer">Bank transfer</string>
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__paypal">PayPal</string>
<!-- Displayed as the user's payment method as a label in a preference row -->
<string name="BackupsTypeSettingsFragment__unknown">Unknown</string>
<!-- EOF --> <!-- EOF -->
</resources> </resources>