mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-05-03 15:24:25 +02:00
Merge branch 'compose-dev' into compose/downloader-system
This commit is contained in:
commit
9ddd421b2a
6
.github/workflows/pr-build.yml
vendored
6
.github/workflows/pr-build.yml
vendored
@ -23,8 +23,8 @@ jobs:
|
|||||||
java-version: '17'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Set up Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/actions/setup-gradle@v3
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
env:
|
env:
|
||||||
@ -38,7 +38,7 @@ jobs:
|
|||||||
run: mv app/build/outputs/apk/release/app-release.apk revanced-manager-${{ env.COMMIT_HASH }}.apk
|
run: mv app/build/outputs/apk/release/app-release.apk revanced-manager-${{ env.COMMIT_HASH }}.apk
|
||||||
|
|
||||||
- name: Upload build
|
- name: Upload build
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: revanced-manager
|
name: revanced-manager
|
||||||
path: revanced-manager-${{ env.COMMIT_HASH }}.apk
|
path: revanced-manager-${{ env.COMMIT_HASH }}.apk
|
||||||
|
6
.github/workflows/release-build.yml
vendored
6
.github/workflows/release-build.yml
vendored
@ -20,10 +20,8 @@ jobs:
|
|||||||
java-version: '17'
|
java-version: '17'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Set up Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/actions/setup-gradle@v3
|
||||||
with:
|
|
||||||
cache-disabled: true
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
env:
|
env:
|
||||||
|
2
.github/workflows/update-documentation.yml
vendored
2
.github/workflows/update-documentation.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
name: Dispatch event to documentation repository
|
name: Dispatch event to documentation repository
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
steps:
|
steps:
|
||||||
- uses: peter-evans/repository-dispatch@v2
|
- uses: peter-evans/repository-dispatch@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.DOCUMENTATION_REPO_ACCESS_TOKEN }}
|
token: ${{ secrets.DOCUMENTATION_REPO_ACCESS_TOKEN }}
|
||||||
repository: revanced/revanced-documentation
|
repository: revanced/revanced-documentation
|
||||||
|
@ -44,7 +44,7 @@ fun AlertDialogExtended(
|
|||||||
titleContentColor: Color = AlertDialogDefaults.titleContentColor,
|
titleContentColor: Color = AlertDialogDefaults.titleContentColor,
|
||||||
textContentColor: Color = AlertDialogDefaults.textContentColor,
|
textContentColor: Color = AlertDialogDefaults.textContentColor,
|
||||||
tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
|
tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
|
||||||
textHorizontalPadding: PaddingValues = PaddingValues(horizontal = 24.dp)
|
textHorizontalPadding: PaddingValues = TextHorizontalPadding
|
||||||
) {
|
) {
|
||||||
BasicAlertDialog(onDismissRequest = onDismissRequest) {
|
BasicAlertDialog(onDismissRequest = onDismissRequest) {
|
||||||
Surface(
|
Surface(
|
||||||
@ -147,4 +147,6 @@ private fun ContentStyle(
|
|||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val TextHorizontalPadding = PaddingValues(horizontal = 24.dp)
|
@ -18,7 +18,8 @@ fun Markdown(
|
|||||||
colors = markdownColor(
|
colors = markdownColor(
|
||||||
text = MaterialTheme.colorScheme.onSurfaceVariant,
|
text = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
codeBackground = MaterialTheme.colorScheme.secondaryContainer,
|
codeBackground = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
codeText = MaterialTheme.colorScheme.onSecondaryContainer
|
codeText = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||||
|
linkText = MaterialTheme.colorScheme.primary
|
||||||
),
|
),
|
||||||
typography = markdownTypography(
|
typography = markdownTypography(
|
||||||
h1 = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold),
|
h1 = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold),
|
||||||
|
@ -4,52 +4,55 @@ import android.net.Uri
|
|||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Close
|
|
||||||
import androidx.compose.material.icons.filled.Topic
|
import androidx.compose.material.icons.filled.Topic
|
||||||
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
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.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.Role
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import androidx.compose.ui.window.DialogProperties
|
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
|
import app.revanced.manager.ui.component.AlertDialogExtended
|
||||||
|
import app.revanced.manager.ui.component.TextHorizontalPadding
|
||||||
import app.revanced.manager.ui.model.BundleType
|
import app.revanced.manager.ui.model.BundleType
|
||||||
import app.revanced.manager.util.APK_MIMETYPE
|
import app.revanced.manager.util.APK_MIMETYPE
|
||||||
import app.revanced.manager.util.JAR_MIMETYPE
|
import app.revanced.manager.util.JAR_MIMETYPE
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImportBundleDialog(
|
fun ImportPatchBundleDialog(
|
||||||
onDismissRequest: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onRemoteSubmit: (String, Boolean) -> Unit,
|
onRemoteSubmit: (String, Boolean) -> Unit,
|
||||||
onLocalSubmit: (Uri, Uri?) -> Unit,
|
onLocalSubmit: (Uri, Uri?) -> Unit
|
||||||
initialBundleType: BundleType
|
|
||||||
) {
|
) {
|
||||||
var remoteUrl by rememberSaveable { mutableStateOf("") }
|
var currentStep by rememberSaveable { mutableIntStateOf(0) }
|
||||||
var autoUpdate by rememberSaveable { mutableStateOf(true) }
|
var bundleType by rememberSaveable { mutableStateOf(BundleType.Remote) }
|
||||||
var bundleType by rememberSaveable { mutableStateOf(initialBundleType) }
|
|
||||||
var patchBundle by rememberSaveable { mutableStateOf<Uri?>(null) }
|
var patchBundle by rememberSaveable { mutableStateOf<Uri?>(null) }
|
||||||
var integrations by rememberSaveable { mutableStateOf<Uri?>(null) }
|
var integrations by rememberSaveable { mutableStateOf<Uri?>(null) }
|
||||||
|
var remoteUrl by rememberSaveable { mutableStateOf("") }
|
||||||
val inputsAreValid by remember {
|
var autoUpdate by rememberSaveable { mutableStateOf(false) }
|
||||||
derivedStateOf {
|
|
||||||
if (bundleType == BundleType.Local) patchBundle != null else remoteUrl.isNotEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val patchActivityLauncher =
|
val patchActivityLauncher =
|
||||||
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||||
@ -69,97 +72,208 @@ fun ImportBundleDialog(
|
|||||||
integrationsActivityLauncher.launch(APK_MIMETYPE)
|
integrationsActivityLauncher.launch(APK_MIMETYPE)
|
||||||
}
|
}
|
||||||
|
|
||||||
Dialog(
|
val steps = listOf<@Composable () -> Unit>(
|
||||||
onDismissRequest = onDismissRequest,
|
{
|
||||||
properties = DialogProperties(
|
SelectBundleTypeStep(bundleType) { selectedType ->
|
||||||
usePlatformDefaultWidth = false,
|
bundleType = selectedType
|
||||||
dismissOnBackPress = true
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
BundleTopBar(
|
|
||||||
title = stringResource(R.string.import_bundle),
|
|
||||||
onBackClick = onDismissRequest,
|
|
||||||
backIcon = {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Close,
|
|
||||||
contentDescription = stringResource(R.string.close)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
TextButton(
|
|
||||||
enabled = inputsAreValid,
|
|
||||||
onClick = {
|
|
||||||
when (bundleType) {
|
|
||||||
BundleType.Local -> onLocalSubmit(patchBundle!!, integrations)
|
|
||||||
BundleType.Remote -> onRemoteSubmit(remoteUrl, autoUpdate)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(end = 16.dp)
|
|
||||||
) {
|
|
||||||
Text(stringResource(R.string.import_))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { paddingValues ->
|
|
||||||
BaseBundleDialog(
|
|
||||||
modifier = Modifier.padding(paddingValues),
|
|
||||||
isDefault = false,
|
|
||||||
name = null,
|
|
||||||
remoteUrl = remoteUrl.takeUnless { bundleType == BundleType.Local },
|
|
||||||
onRemoteUrlChange = { remoteUrl = it },
|
|
||||||
patchCount = 0,
|
|
||||||
version = null,
|
|
||||||
autoUpdate = autoUpdate,
|
|
||||||
onAutoUpdateChange = { autoUpdate = it },
|
|
||||||
onPatchesClick = {},
|
|
||||||
onBundleTypeClick = {
|
|
||||||
bundleType = when (bundleType) {
|
|
||||||
BundleType.Local -> BundleType.Remote
|
|
||||||
BundleType.Remote -> BundleType.Local
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
if (bundleType == BundleType.Remote) return@BaseBundleDialog
|
|
||||||
|
|
||||||
BundleListItem(
|
|
||||||
headlineText = stringResource(R.string.patch_bundle_field),
|
|
||||||
supportingText = stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set),
|
|
||||||
trailingContent = {
|
|
||||||
IconButton(
|
|
||||||
onClick = ::launchPatchActivity
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Topic,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
launchPatchActivity()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
BundleListItem(
|
|
||||||
headlineText = stringResource(R.string.integrations_field),
|
|
||||||
supportingText = stringResource(if (integrations != null) R.string.file_field_set else R.string.file_field_not_set),
|
|
||||||
trailingContent = {
|
|
||||||
IconButton(
|
|
||||||
onClick = ::launchIntegrationsActivity
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Topic,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier.clickable {
|
|
||||||
launchIntegrationsActivity()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ImportBundleStep(
|
||||||
|
bundleType,
|
||||||
|
patchBundle,
|
||||||
|
integrations,
|
||||||
|
remoteUrl,
|
||||||
|
autoUpdate,
|
||||||
|
{ launchPatchActivity() },
|
||||||
|
{ launchIntegrationsActivity() },
|
||||||
|
{ remoteUrl = it },
|
||||||
|
{ autoUpdate = it }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val inputsAreValid by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
(bundleType == BundleType.Local && patchBundle != null) ||
|
||||||
|
(bundleType == BundleType.Remote && remoteUrl.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialogExtended(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
title = {
|
||||||
|
Text(stringResource(if (currentStep == 0) R.string.select else R.string.add_patch_bundle))
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
steps[currentStep]()
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
if (currentStep == steps.lastIndex) {
|
||||||
|
TextButton(
|
||||||
|
enabled = inputsAreValid,
|
||||||
|
onClick = {
|
||||||
|
when (bundleType) {
|
||||||
|
BundleType.Local -> patchBundle?.let {
|
||||||
|
onLocalSubmit(
|
||||||
|
it,
|
||||||
|
integrations
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BundleType.Remote -> onRemoteSubmit(remoteUrl, autoUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.add))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TextButton(onClick = { currentStep++ }) {
|
||||||
|
Text(stringResource(R.string.next))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
if (currentStep > 0) {
|
||||||
|
TextButton(onClick = { currentStep-- }) {
|
||||||
|
Text(stringResource(R.string.back))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TextButton(onClick = onDismiss) {
|
||||||
|
Text(stringResource(R.string.cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
textHorizontalPadding = PaddingValues(0.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SelectBundleTypeStep(
|
||||||
|
bundleType: BundleType,
|
||||||
|
onBundleTypeSelected: (BundleType) -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
|
text = stringResource(R.string.select_bundle_type_dialog_description)
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
ListItem(
|
||||||
|
modifier = Modifier.clickable(
|
||||||
|
role = Role.RadioButton,
|
||||||
|
onClick = { onBundleTypeSelected(BundleType.Remote) }
|
||||||
|
),
|
||||||
|
headlineContent = { Text(stringResource(R.string.enter_url)) },
|
||||||
|
overlineContent = { Text(stringResource(R.string.recommended)) },
|
||||||
|
supportingContent = { Text(stringResource(R.string.remote_bundle_description)) },
|
||||||
|
leadingContent = {
|
||||||
|
RadioButton(
|
||||||
|
selected = bundleType == BundleType.Remote,
|
||||||
|
onClick = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp))
|
||||||
|
ListItem(
|
||||||
|
modifier = Modifier.clickable(
|
||||||
|
role = Role.RadioButton,
|
||||||
|
onClick = { onBundleTypeSelected(BundleType.Local) }
|
||||||
|
),
|
||||||
|
headlineContent = { Text(stringResource(R.string.select_from_storage)) },
|
||||||
|
supportingContent = { Text(stringResource(R.string.local_bundle_description)) },
|
||||||
|
overlineContent = { },
|
||||||
|
leadingContent = {
|
||||||
|
RadioButton(
|
||||||
|
selected = bundleType == BundleType.Local,
|
||||||
|
onClick = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ImportBundleStep(
|
||||||
|
bundleType: BundleType,
|
||||||
|
patchBundle: Uri?,
|
||||||
|
integrations: Uri?,
|
||||||
|
remoteUrl: String,
|
||||||
|
autoUpdate: Boolean,
|
||||||
|
launchPatchActivity: () -> Unit,
|
||||||
|
launchIntegrationsActivity: () -> Unit,
|
||||||
|
onRemoteUrlChange: (String) -> Unit,
|
||||||
|
onAutoUpdateChange: (Boolean) -> Unit
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
when (bundleType) {
|
||||||
|
BundleType.Local -> {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text(stringResource(R.string.patch_bundle_field))
|
||||||
|
},
|
||||||
|
supportingContent = { Text(stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
||||||
|
trailingContent = {
|
||||||
|
IconButton(onClick = launchPatchActivity) {
|
||||||
|
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.clickable { launchPatchActivity() }
|
||||||
|
)
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text(stringResource(R.string.integrations_field))
|
||||||
|
},
|
||||||
|
supportingContent = { Text(stringResource(if (integrations != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
||||||
|
trailingContent = {
|
||||||
|
IconButton(onClick = launchIntegrationsActivity) {
|
||||||
|
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.clickable { launchIntegrationsActivity() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BundleType.Remote -> {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(TextHorizontalPadding)
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = remoteUrl,
|
||||||
|
onValueChange = onRemoteUrlChange,
|
||||||
|
label = { Text(stringResource(R.string.bundle_url)) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
modifier = Modifier.clickable(
|
||||||
|
role = Role.Checkbox,
|
||||||
|
onClick = { onAutoUpdateChange(!autoUpdate) }
|
||||||
|
),
|
||||||
|
headlineContent = { Text(stringResource(R.string.auto_update)) },
|
||||||
|
leadingContent = {
|
||||||
|
CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) {
|
||||||
|
Checkbox(
|
||||||
|
checked = autoUpdate,
|
||||||
|
onCheckedChange = {
|
||||||
|
onAutoUpdateChange(!autoUpdate)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,95 +0,0 @@
|
|||||||
package app.revanced.manager.ui.component.bundle
|
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.ListItem
|
|
||||||
import androidx.compose.material3.RadioButton
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.semantics.Role
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import app.revanced.manager.R
|
|
||||||
import app.revanced.manager.ui.component.AlertDialogExtended
|
|
||||||
import app.revanced.manager.ui.model.BundleType
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ImportBundleTypeSelectorDialog(
|
|
||||||
onDismiss: () -> Unit,
|
|
||||||
onConfirm: (BundleType) -> Unit,
|
|
||||||
) {
|
|
||||||
var bundleType: BundleType by rememberSaveable { mutableStateOf(BundleType.Remote) }
|
|
||||||
|
|
||||||
AlertDialogExtended(
|
|
||||||
onDismissRequest = onDismiss,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(
|
|
||||||
onClick = { onConfirm(bundleType) }
|
|
||||||
) {
|
|
||||||
Text(stringResource(R.string.select))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = onDismiss) {
|
|
||||||
Text(stringResource(R.string.cancel))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Text(stringResource(R.string.select_bundle_type_dialog_title))
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.spacedBy(24.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
|
||||||
text = stringResource(R.string.select_bundle_type_dialog_description)
|
|
||||||
)
|
|
||||||
Column {
|
|
||||||
ListItem(
|
|
||||||
modifier = Modifier.clickable(
|
|
||||||
role = Role.RadioButton,
|
|
||||||
onClick = { bundleType = BundleType.Remote }
|
|
||||||
),
|
|
||||||
headlineContent = { Text(stringResource(R.string.remote)) },
|
|
||||||
overlineContent = { Text(stringResource(R.string.recommended)) },
|
|
||||||
supportingContent = { Text(stringResource(R.string.remote_bundle_description)) },
|
|
||||||
leadingContent = {
|
|
||||||
RadioButton(
|
|
||||||
selected = bundleType == BundleType.Remote,
|
|
||||||
onClick = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp))
|
|
||||||
ListItem(
|
|
||||||
modifier = Modifier.clickable(
|
|
||||||
role = Role.RadioButton,
|
|
||||||
onClick = { bundleType = BundleType.Local }
|
|
||||||
),
|
|
||||||
headlineContent = { Text(stringResource(R.string.local)) },
|
|
||||||
supportingContent = { Text(stringResource(R.string.local_bundle_description)) },
|
|
||||||
overlineContent = { }, // we're using this parameter to force the 3-line ListItem state
|
|
||||||
leadingContent = {
|
|
||||||
RadioButton(
|
|
||||||
selected = bundleType == BundleType.Local,
|
|
||||||
onClick = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
textHorizontalPadding = PaddingValues(0.dp)
|
|
||||||
)
|
|
||||||
}
|
|
@ -55,10 +55,6 @@ fun Changelog(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Tag(
|
|
||||||
Icons.Outlined.Sell,
|
|
||||||
version
|
|
||||||
)
|
|
||||||
Tag(
|
Tag(
|
||||||
Icons.Outlined.FileDownload,
|
Icons.Outlined.FileDownload,
|
||||||
downloadCount
|
downloadCount
|
||||||
|
@ -58,9 +58,7 @@ import app.revanced.manager.ui.component.AutoUpdatesDialog
|
|||||||
import app.revanced.manager.ui.component.NotificationCard
|
import app.revanced.manager.ui.component.NotificationCard
|
||||||
import app.revanced.manager.ui.component.bundle.BundleItem
|
import app.revanced.manager.ui.component.bundle.BundleItem
|
||||||
import app.revanced.manager.ui.component.bundle.BundleTopBar
|
import app.revanced.manager.ui.component.bundle.BundleTopBar
|
||||||
import app.revanced.manager.ui.component.bundle.ImportBundleDialog
|
import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
|
||||||
import app.revanced.manager.ui.component.bundle.ImportBundleTypeSelectorDialog
|
|
||||||
import app.revanced.manager.ui.model.BundleType
|
|
||||||
import app.revanced.manager.ui.viewmodel.DashboardViewModel
|
import app.revanced.manager.ui.viewmodel.DashboardViewModel
|
||||||
import app.revanced.manager.util.toast
|
import app.revanced.manager.util.toast
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -100,33 +98,17 @@ fun DashboardScreen(
|
|||||||
val firstLaunch by vm.prefs.firstLaunch.getAsState()
|
val firstLaunch by vm.prefs.firstLaunch.getAsState()
|
||||||
if (firstLaunch) AutoUpdatesDialog(vm::applyAutoUpdatePrefs)
|
if (firstLaunch) AutoUpdatesDialog(vm::applyAutoUpdatePrefs)
|
||||||
|
|
||||||
var selectedBundleType: BundleType? by rememberSaveable { mutableStateOf(null) }
|
var showAddBundleDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
selectedBundleType?.let {
|
if (showAddBundleDialog) {
|
||||||
fun dismiss() {
|
ImportPatchBundleDialog(
|
||||||
selectedBundleType = null
|
onDismiss = { showAddBundleDialog = false },
|
||||||
}
|
|
||||||
|
|
||||||
ImportBundleDialog(
|
|
||||||
onDismissRequest = ::dismiss,
|
|
||||||
onLocalSubmit = { patches, integrations ->
|
onLocalSubmit = { patches, integrations ->
|
||||||
dismiss()
|
showAddBundleDialog = false
|
||||||
vm.createLocalSource(patches, integrations)
|
vm.createLocalSource(patches, integrations)
|
||||||
},
|
},
|
||||||
onRemoteSubmit = { url, autoUpdate ->
|
onRemoteSubmit = { url, autoUpdate ->
|
||||||
dismiss()
|
showAddBundleDialog = false
|
||||||
vm.createRemoteSource(url, autoUpdate)
|
vm.createRemoteSource(url, autoUpdate)
|
||||||
},
|
|
||||||
initialBundleType = it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var showBundleTypeSelectorDialog by rememberSaveable { mutableStateOf(false) }
|
|
||||||
if (showBundleTypeSelectorDialog) {
|
|
||||||
ImportBundleTypeSelectorDialog(
|
|
||||||
onDismiss = { showBundleTypeSelectorDialog = false },
|
|
||||||
onConfirm = {
|
|
||||||
selectedBundleType = it
|
|
||||||
showBundleTypeSelectorDialog = false
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -200,7 +182,7 @@ fun DashboardScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DashboardPage.BUNDLES.ordinal -> {
|
DashboardPage.BUNDLES.ordinal -> {
|
||||||
showBundleTypeSelectorDialog = true
|
showAddBundleDialog = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +220,6 @@ fun DashboardScreen(
|
|||||||
if (vm.showBatteryOptimizationsWarning) {
|
if (vm.showBatteryOptimizationsWarning) {
|
||||||
{
|
{
|
||||||
NotificationCard(
|
NotificationCard(
|
||||||
modifier = Modifier.padding(16.dp),
|
|
||||||
isWarning = true,
|
isWarning = true,
|
||||||
icon = Icons.Default.BatteryAlert,
|
icon = Icons.Default.BatteryAlert,
|
||||||
text = stringResource(R.string.battery_optimization_notification),
|
text = stringResource(R.string.battery_optimization_notification),
|
||||||
@ -260,7 +241,7 @@ fun DashboardScreen(
|
|||||||
Text(stringResource(R.string.dismiss))
|
Text(stringResource(R.string.dismiss))
|
||||||
}
|
}
|
||||||
TextButton(onClick = onUpdateClick) {
|
TextButton(onClick = onUpdateClick) {
|
||||||
Text(stringResource(R.string.update))
|
Text(stringResource(R.string.show))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -3,12 +3,13 @@ package app.revanced.manager.ui.screen
|
|||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
|
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
|
||||||
|
import androidx.compose.material.icons.filled.AutoFixHigh
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
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
|
||||||
@ -26,6 +27,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.ui.component.AppInfo
|
import app.revanced.manager.ui.component.AppInfo
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
|
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||||
import app.revanced.manager.ui.destination.SelectedAppInfoDestination
|
import app.revanced.manager.ui.destination.SelectedAppInfoDestination
|
||||||
import app.revanced.manager.ui.model.BundleInfo.Extensions.bundleInfoFlow
|
import app.revanced.manager.ui.model.BundleInfo.Extensions.bundleInfoFlow
|
||||||
import app.revanced.manager.ui.model.SelectedApp
|
import app.revanced.manager.ui.model.SelectedApp
|
||||||
@ -164,9 +166,16 @@ private fun SelectedAppInfoScreen(
|
|||||||
title = stringResource(R.string.app_info),
|
title = stringResource(R.string.app_info),
|
||||||
onBackClick = onBackClick
|
onBackClick = onBackClick
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
floatingActionButton = {
|
||||||
|
ExtendedFloatingActionButton(
|
||||||
|
text = { Text(stringResource(R.string.patch)) },
|
||||||
|
icon = { Icon(Icons.Default.AutoFixHigh, null) },
|
||||||
|
onClick = onPatchClick
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(
|
ColumnWithScrollbar(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
@ -179,15 +188,6 @@ private fun SelectedAppInfoScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
PageItem(R.string.patch, stringResource(R.string.patch_item_description), onPatchClick)
|
|
||||||
|
|
||||||
Text(
|
|
||||||
stringResource(R.string.advanced),
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 8.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
PageItem(
|
PageItem(
|
||||||
R.string.patch_selector_item,
|
R.string.patch_selector_item,
|
||||||
stringResource(R.string.patch_selector_item_description, selectedPatchCount),
|
stringResource(R.string.patch_selector_item_description, selectedPatchCount),
|
||||||
|
@ -10,7 +10,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
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.Api
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -32,6 +32,7 @@ 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 androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import app.revanced.manager.BuildConfig
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||||
@ -145,22 +146,17 @@ fun AdvancedSettingsScreen(
|
|||||||
description = R.string.patch_selection_safeguard_description
|
description = R.string.patch_selection_safeguard_description
|
||||||
)
|
)
|
||||||
|
|
||||||
GroupHeader(stringResource(R.string.device))
|
GroupHeader(stringResource(R.string.debugging))
|
||||||
SettingsListItem(
|
SettingsListItem(
|
||||||
headlineContent = stringResource(R.string.device_model),
|
headlineContent = stringResource(R.string.about_device),
|
||||||
supportingContent = Build.MODEL
|
supportingContent = """
|
||||||
)
|
**Version**: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})
|
||||||
SettingsListItem(
|
**Build type**: ${BuildConfig.BUILD_TYPE}
|
||||||
headlineContent = stringResource(R.string.device_android_version),
|
**Model**: ${Build.MODEL}
|
||||||
supportingContent = Build.VERSION.RELEASE
|
**Android version**: ${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})
|
||||||
)
|
**Supported Archs**: ${Build.SUPPORTED_ABIS.joinToString(", ")}
|
||||||
SettingsListItem(
|
**Memory limit**: $memoryLimit
|
||||||
headlineContent = stringResource(R.string.device_architectures),
|
""".trimIndent()
|
||||||
supportingContent = Build.SUPPORTED_ABIS.joinToString(", ")
|
|
||||||
)
|
|
||||||
SettingsListItem(
|
|
||||||
headlineContent = stringResource(R.string.device_memory_limit),
|
|
||||||
supportingContent = memoryLimit
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +183,7 @@ private fun APIUrlDialog(currentUrl: String, onSubmit: (String?) -> Unit) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon = {
|
icon = {
|
||||||
Icon(Icons.Outlined.Http, null)
|
Icon(Icons.Outlined.Api, null)
|
||||||
},
|
},
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
|
@ -112,7 +112,7 @@ private fun ThemePicker(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
Button(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
onConfirm(selectedTheme)
|
onConfirm(selectedTheme)
|
||||||
onDismiss()
|
onDismiss()
|
||||||
|
@ -56,7 +56,7 @@ fun UpdateScreen(
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
AppTopBar(
|
AppTopBar(
|
||||||
title = stringResource(R.string.updates),
|
title = stringResource(R.string.update),
|
||||||
onBackClick = onBackClick
|
onBackClick = onBackClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import android.os.Build
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.foundation.ScrollState
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
@ -175,6 +176,9 @@ fun String.relativeTime(context: Context): String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const val isScrollingUpSensitivity = 10
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LazyListState.isScrollingUp(): State<Boolean> {
|
fun LazyListState.isScrollingUp(): State<Boolean> {
|
||||||
return remember(this) {
|
return remember(this) {
|
||||||
@ -182,10 +186,16 @@ fun LazyListState.isScrollingUp(): State<Boolean> {
|
|||||||
var previousScrollOffset by mutableIntStateOf(firstVisibleItemScrollOffset)
|
var previousScrollOffset by mutableIntStateOf(firstVisibleItemScrollOffset)
|
||||||
|
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (previousIndex != firstVisibleItemIndex) {
|
val indexChanged = previousIndex != firstVisibleItemIndex
|
||||||
|
val offsetChanged =
|
||||||
|
kotlin.math.abs(previousScrollOffset - firstVisibleItemScrollOffset) > isScrollingUpSensitivity
|
||||||
|
|
||||||
|
if (indexChanged) {
|
||||||
previousIndex > firstVisibleItemIndex
|
previousIndex > firstVisibleItemIndex
|
||||||
|
} else if (offsetChanged) {
|
||||||
|
previousScrollOffset > firstVisibleItemScrollOffset
|
||||||
} else {
|
} else {
|
||||||
previousScrollOffset >= firstVisibleItemScrollOffset
|
true
|
||||||
}.also {
|
}.also {
|
||||||
previousIndex = firstVisibleItemIndex
|
previousIndex = firstVisibleItemIndex
|
||||||
previousScrollOffset = firstVisibleItemScrollOffset
|
previousScrollOffset = firstVisibleItemScrollOffset
|
||||||
@ -194,4 +204,18 @@ fun LazyListState.isScrollingUp(): State<Boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val LazyListState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value
|
// TODO: support sensitivity
|
||||||
|
@Composable
|
||||||
|
fun ScrollState.isScrollingUp(): State<Boolean> {
|
||||||
|
return remember(this) {
|
||||||
|
var previousScrollOffset by mutableIntStateOf(value)
|
||||||
|
derivedStateOf {
|
||||||
|
(previousScrollOffset >= value).also {
|
||||||
|
previousScrollOffset = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val LazyListState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value
|
||||||
|
val ScrollState.isScrollingUp: Boolean @Composable get() = this.isScrollingUp().value
|
Binary file not shown.
@ -18,8 +18,8 @@
|
|||||||
<string name="bundle_patches">Bundle patches</string>
|
<string name="bundle_patches">Bundle patches</string>
|
||||||
<string name="patch_bundle_field">Patch bundle</string>
|
<string name="patch_bundle_field">Patch bundle</string>
|
||||||
<string name="integrations_field">Integrations</string>
|
<string name="integrations_field">Integrations</string>
|
||||||
<string name="file_field_set">Provided</string>
|
<string name="file_field_set">Selected</string>
|
||||||
<string name="file_field_not_set">Not provided</string>
|
<string name="file_field_not_set">Not selected</string>
|
||||||
|
|
||||||
<string name="field_not_set">Not set</string>
|
<string name="field_not_set">Not set</string>
|
||||||
|
|
||||||
@ -42,8 +42,8 @@
|
|||||||
|
|
||||||
<string name="legacy_import_failed">Could not import legacy settings</string>
|
<string name="legacy_import_failed">Could not import legacy settings</string>
|
||||||
|
|
||||||
<string name="auto_updates_dialog_title">Select updates to receive</string>
|
<string name="auto_updates_dialog_title">Configure updates</string>
|
||||||
<string name="auto_updates_dialog_description">Periodically connect to update providers to check for updates.</string>
|
<string name="auto_updates_dialog_description">Do you want ReVanced Manager to periodically check for updates for the following components?</string>
|
||||||
<string name="auto_updates_dialog_manager">ReVanced Manager</string>
|
<string name="auto_updates_dialog_manager">ReVanced Manager</string>
|
||||||
<string name="auto_updates_dialog_patches">ReVanced Patches</string>
|
<string name="auto_updates_dialog_patches">ReVanced Patches</string>
|
||||||
<string name="auto_updates_dialog_note">These settings can be changed later.</string>
|
<string name="auto_updates_dialog_note">These settings can be changed later.</string>
|
||||||
@ -169,7 +169,7 @@
|
|||||||
<string name="device_model">Model</string>
|
<string name="device_model">Model</string>
|
||||||
<string name="device_architectures">CPU Architectures</string>
|
<string name="device_architectures">CPU Architectures</string>
|
||||||
<string name="device_memory_limit">Memory limits</string>
|
<string name="device_memory_limit">Memory limits</string>
|
||||||
<string name="device_memory_limit_format">Normal: %1$d MB, Large: %2$d MB</string>
|
<string name="device_memory_limit_format">%1$dMB (Normal) - %2$dMB (Large)</string>
|
||||||
<string name="patch_bundles_section">Patch bundles</string>
|
<string name="patch_bundles_section">Patch bundles</string>
|
||||||
<string name="patch_bundles_redownload">Redownload all patch bundles</string>
|
<string name="patch_bundles_redownload">Redownload all patch bundles</string>
|
||||||
<string name="patch_bundles_reset">Reset patch bundles</string>
|
<string name="patch_bundles_reset">Reset patch bundles</string>
|
||||||
@ -363,9 +363,17 @@
|
|||||||
<string name="no_contributors_found">No contributors found</string>
|
<string name="no_contributors_found">No contributors found</string>
|
||||||
<string name="select">Select</string>
|
<string name="select">Select</string>
|
||||||
<string name="select_deselect_all">Select or deselect all</string>
|
<string name="select_deselect_all">Select or deselect all</string>
|
||||||
<string name="select_bundle_type_dialog_title">Select bundle type</string>
|
<string name="select_bundle_type_dialog_title">Add new bundle</string>
|
||||||
<string name="select_bundle_type_dialog_description">Select the type that is right for you.</string>
|
<string name="select_bundle_type_dialog_description">Add a new bundle from a URL or storage</string>
|
||||||
<string name="local_bundle_description">Import local files from your storage, does not automatically update</string>
|
<string name="local_bundle_description">Import local files from your storage, does not automatically update</string>
|
||||||
<string name="remote_bundle_description">Import remote files from a URL, can automatically update</string>
|
<string name="remote_bundle_description">Import remote files from a URL, can automatically update</string>
|
||||||
<string name="recommended">Recommended</string>
|
<string name="recommended">Recommended</string>
|
||||||
|
<string name="show">Show</string>
|
||||||
|
<string name="debugging">Debugging</string>
|
||||||
|
<string name="about_device">About device</string>
|
||||||
|
<string name="enter_url">Enter URL</string>
|
||||||
|
<string name="next">Next</string>
|
||||||
|
<string name="add_patch_bundle">Add patch bundle</string>
|
||||||
|
<string name="bundle_url">Bundle URL</string>
|
||||||
|
<string name="auto_update">Auto update</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
[versions]
|
[versions]
|
||||||
kotlin = "1.9.22"
|
|
||||||
ktx = "1.13.1"
|
ktx = "1.13.1"
|
||||||
material3 = "1.3.0-beta04"
|
material3 = "1.3.0-beta04"
|
||||||
ui-tooling = "1.6.8"
|
ui-tooling = "1.6.8"
|
||||||
@ -24,9 +23,10 @@ reimagined-navigation = "1.5.0"
|
|||||||
ktor = "2.3.9"
|
ktor = "2.3.9"
|
||||||
markdown-renderer = "0.22.0"
|
markdown-renderer = "0.22.0"
|
||||||
fading-edges = "1.0.4"
|
fading-edges = "1.0.4"
|
||||||
androidGradlePlugin = "8.3.2"
|
android-gradle-plugin = "8.3.2"
|
||||||
devToolsGradlePlugin = "1.9.22-1.0.17"
|
kotlin-gradle-plugin = "1.9.22"
|
||||||
aboutLibrariesGradlePlugin = "11.1.1"
|
dev-tools-gradle-plugin = "1.9.22-1.0.17"
|
||||||
|
about-libraries-gradle-plugin = "11.1.1"
|
||||||
binary-compatibility-validator = "0.15.1"
|
binary-compatibility-validator = "0.15.1"
|
||||||
coil = "2.6.0"
|
coil = "2.6.0"
|
||||||
app-icon-loader-coil = "1.5.0"
|
app-icon-loader-coil = "1.5.0"
|
||||||
@ -89,8 +89,8 @@ koin-workmanager = { group = "io.insert-koin", name = "koin-androidx-workmanager
|
|||||||
# Compose Navigation
|
# Compose Navigation
|
||||||
reimagined-navigation = { group = "dev.olshevski.navigation", name = "reimagined", version.ref = "reimagined-navigation" }
|
reimagined-navigation = { group = "dev.olshevski.navigation", name = "reimagined", version.ref = "reimagined-navigation" }
|
||||||
|
|
||||||
# about-libraries
|
# About Libraries
|
||||||
about-libraries = { group = "com.mikepenz", name = "aboutlibraries-compose", version.ref = "aboutLibrariesGradlePlugin" }
|
about-libraries = { group = "com.mikepenz", name = "aboutlibraries-compose", version.ref = "about-libraries-gradle-plugin" }
|
||||||
|
|
||||||
# Ktor
|
# Ktor
|
||||||
ktor-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
|
ktor-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
|
||||||
@ -131,9 +131,9 @@ reorderable = { module = "sh.calvin.reorderable:reorderable", version.ref = "reo
|
|||||||
compose-icons-fontawesome = { group = "com.github.BenjaminHalko.compose-icons", name = "font-awesome", version.ref = "compose-icons" }
|
compose-icons-fontawesome = { group = "com.github.BenjaminHalko.compose-icons", name = "font-awesome", version.ref = "compose-icons" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
|
android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }
|
||||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
android-library = { id = "com.android.library", version.ref = "android-gradle-plugin" }
|
||||||
devtools = { id = "com.google.devtools.ksp", version.ref = "devToolsGradlePlugin" }
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin-gradle-plugin" }
|
||||||
about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibrariesGradlePlugin" }
|
devtools = { id = "com.google.devtools.ksp", version.ref = "dev-tools-gradle-plugin" }
|
||||||
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
|
about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries-gradle-plugin" }
|
||||||
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
Loading…
x
Reference in New Issue
Block a user