mirror of
https://github.com/ReVanced/revanced-patcher.git
synced 2024-11-10 01:02:22 +01:00
feat: patch options (#81)
* feat: Patch Options * refactor: remove delegate property * feat: List patch options * refactor: add setter example to PatchOptionsUsage.kt * docs: add docs for PatchOptions * docs: tidy docs
This commit is contained in:
parent
9a4d30e152
commit
fbb09f38dc
4 changed files with 151 additions and 0 deletions
|
@ -17,4 +17,9 @@ abstract class Patch<out T : Data> {
|
|||
* The main function of the [Patch] which the patcher will call.
|
||||
*/
|
||||
abstract fun execute(data: @UnsafeVariance T): PatchResult
|
||||
|
||||
/**
|
||||
* A list of [PatchOption]s.
|
||||
*/
|
||||
open val options: Iterable<PatchOption<*>> = listOf()
|
||||
}
|
100
src/main/kotlin/app/revanced/patcher/patch/PatchOption.kt
Normal file
100
src/main/kotlin/app/revanced/patcher/patch/PatchOption.kt
Normal file
|
@ -0,0 +1,100 @@
|
|||
package app.revanced.patcher.patch
|
||||
|
||||
/**
|
||||
* A [Patch] option.
|
||||
* @param key Unique identifier of the option. Example: _`settings.microg.enabled`_
|
||||
* @param default The default value of the option.
|
||||
* @param title A human-readable title of the option. Example: _MicroG Settings_
|
||||
* @param description A human-readable description of the option. Example: _Settings integration for MicroG._
|
||||
* @param required Whether the option is required.
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
sealed class PatchOption<T>(
|
||||
val key: String,
|
||||
default: T?,
|
||||
val title: String,
|
||||
val description: String,
|
||||
val required: Boolean
|
||||
) {
|
||||
var value: T? = default
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [String].
|
||||
* @see PatchOption
|
||||
*/
|
||||
class StringOption(
|
||||
key: String,
|
||||
default: String?,
|
||||
title: String,
|
||||
description: String,
|
||||
required: Boolean = false
|
||||
) : PatchOption<String>(
|
||||
key, default, title, description, required
|
||||
)
|
||||
|
||||
/**
|
||||
* A [PatchOption] representing a [Boolean].
|
||||
* @see PatchOption
|
||||
*/
|
||||
class BooleanOption(
|
||||
key: String,
|
||||
default: Boolean?,
|
||||
title: String,
|
||||
description: String,
|
||||
required: Boolean = false
|
||||
) : PatchOption<Boolean>(
|
||||
key, default, title, description, required
|
||||
)
|
||||
|
||||
/**
|
||||
* A [PatchOption] with a list of allowed options.
|
||||
* @param options A list of allowed options for the [ListOption].
|
||||
* @see PatchOption
|
||||
*/
|
||||
sealed class ListOption<E>(
|
||||
key: String,
|
||||
default: E?,
|
||||
val options: Iterable<E>,
|
||||
title: String,
|
||||
description: String,
|
||||
required: Boolean = false
|
||||
) : PatchOption<E>(
|
||||
key, default, title, description, required
|
||||
) {
|
||||
init {
|
||||
if (default !in options) {
|
||||
throw IllegalStateException("Default option must be an allowed options")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A [ListOption] of type [String].
|
||||
* @see ListOption
|
||||
*/
|
||||
class StringListOption(
|
||||
key: String,
|
||||
default: String?,
|
||||
options: Iterable<String>,
|
||||
title: String,
|
||||
description: String,
|
||||
required: Boolean = false
|
||||
) : ListOption<String>(
|
||||
key, default, options, title, description, required
|
||||
)
|
||||
|
||||
/**
|
||||
* A [ListOption] of type [Int].
|
||||
* @see ListOption
|
||||
*/
|
||||
class IntListOption(
|
||||
key: String,
|
||||
default: Int?,
|
||||
options: Iterable<Int>,
|
||||
title: String,
|
||||
description: String,
|
||||
required: Boolean = false
|
||||
) : ListOption<Int>(
|
||||
key, default, options, title, description, required
|
||||
)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package app.revanced.patcher.usage
|
||||
|
||||
import app.revanced.patcher.patch.PatchOption
|
||||
import app.revanced.patcher.usage.bytecode.ExampleBytecodePatch
|
||||
|
||||
fun patchOptionsUsage() {
|
||||
val options = ExampleBytecodePatch().options
|
||||
for (option in options) {
|
||||
when (option) {
|
||||
is PatchOption.StringOption -> {
|
||||
option.value = "Hello World"
|
||||
}
|
||||
is PatchOption.BooleanOption -> {
|
||||
option.value = false
|
||||
}
|
||||
is PatchOption.StringListOption -> {
|
||||
option.value = option.options.first()
|
||||
for (choice in option.options) {
|
||||
println(choice)
|
||||
}
|
||||
}
|
||||
is PatchOption.IntListOption -> {
|
||||
option.value = option.options.first()
|
||||
for (choice in option.options) {
|
||||
println(choice)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import app.revanced.patcher.data.impl.BytecodeData
|
|||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.PatchOption
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependencyType
|
||||
|
@ -162,4 +163,19 @@ class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
override val options = listOf(
|
||||
PatchOption.StringOption(
|
||||
"key", "default", "title", "description", true
|
||||
),
|
||||
PatchOption.BooleanOption(
|
||||
"key", true, "title", "description" // required defaults to false
|
||||
),
|
||||
PatchOption.StringListOption(
|
||||
"key", "TEST", listOf("TEST", "TEST1", "TEST2"), "title", "description"
|
||||
),
|
||||
PatchOption.IntListOption(
|
||||
"key", 1, listOf(1, 2, 3), "title", "description"
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue