mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2026-01-11 05:36:17 +00:00
Show selected source in overview
This commit is contained in:
@@ -158,7 +158,7 @@ class PatcherWorker(
|
||||
args.version,
|
||||
prefs.suggestedVersionSafeguard.get(),
|
||||
!prefs.disablePatchVersionCompatCheck.get(),
|
||||
onDownload = { progress ->
|
||||
) { progress ->
|
||||
args.onEvent(
|
||||
ProgressEvent.Progress(
|
||||
stepId = StepId.DownloadAPK,
|
||||
@@ -166,8 +166,7 @@ class PatcherWorker(
|
||||
total = progress.second
|
||||
)
|
||||
)
|
||||
}
|
||||
).also { args.setInputFile(it) }
|
||||
}.also { args.setInputFile(it) }
|
||||
|
||||
val inputFile = when (val source = args.source) {
|
||||
is SelectedSource.Auto -> throw Exception("Auto source is not supported in worker.")
|
||||
@@ -212,6 +211,7 @@ class PatcherWorker(
|
||||
}
|
||||
|
||||
is SelectedSource.Downloaded -> File(source.path)
|
||||
is SelectedSource.Local -> File(source.path)
|
||||
|
||||
is SelectedSource.Installed -> File(pm.getPackageInfo(args.packageName)!!.applicationInfo!!.sourceDir)
|
||||
}
|
||||
@@ -251,10 +251,7 @@ class PatcherWorker(
|
||||
Result.failure()
|
||||
} finally {
|
||||
patchedApk.delete()
|
||||
// TODO
|
||||
// if (args.source is SelectedApp.Local && args.source.temporary) {
|
||||
// args.source.file.delete()
|
||||
// }
|
||||
if (args.source is SelectedSource.Local) File(args.source.path).delete()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package app.revanced.manager.ui.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import app.revanced.manager.network.downloader.ParceledDownloaderData
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.io.File
|
||||
|
||||
sealed interface SelectedApp : Parcelable {
|
||||
val packageName: String
|
||||
val version: String?
|
||||
|
||||
@Parcelize
|
||||
data class Download(
|
||||
override val packageName: String,
|
||||
override val version: String?,
|
||||
val data: ParceledDownloaderData
|
||||
) : SelectedApp
|
||||
|
||||
@Parcelize
|
||||
data class Search(override val packageName: String, override val version: String?) : SelectedApp
|
||||
|
||||
@Parcelize
|
||||
data class Local(
|
||||
override val packageName: String,
|
||||
override val version: String,
|
||||
val file: File,
|
||||
val temporary: Boolean
|
||||
) : SelectedApp
|
||||
|
||||
@Parcelize
|
||||
data class Installed(
|
||||
override val packageName: String,
|
||||
override val version: String
|
||||
) : SelectedApp
|
||||
}
|
||||
@@ -8,5 +8,6 @@ sealed class SelectedSource : Parcelable {
|
||||
data object Auto : SelectedSource()
|
||||
data object Installed : SelectedSource()
|
||||
data class Downloaded(val path: String, val version: String) : SelectedSource()
|
||||
data class Local(val path: String) : SelectedSource()
|
||||
data class Plugin(val packageName: String?) : SelectedSource()
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -80,7 +81,6 @@ fun SelectedAppInfoScreen(
|
||||
val incompatibleCount by vm.incompatiblePatchCount.collectAsStateWithLifecycle(0)
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
val plugins by vm.plugins.collectAsStateWithLifecycle(emptyList())
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -150,17 +150,15 @@ fun SelectedAppInfoScreen(
|
||||
customSelection,
|
||||
vm.options
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
if (incompatibleCount > 0) {
|
||||
},
|
||||
extraDescription = if (incompatibleCount > 0) { {
|
||||
Text(
|
||||
"$incompatibleCount incompatible",
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
} } else null,
|
||||
)
|
||||
|
||||
val versionText = resolvedVersion ?: "Any available version"
|
||||
val versionDescription = if (selectedVersion is SelectedVersion.Auto)
|
||||
@@ -179,19 +177,32 @@ fun SelectedAppInfoScreen(
|
||||
},
|
||||
)
|
||||
|
||||
val sourceText = when (val source = resolvedSource) {
|
||||
is SelectedSource.Installed -> "Installed APK"
|
||||
is SelectedSource.Downloaded -> "Downloaded APK"
|
||||
is SelectedSource.Local -> "Local APK"
|
||||
is SelectedSource.Plugin -> {
|
||||
source.packageName ?: "Any available downloader"
|
||||
}
|
||||
else -> "Auto"
|
||||
}
|
||||
val sourceDescription = if (selectedSource is SelectedSource.Auto)
|
||||
"Auto ($sourceText)" // stringResource(R.string.selected_app_meta_auto_version, actualVersion)
|
||||
else sourceText
|
||||
|
||||
PageItem(
|
||||
R.string.apk_source_selector_item,
|
||||
selectedSource.toString(),
|
||||
sourceDescription,
|
||||
onClick = { onSourceClick(packageName, resolvedVersion, selectedSource) },
|
||||
)
|
||||
|
||||
// error?.let {
|
||||
// Text(
|
||||
// stringResource(it.resourceId),
|
||||
// color = MaterialTheme.colorScheme.error,
|
||||
// modifier = Modifier.padding(horizontal = 16.dp)
|
||||
// )
|
||||
// }
|
||||
error?.let {
|
||||
Text(
|
||||
stringResource(it.resourceId),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
if (resolvedSource is SelectedSource.Plugin) Column(
|
||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
|
||||
@@ -225,7 +236,8 @@ private fun PageItem(
|
||||
@StringRes title: Int,
|
||||
description: String,
|
||||
onClick: () -> Unit,
|
||||
enabled: Boolean = true
|
||||
enabled: Boolean = true,
|
||||
extraDescription: @Composable (ColumnScope.() -> Unit)? = null,
|
||||
) {
|
||||
ListItem(
|
||||
modifier = Modifier
|
||||
@@ -239,11 +251,14 @@ private fun PageItem(
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
Column {
|
||||
Text(
|
||||
description,
|
||||
color = MaterialTheme.colorScheme.outline,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
extraDescription?.invoke(this)
|
||||
}
|
||||
},
|
||||
trailingContent = {
|
||||
Icon(Icons.AutoMirrored.Outlined.ArrowRight, null)
|
||||
|
||||
@@ -39,6 +39,9 @@ fun SourceSelectorScreen(
|
||||
val downloadedApps by viewModel.downloadedApps.collectAsStateWithLifecycle(emptyList())
|
||||
val plugins by viewModel.plugins.collectAsStateWithLifecycle(emptyList())
|
||||
|
||||
val version = viewModel.input.version
|
||||
fun matchesVersion(appVersion: String) = version == null || version == appVersion
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
AppTopBar(
|
||||
@@ -82,7 +85,7 @@ fun SourceSelectorScreen(
|
||||
onSelect = { viewModel.selectSource(SelectedSource.Installed) },
|
||||
headlineContent = { Text(installedVersion) },
|
||||
overlineContent = { Text("Installed") },
|
||||
enabled = viewModel.input.version?.let { it == installedVersion } ?: true
|
||||
enabled = matchesVersion(installedVersion)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -95,6 +98,7 @@ fun SourceSelectorScreen(
|
||||
onSelect = { viewModel.selectDownloadedApp(app) },
|
||||
headlineContent = { Text(app.version) },
|
||||
overlineContent = { Text("Downloaded") },
|
||||
enabled = matchesVersion(app.version)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.lifecycle.viewmodel.compose.SavedStateHandleSaveableApi
|
||||
import androidx.lifecycle.viewmodel.compose.saveable
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.domain.manager.PreferencesManager
|
||||
import app.revanced.manager.domain.repository.DownloadedAppRepository
|
||||
import app.revanced.manager.domain.repository.DownloaderPluginRepository
|
||||
import app.revanced.manager.domain.repository.InstalledAppRepository
|
||||
import app.revanced.manager.domain.repository.PatchBundleRepository
|
||||
@@ -49,13 +50,14 @@ import org.koin.core.component.get
|
||||
|
||||
@OptIn(SavedStateHandleSaveableApi::class, PluginHostApi::class)
|
||||
class SelectedAppInfoViewModel(
|
||||
val input: SelectedAppInfo.ViewModelParams
|
||||
private val input: SelectedAppInfo.ViewModelParams
|
||||
) : ViewModel(), KoinComponent {
|
||||
private val bundleRepository: PatchBundleRepository = get()
|
||||
private val selectionRepository: PatchSelectionRepository = get()
|
||||
private val optionsRepository: PatchOptionsRepository = get()
|
||||
private val pluginsRepository: DownloaderPluginRepository = get()
|
||||
private val installedAppRepository: InstalledAppRepository = get()
|
||||
private val downloadedAppRepository: DownloadedAppRepository = get()
|
||||
private val pm: PM = get()
|
||||
private val savedStateHandle: SavedStateHandle = get()
|
||||
private val prefs: PreferencesManager = get()
|
||||
@@ -101,16 +103,8 @@ class SelectedAppInfoViewModel(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// All patches for package
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val bundles = _selectedVersion.flatMapLatest { selectedVersion ->
|
||||
val version = if (selectedVersion is SelectedVersion.Specific)
|
||||
selectedVersion.version
|
||||
else null
|
||||
bundleRepository.scopedBundleInfoFlow(packageName, version)
|
||||
}
|
||||
val bundles = bundleRepository.scopedBundleInfoFlow(packageName, null)
|
||||
|
||||
// Selection derived from selectionFlow
|
||||
val patchSelection = combine(
|
||||
@@ -163,19 +157,28 @@ class SelectedAppInfoViewModel(
|
||||
}
|
||||
|
||||
// Resolve actual source from user selection
|
||||
val resolvedSource = _selectedSource.map { source ->
|
||||
// TODO
|
||||
// when (source) {
|
||||
// is SelectedSource.Auto -> null
|
||||
// is SelectedSource.Installed -> null
|
||||
// is SelectedSource.Downloaded -> null
|
||||
// is SelectedSource.Plugin -> null
|
||||
// }
|
||||
|
||||
source
|
||||
val resolvedSource = combine(
|
||||
_selectedSource,
|
||||
resolvedVersion
|
||||
) { source, version ->
|
||||
when (source) {
|
||||
is SelectedSource.Installed -> source
|
||||
is SelectedSource.Local -> source
|
||||
is SelectedSource.Downloaded -> source
|
||||
is SelectedSource.Plugin -> source
|
||||
is SelectedSource.Auto -> {
|
||||
val app = version?.let {
|
||||
downloadedAppRepository.get(packageName, it)
|
||||
}
|
||||
val file = app?.let {
|
||||
downloadedAppRepository.getApkFileForApp(it)
|
||||
}
|
||||
|
||||
|
||||
file?.let { SelectedSource.Downloaded(it.path, version) }
|
||||
?: SelectedSource.Plugin(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bundleInfoFlow by derivedStateOf {
|
||||
bundleRepository.scopedBundleInfoFlow(packageName, null)
|
||||
@@ -197,6 +200,16 @@ class SelectedAppInfoViewModel(
|
||||
private set
|
||||
|
||||
|
||||
val errorFlow = combine(
|
||||
plugins,
|
||||
resolvedSource,
|
||||
) { pluginsList, source ->
|
||||
when {
|
||||
source is SelectedSource.Plugin && pluginsList.isEmpty() -> Error.NoPlugins
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// var installedAppData: Pair<SelectedApp.Installed, InstalledApp?>? by mutableStateOf(null)
|
||||
@@ -219,20 +232,6 @@ class SelectedAppInfoViewModel(
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: Remove
|
||||
private var oldSelectionState: SelectionState by savedStateHandle.saveable { mutableStateOf(SelectionState.Default) }
|
||||
|
||||
val errorFlow = combine(plugins, snapshotFlow { selectedApp }) { pluginsList, app ->
|
||||
when {
|
||||
// app is SelectedApp.Search && pluginsList.isEmpty() -> Error.NoPlugins
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Load from local file or downloaded app
|
||||
private fun invalidateSelectedAppInfo() = viewModelScope.launch {
|
||||
selectedAppInfo = pm.getPackageInfo(packageName)
|
||||
@@ -259,16 +258,6 @@ class SelectedAppInfoViewModel(
|
||||
)
|
||||
}
|
||||
|
||||
fun getPatches(bundles: List<PatchBundleInfo.Scoped>, allowIncompatible: Boolean) =
|
||||
oldSelectionState.patches(bundles, allowIncompatible)
|
||||
|
||||
fun getCustomPatches(
|
||||
bundles: List<PatchBundleInfo.Scoped>,
|
||||
allowIncompatible: Boolean
|
||||
): PatchSelection? =
|
||||
(oldSelectionState as? SelectionState.Customized)?.patches(bundles, allowIncompatible)
|
||||
|
||||
|
||||
init {
|
||||
invalidateSelectedAppInfo()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user