mirror of
https://github.com/revanced/revanced-manager-compose.git
synced 2025-04-30 06:14:25 +02:00
feat: add settings to select default installer
This commit is contained in:
parent
6ca2268a34
commit
c5d859f990
@ -1,12 +1,21 @@
|
|||||||
package app.revanced.manager.domain.manager
|
package app.revanced.manager.domain.manager
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.domain.manager.base.BasePreferencesManager
|
import app.revanced.manager.domain.manager.base.BasePreferencesManager
|
||||||
import app.revanced.manager.ui.theme.Theme
|
import app.revanced.manager.ui.theme.Theme
|
||||||
|
|
||||||
class PreferencesManager(
|
class PreferencesManager(
|
||||||
context: Context
|
context: Context
|
||||||
) : BasePreferencesManager(context, "settings") {
|
) : BasePreferencesManager(context, "settings") {
|
||||||
|
|
||||||
|
enum class InstallerManager(val displayName: Int) {
|
||||||
|
DEFAULT(R.string.default_installer),
|
||||||
|
SHIZUKU(R.string.shizuku_installer),
|
||||||
|
ROOT(R.string.root_installer),
|
||||||
|
MAGISK(R.string.magisk_installer),
|
||||||
|
}
|
||||||
|
|
||||||
val dynamicColor = booleanPreference("dynamic_color", true)
|
val dynamicColor = booleanPreference("dynamic_color", true)
|
||||||
val theme = enumPreference("theme", Theme.SYSTEM)
|
val theme = enumPreference("theme", Theme.SYSTEM)
|
||||||
|
|
||||||
@ -18,6 +27,7 @@ class PreferencesManager(
|
|||||||
val keystorePass = stringPreference("keystore_pass", KeystoreManager.DEFAULT)
|
val keystorePass = stringPreference("keystore_pass", KeystoreManager.DEFAULT)
|
||||||
|
|
||||||
val preferSplits = booleanPreference("prefer_splits", false)
|
val preferSplits = booleanPreference("prefer_splits", false)
|
||||||
|
val installer = enumPreference("installer", InstallerManager.DEFAULT)
|
||||||
|
|
||||||
val showAutoUpdatesDialog = booleanPreference("show_auto_updates_dialog", true)
|
val showAutoUpdatesDialog = booleanPreference("show_auto_updates_dialog", true)
|
||||||
val managerAutoUpdates = booleanPreference("manager_auto_updates", false)
|
val managerAutoUpdates = booleanPreference("manager_auto_updates", false)
|
||||||
|
@ -5,18 +5,24 @@ import android.os.Build
|
|||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Http
|
import androidx.compose.material.icons.outlined.Http
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.FilledTonalButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
@ -26,6 +32,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
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
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@ -33,10 +40,12 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.GroupHeader
|
import app.revanced.manager.ui.component.GroupHeader
|
||||||
import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel
|
import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel
|
||||||
import org.koin.androidx.compose.getViewModel
|
import org.koin.androidx.compose.getViewModel
|
||||||
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -44,7 +53,9 @@ fun AdvancedSettingsScreen(
|
|||||||
onBackClick: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
vm: AdvancedSettingsViewModel = getViewModel()
|
vm: AdvancedSettingsViewModel = getViewModel()
|
||||||
) {
|
) {
|
||||||
|
val prefs = vm.prefs
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
var showInstallerPicker by rememberSaveable { mutableStateOf(false) }
|
||||||
val memoryLimit = remember {
|
val memoryLimit = remember {
|
||||||
val activityManager = context.getSystemService<ActivityManager>()!!
|
val activityManager = context.getSystemService<ActivityManager>()!!
|
||||||
context.getString(
|
context.getString(
|
||||||
@ -54,6 +65,13 @@ fun AdvancedSettingsScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showInstallerPicker) {
|
||||||
|
InstallerPicker(
|
||||||
|
onDismiss = { showInstallerPicker = false },
|
||||||
|
onConfirm = { vm.setInstaller(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppTopBar(
|
AppTopBar(
|
||||||
@ -99,6 +117,26 @@ fun AdvancedSettingsScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val installer by prefs.installer.getAsState()
|
||||||
|
GroupHeader(stringResource(R.string.installer))
|
||||||
|
ListItem(
|
||||||
|
modifier = Modifier.clickable { showInstallerPicker = true },
|
||||||
|
headlineContent = { Text(stringResource(R.string.installer)) },
|
||||||
|
supportingContent = { Text(stringResource(R.string.installer_description)) },
|
||||||
|
trailingContent = {
|
||||||
|
FilledTonalButton(
|
||||||
|
colors = ButtonDefaults.filledTonalButtonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||||
|
),
|
||||||
|
onClick = {
|
||||||
|
showInstallerPicker = true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(stringResource(installer.displayName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
GroupHeader(stringResource(R.string.device))
|
GroupHeader(stringResource(R.string.device))
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = { Text(stringResource(R.string.device_model)) },
|
headlineContent = { Text(stringResource(R.string.device_model)) },
|
||||||
@ -173,3 +211,42 @@ private fun APIUrlDialog(currentUrl: String, onSubmit: (String?) -> Unit) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun InstallerPicker(
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (PreferencesManager.InstallerManager) -> Unit,
|
||||||
|
prefs: PreferencesManager = koinInject()
|
||||||
|
) {
|
||||||
|
var selectedInstaller by rememberSaveable { mutableStateOf(prefs.installer.getBlocking()) }
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
title = { Text(stringResource(R.string.installer)) },
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
PreferencesManager.InstallerManager.values().forEach {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { selectedInstaller = it },
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
RadioButton(
|
||||||
|
selected = selectedInstaller == it,
|
||||||
|
onClick = { selectedInstaller = it })
|
||||||
|
Text(stringResource(it.displayName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
Button(onClick = {
|
||||||
|
onConfirm(selectedInstaller)
|
||||||
|
onDismiss()
|
||||||
|
}) {
|
||||||
|
Text(stringResource(R.string.apply))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package app.revanced.manager.ui.screen.settings
|
package app.revanced.manager.ui.screen.settings
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
@ -23,7 +22,6 @@ import app.revanced.manager.ui.component.GroupHeader
|
|||||||
import app.revanced.manager.ui.component.settings.BooleanItem
|
import app.revanced.manager.ui.component.settings.BooleanItem
|
||||||
import app.revanced.manager.ui.theme.Theme
|
import app.revanced.manager.ui.theme.Theme
|
||||||
import app.revanced.manager.ui.viewmodel.SettingsViewModel
|
import app.revanced.manager.ui.viewmodel.SettingsViewModel
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -65,7 +63,10 @@ fun GeneralSettingsScreen(
|
|||||||
headlineContent = { Text(stringResource(R.string.theme)) },
|
headlineContent = { Text(stringResource(R.string.theme)) },
|
||||||
supportingContent = { Text(stringResource(R.string.theme_description)) },
|
supportingContent = { Text(stringResource(R.string.theme_description)) },
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
Button(
|
FilledTonalButton(
|
||||||
|
colors = ButtonDefaults.filledTonalButtonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.primaryContainer,
|
||||||
|
),
|
||||||
onClick = {
|
onClick = {
|
||||||
showThemePicker = true
|
showThemePicker = true
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class AdvancedSettingsViewModel(
|
class AdvancedSettingsViewModel(
|
||||||
prefs: PreferencesManager,
|
val prefs: PreferencesManager,
|
||||||
private val app: Application,
|
private val app: Application,
|
||||||
private val patchBundleRepository: PatchBundleRepository
|
private val patchBundleRepository: PatchBundleRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
@ -34,4 +34,8 @@ class AdvancedSettingsViewModel(
|
|||||||
fun resetBundles() = viewModelScope.launch {
|
fun resetBundles() = viewModelScope.launch {
|
||||||
patchBundleRepository.reset()
|
patchBundleRepository.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setInstaller(installer: PreferencesManager.InstallerManager) = viewModelScope.launch {
|
||||||
|
prefs.installer.update(installer)
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ import androidx.work.WorkInfo
|
|||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import app.revanced.manager.domain.manager.KeystoreManager
|
import app.revanced.manager.domain.manager.KeystoreManager
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
import app.revanced.manager.domain.worker.WorkerRepository
|
import app.revanced.manager.domain.worker.WorkerRepository
|
||||||
import app.revanced.manager.patcher.worker.PatcherProgressManager
|
import app.revanced.manager.patcher.worker.PatcherProgressManager
|
||||||
import app.revanced.manager.patcher.worker.PatcherWorker
|
import app.revanced.manager.patcher.worker.PatcherWorker
|
||||||
@ -52,6 +53,7 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
|
|||||||
private val pm: PM by inject()
|
private val pm: PM by inject()
|
||||||
private val workerRepository: WorkerRepository by inject()
|
private val workerRepository: WorkerRepository by inject()
|
||||||
|
|
||||||
|
val prefs: PreferencesManager by inject()
|
||||||
val packageName: String = input.selectedApp.packageName
|
val packageName: String = input.selectedApp.packageName
|
||||||
private val outputFile = File(app.cacheDir, "output.apk")
|
private val outputFile = File(app.cacheDir, "output.apk")
|
||||||
private val signedFile = File(app.cacheDir, "signed.apk").also { if (it.exists()) it.delete() }
|
private val signedFile = File(app.cacheDir, "signed.apk").also { if (it.exists()) it.delete() }
|
||||||
@ -62,6 +64,7 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
|
|||||||
var installedPackageName by mutableStateOf<String?>(null)
|
var installedPackageName by mutableStateOf<String?>(null)
|
||||||
private set
|
private set
|
||||||
val appButtonText by derivedStateOf { if (installedPackageName == null) R.string.install_app else R.string.open_app }
|
val appButtonText by derivedStateOf { if (installedPackageName == null) R.string.install_app else R.string.open_app }
|
||||||
|
private val selectedInstaller by derivedStateOf { prefs.installer.getBlocking() }
|
||||||
|
|
||||||
private val workManager = WorkManager.getInstance(app)
|
private val workManager = WorkManager.getInstance(app)
|
||||||
|
|
||||||
@ -189,9 +192,22 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
|
|||||||
isInstalling = true
|
isInstalling = true
|
||||||
try {
|
try {
|
||||||
if (!signApk()) return@launch
|
if (!signApk()) return@launch
|
||||||
//
|
|
||||||
// pm.installApp(listOf(signedFile))
|
when (selectedInstaller) {
|
||||||
|
PreferencesManager.InstallerManager.DEFAULT -> {
|
||||||
|
pm.installApp(listOf(signedFile))
|
||||||
|
}
|
||||||
|
PreferencesManager.InstallerManager.SHIZUKU -> {
|
||||||
ShizukuApi.installPackage(signedFile)
|
ShizukuApi.installPackage(signedFile)
|
||||||
|
}
|
||||||
|
PreferencesManager.InstallerManager.ROOT -> {
|
||||||
|
// RootApi.installPackage(signedFile)
|
||||||
|
}
|
||||||
|
PreferencesManager.InstallerManager.MAGISK -> {
|
||||||
|
// MagiskApi.installPackage(signedFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
isInstalling = false
|
isInstalling = false
|
||||||
}
|
}
|
||||||
|
@ -233,4 +233,9 @@
|
|||||||
<string name="shizuku_available">Shizuku service available</string>
|
<string name="shizuku_available">Shizuku service available</string>
|
||||||
<string name="shizuku_unavailable">Shizuku service not connected</string>
|
<string name="shizuku_unavailable">Shizuku service not connected</string>
|
||||||
<string name="home_shizuku_warning">Some functions unavailable</string>
|
<string name="home_shizuku_warning">Some functions unavailable</string>
|
||||||
|
<string name="installer_description">Choose the default installer</string>
|
||||||
|
<string name="default_installer">Default</string>
|
||||||
|
<string name="shizuku_installer">Shizuku</string>
|
||||||
|
<string name="root_installer">Root</string>
|
||||||
|
<string name="magisk_installer">Magisk</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user