mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-10 19:33:55 +01:00
Compare commits
15 Commits
v4.11.1-de
...
v4.12.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e72067dcb | ||
|
|
d87f36e7e2 | ||
|
|
4432fe65df | ||
|
|
8b0d8ee9f4 | ||
|
|
250cc7cbde | ||
|
|
1af65de1f6 | ||
|
|
6e87e3044c | ||
|
|
273af26274 | ||
|
|
2b1b081051 | ||
|
|
f2bf2da9a5 | ||
|
|
15317003b1 | ||
|
|
6c81a5b65f | ||
|
|
9ef51abde7 | ||
|
|
1d31565d47 | ||
|
|
b944fb7bf1 |
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
ref: dev
|
||||
|
||||
- name: Pull strings
|
||||
uses: crowdin/github-action@v1
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
config: crowdin.yml
|
||||
download_translations: true
|
||||
|
||||
2
.github/workflows/push_strings.yml
vendored
2
.github/workflows/push_strings.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Push strings
|
||||
uses: crowdin/github-action@v1
|
||||
uses: crowdin/github-action@v2
|
||||
with:
|
||||
config: crowdin.yml
|
||||
upload_sources: true
|
||||
|
||||
43
CHANGELOG.md
43
CHANGELOG.md
@@ -1,3 +1,46 @@
|
||||
# [4.12.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.5...v4.12.0-dev.6) (2024-07-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Spoof build info` patch ([e7829b4](https://github.com/ReVanced/revanced-patches/commit/e7829b41e782c9feda23b9d6acf48bae277d24d9))
|
||||
|
||||
# [4.12.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.4...v4.12.0-dev.5) (2024-07-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Hide mock location` patch ([#3417](https://github.com/ReVanced/revanced-patches/issues/3417)) ([5f81b40](https://github.com/ReVanced/revanced-patches/commit/5f81b40e7d5567fb5689d08ccc9caeaa267c3143))
|
||||
* **Google Photos:** Add `GmsCore support` patch ([#3414](https://github.com/ReVanced/revanced-patches/issues/3414)) ([24528e0](https://github.com/ReVanced/revanced-patches/commit/24528e0a6eec17ce0a3c52f8862585933615ad28))
|
||||
|
||||
# [4.12.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.3...v4.12.0-dev.4) (2024-07-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Google News:** Add `Enable CustomTabs` and `GmsCore support` patch ([#3111](https://github.com/ReVanced/revanced-patches/issues/3111)) ([ad59096](https://github.com/ReVanced/revanced-patches/commit/ad590962275f888b335252ad5bed0f34e959d3c7))
|
||||
|
||||
# [4.12.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.2...v4.12.0-dev.3) (2024-07-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide ads:** Restore compatibility with latest version by fixing fingerprint ([#3455](https://github.com/ReVanced/revanced-patches/issues/3455)) ([4505fa4](https://github.com/ReVanced/revanced-patches/commit/4505fa4138bb55c8957790239c01b8dda63d6cdd))
|
||||
|
||||
# [4.12.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.12.0-dev.1...v4.12.0-dev.2) (2024-07-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add `Bypass image region restrictions` patch ([#3442](https://github.com/ReVanced/revanced-patches/issues/3442)) ([765fab2](https://github.com/ReVanced/revanced-patches/commit/765fab2af2769349446cc0f2109343ef3bd8c621))
|
||||
|
||||
# [4.12.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.11.1-dev.1...v4.12.0-dev.1) (2024-07-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **SoundCloud:** Add `Enable offline sync` patch ([#3407](https://github.com/ReVanced/revanced-patches/issues/3407)) ([4de86c6](https://github.com/ReVanced/revanced-patches/commit/4de86c6407376bcd3cc0513a2f0707410b8d7ccd))
|
||||
|
||||
## [4.11.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.11.0...v4.11.1-dev.1) (2024-07-12)
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,50 @@ public final class app/revanced/patches/all/interaction/gestures/PredictiveBackG
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/location/hide/HideMockLocationPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/all/location/hide/HideMockLocationPatch;
|
||||
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
|
||||
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Lkotlin/Pair;
|
||||
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Pair;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/all/misc/build/BaseSpoofBuildInfoPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
|
||||
public fun <init> ()V
|
||||
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
|
||||
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Lkotlin/Pair;
|
||||
protected fun getBoard ()Ljava/lang/String;
|
||||
protected fun getBootloader ()Ljava/lang/String;
|
||||
protected fun getBrand ()Ljava/lang/String;
|
||||
protected fun getCpuAbi ()Ljava/lang/String;
|
||||
protected fun getCpuAbi2 ()Ljava/lang/String;
|
||||
protected fun getDevice ()Ljava/lang/String;
|
||||
protected fun getDisplay ()Ljava/lang/String;
|
||||
protected fun getFingerprint ()Ljava/lang/String;
|
||||
protected fun getHardware ()Ljava/lang/String;
|
||||
protected fun getHost ()Ljava/lang/String;
|
||||
protected fun getId ()Ljava/lang/String;
|
||||
protected fun getManufacturer ()Ljava/lang/String;
|
||||
protected fun getModel ()Ljava/lang/String;
|
||||
protected fun getOdmSku ()Ljava/lang/String;
|
||||
protected fun getProduct ()Ljava/lang/String;
|
||||
protected fun getRadio ()Ljava/lang/String;
|
||||
protected fun getSerial ()Ljava/lang/String;
|
||||
protected fun getSku ()Ljava/lang/String;
|
||||
protected fun getSocManufacturer ()Ljava/lang/String;
|
||||
protected fun getSocModel ()Ljava/lang/String;
|
||||
protected fun getTags ()Ljava/lang/String;
|
||||
protected fun getTime ()Ljava/lang/Long;
|
||||
protected fun getType ()Ljava/lang/String;
|
||||
protected fun getUser ()Ljava/lang/String;
|
||||
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Pair;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/build/SpoofBuildInfoPatch : app/revanced/patches/all/misc/build/BaseSpoofBuildInfoPatch {
|
||||
public fun <init> ()V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/misc/debugging/EnableAndroidDebuggingPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/all/misc/debugging/EnableAndroidDebuggingPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -217,6 +261,36 @@ public final class app/revanced/patches/finanzonline/detection/root/RootDetectio
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlenews/customtabs/EnableCustomTabs : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlenews/customtabs/EnableCustomTabs;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlenews/misc/gms/GmsCoreSupportPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlenews/misc/gms/GmsCoreSupportResourcePatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlenews/misc/gms/GmsCoreSupportResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlenews/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlenews/misc/integrations/IntegrationsPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/gms/GmsCoreSupportPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlephotos/misc/gms/GmsCoreSupportResourcePatch : app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/gms/GmsCoreSupportResourcePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlephotos/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/integrations/IntegrationsPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1050,6 +1124,12 @@ public final class app/revanced/patches/soundcloud/analytics/DisableTelemetryPat
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/soundcloud/offlinesync/EnableOfflineSyncPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/soundcloud/offlinesync/EnableOfflineSyncPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/spotify/layout/theme/CustomThemePatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/spotify/layout/theme/CustomThemePatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -1718,6 +1798,12 @@ public final class app/revanced/patches/youtube/layout/thumbnails/AlternativeThu
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/layout/thumbnails/BypassImageRegionRestrictions;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/announcements/AnnouncementsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1784,6 +1870,16 @@ public final class app/revanced/patches/youtube/misc/gms/GmsCoreSupportResourceP
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;
|
||||
public final fun addImageUrlErrorCallbackHook (Ljava/lang/String;)V
|
||||
public final fun addImageUrlHook (Ljava/lang/String;Z)V
|
||||
public static synthetic fun addImageUrlHook$default (Lapp/revanced/patches/youtube/misc/imageurlhook/CronetImageUrlHook;Ljava/lang/String;ZILjava/lang/Object;)V
|
||||
public final fun addImageUrlSuccessCallbackHook (Ljava/lang/String;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/integrations/IntegrationsPatch;
|
||||
}
|
||||
@@ -2011,7 +2107,11 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun indexOfIdResourceOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
|
||||
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
|
||||
public static final fun resultOrThrow (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
|
||||
public static final fun returnEarly (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Z)V
|
||||
public static final fun returnEarly (Ljava/lang/Iterable;Z)V
|
||||
public static final fun returnEarly (Ljava/util/List;Z)V
|
||||
public static synthetic fun returnEarly$default (Lapp/revanced/patcher/fingerprint/MethodFingerprint;ZILjava/lang/Object;)V
|
||||
public static synthetic fun returnEarly$default (Ljava/lang/Iterable;ZILjava/lang/Object;)V
|
||||
public static synthetic fun returnEarly$default (Ljava/util/List;ZILjava/lang/Object;)V
|
||||
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun traverseClassHierarchy (Lapp/revanced/patcher/data/BytecodeContext;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 4.11.1-dev.1
|
||||
version = 4.12.0-dev.6
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
revanced-patcher = "19.3.1"
|
||||
#noinspection GradleDependency
|
||||
smali = "3.0.5" # 3.0.7 breaks binary compatibility. Tracking https://github.com/google/smali/issues/58.
|
||||
guava = "33.1.0-jre"
|
||||
gson = "2.10.1"
|
||||
binary-compatibility-validator = "0.14.0"
|
||||
guava = "33.2.1-jre"
|
||||
gson = "2.11.0"
|
||||
binary-compatibility-validator = "0.15.1"
|
||||
kotlin = "2.0.0"
|
||||
|
||||
[libraries]
|
||||
|
||||
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
2152
package-lock.json
generated
2152
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.9.1",
|
||||
"semantic-release": "^23.0.8"
|
||||
"gradle-semantic-release-plugin": "^1.9.2",
|
||||
"semantic-release": "^24.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package app.revanced.patches.all.location.hide
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch
|
||||
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||
import app.revanced.patches.all.misc.transformation.fromMethodReference
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch(
|
||||
name = "Hide mock location",
|
||||
description = "Prevents the app from knowing the device location is being mocked by a third party app.",
|
||||
use = false
|
||||
)
|
||||
object HideMockLocationPatch : BaseTransformInstructionsPatch<Pair<Instruction, Int>>() {
|
||||
override fun filterMap(
|
||||
classDef: ClassDef,
|
||||
method: Method,
|
||||
instruction: Instruction,
|
||||
instructionIndex: Int
|
||||
): Pair<Instruction, Int>? {
|
||||
val reference = instruction.getReference<MethodReference>() ?: return null
|
||||
if (fromMethodReference<MethodCall>(reference) == null) return null
|
||||
|
||||
return instruction to instructionIndex
|
||||
}
|
||||
|
||||
override fun transform(mutableMethod: MutableMethod, entry: Pair<Instruction, Int>) {
|
||||
val (instruction, index) = entry
|
||||
instruction as FiveRegisterInstruction
|
||||
|
||||
// Replace return value with a constant `false` boolean.
|
||||
mutableMethod.replaceInstruction(
|
||||
index + 1,
|
||||
"const/4 v${instruction.registerC}, 0x0"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private enum class MethodCall(
|
||||
override val definedClassName: String,
|
||||
override val methodName: String,
|
||||
override val methodParams: Array<String>,
|
||||
override val returnType: String
|
||||
) : IMethodCall {
|
||||
IsMock("Landroid/location/Location;", "isMock", emptyArray(), "Z"),
|
||||
IsFromMockProvider("Landroid/location/Location;", "isFromMockProvider", emptyArray(), "Z")
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package app.revanced.patches.all.misc.build
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
abstract class BaseSpoofBuildInfoPatch : BaseTransformInstructionsPatch<Pair<Int, Pair<String, String>>>() {
|
||||
// The build information supported32BitAbis, supported64BitAbis, and supportedAbis are not supported for now,
|
||||
// because initializing an array in transform is a bit more complex.
|
||||
|
||||
protected open val board: String? = null
|
||||
|
||||
protected open val bootloader: String? = null
|
||||
|
||||
protected open val brand: String? = null
|
||||
|
||||
protected open val cpuAbi: String? = null
|
||||
|
||||
protected open val cpuAbi2: String? = null
|
||||
|
||||
protected open val device: String? = null
|
||||
|
||||
protected open val display: String? = null
|
||||
|
||||
protected open val fingerprint: String? = null
|
||||
|
||||
protected open val hardware: String? = null
|
||||
|
||||
protected open val host: String? = null
|
||||
|
||||
protected open val id: String? = null
|
||||
|
||||
protected open val manufacturer: String? = null
|
||||
|
||||
protected open val model: String? = null
|
||||
|
||||
protected open val odmSku: String? = null
|
||||
|
||||
protected open val product: String? = null
|
||||
|
||||
protected open val radio: String? = null
|
||||
|
||||
protected open val serial: String? = null
|
||||
|
||||
protected open val sku: String? = null
|
||||
|
||||
protected open val socManufacturer: String? = null
|
||||
|
||||
protected open val socModel: String? = null
|
||||
|
||||
protected open val tags: String? = null
|
||||
|
||||
protected open val time: Long? = null
|
||||
|
||||
protected open val type: String? = null
|
||||
|
||||
protected open val user: String? = null
|
||||
|
||||
|
||||
// Lazy, so that patch options above are initialized before they are accessed.
|
||||
private val replacements: Map<String, Pair<String, String>> by lazy {
|
||||
buildMap {
|
||||
if (board != null) put("BOARD", "const-string" to "\"$board\"")
|
||||
if (bootloader != null) put("BOOTLOADER", "const-string" to "\"$bootloader\"")
|
||||
if (brand != null) put("BRAND", "const-string" to "\"$brand\"")
|
||||
if (cpuAbi != null) put("CPU_ABI", "const-string" to "\"$cpuAbi\"")
|
||||
if (cpuAbi2 != null) put("CPU_ABI2", "const-string" to "\"$cpuAbi2\"")
|
||||
if (device != null) put("DEVICE", "const-string" to "\"$device\"")
|
||||
if (display != null) put("DISPLAY", "const-string" to "\"$display\"")
|
||||
if (fingerprint != null) put("FINGERPRINT", "const-string" to "\"$fingerprint\"")
|
||||
if (hardware != null) put("HARDWARE", "const-string" to "\"$hardware\"")
|
||||
if (host != null) put("HOST", "const-string" to "\"$host\"")
|
||||
if (id != null) put("ID", "const-string" to "\"$id\"")
|
||||
if (manufacturer != null) put("MANUFACTURER", "const-string" to "\"$manufacturer\"")
|
||||
if (model != null) put("MODEL", "const-string" to "\"$model\"")
|
||||
if (odmSku != null) put("ODM_SKU", "const-string" to "\"$odmSku\"")
|
||||
if (product != null) put("PRODUCT", "const-string" to "\"$product\"")
|
||||
if (radio != null) put("RADIO", "const-string" to "\"$radio\"")
|
||||
if (serial != null) put("SERIAL", "const-string" to "\"$serial\"")
|
||||
if (sku != null) put("SKU", "const-string" to "\"$sku\"")
|
||||
if (socManufacturer != null) put("SOC_MANUFACTURER", "const-string" to "\"$socManufacturer\"")
|
||||
if (socModel != null) put("SOC_MODEL", "const-string" to "\"$socModel\"")
|
||||
if (tags != null) put("TAGS", "const-string" to "\"$tags\"")
|
||||
if (time != null) put("TIME", "const-wide" to "$time")
|
||||
if (type != null) put("TYPE", "const-string" to "\"$type\"")
|
||||
if (user != null) put("USER", "const-string" to "\"$user\"")
|
||||
}
|
||||
}
|
||||
|
||||
override fun filterMap(
|
||||
classDef: ClassDef,
|
||||
method: Method,
|
||||
instruction: Instruction,
|
||||
instructionIndex: Int
|
||||
): Pair<Int, Pair<String, String>>? {
|
||||
val reference = instruction.getReference<FieldReference>() ?: return null
|
||||
if (reference.definingClass != BUILD_CLASS_DESCRIPTOR) return null
|
||||
|
||||
return replacements[reference.name]?.let { instructionIndex to it }
|
||||
}
|
||||
|
||||
override fun transform(mutableMethod: MutableMethod, entry: Pair<Int, Pair<String, String>>) {
|
||||
val (index, replacement) = entry
|
||||
val (opcode, operand) = replacement
|
||||
val register = mutableMethod.getInstruction<OneRegisterInstruction>(index).registerA
|
||||
|
||||
mutableMethod.replaceInstruction(index, "$opcode v$register, $operand")
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val BUILD_CLASS_DESCRIPTOR = "Landroid/os/Build;"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package app.revanced.patches.all.misc.build
|
||||
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.longPatchOption
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
|
||||
@Patch(
|
||||
name = "Spoof build info",
|
||||
description = "Spoof the information about the current build.",
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
class SpoofBuildInfoPatch : BaseSpoofBuildInfoPatch() {
|
||||
override val board by stringPatchOption(
|
||||
key = "board",
|
||||
default = null,
|
||||
title = "Board",
|
||||
description = "The name of the underlying board, like \"goldfish\"."
|
||||
)
|
||||
|
||||
override val bootloader by stringPatchOption(
|
||||
key = "bootloader",
|
||||
default = null,
|
||||
title = "Bootloader",
|
||||
description = "The system bootloader version number."
|
||||
)
|
||||
|
||||
override val brand by stringPatchOption(
|
||||
key = "brand",
|
||||
default = null,
|
||||
title = "Brand",
|
||||
description = "The consumer-visible brand with which the product/hardware will be associated, if any."
|
||||
)
|
||||
|
||||
override val cpuAbi by stringPatchOption(
|
||||
key = "cpu-abi",
|
||||
default = null,
|
||||
title = "CPU ABI",
|
||||
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead."
|
||||
)
|
||||
|
||||
override val cpuAbi2 by stringPatchOption(
|
||||
key = "cpu-abi-2",
|
||||
default = null,
|
||||
title = "CPU ABI 2",
|
||||
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead."
|
||||
)
|
||||
|
||||
override val device by stringPatchOption(
|
||||
key = "device",
|
||||
default = null,
|
||||
title = "Device",
|
||||
description = "The name of the industrial design."
|
||||
)
|
||||
|
||||
override val display by stringPatchOption(
|
||||
key = "display",
|
||||
default = null,
|
||||
title = "Display",
|
||||
description = "A build ID string meant for displaying to the user."
|
||||
)
|
||||
|
||||
override val fingerprint by stringPatchOption(
|
||||
key = "fingerprint",
|
||||
default = null,
|
||||
title = "Fingerprint",
|
||||
description = "A string that uniquely identifies this build."
|
||||
)
|
||||
|
||||
override val hardware by stringPatchOption(
|
||||
key = "hardware",
|
||||
default = null,
|
||||
title = "Hardware",
|
||||
description = "The name of the hardware (from the kernel command line or /proc)."
|
||||
)
|
||||
|
||||
override val host by stringPatchOption(
|
||||
key = "host",
|
||||
default = null,
|
||||
title = "Host",
|
||||
description = "The host."
|
||||
)
|
||||
|
||||
override val id by stringPatchOption(
|
||||
key = "id",
|
||||
default = null,
|
||||
title = "ID",
|
||||
description = "Either a changelist number, or a label like \"M4-rc20\"."
|
||||
)
|
||||
|
||||
override val manufacturer by stringPatchOption(
|
||||
key = "manufacturer",
|
||||
default = null,
|
||||
title = "Manufacturer",
|
||||
description = "The manufacturer of the product/hardware."
|
||||
)
|
||||
|
||||
override val model by stringPatchOption(
|
||||
key = "model",
|
||||
default = null,
|
||||
title = "Model",
|
||||
description = "The end-user-visible name for the end product."
|
||||
)
|
||||
|
||||
override val odmSku by stringPatchOption(
|
||||
key = "odm-sku",
|
||||
default = null,
|
||||
title = "ODM SKU",
|
||||
description = "The SKU of the device as set by the original design manufacturer (ODM)."
|
||||
)
|
||||
|
||||
override val product by stringPatchOption(
|
||||
key = "product",
|
||||
default = null,
|
||||
title = "Product",
|
||||
description = "The name of the overall product."
|
||||
)
|
||||
|
||||
override val radio by stringPatchOption(
|
||||
key = "radio",
|
||||
default = null,
|
||||
title = "Radio",
|
||||
description = "This field was deprecated in API level 15. " +
|
||||
"The radio firmware version is frequently not available when this class is initialized, " +
|
||||
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead."
|
||||
)
|
||||
|
||||
override val serial by stringPatchOption(
|
||||
key = "serial",
|
||||
default = null,
|
||||
title = "Serial",
|
||||
description = "This field was deprecated in API level 26. Use getSerial() instead."
|
||||
)
|
||||
|
||||
override val sku by stringPatchOption(
|
||||
key = "sku",
|
||||
default = null,
|
||||
title = "SKU",
|
||||
description = "The SKU of the hardware (from the kernel command line)."
|
||||
)
|
||||
|
||||
override val socManufacturer by stringPatchOption(
|
||||
key = "soc-manufacturer",
|
||||
default = null,
|
||||
title = "SOC Manufacturer",
|
||||
description = "The manufacturer of the device's primary system-on-chip."
|
||||
)
|
||||
|
||||
override val socModel by stringPatchOption(
|
||||
key = "soc-model",
|
||||
default = null,
|
||||
title = "SOC Model",
|
||||
description = "The model name of the device's primary system-on-chip."
|
||||
)
|
||||
|
||||
override val tags by stringPatchOption(
|
||||
key = "tags",
|
||||
default = null,
|
||||
title = "Tags",
|
||||
description = "Comma-separated tags describing the build, like \"unsigned,debug\"."
|
||||
)
|
||||
|
||||
override val time by longPatchOption(
|
||||
key = "time",
|
||||
default = null,
|
||||
title = "Time",
|
||||
description = "The time at which the build was produced, given in milliseconds since the UNIX epoch."
|
||||
)
|
||||
|
||||
override val type by stringPatchOption(
|
||||
key = "type",
|
||||
default = null,
|
||||
title = "Type",
|
||||
description = "The type of build, like \"user\" or \"eng\"."
|
||||
)
|
||||
|
||||
override val user by stringPatchOption(
|
||||
key = "user",
|
||||
default = null,
|
||||
title = "User",
|
||||
description = "The user."
|
||||
)
|
||||
}
|
||||
@@ -347,7 +347,10 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
val targetFile =
|
||||
context.get("res/$value/$resourceFileName.xml").also {
|
||||
it.parentFile?.mkdirs()
|
||||
it.createNewFile()
|
||||
|
||||
if(it.createNewFile()) {
|
||||
it.writeText("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n</resources>")
|
||||
}
|
||||
}
|
||||
|
||||
context.xmlEditor[targetFile.path].let { editor ->
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package app.revanced.patches.googlenews.customtabs
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.googlenews.customtabs.fingerprints.LaunchCustomTabFingerprint
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Enable CustomTabs",
|
||||
description = "Enables CustomTabs to open articles in your default browser.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.magazines")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object EnableCustomTabs : BytecodePatch(
|
||||
setOf(LaunchCustomTabFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LaunchCustomTabFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val checkIndex = result.scanResult.patternScanResult!!.endIndex + 1
|
||||
val register = getInstruction<OneRegisterInstruction>(checkIndex).registerA
|
||||
|
||||
replaceInstruction(checkIndex, "const/4 v$register, 0x1")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.googlenews.customtabs.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object LaunchCustomTabFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IPUT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
),
|
||||
customFingerprint = { _, classDef -> classDef.endsWith("CustomTabsArticleLauncher;") },
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
internal object Constants {
|
||||
const val MAGAZINES_PACKAGE_NAME = "com.google.android.apps.magazines"
|
||||
const val REVANCED_MAGAZINES_PACKAGE_NAME = "app.revanced.android.magazines"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.REVANCED_MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.googlenews.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
|
||||
import app.revanced.patches.googlenews.misc.gms.fingerprints.MagazinesActivityOnCreateFingerprint
|
||||
import app.revanced.patches.googlenews.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
|
||||
|
||||
@Suppress("unused")
|
||||
object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
fromPackageName = MAGAZINES_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
|
||||
primeMethodFingerprint = null,
|
||||
mainActivityOnCreateFingerprint = MagazinesActivityOnCreateFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
// Remove version constraint,
|
||||
// once https://github.com/ReVanced/revanced-patches/pull/3111#issuecomment-2240877277 is resolved.
|
||||
compatiblePackages = setOf(CompatiblePackage(MAGAZINES_PACKAGE_NAME, setOf("5.108.0.644447823"))),
|
||||
) {
|
||||
override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.REVANCED_MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportResourcePatch
|
||||
|
||||
object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch(
|
||||
fromPackageName = MAGAZINES_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
|
||||
spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a666",
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.googlenews.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object MagazinesActivityOnCreateFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;")
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.googlenews.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object PrimeMethodFingerprint : MethodFingerprint(
|
||||
strings = listOf("com.google.android.GoogleCamera", "com.android.vending"),
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.googlenews.misc.integrations
|
||||
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.googlenews.misc.integrations.fingerprints.StartActivityInitFingerprint
|
||||
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
|
||||
|
||||
@Patch(requiresIntegrations = true)
|
||||
object IntegrationsPatch : BaseIntegrationsPatch(
|
||||
setOf(StartActivityInitFingerprint),
|
||||
)
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.patches.googlenews.misc.integrations.fingerprints
|
||||
|
||||
import app.revanced.patches.googlenews.misc.integrations.fingerprints.StartActivityInitFingerprint.getApplicationContextIndex
|
||||
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object StartActivityInitFingerprint : IntegrationsFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.CONST,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.INVOKE_VIRTUAL, // Calls startActivity.getApplicationContext().
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
),
|
||||
insertIndexResolver = { method ->
|
||||
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
getApplicationContextIndex + 2 // Below the move-result-object instruction.
|
||||
},
|
||||
contextRegisterResolver = { method ->
|
||||
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1)
|
||||
as OneRegisterInstruction
|
||||
moveResultInstruction.registerA
|
||||
},
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;")
|
||||
},
|
||||
) {
|
||||
private var getApplicationContextIndex = -1
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
internal object Constants {
|
||||
const val PHOTOS_PACKAGE_NAME = "com.google.android.apps.photos"
|
||||
const val REVANCED_PHOTOS_PACKAGE_NAME = "app.revanced.android.photos"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.PHOTOS_PACKAGE_NAME
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.REVANCED_PHOTOS_PACKAGE_NAME
|
||||
import app.revanced.patches.googlephotos.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
|
||||
import app.revanced.patches.googlephotos.misc.gms.fingerprints.PhotosActivityOnCreateFingerprint
|
||||
import app.revanced.patches.googlephotos.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
|
||||
|
||||
@Suppress("unused")
|
||||
object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
fromPackageName = PHOTOS_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
|
||||
primeMethodFingerprint = null,
|
||||
mainActivityOnCreateFingerprint = PhotosActivityOnCreateFingerprint,
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
compatiblePackages = setOf(CompatiblePackage(PHOTOS_PACKAGE_NAME)),
|
||||
) {
|
||||
override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.PHOTOS_PACKAGE_NAME
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.REVANCED_PHOTOS_PACKAGE_NAME
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportResourcePatch
|
||||
|
||||
object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch(
|
||||
fromPackageName = PHOTOS_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
|
||||
spoofedPackageSignature = "24bb24c05e47e0aefa68a58a766179d9b613a600",
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.googlephotos.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object PhotosActivityOnCreateFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;")
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.googlephotos.misc.integrations
|
||||
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.googlephotos.misc.integrations.fingerprints.HomeActivityInitFingerprint
|
||||
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
|
||||
|
||||
@Patch(requiresIntegrations = true)
|
||||
object IntegrationsPatch : BaseIntegrationsPatch(
|
||||
setOf(HomeActivityInitFingerprint),
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
package app.revanced.patches.googlephotos.misc.integrations.fingerprints
|
||||
|
||||
import app.revanced.patches.googlephotos.misc.integrations.fingerprints.HomeActivityInitFingerprint.getApplicationContextIndex
|
||||
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal object HomeActivityInitFingerprint : IntegrationsFingerprint(
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.INVOKE_VIRTUAL, // Calls getApplicationContext().
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
),
|
||||
insertIndexResolver = { method ->
|
||||
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
getApplicationContextIndex + 2 // Below the move-result-object instruction.
|
||||
},
|
||||
contextRegisterResolver = { method ->
|
||||
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1)
|
||||
as OneRegisterInstruction
|
||||
moveResultInstruction.registerA
|
||||
},
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;")
|
||||
},
|
||||
) {
|
||||
private var getApplicationContextIndex = -1
|
||||
}
|
||||
@@ -12,15 +12,15 @@ import app.revanced.util.returnEarly
|
||||
@Patch(
|
||||
name = "Remove root detection",
|
||||
description = "Removes the check for root permissions and unlocked bootloader.",
|
||||
compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
|
||||
compatiblePackages = [CompatiblePackage("at.gv.oe.app")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RootDetectionPatch : BytecodePatch(
|
||||
setOf(AttestationSupportedCheckFingerprint, BootloaderCheckFingerprint, RootCheckFingerprint)
|
||||
setOf(AttestationSupportedCheckFingerprint, BootloaderCheckFingerprint, RootCheckFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = listOf(
|
||||
override fun execute(context: BytecodeContext) = setOf(
|
||||
AttestationSupportedCheckFingerprint,
|
||||
BootloaderCheckFingerprint,
|
||||
RootCheckFingerprint
|
||||
RootCheckFingerprint,
|
||||
).returnEarly(true)
|
||||
}
|
||||
|
||||
@@ -2,16 +2,13 @@ package app.revanced.patches.instagram.patches.ad.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object AdInjectorFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PRIVATE.value,
|
||||
parameters = listOf("L", "L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
strings = listOf(
|
||||
"SponsoredContentController.insertItem",
|
||||
"SponsoredContentController::Delivery",
|
||||
),
|
||||
strings = listOf("SponsoredContentController::Delivery"),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,9 @@ package app.revanced.patches.music.misc.gms
|
||||
import app.revanced.patches.music.misc.gms.Constants.MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.gms.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||
import app.revanced.patches.music.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
|
||||
import app.revanced.patches.music.misc.gms.fingerprints.*
|
||||
import app.revanced.patches.music.misc.gms.fingerprints.CastDynamiteModuleV2Fingerprint
|
||||
import app.revanced.patches.music.misc.gms.fingerprints.MusicActivityOnCreateFingerprint
|
||||
import app.revanced.patches.music.misc.gms.fingerprints.PrimeMethodFingerprint
|
||||
import app.revanced.patches.music.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.shared.fingerprints.CastContextFetchFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch
|
||||
@@ -14,9 +16,6 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
|
||||
primeMethodFingerprint = PrimeMethodFingerprint,
|
||||
earlyReturnFingerprints = setOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
CastDynamiteModuleFingerprint,
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
),
|
||||
@@ -32,13 +31,10 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
fingerprints = setOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
CastDynamiteModuleFingerprint,
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
PrimeMethodFingerprint,
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package app.revanced.patches.music.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object GooglePlayUtilityFingerprint : MethodFingerprint(
|
||||
"I",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
listOf("L", "I"),
|
||||
strings = listOf(
|
||||
"This should never happen.",
|
||||
"MetadataValueReader",
|
||||
"GooglePlayServicesUtil",
|
||||
"com.android.vending",
|
||||
"android.hardware.type.embedded"
|
||||
)
|
||||
)
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.patches.music.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object ServiceCheckFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
listOf("L", "I"),
|
||||
strings = listOf("Google Play Services not available"),
|
||||
)
|
||||
@@ -15,5 +15,5 @@ abstract class BaseDisableAdsPatch(
|
||||
compatiblePackages = compatiblePackages,
|
||||
fingerprints = setOf(IsAdsEnabledFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = listOf(IsAdsEnabledFingerprint).returnEarly()
|
||||
override fun execute(context: BytecodeContext) = IsAdsEnabledFingerprint.returnEarly()
|
||||
}
|
||||
|
||||
@@ -22,5 +22,5 @@ object UnlockSubscriptionPatch : BytecodePatch(
|
||||
setOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) =
|
||||
listOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected).returnEarly()
|
||||
setOf(StartSubscriptionActivityFingerprint, BillingClientOnServiceConnected).returnEarly()
|
||||
}
|
||||
|
||||
@@ -11,8 +11,11 @@ import app.revanced.patches.all.misc.packagename.ChangePackageNamePatch
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.ACTIONS
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES
|
||||
import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.CastDynamiteModuleFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.GooglePlayUtilityFingerprint
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.ServiceCheckFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.returnEarly
|
||||
@@ -42,8 +45,8 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
abstract class BaseGmsCoreSupportPatch(
|
||||
private val fromPackageName: String,
|
||||
private val toPackageName: String,
|
||||
private val primeMethodFingerprint: MethodFingerprint,
|
||||
private val earlyReturnFingerprints: Set<MethodFingerprint>,
|
||||
private val primeMethodFingerprint: MethodFingerprint?,
|
||||
private val earlyReturnFingerprints: Set<MethodFingerprint> = setOf(),
|
||||
private val mainActivityOnCreateFingerprint: MethodFingerprint,
|
||||
private val integrationsPatchDependency: PatchClass,
|
||||
gmsCoreSupportResourcePatch: BaseGmsCoreSupportResourcePatch,
|
||||
@@ -53,7 +56,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
) : BytecodePatch(
|
||||
name = "GmsCore support",
|
||||
description = "Allows patched Google apps to run without root and under a different package name " +
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
"by using GmsCore instead of Google Play Services.",
|
||||
dependencies = setOf(
|
||||
ChangePackageNamePatch::class,
|
||||
gmsCoreSupportResourcePatch::class,
|
||||
@@ -62,6 +65,9 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
compatiblePackages = compatiblePackages,
|
||||
fingerprints = setOf(
|
||||
GmsCoreSupportFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
ServiceCheckFingerprint,
|
||||
CastDynamiteModuleFingerprint,
|
||||
mainActivityOnCreateFingerprint,
|
||||
) + fingerprints,
|
||||
requiresIntegrations = true,
|
||||
@@ -91,16 +97,19 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
}
|
||||
|
||||
// Specific method that needs to be patched.
|
||||
transformPrimeMethod(packageName)
|
||||
primeMethodFingerprint?.let { transformPrimeMethod(packageName) }
|
||||
|
||||
// Return these methods early to prevent the app from crashing.
|
||||
earlyReturnFingerprints.toList().returnEarly()
|
||||
(earlyReturnFingerprints + ServiceCheckFingerprint + CastDynamiteModuleFingerprint).returnEarly()
|
||||
if (GooglePlayUtilityFingerprint.result != null) {
|
||||
GooglePlayUtilityFingerprint.returnEarly()
|
||||
}
|
||||
|
||||
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
||||
mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
|
||||
"checkGmsCore(Landroid/app/Activity;)V",
|
||||
"checkGmsCore(Landroid/app/Activity;)V",
|
||||
) ?: throw mainActivityOnCreateFingerprint.exception
|
||||
|
||||
// Change the vendor of GmsCore in ReVanced Integrations.
|
||||
@@ -192,7 +201,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
}
|
||||
|
||||
private fun transformPrimeMethod(packageName: String) {
|
||||
primeMethodFingerprint.result?.mutableMethod?.apply {
|
||||
primeMethodFingerprint!!.result?.mutableMethod?.apply {
|
||||
var register = 2
|
||||
|
||||
val index = getInstructions().indexOfFirst {
|
||||
@@ -305,6 +314,7 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
"com.google.android.gms.languageprofile.service.START",
|
||||
"com.google.android.gms.clearcut.service.START",
|
||||
"com.google.android.gms.icing.LIGHTWEIGHT_INDEX_SERVICE",
|
||||
"com.google.android.gms.accountsettings.action.VIEW_SETTINGS",
|
||||
|
||||
// potoken
|
||||
"com.google.android.gms.potokens.service.START",
|
||||
|
||||
@@ -96,27 +96,23 @@ abstract class BaseGmsCoreSupportResourcePatch(
|
||||
private fun ResourceContext.patchManifest() {
|
||||
val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName)
|
||||
|
||||
val manifest = this.get("AndroidManifest.xml").readText()
|
||||
this.get("AndroidManifest.xml").writeText(
|
||||
manifest.replace(
|
||||
"package=\"$fromPackageName",
|
||||
"package=\"$packageName",
|
||||
).replace(
|
||||
"android:authorities=\"$fromPackageName",
|
||||
"android:authorities=\"$packageName",
|
||||
).replace(
|
||||
"$fromPackageName.permission.C2D_MESSAGE",
|
||||
"$packageName.permission.C2D_MESSAGE",
|
||||
).replace(
|
||||
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||
"$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||
).replace(
|
||||
"com.google.android.c2dm",
|
||||
"$gmsCoreVendorGroupId.android.c2dm",
|
||||
).replace(
|
||||
"</queries>",
|
||||
"<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
|
||||
),
|
||||
val transformations = mapOf(
|
||||
"package=\"$fromPackageName" to "package=\"$packageName",
|
||||
"android:authorities=\"$fromPackageName" to "android:authorities=\"$packageName",
|
||||
"$fromPackageName.permission.C2D_MESSAGE" to "$packageName.permission.C2D_MESSAGE",
|
||||
"$fromPackageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" to "$packageName.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION",
|
||||
"com.google.android.c2dm" to "$packageName.android.c2dm",
|
||||
"com.google.android.libraries.photos.api.mars" to "$packageName.android.apps.photos.api.mars",
|
||||
"</queries>" to "<package android:name=\"$gmsCoreVendorGroupId.android.gms\"/></queries>",
|
||||
)
|
||||
|
||||
get("AndroidManifest.xml", false).writeText(
|
||||
transformations.entries.fold(get("AndroidManifest.xml", false).readText()) { acc, (from, to) ->
|
||||
acc.replace(
|
||||
from,
|
||||
to
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.music.misc.gms.fingerprints
|
||||
package app.revanced.patches.shared.misc.gms.fingerprints
|
||||
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.gms.fingerprints
|
||||
package app.revanced.patches.shared.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -8,5 +8,5 @@ internal object GooglePlayUtilityFingerprint : MethodFingerprint(
|
||||
returnType = "I",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("L", "I"),
|
||||
strings = listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms")
|
||||
)
|
||||
strings = listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms"),
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.gms.fingerprints
|
||||
package app.revanced.patches.shared.misc.gms.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -8,5 +8,5 @@ internal object ServiceCheckFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("L", "I"),
|
||||
strings = listOf("Google Play Services not available", "GooglePlayServices not available due to error ")
|
||||
)
|
||||
strings = listOf("Google Play Services not available")
|
||||
)
|
||||
@@ -10,7 +10,7 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.soundcloud.ad.fingerprints.InterceptFingerprint
|
||||
import app.revanced.patches.soundcloud.ad.fingerprints.FeatureConstructorFingerprint
|
||||
import app.revanced.patches.soundcloud.shared.fingerprints.FeatureConstructorFingerprint
|
||||
import app.revanced.patches.soundcloud.ad.fingerprints.UserConsumerPlanConstructorFingerprint
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package app.revanced.patches.soundcloud.offlinesync
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.soundcloud.offlinesync.fingerprints.DownloadOperationsHeaderVerificationFingerprint
|
||||
import app.revanced.patches.soundcloud.offlinesync.fingerprints.DownloadOperationsURLBuilderFingerprint
|
||||
import app.revanced.patches.soundcloud.shared.fingerprints.FeatureConstructorFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Patch(
|
||||
name = "Enable offline sync",
|
||||
compatiblePackages = [CompatiblePackage("com.soundcloud.android")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object EnableOfflineSyncPatch : BytecodePatch(
|
||||
setOf(
|
||||
FeatureConstructorFingerprint, DownloadOperationsURLBuilderFingerprint,
|
||||
DownloadOperationsHeaderVerificationFingerprint
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Enable the feature to allow offline track syncing by modifying the JSON server response.
|
||||
// This method is the constructor of a class representing a "Feature" object parsed from JSON data.
|
||||
// p1 is the name of the feature.
|
||||
// p2 is true if the feature is enabled, false otherwise.
|
||||
FeatureConstructorFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val afterCheckNotNullIndex = 2
|
||||
|
||||
addInstructionsWithLabels(
|
||||
afterCheckNotNullIndex,
|
||||
"""
|
||||
const-string v0, "offline_sync"
|
||||
invoke-virtual { p1, v0 }, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
|
||||
move-result v0
|
||||
if-eqz v0, :skip
|
||||
const/4 p2, 0x1
|
||||
""",
|
||||
ExternalLabel("skip", getInstruction(afterCheckNotNullIndex)),
|
||||
)
|
||||
}
|
||||
|
||||
// Patch the URL builder to use the HTTPS_STREAM endpoint
|
||||
// instead of the offline sync endpoint to downloading the track.
|
||||
DownloadOperationsURLBuilderFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val getEndpointsEnumFieldIndex = 1
|
||||
val getEndpointsEnumFieldInstruction = getInstruction<OneRegisterInstruction>(getEndpointsEnumFieldIndex)
|
||||
|
||||
val targetRegister = getEndpointsEnumFieldInstruction.registerA
|
||||
val endpointsType = getEndpointsEnumFieldInstruction.getReference<FieldReference>()!!.type
|
||||
|
||||
replaceInstruction(
|
||||
getEndpointsEnumFieldIndex,
|
||||
"sget-object v$targetRegister, $endpointsType->HTTPS_STREAM:$endpointsType"
|
||||
)
|
||||
}
|
||||
|
||||
// The HTTPS_STREAM endpoint does not return the necessary headers for offline sync.
|
||||
// Mock the headers to prevent the app from crashing by setting them to empty strings.
|
||||
// The headers are all cosmetic and do not affect the functionality of the app.
|
||||
DownloadOperationsHeaderVerificationFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
// The first three null checks need to be patched.
|
||||
getInstructions().asSequence().filter {
|
||||
it.opcode == Opcode.IF_EQZ
|
||||
}.take(3).map { it.location.index }.forEach { nullCheckIndex ->
|
||||
val headerStringRegister = getInstruction<OneRegisterInstruction>(nullCheckIndex).registerA
|
||||
|
||||
addInstruction(nullCheckIndex, "const-string v$headerStringRegister, \"\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.soundcloud.offlinesync.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object DownloadOperationsHeaderVerificationFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L","L"),
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_STRING
|
||||
),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "DownloadOperations.kt"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.soundcloud.offlinesync.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object DownloadOperationsURLBuilderFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L","L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.FILLED_NEW_ARRAY
|
||||
),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "DownloadOperations.kt"
|
||||
}
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.soundcloud.ad.fingerprints
|
||||
package app.revanced.patches.soundcloud.shared.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,36 +1,18 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.MessageDigestImageUrlParentFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.RequestFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnFailureFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback.OnSucceededFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
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.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
|
||||
@Patch(
|
||||
name = "Alternative thumbnails",
|
||||
@@ -39,7 +21,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
IntegrationsPatch::class,
|
||||
SettingsPatch::class,
|
||||
AddResourcesPatch::class,
|
||||
NavigationBarHookPatch::class
|
||||
NavigationBarHookPatch::class,
|
||||
CronetImageUrlHook::class
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
@@ -74,65 +57,10 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object AlternativeThumbnailsPatch : BytecodePatch(
|
||||
setOf(
|
||||
MessageDigestImageUrlParentFingerprint,
|
||||
OnResponseStartedFingerprint,
|
||||
RequestFingerprint,
|
||||
),
|
||||
) {
|
||||
object AlternativeThumbnailsPatch : BytecodePatch(emptySet()) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch;"
|
||||
|
||||
private lateinit var loadImageUrlMethod: MutableMethod
|
||||
private var loadImageUrlIndex = 0
|
||||
|
||||
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
|
||||
private var loadImageSuccessCallbackIndex = 0
|
||||
|
||||
private lateinit var loadImageErrorCallbackMethod: MutableMethod
|
||||
private var loadImageErrorCallbackIndex = 0
|
||||
|
||||
/**
|
||||
* @param highPriority If the hook should be called before all other hooks.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean) {
|
||||
loadImageUrlMethod.addInstructions(
|
||||
if (highPriority) 0 else loadImageUrlIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p1
|
||||
""",
|
||||
)
|
||||
loadImageUrlIndex += 2
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection completed, which includes normal 200 responses but also includes
|
||||
* status 404 and other error like http responses.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
|
||||
loadImageSuccessCallbackMethod.addInstruction(
|
||||
loadImageSuccessCallbackIndex++,
|
||||
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V",
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection outright failed to complete any connection.
|
||||
*/
|
||||
@Suppress("SameParameterValue")
|
||||
private fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
|
||||
loadImageErrorCallbackMethod.addInstruction(
|
||||
loadImageErrorCallbackIndex++,
|
||||
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V",
|
||||
)
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
|
||||
@@ -177,62 +105,8 @@ object AlternativeThumbnailsPatch : BytecodePatch(
|
||||
ListPreference("revanced_alt_thumbnail_stills_time", summaryKey = null)
|
||||
)
|
||||
|
||||
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
|
||||
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
|
||||
|
||||
fun MethodFingerprint.resolveAndLetMutableMethod(
|
||||
fingerprint: MethodFingerprint,
|
||||
block: (MutableMethod) -> Unit,
|
||||
) = alsoResolve(fingerprint).also { block(it.mutableMethod) }
|
||||
|
||||
MessageDigestImageUrlFingerprint.resolveAndLetMutableMethod(MessageDigestImageUrlParentFingerprint) {
|
||||
loadImageUrlMethod = it
|
||||
addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR, true)
|
||||
}
|
||||
|
||||
OnSucceededFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
||||
loadImageSuccessCallbackMethod = it
|
||||
addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
}
|
||||
|
||||
OnFailureFingerprint.resolveAndLetMutableMethod(OnResponseStartedFingerprint) {
|
||||
loadImageErrorCallbackMethod = it
|
||||
addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
}
|
||||
|
||||
// The URL is required for the failure callback hook, but the URL field is obfuscated.
|
||||
// Add a helper get method that returns the URL field.
|
||||
RequestFingerprint.resultOrThrow().apply {
|
||||
// The url is the only string field that is set inside the constructor.
|
||||
val urlFieldInstruction = mutableMethod.getInstructions().first {
|
||||
if (it.opcode != Opcode.IPUT_OBJECT) return@first false
|
||||
|
||||
val reference = (it as ReferenceInstruction).reference as FieldReference
|
||||
reference.type == "Ljava/lang/String;"
|
||||
} as ReferenceInstruction
|
||||
|
||||
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
|
||||
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
val addedMethodName = "getHookedUrl"
|
||||
mutableClass.methods.add(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
addedMethodName,
|
||||
emptyList(),
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(2),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
iget-object v0, p0, $definingClass->$urlFieldName:Ljava/lang/String;
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
CronetImageUrlHook.addImageUrlSuccessCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
CronetImageUrlHook.addImageUrlErrorCallbackHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.CronetImageUrlHook
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
|
||||
@Patch(
|
||||
name = "Bypass image region restrictions",
|
||||
description = "Adds an option to use a different host for user avatar and channel images," +
|
||||
"and can fix missing images that are blocked in some countries.",
|
||||
dependencies = [
|
||||
IntegrationsPatch::class,
|
||||
SettingsPatch::class,
|
||||
AddResourcesPatch::class,
|
||||
CronetImageUrlHook::class
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.39",
|
||||
"19.03.36",
|
||||
"19.04.38",
|
||||
"19.05.36",
|
||||
"19.06.39",
|
||||
"19.07.40",
|
||||
"19.08.36",
|
||||
"19.09.38",
|
||||
"19.10.39",
|
||||
"19.11.43",
|
||||
"19.12.41",
|
||||
"19.13.37",
|
||||
"19.14.43",
|
||||
"19.15.36",
|
||||
"19.16.39",
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object BypassImageRegionRestrictions : BytecodePatch(emptySet()) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/BypassImageRegionRestrictionsPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
|
||||
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_bypass_image_region_restrictions")
|
||||
)
|
||||
|
||||
// A priority hook is not needed, as the image urls of interest are not modified
|
||||
// by AlternativeThumbnails or any other patch in this repo.
|
||||
CronetImageUrlHook.addImageUrlHook(INTEGRATIONS_CLASS_DESCRIPTOR)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,8 @@ import app.revanced.patches.youtube.misc.fix.playback.SpoofClientPatch
|
||||
import app.revanced.patches.youtube.misc.gms.Constants.REVANCED_YOUTUBE_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME
|
||||
import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption
|
||||
import app.revanced.patches.youtube.misc.gms.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.gms.fingerprints.CastDynamiteModuleV2Fingerprint
|
||||
import app.revanced.patches.youtube.misc.gms.fingerprints.PrimeMethodFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
|
||||
|
||||
@@ -17,9 +18,6 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME,
|
||||
primeMethodFingerprint = PrimeMethodFingerprint,
|
||||
earlyReturnFingerprints = setOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
CastDynamiteModuleFingerprint,
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
),
|
||||
@@ -61,9 +59,6 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
),
|
||||
),
|
||||
fingerprints = setOf(
|
||||
ServiceCheckFingerprint,
|
||||
GooglePlayUtilityFingerprint,
|
||||
CastDynamiteModuleFingerprint,
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
CastContextFetchFingerprint,
|
||||
PrimeMethodFingerprint,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.gms.fingerprints
|
||||
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object CastDynamiteModuleFingerprint : MethodFingerprint(
|
||||
strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
|
||||
)
|
||||
@@ -0,0 +1,134 @@
|
||||
package app.revanced.patches.youtube.misc.imageurlhook
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.MessageDigestImageUrlFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.MessageDigestImageUrlParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.RequestFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnFailureFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnResponseStartedFingerprint
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback.OnSucceededFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
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.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
|
||||
@Patch(
|
||||
description = "Hooks Cronet image urls",
|
||||
dependencies = [
|
||||
IntegrationsPatch::class
|
||||
]
|
||||
)
|
||||
object CronetImageUrlHook : BytecodePatch(
|
||||
setOf(
|
||||
MessageDigestImageUrlParentFingerprint,
|
||||
OnResponseStartedFingerprint,
|
||||
RequestFingerprint
|
||||
)
|
||||
) {
|
||||
private lateinit var loadImageUrlMethod: MutableMethod
|
||||
private var loadImageUrlIndex = 0
|
||||
|
||||
private lateinit var loadImageSuccessCallbackMethod: MutableMethod
|
||||
private var loadImageSuccessCallbackIndex = 0
|
||||
|
||||
private lateinit var loadImageErrorCallbackMethod: MutableMethod
|
||||
private var loadImageErrorCallbackIndex = 0
|
||||
|
||||
/**
|
||||
* @param highPriority If the hook should be called before all other hooks.
|
||||
*/
|
||||
fun addImageUrlHook(targetMethodClass: String, highPriority: Boolean = false) {
|
||||
loadImageUrlMethod.addInstructions(
|
||||
if (highPriority) 0 else loadImageUrlIndex,
|
||||
"""
|
||||
invoke-static { p1 }, $targetMethodClass->overrideImageURL(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p1
|
||||
""",
|
||||
)
|
||||
loadImageUrlIndex += 2
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection completed, which includes normal 200 responses but also includes
|
||||
* status 404 and other error like http responses.
|
||||
*/
|
||||
fun addImageUrlSuccessCallbackHook(targetMethodClass: String) {
|
||||
loadImageSuccessCallbackMethod.addInstruction(
|
||||
loadImageSuccessCallbackIndex++,
|
||||
"invoke-static { p1, p2 }, $targetMethodClass->handleCronetSuccess(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;)V",
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If a connection outright failed to complete any connection.
|
||||
*/
|
||||
fun addImageUrlErrorCallbackHook(targetMethodClass: String) {
|
||||
loadImageErrorCallbackMethod.addInstruction(
|
||||
loadImageErrorCallbackIndex++,
|
||||
"invoke-static { p1, p2, p3 }, $targetMethodClass->handleCronetFailure(" +
|
||||
"Lorg/chromium/net/UrlRequest;Lorg/chromium/net/UrlResponseInfo;Ljava/io/IOException;)V",
|
||||
)
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
fun MethodFingerprint.alsoResolve(fingerprint: MethodFingerprint) =
|
||||
also { resolve(context, fingerprint.resultOrThrow().classDef) }.resultOrThrow()
|
||||
|
||||
loadImageUrlMethod = MessageDigestImageUrlFingerprint
|
||||
.alsoResolve(MessageDigestImageUrlParentFingerprint).mutableMethod
|
||||
|
||||
loadImageSuccessCallbackMethod = OnSucceededFingerprint
|
||||
.alsoResolve(OnResponseStartedFingerprint).mutableMethod
|
||||
|
||||
loadImageErrorCallbackMethod = OnFailureFingerprint
|
||||
.alsoResolve(OnResponseStartedFingerprint).mutableMethod
|
||||
|
||||
// The URL is required for the failure callback hook, but the URL field is obfuscated.
|
||||
// Add a helper get method that returns the URL field.
|
||||
RequestFingerprint.resultOrThrow().apply {
|
||||
// The url is the only string field that is set inside the constructor.
|
||||
val urlFieldInstruction = mutableMethod.getInstructions().single {
|
||||
if (it.opcode != Opcode.IPUT_OBJECT) return@single false
|
||||
|
||||
val reference = (it as ReferenceInstruction).reference as FieldReference
|
||||
reference.type == "Ljava/lang/String;"
|
||||
} as ReferenceInstruction
|
||||
|
||||
val urlFieldName = (urlFieldInstruction.reference as FieldReference).name
|
||||
val definingClass = RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
val addedMethodName = "getHookedUrl"
|
||||
mutableClass.methods.add(
|
||||
ImmutableMethod(
|
||||
definingClass,
|
||||
addedMethodName,
|
||||
emptyList(),
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PUBLIC.value,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(2),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
iget-object v0, p0, $definingClass->$urlFieldName:Ljava/lang/String;
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
import app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.RequestFingerprint.IMPLEMENTATION_CLASS_NAME
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object RequestFingerprint : MethodFingerprint(
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.layout.thumbnails.fingerprints.cronet.request.callback
|
||||
package app.revanced.patches.youtube.misc.imageurlhook.fingerprints.cronet.request.callback
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
@@ -114,7 +114,7 @@ fun Method.indexOfFirstWideLiteralInstructionValue(literal: Long) = implementati
|
||||
*
|
||||
* @return the first literal instruction with the value, or throws [PatchException] if not found.
|
||||
*/
|
||||
fun Method.indexOfFirstWideLiteralInstructionValueOrThrow(literal: Long) : Int {
|
||||
fun Method.indexOfFirstWideLiteralInstructionValueOrThrow(literal: Long): Int {
|
||||
val index = indexOfFirstWideLiteralInstructionValue(literal)
|
||||
if (index < 0) throw PatchException("Could not find literal value: $literal")
|
||||
return index
|
||||
@@ -160,7 +160,7 @@ inline fun <reified T : Reference> Instruction.getReference() = (this as? Refere
|
||||
// TODO: delete this on next major release, the overloaded method with an optional start index serves the same purposes.
|
||||
// Method is deprecated, but annotation is commented out otherwise during compilation usage of the replacement is
|
||||
// incorrectly flagged as deprecated.
|
||||
//@Deprecated("Use the overloaded method with an optional start index.", ReplaceWith("indexOfFirstInstruction(predicate)"))
|
||||
// @Deprecated("Use the overloaded method with an optional start index.", ReplaceWith("indexOfFirstInstruction(predicate)"))
|
||||
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = indexOfFirstInstruction(0, predicate)
|
||||
|
||||
/**
|
||||
@@ -211,28 +211,41 @@ fun Method.findOpcodeIndicesReversed(opcode: Opcode): List<Int> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resolved methods of [MethodFingerprint]s early.
|
||||
* Return the resolved method early.
|
||||
*/
|
||||
fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) {
|
||||
fun MethodFingerprint.returnEarly(bool: Boolean = false) {
|
||||
val const = if (bool) "0x1" else "0x0"
|
||||
this.forEach { fingerprint ->
|
||||
fingerprint.result?.let { result ->
|
||||
val stringInstructions = when (result.method.returnType.first()) {
|
||||
'L' ->
|
||||
"""
|
||||
result?.let { result ->
|
||||
val stringInstructions = when (result.method.returnType.first()) {
|
||||
'L' ->
|
||||
"""
|
||||
const/4 v0, $const
|
||||
return-object v0
|
||||
"""
|
||||
'V' -> "return-void"
|
||||
'I', 'Z' ->
|
||||
"""
|
||||
'V' -> "return-void"
|
||||
'I', 'Z' ->
|
||||
"""
|
||||
const/4 v0, $const
|
||||
return v0
|
||||
"""
|
||||
else -> throw Exception("This case should never happen.")
|
||||
}
|
||||
else -> throw Exception("This case should never happen.")
|
||||
}
|
||||
|
||||
result.mutableMethod.addInstructions(0, stringInstructions)
|
||||
} ?: throw fingerprint.exception
|
||||
}
|
||||
result.mutableMethod.addInstructions(0, stringInstructions)
|
||||
} ?: throw exception
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resolved methods early.
|
||||
*/
|
||||
fun Iterable<MethodFingerprint>.returnEarly(bool: Boolean = false) = forEach { fingerprint ->
|
||||
fingerprint.returnEarly(bool)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resolved methods early.
|
||||
*/
|
||||
@Deprecated("Use the Iterable version")
|
||||
fun List<MethodFingerprint>.returnEarly(bool: Boolean = false) = forEach { fingerprint ->
|
||||
fingerprint.returnEarly(bool)
|
||||
}
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -246,7 +246,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">الكلمة المفتاحية غير صالحة. لا يمكن استخدام: \'%s\' كعامل تصفية</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">الكلمة المفتاحية غير صالحة. \'%1$s\' أقل من %2$d حرفًا</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">الكلمة الرئيسية \'$s\' سوف تخفي جميع الفيديوهات</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">الكلمة الرئيسية \'%s\' سوف تخفي جميع الفيديوهات</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">إخفاء الإعلانات العامة</string>
|
||||
@@ -990,6 +990,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">لون شريط التقدم</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">لون الشريط غير صالح. استخدام القيمة الافتراضية.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">تجاوز قيود منطقة الصورة</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">استخدام مضيف الصورة yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">استخدام مضيف الصور الأصلي\n\nتمكين هذا يمكن إصلاح الصور المفقودة التي يتم حظرها في بعض المناطق</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">علامة تبويب الصفحة الرئيسية</string>
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -246,7 +246,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Няправільнае ключавое слова. Немагчыма выкарыстоўваць: \"%s\" у якасці фільтра</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Няправільнае ключавое слова. \"%1$s\" змяшчае менш за %2$d сімвалаў</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Ключавое слова \"$s\" схавае ўсе відэа</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Ключавое слова \"%s\" схавае ўсе відэа</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Схаваць агульную рэкламу</string>
|
||||
@@ -990,6 +990,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Колер панэлі пошуку</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Няправільнае значэнне колеру панэлі пошуку. Выкарыстоўваецца значэнне па змаўчанні.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Галоўная ўкладка</string>
|
||||
@@ -1162,6 +1164,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_twitch_debug_mode_summary_off">Рэжым адладкі Twitch адключаны</string>
|
||||
</patch>
|
||||
<patch id="misc.settings.SettingsPatch">
|
||||
<string name="revanced_settings">Налады ReVanced</string>
|
||||
<string name="revanced_ads_screen_title">Аб\"явы</string>
|
||||
<string name="revanced_ads_screen_summary">Налады блакіроўкі рэкламы</string>
|
||||
<string name="revanced_chat_screen_title">Чат</string>
|
||||
|
||||
@@ -463,6 +463,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -850,10 +850,10 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_spoof_app_version_target_title">স্পুফ অ্যাপ সংস্করণ লক্ষ্য</string>
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
<string name="revanced_spoof_app_version_target_entry_1">18.33.40 - ছদ্মবেশি মোডে RYD পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">১৮.২০.৩৯ - প্রশ্বস্ত ভিডিও স্পিড এবং গুণমান মেনু পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_3">১৮.০৯.৩৯ - লাইব্রেরি ট্যাপ পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_4">১৭.৪১.৩৯ - পুরোনো প্লেলিস্ট শেলফ পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_5">১৭.৩৩.৪২ - পুরোনো UI লেআউট পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">18.20.39 - প্রশ্বস্ত ভিডিও স্পিড এবং গুণমান মেনু পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_3">18.09.39 - লাইব্রেরি ট্যাপ পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_4">17.41.37 - পুরোনো প্লেলিস্ট শেলফ পুনরুদ্ধার করে</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_5">17.33.42 - পুরোনো UI লেআউট পুনরুদ্ধার করে</string>
|
||||
</patch>
|
||||
<patch id="layout.startpage.ChangeStartPagePatch">
|
||||
<string name="revanced_start_page_title">শুরুর পৃষ্ঠা সেট করুন</string>
|
||||
@@ -919,6 +919,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">সিকবারের রং</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">সিকবারে ভুল রং দেয়া হয়েছে। মূল রং ব্যবহার করছে।</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">হোম ট্যাব</string>
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -206,6 +206,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -249,7 +249,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Neplatné klíčové slovo. Nelze použít: \'%s\' jako filtr</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Neplatné klíčové slovo. \'%1$s\' je menší než %2$d znaků</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Klíčové slovo \'$s\' skryje všechna videa</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Klíčové slovo \'%s\' skryje všechna videa</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Skrýt obecné reklamy</string>
|
||||
@@ -994,6 +994,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Barva vyhledávacího panelu</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Neplatná hodnota barvy vyhledávacího panelu. Použít výchozí hodnotu.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Obejít omezení oblasti obrázku</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Použití hostitele obrázků yt4.gggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Použití originálního hostitele obrázků\n\nPovolení tohoto nastavení může opravit chybějící obrázky, které jsou blokovány v některých regionech</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Záložka Domů</string>
|
||||
|
||||
@@ -248,7 +248,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Ugyldigt søgeord. Kan ikke bruge: \'%s\' som et filter</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Ugyldigt søgeord. \'%1$s\' er mindre end %2$d tegn</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Nøgleord \'$s\' vil skjule alle videoer</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Nøgleord \'%s\' vil skjule alle videoer</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Skjul generelle annoncer</string>
|
||||
@@ -579,11 +579,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Skjul Shorts i hjemmefeed</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Shorts i hjemmet feed er skjult</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Korte i hjemmet feed er vist</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Shorts i hjemmet feed er vist</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
<string name="revanced_hide_shorts_subscriptions_title">Skjul Shorts i abonnementsfeed</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Korte i abonnementsfeed er skjult</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Korte i abonnementsfeed vises</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_on">Shorts i abonnementsfeed er skjult</string>
|
||||
<string name="revanced_hide_shorts_subscriptions_summary_off">Shorts i abonnementsfeed vises</string>
|
||||
<string name="revanced_hide_shorts_search_title">Skjul Shorts i søgeresultater</string>
|
||||
<string name="revanced_hide_shorts_search_summary_on">Shorts i søgeresultater er skjult</string>
|
||||
<string name="revanced_hide_shorts_search_summary_off">Korte i søgeresultater vises</string>
|
||||
@@ -991,6 +991,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Farven på den søgende bar</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Ugyldig søgelinje farveværdi. Brug standardværdi.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Bypass billede region restriktioner</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Bruger billedvært yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Brug af original billedvært\n\nAktivering af dette kan rette manglende billeder, der er blokeret i nogle regioner</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Hjem fane</string>
|
||||
|
||||
@@ -249,7 +249,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Ungültiges Schlüsselwort. Kann nicht verwenden: \'%s\' als Filter</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Ungültiges Schlüsselwort. \'%1$s\' ist weniger als %2$d Zeichen</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Stichwort \'$s\' wird alle Videos ausblenden</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Schlüsselwort \'%s\' wird alle Videos ausblenden</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Allgemeine Werbung ausblenden</string>
|
||||
@@ -680,6 +680,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<patch id="layout.returnyoutubedislike.ReturnYouTubeDislikeResourcePatch">
|
||||
<string name="revanced_ryd_video_likes_hidden_by_video_owner">Nicht anzeigen</string>
|
||||
<!-- Toast shown if network connection times out. Translations of this should not be longer than the original English or the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_ryd_failure_connection_timeout">Dislikes vorläufig nicht verfügbar (API Timeout)</string>
|
||||
<string name="revanced_ryd_failure_connection_status_code">Dislikes nicht verfügbar (Status %d)</string>
|
||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Nicht verfügbar (Client-API-Limit erreicht)</string>
|
||||
<string name="revanced_ryd_failure_generic">Dislikes nicht verfügbar (%s)</string>
|
||||
@@ -991,6 +992,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Die Farbe der Suchleiste</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Ungültiger Suchleisten-Farbwert. Standardwert wird verwendet.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Bildgebietsbeschränkungen umgehen</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Bild-Host yt4.ggpht.com verwenden</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Verwendung des ursprünglichen Bild-Hosts\n\nAktivieren kann fehlende Bilder beheben, die in einigen Regionen blockiert werden</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Home-Tab</string>
|
||||
|
||||
@@ -247,7 +247,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Μη έγκυρη λέξη-κλειδί. Αδυναμία χρήσης: \'%s\' ως φίλτρο</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Μη έγκυρη λέξη-κλειδί. Το \'%1$s\' είναι μικρότερο από %2$d χαρακτήρες</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Η λέξη «$s» θα κρύψει όλα τα βίντεο</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Η λέξη «%s» θα κρύψει όλα τα βίντεο</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Γενικές διαφημίσεις</string>
|
||||
@@ -992,6 +992,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Το χρώμα της γραμμής προόδου</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Μη έγκυρη τιμή χρώματος. Επαναφορά...</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Παράκαμψη μπλοκαρίσματος φόρτωσης εικόνων</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Χρησιμοποιείται το domain yt4.ggpht.com για την φόρτωση εικόνων</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Χρησιμοποιείται το αρχικό domain για την φόρτωση εικόνων\n\nΗ ενεργοποίηση αυτής της ρύθμισης μπορεί να διορθώσει την φόρτωση εικόνων που είναι μπλοκαρισμένες σε κάποιες περιοχές</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Αρχική σελίδα</string>
|
||||
|
||||
@@ -33,7 +33,6 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<resources>
|
||||
<app id="shared">
|
||||
<patch id="misc.settings.BaseSettingsResourcePatch">
|
||||
<string name="revanced_settings_title">ReVanced</string>
|
||||
<string name="revanced_settings_confirm_user_dialog_title">¿Desea continuar?</string>
|
||||
<string name="revanced_settings_reset">Restablecer</string>
|
||||
<string name="revanced_settings_restart_title">Actualizar y reiniciar</string>
|
||||
@@ -248,7 +247,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Palabra clave inválida. No se puede usar: \'%s\' como filtro</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Palabra clave no válida. \'%1$s\' es menor de %2$d caracteres</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">La palabra clave \'$s\' oculta todos los vídeos</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">La palabra clave \'%s\' oculta todos los vídeos</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Ocultar anuncios generales</string>
|
||||
@@ -993,6 +992,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">El color de la barra de ajustes</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Valor de color de la barra de búsqueda inválido. Usando el valor por defecto.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Restricciones de región de imagen bypass</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Usando host de imagen yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Utilizando el host de imágenes original\n\nHabilitar esto puede arreglar las imágenes faltantes que están bloqueadas en algunas regiones</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Pestaña</string>
|
||||
|
||||
@@ -209,6 +209,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -207,6 +207,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -243,7 +243,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Di-wastong keyword. Hindi magagamit ang: \"%s\" bilang filter</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Di-wastong keyword. Ang \"%1$s\" ay mas mababa sa %2$d character</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Itatago ng keyword na \"$s\" ang lahat ng video</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Itatago ng keyword na \"%s\" ang lahat ng video</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Itago ang mga pangkalahatang ad</string>
|
||||
@@ -974,6 +974,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Ang kulay ng seekbar</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Di-wastong halaga ng kulay ng seekbar. Gamit ang default na halaga.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Tab ng tahanan</string>
|
||||
|
||||
@@ -248,7 +248,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Mot-clé invalide. Impossible d\'utiliser : \'%s\' comme filtre</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Mot-clé invalide. \'%1$s\' contient moins de %2$d caractères</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Le mot-clé \'$s\' masquera toutes les vidéos</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Le mot-clé «%s» masquera toutes les vidéos</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Masquer les pubs générales</string>
|
||||
@@ -992,6 +992,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">La couleur de la barre de recherche</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Valeur de couleur de la barre de recherche invalide.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Ignorer les restrictions de région de l\'image</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Utiliser l\'hôte d\'image yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Utiliser l\'hôte d\'image original\n\nActiver ceci peut corriger les images manquantes qui sont bloquées dans certaines régions</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Onglet d\'accueil</string>
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -206,6 +206,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -210,6 +210,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -93,6 +93,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_debug_toast_on_error_user_dialog_message">A hibaüzenetek kikapcsolása elrejti az összes ReVanced hibaértesítést.\n\nNem kap értesítést semmilyen váratlan eseményről.</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.general.HideLayoutComponentsPatch">
|
||||
<string name="revanced_disable_like_subscribe_glow_title">Like / feliratkozás gomb ragyogásának kikapcsolása</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_on">Like / feliratkozás gomb nem fog ragyogni mikor megemlítik</string>
|
||||
<string name="revanced_disable_like_subscribe_glow_summary_off">Like / feliratkozás gomb ragyogni fog mikor megemlítik</string>
|
||||
<string name="revanced_hide_gray_separator_title">Szürke elválasztó elrejtése</string>
|
||||
<string name="revanced_hide_gray_separator_summary_on">A szürke elválasztók el vannak rejtve</string>
|
||||
<string name="revanced_hide_gray_separator_summary_off">A szürke elválasztók láthatóak</string>
|
||||
@@ -244,7 +247,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Érvénytelen kulcsszó.\'%s\'nem használható szűrőként</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Helytelen kulcsszó. \'%1$s\' kevesebb, mint %2$d karakter</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">\'$s\' kulcsszó elrejti az összes videót</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">\'%s\' kulcsszó elrejti az összes videót</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Általános hirdetések elrejtése</string>
|
||||
@@ -989,6 +992,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">A keresősáv színe</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Érvénytelen színérték. Az alap érték használata.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Kezdőlap</string>
|
||||
@@ -1112,6 +1117,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_spoof_client_user_dialog_message">A beállítás kikapcsolása videolejátszási problémákat okozhat.</string>
|
||||
<string name="revanced_spoof_client_use_ios_title">Hamis kliens iOS-re</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_on">A kliens jelenleg iOS-re van hamisítva\n\nA mellékhatások a következők:\n• Nincs HDR-videó\n• Előfordulhat, hogy a megtekintési előzmények nem működnek\n• Hiányozhatnak a jobb videóminőségek\n• Az élő közvetítések nem játszhatók le csak hangként\n• Élő a streamek nem érhetők el Android 8.0 rendszeren</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_off">A kliens jelenleg az Android VR-t utánozza\n\nMellékhatásokkal együtt:\n• Nincs HDR video\n• Nincs \'Kids\' videólejátszás\n• A pillanatmegállított videók véletlenszerűen elindulhatnak\n• Alacsony minőségű Shorts csűszka bélyegképek\n• A letöltés gomb mindig rejtett\n• Videó végi kártyák mindig rejtett</string>
|
||||
<string name="revanced_spoof_client_storyboard_timeout">Hamis kliens miniatűrök nem érhetők el (API időtúllépés)</string>
|
||||
<string name="revanced_spoof_client_storyboard_io_exception">A hamis kliens miniatűrök átmenetileg nem érhetők el: %s</string>
|
||||
</patch>
|
||||
|
||||
@@ -202,6 +202,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -99,14 +99,14 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_gray_separator_summary_on">Pemisah abu-abu disembunyikan</string>
|
||||
<string name="revanced_hide_gray_separator_summary_off">Pemisah abu-abu ditampilkan</string>
|
||||
<string name="revanced_hide_channel_watermark_title">Sembunyikan watermark saluran</string>
|
||||
<string name="revanced_hide_channel_watermark_summary_on">Watermark disembunyikan</string>
|
||||
<string name="revanced_hide_channel_watermark_summary_on">Tanda air disembunyikan</string>
|
||||
<string name="revanced_hide_channel_watermark_summary_off">Watermark ditampilkan</string>
|
||||
<string name="revanced_hide_horizontal_shelves_title">Sembunyikan rak mendatar</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_on">Rak berikut disembunyikan:\n• Berita sela\n• Lanjut menonton\n• Jelajahi saluran lain\n• Belanja\n• Tonton lagi</string>
|
||||
<string name="revanced_hide_horizontal_shelves_summary_off">Rak ditampilkan</string>
|
||||
<!-- 'Join' should be translated using the same localized wording YouTube displays.
|
||||
This appears in the video player for certain videos. -->
|
||||
<string name="revanced_hide_join_membership_button_title">Sembunyikan tombol \'Gabung\'</string>
|
||||
<string name="revanced_hide_join_membership_button_title">Sembunyikan \'Gabung\'</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_on">Tombol disembunyikan</string>
|
||||
<string name="revanced_hide_join_membership_button_summary_off">Tombol ditampilkan</string>
|
||||
<!-- 'For you' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -115,7 +115,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_for_you_shelf_summary_off">Rak ditampilkan</string>
|
||||
<!-- 'Notify me' should be translated using the same localized wording YouTube displays.
|
||||
This item appear in the subscription feed for future livestreams or unreleased videos. -->
|
||||
<string name="revanced_hide_notify_me_button_title">Sembunyikan tombol \'Beri tahu saya\'</string>
|
||||
<string name="revanced_hide_notify_me_button_title">Sembunyikan \'Beri tahu saya\'</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_on">Tombol disembunyikan</string>
|
||||
<string name="revanced_hide_notify_me_button_summary_off">Tombol ditampilkan</string>
|
||||
<!-- 'People also watch' should be translated using the same localized wording YouTube displays. -->
|
||||
@@ -124,41 +124,41 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_search_result_recommendations_summary_off">Anjuran ditampilkan</string>
|
||||
<!-- 'Show more' should be translated with the same localized wording that YouTube displays.
|
||||
This button usually appears when searching for a YT creator. -->
|
||||
<string name="revanced_hide_show_more_button_title">Sembunyikan tombol \'Tampilkan Lebih\'</string>
|
||||
<string name="revanced_hide_show_more_button_title">Sembunyikan \'Tampilkan Lebih\'</string>
|
||||
<string name="revanced_hide_show_more_button_summary_on">Tombol disembunyikan</string>
|
||||
<string name="revanced_hide_show_more_button_summary_off">Tombol ditampilkan</string>
|
||||
<string name="revanced_hide_timed_reactions_title">Sembunyikan waktu reaksi</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_on">Waktu reaksi disembunyikan</string>
|
||||
<string name="revanced_hide_timed_reactions_summary_off">Tampilkan Waktu Reaksi</string>
|
||||
<string name="revanced_hide_search_result_shelf_header_title">Sembunyikan header rak hasil pencarian</string>
|
||||
<string name="revanced_hide_search_result_shelf_header_title">Sembunyikan header rak pencarian</string>
|
||||
<string name="revanced_hide_search_result_shelf_header_summary_on">Sembunyikan Shelf Header</string>
|
||||
<string name="revanced_hide_search_result_shelf_header_summary_off">Tampilkan Shelf Header</string>
|
||||
<string name="revanced_hide_channel_guidelines_title">Sembunyikan Panduan Saluran</string>
|
||||
<string name="revanced_hide_channel_guidelines_summary_on">Panduan saluran disembunyikan</string>
|
||||
<string name="revanced_hide_channel_guidelines_summary_off">Panduan saluran ditampilkan</string>
|
||||
<string name="revanced_hide_expandable_chip_title"></string>
|
||||
<string name="revanced_hide_expandable_chip_summary_on">Chip yang dapat diperluas disembunyikan</string>
|
||||
<string name="revanced_hide_expandable_chip_title">Sembunyikan opsi deret di bawah video</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_on">Opsi deret disembunyikan</string>
|
||||
<string name="revanced_hide_expandable_chip_summary_off">Chip yang dapat diperluas ditampilkan</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_title">Sembunyikan footer menu kualitas video</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_summary_on">Footer menu kualitas video disembunyikan</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_summary_off">Footer menu kualitas video ditampilkan</string>
|
||||
<string name="revanced_hide_community_posts_title">Sembunyikan postingan komunitas</string>
|
||||
<string name="revanced_hide_community_posts_summary_on">Postingan komunitas disembunyikan</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_title">Sembunyikan footer menu mutu video</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_summary_on">Footer menu mutu video disembunyikan</string>
|
||||
<string name="revanced_hide_video_quality_menu_footer_summary_off">Footer menu mutu video ditampilkan</string>
|
||||
<string name="revanced_hide_community_posts_title">Sembunyikan post. komunitas</string>
|
||||
<string name="revanced_hide_community_posts_summary_on">Post. komunitas disembunyikan</string>
|
||||
<string name="revanced_hide_community_posts_summary_off">Postingan komunitas ditampilkan</string>
|
||||
<string name="revanced_hide_compact_banner_title">Sembunyikan banner padat</string>
|
||||
<string name="revanced_hide_compact_banner_summary_on">Banner padat disembunyikan</string>
|
||||
<string name="revanced_hide_compact_banner_title">Sembunyikan spanduk ringkas</string>
|
||||
<string name="revanced_hide_compact_banner_summary_on">Spanduk ringkas disembunyikan</string>
|
||||
<string name="revanced_hide_compact_banner_summary_off">Banner padat ditampilkan</string>
|
||||
<string name="revanced_hide_movies_section_title">Sembunyikan bagian film</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Bagian film sudah disembunyikan</string>
|
||||
<string name="revanced_hide_movies_section_summary_on">Bagian film disembunyikan</string>
|
||||
<string name="revanced_hide_movies_section_summary_off">Bagian film ditampilkan</string>
|
||||
<string name="revanced_hide_feed_survey_title">Sembunyikan survei umpan balik</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Survei umpan balik disembunyikan</string>
|
||||
<string name="revanced_hide_feed_survey_title">Sembunyikan survei</string>
|
||||
<string name="revanced_hide_feed_survey_summary_on">Survei disembunyikan</string>
|
||||
<string name="revanced_hide_feed_survey_summary_off">Survei umpan balik ditampilkan</string>
|
||||
<string name="revanced_hide_community_guidelines_title">Sembunyikan pedoman komunitas</string>
|
||||
<string name="revanced_hide_community_guidelines_summary_on">Pedoman komunitas disembunyikan</string>
|
||||
<string name="revanced_hide_community_guidelines_summary_off">Pedoman komunitas ditampilkan</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_title">Sembunyikan pedoman komunitas untuk para pelanggan</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_summary_on">Pedoman komunitas untuk para pelanggan disembunyikan</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_title">Sembunyikan pedoman komunitas pelanggan</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_summary_on">Pedoman komunitas pelanggan disembunyikan</string>
|
||||
<string name="revanced_hide_subscribers_community_guidelines_summary_off">Pedoman komunitas untuk para pelanggan ditampilkan</string>
|
||||
<string name="revanced_hide_channel_member_shelf_title">Sembunyikan rak anggota saluran</string>
|
||||
<string name="revanced_hide_channel_member_shelf_summary_on">Rak anggota saluran disembunyikan</string>
|
||||
@@ -166,8 +166,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_emergency_box_title">Sembunyikan kotak darurat</string>
|
||||
<string name="revanced_hide_emergency_box_summary_on">Kotak darurat disembunyikan</string>
|
||||
<string name="revanced_hide_emergency_box_summary_off">Kotak darurat ditampilkan</string>
|
||||
<string name="revanced_hide_info_panels_title">Sembunyikan panel informasi</string>
|
||||
<string name="revanced_hide_info_panels_summary_on">Panel informasi disembunyikan</string>
|
||||
<string name="revanced_hide_info_panels_title">Sembunyikan panel info</string>
|
||||
<string name="revanced_hide_info_panels_summary_on">Panel info disembunyikan</string>
|
||||
<string name="revanced_hide_info_panels_summary_off">Panel informasi ditampilkan</string>
|
||||
<string name="revanced_hide_medical_panels_title">Sembunyikan panel medis</string>
|
||||
<string name="revanced_hide_medical_panels_summary_on">Panel medis disembunyikan</string>
|
||||
@@ -175,8 +175,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_channel_bar_title">Sembunyikan bilah saluran</string>
|
||||
<string name="revanced_hide_channel_bar_summary_on">Bilah saluran disembunyikan</string>
|
||||
<string name="revanced_hide_channel_bar_summary_off">Bilah saluran ditampilkan</string>
|
||||
<string name="revanced_hide_playables_title">Sembunyikan konten yang dapat diputar</string>
|
||||
<string name="revanced_hide_playables_summary_on">Konten yang dapat diputar disembunyikan</string>
|
||||
<string name="revanced_hide_playables_title">Sembunyikan konten tonton</string>
|
||||
<string name="revanced_hide_playables_summary_on">Konten tonton disembunyikan</string>
|
||||
<string name="revanced_hide_playables_summary_off">Yang dapat diputar ditunjukkan</string>
|
||||
<string name="revanced_hide_quick_actions_title">Sembunyikan tindakan cepat di layar penuh</string>
|
||||
<string name="revanced_hide_quick_actions_summary_on">Tindakan cepat disembunyikan</string>
|
||||
@@ -184,11 +184,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_related_videos_title">Sembunyikan video terkait dalam tindakan cepat</string>
|
||||
<string name="revanced_hide_related_videos_summary_on">Video terkait disembunyikan</string>
|
||||
<string name="revanced_hide_related_videos_summary_off">Video terkait ditampilkan</string>
|
||||
<string name="revanced_hide_image_shelf_title">Sembunyikan rak gambar dalam hasil pencarian</string>
|
||||
<string name="revanced_hide_image_shelf_title">Sembunyikan rak gambar di pencarian</string>
|
||||
<string name="revanced_hide_image_shelf_summary_on">Rak gambar disembunyikan</string>
|
||||
<string name="revanced_hide_image_shelf_summary_off">Rak gambar ditampilkan</string>
|
||||
<string name="revanced_hide_latest_posts_ads_title">Sembunyikan kiriman terbaru</string>
|
||||
<string name="revanced_hide_latest_posts_ads_summary_on">Kiriman terbaru disembunyikan</string>
|
||||
<string name="revanced_hide_latest_posts_ads_title">Sembunyikan post. terbaru</string>
|
||||
<string name="revanced_hide_latest_posts_ads_summary_on">Post. terbaru disembunyikan</string>
|
||||
<string name="revanced_hide_latest_posts_ads_summary_off">Kiriman terbaru ditampilkan</string>
|
||||
<string name="revanced_hide_mix_playlists_title">Sembunyikan daftar putar campuran</string>
|
||||
<string name="revanced_hide_mix_playlists_summary_on">Daftar putar campuran disembunyikan</string>
|
||||
@@ -197,19 +197,19 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_artist_cards_summary_on">Kartu artis disembunyikan</string>
|
||||
<string name="revanced_hide_artist_cards_summary_off">Kartu artis ditampilkan</string>
|
||||
<string name="revanced_hide_chips_shelf_title">Sembunyikan rak chip</string>
|
||||
<string name="revanced_hide_chips_shelf_summary_on">Rak chip disembunyikan</string>
|
||||
<string name="revanced_hide_chips_shelf_summary_on">Rak opsi deret disembunyikan</string>
|
||||
<string name="revanced_hide_chips_shelf_summary_off">Rak chip ditampilkan</string>
|
||||
<string name="revanced_hide_attributes_section_title">Sembunyikan bagian atribut</string>
|
||||
<string name="revanced_hide_attributes_section_summary_on">\'Tempat unggulan\', bagian Permainan dan Musik disembunyikan</string>
|
||||
<string name="revanced_hide_attributes_section_summary_off">\'Tempat unggulan\', bagian Permainan dan Musik ditampilkan</string>
|
||||
<string name="revanced_hide_attributes_section_summary_on">\'Tempat menonjol\', \'Permainan\', dan \'Musik\' disembunyikan</string>
|
||||
<string name="revanced_hide_attributes_section_summary_off">\'Tempat menonjol\', \'Permainan\', dan \'Musik\' ditampilkan</string>
|
||||
<string name="revanced_hide_chapters_section_title">Sembunyikan bagian Bab</string>
|
||||
<string name="revanced_hide_chapters_section_summary_on">Bagian Bab sudah disembunyikan</string>
|
||||
<string name="revanced_hide_chapters_section_summary_off">Bagian Bab sudah ditampilkan</string>
|
||||
<string name="revanced_hide_podcast_section_title">Sembunyikan bagian \'Jelajahi podcast\'</string>
|
||||
<string name="revanced_hide_podcast_section_summary_on">Bagian \'Jelajahi podcast\' sudah disembunyikan</string>
|
||||
<string name="revanced_hide_podcast_section_summary_on">Bagian \'Jelajahi podcast\' disembunyikan</string>
|
||||
<string name="revanced_hide_podcast_section_summary_off">Bagian \'Jelajahi podcast\' ditampilkan</string>
|
||||
<string name="revanced_hide_info_cards_section_title">Sembunyikan bagian kartu info</string>
|
||||
<string name="revanced_hide_info_cards_section_summary_on">Bagian kartu info sudah disembunyikan</string>
|
||||
<string name="revanced_hide_info_cards_section_title">Sembunyikan kartu info</string>
|
||||
<string name="revanced_hide_info_cards_section_summary_on">Kartu info sudah disembunyikan</string>
|
||||
<string name="revanced_hide_info_cards_section_summary_off">Bagian kartu info sudah ditampilkan</string>
|
||||
<string name="revanced_hide_transcript_section_title">Sembunyikan bagian transkrip</string>
|
||||
<string name="revanced_hide_transcript_section_summary_on">Bagian transkrip sudah disembunyikan</string>
|
||||
@@ -223,7 +223,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_custom_filter_summary_off">Penyaring khusus dimatikan</string>
|
||||
<string name="revanced_custom_filter_strings_title">Penyaring khusus</string>
|
||||
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
|
||||
<string name="revanced_custom_filter_strings_summary">Serangkaian daftar pembangun jalur komponen yang disaring dipisahkan dengan baris baru</string>
|
||||
<string name="revanced_custom_filter_strings_summary">Daftar untaian karakter untuk disaring, dipisah dengan baris baru</string>
|
||||
<string name="revanced_custom_filter_toast_invalid_syntax">Penyaring khusus tidak valid: %s</string>
|
||||
<string name="revanced_hide_keyword_content_screen_title">Sembunyikan kata kunci konten</string>
|
||||
<string name="revanced_hide_keyword_content_screen_summary">Sembunyikan pencarian dan umpan video menggunakan penyaring kata kunci</string>
|
||||
@@ -246,7 +246,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Kata kunci tidak sah: \'%s\'</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Kata kunci tidak sah. \'%1$s\' kurang dari %2$d karakter</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Kata kunci \'$s\' akan menyembunyikan semua video</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Kata kunci \'%s\' akan menyembunyikan semua video</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Sembunyikan iklan umum</string>
|
||||
@@ -271,7 +271,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_shopping_links_summary_on">Tautan belanja disembunyikan</string>
|
||||
<string name="revanced_hide_shopping_links_summary_off">Tautan belanja ditampilkan</string>
|
||||
<!-- 'Visit store' should be translated with the same localized wording that YouTube displays. -->
|
||||
<string name="revanced_hide_visit_store_button_title">Sembunyikan tombol \'Lihat toko\' di laman saluran</string>
|
||||
<string name="revanced_hide_visit_store_button_title">Sembunyikan \'Lihat toko\' di laman saluran</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_on">Tombol disembunyikan</string>
|
||||
<string name="revanced_hide_visit_store_button_summary_off">Tombol ditampilkan</string>
|
||||
<string name="revanced_hide_web_search_results_title">Sembunyikan hasil pencarian web</string>
|
||||
@@ -307,7 +307,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_remove_viewer_discretion_dialog_title">Hapus dialog peringatan untuk penonton</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_on">Dialog akan dihapus</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_summary_off">Dialog akan ditampilkan</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Ini tidak mengabaikan batasan usia. Hanya menerimanya secara otomatis.</string>
|
||||
<string name="revanced_remove_viewer_discretion_dialog_user_dialog_message">Ini tidak mengabaikan batasan usia. Hanya otomatis menerimanya.</string>
|
||||
</patch>
|
||||
<patch id="interaction.downloads.DownloadsResourcePatch">
|
||||
<string name="revanced_external_downloader_screen_title">Unduhan eksternal</string>
|
||||
@@ -454,9 +454,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_player_flyout_captions_summary_on">Menu caption disembunyikan</string>
|
||||
<string name="revanced_hide_player_flyout_captions_summary_off">Menu caption ditampilkan</string>
|
||||
<!-- 'Additional settings' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_additional_settings_title">Sembunyikan Setelan tambahan</string>
|
||||
<string name="revanced_hide_player_flyout_additional_settings_summary_on">Menu Setelan tambahan disembunyikan</string>
|
||||
<string name="revanced_hide_player_flyout_additional_settings_summary_off">Menu setelan tambahan ditampilkan</string>
|
||||
<string name="revanced_hide_player_flyout_additional_settings_title">Sembunyikan P\'aturan tambahan</string>
|
||||
<string name="revanced_hide_player_flyout_additional_settings_summary_on">Menu p\'aturan tambahan disembunyikan</string>
|
||||
<string name="revanced_hide_player_flyout_additional_settings_summary_off">Menu p\'aturan tambahan ditampilkan</string>
|
||||
<!-- 'Loop video' should be translated using the same localized wording YouTube displays for the menu item. -->
|
||||
<string name="revanced_hide_player_flyout_loop_video_title">Sembunyikan Ulangi video</string>
|
||||
<string name="revanced_hide_player_flyout_loop_video_summary_on">Menu ulangi video disembunyikan</string>
|
||||
@@ -516,7 +516,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_comments_preview_comment_title">Sembunyikan komentar pratinjau</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_on">Komentar pratinjau disembunyikan</string>
|
||||
<string name="revanced_hide_comments_preview_comment_summary_off">Komentar pratinjau ditampilkan</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">Sembunyikan tombol terima kasih</string>
|
||||
<string name="revanced_hide_comments_thanks_button_title">Sembunyikan \'terima kasih\'</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_on">Tmbl terima kasih disembunyikan</string>
|
||||
<string name="revanced_hide_comments_thanks_button_summary_off">Tmbl terima kasih ditampilkan</string>
|
||||
<string name="revanced_hide_comments_timestamp_and_emoji_buttons_title">Sembunyikan timestamp dan tombol emoji</string>
|
||||
@@ -754,10 +754,21 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">Tombol buat segmen baru ditampilkan</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_off">Tombol buat segmen baru tidak ditampilkan</string>
|
||||
<string name="revanced_sb_general_adjusting">Sesuaikan langkah segmen baru</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">Jumlah milidetik tombol penyesuaian waktu bergerak saat membuat segmen baru</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">Nilainya harus berupa angka positif</string>
|
||||
<string name="revanced_sb_guidelines_preference_title">Lihat pedoman</string>
|
||||
<string name="revanced_sb_guidelines_preference_sum">Pedoman berisi aturan dan tips untuk membuat segmen baru</string>
|
||||
<string name="revanced_sb_guidelines_popup_title">Ikuti pedoman</string>
|
||||
<string name="revanced_sb_guidelines_popup_content">Bacalah panduan SponsorBlock sebelum membuat segmen baru</string>
|
||||
<string name="revanced_sb_guidelines_popup_already_read">Sudah dibaca</string>
|
||||
<string name="revanced_sb_guidelines_popup_open">Tunjukkan</string>
|
||||
<string name="revanced_sb_general">Umum</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_title">Tampilkan pesan toast jika API tidak tersedia</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_on">Toast ditampilkan jika SponsorBlock tidak tersedia</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_off">Toast tidak ditampilkan jika SponsorBlock tidak tersedia</string>
|
||||
<string name="revanced_sb_general_skipcount">Nyalakan pelacakan melewati hitungan</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_on">Mengizinkan leaderboard SponsorBlock mengetahui berapa banyak waktu yang diselamatkan. Sebuah pesan dikirim ke leaderboard setiap kali sebuah segmen dilewati</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_off">Pelacakan melewati hitungan tidak dinyalakan</string>
|
||||
<string name="revanced_sb_general_min_duration">Durasi minimum segmen</string>
|
||||
<string name="revanced_sb_general_uuid_sum">Ini harus dijaga kerahasiaannya. Seperti kata sandi dan tidak disarankan untuk dibagikan dengan siapa pun. Jika seseorang mendapatkan ini, mereka dapat menyamar sebagai Anda</string>
|
||||
<string name="revanced_sb_general_api_url">Ubah URL API</string>
|
||||
@@ -830,7 +841,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_sb_about">Tentang</string>
|
||||
</patch>
|
||||
<patch id="layout.spoofappversion.SpoofAppVersionPatch">
|
||||
<string name="revanced_spoof_app_version_user_dialog_message">Versi aplikasi akan dipalsukan ke versi YouTube yang lebih lama.\n\nIni akan mengubah tampilan dan fitur aplikasi, namun efek samping yang tidak diketahui mungkin terjadi.\n\nJika nanti dinonaktifkan, disarankan untuk menghapus data aplikasi untuk mencegah kesalahan UI.</string>
|
||||
<string name="revanced_spoof_app_version_user_dialog_message">Versi aplikasi akan dipalsukan ke versi lama YouTube.\n\nIni akan mengubah tampilan dan fitur aplikasi, tapi mungkin terjadi efek samping tidak diketahui.\n\nJika nanti dinonaktifkan, disarankan menghapus data aplikasi agar UI tidak kacau.</string>
|
||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_spoof_app_version_title'.
|
||||
This is because the 'General layout' menu uses alphabetic sorting, and it functionally works better if the spoof target selector appears below the 'Spoof app version' UI switch -->
|
||||
<!-- 'RYD' is 'Return YouTube Dislike' -->
|
||||
@@ -861,6 +872,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Abaikan batasan daerah gambar</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Menggunakan sumber yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Menggunakan sumber gambar asli\n\nMengaktifkan ini akan memperbaiki gambar hilang di daerah tertentu</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
@@ -880,6 +896,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<patch id="misc.gms.GmsCoreSupportResourcePatch">
|
||||
</patch>
|
||||
<patch id="misc.links.BypassURLRedirectsPatch">
|
||||
<string name="revanced_bypass_url_redirects_title">Abaikan pengalihan URL</string>
|
||||
<string name="revanced_bypass_url_redirects_summary_on">Pengalihan URL diabaikan</string>
|
||||
<string name="revanced_bypass_url_redirects_summary_off">Pengalihan URL tidak diabaikan</string>
|
||||
</patch>
|
||||
<patch id="misc.links.OpenLinksExternallyPatch">
|
||||
</patch>
|
||||
@@ -888,6 +907,15 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<patch id="misc.zoomhaptics.ZoomHapticsPatch">
|
||||
</patch>
|
||||
<patch id="video.quality.RememberVideoQualityPatch">
|
||||
<string name="revanced_video_quality_default_entry_1">Mutu video otomatis</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_title">Ingat perubahan mutu video</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_on">Perubahan mutu diatur ke semua video</string>
|
||||
<string name="revanced_remember_video_quality_last_selected_summary_off">Perubahan mutu hanya diatur di video saat ini</string>
|
||||
<string name="revanced_video_quality_default_wifi_title">Mutu video ke bawaan di jejaring Wi-Fi</string>
|
||||
<string name="revanced_video_quality_default_mobile_title">Mutu video ke bawaan di jejaring seluler</string>
|
||||
<string name="revanced_remember_video_quality_mobile">seluler</string>
|
||||
<string name="revanced_remember_video_quality_wifi">wifi</string>
|
||||
<string name="revanced_remember_video_quality_toast">Mutu bawaan %1$s diubah ke: %2$s</string>
|
||||
</patch>
|
||||
<patch id="video.speed.button.PlaybackSpeedButtonPatch">
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">Tombol ditampilkan</string>
|
||||
@@ -898,6 +926,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<patch id="video.speed.remember.RememberPlaybackSpeedPatch">
|
||||
</patch>
|
||||
<patch id="video.videoqualitymenu.RestoreOldVideoQualityMenuResourcePatch">
|
||||
<string name="revanced_restore_old_video_quality_menu_title">Pulihkan menu lawas mutu video</string>
|
||||
<string name="revanced_restore_old_video_quality_menu_summary_on">Menu lawas mutu video ditampilkan</string>
|
||||
<string name="revanced_restore_old_video_quality_menu_summary_off">Menu lawas mutu video tidak ditampilkan</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.EnableSlideToSeekPatch">
|
||||
</patch>
|
||||
|
||||
@@ -207,6 +207,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -246,7 +246,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">Parola chiave non valida. Impossibile utilizzare: \'%s\' come filtro</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">Parola chiave non valida. \'%1$s\' è minore di %2$d caratteri</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">Parola chiave \'$s\' nasconderà tutti i video</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">La parola chiave \'%s\' nasconderà tutti i video</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">Nascondi gli annunci generali</string>
|
||||
@@ -576,7 +576,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.hide.shorts.HideShortsComponentsResourcePatch">
|
||||
<!-- 'home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_hide_shorts_home_title">Nascondi Pantaloncini nel feed home</string>
|
||||
<string name="revanced_hide_shorts_home_title">Nascondi Shorts nella scheda Home</string>
|
||||
<string name="revanced_hide_shorts_home_summary_on">Pantaloncini nel feed domestico sono nascosti</string>
|
||||
<string name="revanced_hide_shorts_home_summary_off">Vengono mostrati i pantaloncini in home feed</string>
|
||||
<!-- 'subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
@@ -990,6 +990,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">Il colore della barra di ricerca</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">Valore colore seekbar non valido. Usare il valore predefinito.</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">Bypass restrizioni regione immagine</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">Uso host immagine yt4.ggpht.com</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">Usando l\'host immagine originale\n\nAbilitando questo si possono correggere le immagini mancanti bloccate in alcune regioni</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">Scheda home</string>
|
||||
@@ -1113,7 +1118,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_spoof_client_user_dialog_message">Disattivare questa impostazione potrebbe causare problemi di riproduzione video.</string>
|
||||
<string name="revanced_spoof_client_use_ios_title">Spoof client per iOS</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_on">Il client è attualmente spoofed per iOS\n\nGli effetti collaterali includono:\n• Nessun video HDR\n• La cronologia dell\'orologio potrebbe non funzionare\n• Potrebbero mancare qualità video più elevate\n• I flussi dal vivo non possono riprodurre solo l\'audio\n• I flussi dal vivo non sono disponibili su Android 8.0</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_off">Il client è attualmente spoofed per Android VR\n\nGli effetti collaterali includono:\n• Nessun video HDR\n• I video per bambini non riproducono\n• I video in pausa possono riprendere casualmente\n• Bassa qualità Pantaloncini seekbar miniature\n• Il pulsante di azione del download è sempre nascosto\n• Le schede dello schermo finale sono sempre nascoste</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_off">Il client è attualmente spoofed per Android VR\n\nGli effetti collaterali includono:\n• Nessun video HDR\n• I video per bambini non riproducono\n• I video in pausa possono riprendere casualmente\n• Bassa qualità Shorts seekbar miniature\n• Il pulsante di azione del download è sempre nascosto\n• Le schede dello schermo finale sono sempre nascoste</string>
|
||||
<string name="revanced_spoof_client_storyboard_timeout">Le miniature del client non sono disponibili (timeout API)</string>
|
||||
<string name="revanced_spoof_client_storyboard_io_exception">Miniature del client Spoof temporaneamente non disponibili: %s</string>
|
||||
</patch>
|
||||
|
||||
@@ -260,6 +260,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -247,7 +247,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">無効なキーワードです。フィルタとして使用できません: \'%s\'</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">無効なキーワードです。\'%1$s\' は %2$d 文字未満です</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">キーワード \'$s\' はすべてのビデオを非表示にします</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">キーワード \'%s\' はすべての動画を非表示にします</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">一般的な広告を非表示</string>
|
||||
@@ -989,6 +989,10 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">シークバーの色</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">シークバーの色の値が無効です。デフォルト値を使用してください。</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">画像領域の制限をバイパスする</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">イメージホストの使用 yt4.ggpht.com</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">ホームタブ</string>
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -205,6 +205,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -203,6 +203,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -46,9 +46,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="misc.gms.BaseGmsCoreSupportResourcePatch">
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="gms_core_toast_not_installed_message">GmsCore가 설치되어 있지 않습니다. 설치하세요</string>
|
||||
<string name="gms_core_toast_not_installed_message">MicroG GmsCore가 설치되어 있지 않습니다. 설치하세요</string>
|
||||
<string name="gms_core_dialog_title">필수 조치</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">MicroG GmsCore에 백그라운드에서 실행할 수 있는 권한이 없습니다\n\n휴대폰에 대한 \"Don\'t kill my app\" 가이드를 읽어보고, MicroG 설치 지침을 적용하세요\n\n앱이 실행하려면 이 과정이 필요합니다</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_not_allowed_in_background_message">MicroG GmsCore에 백그라운드에서 실행할 수 있는 권한이 없습니다\n\n이 기기에 대한 \"Don\'t kill my app\" 가이드를 읽어보고, MicroG 설치 지침을 적용하세요\n\n앱이 실행하려면 이 과정이 필요합니다</string>
|
||||
<string name="gms_core_dialog_open_website_text">웹사이트 열기</string>
|
||||
<string name="gms_core_dialog_not_whitelisted_using_battery_optimizations_message">MicroG GmsCore를 배터리 최적화 목록에서 제외하여 앱 문제를 방지할 수 있습니다\n\n배터리 최적화 목록에서 제외하려면 \'계속하기\' 버튼을 누르세요</string>
|
||||
<string name="gms_core_dialog_continue_text">계속하기</string>
|
||||
@@ -244,12 +244,12 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
This is because keywords can be in any language, and showing an example in the localized script helps convey this. -->
|
||||
<string name="revanced_hide_keyword_content_phrases_summary">필터링할 키워드 및 구문을 줄바꿈으로 구분하여 설정합니다\n\n영어 키워드는 대소문자를 구분하여 입력해야 합니다 (예: iPhone, TikTok, LeBlanc)</string>
|
||||
<string name="revanced_hide_keyword_content_about_title">키워드 필터링 정보</string>
|
||||
<string name="revanced_hide_keyword_content_about_summary">홈 피드 / 구독 피드 / 검색 결과에서 키워드와 일치하는 콘텐츠가 숨겨집니다\n\n알려진 문제점:\n• 일부 Shorts는 숨겨지지 않을 수 있습니다\n• 일부 화면 구성요소가 숨겨지지 않을 수 있습니다\n• 키워드를 검색하면 결과가 표시되지 않을 수 있습니다</string>
|
||||
<string name="revanced_hide_keyword_content_about_summary">홈 피드 / 구독 피드 / 검색 결과에서 키워드와 일치하는 콘텐츠가 숨겨집니다\n\n알려진 문제점:\n• 일부 Shorts는 숨겨지지 않을 수 있습니다\n• 일부 화면 구성요소가 숨겨지지 않을 수 있습니다\n• 필터링 키워드를 검색하면 결과가 표시되지 않을 수 있습니다</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_common">잘못된 키워드입니다. \'%s\'를 필터로 사용할 수 없습니다</string>
|
||||
<!-- Translations of this should not be longer than the original English text, otherwise the text can be clipped and not entirely shown. -->
|
||||
<string name="revanced_hide_keyword_toast_invalid_length">\'%1$s\'는 잘못된 키워드입니다. 필터링 키워드는 %2$d 글자 이상이어야 합니다.</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">키워드 \'$s\'를 사용하면 모든 동영상이 숨겨집니다</string>
|
||||
<string name="revanced_hide_keyword_toast_invalid_broad">키워드 \'%s\'를 사용하면 모든 동영상이 숨겨집니다</string>
|
||||
</patch>
|
||||
<patch id="ad.general.HideAdsResourcePatch">
|
||||
<string name="revanced_hide_general_ads_title">일반 레이아웃 광고 숨기기</string>
|
||||
@@ -258,9 +258,9 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_fullscreen_ads_title">전체 화면 광고 숨기기</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_on">전체 화면 광고가 숨겨집니다\n\n알림: 이 설정은 구형 기기에서만 사용할 수 있습니다</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_off">전체 화면 광고가 노출됩니다</string>
|
||||
<string name="revanced_hide_buttoned_ads_title">일반 레이아웃 광고 숨기기</string>
|
||||
<string name="revanced_hide_buttoned_ads_summary_on">일반 레이아웃 광고가 숨겨집니다</string>
|
||||
<string name="revanced_hide_buttoned_ads_summary_off">일반 레이아웃 광고가 노출됩니다</string>
|
||||
<string name="revanced_hide_buttoned_ads_title">버튼형 광고 숨기기</string>
|
||||
<string name="revanced_hide_buttoned_ads_summary_on">버튼형 광고가 숨겨집니다</string>
|
||||
<string name="revanced_hide_buttoned_ads_summary_off">버튼형 광고가 노출됩니다</string>
|
||||
<string name="revanced_hide_paid_promotion_label_title">유료 광고 포함 라벨 숨기기</string>
|
||||
<string name="revanced_hide_paid_promotion_label_summary_on">유료 광고 포함 라벨이 숨겨집니다</string>
|
||||
<string name="revanced_hide_paid_promotion_label_summary_off">유료 광고 포함 라벨이 노출됩니다</string>
|
||||
@@ -300,12 +300,10 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_share_copy_url_success">URL을 클립보드에 복사하였습니다</string>
|
||||
<string name="revanced_share_copy_url_timestamp_success">타임스탬프를 표기한 URL을 클립보드에 복사하였습니다</string>
|
||||
<string name="revanced_copy_video_url_title">동영상 URL 복사 버튼 표시하기</string>
|
||||
<string name="revanced_copy_video_url_summary_on">버튼을 표시합니다.
|
||||
버튼을 눌러서 동영상 URL을 복사할 수 있습니다. 길게 누르면 타임스탬프를 표기한 동영상 URL이 복사됩니다</string>
|
||||
<string name="revanced_copy_video_url_summary_on">버튼을 표시합니다. \n버튼을 눌러서 동영상 URL을 복사할 수 있습니다. 길게 누르면 타임스탬프를 표기한 동영상 URL이 복사됩니다</string>
|
||||
<string name="revanced_copy_video_url_summary_off">버튼을 표시하지 않습니다</string>
|
||||
<string name="revanced_copy_video_url_timestamp_title">타임스탬프를 표기한 URL 복사 버튼 표시하기</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_on">버튼을 표시합니다.
|
||||
버튼을 눌러서 타임스탬프를 표기한 동영상 URL을 복사할 수 있습니다. 길게 누르면 타임스탬프를 표기하지 않은 동영상 URL이 복사됩니다</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_on">버튼을 표시합니다. \n버튼을 눌러서 타임스탬프를 표기한 동영상 URL을 복사할 수 있습니다. 길게 누르면 타임스탬프를 표기하지 않은 동영상 URL이 복사됩니다</string>
|
||||
<string name="revanced_copy_video_url_timestamp_summary_off">버튼을 표시하지 않습니다</string>
|
||||
</patch>
|
||||
<patch id="interaction.dialog.RemoveViewerDiscretionDialogPatch">
|
||||
@@ -326,12 +324,12 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_external_downloader_action_button_summary_off">오프라인 저장 버튼으로 기본 다운로더를 실행할 수 있습니다 (YouTube Premium 기능)</string>
|
||||
<string name="revanced_external_downloader_name_title">외부 다운로더 패키지명</string>
|
||||
<string name="revanced_external_downloader_name_summary">NewPipe 또는 Seal와 같은 설치된 외부 다운로더 패키지명입니다</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s은(는) 설치되어 있지 않습니다. 설치하세요</string>
|
||||
<string name="revanced_external_downloader_not_installed_warning">%s 는 설치되어 있지 않습니다. 설치하세요</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.DisablePreciseSeekingGesturePatch">
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">세밀하게 탐색 제스처 비활성화하기</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_on">세밀하게 탐색 제스처를 비활성화합니다\n• 필름 스트립 오버레이</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_off">세밀하게 탐색 제스처를 활성화합니다\n• 필름 스트립 오버레이</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_title">세밀하게 보면서 탐색 제스처 비활성화하기</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_on">세밀하게 보면서 탐색 제스처를 비활성화합니다\n• 필름 스트립 오버레이</string>
|
||||
<string name="revanced_disable_precise_seeking_gesture_summary_off">세밀하게 보면서 탐색 제스처를 활성화합니다\n• 필름 스트립 오버레이</string>
|
||||
</patch>
|
||||
<patch id="interaction.seekbar.EnableSeekbarTappingPatch">
|
||||
<string name="revanced_seekbar_tapping_title">재생바 터치 조작 활성화하기</string>
|
||||
@@ -352,8 +350,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_swipe_haptic_feedback_summary_on">진동 피드백을 활성화합니다</string>
|
||||
<string name="revanced_swipe_haptic_feedback_summary_off">진동 피드백을 비활성화합니다</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_title">화면 밝기 저장 및 복원 활성화하기</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_summary_on">전체 화면에서 나가거나 들어갈 때마다 밝기 값을 저장 및 복원합니다</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_summary_off">전체 화면에서 나가거나 들어갈 때마다 밝기 값을 저장 및 복원하지 않습니다</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_summary_on">전체 화면에서 나가거나 들어갈 때마다 화면 밝기 값을 저장 및 복원합니다</string>
|
||||
<string name="revanced_swipe_save_and_restore_brightness_summary_off">전체 화면에서 나가거나 들어갈 때마다 화면 밝기 값을 저장 및 복원하지 않습니다</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_title">스와이프 제스처로 자동 밝기 활성화하기</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_on">스와이프 제스처로 밝기가 0이 되면 자동 밝기를 활성화합니다</string>
|
||||
<string name="revanced_swipe_lowest_value_enable_auto_brightness_summary_off">스와이프 제스처로 밝기가 0이 되더라도 자동 밝기를 활성화하지 않습니다</string>
|
||||
@@ -568,8 +566,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.hide.rollingnumber.DisableRollingNumberAnimationPatch">
|
||||
<string name="revanced_disable_rolling_number_animations_title">롤링 넘버 애니메이션 비활성화하기</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_on">다음 롤링 넘버 애니메이션을 비활성화합니다\n• 실시간 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 개수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">다음 롤링 넘버 애니메이션을 활성화합니다\n• 실시간 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 개수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_on">다음 롤링 넘버 애니메이션을 비활성화합니다\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 개수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||
<string name="revanced_disable_rolling_number_animations_summary_off">다음 롤링 넘버 애니메이션을 활성화합니다\n• 조회수, 시청자 수 롤링 애니메이션 (플레이어 하단)\n• 좋아요 개수, 조회수 롤링 애니메이션 (동영상 설명)</string>
|
||||
</patch>
|
||||
<patch id="layout.hide.seekbar.HideSeekbarPatch">
|
||||
<string name="revanced_hide_seekbar_title">동영상 플레이어 재생바 숨기기</string>
|
||||
@@ -649,7 +647,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_hide_shorts_sound_metadata_label_title">사운드 메타데이터 라벨 숨기기</string>
|
||||
<string name="revanced_hide_shorts_sound_metadata_label_summary_on">메타데이터 라벨이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_sound_metadata_label_summary_off">메타데이터 라벨이 노출됩니다</string>
|
||||
<string name="revanced_hide_shorts_full_video_link_label_title">관련 동영상 링크 라벨 숨기기</string>
|
||||
<string name="revanced_hide_shorts_full_video_link_label_title">FULL 또는 관련 동영상 링크 라벨 숨기기</string>
|
||||
<string name="revanced_hide_shorts_full_video_link_label_summary_on">동영상 링크 라벨이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_full_video_link_label_summary_off">동영상 링크 라벨이 노출됩니다</string>
|
||||
<string name="revanced_hide_shorts_sound_button_title">사운드 버튼 숨기기</string>
|
||||
@@ -866,12 +864,12 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_sb_vote_downvote">싫어요</string>
|
||||
<string name="revanced_sb_vote_category">카테고리 변경</string>
|
||||
<string name="revanced_sb_vote_no_segments">투표할 구간이 없습니다</string>
|
||||
<string name="revanced_sb_new_segment_choose_category">구간 카테고리를 선택해주세요</string>
|
||||
<string name="revanced_sb_new_segment_choose_category">구간 카테고리를 선택하세요</string>
|
||||
<string name="revanced_sb_new_segment_disabled_category">이 카테고리는 비활성화되어 있습니다. 제출하려면 설정에서 활성화해야 합니다</string>
|
||||
<string name="revanced_sb_new_segment_title">새 SponsorBlock 구간</string>
|
||||
<!-- Do not rearrange the (hour):(minute):second) time format operators here.
|
||||
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
|
||||
<string name="revanced_sb_new_segment_mark_time_as_question">%1$02d:%2$02d:%3$03d을 구간의 시작 또는 끝으로 설정할까요?</string>
|
||||
<string name="revanced_sb_new_segment_mark_time_as_question">%1$02d:%2$02d:%3$03d을 구간의 시작 또는 끝으로 설정하겠습니까?</string>
|
||||
<string name="revanced_sb_new_segment_mark_start">시작</string>
|
||||
<string name="revanced_sb_new_segment_mark_end">끝</string>
|
||||
<string name="revanced_sb_new_segment_now">현재</string>
|
||||
@@ -882,8 +880,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
YT shows the same seekbar time format for all languages, and this string is confirming the segment time as it appears in the seekbar. -->
|
||||
<string name="revanced_sb_new_segment_confirm_content">선택한 구간이\n\n%1$s\n부터\n%2$s\n\n(%3$s) 까지 입니다\n\n이렇게 제출하겠습니까?</string>
|
||||
<string name="revanced_sb_new_segment_start_is_before_end">구간의 시작 또는 끝을 잘못 설정하였습니다</string>
|
||||
<string name="revanced_sb_new_segment_mark_locations_first">먼저 재생바에서 시작 지점과 끝 지점을 표시해주세요</string>
|
||||
<string name="revanced_sb_new_segment_preview_segment_first">구간 미리 보기 버튼을 눌러서 설정한 구간이 정상적으로 건너뛰기가 되는지 확인해주세요</string>
|
||||
<string name="revanced_sb_new_segment_mark_locations_first">먼저 재생바에서 시작 지점과 끝 지점을 표시하세요</string>
|
||||
<string name="revanced_sb_new_segment_preview_segment_first">구간 미리 보기 버튼을 눌러서 설정한 구간이 정상적으로 건너뛰기가 되는지 확인하세요</string>
|
||||
<string name="revanced_sb_new_segment_edit_by_hand_title">직접 시간 구간 편집하기</string>
|
||||
<string name="revanced_sb_new_segment_edit_by_hand_content">구간의 시작이나 끝을 편집하겠습니까?</string>
|
||||
<string name="revanced_sb_new_segment_edit_by_hand_parse_error">잘못된 시간 형식입니다</string>
|
||||
@@ -934,7 +932,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.startpage.ChangeStartPagePatch">
|
||||
<string name="revanced_start_page_title">앱 시작 페이지 변경하기</string>
|
||||
<string name="revanced_start_page_entry_0">기본</string>
|
||||
<string name="revanced_start_page_entry_0">기본값</string>
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_start_page_entry_1">홈</string>
|
||||
<string name="revanced_start_page_entry_2">검색</string>
|
||||
@@ -996,6 +994,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_seekbar_custom_color_value_summary">재생바 색상</string>
|
||||
<string name="revanced_seekbar_custom_color_invalid">잘못된 재생바 색상 값이므로 기본값으로 초기화합니다</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
<string name="revanced_bypass_image_region_restrictions_title">이미지 표시 국가 제한 우회하기</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">이미지 호스트로 yt4.ggpht.com를 사용합니다</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">기본 이미지 호스트를 사용합니다\n\n이 설정을 활성화하면 일부 국가에서 차단된 이미지를 수신할 수 있습니다 (채널 프로필 사진, 커뮤니티 게시물 이미지, etc.)</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<string name="revanced_alt_thumbnail_home_title">홈 탭</string>
|
||||
@@ -1084,7 +1087,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="video.speed.button.PlaybackSpeedButtonPatch">
|
||||
<string name="revanced_playback_speed_dialog_button_title">동영상 재생 속도 다이얼로그 버튼 표시하기</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">버튼이 노출됩니다</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_on">버튼을 표시합니다</string>
|
||||
<string name="revanced_playback_speed_dialog_button_summary_off">버튼을 표시하지 않습니다</string>
|
||||
</patch>
|
||||
<patch id="video.speed.custom.CustomPlaybackSpeedPatch">
|
||||
@@ -1119,7 +1122,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_spoof_client_user_dialog_message">이 설정을 비활성화하면 동영상 재생 문제가 발생할 수 있습니다</string>
|
||||
<string name="revanced_spoof_client_use_ios_title">iOS 클라이언트로 변경하기</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_on">클라이언트를 iOS 클라이언트로 변경합니다\n\n알려진 문제점:\n• HDR 동영상을 재생할 수 없습니다\n• 브랜드 계정 사용자는 시청 기록을 사용할 수 없습니다\n• 동영상이 초고화질 동영상 값으로 재생되지 않을 수 있습니다 (1440p, 2160p)\n• 실시간 스트림에서 \'백그라운드 재생\'을 사용할 수 없습니다\n• Android 8.0 사용자는 실시간 스트림을 재생할 수 없습니다</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_off">클라이언트를 Android VR 클라이언트로 변경합니다\n\n알려진 문제점: \n• HDR 동영상을 재생할 수 없습니다\n- Kids 동영상을 재생할 수 없습니다\n• 일시 정지된 동영상이 갑자기 다시 시작될 수 있습니다\n• 저화질 Shorts 재생바 썸네일이 표시됩니다\n• 플레이어 하단에서 오프라인 저장 버튼이 표시되지 않습니다\n• 최종 화면 카드가 표지되지 않습니다</string>
|
||||
<string name="revanced_spoof_client_use_ios_summary_off">클라이언트를 Android VR 클라이언트로 변경합니다\n\n알려진 문제점: \n• HDR 동영상을 재생할 수 없습니다\n- Kids 동영상을 재생할 수 없습니다\n• 일시 정지된 동영상이 갑자기 다시 시작될 수 있습니다\n• 저화질 Shorts 재생바 썸네일이 표시됩니다\n• 플레이어 하단에서 오프라인 저장 버튼이 표시되지 않습니다\n• 최종 화면 카드가 표시되지 않습니다</string>
|
||||
<string name="revanced_spoof_client_storyboard_timeout">클라이언트 썸네일을 사용할 수 없습니다 (응답 시간 초과)</string>
|
||||
<string name="revanced_spoof_client_storyboard_io_exception">클라이언트 썸네일을 일시적으로 사용할 수 없습니다: %s</string>
|
||||
</patch>
|
||||
@@ -1148,8 +1151,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_embedded_ads_service_failed">%s 서버에서 오류가 발생했기 때문에 광고가 표시될 것입니다. 설정에서 다른 광고 차단 서비스로 전환해 보세요</string>
|
||||
<string name="revanced_block_embedded_ads_title">광고 차단 Proxy 서버 사용하기</string>
|
||||
<string name="revanced_block_embedded_ads_entry_1">사용하지 않기</string>
|
||||
<string name="revanced_block_embedded_ads_entry_2">Luminous proxy</string>
|
||||
<string name="revanced_block_embedded_ads_entry_3">PurpleAdBlock proxy</string>
|
||||
<string name="revanced_block_embedded_ads_entry_2">Luminous Proxy</string>
|
||||
<string name="revanced_block_embedded_ads_entry_3">PurpleAdBlock Proxy</string>
|
||||
</patch>
|
||||
<patch id="ad.video.VideoAdsPatch">
|
||||
<string name="revanced_block_video_ads_title">동영상 광고 차단하기</string>
|
||||
@@ -1157,11 +1160,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
<string name="revanced_block_video_ads_summary_off">동영상 광고를 차단하지 않습니다</string>
|
||||
</patch>
|
||||
<patch id="chat.antidelete.ShowDeletedMessagesPatch">
|
||||
<string name="revanced_deleted_msg">메시지를 삭제합니다</string>
|
||||
<string name="revanced_show_deleted_messages_title">삭제된 메시지 표시하기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_1">삭제된 메시지 표시하지 않기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_2">스포일러 뒤에 삭제된 메시지 숨기기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_3">삭제된 메시지를 줄이 그어진 텍스트로 표시하기</string>
|
||||
<string name="revanced_deleted_msg">메시지를 제거합니다</string>
|
||||
<string name="revanced_show_deleted_messages_title">제거된 메시지 표시하기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_1">제거된 메시지 표시하지 않기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_2">스포일러 뒤에 제거된 메시지 숨기기</string>
|
||||
<string name="revanced_show_deleted_messages_entry_3">제거된 메시지를 줄이 그어진 텍스트로 표시하기</string>
|
||||
</patch>
|
||||
<patch id="chat.autoclaim.AutoClaimChannelPointsPatch">
|
||||
<string name="revanced_auto_claim_channel_points_title">채널 포인트 자동 적립하기</string>
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -207,6 +207,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -206,6 +206,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
@@ -198,6 +198,8 @@ This is because Crowdin requires temporarily flattening this file and removing t
|
||||
</patch>
|
||||
<patch id="layout.theme.ThemeResourcePatch">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.BypassImageRegionRestrictions">
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.AlternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the home tab. -->
|
||||
<!-- 'Subscription' should be translated using the same localized wording YouTube displays for the subscription tab. -->
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user