mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
Update backups bottom sheet data handling.
This commit is contained in:
committed by
Greyson Parrelli
parent
3901c52e45
commit
f14f7f7478
@@ -125,6 +125,11 @@ object BackupRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun skipMediaRestore() {
|
||||||
|
// TODO [backups] -- Clear the error as necessary
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the yellow dot should be displayed on the conversation list avatar.
|
* Whether the yellow dot should be displayed on the conversation list avatar.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
package org.thoughtcrime.securesms.backup.v2.ui
|
package org.thoughtcrime.securesms.backup.v2.ui
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.annotation.StringRes
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -37,6 +37,7 @@ import androidx.compose.ui.res.pluralStringResource
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.BundleCompat
|
import androidx.core.os.BundleCompat
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
@@ -46,6 +47,7 @@ import org.signal.core.ui.Buttons
|
|||||||
import org.signal.core.ui.Previews
|
import org.signal.core.ui.Previews
|
||||||
import org.signal.core.ui.SignalPreview
|
import org.signal.core.ui.SignalPreview
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||||
import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription
|
import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription
|
||||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||||
@@ -63,6 +65,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
|
|||||||
companion object {
|
companion object {
|
||||||
private const val ARG_ALERT = "alert"
|
private const val ARG_ALERT = "alert"
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
fun create(backupAlert: BackupAlert): BackupAlertBottomSheet {
|
fun create(backupAlert: BackupAlert): BackupAlertBottomSheet {
|
||||||
return BackupAlertBottomSheet().apply {
|
return BackupAlertBottomSheet().apply {
|
||||||
arguments = bundleOf(ARG_ALERT to backupAlert)
|
arguments = bundleOf(ARG_ALERT to backupAlert)
|
||||||
@@ -94,17 +97,17 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
|
|||||||
@Stable
|
@Stable
|
||||||
private fun performPrimaryAction() {
|
private fun performPrimaryAction() {
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> {
|
BackupAlert.CouldNotCompleteBackup -> {
|
||||||
BackupMessagesJob.enqueue()
|
BackupMessagesJob.enqueue()
|
||||||
startActivity(AppSettingsActivity.remoteBackups(requireContext()))
|
startActivity(AppSettingsActivity.remoteBackups(requireContext()))
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupAlert.PAYMENT_PROCESSING -> launchManageBackupsSubscription()
|
BackupAlert.FailedToRenew -> launchManageBackupsSubscription()
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF, BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> {
|
BackupAlert.MediaBackupsAreOff, BackupAlert.MediaWillBeDeletedToday -> {
|
||||||
performFullMediaDownload()
|
performFullMediaDownload()
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupAlert.DISK_FULL -> Unit
|
is BackupAlert.DiskFull -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
@@ -113,20 +116,22 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
|
|||||||
@Stable
|
@Stable
|
||||||
private fun performSecondaryAction() {
|
private fun performSecondaryAction() {
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> {
|
BackupAlert.CouldNotCompleteBackup -> {
|
||||||
// TODO [backups] - Dismiss and notify later
|
// TODO [backups] - Dismiss and notify later
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupAlert.PAYMENT_PROCESSING -> Unit
|
BackupAlert.FailedToRenew -> Unit
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF -> {
|
BackupAlert.MediaBackupsAreOff -> {
|
||||||
// TODO [backups] - Silence and remind on last day
|
// TODO [backups] - Silence and remind on last day
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> {
|
BackupAlert.MediaWillBeDeletedToday -> {
|
||||||
displayLastChanceDialog()
|
displayLastChanceDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupAlert.DISK_FULL -> Unit
|
is BackupAlert.DiskFull -> {
|
||||||
|
displaySkipRestoreDialog()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
@@ -143,6 +148,23 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun displaySkipRestoreDialog() {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setTitle((R.string.BackupAlertBottomSheet__skip_restore_question))
|
||||||
|
.setMessage(R.string.BackupAlertBottomSheet__if_you_skip_restore)
|
||||||
|
.setPositiveButton(R.string.BackupAlertBottomSheet__skip) { _, _ ->
|
||||||
|
BackupRepository.skipMediaRestore()
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.create()
|
||||||
|
.apply {
|
||||||
|
setOnShowListener {
|
||||||
|
getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(ContextCompat.getColor(requireContext(), R.color.signal_colorError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun performFullMediaDownload() {
|
private fun performFullMediaDownload() {
|
||||||
// TODO [backups] -- We need to force this to download everything
|
// TODO [backups] -- We need to force this to download everything
|
||||||
AppDependencies.jobManager.add(BackupRestoreMediaJob())
|
AppDependencies.jobManager.add(BackupRestoreMediaJob())
|
||||||
@@ -167,7 +189,7 @@ private fun BackupAlertSheetContent(
|
|||||||
Spacer(modifier = Modifier.size(26.dp))
|
Spacer(modifier = Modifier.size(26.dp))
|
||||||
|
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.PAYMENT_PROCESSING, BackupAlert.MEDIA_BACKUPS_ARE_OFF -> {
|
BackupAlert.FailedToRenew, BackupAlert.MediaBackupsAreOff -> {
|
||||||
Box {
|
Box {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.image_signal_backups),
|
painter = painterResource(id = R.drawable.image_signal_backups),
|
||||||
@@ -200,24 +222,21 @@ private fun BackupAlertSheetContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = rememberTitleResource(backupAlert = backupAlert)),
|
text = titleString(backupAlert = backupAlert),
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.padding(top = 16.dp, bottom = 6.dp)
|
modifier = Modifier.padding(top = 16.dp, bottom = 6.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> CouldNotCompleteBackup(
|
BackupAlert.CouldNotCompleteBackup -> CouldNotCompleteBackup(
|
||||||
daysSinceLastBackup = 7 // TODO [backups]
|
daysSinceLastBackup = 7 // TODO [backups]
|
||||||
)
|
)
|
||||||
|
|
||||||
BackupAlert.PAYMENT_PROCESSING -> PaymentProcessingBody()
|
BackupAlert.FailedToRenew -> PaymentProcessingBody()
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF -> MediaBackupsAreOffBody(30) // TODO [backups] -- Get this value from backend
|
BackupAlert.MediaBackupsAreOff -> MediaBackupsAreOffBody(30) // TODO [backups] -- Get this value from backend
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> MediaWillBeDeletedTodayBody()
|
BackupAlert.MediaWillBeDeletedToday -> MediaWillBeDeletedTodayBody()
|
||||||
BackupAlert.DISK_FULL -> DiskFullBody(
|
is BackupAlert.DiskFull -> DiskFullBody(requiredSpace = backupAlert.requiredSpace)
|
||||||
requiredSpace = "12 GB", // TODO [backups] Where does this value come from?
|
|
||||||
daysUntilDeletion = 30 // TODO [backups] Where does this value come from?
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val secondaryActionResource = rememberSecondaryActionResource(backupAlert = backupAlert)
|
val secondaryActionResource = rememberSecondaryActionResource(backupAlert = backupAlert)
|
||||||
@@ -299,19 +318,16 @@ private fun MediaWillBeDeletedTodayBody() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DiskFullBody(
|
private fun DiskFullBody(requiredSpace: String) {
|
||||||
requiredSpace: String,
|
|
||||||
daysUntilDeletion: Long
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.BackupAlertBottomSheet__your_device_does_not_have_enough_free_space, requiredSpace),
|
text = stringResource(id = R.string.BackupAlertBottomSheet__to_finish_downloading_your_signal_backup, requiredSpace),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
modifier = Modifier.padding(bottom = 24.dp)
|
modifier = Modifier.padding(bottom = 24.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = pluralStringResource(id = R.plurals.BackupAlertBottomSheet__if_you_choose_skip, daysUntilDeletion.toInt(), daysUntilDeletion), // TODO [backups] Learn More link
|
text = stringResource(R.string.BackupAlertBottomSheet__to_free_up_space_offload),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
modifier = Modifier.padding(bottom = 36.dp)
|
modifier = Modifier.padding(bottom = 36.dp)
|
||||||
@@ -322,24 +338,21 @@ private fun DiskFullBody(
|
|||||||
private fun rememberBackupsIconColors(backupAlert: BackupAlert): BackupsIconColors {
|
private fun rememberBackupsIconColors(backupAlert: BackupAlert): BackupsIconColors {
|
||||||
return remember(backupAlert) {
|
return remember(backupAlert) {
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.PAYMENT_PROCESSING, BackupAlert.MEDIA_BACKUPS_ARE_OFF -> error("Not icon-based options.")
|
BackupAlert.FailedToRenew, BackupAlert.MediaBackupsAreOff -> error("Not icon-based options.")
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP, BackupAlert.DISK_FULL -> BackupsIconColors.Warning
|
BackupAlert.CouldNotCompleteBackup, is BackupAlert.DiskFull -> BackupsIconColors.Warning
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> BackupsIconColors.Error
|
BackupAlert.MediaWillBeDeletedToday -> BackupsIconColors.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@StringRes
|
private fun titleString(backupAlert: BackupAlert): String {
|
||||||
private fun rememberTitleResource(backupAlert: BackupAlert): Int {
|
return when (backupAlert) {
|
||||||
return remember(backupAlert) {
|
BackupAlert.CouldNotCompleteBackup -> stringResource(R.string.BackupAlertBottomSheet__couldnt_complete_backup)
|
||||||
when (backupAlert) {
|
BackupAlert.FailedToRenew -> stringResource(R.string.BackupAlertBottomSheet__your_backups_subscription_failed_to_renew)
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> R.string.BackupAlertBottomSheet__couldnt_complete_backup
|
BackupAlert.MediaBackupsAreOff -> stringResource(R.string.BackupAlertBottomSheet__your_backups_subscription_expired)
|
||||||
BackupAlert.PAYMENT_PROCESSING -> R.string.BackupAlertBottomSheet__your_backups_subscription_failed_to_renew
|
BackupAlert.MediaWillBeDeletedToday -> stringResource(R.string.BackupAlertBottomSheet__your_media_will_be_deleted_today)
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.BackupAlertBottomSheet__your_backups_subscription_expired
|
is BackupAlert.DiskFull -> stringResource(R.string.BackupAlertBottomSheet__free_up_s_on_this_device, backupAlert.requiredSpace)
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.BackupAlertBottomSheet__your_media_will_be_deleted_today
|
|
||||||
BackupAlert.DISK_FULL -> R.string.BackupAlertBottomSheet__cant_complete_download
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,11 +362,11 @@ private fun primaryActionString(
|
|||||||
pricePerMonth: String
|
pricePerMonth: String
|
||||||
): String {
|
): String {
|
||||||
return when (backupAlert) {
|
return when (backupAlert) {
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> stringResource(R.string.BackupAlertBottomSheet__back_up_now)
|
BackupAlert.CouldNotCompleteBackup -> stringResource(R.string.BackupAlertBottomSheet__back_up_now)
|
||||||
BackupAlert.PAYMENT_PROCESSING -> stringResource(R.string.BackupAlertBottomSheet__manage_subscription)
|
BackupAlert.FailedToRenew -> stringResource(R.string.BackupAlertBottomSheet__manage_subscription)
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF -> stringResource(R.string.BackupAlertBottomSheet__subscribe_for_s_month, pricePerMonth)
|
BackupAlert.MediaBackupsAreOff -> stringResource(R.string.BackupAlertBottomSheet__subscribe_for_s_month, pricePerMonth)
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> stringResource(R.string.BackupAlertBottomSheet__download_media_now)
|
BackupAlert.MediaWillBeDeletedToday -> stringResource(R.string.BackupAlertBottomSheet__download_media_now)
|
||||||
BackupAlert.DISK_FULL -> stringResource(android.R.string.ok)
|
is BackupAlert.DiskFull -> stringResource(R.string.BackupAlertBottomSheet__got_it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,11 +374,11 @@ private fun primaryActionString(
|
|||||||
private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int {
|
private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int {
|
||||||
return remember(backupAlert) {
|
return remember(backupAlert) {
|
||||||
when (backupAlert) {
|
when (backupAlert) {
|
||||||
BackupAlert.COULD_NOT_COMPLETE_BACKUP -> android.R.string.cancel // TODO [backups] -- Finalized copy
|
BackupAlert.CouldNotCompleteBackup -> R.string.BackupAlertBottomSheet__try_later
|
||||||
BackupAlert.PAYMENT_PROCESSING -> R.string.BackupAlertBottomSheet__not_now
|
BackupAlert.FailedToRenew -> R.string.BackupAlertBottomSheet__not_now
|
||||||
BackupAlert.MEDIA_BACKUPS_ARE_OFF -> R.string.BackupAlertBottomSheet__not_now
|
BackupAlert.MediaBackupsAreOff -> R.string.BackupAlertBottomSheet__not_now
|
||||||
BackupAlert.MEDIA_WILL_BE_DELETED_TODAY -> R.string.BackupAlertBottomSheet__dont_download_media
|
BackupAlert.MediaWillBeDeletedToday -> R.string.BackupAlertBottomSheet__dont_download_media
|
||||||
BackupAlert.DISK_FULL -> R.string.BackupAlertBottomSheet__skip
|
is BackupAlert.DiskFull -> R.string.BackupAlertBottomSheet__skip_restore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,7 +388,7 @@ private fun rememberSecondaryActionResource(backupAlert: BackupAlert): Int {
|
|||||||
private fun BackupAlertSheetContentPreviewGeneric() {
|
private fun BackupAlertSheetContentPreviewGeneric() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.COULD_NOT_COMPLETE_BACKUP
|
backupAlert = BackupAlert.CouldNotCompleteBackup
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,7 +398,7 @@ private fun BackupAlertSheetContentPreviewGeneric() {
|
|||||||
private fun BackupAlertSheetContentPreviewPayment() {
|
private fun BackupAlertSheetContentPreviewPayment() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.PAYMENT_PROCESSING
|
backupAlert = BackupAlert.FailedToRenew
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,7 +408,7 @@ private fun BackupAlertSheetContentPreviewPayment() {
|
|||||||
private fun BackupAlertSheetContentPreviewMedia() {
|
private fun BackupAlertSheetContentPreviewMedia() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.MEDIA_BACKUPS_ARE_OFF,
|
backupAlert = BackupAlert.MediaBackupsAreOff,
|
||||||
pricePerMonth = "$2.99"
|
pricePerMonth = "$2.99"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -406,7 +419,7 @@ private fun BackupAlertSheetContentPreviewMedia() {
|
|||||||
private fun BackupAlertSheetContentPreviewDelete() {
|
private fun BackupAlertSheetContentPreviewDelete() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.MEDIA_WILL_BE_DELETED_TODAY
|
backupAlert = BackupAlert.MediaWillBeDeletedToday
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,16 +429,28 @@ private fun BackupAlertSheetContentPreviewDelete() {
|
|||||||
private fun BackupAlertSheetContentPreviewDiskFull() {
|
private fun BackupAlertSheetContentPreviewDiskFull() {
|
||||||
Previews.BottomSheetPreview {
|
Previews.BottomSheetPreview {
|
||||||
BackupAlertSheetContent(
|
BackupAlertSheetContent(
|
||||||
backupAlert = BackupAlert.DISK_FULL
|
backupAlert = BackupAlert.DiskFull(requiredSpace = "12GB")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All necessary information to display the sheet should be handed in through the specific alert.
|
||||||
|
*/
|
||||||
@Parcelize
|
@Parcelize
|
||||||
enum class BackupAlert : Parcelable {
|
sealed class BackupAlert : Parcelable {
|
||||||
COULD_NOT_COMPLETE_BACKUP,
|
|
||||||
PAYMENT_PROCESSING,
|
data object CouldNotCompleteBackup : BackupAlert()
|
||||||
MEDIA_BACKUPS_ARE_OFF,
|
|
||||||
MEDIA_WILL_BE_DELETED_TODAY,
|
data object FailedToRenew : BackupAlert()
|
||||||
DISK_FULL
|
|
||||||
|
data object MediaBackupsAreOff : BackupAlert()
|
||||||
|
|
||||||
|
data object MediaWillBeDeletedToday : BackupAlert()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The disk is full. Contains a value representing the amount of space that must be freed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
data class DiskFull(val requiredSpace: String) : BackupAlert()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import androidx.lifecycle.Lifecycle
|
|||||||
import androidx.lifecycle.coroutineScope
|
import androidx.lifecycle.coroutineScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegate that controls whether and which backup alert sheet is displayed.
|
* Delegate that controls whether and which backup alert sheet is displayed.
|
||||||
@@ -19,12 +20,12 @@ object BackupAlertDelegate {
|
|||||||
fun delegate(fragmentManager: FragmentManager, lifecycle: Lifecycle) {
|
fun delegate(fragmentManager: FragmentManager, lifecycle: Lifecycle) {
|
||||||
lifecycle.coroutineScope.launch {
|
lifecycle.coroutineScope.launch {
|
||||||
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
// TODO [backups]
|
if (BackupRepository.shouldDisplayBackupFailedSheet()) {
|
||||||
// 1. Get unnotified backup upload failures
|
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup).show(fragmentManager, null)
|
||||||
// 2. Get unnotified backup download failures
|
}
|
||||||
// 3. Get unnotified backup payment failures
|
|
||||||
|
|
||||||
// Decide which do display
|
// TODO [backups]
|
||||||
|
// Get unnotified backup download failures & display sheet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ private const val NONE = -1
|
|||||||
@Composable
|
@Composable
|
||||||
fun BackupStatusBanner(
|
fun BackupStatusBanner(
|
||||||
data: BackupStatusData,
|
data: BackupStatusData,
|
||||||
onSkipClick: () -> Unit = {},
|
onActionClick: (BackupStatusData) -> Unit = {},
|
||||||
onDismissClick: () -> Unit = {},
|
onDismissClick: () -> Unit = {},
|
||||||
contentPadding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
|
contentPadding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -119,7 +119,7 @@ fun BackupStatusBanner(
|
|||||||
|
|
||||||
if (data.actionRes != NONE) {
|
if (data.actionRes != NONE) {
|
||||||
Buttons.Small(
|
Buttons.Small(
|
||||||
onClick = onSkipClick,
|
onClick = { onActionClick(data) },
|
||||||
modifier = Modifier.padding(start = 8.dp)
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(id = data.actionRes))
|
Text(text = stringResource(id = data.actionRes))
|
||||||
@@ -250,7 +250,7 @@ sealed interface BackupStatusData {
|
|||||||
get() = stringResource(R.string.BackupStatus__free_up_s_of_space_to_download_your_media, requiredSpace)
|
get() = stringResource(R.string.BackupStatus__free_up_s_of_space_to_download_your_media, requiredSpace)
|
||||||
|
|
||||||
override val iconColors: BackupsIconColors = BackupsIconColors.Warning
|
override val iconColors: BackupsIconColors = BackupsIconColors.Warning
|
||||||
override val actionRes: Int = R.string.registration_activity__skip
|
override val actionRes: Int = R.string.BackupStatus__details
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList
|
|||||||
override fun DisplayBanner(model: BackupStatusData, contentPadding: PaddingValues) {
|
override fun DisplayBanner(model: BackupStatusData, contentPadding: PaddingValues) {
|
||||||
BackupStatusBanner(
|
BackupStatusBanner(
|
||||||
data = model,
|
data = model,
|
||||||
onSkipClick = listener::onSkip,
|
onActionClick = listener::onActionClick,
|
||||||
onDismissClick = listener::onDismissComplete
|
onDismissClick = listener::onDismissComplete
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -124,12 +124,12 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface RestoreProgressBannerListener {
|
interface RestoreProgressBannerListener {
|
||||||
fun onSkip()
|
fun onActionClick(data: BackupStatusData)
|
||||||
fun onDismissComplete()
|
fun onDismissComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
private object EmptyListener : RestoreProgressBannerListener {
|
private object EmptyListener : RestoreProgressBannerListener {
|
||||||
override fun onSkip() = Unit
|
override fun onActionClick(data: BackupStatusData) = Unit
|
||||||
override fun onDismissComplete() = Unit
|
override fun onDismissComplete() = Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun skipMediaRestore() {
|
fun skipMediaRestore() {
|
||||||
// TODO [backups] -- Clear the error as necessary
|
BackupRepository.skipMediaRestore()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelMediaRestore() {
|
fun cancelMediaRestore() {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import org.signal.donations.InAppPaymentType
|
|||||||
import org.signal.donations.PaymentSourceType
|
import org.signal.donations.PaymentSourceType
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord
|
import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
import org.thoughtcrime.securesms.util.Environment
|
import org.thoughtcrime.securesms.util.Environment
|
||||||
import org.thoughtcrime.securesms.util.LocaleRemoteConfig
|
import org.thoughtcrime.securesms.util.LocaleRemoteConfig
|
||||||
@@ -28,9 +27,9 @@ object InAppDonations {
|
|||||||
return isCreditCardAvailable() || isPayPalAvailable() || isGooglePayAvailable() || isSEPADebitAvailable() || isIDEALAvailable()
|
return isCreditCardAvailable() || isPayPalAvailable() || isGooglePayAvailable() || isSEPADebitAvailable() || isIDEALAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPaymentSourceAvailable(paymentSourceType: PaymentSourceType, inAppPaymentType: InAppPaymentType): Boolean {
|
fun isDonationsPaymentSourceAvailable(paymentSourceType: PaymentSourceType, inAppPaymentType: InAppPaymentType): Boolean {
|
||||||
if (inAppPaymentType == InAppPaymentType.RECURRING_BACKUP) {
|
if (inAppPaymentType == InAppPaymentType.RECURRING_BACKUP) {
|
||||||
return paymentSourceType == PaymentSourceType.GooglePlayBilling && AppDependencies.billingApi.isApiAvailable()
|
error("Not supported.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (paymentSourceType) {
|
return when (paymentSourceType) {
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ class InAppPaymentsBottomSheetDelegate(
|
|||||||
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy { inAppPayments ->
|
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy { inAppPayments ->
|
||||||
for (payment in inAppPayments) {
|
for (payment in inAppPayments) {
|
||||||
if (isPaymentProcessingError(payment.state, payment.data)) {
|
if (isPaymentProcessingError(payment.state, payment.data)) {
|
||||||
BackupAlertBottomSheet.create(BackupAlert.COULD_NOT_COMPLETE_BACKUP).show(fragmentManager, null)
|
BackupAlertBottomSheet.create(BackupAlert.CouldNotCompleteBackup).show(fragmentManager, null)
|
||||||
} else if (isUnexpectedCancellation(payment.state, payment.data)) {
|
} else if (isUnexpectedCancellation(payment.state, payment.data)) {
|
||||||
BackupAlertBottomSheet.create(BackupAlert.MEDIA_BACKUPS_ARE_OFF).show(fragmentManager, null)
|
BackupAlertBottomSheet.create(BackupAlert.MediaBackupsAreOff).show(fragmentManager, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ class InAppPaymentsBottomSheetDelegate(
|
|||||||
InAppPaymentsRepository.getExpiredBackupDeletionState()
|
InAppPaymentsRepository.getExpiredBackupDeletionState()
|
||||||
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy {
|
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeBy {
|
||||||
if (it == InAppPaymentsRepository.ExpiredBackupDeletionState.DELETE_TODAY) {
|
if (it == InAppPaymentsRepository.ExpiredBackupDeletionState.DELETE_TODAY) {
|
||||||
BackupAlertBottomSheet.create(BackupAlert.MEDIA_WILL_BE_DELETED_TODAY).show(fragmentManager, null)
|
BackupAlertBottomSheet.create(BackupAlert.MediaWillBeDeletedToday).show(fragmentManager, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class InAppPaymentCheckoutDelegate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun handleGatewaySelectionResponse(inAppPayment: InAppPaymentTable.InAppPayment) {
|
fun handleGatewaySelectionResponse(inAppPayment: InAppPaymentTable.InAppPayment) {
|
||||||
if (InAppDonations.isPaymentSourceAvailable(inAppPayment.data.paymentMethodType.toPaymentSourceType(), inAppPayment.type)) {
|
if (InAppDonations.isDonationsPaymentSourceAvailable(inAppPayment.data.paymentMethodType.toPaymentSourceType(), inAppPayment.type)) {
|
||||||
when (inAppPayment.data.paymentMethodType) {
|
when (inAppPayment.data.paymentMethodType) {
|
||||||
InAppPaymentData.PaymentMethodType.GOOGLE_PAY -> launchGooglePay(inAppPayment)
|
InAppPaymentData.PaymentMethodType.GOOGLE_PAY -> launchGooglePay(inAppPayment)
|
||||||
InAppPaymentData.PaymentMethodType.PAYPAL -> launchPayPal(inAppPayment)
|
InAppPaymentData.PaymentMethodType.PAYPAL -> launchPayPal(inAppPayment)
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ class GatewaySelectorViewModel(
|
|||||||
GatewaySelectorState(
|
GatewaySelectorState(
|
||||||
gatewayOrderStrategy = GatewayOrderStrategy.getStrategy(),
|
gatewayOrderStrategy = GatewayOrderStrategy.getStrategy(),
|
||||||
inAppPayment = args.inAppPayment,
|
inAppPayment = args.inAppPayment,
|
||||||
isCreditCardAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.CreditCard, args.inAppPayment.type),
|
isCreditCardAvailable = InAppDonations.isDonationsPaymentSourceAvailable(PaymentSourceType.Stripe.CreditCard, args.inAppPayment.type),
|
||||||
isGooglePayAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.GooglePay, args.inAppPayment.type),
|
isGooglePayAvailable = InAppDonations.isDonationsPaymentSourceAvailable(PaymentSourceType.Stripe.GooglePay, args.inAppPayment.type),
|
||||||
isPayPalAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.PayPal, args.inAppPayment.type),
|
isPayPalAvailable = InAppDonations.isDonationsPaymentSourceAvailable(PaymentSourceType.PayPal, args.inAppPayment.type),
|
||||||
isSEPADebitAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.SEPADebit, args.inAppPayment.type),
|
isSEPADebitAvailable = InAppDonations.isDonationsPaymentSourceAvailable(PaymentSourceType.Stripe.SEPADebit, args.inAppPayment.type),
|
||||||
isIDEALAvailable = InAppDonations.isPaymentSourceAvailable(PaymentSourceType.Stripe.IDEAL, args.inAppPayment.type)
|
isIDEALAvailable = InAppDonations.isDonationsPaymentSourceAvailable(PaymentSourceType.Stripe.IDEAL, args.inAppPayment.type)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
private val disposables = CompositeDisposable()
|
private val disposables = CompositeDisposable()
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import android.net.Uri;
|
|||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -94,11 +93,10 @@ import org.thoughtcrime.securesms.MainNavigator;
|
|||||||
import org.thoughtcrime.securesms.MuteDialog;
|
import org.thoughtcrime.securesms.MuteDialog;
|
||||||
import org.thoughtcrime.securesms.NewConversationActivity;
|
import org.thoughtcrime.securesms.NewConversationActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.backup.v2.ArchiveValidator;
|
|
||||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository;
|
|
||||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlert;
|
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlert;
|
||||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertBottomSheet;
|
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertBottomSheet;
|
||||||
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertDelegate;
|
import org.thoughtcrime.securesms.backup.v2.ui.BackupAlertDelegate;
|
||||||
|
import org.thoughtcrime.securesms.backup.v2.ui.status.BackupStatusData;
|
||||||
import org.thoughtcrime.securesms.badges.models.Badge;
|
import org.thoughtcrime.securesms.badges.models.Badge;
|
||||||
import org.thoughtcrime.securesms.badges.self.expired.ExpiredOneTimeBadgeBottomSheetDialogFragment;
|
import org.thoughtcrime.securesms.badges.self.expired.ExpiredOneTimeBadgeBottomSheetDialogFragment;
|
||||||
import org.thoughtcrime.securesms.badges.self.expired.MonthlyDonationCanceledBottomSheetDialogFragment;
|
import org.thoughtcrime.securesms.badges.self.expired.MonthlyDonationCanceledBottomSheetDialogFragment;
|
||||||
@@ -163,7 +161,6 @@ import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
|||||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile;
|
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.profiles.manage.UsernameEditFragment;
|
import org.thoughtcrime.securesms.profiles.manage.UsernameEditFragment;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
|
||||||
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment;
|
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
@@ -178,12 +175,10 @@ import org.thoughtcrime.securesms.util.AppStartup;
|
|||||||
import org.thoughtcrime.securesms.util.BottomSheetUtil;
|
import org.thoughtcrime.securesms.util.BottomSheetUtil;
|
||||||
import org.thoughtcrime.securesms.util.CachedInflater;
|
import org.thoughtcrime.securesms.util.CachedInflater;
|
||||||
import org.thoughtcrime.securesms.util.ConversationUtil;
|
import org.thoughtcrime.securesms.util.ConversationUtil;
|
||||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
||||||
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
||||||
import org.thoughtcrime.securesms.util.SnapToTopDataObserver;
|
import org.thoughtcrime.securesms.util.SnapToTopDataObserver;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
|
import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
|
||||||
@@ -193,10 +188,6 @@ import org.thoughtcrime.securesms.util.views.Stub;
|
|||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -581,10 +572,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||||||
if (this.bannerManager != null) {
|
if (this.bannerManager != null) {
|
||||||
this.bannerManager.updateContent(bannerView.get());
|
this.bannerManager.updateContent(bannerView.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BackupRepository.shouldDisplayBackupFailedSheet()) {
|
|
||||||
BackupAlertBottomSheet.Companion.create(BackupAlert.COULD_NOT_COMPLETE_BACKUP).show(getParentFragmentManager(), null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -928,8 +915,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
|||||||
}),
|
}),
|
||||||
new MediaRestoreProgressBanner(new MediaRestoreProgressBanner.RestoreProgressBannerListener() {
|
new MediaRestoreProgressBanner(new MediaRestoreProgressBanner.RestoreProgressBannerListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSkip() {
|
public void onActionClick(@NonNull BackupStatusData backupStatusData) {
|
||||||
// TODO [backups] add skip restore ability
|
if (backupStatusData instanceof BackupStatusData.NotEnoughFreeSpace) {
|
||||||
|
BackupAlertBottomSheet.create(new BackupAlert.DiskFull(((BackupStatusData.NotEnoughFreeSpace) backupStatusData).getRequiredSpace()))
|
||||||
|
.show(getParentFragmentManager(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,20 +6,31 @@
|
|||||||
package org.thoughtcrime.securesms.dependencies
|
package org.thoughtcrime.securesms.dependencies
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import org.signal.billing.BillingError
|
||||||
import org.signal.core.util.billing.BillingDependencies
|
import org.signal.core.util.billing.BillingDependencies
|
||||||
|
import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependency object for Google Play Billing.
|
* Dependency object for Google Play Billing.
|
||||||
*/
|
*/
|
||||||
object GooglePlayBillingDependencies : BillingDependencies {
|
object GooglePlayBillingDependencies : BillingDependencies {
|
||||||
|
|
||||||
|
private const val BILLING_PRODUCT_ID_NOT_AVAILABLE = -1000
|
||||||
|
|
||||||
override val context: Context get() = AppDependencies.application
|
override val context: Context get() = AppDependencies.application
|
||||||
|
|
||||||
override suspend fun getProductId(): String {
|
override suspend fun getProductId(): String {
|
||||||
return "backup" // TODO [backups] This really shouldn't be hardcoded into the app.
|
val config = AppDependencies.donationsService.getDonationsConfiguration(Locale.getDefault())
|
||||||
|
|
||||||
|
if (config.result.isPresent) {
|
||||||
|
return config.result.get().backupConfiguration.backupLevelConfigurationMap[SubscriptionsConfiguration.BACKUPS_LEVEL]?.playProductId ?: throw BillingError(BILLING_PRODUCT_ID_NOT_AVAILABLE)
|
||||||
|
} else {
|
||||||
|
throw BillingError(BILLING_PRODUCT_ID_NOT_AVAILABLE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getBasePlanId(): String {
|
override suspend fun getBasePlanId(): String {
|
||||||
return "monthly" // TODO [backups] This really shouldn't be hardcoded into the app.
|
return "monthly"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7431,15 +7431,12 @@
|
|||||||
<string name="BackupAlertBottomSheet__your_media_will_be_deleted_today">Your media will be deleted today</string>
|
<string name="BackupAlertBottomSheet__your_media_will_be_deleted_today">Your media will be deleted today</string>
|
||||||
<!-- Sheet body part 1 when user\'s media will be deleted today -->
|
<!-- Sheet body part 1 when user\'s media will be deleted today -->
|
||||||
<string name="BackupAlertBottomSheet__your_signal_media_backup_plan_has_been">Your Signal media backup plan has been canceled because we couldn\'t process your payment. This is your last chance to download the media in your backup before it is deleted.</string>
|
<string name="BackupAlertBottomSheet__your_signal_media_backup_plan_has_been">Your Signal media backup plan has been canceled because we couldn\'t process your payment. This is your last chance to download the media in your backup before it is deleted.</string>
|
||||||
<!-- Sheet title when user does not have enough space to download their backup -->
|
<!-- Sheet title when user does not have enough space to download their backup. Placeholder is formatted byte size, for example 12GB. -->
|
||||||
<string name="BackupAlertBottomSheet__cant_complete_download">Can\'t complete download</string>
|
<string name="BackupAlertBottomSheet__free_up_s_on_this_device">Free up %1$s on this device</string>
|
||||||
<!-- Sheet body part 1 when user does not have enough space to download their backup. Placeholder is the amount of space needed. -->
|
<!-- Sheet body part 1 when user does not have enough space to download their backup. Placeholder is the amount of space needed. -->
|
||||||
<string name="BackupAlertBottomSheet__your_device_does_not_have_enough_free_space">Your device does not have enough free space. Free up %1$s of space to download the media stored in your backup.</string>
|
<string name="BackupAlertBottomSheet__to_finish_downloading_your_signal_backup">To finish downloading your Signal Backup your device needs %1$s of storage space.</string>
|
||||||
<!-- Sheet body part 2 when user does not have enough space to download their backup. Placeholder is the number of days until deletion -->
|
<!-- Sheet body part 2 when user does not have enough space to download their backup. -->
|
||||||
<plurals name="BackupAlertBottomSheet__if_you_choose_skip">
|
<string name="BackupAlertBottomSheet__to_free_up_space_offload">To free up space offload or delete unused apps or content large in file size.</string>
|
||||||
<item quantity="one">If you choose \"Skip\" the media in your backup will be deleted in %1$d day.</item>
|
|
||||||
<item quantity="other">If you choose \"Skip\" the media in your backup will be deleted in %1$d days.</item>
|
|
||||||
</plurals>
|
|
||||||
<!-- Sheet title when user payment failed to process -->
|
<!-- Sheet title when user payment failed to process -->
|
||||||
<string name="BackupAlertBottomSheet__your_backups_subscription_failed_to_renew">Your backups subscription failed to renew</string>
|
<string name="BackupAlertBottomSheet__your_backups_subscription_failed_to_renew">Your backups subscription failed to renew</string>
|
||||||
<!-- Sheet body when user payment failed to process -->
|
<!-- Sheet body when user payment failed to process -->
|
||||||
@@ -7451,9 +7448,11 @@
|
|||||||
<!-- Clickable text to learn more about the content of this bottom sheet -->
|
<!-- Clickable text to learn more about the content of this bottom sheet -->
|
||||||
<string name="BackupAlertBottomSheet__learn_more">Learn more</string>
|
<string name="BackupAlertBottomSheet__learn_more">Learn more</string>
|
||||||
<!-- Secondary action button text when user does not have enough free space to download their backup. -->
|
<!-- Secondary action button text when user does not have enough free space to download their backup. -->
|
||||||
<string name="BackupAlertBottomSheet__skip">Skip</string>
|
<string name="BackupAlertBottomSheet__skip_restore">Skip restore</string>
|
||||||
<!-- Primary action button to start backup immediately -->
|
<!-- Primary action button to start backup immediately -->
|
||||||
<string name="BackupAlertBottomSheet__back_up_now">Back up now</string>
|
<string name="BackupAlertBottomSheet__back_up_now">Back up now</string>
|
||||||
|
<!-- Primary action button when user doesn't have enough space -->
|
||||||
|
<string name="BackupAlertBottomSheet__got_it">Got it</string>
|
||||||
<!-- Primary action button to manage subscription in Google Play -->
|
<!-- Primary action button to manage subscription in Google Play -->
|
||||||
<string name="BackupAlertBottomSheet__manage_subscription">Manage subscription</string>
|
<string name="BackupAlertBottomSheet__manage_subscription">Manage subscription</string>
|
||||||
<!-- Primary action button text prompting user to subscriber. Placeholder is formatted price -->
|
<!-- Primary action button text prompting user to subscriber. Placeholder is formatted price -->
|
||||||
@@ -7464,6 +7463,8 @@
|
|||||||
<string name="BackupAlertBottomSheet__dont_download_media">Don\'t download media</string>
|
<string name="BackupAlertBottomSheet__dont_download_media">Don\'t download media</string>
|
||||||
<!-- Secondary generic action button to dismiss sheet without performing an action -->
|
<!-- Secondary generic action button to dismiss sheet without performing an action -->
|
||||||
<string name="BackupAlertBottomSheet__not_now">Not now</string>
|
<string name="BackupAlertBottomSheet__not_now">Not now</string>
|
||||||
|
<!-- Secondary action button to dismiss could not complete backup sheet -->
|
||||||
|
<string name="BackupAlertBottomSheet__try_later">Try later</string>
|
||||||
<!-- Dialog title for last chance to download backup -->
|
<!-- Dialog title for last chance to download backup -->
|
||||||
<string name="BackupAlertBottomSheet__media_will_be_deleted">Media will be deleted</string>
|
<string name="BackupAlertBottomSheet__media_will_be_deleted">Media will be deleted</string>
|
||||||
<!-- Dialog message for last chance to download backup -->
|
<!-- Dialog message for last chance to download backup -->
|
||||||
@@ -7472,6 +7473,12 @@
|
|||||||
<string name="BackupAlertBottomSheet__download">Download</string>
|
<string name="BackupAlertBottomSheet__download">Download</string>
|
||||||
<!-- Dialog action to not download now -->
|
<!-- Dialog action to not download now -->
|
||||||
<string name="BackupAlertBottomSheet__dont_download">Don\'t download</string>
|
<string name="BackupAlertBottomSheet__dont_download">Don\'t download</string>
|
||||||
|
<!-- Dialog action to skip media download -->
|
||||||
|
<string name="BackupAlertBottomSheet__skip">Skip</string>
|
||||||
|
<!-- Dialog title for skipping media restore -->
|
||||||
|
<string name="BackupAlertBottomSheet__skip_restore_question">Skip restore?</string>
|
||||||
|
<!-- Dialog text for skipping media restore -->
|
||||||
|
<string name="BackupAlertBottomSheet__if_you_skip_restore">If you skip restore the remaining media and attachments in your backup will be deleted the next time your device completes a new backup.</string>
|
||||||
|
|
||||||
<!-- BackupStatus -->
|
<!-- BackupStatus -->
|
||||||
<!-- Status title when user does not have enough free space to download their media. Placeholder is required disk space. -->
|
<!-- Status title when user does not have enough free space to download their media. Placeholder is required disk space. -->
|
||||||
@@ -7482,6 +7489,8 @@
|
|||||||
<string name="BackupStatus__restore_paused">Restore paused</string>
|
<string name="BackupStatus__restore_paused">Restore paused</string>
|
||||||
<!-- Status title for banner when user has completed restoring restore media from a backup -->
|
<!-- Status title for banner when user has completed restoring restore media from a backup -->
|
||||||
<string name="BackupStatus__restore_complete">Restore complete</string>
|
<string name="BackupStatus__restore_complete">Restore complete</string>
|
||||||
|
<!-- Status action label for seeing more details about storage space -->
|
||||||
|
<string name="BackupStatus__details">Details</string>
|
||||||
|
|
||||||
<!-- Status subtitle for banner when restoring media pauses for Wi-Fi -->
|
<!-- Status subtitle for banner when restoring media pauses for Wi-Fi -->
|
||||||
<string name="BackupStatus__status_waiting_for_wifi">Waiting for Wi-Fi…</string>
|
<string name="BackupStatus__status_waiting_for_wifi">Waiting for Wi-Fi…</string>
|
||||||
|
|||||||
@@ -249,8 +249,10 @@ internal class BillingApiImpl(
|
|||||||
* Returns whether or not subscriptions are supported by a user's device. Lack of subscription support is generally due
|
* Returns whether or not subscriptions are supported by a user's device. Lack of subscription support is generally due
|
||||||
* to out-of-date Google Play API
|
* to out-of-date Google Play API
|
||||||
*/
|
*/
|
||||||
override fun isApiAvailable(): Boolean {
|
override suspend fun isApiAvailable(): Boolean {
|
||||||
return billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).responseCode == BillingResponseCode.OK
|
return doOnConnectionReady {
|
||||||
|
billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).responseCode == BillingResponseCode.OK
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun queryProductsInternal(): ProductDetailsResult {
|
private suspend fun queryProductsInternal(): ProductDetailsResult {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ interface BillingApi {
|
|||||||
*/
|
*/
|
||||||
fun getBillingPurchaseResults(): Flow<BillingPurchaseResult> = emptyFlow()
|
fun getBillingPurchaseResults(): Flow<BillingPurchaseResult> = emptyFlow()
|
||||||
|
|
||||||
fun isApiAvailable(): Boolean = false
|
suspend fun isApiAvailable(): Boolean = false
|
||||||
|
|
||||||
suspend fun queryProduct(): BillingProduct? = null
|
suspend fun queryProduct(): BillingProduct? = null
|
||||||
|
|
||||||
|
|||||||
@@ -105,9 +105,16 @@ public class SubscriptionsConfiguration {
|
|||||||
@JsonProperty("storageAllowanceBytes")
|
@JsonProperty("storageAllowanceBytes")
|
||||||
private long storageAllowanceBytes;
|
private long storageAllowanceBytes;
|
||||||
|
|
||||||
|
@JsonProperty("playProductId")
|
||||||
|
private String playProductId;
|
||||||
|
|
||||||
public long getStorageAllowanceBytes() {
|
public long getStorageAllowanceBytes() {
|
||||||
return storageAllowanceBytes;
|
return storageAllowanceBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPlayProductId() {
|
||||||
|
return playProductId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, CurrencyConfiguration> getCurrencies() {
|
public Map<String, CurrencyConfiguration> getCurrencies() {
|
||||||
|
|||||||
Reference in New Issue
Block a user