diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupsIconColors.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupsIconColors.kt
index 16e8396066..d2f69ffd41 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupsIconColors.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/BackupsIconColors.kt
@@ -20,7 +20,7 @@ sealed interface BackupsIconColors {
@get:Composable
val background: Color
- object Normal : BackupsIconColors {
+ data object Normal : BackupsIconColors {
override val foreground: Brush
@Composable get() = remember {
Brush.linearGradient(
diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/CreateBackupBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/CreateBackupBottomSheet.kt
new file mode 100644
index 0000000000..b802df6bf0
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/CreateBackupBottomSheet.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2024 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.backup.v2.ui
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.dimensionResource
+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 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.
+ */
+class CreateBackupBottomSheet : ComposeBottomSheetDialogFragment() {
+ @Composable
+ override fun SheetContent() {
+ CreateBackupBottomSheetContent(
+ onBackupNowClick = {
+ BackupMessagesJob.enqueue()
+ startActivity(AppSettingsActivity.remoteBackups(requireContext()))
+ dismissAllowingStateLoss()
+ },
+ onBackupLaterClick = {
+ dismissAllowingStateLoss()
+ }
+ )
+ }
+}
+
+@Composable
+private fun CreateBackupBottomSheetContent(
+ onBackupNowClick: () -> Unit,
+ onBackupLaterClick: () -> Unit
+) {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ BottomSheets.Handle()
+
+ Icons.BrushedForeground(
+ painter = painterResource(id = R.drawable.symbol_backup_light),
+ foregroundBrush = BackupsIconColors.Normal.foreground,
+ contentDescription = null,
+ modifier = Modifier
+ .padding(top = 18.dp, bottom = 11.dp)
+ .size(88.dp)
+ .background(
+ color = BackupsIconColors.Normal.background,
+ shape = CircleShape
+ )
+ .padding(20.dp)
+ )
+
+ Text(
+ text = stringResource(id = R.string.CreateBackupBottomSheet__create_backup),
+ style = MaterialTheme.typography.titleLarge
+ )
+
+ Text(
+ text = stringResource(id = R.string.CreateBackupBottomSheet__depending_on_the_size),
+ style = MaterialTheme.typography.bodyLarge,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .padding(top = 8.dp, bottom = 64.dp)
+ .padding(horizontal = dimensionResource(id = R.dimen.core_ui__gutter))
+ )
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = 31.dp)
+ ) {
+ TextButton(
+ onClick = onBackupLaterClick,
+ modifier = Modifier.padding(start = dimensionResource(id = R.dimen.core_ui__gutter))
+ ) {
+ Text(
+ text = stringResource(id = R.string.CreateBackupBottomSheet__back_up_later)
+ )
+ }
+
+ Spacer(modifier = Modifier.weight(1f))
+
+ Buttons.LargeTonal(
+ onClick = onBackupNowClick,
+ modifier = Modifier.padding(end = dimensionResource(id = R.dimen.core_ui__gutter))
+ ) {
+ Text(
+ text = stringResource(id = R.string.CreateBackupBottomSheet__back_up_now)
+ )
+ }
+ }
+ }
+}
+
+@SignalPreview
+@Composable
+private fun CreateBackupBottomSheetContentPreview() {
+ Previews.BottomSheetPreview {
+ CreateBackupBottomSheetContent(
+ onBackupNowClick = {},
+ onBackupLaterClick = {}
+ )
+ }
+}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt
index 83c38b552d..2a292ecbfe 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt
@@ -67,6 +67,7 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
StartLocation.LINKED_DEVICES -> AppSettingsFragmentDirections.actionDirectToDevices()
StartLocation.USERNAME_LINK -> AppSettingsFragmentDirections.actionDirectToUsernameLinkSettings()
StartLocation.RECOVER_USERNAME -> AppSettingsFragmentDirections.actionDirectToUsernameRecovery()
+ StartLocation.REMOTE_BACKUPS -> AppSettingsFragmentDirections.actionDirectToRemoteBackupsSettingsFragment()
}
}
@@ -194,6 +195,9 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
@JvmStatic
fun usernameRecovery(context: Context): Intent = getIntentForStartLocation(context, StartLocation.RECOVER_USERNAME)
+ @JvmStatic
+ fun remoteBackups(context: Context): Intent = getIntentForStartLocation(context, StartLocation.REMOTE_BACKUPS)
+
private fun getIntentForStartLocation(context: Context, startLocation: StartLocation): Intent {
return Intent(context, AppSettingsActivity::class.java)
.putExtra(ARG_NAV_GRAPH, R.navigation.app_settings_with_change_number)
@@ -217,7 +221,8 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
PRIVACY(12),
LINKED_DEVICES(13),
USERNAME_LINK(14),
- RECOVER_USERNAME(15);
+ RECOVER_USERNAME(15),
+ REMOTE_BACKUPS(16);
companion object {
fun fromCode(code: Int?): StartLocation {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/InAppPaymentCheckoutDelegate.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/InAppPaymentCheckoutDelegate.kt
index 8cb92d5837..c19909753c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/InAppPaymentCheckoutDelegate.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/InAppPaymentCheckoutDelegate.kt
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
+import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import androidx.fragment.app.Fragment
@@ -127,6 +128,7 @@ class InAppPaymentCheckoutDelegate(
if (result.action == InAppPaymentProcessorAction.CANCEL_SUBSCRIPTION) {
callback.onSubscriptionCancelled(result.inAppPaymentType)
} else {
+ fragment.requireActivity().setResult(Activity.RESULT_OK)
callback.onPaymentComplete(result.inAppPayment!!)
}
}
diff --git a/app/src/main/res/navigation/app_settings.xml b/app/src/main/res/navigation/app_settings.xml
index 015405d2bc..78d3ec0d81 100644
--- a/app/src/main/res/navigation/app_settings.xml
+++ b/app/src/main/res/navigation/app_settings.xml
@@ -617,6 +617,14 @@
app:argType="org.thoughtcrime.securesms.profiles.manage.UsernameEditMode" />
+
+
diff --git a/app/src/main/res/navigation/app_settings_with_change_number.xml b/app/src/main/res/navigation/app_settings_with_change_number.xml
index d6c0bbcc79..ed2e7e39a6 100644
--- a/app/src/main/res/navigation/app_settings_with_change_number.xml
+++ b/app/src/main/res/navigation/app_settings_with_change_number.xml
@@ -617,6 +617,14 @@
app:argType="org.thoughtcrime.securesms.profiles.manage.UsernameEditMode" />
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2214777347..336d9856eb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -792,6 +792,16 @@
Backup has a bad extension.
+
+
+ Create backup
+
+ Depending on the size of your backup, this could take a long time. You can use your phone as you normally do while the backup takes place.
+
+ Back up later
+
+ Back up now
+
Chat backups
Backups are encrypted with a passphrase and stored on your device.