Skip to content

Commit a8bf03a

Browse files
committed
Add restore local backupv2 infra.
1 parent 00d20a1 commit a8bf03a

41 files changed

Lines changed: 606 additions & 315 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ object BackupRepository {
365365
private fun import(
366366
backupKey: BackupKey,
367367
frameReader: BackupImportReader,
368-
selfData: SelfData,
369-
importExtras: ((EventTimer) -> Unit)? = null
368+
selfData: SelfData
370369
): ImportResult {
371370
val eventTimer = EventTimer()
372371

@@ -444,23 +443,27 @@ object BackupRepository {
444443
eventTimer.emit("chatItem")
445444
}
446445

447-
importExtras?.invoke(eventTimer)
448-
449446
importState.chatIdToLocalThreadId.values.forEach {
450447
SignalDatabase.threads.update(it, unarchive = false, allowDeletion = false)
451448
}
452449
}
453450

454-
SignalDatabase.groups.getGroups().use { groups ->
455-
while (groups.hasNext()) {
456-
val group = groups.next()
457-
if (group.id.isV2) {
458-
AppDependencies.jobManager.add(RequestGroupV2InfoJob(group.id as GroupId.V2))
451+
Log.d(TAG, "import() ${eventTimer.stop().summary}")
452+
453+
val groupJobs = SignalDatabase.groups.getGroups().use { groups ->
454+
groups
455+
.asSequence()
456+
.mapNotNull { group ->
457+
if (group.id.isV2) {
458+
RequestGroupV2InfoJob(group.id as GroupId.V2)
459+
} else {
460+
null
461+
}
459462
}
460-
}
463+
.toList()
461464
}
465+
AppDependencies.jobManager.addAll(groupJobs)
462466

463-
Log.d(TAG, "import() ${eventTimer.stop().summary}")
464467
return ImportResult.Success(backupTime = header.backupTimeMs)
465468
}
466469

app/src/main/java/org/thoughtcrime/securesms/backup/v2/local/ArchiveFileSystem.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ class ArchiveFileSystem private constructor(private val context: Context, root:
6363
fun fromFile(context: Context, backupDirectory: File): ArchiveFileSystem {
6464
return ArchiveFileSystem(context, DocumentFile.fromFile(backupDirectory))
6565
}
66+
67+
fun openInputStream(context: Context, uri: Uri): InputStream? {
68+
return context.contentResolver.openInputStream(uri)
69+
}
6670
}
6771

6872
private val signalBackups: DocumentFile
@@ -284,29 +288,22 @@ class FilesFileSystem(private val context: Context, private val root: DocumentFi
284288
* undefined and should be avoided.
285289
*/
286290
fun fileOutputStream(mediaName: MediaName): OutputStream? {
287-
val subFileDirectoryName = mediaName.name.substring(0..1)
288-
val subFileDirectory = subFolders[subFileDirectoryName]!!
291+
val subFileDirectory = subFileDirectoryFor(mediaName)
289292
val file = subFileDirectory.createFile("application/octet-stream", mediaName.name)
290293
return file?.outputStream(context)
291294
}
292295

293-
/**
294-
* Given a [file], open and return an [InputStream].
295-
*/
296-
fun fileInputStream(file: DocumentFileInfo): InputStream? {
297-
return file.documentFile.inputStream(context)
298-
}
299-
300296
/**
301297
* Delete a file for the given [mediaName] if it exists.
302298
*
303299
* @return true if deleted, false if not, null if not found
304300
*/
305301
fun delete(mediaName: MediaName): Boolean? {
306-
val subFileDirectoryName = mediaName.name.substring(0..1)
307-
val subFileDirectory = subFolders[subFileDirectoryName]!!
302+
return subFileDirectoryFor(mediaName).delete(context, mediaName.name)
303+
}
308304

309-
return subFileDirectory.delete(context, mediaName.name)
305+
private fun subFileDirectoryFor(mediaName: MediaName): DocumentFile {
306+
return subFolders[mediaName.name.substring(0..1)]!!
310307
}
311308
}
312309

app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatus.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import androidx.annotation.DrawableRes
99
import androidx.annotation.StringRes
1010
import androidx.compose.foundation.background
1111
import androidx.compose.foundation.border
12-
import androidx.compose.foundation.layout.Arrangement
1312
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.PaddingValues
1414
import androidx.compose.foundation.layout.Row
1515
import androidx.compose.foundation.layout.fillMaxWidth
1616
import androidx.compose.foundation.layout.padding
1717
import androidx.compose.foundation.shape.CircleShape
1818
import androidx.compose.foundation.shape.RoundedCornerShape
19+
import androidx.compose.material3.HorizontalDivider
1920
import androidx.compose.material3.LinearProgressIndicator
2021
import androidx.compose.material3.MaterialTheme
2122
import androidx.compose.material3.Text
@@ -45,11 +46,13 @@ private const val NONE = -1
4546
@Composable
4647
fun BackupStatus(
4748
data: BackupStatusData,
48-
onActionClick: () -> Unit = {}
49+
onActionClick: () -> Unit = {},
50+
contentPadding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp)
4951
) {
5052
Row(
5153
verticalAlignment = Alignment.CenterVertically,
5254
modifier = Modifier
55+
.padding(contentPadding)
5356
.border(1.dp, color = MaterialTheme.colorScheme.outline.copy(alpha = 0.38f), shape = RoundedCornerShape(12.dp))
5457
.fillMaxWidth()
5558
.padding(14.dp)
@@ -71,7 +74,8 @@ fun BackupStatus(
7174
) {
7275
Text(
7376
text = data.title,
74-
style = MaterialTheme.typography.bodyMedium
77+
style = MaterialTheme.typography.bodyMedium,
78+
color = MaterialTheme.colorScheme.onSurface
7579
)
7680

7781
if (data.progress >= 0f) {
@@ -108,17 +112,19 @@ fun BackupStatus(
108112
@Composable
109113
fun BackupStatusPreview() {
110114
Previews.Preview {
111-
Column(
112-
verticalArrangement = Arrangement.spacedBy(12.dp)
113-
) {
115+
Column {
114116
BackupStatus(
115117
data = BackupStatusData.CouldNotCompleteBackup
116118
)
117119

120+
HorizontalDivider()
121+
118122
BackupStatus(
119123
data = BackupStatusData.NotEnoughFreeSpace("12 GB")
120124
)
121125

126+
HorizontalDivider()
127+
122128
BackupStatus(
123129
data = BackupStatusData.RestoringMedia(50, 100)
124130
)
@@ -201,7 +207,7 @@ sealed interface BackupStatusData {
201207
)
202208

203209
override val statusRes: Int = when (status) {
204-
Status.NONE -> R.string.default_error_msg
210+
Status.NONE -> NONE
205211
Status.LOW_BATTERY -> R.string.default_error_msg
206212
Status.WAITING_FOR_INTERNET -> R.string.default_error_msg
207213
Status.WAITING_FOR_WIFI -> R.string.default_error_msg

app/src/main/java/org/thoughtcrime/securesms/banner/Banner.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.thoughtcrime.securesms.banner
77

8+
import androidx.compose.foundation.layout.PaddingValues
89
import androidx.compose.runtime.Composable
910
import kotlinx.coroutines.flow.Flow
1011
import kotlinx.coroutines.flow.flow
@@ -44,5 +45,5 @@ abstract class Banner {
4445
* @see [org.thoughtcrime.securesms.banner.ui.compose.DefaultBanner]
4546
*/
4647
@Composable
47-
abstract fun DisplayBanner()
48+
abstract fun DisplayBanner(contentPadding: PaddingValues)
4849
}

app/src/main/java/org/thoughtcrime/securesms/banner/BannerManager.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
package org.thoughtcrime.securesms.banner
77

88
import androidx.compose.foundation.layout.Box
9+
import androidx.compose.foundation.layout.PaddingValues
910
import androidx.compose.ui.platform.ComposeView
1011
import androidx.compose.ui.platform.ViewCompositionStrategy
12+
import androidx.compose.ui.unit.dp
1113
import androidx.lifecycle.compose.collectAsStateWithLifecycle
1214
import kotlinx.coroutines.flow.Flow
1315
import kotlinx.coroutines.flow.combine
16+
import org.signal.core.ui.theme.SignalTheme
1417
import org.signal.core.util.logging.Log
1518

1619
/**
@@ -47,8 +50,10 @@ class BannerManager @JvmOverloads constructor(
4750

4851
val bannerToDisplay = state.value.firstOrNull()
4952
if (bannerToDisplay != null) {
50-
Box {
51-
bannerToDisplay.DisplayBanner()
53+
SignalTheme {
54+
Box {
55+
bannerToDisplay.DisplayBanner(PaddingValues(horizontal = 12.dp, vertical = 8.dp))
56+
}
5257
}
5358

5459
onNewBannerShownListener()

app/src/main/java/org/thoughtcrime/securesms/banner/banners/BubbleOptOutBanner.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.thoughtcrime.securesms.banner.banners
77

88
import android.os.Build
9+
import androidx.compose.foundation.layout.PaddingValues
910
import androidx.compose.runtime.Composable
1011
import androidx.compose.ui.res.stringResource
1112
import kotlinx.coroutines.flow.Flow
@@ -21,7 +22,7 @@ class BubbleOptOutBanner(inBubble: Boolean, private val actionListener: (Boolean
2122
override val enabled: Boolean = inBubble && !SignalStore.tooltips.hasSeenBubbleOptOutTooltip() && Build.VERSION.SDK_INT > 29
2223

2324
@Composable
24-
override fun DisplayBanner() {
25+
override fun DisplayBanner(contentPadding: PaddingValues) {
2526
DefaultBanner(
2627
title = null,
2728
body = stringResource(id = R.string.BubbleOptOutTooltip__description),
@@ -32,7 +33,8 @@ class BubbleOptOutBanner(inBubble: Boolean, private val actionListener: (Boolean
3233
Action(R.string.BubbleOptOutTooltip__not_now) {
3334
actionListener(false)
3435
}
35-
)
36+
),
37+
paddingValues = contentPadding
3638
)
3739
}
3840

app/src/main/java/org/thoughtcrime/securesms/banner/banners/CdsPermanentErrorBanner.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.thoughtcrime.securesms.banner.banners
77

8+
import androidx.compose.foundation.layout.PaddingValues
89
import androidx.compose.runtime.Composable
910
import androidx.compose.ui.res.stringResource
1011
import androidx.fragment.app.FragmentManager
@@ -24,7 +25,7 @@ class CdsPermanentErrorBanner(private val fragmentManager: FragmentManager) : Ba
2425
override val enabled: Boolean = SignalStore.misc.isCdsBlocked && timeUntilUnblock >= PERMANENT_TIME_CUTOFF
2526

2627
@Composable
27-
override fun DisplayBanner() {
28+
override fun DisplayBanner(contentPadding: PaddingValues) {
2829
DefaultBanner(
2930
title = null,
3031
body = stringResource(id = R.string.reminder_cds_permanent_error_body),
@@ -33,7 +34,8 @@ class CdsPermanentErrorBanner(private val fragmentManager: FragmentManager) : Ba
3334
Action(R.string.reminder_cds_permanent_error_learn_more) {
3435
CdsPermanentErrorBottomSheet.show(fragmentManager)
3536
}
36-
)
37+
),
38+
paddingValues = contentPadding
3739
)
3840
}
3941

app/src/main/java/org/thoughtcrime/securesms/banner/banners/CdsTemporaryErrorBanner.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.thoughtcrime.securesms.banner.banners
77

8+
import androidx.compose.foundation.layout.PaddingValues
89
import androidx.compose.runtime.Composable
910
import androidx.compose.ui.res.stringResource
1011
import androidx.fragment.app.FragmentManager
@@ -23,7 +24,7 @@ class CdsTemporaryErrorBanner(private val fragmentManager: FragmentManager) : Ba
2324
override val enabled: Boolean = SignalStore.misc.isCdsBlocked && timeUntilUnblock < CdsPermanentErrorBanner.PERMANENT_TIME_CUTOFF
2425

2526
@Composable
26-
override fun DisplayBanner() {
27+
override fun DisplayBanner(contentPadding: PaddingValues) {
2728
DefaultBanner(
2829
title = null,
2930
body = stringResource(id = R.string.reminder_cds_warning_body),
@@ -32,7 +33,8 @@ class CdsTemporaryErrorBanner(private val fragmentManager: FragmentManager) : Ba
3233
Action(R.string.reminder_cds_warning_learn_more) {
3334
CdsTemporaryErrorBottomSheet.show(fragmentManager)
3435
}
35-
)
36+
),
37+
paddingValues = contentPadding
3638
)
3739
}
3840

app/src/main/java/org/thoughtcrime/securesms/banner/banners/DozeBanner.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.banner.banners
77

88
import android.content.Context
99
import android.os.Build
10+
import androidx.compose.foundation.layout.PaddingValues
1011
import androidx.compose.runtime.Composable
1112
import androidx.compose.ui.res.stringResource
1213
import kotlinx.coroutines.flow.Flow
@@ -25,23 +26,24 @@ class DozeBanner(private val context: Context, val dismissed: Boolean, private v
2526
Build.VERSION.SDK_INT >= 23 && !SignalStore.account.fcmEnabled && !TextSecurePreferences.hasPromptedOptimizeDoze(context) && !ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.packageName)
2627

2728
@Composable
28-
override fun DisplayBanner() {
29+
override fun DisplayBanner(contentPadding: PaddingValues) {
2930
if (Build.VERSION.SDK_INT < 23) {
3031
throw IllegalStateException("Showing a Doze banner for an OS prior to Android 6.0")
3132
}
3233
DefaultBanner(
3334
title = stringResource(id = R.string.DozeReminder_optimize_for_missing_play_services),
3435
body = stringResource(id = R.string.DozeReminder_this_device_does_not_support_play_services_tap_to_disable_system_battery),
36+
onDismissListener = {
37+
TextSecurePreferences.setPromptedOptimizeDoze(context, true)
38+
onDismiss()
39+
},
3540
actions = listOf(
3641
Action(android.R.string.ok) {
3742
TextSecurePreferences.setPromptedOptimizeDoze(context, true)
3843
PowerManagerCompat.requestIgnoreBatteryOptimizations(context)
3944
}
4045
),
41-
onDismissListener = {
42-
TextSecurePreferences.setPromptedOptimizeDoze(context, true)
43-
onDismiss()
44-
}
46+
paddingValues = contentPadding
4547
)
4648
}
4749

app/src/main/java/org/thoughtcrime/securesms/banner/banners/EnclaveFailureBanner.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.thoughtcrime.securesms.banner.banners
77

88
import android.content.Context
9+
import androidx.compose.foundation.layout.PaddingValues
910
import androidx.compose.runtime.Composable
1011
import androidx.compose.ui.res.stringResource
1112
import kotlinx.coroutines.flow.Flow
@@ -21,7 +22,7 @@ class EnclaveFailureBanner(enclaveFailed: Boolean, private val context: Context)
2122
override val enabled: Boolean = enclaveFailed
2223

2324
@Composable
24-
override fun DisplayBanner() {
25+
override fun DisplayBanner(contentPadding: PaddingValues) {
2526
DefaultBanner(
2627
title = null,
2728
body = stringResource(id = R.string.EnclaveFailureReminder_update_signal),
@@ -30,7 +31,8 @@ class EnclaveFailureBanner(enclaveFailed: Boolean, private val context: Context)
3031
Action(R.string.ExpiredBuildReminder_update_now) {
3132
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(context)
3233
}
33-
)
34+
),
35+
paddingValues = contentPadding
3436
)
3537
}
3638

0 commit comments

Comments
 (0)