Compare commits

..

9 Commits

Author SHA1 Message Date
a69b7ac73b aa 2025-07-15 00:07:48 +02:00
ac2df7239e ... 2025-07-15 00:02:52 +02:00
65bead3517 even more refactoring 2025-07-14 23:45:59 +02:00
d6ff1e0b34 more refactoring 2025-07-14 23:28:12 +02:00
19908674f0 improve bundle list screen and fix importing local bundles 2025-07-14 18:03:00 +02:00
a15bb3e6b8 cleanup bundle dao 2025-07-14 00:03:56 +02:00
98722d5c24 fix toasts 2025-07-13 23:58:24 +02:00
6e4043c1e5 Merge branch 'compose-dev' into feat/compose/bundle-deps-support-rebased 2025-07-13 23:51:59 +02:00
f30f233e71 feat: allow bundles to use classes from other bundles 2025-07-09 22:02:00 +02:00
19 changed files with 92 additions and 132 deletions

View File

@ -5,7 +5,6 @@ on:
pull_request: pull_request:
branches: branches:
- dev - dev
- compose-dev
jobs: jobs:
release: release:
@ -14,9 +13,11 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache Gradle - name: Cache Gradle
uses: burrunan/gradle-cache-action@v3 uses: burrunan/gradle-cache-action@v1
- name: Build - name: Build
env: env:

View File

@ -18,6 +18,8 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
@ -26,7 +28,7 @@ jobs:
java-version: '17' java-version: '17'
- name: Cache Gradle - name: Cache Gradle
uses: burrunan/gradle-cache-action@v3 uses: burrunan/gradle-cache-action@v1
- name: Build - name: Build
env: env:

View File

