mirror of
https://github.com/revanced/revanced-manager-compose-old.git
synced 2025-05-01 06:54:28 +02:00
feat: partial implementation of installed apps
This commit is contained in:
parent
a3e41552f8
commit
7e1f829e3c
@ -8,6 +8,8 @@ import androidx.compose.runtime.mutableStateListOf
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import app.revanced.manager.ui.Resource
|
import app.revanced.manager.ui.Resource
|
||||||
import app.revanced.manager.ui.viewmodel.PatchClass
|
import app.revanced.manager.ui.viewmodel.PatchClass
|
||||||
|
import app.revanced.manager.ui.viewmodel.PatchedApp
|
||||||
|
import app.revanced.manager.util.reVancedFolder
|
||||||
import app.revanced.manager.util.tag
|
import app.revanced.manager.util.tag
|
||||||
import app.revanced.patcher.data.Context
|
import app.revanced.patcher.data.Context
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||||
@ -16,20 +18,46 @@ import app.revanced.patcher.patch.Patch
|
|||||||
import app.revanced.patcher.util.patch.PatchBundle
|
import app.revanced.patcher.util.patch.PatchBundle
|
||||||
import dalvik.system.DexClassLoader
|
import dalvik.system.DexClassLoader
|
||||||
import io.sentry.Sentry
|
import io.sentry.Sentry
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
|
import kotlinx.serialization.json.encodeToStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class PatcherUtils(val app: Application) {
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
class PatcherUtils(val app: Application, val json: Json) {
|
||||||
val patches = mutableStateOf<Resource<List<Class<out Patch<Context>>>>>(Resource.Loading)
|
val patches = mutableStateOf<Resource<List<Class<out Patch<Context>>>>>(Resource.Loading)
|
||||||
val filteredPatches = mutableStateListOf<PatchClass>()
|
val filteredPatches = mutableStateListOf<PatchClass>()
|
||||||
val selectedAppPackage = mutableStateOf(Optional.empty<ApplicationInfo>())
|
val selectedAppPackage = mutableStateOf(Optional.empty<ApplicationInfo>())
|
||||||
val selectedAppPackagePath = mutableStateOf<String?>(null)
|
val selectedAppPackagePath = mutableStateOf<String?>(null)
|
||||||
val selectedPatches = mutableStateListOf<String>()
|
val selectedPatches = mutableStateListOf<String>()
|
||||||
|
val patchedAppsFile = reVancedFolder.resolve("apps.json")
|
||||||
|
val patchedApps = mutableStateListOf<PatchedApp>()
|
||||||
lateinit var patchBundleFile: String
|
lateinit var patchBundleFile: String
|
||||||
|
|
||||||
fun cleanup() {
|
suspend fun getPatchedApps() = withContext(Dispatchers.IO) {
|
||||||
patches.value = Resource.Loading
|
if (patchedAppsFile.exists()) {
|
||||||
selectedAppPackage.value = Optional.empty()
|
val apps: List<PatchedApp> = try {
|
||||||
selectedPatches.clear()
|
json.decodeFromStream(patchedAppsFile.inputStream())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(tag, e.stackTraceToString())
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
apps.forEach { app ->
|
||||||
|
if (!patchedApps.any { it.pkgName == app.pkgName }) {
|
||||||
|
patchedApps.add(app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun savePatchedApp(app: PatchedApp) {
|
||||||
|
patchedApps.removeIf { it.pkgName == app.pkgName }
|
||||||
|
patchedApps.add(app)
|
||||||
|
|
||||||
|
json.encodeToStream(patchedApps as List<PatchedApp>, patchedAppsFile.outputStream())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadPatchBundle(file: String? = patchBundleFile) {
|
fun loadPatchBundle(file: String? = patchBundleFile) {
|
||||||
@ -50,7 +78,9 @@ class PatcherUtils(val app: Application) {
|
|||||||
|
|
||||||
fun getSelectedPackageInfo(): PackageInfo? {
|
fun getSelectedPackageInfo(): PackageInfo? {
|
||||||
return if (selectedAppPackage.value.isPresent) {
|
return if (selectedAppPackage.value.isPresent) {
|
||||||
val path = selectedAppPackage.value.get().publicSourceDir ?: selectedAppPackagePath.value ?: return null
|
val path =
|
||||||
|
selectedAppPackage.value.get().publicSourceDir ?: selectedAppPackagePath.value
|
||||||
|
?: return null
|
||||||
app.packageManager.getPackageArchiveInfo(
|
app.packageManager.getPackageArchiveInfo(
|
||||||
path, 1
|
path, 1
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,6 @@ import android.app.PendingIntent
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Environment
|
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
@ -23,6 +22,7 @@ import app.revanced.manager.patcher.aligning.ZipAligner
|
|||||||
import app.revanced.manager.patcher.aligning.zip.ZipFile
|
import app.revanced.manager.patcher.aligning.zip.ZipFile
|
||||||
import app.revanced.manager.patcher.aligning.zip.structures.ZipEntry
|
import app.revanced.manager.patcher.aligning.zip.structures.ZipEntry
|
||||||
import app.revanced.manager.patcher.signing.Signer
|
import app.revanced.manager.patcher.signing.Signer
|
||||||
|
import app.revanced.manager.util.reVancedFolder
|
||||||
import app.revanced.manager.util.tag
|
import app.revanced.manager.util.tag
|
||||||
import app.revanced.patcher.Patcher
|
import app.revanced.patcher.Patcher
|
||||||
import app.revanced.patcher.PatcherOptions
|
import app.revanced.patcher.PatcherOptions
|
||||||
@ -112,8 +112,6 @@ class PatcherWorker(
|
|||||||
applicationContext.filesDir.resolve("framework").also { it.mkdirs() }.absolutePath
|
applicationContext.filesDir.resolve("framework").also { it.mkdirs() }.absolutePath
|
||||||
val integrationsCacheDir =
|
val integrationsCacheDir =
|
||||||
applicationContext.filesDir.resolve("integrations-cache").also { it.mkdirs() }
|
applicationContext.filesDir.resolve("integrations-cache").also { it.mkdirs() }
|
||||||
val reVancedFolder =
|
|
||||||
Environment.getExternalStorageDirectory().resolve("ReVanced").also { it.mkdirs() }
|
|
||||||
val appInfo = patcherUtils.selectedAppPackage.value.get()
|
val appInfo = patcherUtils.selectedAppPackage.value.get()
|
||||||
val appPath = patcherUtils.selectedAppPackagePath.value
|
val appPath = patcherUtils.selectedAppPackagePath.value
|
||||||
|
|
||||||
@ -208,7 +206,6 @@ class PatcherWorker(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
log("Successfully patched!", SUCCESS)
|
log("Successfully patched!", SUCCESS)
|
||||||
patcherUtils.cleanup()
|
|
||||||
} finally {
|
} finally {
|
||||||
Log.d(tag, "Deleting workdir")
|
Log.d(tag, "Deleting workdir")
|
||||||
workdir.deleteRecursively()
|
workdir.deleteRecursively()
|
||||||
|
@ -39,20 +39,20 @@ fun ApplicationItem(
|
|||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxSize()
|
||||||
.padding(horizontal = 14.dp, vertical = 2.dp)
|
.padding(horizontal = 14.dp, vertical = 2.dp),
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(68.dp)
|
.height(68.dp)
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
) {
|
||||||
appIcon()
|
appIcon()
|
||||||
Column(modifier = Modifier.padding(start = 8.dp)) {
|
Column(modifier = Modifier.padding(start = 8.dp)) {
|
||||||
@ -68,7 +68,7 @@ fun ApplicationItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.rotate(rotateState),
|
modifier = Modifier.rotate(rotateState),
|
||||||
onClick = { expandedState = !expandedState },
|
onClick = { expandedState = !expandedState },
|
||||||
@ -78,7 +78,7 @@ fun ApplicationItem(
|
|||||||
contentDescription = stringResource(R.string.expand)
|
contentDescription = stringResource(R.string.expand)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
OutlinedButton(onClick = { /*TODO*/ }) {
|
OutlinedButton(onClick = {}) {
|
||||||
Text(stringResource(R.string.update))
|
Text(stringResource(R.string.update))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@ -16,7 +16,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.ui.component.AppIcon
|
import app.revanced.manager.ui.component.AppIcon
|
||||||
import app.revanced.manager.ui.component.ApplicationItem
|
import app.revanced.manager.ui.component.ApplicationItem
|
||||||
import app.revanced.manager.ui.component.ApplicationItemDualTint
|
|
||||||
import app.revanced.manager.ui.component.HeadlineWithCard
|
import app.revanced.manager.ui.component.HeadlineWithCard
|
||||||
import app.revanced.manager.ui.viewmodel.DashboardViewModel
|
import app.revanced.manager.ui.viewmodel.DashboardViewModel
|
||||||
import app.revanced.manager.util.loadIcon
|
import app.revanced.manager.util.loadIcon
|
||||||
@ -25,10 +24,10 @@ import org.koin.androidx.compose.getViewModel
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DashboardScreen(viewModel: DashboardViewModel = getViewModel()) {
|
fun DashboardScreen(viewModel: DashboardViewModel = getViewModel()) {
|
||||||
|
var showUpdates by remember { mutableStateOf(false) }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val padHoriz = 16.dp
|
val padHoriz = 16.dp
|
||||||
val padVert = 10.dp
|
val padVert = 10.dp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@ -73,10 +72,10 @@ fun DashboardScreen(viewModel: DashboardViewModel = getViewModel()) {
|
|||||||
style = MaterialTheme.typography.headlineSmall
|
style = MaterialTheme.typography.headlineSmall
|
||||||
)
|
)
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
FilterChip(selected = true, onClick = { /*TODO*/ }, label = {
|
//FilterChip(selected = showUpdates, onClick = { showUpdates = true }, label = {
|
||||||
Text(stringResource(R.string.updates_available))
|
// Text(stringResource(R.string.updates_available))
|
||||||
})
|
//})
|
||||||
FilterChip(selected = false, onClick = { /*TODO*/ }, label = {
|
FilterChip(selected = !showUpdates, onClick = { showUpdates = false }, label = {
|
||||||
Text(stringResource(R.string.installed))
|
Text(stringResource(R.string.installed))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -87,39 +86,19 @@ fun DashboardScreen(viewModel: DashboardViewModel = getViewModel()) {
|
|||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
ApplicationItem(
|
viewModel.apps.forEach {
|
||||||
appName = "Compose Manager",
|
ApplicationItem(
|
||||||
appIcon = {
|
appName = it.appName,
|
||||||
AppIcon(
|
appIcon = {
|
||||||
drawable = context.loadIcon("app.revanced.manager.compose"),
|
AppIcon(
|
||||||
contentDescription = null,
|
drawable = context.loadIcon(it.pkgName),
|
||||||
size = 38
|
contentDescription = null,
|
||||||
)
|
size = 38
|
||||||
},
|
)
|
||||||
releaseAgo = "9d ago"
|
},
|
||||||
) {
|
releaseAgo = it.version
|
||||||
ChangelogText(
|
) {
|
||||||
"""
|
|
||||||
cossal will explode
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ApplicationItemDualTint(
|
|
||||||
appName = "Flutter Manager",
|
|
||||||
releaseAgo = "9d ago",
|
|
||||||
appIcon = {
|
|
||||||
AppIcon(
|
|
||||||
drawable = context.loadIcon("app.revanced.manager.flutter"),
|
|
||||||
contentDescription = null,
|
|
||||||
size = 38
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) {
|
|
||||||
ChangelogText(
|
|
||||||
"""
|
|
||||||
cossal will explode
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import app.revanced.manager.ui.component.AppMediumTopBar
|
|||||||
import app.revanced.manager.ui.component.AppScaffold
|
import app.revanced.manager.ui.component.AppScaffold
|
||||||
import app.revanced.manager.ui.component.LoadingIndicator
|
import app.revanced.manager.ui.component.LoadingIndicator
|
||||||
import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
|
import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
|
||||||
|
import app.revanced.manager.util.appName
|
||||||
import org.koin.androidx.compose.getViewModel
|
import org.koin.androidx.compose.getViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -54,10 +55,12 @@ fun AppSelectorSubscreen(
|
|||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
if (vm.filteredApps.isNotEmpty()) {
|
if (vm.filteredApps.isNotEmpty()) {
|
||||||
LazyColumn(modifier = Modifier.fillMaxSize().padding(paddingValues)) {
|
LazyColumn(modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)) {
|
||||||
items(count = vm.filteredApps.size) { int ->
|
items(count = vm.filteredApps.size) { int ->
|
||||||
val app = vm.filteredApps[int]
|
val app = vm.filteredApps[int]
|
||||||
val label = vm.applicationLabel(app)
|
val label = vm.app.appName(app)
|
||||||
val packageName = app.packageName
|
val packageName = app.packageName
|
||||||
|
|
||||||
val same = packageName == label
|
val same = packageName == label
|
||||||
|
@ -10,13 +10,21 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import app.revanced.manager.domain.repository.ReVancedRepositoryImpl
|
import app.revanced.manager.domain.repository.ReVancedRepositoryImpl
|
||||||
import app.revanced.manager.network.dto.Assets
|
import app.revanced.manager.network.dto.Assets
|
||||||
import app.revanced.manager.network.utils.getOrNull
|
import app.revanced.manager.network.utils.getOrNull
|
||||||
|
import app.revanced.manager.patcher.PatcherUtils
|
||||||
import app.revanced.manager.util.ghManager
|
import app.revanced.manager.util.ghManager
|
||||||
import app.revanced.manager.util.ghPatcher
|
import app.revanced.manager.util.ghPatcher
|
||||||
|
import io.ktor.http.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class DashboardViewModel(private val reVancedApi: ReVancedRepositoryImpl) : ViewModel() {
|
class DashboardViewModel(
|
||||||
|
private val reVancedApi: ReVancedRepositoryImpl,
|
||||||
|
private val patcherUtils: PatcherUtils
|
||||||
|
) : ViewModel() {
|
||||||
|
val apps = patcherUtils.patchedApps
|
||||||
|
|
||||||
private var _latestPatcherCommit: Assets? by mutableStateOf(null)
|
private var _latestPatcherCommit: Assets? by mutableStateOf(null)
|
||||||
val patcherCommitDate: String
|
val patcherCommitDate: String
|
||||||
get() = _latestPatcherCommit?.commitDate ?: "unknown"
|
get() = _latestPatcherCommit?.commitDate ?: "unknown"
|
||||||
@ -26,22 +34,23 @@ class DashboardViewModel(private val reVancedApi: ReVancedRepositoryImpl) : View
|
|||||||
get() = _latestManagerCommit?.commitDate ?: "unknown"
|
get() = _latestManagerCommit?.commitDate ?: "unknown"
|
||||||
|
|
||||||
init {
|
init {
|
||||||
fetchLastCommit()
|
viewModelScope.launch {
|
||||||
|
patcherUtils.getPatchedApps()
|
||||||
|
fetchLastCommit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchLastCommit() {
|
private suspend fun fetchLastCommit() {
|
||||||
viewModelScope.launch {
|
val repo = reVancedApi.getAssets().getOrNull() ?: return
|
||||||
val repo = reVancedApi.getAssets().getOrNull() ?: return@launch
|
for (asset in repo.tools) {
|
||||||
for (asset in repo.tools) {
|
when (asset.repository) {
|
||||||
when (asset.repository) {
|
ghPatcher -> {
|
||||||
ghPatcher -> {
|
_latestPatcherCommit = asset
|
||||||
_latestPatcherCommit = asset
|
|
||||||
}
|
|
||||||
ghManager -> {
|
|
||||||
_latestManagerCommit = asset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ghManager -> {
|
||||||
|
_latestManagerCommit = asset
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,4 +65,12 @@ class DashboardViewModel(private val reVancedApi: ReVancedRepositoryImpl) : View
|
|||||||
@SuppressLint("ConstantLocale")
|
@SuppressLint("ConstantLocale")
|
||||||
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
|
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class PatchedApp(
|
||||||
|
val appName: String,
|
||||||
|
val pkgName: String,
|
||||||
|
val version: String,
|
||||||
|
val appliedPatches: List<String>
|
||||||
|
)
|
||||||
|
@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
@ -16,11 +17,14 @@ import androidx.work.*
|
|||||||
import app.revanced.manager.installer.service.InstallService
|
import app.revanced.manager.installer.service.InstallService
|
||||||
import app.revanced.manager.installer.service.UninstallService
|
import app.revanced.manager.installer.service.UninstallService
|
||||||
import app.revanced.manager.installer.utils.PM
|
import app.revanced.manager.installer.utils.PM
|
||||||
|
import app.revanced.manager.patcher.PatcherUtils
|
||||||
import app.revanced.manager.patcher.worker.PatcherWorker
|
import app.revanced.manager.patcher.worker.PatcherWorker
|
||||||
|
import app.revanced.manager.util.appName
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class PatchingScreenViewModel(
|
class PatchingScreenViewModel(
|
||||||
private val app: Application,
|
private val app: Application,
|
||||||
|
private val patcherUtils: PatcherUtils,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
sealed interface PatchLog {
|
sealed interface PatchLog {
|
||||||
@ -38,7 +42,7 @@ class PatchingScreenViewModel(
|
|||||||
object Failure : Status()
|
object Failure : Status()
|
||||||
}
|
}
|
||||||
|
|
||||||
val workManager = WorkManager.getInstance(app)
|
private val workManager = WorkManager.getInstance(app)
|
||||||
var installFailure by mutableStateOf(false)
|
var installFailure by mutableStateOf(false)
|
||||||
var pmStatus by mutableStateOf(-999)
|
var pmStatus by mutableStateOf(-999)
|
||||||
var extra by mutableStateOf("")
|
var extra by mutableStateOf("")
|
||||||
@ -109,12 +113,24 @@ class PatchingScreenViewModel(
|
|||||||
fun postInstallStatus() {
|
fun postInstallStatus() {
|
||||||
if (pmStatus == PackageInstaller.STATUS_SUCCESS) {
|
if (pmStatus == PackageInstaller.STATUS_SUCCESS) {
|
||||||
log(PatchLog.Success("Successfully installed!"))
|
log(PatchLog.Success("Successfully installed!"))
|
||||||
|
patcherUtils.getSelectedPackageInfo()?.let { saveApp(it) }
|
||||||
} else {
|
} else {
|
||||||
installFailure = true
|
installFailure = true
|
||||||
log(PatchLog.Error("Failed to install!"))
|
log(PatchLog.Error("Failed to install!"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveApp(packageInfo: PackageInfo) = patcherUtils.savePatchedApp(
|
||||||
|
packageInfo.run {
|
||||||
|
PatchedApp(
|
||||||
|
appName = app.appName(applicationInfo),
|
||||||
|
pkgName = applicationInfo.packageName,
|
||||||
|
version = versionName,
|
||||||
|
appliedPatches = patcherUtils.selectedPatches
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
liveData.removeObserver(observer)
|
liveData.removeObserver(observer)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package app.revanced.manager.util
|
package app.revanced.manager.util
|
||||||
|
|
||||||
|
import android.os.Environment
|
||||||
|
|
||||||
private const val team = "revanced"
|
private const val team = "revanced"
|
||||||
const val ghOrganization = "https://github.com/$team"
|
const val ghOrganization = "https://github.com/$team"
|
||||||
const val ghCli = "$team/revanced-cli"
|
const val ghCli = "$team/revanced-cli"
|
||||||
@ -7,4 +9,6 @@ const val ghPatches = "$team/revanced-patches"
|
|||||||
const val ghPatcher = "$team/revanced-patcher"
|
const val ghPatcher = "$team/revanced-patcher"
|
||||||
const val ghManager = "$team/revanced-manager"
|
const val ghManager = "$team/revanced-manager"
|
||||||
const val ghIntegrations = "$team/revanced-integrations"
|
const val ghIntegrations = "$team/revanced-integrations"
|
||||||
const val tag = "ReVanced Manager"
|
const val tag = "ReVanced Manager"
|
||||||
|
val reVancedFolder =
|
||||||
|
Environment.getExternalStorageDirectory().resolve("ReVanced").also { it.mkdirs() }
|
@ -2,6 +2,7 @@ package app.revanced.manager.util
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageManager.NameNotFoundException
|
import android.content.pm.PackageManager.NameNotFoundException
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
@ -19,4 +20,8 @@ fun Context.loadIcon(string: String): Drawable? {
|
|||||||
} catch (e: NameNotFoundException) {
|
} catch (e: NameNotFoundException) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.appName(info: ApplicationInfo): String {
|
||||||
|
return packageManager.getApplicationLabel(info).toString()
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user