feat: Show patch bundle version used to patch an app (#2966)

Co-authored-by: planshim <100317079+planshim@users.noreply.github.com>
This commit is contained in:
AunAli K.
2026-02-28 07:31:23 +05:30
committed by GitHub
parent e03f3666c8
commit 11bd46ce26
10 changed files with 663 additions and 11 deletions

View File

@@ -0,0 +1,466 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "d9350f0e779a1bde46227a29884a7865",
"entities": [
{
"tableName": "patch_bundles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `name` TEXT NOT NULL, `version` TEXT, `source` TEXT NOT NULL, `auto_update` INTEGER NOT NULL, PRIMARY KEY(`uid`))",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "versionHash",
"columnName": "version",
"affinity": "TEXT"
},
{
"fieldPath": "source",
"columnName": "source",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "autoUpdate",
"columnName": "auto_update",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
}
},
{
"tableName": "patch_selections",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `patch_bundle` INTEGER NOT NULL, `package_name` TEXT NOT NULL, PRIMARY KEY(`uid`), FOREIGN KEY(`patch_bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchBundle",
"columnName": "patch_bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [
{
"name": "index_patch_selections_patch_bundle_package_name",
"unique": true,
"columnNames": [
"patch_bundle",
"package_name"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_patch_selections_patch_bundle_package_name` ON `${TABLE_NAME}` (`patch_bundle`, `package_name`)"
}
],
"foreignKeys": [
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"patch_bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "selected_patches",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`selection` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, PRIMARY KEY(`selection`, `patch_name`), FOREIGN KEY(`selection`) REFERENCES `patch_selections`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "selection",
"columnName": "selection",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"selection",
"patch_name"
]
},
"foreignKeys": [
{
"table": "patch_selections",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"selection"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "downloaded_app",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `directory` TEXT NOT NULL, `last_used` INTEGER NOT NULL, PRIMARY KEY(`package_name`, `version`))",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "directory",
"columnName": "directory",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastUsed",
"columnName": "last_used",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name",
"version"
]
}
},
{
"tableName": "installed_app",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`current_package_name` TEXT NOT NULL, `original_package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `install_type` TEXT NOT NULL, PRIMARY KEY(`current_package_name`))",
"fields": [
{
"fieldPath": "currentPackageName",
"columnName": "current_package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "originalPackageName",
"columnName": "original_package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "installType",
"columnName": "install_type",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"current_package_name"
]
}
},
{
"tableName": "applied_patch",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `bundle` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, PRIMARY KEY(`package_name`, `bundle`, `patch_name`), FOREIGN KEY(`package_name`) REFERENCES `installed_app`(`current_package_name`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "bundle",
"columnName": "bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name",
"bundle",
"patch_name"
]
},
"indices": [
{
"name": "index_applied_patch_bundle",
"unique": false,
"columnNames": [
"bundle"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_applied_patch_bundle` ON `${TABLE_NAME}` (`bundle`)"
}
],
"foreignKeys": [
{
"table": "installed_app",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"package_name"
],
"referencedColumns": [
"current_package_name"
]
},
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "installed_patch_bundle",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `bundle_uid` INTEGER NOT NULL, `bundle_name` TEXT NOT NULL, `bundle_version` TEXT, PRIMARY KEY(`package_name`, `bundle_uid`), FOREIGN KEY(`package_name`) REFERENCES `installed_app`(`current_package_name`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "bundleUid",
"columnName": "bundle_uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "bundleName",
"columnName": "bundle_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "bundleVersion",
"columnName": "bundle_version",
"affinity": "TEXT"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name",
"bundle_uid"
]
},
"foreignKeys": [
{
"table": "installed_app",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"package_name"
],
"referencedColumns": [
"current_package_name"
]
}
]
},
{
"tableName": "option_groups",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `patch_bundle` INTEGER NOT NULL, `package_name` TEXT NOT NULL, PRIMARY KEY(`uid`), FOREIGN KEY(`patch_bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchBundle",
"columnName": "patch_bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [
{
"name": "index_option_groups_patch_bundle_package_name",
"unique": true,
"columnNames": [
"patch_bundle",
"package_name"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_option_groups_patch_bundle_package_name` ON `${TABLE_NAME}` (`patch_bundle`, `package_name`)"
}
],
"foreignKeys": [
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"patch_bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "options",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`group` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`group`, `patch_name`, `key`), FOREIGN KEY(`group`) REFERENCES `option_groups`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "group",
"columnName": "group",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"group",
"patch_name",
"key"
]
},
"foreignKeys": [
{
"table": "option_groups",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"group"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "trusted_downloaders",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `signature` BLOB NOT NULL, PRIMARY KEY(`package_name`))",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name"
]
}
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd9350f0e779a1bde46227a29884a7865')"
]
}
}

