feat: select patch bundle from storage

Co-authored-by: Canny <canny1913@outlook.com>
This commit is contained in:
Ushie 2022-10-12 15:14:24 +03:00 committed by GitHub
parent 7b19a4fb83
commit 69df08e0ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 75 deletions

View File

@ -26,5 +26,10 @@
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://maven.pkg.github.com/revanced/revanced-patcher" />
</remote-repository>
</component>
</project>

View File

@ -1,5 +1,6 @@
package app.revanced.manager.ui.screen.subscreens
import android.annotation.SuppressLint
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@ -9,7 +10,6 @@ import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@ -30,6 +30,7 @@ import app.revanced.patcher.extensions.PatchExtensions.version
import com.xinto.taxi.BackstackNavigator
import org.koin.androidx.compose.getViewModel
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PatchesSelectorSubscreen(
@ -39,7 +40,6 @@ fun PatchesSelectorSubscreen(
val patches = pvm.getFilteredPatchesAndCheckOptions()
var query by mutableStateOf("")
Scaffold(
topBar = {
MediumTopAppBar(
@ -68,7 +68,7 @@ fun PatchesSelectorSubscreen(
}
}
)
},
}
) { paddingValues ->
Column(
modifier = Modifier
@ -76,6 +76,7 @@ fun PatchesSelectorSubscreen(
) {
when (patchesState) {
is Resource.Success -> {
if (patches.isNotEmpty()) {
Box(
modifier = Modifier
.fillMaxWidth()
@ -131,6 +132,13 @@ fun PatchesSelectorSubscreen(
}
}
}
else {
Column(Modifier.fillMaxSize(), Arrangement.Center, Alignment.CenterHorizontally) {
Text(text = "No compatible patches found.")
}
}
}
else -> LoadingIndicator(null)
}
}

View File

@ -1,38 +1,62 @@
package app.revanced.manager.ui.screen.subscreens
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.ui.component.SourceItem
import app.revanced.manager.ui.navigation.AppDestination
import app.revanced.manager.ui.theme.Typography
import coil.compose.AsyncImage
import app.revanced.manager.ui.viewmodel.PatcherScreenViewModel
import com.xinto.taxi.BackstackNavigator
import org.koin.androidx.compose.getViewModel
import java.nio.file.Files
import java.nio.file.StandardCopyOption
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SourceSelectorSubscreen(
navigator: BackstackNavigator<AppDestination>
navigator: BackstackNavigator<AppDestination>,
pvm: PatcherScreenViewModel = getViewModel()
) {
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
state = rememberTopAppBarState(),
canScroll = { true }
)
val context = LocalContext.current
val filePicker = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
it?.let { uri ->
val patchesFile = context.cacheDir.resolve("patches.jar")
Files.copy(
context.contentResolver.openInputStream(uri),
patchesFile.toPath(),
StandardCopyOption.REPLACE_EXISTING
)
pvm.patchBundleFile = patchesFile.absolutePath
pvm.loadPatches0()
navigator.pop()
return@rememberLauncherForActivityResult
}
Toast.makeText(context, "Couldn't load local patch bundle.", Toast.LENGTH_SHORT).show()
}
Scaffold(
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection),
@ -61,7 +85,7 @@ fun SourceSelectorSubscreen(
) {
ListItem(
modifier = Modifier
.clickable { /* TODO */ },
.clickable { filePicker.launch(arrayOf("application/java-archive")) },
headlineText = { Text(stringResource(R.string.select_bundle_from_storage)) },
leadingContent = {
Icon(

View File

@ -5,6 +5,7 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Parcelable
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.revanced.manager.Variables.patches
@ -12,7 +13,6 @@ import app.revanced.manager.Variables.selectedAppPackage
import app.revanced.manager.Variables.selectedPatches
import app.revanced.manager.api.API
import app.revanced.manager.ui.Resource
import app.revanced.manager.util.tag
import app.revanced.patcher.data.Context
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.options
@ -24,7 +24,8 @@ import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
class PatcherScreenViewModel(private val app: Application, private val api: API) : ViewModel() {
private lateinit var patchBundleFile: String
lateinit var patchBundleFile: String
private val tag = "ReVanced Manager"
init {
viewModelScope.launch {
@ -66,13 +67,13 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
fun getSelectedPackageInfo(): PackageInfo? {
if (selectedAppPackage.value.isPresent) {
return app.packageManager.getPackageArchiveInfo(
return if (selectedAppPackage.value.isPresent) {
app.packageManager.getPackageArchiveInfo(
selectedAppPackage.value.get().publicSourceDir,
PackageManager.GET_META_DATA
)
} else {
return null
null
}
}
@ -95,11 +96,12 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
patchBundleFile = file.absolutePath
loadPatches0()
} catch (e: Exception) {
Log.e("ReVancedManager", "An error occurred while loading patches", e)
Log.e(tag, "An error occurred while loading patches", e)
}
}
fun loadPatches0() {
try {
val patchClasses = PatchBundle.Dex(
patchBundleFile, DexClassLoader(
patchBundleFile,
@ -109,7 +111,12 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
)
).loadPatches()
patches.value = Resource.Success(patchClasses)
Log.d("ReVanced Manager", "Finished loading patches")
} catch (e: Exception) {
Toast.makeText(app, "Failed to load patch bundle.", Toast.LENGTH_LONG).show()
Log.e(tag, "Failed to load patch bundle.", e)
return
}
Toast.makeText(app, "Successfully loaded patch bundle.", Toast.LENGTH_LONG).show()
}
fun getFilteredPatchesAndCheckOptions(): List<PatchClass> {