refactor: simplify casting instructions

This commit is contained in:
inotia00
2023-05-11 16:35:02 +09:00
parent 2b70050200
commit 3b6848ab1a
16 changed files with 247 additions and 384 deletions

View File

@ -0,0 +1,10 @@
package app.revanced.patches.youtube.layout.fullscreen.endscreenoverlay.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.appRelatedEndScreenResultsId
import app.revanced.util.bytecode.isWideLiteralExists
object EndScreenResultsFingerprint : MethodFingerprint(
returnType = "V",
customFingerprint = { it.isWideLiteralExists(appRelatedEndScreenResultsId) }
)

View File

@ -1,6 +1,6 @@
package app.revanced.patches.youtube.layout.fullscreen.endscreenoverlay.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
@ -9,91 +9,54 @@ import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.fullscreen.endscreenoverlay.fingerprints.EndScreenResultsFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.FULLSCREEN
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
@Patch
@Name("hide-endscreen-overlay")
@Description("Hide endscreen overlay on swipe controls.")
@DependsOn(
[
ResourceMappingPatch::class,
SettingsPatch::class
SettingsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class HideEndScreenOverlayPatch : BytecodePatch() {
// list of resource names to get the id of
private val resourceIds = arrayOf(
"app_related_endscreen_results"
).map { name ->
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
class HideEndScreenOverlayPatch : BytecodePatch(
listOf(EndScreenResultsFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // end screen result
val insertIndex = index - 13
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.IF_NEZ) return@forEachIndexed
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA
mutableMethod.addInstructions(
insertIndex, """
invoke-static {}, $FULLSCREEN->hideEndScreenOverlay()Z
move-result v$dummyRegister
if-eqz v$dummyRegister, :on
return-void
""", listOf(ExternalLabel("on", mutableMethod.instruction(insertIndex)))
)
patchSuccessArray[0] = true
}
}
}
else -> return@forEachIndexed
}
}
}
}
}
val errorIndex: Int = patchSuccessArray.indexOf(false)
if (errorIndex == -1) {
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: FULLSCREEN_SETTINGS",
"SETTINGS: HIDE_END_SCREEN_OVERLAY"
)
EndScreenResultsFingerprint.result?.mutableMethod?.let {
it.addInstructions(
0, """
invoke-static {}, $FULLSCREEN->hideEndScreenOverlay()Z
move-result v0
if-eqz v0, :show
return-void
""", listOf(ExternalLabel("show", it.instruction(0)))
)
} ?: return EndScreenResultsFingerprint.toErrorResult()
SettingsPatch.updatePatchStatus("hide-endscreen-overlay")
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: FULLSCREEN_SETTINGS",
"SETTINGS: HIDE_END_SCREEN_OVERLAY"
)
)
return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
SettingsPatch.updatePatchStatus("hide-endscreen-overlay")
return PatchResultSuccess()
}
}

View File

@ -1,16 +0,0 @@
package app.revanced.patches.youtube.layout.fullscreen.flimstripoverlay.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.accessibilityVideoTimeId
import app.revanced.util.bytecode.isWideLiteralExists
import org.jf.dexlib2.Opcode
object ScrubbingLabelAlternativeFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID
),
customFingerprint = { it.isWideLiteralExists(accessibilityVideoTimeId) }
)

View File

