mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2026-01-11 13:46:17 +00:00
Use selected source in patcher
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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")
|
||||||
|
} }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user