View File

@@ -1,13 +1,15 @@
package app.revanced.manager.data.room
import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import app.revanced.manager.data.room.apps.downloaded.DownloadedAppDao
import app.revanced.manager.data.room.apps.downloaded.DownloadedApp
import app.revanced.manager.data.room.apps.downloaded.DownloadedAppDao
import app.revanced.manager.data.room.apps.installed.AppliedPatch
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.data.room.apps.installed.InstalledAppDao
import app.revanced.manager.data.room.apps.installed.InstalledPatchBundle
import app.revanced.manager.data.room.selection.PatchSelection
import app.revanced.manager.data.room.selection.SelectedPatch
import app.revanced.manager.data.room.selection.SelectionDao
@@ -21,8 +23,9 @@ import app.revanced.manager.data.room.downloader.TrustedDownloaderDao
import kotlin.random.Random
@Database(
entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class, OptionGroup::class, Option::class, TrustedDownloader::class],
version = 1
entities = [PatchBundleEntity::class, PatchSelection::class, SelectedPatch::class, DownloadedApp::class, InstalledApp::class, AppliedPatch::class, InstalledPatchBundle::class, OptionGroup::class, Option::class, TrustedDownloader::class],
version = 2,
autoMigrations = [AutoMigration(from = 1, to = 2)]
)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {

View File

@@ -25,11 +25,20 @@ interface InstalledAppDao {
"patch_name"
) String>>
@Query("SELECT * FROM installed_patch_bundle WHERE package_name = :packageName")
suspend fun getInstalledPatchBundles(packageName: String): List<InstalledPatchBundle>
@Transaction
suspend fun upsertApp(installedApp: InstalledApp, appliedPatches: List<AppliedPatch>) {
suspend fun upsertApp(
installedApp: InstalledApp,
appliedPatches: List<AppliedPatch>,
patchBundles: List<InstalledPatchBundle>
) {
upsertApp(installedApp)
deleteAppliedPatches(installedApp.currentPackageName)
deleteInstalledPatchBundles(installedApp.currentPackageName)
insertAppliedPatches(appliedPatches)
insertInstalledPatchBundles(patchBundles)
}
@Upsert
@@ -38,9 +47,15 @@ interface InstalledAppDao {
@Insert
suspend fun insertAppliedPatches(appliedPatches: List<AppliedPatch>)
@Insert
suspend fun insertInstalledPatchBundles(patchBundles: List<InstalledPatchBundle>)
@Query("DELETE FROM applied_patch WHERE package_name = :packageName")
suspend fun deleteAppliedPatches(packageName: String)
@Query("DELETE FROM installed_patch_bundle WHERE package_name = :packageName")
suspend fun deleteInstalledPatchBundles(packageName: String)
@Delete
suspend fun delete(installedApp: InstalledApp)
}

View File

@@ -0,0 +1,24 @@
package app.revanced.manager.data.room.apps.installed
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
@Entity(
tableName = "installed_patch_bundle",
primaryKeys = ["package_name", "bundle_uid"],
foreignKeys = [
ForeignKey(
InstalledApp::class,
parentColumns = ["current_package_name"],
childColumns = ["package_name"],
onDelete = ForeignKey.CASCADE
)
]
)
data class InstalledPatchBundle(
@ColumnInfo(name = "package_name") val packageName: String,
@ColumnInfo(name = "bundle_uid") val bundleUid: Int,
@ColumnInfo(name = "bundle_name") val bundleName: String,
@ColumnInfo(name = "bundle_version") val bundleVersion: String?
)

View File

@@ -4,6 +4,8 @@ import app.revanced.manager.data.room.AppDatabase
import app.revanced.manager.data.room.apps.installed.AppliedPatch
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.data.room.apps.installed.InstalledPatchBundle
import app.revanced.manager.patcher.patch.PatchBundleInfo
import app.revanced.manager.util.PatchSelection
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -19,12 +21,16 @@ class InstalledAppRepository(
suspend fun getAppliedPatches(packageName: String): PatchSelection =
dao.getPatchesSelection(packageName).mapValues { (_, patches) -> patches.toSet() }
suspend fun getInstalledPatchBundles(packageName: String) =
dao.getInstalledPatchBundles(packageName)
suspend fun addOrUpdate(
currentPackageName: String,
originalPackageName: String,
version: String,
installType: InstallType,
patchSelection: PatchSelection
patchSelection: PatchSelection,
bundleInfo: Map<Int, PatchBundleInfo.Global> = emptyMap()
) {
dao.upsertApp(
InstalledApp(
@@ -41,6 +47,15 @@ class InstalledAppRepository(
patchName = patch
)
}
},
patchSelection.keys.mapNotNull { uid ->
val info = bundleInfo[uid] ?: return@mapNotNull null
InstalledPatchBundle(
packageName = currentPackageName,
bundleUid = uid,
bundleName = info.name,
bundleVersion = info.version
)
}
)
}

View File

@@ -0,0 +1,74 @@
package app.revanced.manager.ui.screen
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ListItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.data.room.apps.installed.InstalledPatchBundle
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.FullscreenDialog
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.util.PatchSelection
import app.revanced.manager.util.transparentListItemColors
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppliedPatchesDialog(
onDismissRequest: () -> Unit,
appliedPatches: PatchSelection?,
patchBundles: List<InstalledPatchBundle>
) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
FullscreenDialog(onDismissRequest = onDismissRequest) {
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.applied_patches),
scrollBehavior = scrollBehavior,
onBackClick = onDismissRequest
)
},
) { paddingValues ->
LazyColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
val patches = appliedPatches ?: return@LazyColumnWithScrollbar
val bundleMap = patchBundles.associateBy { it.bundleUid }
patches.forEach { (bundleUid, patchNames) ->
val bundle = bundleMap[bundleUid]
item(key = "header_$bundleUid") {
ListHeader(title = bundle?.let {
it.bundleVersion?.let { version ->
"${it.bundleName} v$version"
} ?: it.bundleName
} ?: "${stringResource(R.string.patches)} $bundleUid")
}
items(
items = patchNames.sorted(),
key = { "${bundleUid}_$it" }
) { patchName ->
ListItem(
headlineContent = { Text(patchName) },
colors = transparentListItemColors
)
}
}
}
}
}
}