@ -15,7 +15,6 @@ import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.youtube.layout.fullscreen.flimstripoverlay.fingerprints.ScrubbingLabelAlternativeFingerprint
import app.revanced.patches.youtube.layout.fullscreen.flimstripoverlay.fingerprints.ScrubbingLabelFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
@ -35,19 +34,11 @@ import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
@YouTubeCompatibility
@Version("0.0.1")
class HideFilmstripOverlayPatch : BytecodePatch(
listOf(
ScrubbingLabelFingerprint,
ScrubbingLabelAlternativeFingerprint
)
listOf(ScrubbingLabelFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val result = try {
ScrubbingLabelFingerprint.result!!
} catch (_: Exception) {
ScrubbingLabelAlternativeFingerprint.result
?: return ScrubbingLabelAlternativeFingerprint.toErrorResult()
}
val result = ScrubbingLabelFingerprint.result?: return ScrubbingLabelFingerprint.toErrorResult()
result.mutableMethod.hook(result.scanResult.patternScanResult!!.endIndex - 1)

View File

@ -43,7 +43,7 @@ class HideEndscreenCardsPatch : BytecodePatch(
val index = this.scanResult.patternScanResult!!.endIndex
this.mutableMethod.apply {
val register = this.instruction<OneRegisterInstruction>(index).registerA
this.implementation!!.injectHideCall(index + 1, register, "layout/PlayerPatch", "hideEndscreen")
this.implementation!!.injectHideCall(index + 1, register, "layout/PlayerPatch", "hideEndScreen")
}
}

View File

@ -0,0 +1,9 @@
package app.revanced.patches.youtube.layout.player.playeroverlayfilter.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.scrimOverlayId
import app.revanced.util.bytecode.isWideLiteralExists
object ScrimOverlayFingerprint : MethodFingerprint(
customFingerprint = { it.definingClass.endsWith("YouTubeControlsOverlay;") && it.isWideLiteralExists(scrimOverlayId) }
)

View File

@ -1,11 +1,11 @@
package app.revanced.patches.youtube.layout.player.playeroverlayfilter.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
@ -13,95 +13,58 @@ import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.player.playeroverlayfilter.fingerprints.ScrimOverlayFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.scrimOverlayId
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.bytecode.getWideLiteralIndex
import app.revanced.util.integrations.Constants.PLAYER
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
@Patch
@Name("hide-player-overlay-filter")
@Description("Remove the dark filter layer from the player's background.")
@DependsOn(
[
ResourceMappingPatch::class,
SettingsPatch::class
SettingsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class PlayerOverlayFilterPatch : BytecodePatch() {
// list of resource names to get the id of
private val resourceIds = arrayOf(
"scrim_overlay",
"google_transparent"
).map { name ->
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
class PlayerOverlayFilterPatch : BytecodePatch(
listOf(ScrimOverlayFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // player overlay filter
val insertIndex = index + 3
val invokeInstruction = instructions.elementAt(insertIndex)
if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
val dummyRegister = (instructions.elementAt(index) as Instruction31i).registerA
val viewRegister = (invokeInstruction as Instruction21c).registerA
ScrimOverlayFingerprint.result?.mutableMethod?.let {
val targetIndex = it.getWideLiteralIndex(scrimOverlayId) + 3
val targetParameter = it.instruction<ReferenceInstruction>(targetIndex).reference
val targetRegister = it.instruction<OneRegisterInstruction>(targetIndex).registerA
val transparent = resourceIds[1]
if (!targetParameter.toString().endsWith("Landroid/widget/ImageView;"))
return PatchResultError("Method signature parameter did not match: $targetParameter")
mutableMethod.addInstructions(
insertIndex + 1, """
invoke-static {}, $PLAYER->hidePlayerOverlayFilter()Z
move-result v$dummyRegister
if-eqz v$dummyRegister, :currentcolor
const v$dummyRegister, $transparent
invoke-virtual {v$viewRegister, v$dummyRegister}, Landroid/widget/ImageView;->setImageResource(I)V
""", listOf(ExternalLabel("currentcolor", mutableMethod.instruction(insertIndex + 1)))
)
patchSuccessArray[0] = true
patchSuccessArray[1] = true
}
}
}
else -> return@forEachIndexed
}
}
}
}
}
val errorIndex: Int = patchSuccessArray.indexOf(false)
if (errorIndex == -1) {
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: HIDE_PLAYER_OVERLAY_FILTER"
)
it.addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $PLAYER->hidePlayerOverlayFilter(Landroid/widget/ImageView;)V"
)
} ?: return ScrimOverlayFingerprint.toErrorResult()
SettingsPatch.updatePatchStatus("hide-player-overlay-filter")
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: HIDE_PLAYER_OVERLAY_FILTER"
)
)
return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
SettingsPatch.updatePatchStatus("hide-player-overlay-filter")
return PatchResultSuccess()
}
}
}

View File

@ -0,0 +1,17 @@
package app.revanced.patches.youtube.layout.player.suggestactions.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.suggestedActionId
import app.revanced.util.bytecode.isWideLiteralExists
import org.jf.dexlib2.Opcode
object SuggestedActionsFingerprint : MethodFingerprint(
returnType = "V",
opcodes = listOf(
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT
),
customFingerprint = { it.isWideLiteralExists(suggestedActionId) }
)

View File

@ -1,26 +1,23 @@
package app.revanced.patches.youtube.layout.player.suggestactions.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.injectHideCall
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.youtube.layout.player.suggestactions.fingerprints.SuggestedActionsFingerprint
import app.revanced.patches.youtube.misc.litho.patch.ByteBufferFilterPatch
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.bytecode.BytecodeHelper.updatePatchStatus
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@Name("hide-suggested-actions")
@ -28,71 +25,37 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction31i
@DependsOn(
[
ByteBufferFilterPatch::class,
PlayerTypeHookPatch::class,
ResourceMappingPatch::class,
SettingsPatch::class
SettingsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class SuggestedActionsPatch : BytecodePatch() {
// list of resource names to get the id of
private val resourceIds = arrayOf(
"suggested_action"
).map { name ->
ResourceMappingPatch.resourceMappings.single { it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
class SuggestedActionsPatch : BytecodePatch(
listOf(SuggestedActionsFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { index, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // suggested_action
val insertIndex = index + 4
val iPutInstruction = instructions.elementAt(insertIndex)
if (iPutInstruction.opcode != Opcode.IPUT_OBJECT) return@forEachIndexed
SuggestedActionsFingerprint.result?.let{
it.mutableMethod.apply {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = instruction<OneRegisterInstruction>(targetIndex).registerA
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
val viewRegister = (iPutInstruction as Instruction22c).registerA
mutableMethod.implementation!!.injectHideCall(insertIndex, viewRegister, "layout/PlayerPatch", "hideSuggestedActions")
patchSuccessArray[0] = true
}
}
}
else -> return@forEachIndexed
}
}
}
implementation!!.injectHideCall(targetIndex + 1, targetRegister, "layout/PlayerPatch", "hideSuggestedActions")
}
}
} ?: return SuggestedActionsFingerprint.toErrorResult()
val errorIndex: Int = patchSuccessArray.indexOf(false)
if (errorIndex == -1) {
context.updatePatchStatus("SuggestedActions")
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: HIDE_SUGGESTED_ACTION"
)
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: PLAYER_SETTINGS",
"SETTINGS: HIDE_SUGGESTED_ACTION"
)
)
SettingsPatch.updatePatchStatus("hide-suggested-actions")
SettingsPatch.updatePatchStatus("hide-suggested-actions")
return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
return PatchResultSuccess()
}
}

