mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-04-30 05:54:26 +02:00
start implementing new UI and API changes (WIP)
This commit is contained in:
parent
29c849b6a1
commit
770e35bfe4
@ -112,8 +112,6 @@ dependencies {
|
|||||||
implementation(libs.runtime.compose)
|
implementation(libs.runtime.compose)
|
||||||
implementation(libs.splash.screen)
|
implementation(libs.splash.screen)
|
||||||
implementation(libs.compose.activity)
|
implementation(libs.compose.activity)
|
||||||
implementation(libs.paging.common.ktx)
|
|
||||||
implementation(libs.paging.compose)
|
|
||||||
implementation(libs.work.runtime.ktx)
|
implementation(libs.work.runtime.ktx)
|
||||||
implementation(libs.preferences.datastore)
|
implementation(libs.preferences.datastore)
|
||||||
|
|
||||||
|
@ -98,10 +98,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
is Destination.AppSelector -> AppSelectorScreen(
|
is Destination.AppSelector -> AppSelectorScreen(
|
||||||
// onAppClick = { navController.navigate(Destination.VersionSelector(it)) },
|
// onAppClick = { navController.navigate(Destination.VersionSelector(it)) },
|
||||||
|
// TODO: complete this feature
|
||||||
onAppClick = { packageName, version ->
|
onAppClick = { packageName, version ->
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
Destination.SelectedApplicationInfo(
|
Destination.SelectedApplicationInfo(
|
||||||
SelectedApp.Downloadable(packageName, version.orEmpty())
|
SelectedApp.Search(packageName, version)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,7 @@ class DownloadedAppRepository(app: Application, db: AppDatabase) {
|
|||||||
suspend fun download(
|
suspend fun download(
|
||||||
plugin: LoadedDownloaderPlugin,
|
plugin: LoadedDownloaderPlugin,
|
||||||
app: App,
|
app: App,
|
||||||
onDownload: suspend (downloadProgress: Pair<Float, Float?>) -> Unit,
|
onDownload: suspend (downloadProgress: Pair<Double, Double?>) -> Unit,
|
||||||
): File {
|
): File {
|
||||||
this.get(app.packageName, app.version)?.let { downloaded ->
|
this.get(app.packageName, app.version)?.let { downloaded ->
|
||||||
return getApkFileForApp(downloaded)
|
return getApkFileForApp(downloaded)
|
||||||
@ -37,10 +37,10 @@ class DownloadedAppRepository(app: Application, db: AppDatabase) {
|
|||||||
try {
|
try {
|
||||||
val scope = object : DownloadScope {
|
val scope = object : DownloadScope {
|
||||||
override val targetFile = targetFile
|
override val targetFile = targetFile
|
||||||
override suspend fun reportProgress(bytesReceived: Int, bytesTotal: Int?) {
|
override suspend fun reportProgress(bytesReceived: Long, bytesTotal: Long?) {
|
||||||
require(bytesReceived >= 0) { "bytesReceived must not be negative" }
|
require(bytesReceived >= 0) { "bytesReceived must not be negative" }
|
||||||
require(bytesTotal == null || bytesTotal >= bytesReceived) { "bytesTotal must be greater than or equal to bytesReceived" }
|
require(bytesTotal == null || bytesTotal >= bytesReceived) { "bytesTotal must be greater than or equal to bytesReceived" }
|
||||||
require(bytesTotal != 0) { "bytesTotal must not be zero" }
|
require(bytesTotal != 0L) { "bytesTotal must not be zero" }
|
||||||
|
|
||||||
onDownload(bytesReceived.megaBytes to bytesTotal?.megaBytes)
|
onDownload(bytesReceived.megaBytes to bytesTotal?.megaBytes)
|
||||||
}
|
}
|
||||||
@ -77,6 +77,6 @@ class DownloadedAppRepository(app: Application, db: AppDatabase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val Int.megaBytes get() = div(100000).toFloat() / 10
|
val Long.megaBytes get() = toDouble() / 1_000_000
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,6 @@ import android.content.pm.PackageInfo
|
|||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.Signature
|
import android.content.pm.Signature
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import app.revanced.manager.data.platform.Filesystem
|
|
||||||
import app.revanced.manager.data.room.AppDatabase
|
import app.revanced.manager.data.room.AppDatabase
|
||||||
import app.revanced.manager.data.room.plugins.TrustedDownloaderPlugin
|
import app.revanced.manager.data.room.plugins.TrustedDownloaderPlugin
|
||||||
import app.revanced.manager.domain.manager.PreferencesManager
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
@ -26,12 +25,10 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
class DownloaderPluginRepository(
|
class DownloaderPluginRepository(
|
||||||
private val pm: PM,
|
private val pm: PM,
|
||||||
private val fs: Filesystem,
|
|
||||||
private val prefs: PreferencesManager,
|
private val prefs: PreferencesManager,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
db: AppDatabase
|
db: AppDatabase
|
||||||
@ -92,9 +89,11 @@ class DownloaderPluginRepository(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val downloaderContext = DownloaderContext(
|
val downloaderContext = DownloaderContext(
|
||||||
androidContext = context,
|
androidContext = context.createPackageContext(
|
||||||
tempDirectory = fs.tempDir.resolve("dl_plugin_${packageInfo.packageName}")
|
packageInfo.packageName,
|
||||||
.also(File::mkdir)
|
0
|
||||||
|
),
|
||||||
|
pluginHostPackageName = context.packageName
|
||||||
)
|
)
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package app.revanced.manager.network.downloader
|
package app.revanced.manager.network.downloader
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import app.revanced.manager.plugin.downloader.App
|
import app.revanced.manager.plugin.downloader.App
|
||||||
import app.revanced.manager.plugin.downloader.DownloadScope
|
import app.revanced.manager.plugin.downloader.DownloadScope
|
||||||
import app.revanced.manager.plugin.downloader.GetScope
|
import app.revanced.manager.plugin.downloader.GetScope
|
||||||
|
@ -28,15 +28,14 @@ data class PatchInfo(
|
|||||||
fun compatibleWith(packageName: String) =
|
fun compatibleWith(packageName: String) =
|
||||||
compatiblePackages?.any { it.packageName == packageName } ?: true
|
compatiblePackages?.any { it.packageName == packageName } ?: true
|
||||||
|
|
||||||
fun supportsVersion(packageName: String, versionName: String): Boolean {
|
fun supports(packageName: String, versionName: String?): Boolean {
|
||||||
val packages = compatiblePackages ?: return true // Universal patch
|
val packages = compatiblePackages ?: return true // Universal patch
|
||||||
|
|
||||||
return packages.any { pkg ->
|
return packages.any { pkg ->
|
||||||
if (pkg.packageName != packageName) {
|
if (pkg.packageName != packageName) return@any false
|
||||||
return@any false
|
if (pkg.versions == null) return@any true
|
||||||
}
|
|
||||||
|
|
||||||
pkg.versions == null || pkg.versions.contains(versionName)
|
versionName != null && versionName in pkg.versions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class PatcherWorker(
|
|||||||
val selectedPatches: PatchSelection,
|
val selectedPatches: PatchSelection,
|
||||||
val options: Options,
|
val options: Options,
|
||||||
val logger: Logger,
|
val logger: Logger,
|
||||||
val downloadProgress: MutableStateFlow<Pair<Float, Float?>?>,
|
val downloadProgress: MutableStateFlow<Pair<Double, Double?>?>,
|
||||||
val patchesProgress: MutableStateFlow<Pair<Int, Int>>,
|
val patchesProgress: MutableStateFlow<Pair<Int, Int>>,
|
||||||
val handleUserInteractionRequest: suspend () -> ActivityLaunchPermit?,
|
val handleUserInteractionRequest: suspend () -> ActivityLaunchPermit?,
|
||||||
val setInputFile: (File) -> Unit,
|
val setInputFile: (File) -> Unit,
|
||||||
@ -167,7 +167,7 @@ class PatcherWorker(
|
|||||||
download(plugin, app)
|
download(plugin, app)
|
||||||
}
|
}
|
||||||
|
|
||||||
is SelectedApp.Downloadable -> {
|
is SelectedApp.Search -> {
|
||||||
val getScope = object : GetScope {
|
val getScope = object : GetScope {
|
||||||
override suspend fun requestUserInteraction() =
|
override suspend fun requestUserInteraction() =
|
||||||
args.handleUserInteractionRequest()
|
args.handleUserInteractionRequest()
|
||||||
@ -180,9 +180,11 @@ class PatcherWorker(
|
|||||||
plugin.get(
|
plugin.get(
|
||||||
getScope,
|
getScope,
|
||||||
selectedApp.packageName,
|
selectedApp.packageName,
|
||||||
selectedApp.suggestedVersion
|
selectedApp.version
|
||||||
)
|
)
|
||||||
?.takeIf { selectedApp.suggestedVersion == null || it.version == selectedApp.suggestedVersion }
|
?.takeIf { selectedApp.version == null || it.version == selectedApp.version }
|
||||||
|
} catch (e: UserInteractionException.Activity.NotCompleted) {
|
||||||
|
throw e
|
||||||
} catch (_: UserInteractionException) {
|
} catch (_: UserInteractionException) {
|
||||||
null
|
null
|
||||||
}?.let { app -> download(plugin, app) }
|
}?.let { app -> download(plugin, app) }
|
||||||
|
@ -43,6 +43,7 @@ import app.revanced.manager.ui.component.LoadingIndicator
|
|||||||
import app.revanced.manager.ui.model.State
|
import app.revanced.manager.ui.model.State
|
||||||
import app.revanced.manager.ui.model.Step
|
import app.revanced.manager.ui.model.Step
|
||||||
import app.revanced.manager.ui.model.StepCategory
|
import app.revanced.manager.ui.model.StepCategory
|
||||||
|
import java.util.Locale
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
// Credits: https://github.com/Aliucord/AliucordManager/blob/main/app/src/main/kotlin/com/aliucord/manager/ui/component/installer/InstallGroup.kt
|
// Credits: https://github.com/Aliucord/AliucordManager/blob/main/app/src/main/kotlin/com/aliucord/manager/ui/component/installer/InstallGroup.kt
|
||||||
@ -134,7 +135,7 @@ fun SubStep(
|
|||||||
name: String,
|
name: String,
|
||||||
state: State,
|
state: State,
|
||||||
message: String? = null,
|
message: String? = null,
|
||||||
downloadProgress: Pair<Float, Float?>? = null
|
downloadProgress: Pair<Double, Double?>? = null
|
||||||
) {
|
) {
|
||||||
var messageExpanded by rememberSaveable { mutableStateOf(true) }
|
var messageExpanded by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ fun SubStep(
|
|||||||
} else {
|
} else {
|
||||||
downloadProgress?.let { (current, total) ->
|
downloadProgress?.let { (current, total) ->
|
||||||
Text(
|
Text(
|
||||||
if (total != null) "$current/$total MB" else "$current MB",
|
if (total != null) "${current.formatted}/${total.formatted} MB" else "${current.formatted} MB",
|
||||||
style = MaterialTheme.typography.labelSmall
|
style = MaterialTheme.typography.labelSmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ fun SubStep(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun StepIcon(state: State, progress: Pair<Float, Float?>? = null, size: Dp) {
|
fun StepIcon(state: State, progress: Pair<Double, Double?>? = null, size: Dp) {
|
||||||
val strokeWidth = Dp(floor(size.value / 10) + 1)
|
val strokeWidth = Dp(floor(size.value / 10) + 1)
|
||||||
|
|
||||||
when (state) {
|
when (state) {
|
||||||
@ -237,9 +238,11 @@ fun StepIcon(state: State, progress: Pair<Float, Float?>? = null, size: Dp) {
|
|||||||
progress?.let { (current, total) ->
|
progress?.let { (current, total) ->
|
||||||
if (total == null) return@let null
|
if (total == null) return@let null
|
||||||
current / total
|
current / total
|
||||||
}
|
}?.toFloat()
|
||||||
},
|
},
|
||||||
strokeWidth = strokeWidth
|
strokeWidth = strokeWidth
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Double.formatted get() = "%.1f".format(locale = Locale.ROOT, this)
|
@ -49,7 +49,7 @@ data class BundleInfo(
|
|||||||
bundle.uid to patches
|
bundle.uid to patches
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PatchBundleRepository.bundleInfoFlow(packageName: String, version: String) =
|
fun PatchBundleRepository.bundleInfoFlow(packageName: String, version: String?) =
|
||||||
sources.flatMapLatestAndCombine(
|
sources.flatMapLatestAndCombine(
|
||||||
combiner = { it.filterNotNull() }
|
combiner = { it.filterNotNull() }
|
||||||
) { source ->
|
) { source ->
|
||||||
@ -64,7 +64,7 @@ data class BundleInfo(
|
|||||||
bundle.patches.filter { it.compatibleWith(packageName) }.forEach {
|
bundle.patches.filter { it.compatibleWith(packageName) }.forEach {
|
||||||
val targetList = when {
|
val targetList = when {
|
||||||
it.compatiblePackages == null -> universal
|
it.compatiblePackages == null -> universal
|
||||||
it.supportsVersion(
|
it.supports(
|
||||||
packageName,
|
packageName,
|
||||||
version
|
version
|
||||||
) -> supported
|
) -> supported
|
||||||
|
@ -19,5 +19,5 @@ data class Step(
|
|||||||
val category: StepCategory,
|
val category: StepCategory,
|
||||||
val state: State = State.WAITING,
|
val state: State = State.WAITING,
|
||||||
val message: String? = null,
|
val message: String? = null,
|
||||||
val downloadProgress: StateFlow<Pair<Float, Float?>?>? = null
|
val downloadProgress: StateFlow<Pair<Double, Double?>?>? = null
|
||||||
)
|
)
|
@ -2,13 +2,12 @@ package app.revanced.manager.ui.model
|
|||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import app.revanced.manager.network.downloader.ParceledDownloaderApp
|
import app.revanced.manager.network.downloader.ParceledDownloaderApp
|
||||||
import kotlinx.parcelize.IgnoredOnParcel
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
sealed interface SelectedApp : Parcelable {
|
sealed interface SelectedApp : Parcelable {
|
||||||
val packageName: String
|
val packageName: String
|
||||||
val version: String // TODO: make this nullable
|
val version: String?
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Download(
|
data class Download(
|
||||||
@ -18,10 +17,7 @@ sealed interface SelectedApp : Parcelable {
|
|||||||
) : SelectedApp
|
) : SelectedApp
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Downloadable(override val packageName: String, val suggestedVersion: String?) : SelectedApp {
|
data class Search(override val packageName: String, override val version: String?) : SelectedApp
|
||||||
@IgnoredOnParcel
|
|
||||||
override val version = suggestedVersion.orEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Local(
|
data class Local(
|
||||||
|
@ -142,7 +142,7 @@ fun PatchesSelectorScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.compatibleVersions.isNotEmpty())
|
if (vm.compatibleVersions.isNotEmpty() && vm.appVersion != null)
|
||||||
UnsupportedDialog(
|
UnsupportedDialog(
|
||||||
appVersion = vm.appVersion,
|
appVersion = vm.appVersion,
|
||||||
supportedVersions = vm.compatibleVersions,
|
supportedVersions = vm.compatibleVersions,
|
||||||
|
@ -148,7 +148,7 @@ private fun SelectedAppInfoScreen(
|
|||||||
availablePatchCount: Int,
|
availablePatchCount: Int,
|
||||||
selectedPatchCount: Int,
|
selectedPatchCount: Int,
|
||||||
packageName: String,
|
packageName: String,
|
||||||
version: String,
|
version: String?,
|
||||||
packageInfo: PackageInfo?,
|
packageInfo: PackageInfo?,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@ -173,7 +173,13 @@ private fun SelectedAppInfoScreen(
|
|||||||
) {
|
) {
|
||||||
AppInfo(packageInfo, placeholderLabel = packageName) {
|
AppInfo(packageInfo, placeholderLabel = packageName) {
|
||||||
Text(
|
Text(
|
||||||
stringResource(R.string.selected_app_meta, version, availablePatchCount),
|
version?.let {
|
||||||
|
stringResource(
|
||||||
|
R.string.selected_app_meta_version,
|
||||||
|
it,
|
||||||
|
availablePatchCount
|
||||||
|
)
|
||||||
|
} ?: stringResource(R.string.selected_app_meta_no_version, availablePatchCount),
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
@ -186,7 +192,8 @@ private fun SelectedAppInfoScreen(
|
|||||||
)
|
)
|
||||||
PageItem(
|
PageItem(
|
||||||
R.string.version_selector_item,
|
R.string.version_selector_item,
|
||||||
stringResource(R.string.version_selector_item_description, version),
|
version?.let { stringResource(R.string.version_selector_item_description, it) }
|
||||||
|
?: stringResource(R.string.version_selector_item_description_auto),
|
||||||
onVersionSelectorClick
|
onVersionSelectorClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.lifecycle.ViewModel
|
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.manager.PreferencesManager
|
|
||||||
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.domain.repository.DownloaderPluginRepository
|
||||||
import app.revanced.manager.util.PM
|
import app.revanced.manager.util.PM
|
||||||
|
@ -106,7 +106,7 @@ class PatcherViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val patchesProgress = MutableStateFlow(Pair(0, input.selectedPatches.values.sumOf { it.size }))
|
val patchesProgress = MutableStateFlow(Pair(0, input.selectedPatches.values.sumOf { it.size }))
|
||||||
private val downloadProgress = MutableStateFlow<Pair<Float, Float?>?>(null)
|
private val downloadProgress = MutableStateFlow<Pair<Double, Double?>?>(null)
|
||||||
val steps = generateSteps(
|
val steps = generateSteps(
|
||||||
app,
|
app,
|
||||||
input.selectedApp,
|
input.selectedApp,
|
||||||
@ -184,13 +184,15 @@ class PatcherViewModel(
|
|||||||
installedAppRepository.addOrUpdate(
|
installedAppRepository.addOrUpdate(
|
||||||
installedPackageName!!,
|
installedPackageName!!,
|
||||||
packageName,
|
packageName,
|
||||||
input.selectedApp.version,
|
input.selectedApp.version
|
||||||
|
?: pm.getPackageInfo(outputFile)!!.versionName,
|
||||||
InstallType.DEFAULT,
|
InstallType.DEFAULT,
|
||||||
input.selectedPatches
|
input.selectedPatches
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
app.toast(app.getString(R.string.install_app_fail, extra))
|
app.toast(app.getString(R.string.install_app_fail, extra))
|
||||||
|
Log.e(tag, "Installation failed: $extra")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +242,6 @@ class PatcherViewModel(
|
|||||||
|
|
||||||
fun rejectInteraction() {
|
fun rejectInteraction() {
|
||||||
currentInteractionRequest?.complete(null)
|
currentInteractionRequest?.complete(null)
|
||||||
currentInteractionRequest = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allowInteraction() {
|
fun allowInteraction() {
|
||||||
@ -253,14 +254,19 @@ class PatcherViewModel(
|
|||||||
|
|
||||||
launchedActivity = job
|
launchedActivity = job
|
||||||
val result = job.await()
|
val result = job.await()
|
||||||
if (result.code != Activity.RESULT_OK) throw UserInteractionException.ActivityCancelled()
|
when (result.code) {
|
||||||
result.intent
|
Activity.RESULT_OK -> result.intent
|
||||||
|
Activity.RESULT_CANCELED -> throw UserInteractionException.Activity.Cancelled()
|
||||||
|
else -> throw UserInteractionException.Activity.NotCompleted(
|
||||||
|
result.code,
|
||||||
|
result.intent
|
||||||
|
)
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
launchedActivity = null
|
launchedActivity = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
currentInteractionRequest = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleActivityResult(result: IntentContract.Result) {
|
fun handleActivityResult(result: IntentContract.Result) {
|
||||||
@ -303,23 +309,24 @@ class PatcherViewModel(
|
|||||||
|
|
||||||
InstallType.ROOT -> {
|
InstallType.ROOT -> {
|
||||||
try {
|
try {
|
||||||
|
val packageInfo = pm.getPackageInfo(outputFile)
|
||||||
|
?: throw Exception("Failed to load application info")
|
||||||
val label = with(pm) {
|
val label = with(pm) {
|
||||||
getPackageInfo(outputFile)?.label()
|
packageInfo.label()
|
||||||
?: throw Exception("Failed to load application info")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rootInstaller.install(
|
rootInstaller.install(
|
||||||
outputFile,
|
outputFile,
|
||||||
inputFile,
|
inputFile,
|
||||||
packageName,
|
packageName,
|
||||||
input.selectedApp.version,
|
packageInfo.versionName,
|
||||||
label
|
label
|
||||||
)
|
)
|
||||||
|
|
||||||
installedAppRepository.addOrUpdate(
|
installedAppRepository.addOrUpdate(
|
||||||
packageName,
|
packageName,
|
||||||
packageName,
|
packageName,
|
||||||
input.selectedApp.version,
|
packageInfo.versionName,
|
||||||
InstallType.ROOT,
|
InstallType.ROOT,
|
||||||
input.selectedPatches
|
input.selectedPatches
|
||||||
)
|
)
|
||||||
@ -357,10 +364,10 @@ class PatcherViewModel(
|
|||||||
fun generateSteps(
|
fun generateSteps(
|
||||||
context: Context,
|
context: Context,
|
||||||
selectedApp: SelectedApp,
|
selectedApp: SelectedApp,
|
||||||
downloadProgress: StateFlow<Pair<Float, Float?>?>? = null
|
downloadProgress: StateFlow<Pair<Double, Double?>?>? = null
|
||||||
): List<Step> {
|
): List<Step> {
|
||||||
val needsDownload =
|
val needsDownload =
|
||||||
selectedApp is SelectedApp.Download || selectedApp is SelectedApp.Downloadable
|
selectedApp is SelectedApp.Download || selectedApp is SelectedApp.Search
|
||||||
|
|
||||||
return listOfNotNull(
|
return listOfNotNull(
|
||||||
Step(
|
Step(
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
<string name="bundle_name_default">Default</string>
|
<string name="bundle_name_default">Default</string>
|
||||||
<string name="bundle_name_fallback">Unnamed</string>
|
<string name="bundle_name_fallback">Unnamed</string>
|
||||||
|
|
||||||
<string name="selected_app_meta">%1$s • %2$d available patches</string>
|
<string name="selected_app_meta_version">%1$s • %2$d available patches</string>
|
||||||
|
<string name="selected_app_meta_no_version">%d available patches</string>
|
||||||
|
|
||||||
<string name="patch_item_description">Start patching the application</string>
|
<string name="patch_item_description">Start patching the application</string>
|
||||||
<string name="patch_selector_item">Patch selection and options</string>
|
<string name="patch_selector_item">Patch selection and options</string>
|
||||||
@ -43,6 +44,7 @@
|
|||||||
|
|
||||||
<string name="version_selector_item">Change version</string>
|
<string name="version_selector_item">Change version</string>
|
||||||
<string name="version_selector_item_description">%s selected</string>
|
<string name="version_selector_item_description">%s selected</string>
|
||||||
|
<string name="version_selector_item_description_auto">Automatically selected</string>
|
||||||
|
|
||||||
<string name="legacy_import_failed">Could not import legacy settings</string>
|
<string name="legacy_import_failed">Could not import legacy settings</string>
|
||||||
|
|
||||||
|
@ -21,9 +21,13 @@ public final class app/revanced/manager/plugin/downloader/App$Creator : android/
|
|||||||
public synthetic fun newArray (I)[Ljava/lang/Object;
|
public synthetic fun newArray (I)[Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/manager/plugin/downloader/ConstantsKt {
|
||||||
|
public static final field PLUGIN_HOST_PERMISSION Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface class app/revanced/manager/plugin/downloader/DownloadScope {
|
public abstract interface class app/revanced/manager/plugin/downloader/DownloadScope {
|
||||||
public abstract fun getTargetFile ()Ljava/io/File;
|
public abstract fun getTargetFile ()Ljava/io/File;
|
||||||
public abstract fun reportProgress (ILjava/lang/Integer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
public abstract fun reportProgress (JLjava/lang/Long;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/Downloader {
|
public final class app/revanced/manager/plugin/downloader/Downloader {
|
||||||
@ -39,9 +43,9 @@ public final class app/revanced/manager/plugin/downloader/DownloaderBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/DownloaderContext {
|
public final class app/revanced/manager/plugin/downloader/DownloaderContext {
|
||||||
public fun <init> (Landroid/content/Context;Ljava/io/File;)V
|
public fun <init> (Landroid/content/Context;Ljava/lang/String;)V
|
||||||
public final fun getAndroidContext ()Landroid/content/Context;
|
public final fun getAndroidContext ()Landroid/content/Context;
|
||||||
public final fun getTempDirectory ()Ljava/io/File;
|
public final fun getPluginHostPackageName ()Ljava/lang/String;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface annotation class app/revanced/manager/plugin/downloader/DownloaderDsl : java/lang/annotation/Annotation {
|
public abstract interface annotation class app/revanced/manager/plugin/downloader/DownloaderDsl : java/lang/annotation/Annotation {
|
||||||
@ -59,10 +63,20 @@ public abstract class app/revanced/manager/plugin/downloader/UserInteractionExce
|
|||||||
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/UserInteractionException$ActivityCancelled : app/revanced/manager/plugin/downloader/UserInteractionException {
|
public abstract class app/revanced/manager/plugin/downloader/UserInteractionException$Activity : app/revanced/manager/plugin/downloader/UserInteractionException {
|
||||||
|
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$Cancelled : app/revanced/manager/plugin/downloader/UserInteractionException$Activity {
|
||||||
public fun <init> ()V
|
public fun <init> ()V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$NotCompleted : app/revanced/manager/plugin/downloader/UserInteractionException$Activity {
|
||||||
|
public fun <init> (ILandroid/content/Intent;)V
|
||||||
|
public final fun getIntent ()Landroid/content/Intent;
|
||||||
|
public final fun getResultCode ()I
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/UserInteractionException$RequestDenied : app/revanced/manager/plugin/downloader/UserInteractionException {
|
public final class app/revanced/manager/plugin/downloader/UserInteractionException$RequestDenied : app/revanced/manager/plugin/downloader/UserInteractionException {
|
||||||
public fun <init> ()V
|
public fun <init> ()V
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@ plugins {
|
|||||||
alias(libs.plugins.android.library)
|
alias(libs.plugins.android.library)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
|
`maven-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "app.revanced.manager.downloader_plugin"
|
namespace = "app.revanced.manager.plugin.downloader"
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@ -32,6 +33,20 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
publishing {
|
||||||
api(libs.paging.common.ktx)
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("release") {
|
||||||
|
groupId = "app.revanced"
|
||||||
|
artifactId = "manager-downloader-plugin"
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
from(components["release"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ interface DownloadScope {
|
|||||||
/**
|
/**
|
||||||
* A callback for reporting download progress
|
* A callback for reporting download progress
|
||||||
*/
|
*/
|
||||||
suspend fun reportProgress(bytesReceived: Int, bytesTotal: Int?)
|
suspend fun reportProgress(bytesReceived: Long, bytesTotal: Long?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@DownloaderDsl
|
@DownloaderDsl
|
||||||
@ -58,6 +58,10 @@ fun <A : App> downloader(block: DownloaderBuilder<A>.() -> Unit) =
|
|||||||
|
|
||||||
sealed class UserInteractionException(message: String) : Exception(message) {
|
sealed class UserInteractionException(message: String) : Exception(message) {
|
||||||
class RequestDenied : UserInteractionException("Request was denied")
|
class RequestDenied : UserInteractionException("Request was denied")
|
||||||
// TODO: can cancelled activities return an intent?
|
|
||||||
class ActivityCancelled : UserInteractionException("Interaction was cancelled")
|
sealed class Activity(message: String) : UserInteractionException(message) {
|
||||||
|
class Cancelled : Activity("Interaction was cancelled")
|
||||||
|
class NotCompleted(val resultCode: Int, val intent: Intent?) :
|
||||||
|
Activity("Unexpected activity result code: $resultCode")
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,13 +1,12 @@
|
|||||||
package app.revanced.manager.plugin.downloader
|
package app.revanced.manager.plugin.downloader
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
@Suppress("Unused", "MemberVisibilityCanBePrivate")
|
@Suppress("Unused", "MemberVisibilityCanBePrivate")
|
||||||
/**
|
/**
|
||||||
* The downloader plugin context.
|
* The downloader plugin context.
|
||||||
*
|
*
|
||||||
* @param androidContext An Android [Context].
|
* @param androidContext An Android [Context] for this plugin.
|
||||||
* @param tempDirectory The temporary directory belonging to this plugin.
|
* @param pluginHostPackageName The package name of the plugin host.
|
||||||
*/
|
*/
|
||||||
class DownloaderContext(val androidContext: Context, val tempDirectory: File)
|
class DownloaderContext(val androidContext: Context, val pluginHostPackageName: String)
|
@ -5,7 +5,6 @@ ui-tooling = "1.6.8"
|
|||||||
viewmodel-lifecycle = "2.8.3"
|
viewmodel-lifecycle = "2.8.3"
|
||||||
splash-screen = "1.0.1"
|
splash-screen = "1.0.1"
|
||||||
compose-activity = "1.9.0"
|
compose-activity = "1.9.0"
|
||||||
paging = "3.3.0"
|
|
||||||
preferences-datastore = "1.1.1"
|
preferences-datastore = "1.1.1"
|
||||||
work-runtime = "2.9.0"
|
work-runtime = "2.9.0"
|
||||||
compose-bom = "2024.06.00"
|
compose-bom = "2024.06.00"
|
||||||
@ -44,8 +43,6 @@ runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", ve
|
|||||||
runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "viewmodel-lifecycle" }
|
runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "viewmodel-lifecycle" }
|
||||||
splash-screen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splash-screen" }
|
splash-screen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splash-screen" }
|
||||||
compose-activity = { group = "androidx.activity", name = "activity-compose", version.ref = "compose-activity" }
|
compose-activity = { group = "androidx.activity", name = "activity-compose", version.ref = "compose-activity" }
|
||||||
paging-common-ktx = { group = "androidx.paging", name = "paging-common-ktx", version.ref = "paging" }
|
|
||||||
paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" }
|
|
||||||
work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work-runtime" }
|
work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work-runtime" }
|
||||||
preferences-datastore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "preferences-datastore" }
|
preferences-datastore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "preferences-datastore" }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user