Add meta item for restoring all (internal) system apps

This way we don't need to show the long complicated list, but provide an all or nothing option at least.
This commit is contained in:
Torsten Grote 2024-05-23 18:00:08 -03:00
parent 573e48f393
commit 787b9346a8
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
4 changed files with 34 additions and 7 deletions

View file

@ -94,6 +94,7 @@ data class PackageMetadata(
internal val sha256: String? = null,
internal val signatures: List<String>? = null,
) {
val isInternalSystem: Boolean = system && !isLaunchableSystemApp
fun hasApk(): Boolean {
return version != null && sha256 != null && signatures != null
}

View file

@ -19,6 +19,7 @@ import androidx.recyclerview.widget.RecyclerView.VISIBLE
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.ui.AppViewHolder
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SYSTEM
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@ -118,7 +119,7 @@ internal class AppSelectionAdapter(
val itemsWithSections = items.toMutableList().apply {
val i = indexOfLast {
it as SelectableAppItem
it.metadata.system && !it.metadata.isLaunchableSystemApp
it.packageName == PACKAGE_NAME_SYSTEM
}
add(i + 1, AppSelectionSection(R.string.backup_section_user))
add(0, AppSelectionSection(R.string.backup_section_system))

View file

@ -63,6 +63,7 @@ import com.stevesoltys.seedvault.ui.AppBackupState.NOT_YET_BACKED_UP
import com.stevesoltys.seedvault.ui.AppBackupState.SUCCEEDED
import com.stevesoltys.seedvault.ui.LiveEvent
import com.stevesoltys.seedvault.ui.MutableLiveEvent
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SYSTEM
import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel
import com.stevesoltys.seedvault.ui.notification.getAppName
import com.stevesoltys.seedvault.ui.systemData
@ -188,7 +189,7 @@ internal class RestoreViewModel(
// filter and sort app items for display
val items = restorableBackup.packageMetadataMap.mapNotNull { (packageName, metadata) ->
if (metadata.time == 0L && !metadata.hasApk()) null
else if (metadata.system && !metadata.isLaunchableSystemApp) null
else if (metadata.isInternalSystem) null
else SelectableAppItem(packageName, metadata, true)
}.sortedBy {
it.name.lowercase(Locale.getDefault())
@ -200,6 +201,18 @@ internal class RestoreViewModel(
val name = app.getString(data.nameRes)
SelectableAppItem(packageName, metadata.copy(name = name), true, hasIcon = true)
}
val systemItem = SelectableAppItem(
packageName = PACKAGE_NAME_SYSTEM,
metadata = PackageMetadata(
time = restorableBackup.packageMetadataMap.values.maxOf {
if (it.system) it.time else -1
},
system = true,
name = app.getString(R.string.backup_system_apps),
),
selected = true,
)
items.add(0, systemItem)
items.addAll(0, systemDataItems)
mSelectedApps.value =
SelectedAppsState(apps = items, allSelected = true, iconsLoaded = false)
@ -227,9 +240,10 @@ internal class RestoreViewModel(
}
suspend fun loadIcon(item: SelectableAppItem, callback: (Bitmap) -> Unit) {
if (item.metadata.system && !item.metadata.isLaunchableSystemApp &&
item.packageName in systemData.keys
) {
if (item.packageName == PACKAGE_NAME_SYSTEM) {
val bitmap = getDrawable(app, R.drawable.ic_app_settings)!!.toBitmap()
callback(bitmap)
} else if (item.metadata.isInternalSystem && item.packageName in systemData.keys) {
val bitmap = getDrawable(app, systemData[item.packageName]!!.iconRes)!!.toBitmap()
callback(bitmap)
} else {
@ -274,8 +288,18 @@ internal class RestoreViewModel(
Pair(it.packageName, it.selected)
} ?: error("no selected apps")
// filter out unselected packages
val packages = backup.packageMetadataMap.filterKeys { packageName ->
apps[packageName] != true // packages that weren't found, won't get filtered
// Attention: This code is complicated and hard to test, proceed with plenty of care!
val restoreSystemApps = apps[PACKAGE_NAME_SYSTEM] != false
val packages = backup.packageMetadataMap.filter { (packageName, metadata) ->
val isSelected = apps[packageName]
@Suppress("IfThenToElvis") // the code is more readable like this
if (isSelected == null) { // was not in list
// internal system apps were not in the list and are controlled by meta item
if (metadata.isInternalSystem) restoreSystemApps // only if allowed by meta item
else true // non-system packages that weren't found, won't get filtered
} else { // was in list and either selected or not
isSelected
}
} as PackageMetadataMap
// replace original chosen backup with unselected packages removed
mChosenRestorableBackup.value = backup.copy(

View file

@ -13,6 +13,7 @@ internal const val PACKAGE_NAME_SMS = "com.android.providers.telephony"
internal const val PACKAGE_NAME_SETTINGS = "com.android.providers.settings"
internal const val PACKAGE_NAME_CALL_LOG = "com.android.calllogbackup"
internal const val PACKAGE_NAME_CONTACTS = "org.calyxos.backup.contacts"
internal const val PACKAGE_NAME_SYSTEM = "@org.calyxos.system@"
val systemData = mapOf(
PACKAGE_NAME_SMS to SystemData(R.string.backup_sms, R.drawable.ic_message),