@ -1,4 +1,3 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.io.IOException import java.io.IOException
plugins { plugins {
@ -82,10 +81,8 @@ android {
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17
} }
kotlin { kotlinOptions {
compilerOptions { jvmTarget = "17"
jvmTarget = JvmTarget.fromTarget("17")
}
} }
buildFeatures { buildFeatures {

View File

@ -1,4 +1,3 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import kotlin.random.Random import kotlin.random.Random
plugins { plugins {
@ -41,6 +40,10 @@ dependencies {
// Placeholder // Placeholder
implementation(libs.placeholder.material3) implementation(libs.placeholder.material3)
// HTML Scraper
implementation(libs.skrapeit.dsl)
implementation(libs.skrapeit.parser)
// Coil (async image loading, network image) // Coil (async image loading, network image)
implementation(libs.coil.compose) implementation(libs.coil.compose)
implementation(libs.coil.appiconloader) implementation(libs.coil.appiconloader)
@ -53,6 +56,7 @@ dependencies {
// Room // Room
implementation(libs.room.runtime) implementation(libs.room.runtime)
implementation(libs.room.ktx) implementation(libs.room.ktx)
annotationProcessor(libs.room.compiler)
ksp(libs.room.compiler) ksp(libs.room.compiler)
// ReVanced // ReVanced
@ -124,8 +128,6 @@ android {
} }
buildTypes { buildTypes {
configureEach {
}
debug { debug {
applicationIdSuffix = ".debug" applicationIdSuffix = ".debug"
resValue("string", "app_name", "ReVanced Manager (Debug)") resValue("string", "app_name", "ReVanced Manager (Debug)")
@ -201,11 +203,8 @@ android {
arg("room.schemaLocation", "$projectDir/schemas") arg("room.schemaLocation", "$projectDir/schemas")
} }
kotlin { kotlinOptions {
compilerOptions { jvmTarget = "17"
jvmTarget = JvmTarget.fromTarget("17")
jvmToolchain(17)
}
} }
buildFeatures { buildFeatures {
@ -228,6 +227,10 @@ android {
} }
} }
kotlin {
jvmToolchain(17)
}
tasks { tasks {
// Needed by gradle-semantic-release-plugin. // Needed by gradle-semantic-release-plugin.
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435. // Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435.

View File

@ -10,12 +10,7 @@
# Required for serialization to work properly # Required for serialization to work properly
-if @kotlinx.serialization.Serializable class ** -if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> { -keepclassmembers class <1> {
static <1>$* Companion; static <1>$Companion Companion;
}
-keepnames @kotlinx.serialization.internal.NamedCompanion class *
-if @kotlinx.serialization.internal.NamedCompanion class *
-keepclassmembernames class * {
static <1> *;
} }
-if @kotlinx.serialization.Serializable class ** { -if @kotlinx.serialization.Serializable class ** {
static **$* *; static **$* *;

View File

@ -8,6 +8,7 @@ import app.revanced.manager.util.tag
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.request.prepareGet import io.ktor.client.request.prepareGet
import io.ktor.client.request.request import io.ktor.client.request.request
import io.ktor.client.statement.bodyAsText import io.ktor.client.statement.bodyAsText
@ -16,6 +17,7 @@ import io.ktor.http.isSuccess
import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.isNotEmpty import io.ktor.utils.io.core.isNotEmpty
import io.ktor.utils.io.core.readBytes import io.ktor.utils.io.core.readBytes
import it.skrape.core.htmlDocument
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -91,5 +93,9 @@ class HttpService(
builder: HttpRequestBuilder.() -> Unit builder: HttpRequestBuilder.() -> Unit
) = saveLocation.outputStream().use { streamTo(it, builder) } ) = saveLocation.outputStream().use { streamTo(it, builder) }
suspend fun getHtml(builder: HttpRequestBuilder.() -> Unit) = htmlDocument(
html = http.get(builder).bodyAsText()
)
class HttpException(status: HttpStatusCode) : Exception("Failed to fetch: http status: $status") class HttpException(status: HttpStatusCode) : Exception("Failed to fetch: http status: $status")
} }

View File

@ -1,7 +1,6 @@
package app.revanced.manager.ui.component package app.revanced.manager.ui.component
import android.view.WindowManager import android.view.WindowManager
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -10,7 +9,6 @@ import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.DialogWindowProvider import androidx.compose.ui.window.DialogWindowProvider
import androidx.core.view.WindowCompat
private val properties = DialogProperties( private val properties = DialogProperties(
usePlatformDefaultWidth = false, usePlatformDefaultWidth = false,
@ -24,17 +22,11 @@ fun FullscreenDialog(onDismissRequest: () -> Unit, content: @Composable () -> Un
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
properties = properties properties = properties
) { ) {
val view = LocalView.current val window = (LocalView.current.parent as DialogWindowProvider).window
val isDarkTheme = isSystemInDarkTheme() LaunchedEffect(Unit) {
LaunchedEffect(isDarkTheme) {
val window = (view.parent as DialogWindowProvider).window
window.statusBarColor = Color.Transparent.toArgb() window.statusBarColor = Color.Transparent.toArgb()
window.navigationBarColor = Color.Transparent.toArgb() window.navigationBarColor = Color.Transparent.toArgb()
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
val insetsController = WindowCompat.getInsetsController(window, view)
insetsController.isAppearanceLightStatusBars = !isDarkTheme
insetsController.isAppearanceLightNavigationBars = !isDarkTheme
} }
content() content()

View File

@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListItemInfo
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@ -73,11 +74,13 @@ import app.revanced.manager.util.saver.snapshotStateListSaver
import app.revanced.manager.util.saver.snapshotStateSetSaver import app.revanced.manager.util.saver.snapshotStateSetSaver
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
import app.revanced.manager.util.transparentListItemColors import app.revanced.manager.util.transparentListItemColors
import kotlinx.coroutines.CoroutineScope
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.koin.compose.koinInject import org.koin.compose.koinInject
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.get import org.koin.core.component.get
import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyColumnState
import sh.calvin.reorderable.rememberReorderableLazyListState import sh.calvin.reorderable.rememberReorderableLazyListState
import java.io.Serializable import java.io.Serializable
import kotlin.random.Random import kotlin.random.Random
@ -88,28 +91,15 @@ private class OptionEditorScope<T : Any>(
val option: Option<T>, val option: Option<T>,
val openDialog: () -> Unit, val openDialog: () -> Unit,
val dismissDialog: () -> Unit, val dismissDialog: () -> Unit,
val selectionWarningEnabled: Boolean,
val showSelectionWarning: () -> Unit,
val value: T?, val value: T?,
val setValue: (T?) -> Unit val setValue: (T?) -> Unit,
) { ) {
fun submitDialog(value: T?) { fun submitDialog(value: T?) {
setValue(value) setValue(value)
dismissDialog() dismissDialog()
} }
fun checkSafeguard(block: () -> Unit) { fun clickAction() = editor.clickAction(this)
if (!option.required && selectionWarningEnabled)
showSelectionWarning()
else
block()
}
fun clickAction() {
checkSafeguard {
editor.clickAction(this)
}
}
@Composable @Composable
fun ListItemTrailingContent() = editor.ListItemTrailingContent(this) fun ListItemTrailingContent() = editor.ListItemTrailingContent(this)
@ -123,7 +113,7 @@ private interface OptionEditor<T : Any> {
@Composable @Composable
fun ListItemTrailingContent(scope: OptionEditorScope<T>) { fun ListItemTrailingContent(scope: OptionEditorScope<T>) {
IconButton(onClick = { scope.checkSafeguard { clickAction(scope) } }) { IconButton(onClick = { clickAction(scope) }) {
Icon(Icons.Outlined.Edit, stringResource(R.string.edit)) Icon(Icons.Outlined.Edit, stringResource(R.string.edit))
} }
} }
@ -151,14 +141,11 @@ private inline fun <T : Any> WithOptionEditor(
option: Option<T>, option: Option<T>,
value: T?, value: T?,
noinline setValue: (T?) -> Unit, noinline setValue: (T?) -> Unit,
selectionWarningEnabled: Boolean,
crossinline onDismissDialog: @DisallowComposableCalls () -> Unit = {}, crossinline onDismissDialog: @DisallowComposableCalls () -> Unit = {},
block: OptionEditorScope<T>.() -> Unit block: OptionEditorScope<T>.() -> Unit
) { ) {
var showDialog by rememberSaveable { mutableStateOf(false) } var showDialog by rememberSaveable { mutableStateOf(false) }
var showSelectionWarningDialog by rememberSaveable { mutableStateOf(false) } val scope = remember(editor, option, value, setValue) {
val scope = remember(editor, option, value, setValue, selectionWarningEnabled) {
OptionEditorScope( OptionEditorScope(
editor, editor,
option, option,
@ -167,18 +154,11 @@ private inline fun <T : Any> WithOptionEditor(
showDialog = false showDialog = false
onDismissDialog() onDismissDialog()
}, },
selectionWarningEnabled,
showSelectionWarning = { showSelectionWarningDialog = true },
value, value,
setValue setValue
) )
} }
if (showSelectionWarningDialog)
SelectionWarningDialog(
onDismiss = { showSelectionWarningDialog = false }
)
if (showDialog) scope.Dialog() if (showDialog) scope.Dialog()
scope.block() scope.block()
@ -189,7 +169,6 @@ fun <T : Any> OptionItem(
option: Option<T>, option: Option<T>,
value: T?, value: T?,
setValue: (T?) -> Unit, setValue: (T?) -> Unit,
selectionWarningEnabled: Boolean
) { ) {
val editor = remember(option.type, option.presets) { val editor = remember(option.type, option.presets) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@ -202,7 +181,7 @@ fun <T : Any> OptionItem(
else baseOptionEditor else baseOptionEditor
} }
WithOptionEditor(editor, option, value, setValue, selectionWarningEnabled) { WithOptionEditor(editor, option, value, setValue) {
ListItem( ListItem(
modifier = Modifier.clickable(onClick = ::clickAction), modifier = Modifier.clickable(onClick = ::clickAction),
headlineContent = { Text(option.title) }, headlineContent = { Text(option.title) },
@ -321,7 +300,7 @@ private object StringOptionEditor : OptionEditor<String> {
private abstract class NumberOptionEditor<T : Number> : OptionEditor<T> { private abstract class NumberOptionEditor<T : Number> : OptionEditor<T> {
@Composable @Composable
abstract fun NumberDialog( protected abstract fun NumberDialog(
title: String, title: String,
current: T?, current: T?,
validator: (T?) -> Boolean, validator: (T?) -> Boolean,
@ -375,14 +354,7 @@ private object BooleanOptionEditor : OptionEditor<Boolean> {
@Composable @Composable
override fun ListItemTrailingContent(scope: OptionEditorScope<Boolean>) { override fun ListItemTrailingContent(scope: OptionEditorScope<Boolean>) {
HapticSwitch( HapticSwitch(checked = scope.current, onCheckedChange = scope.setValue)
checked = scope.current,
onCheckedChange = { value ->
scope.checkSafeguard {
scope.setValue(value)
}
}
)
} }
@Composable @Composable
@ -421,7 +393,6 @@ private class PresetOptionEditor<T : Any>(private val innerEditor: OptionEditor<
scope.option, scope.option,
scope.value, scope.value,
scope.setValue, scope.setValue,
scope.selectionWarningEnabled,
onDismissDialog = scope.dismissDialog onDismissDialog = scope.dismissDialog
) inner@{ ) inner@{
var hidePresetsDialog by rememberSaveable { var hidePresetsDialog by rememberSaveable {
@ -643,8 +614,7 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
elementEditor, elementEditor,
elementOption, elementOption,
value = item.value, value = item.value,
setValue = { items[index] = item.copy(value = it) }, setValue = { items[index] = item.copy(value = it) }
selectionWarningEnabled = scope.selectionWarningEnabled
) { ) {
ListItem( ListItem(
modifier = Modifier.combinedClickable( modifier = Modifier.combinedClickable(

View File

@ -1,17 +0,0 @@
package app.revanced.manager.ui.component.patches
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.ui.component.SafeguardDialog
@Composable
fun SelectionWarningDialog(
onDismiss: () -> Unit
) {
SafeguardDialog(
onDismiss = onDismiss,
title = R.string.warning,
body = stringResource(R.string.selection_warning_description),
)
}

View File

@ -73,7 +73,6 @@ import app.revanced.manager.ui.component.haptics.HapticCheckbox
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
import app.revanced.manager.ui.component.haptics.HapticTab import app.revanced.manager.ui.component.haptics.HapticTab
import app.revanced.manager.ui.component.patches.OptionItem import app.revanced.manager.ui.component.patches.OptionItem
import app.revanced.manager.ui.component.patches.SelectionWarningDialog
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_INCOMPATIBLE import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_INCOMPATIBLE
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNIVERSAL import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNIVERSAL
@ -182,8 +181,7 @@ fun PatchesSelectorScreen(
patch = patch, patch = patch,
values = viewModel.getOptions(bundle, patch), values = viewModel.getOptions(bundle, patch),
reset = { viewModel.resetOptions(bundle, patch) }, reset = { viewModel.resetOptions(bundle, patch) },
set = { key, value -> viewModel.setOption(bundle, patch, key, value) }, set = { key, value -> viewModel.setOption(bundle, patch, key, value) }
selectionWarningEnabled = viewModel.selectionWarningEnabled
) )
} }
@ -217,7 +215,9 @@ fun PatchesSelectorScreen(
) { patch -> ) { patch ->
PatchItem( PatchItem(
patch = patch, patch = patch,
onOptionsDialog = { viewModel.optionsDialog = uid to patch }, onOptionsDialog = {
viewModel.optionsDialog = uid to patch
},
selected = compatible && viewModel.isSelected( selected = compatible && viewModel.isSelected(
uid, uid,
patch patch
@ -472,6 +472,17 @@ fun PatchesSelectorScreen(
} }
} }
@Composable
private fun SelectionWarningDialog(
onDismiss: () -> Unit
) {
SafeguardDialog(
onDismiss = onDismiss,
title = R.string.warning,
body = stringResource(R.string.selection_warning_description),
)
}
@Composable @Composable
private fun UniversalPatchWarningDialog( private fun UniversalPatchWarningDialog(
onDismiss: () -> Unit onDismiss: () -> Unit
@ -601,7 +612,6 @@ private fun OptionsDialog(
reset: () -> Unit, reset: () -> Unit,
set: (String, Any?) -> Unit, set: (String, Any?) -> Unit,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
selectionWarningEnabled: Boolean
) = FullscreenDialog(onDismissRequest = onDismissRequest) { ) = FullscreenDialog(onDismissRequest = onDismissRequest) {
Scaffold( Scaffold(
topBar = { topBar = {
@ -632,8 +642,7 @@ private fun OptionsDialog(
value = value, value = value,
setValue = { setValue = {
set(key, it) set(key, it)
}, }
selectionWarningEnabled = selectionWarningEnabled
) )
} }
} }

View File

@ -154,8 +154,7 @@ fun RequiredOptionsScreen(
value = value, value = value,
setValue = { new -> setValue = { new ->
vm.setOption(bundle.uid, it, key, new) vm.setOption(bundle.uid, it, key, new)
}, }
selectionWarningEnabled = vm.selectionWarningEnabled
) )
} }
} }

View File

@ -296,8 +296,8 @@ fun ImportExportSettingsScreen(
} }
} }
}, },
headline = R.string.patch_options_reset_patches, headline = R.string.patch_options_reset,
description = R.string.patch_options_reset_patches_description, description = R.string.patch_options_reset_all,
) )
} }
} }

View File

@ -81,8 +81,8 @@ sealed class ResetDialogState(
) )
class PatchOptionBundle(dialogOptionName: String, onConfirm: () -> Unit) : ResetDialogState( class PatchOptionBundle(dialogOptionName: String, onConfirm: () -> Unit) : ResetDialogState(
titleResId = R.string.patch_options_reset_patches, titleResId = R.string.patch_options_reset,
descriptionResId = R.string.patch_options_reset_patches_dialog_description, descriptionResId = R.string.patch_options_reset_dialog_description,
onConfirm = onConfirm, onConfirm = onConfirm,
dialogOptionName = dialogOptionName dialogOptionName = dialogOptionName
) )

View File

@ -95,8 +95,8 @@
<string name="suggested_version_safeguard">Require suggested app version</string> <string name="suggested_version_safeguard">Require suggested app version</string>
<string name="suggested_version_safeguard_description">Enforce selection of the suggested app version</string> <string name="suggested_version_safeguard_description">Enforce selection of the suggested app version</string>
<string name="suggested_version_safeguard_confirmation">Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?</string> <string name="suggested_version_safeguard_confirmation">Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?</string>
<string name="patch_selection_safeguard">Allow changing patch selection and options</string> <string name="patch_selection_safeguard">Allow changing patch selection</string>
<string name="patch_selection_safeguard_description">Do not prevent selecting or deselecting patches and customization of options</string> <string name="patch_selection_safeguard_description">Do not prevent selecting or deselecting patches</string>
<string name="patch_selection_safeguard_confirmation">Changing the selection of patches may cause unexpected issues.\n\nEnable anyways?</string> <string name="patch_selection_safeguard_confirmation">Changing the selection of patches may cause unexpected issues.\n\nEnable anyways?</string>
<string name="universal_patches_safeguard">Allow using universal patches</string> <string name="universal_patches_safeguard">Allow using universal patches</string>
<string name="universal_patches_safeguard_description">Do not prevent using universal patches</string> <string name="universal_patches_safeguard_description">Do not prevent using universal patches</string>
@ -131,22 +131,21 @@
<string name="reset_patch_options">Reset patch options</string> <string name="reset_patch_options">Reset patch options</string>
<string name="reset_patch_options_description">Reset the stored patch options</string> <string name="reset_patch_options_description">Reset the stored patch options</string>
<string name="reset_patch_selection_success">Patch selection has been reset</string> <string name="reset_patch_selection_success">Patch selection has been reset</string>
<string name="patch_selection_reset_all">Reset patch selection globally</string> <string name="patch_selection_reset_all">Reset all patch selection</string>
<string name="patch_selection_reset_all_dialog_description">You are about to reset all the patch selections. You will need to manually select each patch again.</string> <string name="patch_selection_reset_all_dialog_description">You are about to reset all the patch selections. You will need to manually select each patch again.</string>
<string name="patch_selection_reset_all_description">Resets all the patch selections</string> <string name="patch_selection_reset_all_description">Reset all the patch selections</string>
<string name="patch_selection_reset_package">Reset patch selection for app</string> <string name="patch_selection_reset_package">Reset patch selection for app</string>
<string name="patch_selection_reset_package_dialog_description">You are about to reset the patch selection for the app \"%s\". You will have to manually select each patch again.</string> <string name="patch_selection_reset_package_dialog_description">You are about to reset the patch selection for the app \"%s\". You will have to manually select each patch again.</string>
<string name="patch_selection_reset_package_description">Resets patch selection for a single app</string> <string name="patch_selection_reset_package_description">Resets patch selection for a single app</string>
<string name="patch_selection_reset_patches">Reset patch selection (single)</string> <string name="patch_selection_reset_patches">Resets patch selection for a specific patches</string>
<string name="patch_selection_reset_patches_dialog_description">You are about to reset the patch selection for \"%s\". You will have to manually select each patch again.</string> <string name="patch_selection_reset_patches_dialog_description">You are about to reset the patch selection for \"%s\". You will have to manually select each patch again.</string>
<string name="patch_selection_reset_patches_description">Resets the patch selection for a specific collection of patches</string> <string name="patch_selection_reset_patches_description">Resets the patch selection for a specific patches</string>
<string name="patch_options_reset_package">Reset patch options for app</string> <string name="patch_options_reset_package">Reset patch options for app</string>
<string name="patch_options_reset_package_dialog_description">You are about to reset the patch options for the app \"%s\". You will have to reapply each option again.</string> <string name="patch_options_reset_package_dialog_description">You are about to reset the patch options for the app \"%s\". You will have to reapply each option again.</string>
<string name="patch_options_reset_package_description">Resets patch options for a single app</string> <string name="patch_options_reset_package_description">Resets patch options for a single app</string>
<string name="patch_options_reset_patches">Reset patch options (single)</string> <string name="patch_options_reset">Reset patch options</string>
<string name="patch_options_reset_patches_dialog_description">You are about to reset the patch options for \"%s\". You will have to reapply each option again.</string> <string name="patch_options_reset_dialog_description">You are about to reset the patch options for \"%s\". You will have to reapply each option again.</string>
<string name="patch_options_reset_patches_description">Resets the patch options for a specific collection of patches</string> <string name="patch_options_reset_all">Reset patch options for all</string>
<string name="patch_options_reset_all">Reset patch options globally</string>
<string name="patch_options_reset_all_dialog_description">You are about to reset patch options. You will have to reapply each option again.</string> <string name="patch_options_reset_all_dialog_description">You are about to reset patch options. You will have to reapply each option again.</string>
<string name="patch_options_reset_all_description">Resets all patch options</string> <string name="patch_options_reset_all_description">Resets all patch options</string>
<string name="downloader_plugins">Plugins</string> <string name="downloader_plugins">Plugins</string>

View File

@ -6,7 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html # http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx3072m -XX:MaxMetaspaceSize=1024m -Dfile.encoding=UTF-8 org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit # This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
@ -25,5 +25,4 @@ android.nonFinalResIds=false
# Task :app:assembleReleaseSignApk fails if this is set to true. # Task :app:assembleReleaseSignApk fails if this is set to true.
org.gradle.configuration-cache=false org.gradle.configuration-cache=false
org.gradle.caching=true org.gradle.caching=true
org.gradle.parallel=true
version=1.25.0-dev.1 version=1.25.0-dev.1

View File

@ -1,34 +1,35 @@
[versions] [versions]
ktx = "1.16.0" ktx = "1.16.0"
material3 = "1.3.2" material3 = "1.3.2"
ui-tooling = "1.8.3" ui-tooling = "1.8.1"
viewmodel-lifecycle = "2.9.2" viewmodel-lifecycle = "2.9.0"
splash-screen = "1.0.1" splash-screen = "1.0.1"
activity = "1.10.1" activity = "1.10.1"
appcompat = "1.7.1" appcompat = "1.7.0"
preferences-datastore = "1.1.7" preferences-datastore = "1.1.2"
work-runtime = "2.10.3" work-runtime = "2.10.1"
compose-bom = "2025.07.00" compose-bom = "2025.05.00"
navigation = "2.9.3" navigation = "2.8.6"
accompanist = "0.37.3" accompanist = "0.37.0"
placeholder = "1.1.2" placeholder = "1.1.2"
reorderable = "2.5.1" reorderable = "2.4.3"
serialization = "1.9.0" serialization = "1.8.0"
collection = "0.3.8" collection = "0.3.8"
datetime = "0.6.1" datetime = "0.6.1"
room-version = "2.7.2" room-version = "2.7.1"
revanced-patcher = "21.0.0" revanced-patcher = "21.0.0"
revanced-library = "3.0.2" revanced-library = "3.0.2"
koin = "3.5.3" koin = "3.5.3"
ktor = "2.3.9" ktor = "2.3.9"
markdown-renderer = "0.30.0" markdown-renderer = "0.30.0"
fading-edges = "1.0.4" fading-edges = "1.0.4"
kotlin = "2.2.0" kotlin = "2.1.10"
android-gradle-plugin = "8.11.1" android-gradle-plugin = "8.9.1"
dev-tools-gradle-plugin = "2.2.0-2.0.2" dev-tools-gradle-plugin = "2.1.10-1.0.29"
about-libraries-gradle-plugin = "12.1.2" about-libraries-gradle-plugin = "12.1.2"
coil = "2.7.0" coil = "2.7.0"
app-icon-loader-coil = "1.5.0" app-icon-loader-coil = "1.5.0"
skrapeit = "1.2.2"
libsu = "6.0.0" libsu = "6.0.0"
scrollbars = "1.0.4" scrollbars = "1.0.4"
enumutil = "1.1.1" enumutil = "1.1.1"
@ -98,6 +99,10 @@ ktor-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "k
ktor-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" } ktor-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" } ktor-serialization = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" }
# HTML Scraper
skrapeit-dsl = { group = "it.skrape", name = "skrapeit-dsl", version.ref = "skrapeit" }
skrapeit-parser = { group = "it.skrape", name = "skrapeit-html-parser", version.ref = "skrapeit" }
# Markdown # Markdown
markdown-renderer = { group = "com.mikepenz", name = "multiplatform-markdown-renderer-m3", version.ref = "markdown-renderer" } markdown-renderer = { group = "com.mikepenz", name = "multiplatform-markdown-renderer-m3", version.ref = "markdown-renderer" }

Binary file not shown.

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=8fad3d78296ca518113f3d29016617c7f9367dc005f932bd9d93bf45ba46072b distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored
View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015 the original authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.