View File

@@ -32,7 +32,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@@ -44,7 +43,6 @@ import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.SegmentedButton
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.InstalledAppInfoViewModel
import app.revanced.manager.util.toast
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -53,19 +51,26 @@ fun InstalledAppInfoScreen(
onBackClick: () -> Unit,
viewModel: InstalledAppInfoViewModel
) {
val context = LocalContext.current
SideEffect {
viewModel.onBackClick = onBackClick
}
var showUninstallDialog by rememberSaveable { mutableStateOf(false) }
var showAppliedPatchesDialog by rememberSaveable { mutableStateOf(false) }
if (showUninstallDialog)
UninstallDialog(
onDismiss = { showUninstallDialog = false },
onConfirm = { viewModel.uninstall() }
)
if (showAppliedPatchesDialog) {
AppliedPatchesDialog(
onDismissRequest = { showAppliedPatchesDialog = false },
appliedPatches = viewModel.appliedPatches,
patchBundles = viewModel.patchBundles
)
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
@@ -152,7 +157,7 @@ fun InstalledAppInfoScreen(
modifier = Modifier.padding(vertical = 16.dp)
) {
SettingsListItem(
modifier = Modifier.clickable { context.toast("Not implemented yet!") },
modifier = Modifier.clickable(onClick = { showAppliedPatchesDialog = true }),
headlineContent = stringResource(R.string.applied_patches),
supportingContent =
(viewModel.appliedPatches?.values?.sumOf { it.size } ?: 0).let {

View File

@@ -0,0 +1,37 @@
package app.revanced.manager.ui.viewmodel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.revanced.manager.data.room.apps.installed.InstalledPatchBundle
import app.revanced.manager.domain.repository.InstalledAppRepository
import app.revanced.manager.util.PatchSelection
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class AppliedPatchesViewModel(
packageName: String
) : ViewModel(), KoinComponent {
private val installedAppRepository: InstalledAppRepository by inject()
var appliedPatches: PatchSelection? by mutableStateOf(null)
private set
var patchBundles: List<InstalledPatchBundle> by mutableStateOf(emptyList())
private set
init {
viewModelScope.launch {
appliedPatches = withContext(Dispatchers.IO) {
installedAppRepository.getAppliedPatches(packageName)
}
patchBundles = withContext(Dispatchers.IO) {
installedAppRepository.getInstalledPatchBundles(packageName)
}
}
}
}

View File

@@ -11,6 +11,7 @@ import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.data.room.apps.installed.InstalledPatchBundle
import app.revanced.manager.domain.installer.RootInstaller
import app.revanced.manager.domain.repository.InstalledAppRepository
import app.revanced.manager.util.PM
@@ -41,6 +42,8 @@ class InstalledAppInfoViewModel(
var appInfo: PackageInfo? by mutableStateOf(null)
private set
var appliedPatches: PatchSelection? by mutableStateOf(null)
var patchBundles: List<InstalledPatchBundle> by mutableStateOf(emptyList())
private set
var isMounted by mutableStateOf(false)
private set
@@ -54,6 +57,9 @@ class InstalledAppInfoViewModel(
appliedPatches = withContext(Dispatchers.IO) {
installedAppRepository.getAppliedPatches(it.currentPackageName)
}
patchBundles = withContext(Dispatchers.IO) {
installedAppRepository.getInstalledPatchBundles(it.currentPackageName)
}
}
}
}

View File

@@ -28,6 +28,7 @@ import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.domain.installer.RootInstaller
import app.revanced.manager.domain.repository.InstalledAppRepository
import app.revanced.manager.domain.repository.PatchBundleRepository
import app.revanced.manager.domain.worker.WorkerRepository
import app.revanced.manager.patcher.ProgressEvent
import app.revanced.manager.patcher.StepId
@@ -59,6 +60,7 @@ import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.time.withTimeout
@@ -88,6 +90,7 @@ class PatcherViewModel(
private val pm: PM by inject()
private val workerRepository: WorkerRepository by inject()
private val installedAppRepository: InstalledAppRepository by inject()
private val patchBundleRepository: PatchBundleRepository by inject()
private val rootInstaller: RootInstaller by inject()
private val savedStateHandle: SavedStateHandle = get()
private val ackpineInstaller: PackageInstaller = get()
@@ -378,13 +381,15 @@ class PatcherViewModel(
Session.State.Succeeded -> {
app.toast(app.getString(R.string.install_app_success))
installedPackageName = installerPkgName
val bundleInfo = patchBundleRepository.bundleInfoFlow.first()
installedAppRepository.addOrUpdate(
installerPkgName,
packageName,
input.selectedApp.version
?: withContext(Dispatchers.IO) { pm.getPackageInfo(outputFile)?.versionName!! },
InstallType.DEFAULT,
input.selectedPatches
input.selectedPatches,
bundleInfo
)
}
}
@@ -457,12 +462,14 @@ class PatcherViewModel(
label
)
val bundleInfo = patchBundleRepository.bundleInfoFlow.first()
installedAppRepository.addOrUpdate(
currentPackageInfo.packageName,
packageName,
inputVersion,
InstallType.MOUNT,
input.selectedPatches
input.selectedPatches,
bundleInfo
)
rootInstaller.mount(packageName)