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 sha256: String? = null,
internal val signatures: List<String>? = null, internal val signatures: List<String>? = null,
) { ) {
val isInternalSystem: Boolean = system && !isLaunchableSystemApp
fun hasApk(): Boolean { fun hasApk(): Boolean {
return version != null && sha256 != null && signatures != null 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.R
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.ui.AppViewHolder import com.stevesoltys.seedvault.ui.AppViewHolder
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SYSTEM
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -118,7 +119,7 @@ internal class AppSelectionAdapter(
val itemsWithSections = items.toMutableList().apply { val itemsWithSections = items.toMutableList().apply {
val i = indexOfLast { val i = indexOfLast {
it as SelectableAppItem it as SelectableAppItem
it.metadata.system && !it.metadata.isLaunchableSystemApp it.packageName == PACKAGE_NAME_SYSTEM
} }
add(i + 1, AppSelectionSection(R.string.backup_section_user)) add(i + 1, AppSelectionSection(R.string.backup_section_user))
add(0, AppSelectionSection(R.string.backup_section_system)) 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.AppBackupState.SUCCEEDED
import com.stevesoltys.seedvault.ui.LiveEvent import com.stevesoltys.seedvault.ui.LiveEvent
import com.stevesoltys.seedvault.ui.MutableLiveEvent 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.RequireProvisioningViewModel
import com.stevesoltys.seedvault.ui.notification.getAppName import com.stevesoltys.seedvault.ui.notification.getAppName
import com.stevesoltys.seedvault.ui.systemData import com.stevesoltys.seedvault.ui.systemData
@ -188,7 +189,7 @@ internal class RestoreViewModel(
// filter and sort app items for display // filter and sort app items for display
val items = restorableBackup.packageMetadataMap.mapNotNull { (packageName, metadata) -> val items = restorableBackup.packageMetadataMap.mapNotNull { (packageName, metadata) ->
if (metadata.time == 0L && !metadata.hasApk()) null if (metadata.time == 0L && !metadata.hasApk()) null
else if (metadata.system && !metadata.isLaunchableSystemApp) null else if (metadata.isInternalSystem) null
else SelectableAppItem(packageName, metadata, true) else SelectableAppItem(packageName, metadata, true)
}.sortedBy { }.sortedBy {
it.name.lowercase(Locale.getDefault()) it.name.lowercase(Locale.getDefault())
@ -200,6 +201,18 @@ internal class RestoreViewModel(
val name = app.getString(data.nameRes) val name = app.getString(data.nameRes)
SelectableAppItem(packageName, metadata.copy(name = name), true, hasIcon = true) 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) items.addAll(0, systemDataItems)
mSelectedApps.value = mSelectedApps.value =
SelectedAppsState(apps = items, allSelected = true, iconsLoaded = false) SelectedAppsState(apps = items, allSelected = true, iconsLoaded = false)
@ -227,9 +240,10 @@ internal class RestoreViewModel(
} }
suspend fun loadIcon(item: SelectableAppItem, callback: (Bitmap) -> Unit) { suspend fun loadIcon(item: SelectableAppItem, callback: (Bitmap) -> Unit) {
if (item.metadata.system && !item.metadata.isLaunchableSystemApp && if (item.packageName == PACKAGE_NAME_SYSTEM) {
item.packageName in systemData.keys 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() val bitmap = getDrawable(app, systemData[item.packageName]!!.iconRes)!!.toBitmap()
callback(bitmap) callback(bitmap)
} else { } else {
@ -274,8 +288,18 @@ internal class RestoreViewModel(
Pair(it.packageName, it.selected) Pair(it.packageName, it.selected)
} ?: error("no selected apps") } ?: error("no selected apps")
// filter out unselected packages // filter out unselected packages
val packages = backup.packageMetadataMap.filterKeys { packageName -> // Attention: This code is complicated and hard to test, proceed with plenty of care!
apps[packageName] != true // packages that weren't found, won't get filtered 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 } as PackageMetadataMap
// replace original chosen backup with unselected packages removed // replace original chosen backup with unselected packages removed
mChosenRestorableBackup.value = backup.copy( 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_SETTINGS = "com.android.providers.settings"
internal const val PACKAGE_NAME_CALL_LOG = "com.android.calllogbackup" 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_CONTACTS = "org.calyxos.backup.contacts"
internal const val PACKAGE_NAME_SYSTEM = "@org.calyxos.system@"
val systemData = mapOf( val systemData = mapOf(
PACKAGE_NAME_SMS to SystemData(R.string.backup_sms, R.drawable.ic_message), PACKAGE_NAME_SMS to SystemData(R.string.backup_sms, R.drawable.ic_message),