View File

@ -1,11 +1,12 @@
package app.revanced.patches.youtube.layout.seekbar.speed.patch
import app.revanced.extensions.findMutableMethodOf
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
@ -13,13 +14,13 @@ import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.shared.annotation.YouTubeCompatibility
import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch
import app.revanced.patches.shared.fingerprints.TotalTimeFingerprint
import app.revanced.patches.youtube.misc.overridespeed.bytecode.patch.OverrideSpeedHookPatch
import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsPatch
import app.revanced.util.integrations.Constants.SEEKBAR
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction35c
import org.jf.dexlib2.iface.instruction.formats.Instruction31i
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@ -28,78 +29,55 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@DependsOn(
[
OverrideSpeedHookPatch::class,
ResourceMappingPatch::class,
SettingsPatch::class
SettingsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeCompatibility
@Version("0.0.1")
class AppendSpeedPatch : BytecodePatch() {
// list of resource names to get the id of
private val resourceIds = arrayOf(
"string" to "total_time"
).map { (type, name) ->
ResourceMappingPatch
.resourceMappings
.single { it.type == type && it.name == name }.id
}
private var patchSuccessArray = Array(resourceIds.size) {false}
class AppendSpeedPatch : BytecodePatch(
listOf(TotalTimeFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
with(method.implementation) {
this?.instructions?.forEachIndexed { _, instruction ->
when (instruction.opcode) {
Opcode.CONST -> {
when ((instruction as Instruction31i).wideLiteral) {
resourceIds[0] -> { // total time
val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method)
TotalTimeFingerprint.result?.mutableMethod?.let {
it.implementation!!.instructions.apply {
var insertIndex = -1
for ((targetIndex, targetInstruction) in instructions.withIndex()) {
if (targetInstruction.opcode != Opcode.INVOKE_VIRTUAL) continue
for ((targetIndex, targetInstruction) in withIndex()) {
if (targetInstruction.opcode != Opcode.INVOKE_VIRTUAL) continue
if ((targetInstruction as DexBackedInstruction35c).reference.toString() ==
"Landroid/widget/TextView;->getText()Ljava/lang/CharSequence;") {
val insertIndex = targetIndex + 2
val insertRegister = (instructions.elementAt(insertIndex) as Instruction35c).registerC
mutableMethod.addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $SEEKBAR->enableTimeStampSpeed(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$insertRegister
"""
)
patchSuccessArray[0] = true
break
}
}
}
}
}
else -> return@forEachIndexed
}
if (it.instruction<ReferenceInstruction>(targetIndex).reference.toString() ==
"Landroid/widget/TextView;->getText()Ljava/lang/CharSequence;") {
insertIndex = targetIndex + 2
val insertRegister = it.instruction<Instruction35c>(insertIndex).registerC
it.addInstructions(
insertIndex, """
invoke-static {v$insertRegister}, $SEEKBAR->enableTimeStampSpeed(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$insertRegister
"""
)
break
}
}
if (insertIndex == -1)
return PatchResultError("target Instruction not found!")
}
}
val errorIndex: Int = patchSuccessArray.indexOf(false)
} ?: return TotalTimeFingerprint.toErrorResult()
if (errorIndex == -1) {
/*
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: SEEKBAR_SETTINGS",
"SETTINGS: ENABLE_TIME_STAMP_SPEED"
)
/**
* Add settings
*/
SettingsPatch.addPreference(
arrayOf(
"PREFERENCE: SEEKBAR_SETTINGS",
"SETTINGS: ENABLE_TIME_STAMP_SPEED"
)
)
SettingsPatch.updatePatchStatus("enable-timestamps-speed")
SettingsPatch.updatePatchStatus("enable-timestamps-speed")
return PatchResultSuccess()
} else
return PatchResultError("Instruction not found: $errorIndex")
return PatchResultSuccess()
}
}