mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-04-30 06:34:28 +02:00
Compare commits
7 Commits
main
...
v5.22.0-de
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1d5c6c9351 | ||
![]() |
06b35b2a7d | ||
![]() |
a1207c9784 | ||
![]() |
f198bece65 | ||
![]() |
f459c3c7fa | ||
![]() |
39769bf384 | ||
![]() |
c255ac18e0 |
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,3 +1,23 @@
|
||||
# [5.22.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.22.0-dev.1...v5.22.0-dev.2) (2025-04-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Shorts autoplay:** Fix autoplay with YT 20.12 ([06b35b2](https://github.com/ReVanced/revanced-patches/commit/06b35b2a7d7371915881e8f430c32ce15fa224de))
|
||||
|
||||
# [5.22.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.21.0...v5.22.0-dev.1) (2025-04-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok - Feed filter:** Hide ads in following feed ([#4844](https://github.com/ReVanced/revanced-patches/issues/4844)) ([c255ac1](https://github.com/ReVanced/revanced-patches/commit/c255ac18e0b2dcf917bd0559876be5a2a81023db))
|
||||
* **YouTube - Spoof app version:** Do not hide spoof version in general settings menu ([#4861](https://github.com/ReVanced/revanced-patches/issues/4861)) ([f459c3c](https://github.com/ReVanced/revanced-patches/commit/f459c3c7fae3a1b8addf3354488dcef9f95255cc))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok - Feed Filter:** Remove TikTok Shop from feed. ([#4851](https://github.com/ReVanced/revanced-patches/issues/4851)) ([f198bec](https://github.com/ReVanced/revanced-patches/commit/f198bece653e3e1adf083129dedb77c1d1a633d7))
|
||||
|
||||
# [5.21.0](https://github.com/ReVanced/revanced-patches/compare/v5.20.1...v5.21.0) (2025-04-25)
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@ package app.revanced.extension.tiktok.feedfilter;
|
||||
|
||||
import com.ss.android.ugc.aweme.feed.model.Aweme;
|
||||
import com.ss.android.ugc.aweme.feed.model.FeedItemList;
|
||||
import com.ss.android.ugc.aweme.follow.presenter.FollowFeedList;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -13,22 +14,41 @@ public final class FeedItemsFilter {
|
||||
new StoryFilter(),
|
||||
new ImageVideoFilter(),
|
||||
new ViewCountFilter(),
|
||||
new LikeCountFilter()
|
||||
new LikeCountFilter(),
|
||||
new ShopFilter()
|
||||
);
|
||||
|
||||
public static void filter(FeedItemList feedItemList) {
|
||||
Iterator<Aweme> feedItemListIterator = feedItemList.items.iterator();
|
||||
while (feedItemListIterator.hasNext()) {
|
||||
Aweme item = feedItemListIterator.next();
|
||||
if (item == null) continue;
|
||||
filterFeedList(feedItemList.items, item -> item);
|
||||
}
|
||||
|
||||
public static void filter(FollowFeedList followFeedList) {
|
||||
filterFeedList(followFeedList.mItems, feed -> (feed != null) ? feed.aweme : null);
|
||||
}
|
||||
|
||||
private static <T> void filterFeedList(List<T> list, AwemeExtractor<T> extractor) {
|
||||
// Could be simplified with removeIf() but requires Android 7.0+ while TikTok supports 4.0+.
|
||||
Iterator<T> iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
T container = iterator.next();
|
||||
Aweme item = extractor.extract(container);
|
||||
if (item != null && shouldFilter(item)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldFilter(Aweme item) {
|
||||
for (IFilter filter : FILTERS) {
|
||||
boolean enabled = filter.getEnabled();
|
||||
if (enabled && filter.getFiltered(item)) {
|
||||
feedItemListIterator.remove();
|
||||
break;
|
||||
}
|
||||
if (filter.getEnabled() && filter.getFiltered(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface AwemeExtractor<T> {
|
||||
Aweme extract(T source);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package app.revanced.extension.tiktok.feedfilter;
|
||||
|
||||
import app.revanced.extension.tiktok.settings.Settings;
|
||||
import com.ss.android.ugc.aweme.feed.model.Aweme;
|
||||
|
||||
public class ShopFilter implements IFilter {
|
||||
private static final String SHOP_INFO = "placeholder_product_id";
|
||||
@Override
|
||||
public boolean getEnabled() {
|
||||
return Settings.HIDE_SHOP.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFiltered(Aweme item) {
|
||||
return item.getShareUrl().contains(SHOP_INFO);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import app.revanced.extension.shared.settings.StringSetting;
|
||||
public class Settings extends BaseSettings {
|
||||
public static final BooleanSetting REMOVE_ADS = new BooleanSetting("remove_ads", TRUE, true);
|
||||
public static final BooleanSetting HIDE_LIVE = new BooleanSetting("hide_live", FALSE, true);
|
||||
public static final BooleanSetting HIDE_SHOP = new BooleanSetting("hide_shop", FALSE, true);
|
||||
public static final BooleanSetting HIDE_STORY = new BooleanSetting("hide_story", FALSE, true);
|
||||
public static final BooleanSetting HIDE_IMAGE = new BooleanSetting("hide_image", FALSE, true);
|
||||
public static final StringSetting MIN_MAX_VIEWS = new StringSetting("min_max_views", "0-" + Long.MAX_VALUE, true);
|
||||
|
@ -26,6 +26,11 @@ public class FeedFilterPreferenceCategory extends ConditionalPreferenceCategory
|
||||
"Remove feed ads", "Remove ads from feed.",
|
||||
Settings.REMOVE_ADS
|
||||
));
|
||||
addPreference(new TogglePreference(
|
||||
context,
|
||||
"Hide TikTok Shop", "Hide TikTok shop from feed.",
|
||||
Settings.HIDE_SHOP
|
||||
));
|
||||
addPreference(new TogglePreference(
|
||||
context,
|
||||
"Hide livestreams", "Hide livestreams from feed.",
|
||||
|
@ -33,4 +33,8 @@ public class Aweme {
|
||||
public AwemeStatistics getStatistics() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
|
||||
public String getShareUrl() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.ss.android.ugc.aweme.follow.presenter;
|
||||
|
||||
import com.ss.android.ugc.aweme.feed.model.Aweme;
|
||||
|
||||
//Dummy class
|
||||
public class FollowFeed {
|
||||
public Aweme aweme;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.ss.android.ugc.aweme.follow.presenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
//Dummy class
|
||||
public class FollowFeedList {
|
||||
public List<FollowFeed> mItems;
|
||||
}
|
@ -2,6 +2,8 @@ package app.revanced.extension.youtube.patches;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -76,7 +78,7 @@ public class ShortsAutoplayPatch {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static Enum<?> changeShortsRepeatBehavior(Enum<?> original) {
|
||||
public static Enum<?> changeShortsRepeatBehavior(@Nullable Enum<?> original) {
|
||||
try {
|
||||
final boolean autoplay;
|
||||
|
||||
@ -98,17 +100,35 @@ public class ShortsAutoplayPatch {
|
||||
: ShortsLoopBehavior.REPEAT;
|
||||
|
||||
if (behavior.ytEnumValue != null) {
|
||||
Logger.printDebug(() -> behavior.ytEnumValue == original
|
||||
? "Changing Shorts repeat behavior from: " + original.name() + " to: " + behavior.ytEnumValue
|
||||
: "Behavior setting is same as original. Using original: " + original.name()
|
||||
);
|
||||
Logger.printDebug(() -> {
|
||||
String name = (original == null ? "unknown (null)" : original.name());
|
||||
return behavior == original
|
||||
? "Behavior setting is same as original. Using original: " + name
|
||||
: "Changing Shorts repeat behavior from: " + name + " to: " + behavior.name();
|
||||
});
|
||||
|
||||
return behavior.ytEnumValue;
|
||||
}
|
||||
|
||||
if (original == null) {
|
||||
// Cannot return null, as null is used to indicate Short was auto played.
|
||||
// Unpatched app replaces null with unknown enum type (appears to fix for bad api data).
|
||||
Enum<?> unknown = ShortsLoopBehavior.UNKNOWN.ytEnumValue;
|
||||
Logger.printDebug(() -> "Original is null, returning: " + unknown.name());
|
||||
return unknown;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "changeShortsRepeatState failure", ex);
|
||||
Logger.printException(() -> "changeShortsRepeatBehavior failure", ex);
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean isAutoPlay(Enum<?> original) {
|
||||
return ShortsLoopBehavior.SINGLE_PLAY.ytEnumValue == original;
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.21.0
|
||||
version = 5.22.0-dev.2
|
||||
|
@ -642,14 +642,12 @@ public abstract class app/revanced/patches/shared/misc/settings/preference/BaseP
|
||||
public static final field Companion Lapp/revanced/patches/shared/misc/settings/preference/BasePreference$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getIcon ()Ljava/lang/String;
|
||||
public final fun getKey ()Ljava/lang/String;
|
||||
public final fun getLayout ()Ljava/lang/String;
|
||||
public final fun getSummaryKey ()Ljava/lang/String;
|
||||
public final fun getTag ()Ljava/lang/String;
|
||||
public final fun getTitleKey ()Ljava/lang/String;
|
||||
public fun hashCode ()I
|
||||
public fun serialize (Lorg/w3c/dom/Document;Lkotlin/jvm/functions/Function1;)Lorg/w3c/dom/Element;
|
||||
}
|
||||
|
||||
|
@ -51,26 +51,6 @@ abstract class BasePreference(
|
||||
layout?.let { setAttribute("android:layout", layout) }
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = key?.hashCode() ?: 0
|
||||
result = 31 * result + titleKey.hashCode()
|
||||
result = 31 * result + tag.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as BasePreference
|
||||
|
||||
if (key != other.key) return false
|
||||
if (titleKey != other.titleKey) return false
|
||||
if (tag != other.tag) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun Element.addSummary(summaryKey: String, summaryType: SummaryType = SummaryType.DEFAULT) =
|
||||
setAttribute("android:${summaryType.type}", "@string/$summaryKey")
|
||||
|
@ -9,6 +9,8 @@ import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/tiktok/feedfilter/FeedItemsFilter;"
|
||||
|
||||
@Suppress("unused")
|
||||
val feedFilterPatch = bytecodePatch(
|
||||
name = "Feed filter",
|
||||
@ -26,14 +28,15 @@ val feedFilterPatch = bytecodePatch(
|
||||
)
|
||||
|
||||
execute {
|
||||
feedApiServiceLIZFingerprint.method.apply {
|
||||
val returnFeedItemInstruction = instructions.first { it.opcode == Opcode.RETURN_OBJECT }
|
||||
val feedItemsRegister = (returnFeedItemInstruction as OneRegisterInstruction).registerA
|
||||
|
||||
addInstruction(
|
||||
returnFeedItemInstruction.location.index,
|
||||
"invoke-static { v$feedItemsRegister }, " +
|
||||
"Lapp/revanced/extension/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V",
|
||||
arrayOf(
|
||||
feedApiServiceLIZFingerprint.method to "$EXTENSION_CLASS_DESCRIPTOR->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V",
|
||||
followFeedFingerprint.method to "$EXTENSION_CLASS_DESCRIPTOR->filter(Lcom/ss/android/ugc/aweme/follow/presenter/FollowFeedList;)V"
|
||||
).forEach { (method, filterSignature) ->
|
||||
val returnInstruction = method.instructions.first { it.opcode == Opcode.RETURN_OBJECT }
|
||||
val register = (returnInstruction as OneRegisterInstruction).registerA
|
||||
method.addInstruction(
|
||||
returnInstruction.location.index,
|
||||
"invoke-static { v$register }, $filterSignature"
|
||||
)
|
||||
}
|
||||
|
||||
@ -42,4 +45,5 @@ val feedFilterPatch = bytecodePatch(
|
||||
"invoke-static {}, Lapp/revanced/extension/tiktok/settings/SettingsStatus;->enableFeedFilter()V",
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,22 @@
|
||||
package app.revanced.patches.tiktok.feedfilter
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val feedApiServiceLIZFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/FeedApiService;") && method.name == "fetchFeedList"
|
||||
}
|
||||
}
|
||||
|
||||
internal val followFeedFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Lcom/ss/android/ugc/aweme/follow/presenter/FollowFeedList;")
|
||||
strings("getFollowFeedList")
|
||||
opcodes(
|
||||
Opcode.INVOKE_INTERFACE_RANGE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE
|
||||
)
|
||||
}
|
@ -1,8 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.shortsautoplay
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal val reelEnumConstructorFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||
@ -20,3 +25,27 @@ internal val reelPlaybackRepeatFingerprint = fingerprint {
|
||||
parameters("L")
|
||||
strings("YoutubePlayerState is in throwing an Error.")
|
||||
}
|
||||
|
||||
internal val reelPlaybackFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("J")
|
||||
custom { method, _ ->
|
||||
indexOfMilliSecondsInstruction(method) >= 0 &&
|
||||
indexOfInitializationInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
private fun indexOfMilliSecondsInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
getReference<FieldReference>()?.name == "MILLISECONDS"
|
||||
}
|
||||
|
||||
internal fun indexOfInitializationInstruction(method: Method) =
|
||||
method.indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>()
|
||||
opcode == Opcode.INVOKE_DIRECT &&
|
||||
reference?.name == "<init>" &&
|
||||
reference.parameterTypes.size == 3 &&
|
||||
reference.parameterTypes.firstOrNull() == "I"
|
||||
}
|
||||
|
@ -2,21 +2,32 @@ package app.revanced.patches.youtube.layout.shortsautoplay
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.addResources
|
||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.youtube.misc.playservice.is_19_34_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.is_20_09_or_greater
|
||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
||||
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
|
||||
import app.revanced.patches.youtube.misc.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.shared.mainActivityOnCreateFingerprint
|
||||
import app.revanced.util.findInstructionIndicesReversedOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/ShortsAutoplayPatch;"
|
||||
|
||||
@ -98,5 +109,84 @@ val shortsAutoplayPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// As of YouTube 20.09, Google has removed the code for 'Autoplay' and 'Pause' from this method.
|
||||
// Manually restore the removed 'Autoplay' code.
|
||||
if (is_20_09_or_greater) {
|
||||
// Variable names are only a rough guess of what these methods do.
|
||||
val userActionMethodIndex = indexOfInitializationInstruction(reelPlaybackFingerprint.method)
|
||||
val userActionMethodReference = reelPlaybackFingerprint.method
|
||||
.getInstruction<ReferenceInstruction>(userActionMethodIndex).reference as MethodReference
|
||||
val reelSequenceControllerMethodIndex = reelPlaybackFingerprint.method
|
||||
.indexOfFirstInstructionOrThrow(userActionMethodIndex, Opcode.INVOKE_VIRTUAL)
|
||||
val reelSequenceControllerMethodReference = reelPlaybackFingerprint.method
|
||||
.getInstruction<ReferenceInstruction>(reelSequenceControllerMethodIndex).reference as MethodReference
|
||||
|
||||
reelPlaybackRepeatFingerprint.method.apply {
|
||||
// Find the first call modified by extension code above.
|
||||
val extensionReturnResultIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_STATIC &&
|
||||
getReference<MethodReference>()?.definingClass == EXTENSION_CLASS_DESCRIPTOR
|
||||
} + 1
|
||||
val enumRegister = getInstruction<OneRegisterInstruction>(extensionReturnResultIndex).registerA
|
||||
val getReelSequenceControllerIndex = indexOfFirstInstructionOrThrow(extensionReturnResultIndex) {
|
||||
val reference = getReference<FieldReference>()
|
||||
opcode == Opcode.IGET_OBJECT &&
|
||||
reference?.definingClass == definingClass &&
|
||||
reference.type == reelSequenceControllerMethodReference.definingClass
|
||||
}
|
||||
val getReelSequenceControllerReference =
|
||||
getInstruction<ReferenceInstruction>(getReelSequenceControllerIndex).reference
|
||||
|
||||
// Add a helper method to avoid finding multiple free registers.
|
||||
// If enum is autoplay then method performs autoplay and returns null,
|
||||
// otherwise returns the same enum.
|
||||
val helperClass = definingClass
|
||||
val helperName = "patch_handleAutoPlay"
|
||||
val helperReturnType = "Ljava/lang/Enum;"
|
||||
val helperMethod = ImmutableMethod(
|
||||
helperClass,
|
||||
helperName,
|
||||
listOf(ImmutableMethodParameter("Ljava/lang/Enum;", null, null)),
|
||||
helperReturnType,
|
||||
AccessFlags.PRIVATE.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(7),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->isAutoPlay(Ljava/lang/Enum;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :ignore
|
||||
new-instance v0, ${userActionMethodReference.definingClass}
|
||||
const/4 v1, 0x3
|
||||
const/4 v2, 0x0
|
||||
invoke-direct { v0, v1, v2, v2 }, $userActionMethodReference
|
||||
iget-object v3, p0, $getReelSequenceControllerReference
|
||||
invoke-virtual { v3, v0 }, $reelSequenceControllerMethodReference
|
||||
const/4 v4, 0x0
|
||||
return-object v4
|
||||
:ignore
|
||||
return-object p1
|
||||
"""
|
||||
)
|
||||
}
|
||||
reelPlaybackRepeatFingerprint.classDef.methods.add(helperMethod)
|
||||
|
||||
addInstructionsWithLabels(
|
||||
extensionReturnResultIndex + 1,
|
||||
"""
|
||||
invoke-direct { p0, v$enumRegister }, $helperClass->$helperName(Ljava/lang/Enum;)$helperReturnType
|
||||
move-result-object v$enumRegister
|
||||
if-nez v$enumRegister, :ignore
|
||||
return-void # Autoplay was performed.
|
||||
:ignore
|
||||
nop
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
|
||||
PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
// Group the switch and list preference together, since General menu is sorted by name
|
||||
// and the preferences can be scattered apart with non English langauges.
|
||||
// and the preferences can be scattered apart with non English languages.
|
||||
PreferenceCategory(
|
||||
titleKey = null,
|
||||
sorting = Sorting.UNSORTED,
|
||||
@ -122,12 +122,12 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
|
||||
val insertIndex = spoofAppVersionFingerprint.patternMatch!!.startIndex + 1
|
||||
val buildOverrideNameRegister =
|
||||
spoofAppVersionFingerprint.method.getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
|
||||
spoofAppVersionFingerprint.apply {
|
||||
val startIndex = patternMatch!!.startIndex
|
||||
val buildOverrideNameRegister = method.getInstruction<OneRegisterInstruction>(startIndex).registerA
|
||||
|
||||
spoofAppVersionFingerprint.method.addInstructions(
|
||||
insertIndex,
|
||||
method.addInstructions(
|
||||
startIndex + 1,
|
||||
"""
|
||||
invoke-static {v$buildOverrideNameRegister}, $EXTENSION_CLASS_DESCRIPTOR->getYouTubeVersionOverride(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$buildOverrideNameRegister
|
||||
@ -135,3 +135,4 @@ val spoofAppVersionPatch = bytecodePatch(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -524,6 +524,9 @@ Ekranın sağ tərəfində düzünə sürüşdürərək səs səviyyəsini tənz
|
||||
<string name="revanced_hide_thanks_button_summary_off">Təşəkkür düyməsi göstərilir</string>
|
||||
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
|
||||
Button only shows if the user ip is from specific region such as the USA or EU. -->
|
||||
<string name="revanced_hide_ask_button_title">Soruş\'u Gizlət</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">Soruş düyməsi gizlidir</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">\"Soruş\" düyməsi göstərilir</string>
|
||||
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_clip_button_title">Kəsmə/ gizlət</string>
|
||||
<string name="revanced_hide_clip_button_summary_on">Kəsmə düyməsi gizlidir</string>
|
||||
@ -1252,7 +1255,7 @@ Bunu aktivləşdirmə, bəzi regionlarda əngəllənib silinən şəkilləri dü
|
||||
<string name="revanced_alt_thumbnail_options_entry_2">DeArrow & Orijinal miniatürlər</string>
|
||||
<string name="revanced_alt_thumbnail_options_entry_3">DeArrow & Kadr çəkilişlər</string>
|
||||
<string name="revanced_alt_thumbnail_options_entry_4">Kadr çəkilişləri</string>
|
||||
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow YouTube videoları üçün izdiham mənbəli miniatürlər təqdim edir. Bu miniatürlər YouTube tərəfindən təqdim edilənlərdən dəfələrlə daha uyğundur.
|
||||
<string name="revanced_alt_thumbnail_dearrow_about_summary">"DeArrow YouTube videoları üçün çox mənbəli miniatürlər təqdim edir. Bu miniatürlər YouTube tərəfindən təqdim edilənlərdən dəfələrlə daha uyğundur.
|
||||
|
||||
Aktivləşdirilərsə, video URL-lər API alıcısına göndəriləcək və başqa məlumat göndərilməyəcək. Videonun DeArrow miniatürləri yoxdursa, orijinal və ya hələ də çəkilişlər göstərilir.
|
||||
|
||||
|
@ -29,7 +29,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_check_environment_manager_not_expected_installer">ReVanced Manager によってインストールされていない</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time">10 分以上前にパッチが適用されている</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_days">%s 日前にパッチが適用されている</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK の作成日情報が破損している</string>
|
||||
<string name="revanced_check_environment_not_near_patch_time_invalid">APK の作成日時データが破損している</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.settingsResourcePatch">
|
||||
<string name="revanced_settings_submenu_title">設定</string>
|
||||
@ -895,10 +895,10 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_restore_old_seekbar_thumbnails_summary_off">シーク中のサムネイルはプレーヤー画面全体に表示されます</string>
|
||||
</patch>
|
||||
<patch id="layout.sponsorblock.sponsorBlockResourcePatch">
|
||||
<string name="revanced_sb_enable_sb">SponsorBlock を有効化</string>
|
||||
<string name="revanced_sb_enable_sb">SponsorBlock を有効にする</string>
|
||||
<string name="revanced_sb_enable_sb_sum">SponsorBlock はユーザーからの情報提供により YouTube 動画のわずらわしい部分をスキップする機能です</string>
|
||||
<string name="revanced_sb_appearance_category">外観</string>
|
||||
<string name="revanced_sb_enable_voting">投票ボタンを表示</string>
|
||||
<string name="revanced_sb_enable_voting">投票ボタンを表示する</string>
|
||||
<string name="revanced_sb_enable_voting_sum_on">セグメントへの投票ボタンはプレーヤー オーバーレイに表示されます</string>
|
||||
<string name="revanced_sb_enable_voting_sum_off">セグメントへの投票ボタンはプレーヤー オーバーレイに表示されません</string>
|
||||
<string name="revanced_sb_square_layout">四角ボタンを使用する</string>
|
||||
@ -909,45 +909,45 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_enable_compact_skip_button_sum_on">ボタンに「スキップ」とだけ表示されます</string>
|
||||
<string name="revanced_sb_enable_compact_skip_button_sum_off">ボタンにカテゴリー名が表示されます</string>
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button">スキップボタンを自動的に非表示にする</string>
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_on">スキップボタンは表示された数秒後に自動的に非表示になります</string>
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_off">スキップボタンはセグメントの開始から終了まで表示されます</string>
|
||||
<string name="revanced_sb_general_skiptoast">スキップ時にトーストを表示</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_on">セグメントが自動的にスキップされたときにトースト ポップアップが表示されます。ここをタップするとサンプルが表示されます</string>
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_on">スキップボタンは、表示された数秒後に自動的に非表示になります</string>
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_off">スキップボタンは、セグメントの開始から終了まで表示されます</string>
|
||||
<string name="revanced_sb_general_skiptoast">スキップ時にトーストを表示する</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_on">セグメントが自動的にスキップされたときに、トースト ポップアップが表示されます。ここをタップするとサンプルが表示されます</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_off">トースト ポップアップは表示されません。ここをタップするとサンプルが表示されます</string>
|
||||
<string name="revanced_sb_general_time_without">セグメントを除いた再生時間を表示</string>
|
||||
<string name="revanced_sb_general_time_without">セグメントを除いた再生時間を表示する</string>
|
||||
<string name="revanced_sb_general_time_without_sum_on">セグメントを除いた再生時間が、動画全体の再生時間の横に括弧付きで表示されます</string>
|
||||
<string name="revanced_sb_general_time_without_sum_off">動画全体の再生時間のみが表示されます</string>
|
||||
<string name="revanced_sb_create_segment_category">セグメントの作成</string>
|
||||
<string name="revanced_sb_enable_create_segment">セグメント作成ボタンを表示する</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">セグメント作成ボタンは表示されます</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_off">セグメント作成ボタンは表示されません</string>
|
||||
<string name="revanced_sb_general_adjusting">新しいセグメントステップを調整する</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">新しいセグメントを作成する際の時間調節ボタンの移動時間 (単位: ミリ秒)</string>
|
||||
<string name="revanced_sb_general_adjusting">セグメントの時間調整幅</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">「セグメントを作成」メニュー内の早送り / 巻き戻しボタンで移動する時間 (ミリ秒)</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">値は正の整数でなければなりません</string>
|
||||
<string name="revanced_sb_guidelines_preference_title">ガイドラインを見る</string>
|
||||
<string name="revanced_sb_guidelines_preference_sum">ガイドラインには、新しいセグメントを作成するためのルールとヒントが含まれています</string>
|
||||
<string name="revanced_sb_guidelines_popup_title">ガイドラインに従ってください</string>
|
||||
<string name="revanced_sb_guidelines_popup_content">新しいセグメントを作成する前に SponsorBlock ガイドラインを読んでください</string>
|
||||
<string name="revanced_sb_guidelines_popup_already_read">既に読んでいます</string>
|
||||
<string name="revanced_sb_guidelines_popup_open">見る</string>
|
||||
<string name="revanced_sb_general">一般設定</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_title">API 利用不可時にトーストを表示</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_on">SponsorBlock が利用できない場合はトースト ポップアップが表示されます</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_off">SponsorBlock が利用できない場合でもトースト ポップアップは表示されません</string>
|
||||
<string name="revanced_sb_general_skipcount">スキップ数の追跡を有効にする</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_on">SponsorBlock リーダーボードに、どれだけの時間が節約されたかを報告します。セグメントがスキップされるたびにメッセージがリーダーボードに送信されます</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_off">スキップカウント追跡が有効になっていません</string>
|
||||
<string name="revanced_sb_general_min_duration">最小のセグメントの長さ</string>
|
||||
<string name="revanced_sb_guidelines_popup_already_read">既読</string>
|
||||
<string name="revanced_sb_guidelines_popup_open">表示</string>
|
||||
<string name="revanced_sb_general">その他</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_title">API 利用不可時にトーストを表示する</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_on">SponsorBlock が利用できない場合は、トースト ポップアップが表示されます</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_off">SponsorBlock が利用できない場合でも、トースト ポップアップは表示されません</string>
|
||||
<string name="revanced_sb_general_skipcount">スキップデータを送信する</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_on">SponsorBlock リーダーボード にスキップによって節約した時間を送信します。セグメントをスキップする度にデータを送信します</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_off">スキップデータは送信されません</string>
|
||||
<string name="revanced_sb_general_min_duration">セグメントのしきい値</string>
|
||||
<string name="revanced_sb_general_min_duration_sum">設定値 (単位: 秒) より短いセグメントはスキップされず、プレーヤーにも表示されません</string>
|
||||
<string name="revanced_sb_general_min_duration_invalid">セグメントのしきい値が無効です</string>
|
||||
<string name="revanced_sb_general_uuid">非公開ユーザー ID</string>
|
||||
<string name="revanced_sb_general_uuid_sum">この ID は公開すべきではありません。パスワードのようなものであり、誰とも共有すべきではありません。もし誰かがこの ID を手に入れた場合、あなたになりすますことができます</string>
|
||||
<string name="revanced_sb_general_uuid_invalid">非公開ユーザー ID は 30 文字以上必要です</string>
|
||||
<string name="revanced_sb_general_api_url">API の URL を変更</string>
|
||||
<string name="revanced_sb_general_api_url_sum">SponsorBlockのアドレスはサーバーへの呼び出しに使用されます</string>
|
||||
<string name="revanced_sb_api_url_reset">API の URL をリセットしました</string>
|
||||
<string name="revanced_sb_general_api_url">API URL</string>
|
||||
<string name="revanced_sb_general_api_url_sum">SponsorBlock がサーバーとの通信で使用するアドレス</string>
|
||||
<string name="revanced_sb_api_url_reset">API URL をリセットしました</string>
|
||||
<string name="revanced_sb_api_url_invalid">API URL が無効です</string>
|
||||
<string name="revanced_sb_api_url_changed">API の URL を変更しました</string>
|
||||
<string name="revanced_sb_api_url_changed">API URL を変更しました</string>
|
||||
<string name="revanced_sb_settings_ie">設定のインポート / エクスポート</string>
|
||||
<string name="revanced_sb_settings_copy">コピー</string>
|
||||
<string name="revanced_sb_settings_ie_sum">SponsorBlock の設定を JSON 形式のテキストでインポート / エクスポートします。この JSON テキストは他のプラットフォームでも利用可能です</string>
|
||||
@ -955,7 +955,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_settings_import_successful">設定が正常にインポートされました</string>
|
||||
<string name="revanced_sb_settings_import_failed">インポートに失敗しました: %s</string>
|
||||
<string name="revanced_sb_settings_export_failed">エクスポートに失敗しました: %s</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning">"設定には、SponsorBlock の非公開ユーザー ID が含まれています。このユーザー ID はパスワードのようなものであり、決して共有すべきではありません。"</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning">"設定には、SponsorBlock の非公開ユーザー ID が含まれています。この ID はパスワードのようなものであり、決して共有すべきではありません。"</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning_dismiss">今後表示しない</string>
|
||||
<string name="revanced_sb_diff_segments">セグメントのスキップ</string>
|
||||
<string name="revanced_sb_segments_sponsor">スポンサー</string>
|
||||
@ -968,7 +968,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_segments_highlight_sum">動画の中で最も興味を引く場面</string>
|
||||
<string name="revanced_sb_segments_intro">幕間 / オープニング (イントロ)</string>
|
||||
<string name="revanced_sb_segments_intro_sum">実際のコンテンツを含まない間隔。一時停止、固定フレーム、繰り返しアニメーションを使用できます。情報を含むトランジションは含まれません。</string>
|
||||
<string name="revanced_sb_segments_outro">終了画面 / クレジット (アウトロ)</string>
|
||||
<string name="revanced_sb_segments_outro">終了画面 / クレジット(アウトロ)</string>
|
||||
<string name="revanced_sb_segments_outro_sum">クレジットまたはYouTubeのエンドカードが表示される場合、情報を持つ結論にはなりません</string>
|
||||
<string name="revanced_sb_segments_preview">予告編 / 総集編 / フック</string>
|
||||
<string name="revanced_sb_segments_preview_sum">ビデオやシリーズの他のビデオで何が起こったのかを示すクリップのコレクション 全ての情報が他の場所で繰り返されます</string>
|
||||
@ -1024,9 +1024,9 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_timeout">SponsorBlock は一時的に利用できません (API タイムアウト)</string>
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_status">SponsorBlockは一時的に利用できません (ステータス: %d)</string>
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_generic">SponsorBlockは一時的に利用できません</string>
|
||||
<string name="revanced_sb_vote_failed_timeout">セグメントに投票できません (API タイムアウト)</string>
|
||||
<string name="revanced_sb_vote_failed_timeout">セグメントに投票できませんでした (API タイムアウト)</string>
|
||||
<string name="revanced_sb_vote_failed_unknown_error">セグメントに投票できませんでした(ステータス: %1$d %2$s)</string>
|
||||
<string name="revanced_sb_vote_failed_forbidden">セグメントに投票できません: %s</string>
|
||||
<string name="revanced_sb_vote_failed_forbidden">セグメントに投票できませんでした: %s</string>
|
||||
<string name="revanced_sb_vote_upvote">高評価</string>
|
||||
<string name="revanced_sb_vote_downvote">低評価</string>
|
||||
<string name="revanced_sb_vote_category">カテゴリーの変更</string>
|
||||
@ -1083,7 +1083,7 @@ MicroG GmsCore に対する電池の最適化を無効にしても、バッテ
|
||||
<string name="revanced_sb_color_opacity_label">透明度:</string>
|
||||
<string name="revanced_sb_color_dot_label">色:</string>
|
||||
<string name="revanced_sb_color_changed">色を変更しました</string>
|
||||
<string name="revanced_sb_color_reset">色をリセット</string>
|
||||
<string name="revanced_sb_color_reset">色がリセットされました</string>
|
||||
<string name="revanced_sb_color_invalid">色の値が無効です</string>
|
||||
<string name="revanced_sb_reset_color">色をリセット</string>
|
||||
<string name="revanced_sb_reset">リセット</string>
|
||||
|
@ -524,7 +524,7 @@ Podesite jačinu zvuka prevlačenjem vertikalno na desnoj strani ekrana"</string
|
||||
<string name="revanced_hide_thanks_button_summary_off">Dugme „Hvala” je prikazano</string>
|
||||
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
|
||||
Button only shows if the user ip is from specific region such as the USA or EU. -->
|
||||
<string name="revanced_hide_ask_button_title">Sakrij „Pitaj”</string>
|
||||
<string name="revanced_hide_ask_button_title">Sakrij dugme „Pitaj”</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">Dugme „Pitaj” je skriveno</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">Dugme „Pitaj” je prikazano</string>
|
||||
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
|
||||
|
@ -524,7 +524,7 @@ Second \"item\" text"</string>
|
||||
<string name="revanced_hide_thanks_button_summary_off">Дугме „Хвала” је приказано</string>
|
||||
<!-- 'Ask' should be translated with the same localized wording that YouTube displays.
|
||||
Button only shows if the user ip is from specific region such as the USA or EU. -->
|
||||
<string name="revanced_hide_ask_button_title">Сакриј „Питај”</string>
|
||||
<string name="revanced_hide_ask_button_title">Сакриј дугме „Питај”</string>
|
||||
<string name="revanced_hide_ask_button_summary_on">Дугме „Питај” је скривено</string>
|
||||
<string name="revanced_hide_ask_button_summary_off">Дугме „Питај” је приказано</string>
|
||||
<!-- 'Clip' should be translated with the same localized wording that YouTube displays. -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user