Use selected source in patcher

This commit is contained in:
Robert
2026-01-07 00:42:21 +01:00
parent 0169fd2109
commit 08662b2132
11 changed files with 140 additions and 134 deletions

View File

@@ -37,7 +37,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -84,7 +83,7 @@ class PatchBundleRepository(
.map(PatchInfo::toPatcherPatch) .map(PatchInfo::toPatcherPatch)
}.toSet() }.toSet()
allPatches.mostCommonCompatibleVersions(countUnusedPatches = false)[packageName] allPatches.mostCommonCompatibleVersions(countUnusedPatches = true)[packageName]
} }
val suggestedVersions = bundleInfoFlow.map { val suggestedVersions = bundleInfoFlow.map {

View File

@@ -39,7 +39,7 @@ import app.revanced.manager.patcher.toRemoteError
import app.revanced.manager.plugin.downloader.GetScope import app.revanced.manager.plugin.downloader.GetScope
import app.revanced.manager.plugin.downloader.PluginHostApi import app.revanced.manager.plugin.downloader.PluginHostApi
import app.revanced.manager.plugin.downloader.UserInteractionException import app.revanced.manager.plugin.downloader.UserInteractionException
import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.SelectedSource
import app.revanced.manager.util.Options import app.revanced.manager.util.Options
import app.revanced.manager.util.PM import app.revanced.manager.util.PM
import app.revanced.manager.util.PatchSelection import app.revanced.manager.util.PatchSelection
@@ -67,7 +67,9 @@ class PatcherWorker(
private val rootInstaller: RootInstaller by inject() private val rootInstaller: RootInstaller by inject()
class Args( class Args(
val input: SelectedApp, val packageName: String,
val version: String?,
val source: SelectedSource,
val output: String, val output: String,
val selectedPatches: PatchSelection, val selectedPatches: PatchSelection,
val options: Options, val options: Options,
@@ -75,9 +77,7 @@ class PatcherWorker(
val handleStartActivityRequest: suspend (LoadedDownloaderPlugin, Intent) -> ActivityResult, val handleStartActivityRequest: suspend (LoadedDownloaderPlugin, Intent) -> ActivityResult,
val setInputFile: suspend (File) -> Unit, val setInputFile: suspend (File) -> Unit,
val onEvent: (ProgressEvent) -> Unit, val onEvent: (ProgressEvent) -> Unit,
) { )
val packageName get() = input.packageName
}
override suspend fun getForegroundInfo() = override suspend fun getForegroundInfo() =
ForegroundInfo( ForegroundInfo(
@@ -142,7 +142,7 @@ class PatcherWorker(
val patchedApk = fs.tempDir.resolve("patched.apk") val patchedApk = fs.tempDir.resolve("patched.apk")
return try { return try {
if (args.input is SelectedApp.Installed) { if (args.source is SelectedSource.Installed) {
installedAppRepository.get(args.packageName)?.let { installedAppRepository.get(args.packageName)?.let {
if (it.installType == InstallType.MOUNT) { if (it.installType == InstallType.MOUNT) {
rootInstaller.unmount(args.packageName) rootInstaller.unmount(args.packageName)
@@ -155,7 +155,7 @@ class PatcherWorker(
plugin, plugin,
data, data,
args.packageName, args.packageName,
args.input.version, args.version,
prefs.suggestedVersionSafeguard.get(), prefs.suggestedVersionSafeguard.get(),
!prefs.disablePatchVersionCompatCheck.get(), !prefs.disablePatchVersionCompatCheck.get(),
onDownload = { progress -> onDownload = { progress ->
@@ -169,18 +169,10 @@ class PatcherWorker(
} }
).also { args.setInputFile(it) } ).also { args.setInputFile(it) }
val inputFile = when (val selectedApp = args.input) { val inputFile = when (val source = args.source) {
is SelectedApp.Download -> { is SelectedSource.Auto -> throw Exception("Auto source is not supported in worker.")
runStep(StepId.DownloadAPK, args.onEvent) {
val (plugin, data) = downloaderPluginRepository.unwrapParceledData(
selectedApp.data
)
download(plugin, data) is SelectedSource.Plugin -> {
}
}
is SelectedApp.Search -> {
runStep(StepId.DownloadAPK, args.onEvent) { runStep(StepId.DownloadAPK, args.onEvent) {
downloaderPluginRepository.loadedPluginsFlow.first() downloaderPluginRepository.loadedPluginsFlow.first()
.firstNotNullOfOrNull { plugin -> .firstNotNullOfOrNull { plugin ->
@@ -206,10 +198,10 @@ class PatcherWorker(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
plugin.get( plugin.get(
getScope, getScope,
selectedApp.packageName, args.packageName,
selectedApp.version args.version
) )
}?.takeIf { (_, version) -> selectedApp.version == null || version == selectedApp.version } }?.takeIf { (_, version) -> args.version == null || version == args.version }
} catch (e: UserInteractionException.Activity.NotCompleted) { } catch (e: UserInteractionException.Activity.NotCompleted) {
throw e throw e
} catch (_: UserInteractionException) { } catch (_: UserInteractionException) {
@@ -219,8 +211,9 @@ class PatcherWorker(
} }
} }
is SelectedApp.Local -> selectedApp.file.also { args.setInputFile(it) } is SelectedSource.Downloaded -> File(source.path)
is SelectedApp.Installed -> File(pm.getPackageInfo(selectedApp.packageName)!!.applicationInfo!!.sourceDir)
is SelectedSource.Installed -> File(pm.getPackageInfo(args.packageName)!!.applicationInfo!!.sourceDir)
} }
val runtime = if (prefs.useProcessRuntime.get()) { val runtime = if (prefs.useProcessRuntime.get()) {
@@ -258,9 +251,10 @@ class PatcherWorker(
Result.failure() Result.failure()
} finally { } finally {
patchedApk.delete() patchedApk.delete()
if (args.input is SelectedApp.Local && args.input.temporary) { // TODO
args.input.file.delete() // if (args.source is SelectedApp.Local && args.source.temporary) {
} // args.source.file.delete()
// }
} }
} }

View File

@@ -8,5 +8,5 @@ sealed class SelectedSource : Parcelable {
data object Auto : SelectedSource() data object Auto : SelectedSource()
data object Installed : SelectedSource() data object Installed : SelectedSource()
data class Downloaded(val path: String, val version: String) : SelectedSource() data class Downloaded(val path: String, val version: String) : SelectedSource()
data class Plugin(val plugin: String) : SelectedSource() // TODO data class Plugin(val packageName: String?) : SelectedSource()
} }

View File

@@ -1,7 +1,6 @@
package app.revanced.manager.ui.model.navigation package app.revanced.manager.ui.model.navigation
import android.os.Parcelable import android.os.Parcelable
import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.ui.model.SelectedSource import app.revanced.manager.ui.model.SelectedSource
import app.revanced.manager.ui.model.SelectedVersion import app.revanced.manager.ui.model.SelectedVersion
import app.revanced.manager.util.Options import app.revanced.manager.util.Options
@@ -76,7 +75,9 @@ data object SelectedAppInfo : ComplexParameter<SelectedAppInfo.ViewModelParams>
data object Patcher : ComplexParameter<Patcher.ViewModelParams> { data object Patcher : ComplexParameter<Patcher.ViewModelParams> {
@Parcelize @Parcelize
data class ViewModelParams( data class ViewModelParams(
val selectedApp: SelectedApp, val packageName: String,
val version: String?,
val selectedSource: SelectedSource,
val selectedPatches: PatchSelection, val selectedPatches: PatchSelection,
val options: @RawValue Options val options: @RawValue Options
) : Parcelable ) : Parcelable

View File

@@ -83,12 +83,12 @@ fun AppSelectorScreen(
} }
} }
vm.nonSuggestedVersionDialogSubject?.let { // vm.nonSuggestedVersionDialogSubject?.let {
NonSuggestedVersionDialog( // NonSuggestedVersionDialog(
suggestedVersion = suggestedVersions[it.packageName].orEmpty(), // suggestedVersion = suggestedVersions[it.packageName].orEmpty(),
onDismiss = vm::dismissNonSuggestedVersionDialog // onDismiss = vm::dismissNonSuggestedVersionDialog
) // )
} // }
if (search) if (search)
SearchView( SearchView(

View File

@@ -182,25 +182,22 @@ fun SelectedAppInfoScreen(
PageItem( PageItem(
R.string.apk_source_selector_item, R.string.apk_source_selector_item,
selectedSource.toString(), selectedSource.toString(),
onClick = { onSourceClick(packageName, versionText, selectedSource) }, onClick = { onSourceClick(packageName, resolvedVersion, selectedSource) },
) )
error?.let { // error?.let {
Text( // Text(
stringResource(it.resourceId), // stringResource(it.resourceId),
color = MaterialTheme.colorScheme.error, // color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(horizontal = 16.dp) // modifier = Modifier.padding(horizontal = 16.dp)
) // )
} // }
Column( if (resolvedSource is SelectedSource.Plugin) Column(
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp), modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
val needsInternet = resolvedSource is SelectedSource.Plugin
when { when {
!needsInternet -> {}
!networkConnected -> { !networkConnected -> {
NotificationCard( NotificationCard(
isWarning = true, isWarning = true,
@@ -209,7 +206,6 @@ fun SelectedAppInfoScreen(
onDismiss = null onDismiss = null
) )
} }
networkMetered -> { networkMetered -> {
NotificationCard( NotificationCard(
isWarning = true, isWarning = true,

View File

@@ -1,8 +1,6 @@
package app.revanced.manager.ui.screen package app.revanced.manager.ui.screen
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@@ -16,8 +14,12 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import app.revanced.manager.network.downloader.DownloaderPluginState
import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
import app.revanced.manager.ui.model.SelectedSource import app.revanced.manager.ui.model.SelectedSource
@@ -32,7 +34,10 @@ fun SourceSelectorScreen(
onSave: (source: SelectedSource) -> Unit, onSave: (source: SelectedSource) -> Unit,
viewModel: SourceSelectorViewModel, viewModel: SourceSelectorViewModel,
) { ) {
val context = LocalContext.current
val downloadedApps by viewModel.downloadedApps.collectAsStateWithLifecycle(emptyList()) val downloadedApps by viewModel.downloadedApps.collectAsStateWithLifecycle(emptyList())
val plugins by viewModel.plugins.collectAsStateWithLifecycle(emptyList())
Scaffold( Scaffold(
topBar = { topBar = {
@@ -49,67 +54,72 @@ fun SourceSelectorScreen(
) )
} }
) { paddingValues -> ) { paddingValues ->
Column( LazyColumn (
modifier = Modifier.padding(paddingValues) contentPadding = paddingValues,
) { ) {
SourceOption( item {
isSelected = viewModel.selectedSource == SelectedSource.Auto,
onSelect = { viewModel.selectSource(SelectedSource.Auto) },
headlineContent = { Text("Auto (Recommended)") },
supportingContent = { Text("Automatically select the best available source") }
)
SourceOption(
isSelected = viewModel.selectedSource == SelectedSource.Plugin("any"),
onSelect = { viewModel.selectSource(SelectedSource.Plugin("any")) },
headlineContent = { Text("Any available downloader") },
)
viewModel.installedVersion?.let { installedVersion ->
HorizontalDivider()
SourceOption( SourceOption(
isSelected = viewModel.selectedSource == SelectedSource.Installed, isSelected = viewModel.selectedSource == SelectedSource.Auto,
onSelect = { viewModel.selectSource(SelectedSource.Installed) }, onSelect = { viewModel.selectSource(SelectedSource.Auto) },
headlineContent = { Text(installedVersion) }, headlineContent = { Text("Auto (Recommended)") },
overlineContent = { Text("Installed") }, supportingContent = { Text("Automatically select the best available source") }
enabled = viewModel.input.version?.let { it == installedVersion } ?: true )
}
item {
SourceOption(
isSelected = viewModel.selectedSource == SelectedSource.Plugin(null),
onSelect = { viewModel.selectSource(SelectedSource.Plugin(null)) },
headlineContent = { Text("Any available downloader") },
) )
} }
if (downloadedApps.isNotEmpty()) { viewModel.installedVersion?.let { installedVersion ->
HorizontalDivider() item {
HorizontalDivider()
LazyColumn { SourceOption(
items(downloadedApps, key = { it.version }) { app -> isSelected = viewModel.selectedSource == SelectedSource.Installed,
SourceOption( onSelect = { viewModel.selectSource(SelectedSource.Installed) },
isSelected = (viewModel.selectedSource as? SelectedSource.Downloaded)?.version == app.version, headlineContent = { Text(installedVersion) },
onSelect = { viewModel.selectDownloadedApp(app) }, overlineContent = { Text("Installed") },
headlineContent = { Text(app.version) }, enabled = viewModel.input.version?.let { it == installedVersion } ?: true
overlineContent = { Text("Downloaded") }, )
)
}
} }
} }
HorizontalDivider() if (downloadedApps.isNotEmpty()) item { HorizontalDivider() }
SourceOption( items(downloadedApps, key = { it.version }) { app ->
isSelected = viewModel.selectedSource == SelectedSource.Plugin("plugin-id"), SourceOption(
onSelect = { viewModel.selectSource(SelectedSource.Plugin("plugin-id")) }, isSelected = (viewModel.selectedSource as? SelectedSource.Downloaded)?.version == app.version,
headlineContent = { Text("APKMirror Downloader") }, onSelect = { viewModel.selectDownloadedApp(app) },
overlineContent = { Text("Plugin") }, headlineContent = { Text(app.version) },
) overlineContent = { Text("Downloaded") },
)
}
SourceOption( if (plugins.isNotEmpty()) item { HorizontalDivider() }
isSelected = viewModel.selectedSource == SelectedSource.Plugin("another-plugin-id"),
onSelect = { viewModel.selectSource(SelectedSource.Plugin("another-plugin-id")) },
headlineContent = { Text("Another Plugin") },
overlineContent = { Text("Plugin") },
supportingContent = { Text("Untrusted") },
enabled = false,
)
items(plugins, key = { it.first }) {
val packageInfo = remember {
viewModel.getPackageInfo(it.first)
}
val label = remember {
packageInfo?.applicationInfo?.loadLabel(context.packageManager).toString()
}
SourceOption(
isSelected = viewModel.selectedSource == SelectedSource.Plugin(it.first),
onSelect = { viewModel.selectSource(SelectedSource.Plugin(it.first)) },
headlineContent = { Text(label, maxLines = 1, overflow = TextOverflow.Ellipsis) },
overlineContent = { Text("Plugin") },
enabled = it.second is DownloaderPluginState.Loaded,
supportingContent = (it.second as? DownloaderPluginState.Untrusted)?.let { {
Text("Not trusted")
} }
)
}
} }
} }
} }

View File

@@ -3,9 +3,6 @@ package app.revanced.manager.ui.viewmodel
import android.app.Application import android.app.Application
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.net.Uri import android.net.Uri
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -14,7 +11,6 @@ import androidx.lifecycle.viewmodel.compose.saveable
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.data.platform.Filesystem import app.revanced.manager.data.platform.Filesystem
import app.revanced.manager.domain.repository.PatchBundleRepository import app.revanced.manager.domain.repository.PatchBundleRepository
import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.util.PM import app.revanced.manager.util.PM
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -47,14 +43,14 @@ class AppSelectorViewModel(
val suggestedAppVersions = patchBundleRepository.suggestedVersions.flowOn(Dispatchers.Default) val suggestedAppVersions = patchBundleRepository.suggestedVersions.flowOn(Dispatchers.Default)
var nonSuggestedVersionDialogSubject by mutableStateOf<SelectedApp.Local?>(null) // var nonSuggestedVersionDialogSubject by mutableStateOf<SelectedApp.Local?>(null)
private set // private set
fun loadLabel(app: PackageInfo?) = with(pm) { app?.label() ?: "Not installed" } fun loadLabel(app: PackageInfo?) = with(pm) { app?.label() ?: "Not installed" }
fun dismissNonSuggestedVersionDialog() { // fun dismissNonSuggestedVersionDialog() {
nonSuggestedVersionDialogSubject = null // nonSuggestedVersionDialogSubject = null
} // }
fun handleStorageResult(uri: Uri) = viewModelScope.launch { fun handleStorageResult(uri: Uri) = viewModelScope.launch {
val selectedApp = withContext(Dispatchers.IO) { val selectedApp = withContext(Dispatchers.IO) {

View File

@@ -37,7 +37,7 @@ import app.revanced.manager.patcher.worker.PatcherWorker
import app.revanced.manager.plugin.downloader.PluginHostApi import app.revanced.manager.plugin.downloader.PluginHostApi
import app.revanced.manager.plugin.downloader.UserInteractionException import app.revanced.manager.plugin.downloader.UserInteractionException
import app.revanced.manager.ui.model.InstallerModel import app.revanced.manager.ui.model.InstallerModel
import app.revanced.manager.ui.model.SelectedApp import app.revanced.manager.ui.model.SelectedSource
import app.revanced.manager.ui.model.State import app.revanced.manager.ui.model.State
import app.revanced.manager.ui.model.StepCategory import app.revanced.manager.ui.model.StepCategory
import app.revanced.manager.ui.model.Step import app.revanced.manager.ui.model.Step
@@ -93,9 +93,8 @@ class PatcherViewModel(
private val ackpineInstaller: PackageInstaller = get() private val ackpineInstaller: PackageInstaller = get()
private var installedApp: InstalledApp? = null private var installedApp: InstalledApp? = null
private val selectedApp = input.selectedApp val packageName = input.packageName
val packageName = selectedApp.packageName val version = input.version
val version = selectedApp.version
var installedPackageName by savedStateHandle.saveable( var installedPackageName by savedStateHandle.saveable(
key = "installedPackageName", key = "installedPackageName",
@@ -160,7 +159,7 @@ class PatcherViewModel(
} }
val steps by savedStateHandle.saveable(saver = snapshotStateListSaver()) { val steps by savedStateHandle.saveable(saver = snapshotStateListSaver()) {
generateSteps(app, input.selectedApp, input.selectedPatches).toMutableStateList() generateSteps(app, input.selectedSource, input.selectedPatches).toMutableStateList()
} }
val progress by derivedStateOf { val progress by derivedStateOf {
@@ -178,7 +177,9 @@ class PatcherViewModel(
ParcelUuid( ParcelUuid(
workerRepository.launchExpedited<PatcherWorker, PatcherWorker.Args>( workerRepository.launchExpedited<PatcherWorker, PatcherWorker.Args>(
"patching", PatcherWorker.Args( "patching", PatcherWorker.Args(
input.selectedApp, input.packageName,
input.version,
input.selectedSource,
outputFile.path, outputFile.path,
input.selectedPatches, input.selectedPatches,
input.options, input.options,
@@ -257,7 +258,7 @@ class PatcherViewModel(
super.onCleared() super.onCleared()
workManager.cancelWorkById(patcherWorkerId.uuid) workManager.cancelWorkById(patcherWorkerId.uuid)
if (input.selectedApp is SelectedApp.Installed && installedApp?.installType == InstallType.MOUNT) { if (input.selectedSource is SelectedSource.Installed && installedApp?.installType == InstallType.MOUNT) {
GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) {
uiSafe(app, R.string.failed_to_mount, "Failed to mount") { uiSafe(app, R.string.failed_to_mount, "Failed to mount") {
withTimeout(Duration.ofMinutes(1L)) { withTimeout(Duration.ofMinutes(1L)) {
@@ -381,7 +382,7 @@ class PatcherViewModel(
installedAppRepository.addOrUpdate( installedAppRepository.addOrUpdate(
installerPkgName, installerPkgName,
packageName, packageName,
input.selectedApp.version input.version
?: withContext(Dispatchers.IO) { pm.getPackageInfo(outputFile)?.versionName!! }, ?: withContext(Dispatchers.IO) { pm.getPackageInfo(outputFile)?.versionName!! },
InstallType.DEFAULT, InstallType.DEFAULT,
input.selectedPatches input.selectedPatches
@@ -443,7 +444,7 @@ class PatcherViewModel(
} }
} }
val inputVersion = input.selectedApp.version val inputVersion = input.version
?: withContext(Dispatchers.IO) { inputFile?.let(pm::getPackageInfo)?.versionName } ?: withContext(Dispatchers.IO) { inputFile?.let(pm::getPackageInfo)?.versionName }
?: throw Exception("Failed to determine input APK version") ?: throw Exception("Failed to determine input APK version")
@@ -535,10 +536,10 @@ class PatcherViewModel(
fun generateSteps( fun generateSteps(
context: Context, context: Context,
selectedApp: SelectedApp, selectedSource: SelectedSource,
selectedPatches: PatchSelection selectedPatches: PatchSelection
): List<Step> = buildList { ): List<Step> = buildList {
if (selectedApp is SelectedApp.Download || selectedApp is SelectedApp.Search) if (selectedSource is SelectedSource.Plugin)
add( add(
Step( Step(
StepId.DownloadAPK, StepId.DownloadAPK,

View File

@@ -14,7 +14,6 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi
import androidx.lifecycle.viewmodel.compose.saveable import androidx.lifecycle.viewmodel.compose.saveable
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.domain.manager.PreferencesManager import app.revanced.manager.domain.manager.PreferencesManager
import app.revanced.manager.domain.repository.DownloaderPluginRepository import app.revanced.manager.domain.repository.DownloaderPluginRepository
import app.revanced.manager.domain.repository.InstalledAppRepository import app.revanced.manager.domain.repository.InstalledAppRepository
@@ -25,7 +24,6 @@ import app.revanced.manager.patcher.patch.PatchBundleInfo
import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.requiredOptionsSet import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.requiredOptionsSet
import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.toPatchSelection import app.revanced.manager.patcher.patch.PatchBundleInfo.Extensions.toPatchSelection
import app.revanced.manager.plugin.downloader.PluginHostApi import app.revanced.manager.plugin.downloader.PluginHostApi
import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.ui.model.SelectedSource import app.revanced.manager.ui.model.SelectedSource
import app.revanced.manager.ui.model.SelectedVersion import app.revanced.manager.ui.model.SelectedVersion
import app.revanced.manager.ui.model.navigation.Patcher import app.revanced.manager.ui.model.navigation.Patcher
@@ -201,8 +199,8 @@ class SelectedAppInfoViewModel(
var installedAppData: Pair<SelectedApp.Installed, InstalledApp?>? by mutableStateOf(null) // var installedAppData: Pair<SelectedApp.Installed, InstalledApp?>? by mutableStateOf(null)
private set // private set
private var _selectedApp by savedStateHandle.saveable { private var _selectedApp by savedStateHandle.saveable {
mutableStateOf(null) mutableStateOf(null)
@@ -229,7 +227,7 @@ class SelectedAppInfoViewModel(
val errorFlow = combine(plugins, snapshotFlow { selectedApp }) { pluginsList, app -> val errorFlow = combine(plugins, snapshotFlow { selectedApp }) { pluginsList, app ->
when { when {
app is SelectedApp.Search && pluginsList.isEmpty() -> Error.NoPlugins // app is SelectedApp.Search && pluginsList.isEmpty() -> Error.NoPlugins
else -> null else -> null
} }
} }
@@ -253,7 +251,9 @@ class SelectedAppInfoViewModel(
val allowIncompatible = prefs.disablePatchVersionCompatCheck.get() val allowIncompatible = prefs.disablePatchVersionCompatCheck.get()
val bundles = bundleInfoFlow.first() val bundles = bundleInfoFlow.first()
return Patcher.ViewModelParams( return Patcher.ViewModelParams(
SelectedApp.Installed(packageName, version = "123"), // TODO input.packageName,
resolvedVersion.first(),
resolvedSource.first(),
patchSelection.first(), patchSelection.first(),
getOptionsFiltered(bundles) getOptionsFiltered(bundles)
) )
@@ -287,13 +287,13 @@ class SelectedAppInfoViewModel(
val installedAppDeferred = val installedAppDeferred =
async(Dispatchers.IO) { installedAppRepository.get(packageName) } async(Dispatchers.IO) { installedAppRepository.get(packageName) }
installedAppData = // installedAppData =
packageInfo.await()?.let { // packageInfo.await()?.let {
SelectedApp.Installed( // SelectedApp.Installed(
packageName, // packageName,
it.versionName!! // it.versionName!!
) to installedAppDeferred.await() // ) to installedAppDeferred.await()
} // }
} }
} }

View File

@@ -7,6 +7,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import app.revanced.manager.data.room.apps.downloaded.DownloadedApp import app.revanced.manager.data.room.apps.downloaded.DownloadedApp
import app.revanced.manager.domain.repository.DownloadedAppRepository import app.revanced.manager.domain.repository.DownloadedAppRepository
import app.revanced.manager.domain.repository.DownloaderPluginRepository
import app.revanced.manager.network.downloader.DownloaderPluginState
import app.revanced.manager.ui.model.SelectedSource import app.revanced.manager.ui.model.SelectedSource
import app.revanced.manager.ui.model.navigation.SelectedAppInfo import app.revanced.manager.ui.model.navigation.SelectedAppInfo
import app.revanced.manager.util.PM import app.revanced.manager.util.PM
@@ -19,11 +21,18 @@ class SourceSelectorViewModel(
val input: SelectedAppInfo.SourceSelector.ViewModelParams val input: SelectedAppInfo.SourceSelector.ViewModelParams
) : ViewModel(), KoinComponent { ) : ViewModel(), KoinComponent {
private val downloadedAppRepository: DownloadedAppRepository = get() private val downloadedAppRepository: DownloadedAppRepository = get()
private val pluginRepository: DownloaderPluginRepository = get()
private val pm: PM = get() private val pm: PM = get()
val downloadedApps = downloadedAppRepository.get(input.packageName) val downloadedApps = downloadedAppRepository.get(input.packageName)
.map { it.sortedByDescending { app -> app.version } } .map { it.sortedByDescending { app -> app.version } }
val plugins = pluginRepository.pluginStates.map { plugins ->
plugins.toList().sortedByDescending { it.second is DownloaderPluginState.Loaded }
}
fun getPackageInfo(packageName: String) = pm.getPackageInfo(packageName)
var selectedSource by mutableStateOf(input.selectedSource) var selectedSource by mutableStateOf(input.selectedSource)
private set private set