mirror of
https://github.com/ReVanced/revanced-patches.git
synced 2026-01-15 07:23:13 +00:00
Compare commits
4 Commits
v2.174.0-d
...
v2.174.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
529e90d232 | ||
|
|
c72fd1e2fc | ||
|
|
48965ace7e | ||
|
|
08f1702b18 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,3 +1,17 @@
|
||||
# [2.174.0-dev.20](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.19...v2.174.0-dev.20) (2023-05-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** add `hide-filter-bar` patch ([6cc5f61](https://github.com/revanced/revanced-patches/commit/6cc5f61e0712fe25cd45b137773decaf4b9bb582))
|
||||
|
||||
# [2.174.0-dev.19](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.18...v2.174.0-dev.19) (2023-05-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube/video-speed:** change custom video speeds inside app settings ([#2114](https://github.com/revanced/revanced-patches/issues/2114)) ([d97815a](https://github.com/revanced/revanced-patches/commit/d97815af18e645fd0fa087db0174bcc2a771ec72))
|
||||
|
||||
# [2.174.0-dev.18](https://github.com/revanced/revanced-patches/compare/v2.174.0-dev.17...v2.174.0-dev.18) (2023-05-11)
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ The official ReVanced Patches.
|
||||
| `copy-video-url` | Adds buttons in player to copy video links. | 18.16.37 |
|
||||
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.16.37 |
|
||||
| `custom-video-speed` | Adds more video speed options. | 18.16.37 |
|
||||
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.16.37 |
|
||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.16.37 |
|
||||
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.16.37 |
|
||||
@@ -34,6 +33,7 @@ The official ReVanced Patches.
|
||||
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.16.37 |
|
||||
| `hide-email-address` | Hides the email address in the account switcher. | 18.16.37 |
|
||||
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.16.37 |
|
||||
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.16.37 |
|
||||
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.16.37 |
|
||||
| `hide-get-premium` | Hides advertisement for YouTube Premium under the video player. | 18.16.37 |
|
||||
| `hide-info-cards` | Hides info cards in videos. | 18.16.37 |
|
||||
@@ -49,7 +49,6 @@ The official ReVanced Patches.
|
||||
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.16.37 |
|
||||
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.16.37 |
|
||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||
| `remember-playback-speed` | Adds the ability to remember the playback speed you chose in the video playback speed flyout. | 18.16.37 |
|
||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.16.37 |
|
||||
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.16.37 |
|
||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.16.37 |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.174.0-dev.18
|
||||
version = 2.174.0-dev.20
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,8 @@
|
||||
package app.revanced.patches.shared.settings.preference.impl
|
||||
|
||||
enum class InputType(val type: String) {
|
||||
STRING("text"),
|
||||
STRING("text"), // TODO: rename to "TEXT"
|
||||
TEXT_CAP_CHARACTERS("textCapCharacters"),
|
||||
TEXT_MULTI_LINE("textMultiLine"),
|
||||
NUMBER("number"),
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideFilterBar
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.filterBarHeightId
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object FilterBarHeightFingerprint : LiteralOpcodesFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IPUT
|
||||
),
|
||||
filterBarHeightId
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction
|
||||
|
||||
|
||||
abstract class LiteralOpcodesFingerprint(opcodes: List<Opcode>, literal: Long) : MethodFingerprint(
|
||||
opcodes = opcodes,
|
||||
customFingerprint = {
|
||||
it.implementation?.instructions?.any { instruction ->
|
||||
if (instruction.opcode != Opcode.CONST) return@any false
|
||||
|
||||
val wideLiteral = (instruction as WideLiteralInstruction).wideLiteral
|
||||
|
||||
literal == wideLiteral
|
||||
} ?: false
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.relatedChipCloudMarginId
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object RelatedChipCloudFingerprint : LiteralOpcodesFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
),
|
||||
relatedChipCloudMarginId
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.fingerprints
|
||||
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.patch.HideFilterBarResourcePatch.Companion.barContainerHeightId
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object SearchResultsChipBarFingerprint : LiteralOpcodesFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
),
|
||||
barContainerHeightId
|
||||
)
|
||||
@@ -0,0 +1,87 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.patch
|
||||
|
||||
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.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.annotations.HideFilterBar
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.FilterBarHeightFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.RelatedChipCloudFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.filterbar.fingerprints.SearchResultsChipBarFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Name("hide-filter-bar")
|
||||
@Description("Hides the filter bar in video feeds.")
|
||||
@DependsOn([HideFilterBarResourcePatch::class])
|
||||
@HideFilterBar
|
||||
@Version("0.0.1")
|
||||
class HideFilterBarPatch : BytecodePatch(
|
||||
listOf(
|
||||
RelatedChipCloudFingerprint,
|
||||
SearchResultsChipBarFingerprint,
|
||||
FilterBarHeightFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
FilterBarHeightFingerprint.patch<TwoRegisterInstruction> { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInFeed(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
RelatedChipCloudFingerprint.patch<OneRegisterInstruction>(1) { register ->
|
||||
"invoke-static { v$register }, " +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->hideInRelatedVideos(Landroid/view/View;)V"
|
||||
}
|
||||
|
||||
SearchResultsChipBarFingerprint.patch<OneRegisterInstruction>(-1, -2) { register ->
|
||||
"""
|
||||
invoke-static { v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR->hideInSearch(I)I
|
||||
move-result v$register
|
||||
"""
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/HideFilterBarPatch;"
|
||||
|
||||
/**
|
||||
* Patch a [MethodFingerprint] with a given [instructions].
|
||||
*
|
||||
* @param RegisterInstruction The type of instruction to get the register from.
|
||||
* @param insertIndexOffset The offset to add to the end index of the [MethodFingerprint].
|
||||
* @param hookRegisterOffset The offset to add to the register of the hook.
|
||||
* @param instructions The instructions to add with the register as a parameter.
|
||||
*/
|
||||
private fun <RegisterInstruction: OneRegisterInstruction> MethodFingerprint.patch(
|
||||
insertIndexOffset: Int = 0,
|
||||
hookRegisterOffset: Int = 0,
|
||||
instructions: (Int) -> String
|
||||
) =
|
||||
result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
|
||||
val insertIndex = endIndex + insertIndexOffset
|
||||
val register = instruction<RegisterInstruction>(endIndex + hookRegisterOffset).registerA
|
||||
|
||||
addInstructions(insertIndex, instructions(register))
|
||||
}
|
||||
} ?: throw toErrorResult()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package app.revanced.patches.youtube.layout.hide.filterbar.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@Version("0.0.1")
|
||||
class HideFilterBarResourcePatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
PreferenceScreen(
|
||||
"revanced_hide_filter_bar_preference",
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_preference_title",
|
||||
"Hide filter bar"
|
||||
),
|
||||
listOf(
|
||||
SwitchPreference(
|
||||
"revanced_hide_filter_bar_feed_in_feed",
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_feed_title",
|
||||
"Hide in feed"
|
||||
),
|
||||
false,
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_feed_summary_on",
|
||||
"Hidden in feed"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_feed_summary_off",
|
||||
"Shown in feed"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_filter_bar_feed_in_search",
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_search_title",
|
||||
"Hide in search"
|
||||
),
|
||||
false,
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_search_summary_on",
|
||||
"Hidden in search"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_search_summary_off",
|
||||
"Shown in search"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_filter_bar_feed_in_related_videos",
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_related_videos_title",
|
||||
"Hide in related videos"
|
||||
),
|
||||
false,
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_related_videos_summary_on",
|
||||
"Hidden in related videos"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_filter_bar_feed_in_related_videos_summary_off",
|
||||
"Shown in related videos"
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
relatedChipCloudMarginId = "related_chip_cloud_reduced_margins".layoutResourceId("layout")
|
||||
filterBarHeightId = "filter_bar_height".layoutResourceId()
|
||||
barContainerHeightId = "bar_container_height".layoutResourceId()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
var filterBarHeightId = -1L
|
||||
var relatedChipCloudMarginId = -1L
|
||||
var barContainerHeightId = -1L
|
||||
|
||||
private fun String.layoutResourceId(type: String = "dimen") =
|
||||
ResourceMappingPatch.resourceMappings.single { it.type == type && it.name == this }.id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.youtube.misc.video.speed
|
||||
|
||||
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.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.patch.CustomVideoSpeedPatch
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch
|
||||
|
||||
@Patch
|
||||
@Name("video-speed")
|
||||
@Description("Adds custom video speeds and ability to remember the playback speed you chose in the video playback speed flyout.")
|
||||
@DependsOn([CustomVideoSpeedPatch::class, RememberPlaybackSpeedPatch::class])
|
||||
@Version("0.0.1")
|
||||
class VideoSpeeds : BytecodePatch() {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
return PatchResultSuccess() // All sub patches succeeded.
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object VideoSpeedPatchFingerprint : MethodFingerprint(
|
||||
opcodes = listOf(Opcode.FILL_ARRAY_DATA),
|
||||
customFingerprint = { methodDef ->
|
||||
methodDef.definingClass.endsWith("CustomVideoSpeedPatch;") && methodDef.name == "<clinit>"
|
||||
}
|
||||
)
|
||||
@@ -8,37 +8,47 @@ import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.InputType
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedLimiterFingerprint
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.VideoSpeedPatchFingerprint
|
||||
import org.jf.dexlib2.builder.instruction.BuilderArrayPayload
|
||||
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.FieldReference
|
||||
import org.jf.dexlib2.iface.reference.MethodReference
|
||||
import java.util.stream.DoubleStream
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Patch
|
||||
@Name("custom-video-speed")
|
||||
@Description("Adds more video speed options.")
|
||||
@Description("Adds custom video speed options.")
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@CustomPlaybackSpeedCompatibility
|
||||
@Version("0.0.1")
|
||||
class CustomVideoSpeedPatch : BytecodePatch(
|
||||
listOf(
|
||||
SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint, VideoSpeedPatchFingerprint
|
||||
SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint
|
||||
)
|
||||
) {
|
||||
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
val speedLimitMin = minVideoSpeed!!.toFloat()
|
||||
val speedLimitMax = maxVideoSpeed!!.toFloat().coerceAtLeast(speedLimitMin)
|
||||
val speedsGranularity = videoSpeedsGranularity!!.toFloat()
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
TextPreference(
|
||||
key = "revanced_custom_video_speeds",
|
||||
title = StringResource(
|
||||
"revanced_custom_video_speeds_title",
|
||||
"Custom playback speeds"
|
||||
),
|
||||
inputType = InputType.TEXT_MULTI_LINE,
|
||||
summary = StringResource(
|
||||
"revanced_custom_video_speeds_summary",
|
||||
"Add or change the video speeds available"
|
||||
),
|
||||
default = "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0"
|
||||
)
|
||||
)
|
||||
|
||||
val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!!
|
||||
val arrayGenMethodImpl = arrayGenMethod.implementation!!
|
||||
@@ -61,7 +71,7 @@ class CustomVideoSpeedPatch : BytecodePatch(
|
||||
|
||||
val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA
|
||||
|
||||
val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->videoSpeeds:[F"
|
||||
val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->customVideoSpeeds:[F"
|
||||
|
||||
arrayGenMethod.addInstructions(
|
||||
arrayLengthConstIndex + 1,
|
||||
@@ -96,100 +106,17 @@ class CustomVideoSpeedPatch : BytecodePatch(
|
||||
val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA
|
||||
val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA
|
||||
|
||||
fun hexFloat(float: Float): String = "0x%08x".format(float.toRawBits())
|
||||
|
||||
// edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x
|
||||
limiterMethod.replaceInstruction(
|
||||
limiterMinConstIndex,
|
||||
"const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}"
|
||||
"sget v$limiterMinConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->minVideoSpeed:F"
|
||||
)
|
||||
limiterMethod.replaceInstruction(
|
||||
limiterMaxConstIndex,
|
||||
"const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}"
|
||||
)
|
||||
|
||||
val constructorResult = VideoSpeedPatchFingerprint.result!!
|
||||
val constructor = constructorResult.mutableMethod
|
||||
val implementation = constructor.implementation!!
|
||||
|
||||
val stepsGranularity = 8F
|
||||
val step = speedLimitMax
|
||||
.minus(speedLimitMin) // calculate the range of the speeds
|
||||
.div(speedsGranularity)
|
||||
.times(stepsGranularity)
|
||||
.roundToInt()
|
||||
.div(stepsGranularity)// round to nearest multiple of stepsGranularity
|
||||
.coerceAtLeast(1 / stepsGranularity) // ensure steps are at least 1/8th of the step granularity
|
||||
|
||||
val videoSpeedsArray = buildList<Number> {
|
||||
DoubleStream
|
||||
.iterate(speedLimitMin.toDouble()) { it + step } // create a stream of speeds
|
||||
.let { speedStream ->
|
||||
for (speed in speedStream) {
|
||||
if (speed > speedLimitMax) break
|
||||
add(speed.toFloat().toRawBits())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adjust the new array of speeds size
|
||||
constructor.replaceInstruction(
|
||||
0,
|
||||
"const/16 v0, ${videoSpeedsArray.size}"
|
||||
)
|
||||
|
||||
// create the payload with the new speeds
|
||||
val arrayPayloadIndex = implementation.instructions.size - 1
|
||||
implementation.replaceInstruction(
|
||||
arrayPayloadIndex,
|
||||
BuilderArrayPayload(
|
||||
4,
|
||||
videoSpeedsArray
|
||||
)
|
||||
"sget v$limiterMaxConstDestination, Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->maxVideoSpeed:F"
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object : OptionsContainer() {
|
||||
private fun String?.validate(max: Int? = null) = this?.toFloatOrNull() != null &&
|
||||
toFloat().let { float ->
|
||||
float > 0 && max?.let { max -> float <= max } ?: true
|
||||
}
|
||||
|
||||
val videoSpeedsGranularity by option(
|
||||
PatchOption.StringOption(
|
||||
"granularity",
|
||||
"16",
|
||||
"Video speed granularity",
|
||||
"The granularity of the video speeds. The higher the value, the more speeds will be available.",
|
||||
true
|
||||
) {
|
||||
it.validate()
|
||||
}
|
||||
)
|
||||
|
||||
val minVideoSpeed by option(
|
||||
PatchOption.StringOption(
|
||||
"min",
|
||||
"0.25",
|
||||
"Minimum video speed",
|
||||
"The minimum video speed.",
|
||||
true
|
||||
) {
|
||||
it.validate()
|
||||
}
|
||||
)
|
||||
|
||||
val maxVideoSpeed by option(
|
||||
PatchOption.StringOption(
|
||||
"max",
|
||||
"5.0",
|
||||
"Maximum video speed",
|
||||
"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.",
|
||||
true
|
||||
) {
|
||||
it.validate(5)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch.Companion.reference
|
||||
import app.revanced.patches.youtube.misc.video.speed.custom.patch.CustomVideoSpeedPatch
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.annotation.RememberPlaybackSpeedCompatibility
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("remember-playback-speed")
|
||||
@Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.")
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoInformationPatch::class, CustomVideoSpeedPatch::class])
|
||||
@RememberPlaybackSpeedCompatibility
|
||||
@Version("0.0.1")
|
||||
class RememberPlaybackSpeedPatch : BytecodePatch(
|
||||
|
||||
Reference in New Issue
Block a user