mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-25 02:14:09 +01:00
Compare commits
21 Commits
v5.35.0-de
...
v5.36.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f6093ee66 | ||
|
|
9d4aa5cd16 | ||
|
|
5ace6f587c | ||
|
|
796f56745e | ||
|
|
88b47ef414 | ||
|
|
8cd8e59bbc | ||
|
|
6e72b14d07 | ||
|
|
52b088327b | ||
|
|
8e934cc56b | ||
|
|
b3140d909b | ||
|
|
97645aa9f4 | ||
|
|
603e2d018c | ||
|
|
144af2f07e | ||
|
|
b8629aacb6 | ||
|
|
3951527f51 | ||
|
|
7a8b618c4e | ||
|
|
c66c42e946 | ||
|
|
b340769cf3 | ||
|
|
0a8cd7a7db | ||
|
|
39f90e4b11 | ||
|
|
9256aa4548 |
4
.github/workflows/build_pull_request.yml
vendored
4
.github/workflows/build_pull_request.yml
vendored
@@ -12,10 +12,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
2
.github/workflows/open_pull_request.yml
vendored
2
.github/workflows/open_pull_request.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
|
||||
2
.github/workflows/pull_strings.yml
vendored
2
.github/workflows/pull_strings.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: dev
|
||||
clean: true
|
||||
|
||||
2
.github/workflows/push_strings.yml
vendored
2
.github/workflows/push_strings.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preprocess strings
|
||||
env:
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
@@ -51,14 +51,14 @@ jobs:
|
||||
fingerprint: ${{ vars.GPG_FINGERPRINT }}
|
||||
|
||||
- name: Release
|
||||
uses: cycjimmy/semantic-release-action@v5
|
||||
uses: cycjimmy/semantic-release-action@v4
|
||||
id: release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Attest
|
||||
if: steps.release.outputs.new_release_published == 'true'
|
||||
uses: actions/attest-build-provenance@v3
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: 'ReVanced Patches ${{ steps.release.outputs.new_release_git_tag }}'
|
||||
subject-path: patches/build/libs/patches-*.rvp
|
||||
|
||||
2
.github/workflows/update-gradle-wrapper.yml
vendored
2
.github/workflows/update-gradle-wrapper.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v1
|
||||
|
||||
63
CHANGELOG.md
63
CHANGELOG.md
@@ -1,3 +1,66 @@
|
||||
# [5.36.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.1-dev.1...v5.36.0-dev.1) (2025-09-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - SponsorBlock:** Add 'Hook' segment category ([#5783](https://github.com/ReVanced/revanced-patches/issues/5783)) ([2e042c4](https://github.com/ReVanced/revanced-patches/commit/2e042c4b3366fa3daf991d5560fcae991d00ad12))
|
||||
|
||||
## [5.35.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.35.0...v5.35.1-dev.1) (2025-09-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Duolingo - Disable ads:** Support latest app target ([#5782](https://github.com/ReVanced/revanced-patches/issues/5782)) ([8491516](https://github.com/ReVanced/revanced-patches/commit/849151637389b8f399356d0d331bb74482f3f05d))
|
||||
* **YouTube - Hide layout components:** Hide new type of Playable shelf ([3af4126](https://github.com/ReVanced/revanced-patches/commit/3af41265338ddaab52d009f53370c57abddd4599))
|
||||
|
||||
# [5.35.0](https://github.com/ReVanced/revanced-patches/compare/v5.34.0...v5.35.0) (2025-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0d10e94](https://github.com/ReVanced/revanced-patches/commit/0d10e94663283fac09f3efc57c9b9805c38c4e13))
|
||||
* **Proton mail:** Constrain patches to last working app target ([21c34b9](https://github.com/ReVanced/revanced-patches/commit/21c34b908e07a97de8c31c7c828b44a8cc4739b6))
|
||||
* Revert dependency updates to fix Manager pre-release patching ([4c7a1a8](https://github.com/ReVanced/revanced-patches/commit/4c7a1a8554c67797bf663e5230f566c5a9b229af))
|
||||
* **Spotify - Unlock Premium:** Make compatible with latest versions again by fixing fingerprint ([#5684](https://github.com/ReVanced/revanced-patches/issues/5684)) ([30dcff1](https://github.com/ReVanced/revanced-patches/commit/30dcff13a56883efc499b71faadb403877cd1c67))
|
||||
* **YouTube - Hide layout components:** Hide Playable shelf header ([fbb5046](https://github.com/ReVanced/revanced-patches/commit/fbb50463f0e3f533a278c5251cfbce59f09ce641))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([08868c0](https://github.com/ReVanced/revanced-patches/commit/08868c00d3c4f1f37f4a77f333a03ca5a3259b59))
|
||||
* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c5e8079](https://github.com/ReVanced/revanced-patches/commit/c5e8079eab08075a72078cd0fa79f3beb1f75d98))
|
||||
* **Instagram:** Add `Hide navigation buttons` patch ([#5678](https://github.com/ReVanced/revanced-patches/issues/5678)) ([415cf0f](https://github.com/ReVanced/revanced-patches/commit/415cf0fb5b9b3dcaf4592943a69eea1c10447b07))
|
||||
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([3ae3251](https://github.com/ReVanced/revanced-patches/commit/3ae3251dc0317b6ced136fe9aa14be369642f203))
|
||||
|
||||
# [5.35.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.4...v5.35.0-dev.5) (2025-09-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **BaconReader:** Add `Fix Redgifs API` patch ([#5761](https://github.com/ReVanced/revanced-patches/issues/5761)) ([08868c0](https://github.com/ReVanced/revanced-patches/commit/08868c00d3c4f1f37f4a77f333a03ca5a3259b59))
|
||||
* **Instagram:** Add `Hide Stories from Home` patch ([#5756](https://github.com/ReVanced/revanced-patches/issues/5756)) ([3ae3251](https://github.com/ReVanced/revanced-patches/commit/3ae3251dc0317b6ced136fe9aa14be369642f203))
|
||||
|
||||
# [5.35.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.3...v5.35.0-dev.4) (2025-09-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Boost/Sync for Reddit:** Add `Fix Redgifs` patch ([#5725](https://github.com/ReVanced/revanced-patches/issues/5725)) ([c5e8079](https://github.com/ReVanced/revanced-patches/commit/c5e8079eab08075a72078cd0fa79f3beb1f75d98))
|
||||
|
||||
# [5.35.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.2...v5.35.0-dev.3) (2025-09-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Instagram - Hide navigation buttons:** Fix Manager patching error ([0d10e94](https://github.com/ReVanced/revanced-patches/commit/0d10e94663283fac09f3efc57c9b9805c38c4e13))
|
||||
|
||||
# [5.35.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.35.0-dev.1...v5.35.0-dev.2) (2025-09-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Revert dependency updates to fix Manager pre-release patching ([4c7a1a8](https://github.com/ReVanced/revanced-patches/commit/4c7a1a8554c67797bf663e5230f566c5a9b229af))
|
||||
|
||||
# [5.35.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.34.1-dev.3...v5.35.0-dev.1) (2025-09-03)
|
||||
|
||||
|
||||
|
||||
8
adsfund.json
Normal file
8
adsfund.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"info": "This is verification file for ads.fund project",
|
||||
"project": {
|
||||
"name": "Revanced Patches",
|
||||
"walletAddress": "0x7ab4091e00363654bf84B34151225742cd92FCE5",
|
||||
"tokenAddress": "0xadf325f255083a3f3d9a9d01ffb3db52a148d802"
|
||||
}
|
||||
}
|
||||
5
extensions/baconreader/build.gradle.kts
Normal file
5
extensions/baconreader/build.gradle.kts
Normal file
@@ -0,0 +1,5 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(libs.annotation)
|
||||
compileOnly(libs.okhttp)
|
||||
}
|
||||
1
extensions/baconreader/src/main/AndroidManifest.xml
Normal file
1
extensions/baconreader/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest/>
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.extension.baconreader;
|
||||
|
||||
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* @noinspection unused
|
||||
*/
|
||||
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
|
||||
static {
|
||||
INSTANCE = new FixRedgifsApiPatch();
|
||||
}
|
||||
|
||||
public String getDefaultUserAgent() {
|
||||
// BaconReader uses a static user agent for Redgifs API calls
|
||||
return "BaconReader";
|
||||
}
|
||||
|
||||
public static OkHttpClient install(OkHttpClient.Builder builder) {
|
||||
return builder.addInterceptor(INSTANCE).build();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:boostforreddit:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
compileOnly(libs.okhttp)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.extension.boostforreddit;
|
||||
|
||||
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* @noinspection unused
|
||||
*/
|
||||
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
|
||||
static {
|
||||
INSTANCE = new FixRedgifsApiPatch();
|
||||
}
|
||||
|
||||
public String getDefaultUserAgent() {
|
||||
// Boost uses a static user agent for Redgifs API calls
|
||||
return "Boost";
|
||||
}
|
||||
|
||||
public static OkHttpClient createClient() {
|
||||
return new OkHttpClient.Builder().addInterceptor(INSTANCE).build();
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies {
|
||||
implementation(project(":extensions:shared:library"))
|
||||
compileOnly(libs.okhttp)
|
||||
}
|
||||
|
||||
@@ -18,4 +18,5 @@ android {
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.annotation)
|
||||
compileOnly(libs.okhttp)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package app.revanced.extension.shared.fixes.redgifs;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
|
||||
public abstract class BaseFixRedgifsApiPatch implements Interceptor {
|
||||
protected static BaseFixRedgifsApiPatch INSTANCE;
|
||||
public abstract String getDefaultUserAgent();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
if (!request.url().host().equals("api.redgifs.com")) {
|
||||
return chain.proceed(request);
|
||||
}
|
||||
|
||||
String userAgent = getDefaultUserAgent();
|
||||
|
||||
if (request.header("Authorization") != null) {
|
||||
Response response = chain.proceed(request.newBuilder().header("User-Agent", userAgent).build());
|
||||
if (response.isSuccessful()) {
|
||||
return response;
|
||||
}
|
||||
// It's possible that the user agent is being overwritten later down in the interceptor
|
||||
// chain, so make sure we grab the new user agent from the request headers.
|
||||
userAgent = response.request().header("User-Agent");
|
||||
response.close();
|
||||
}
|
||||
|
||||
try {
|
||||
RedgifsTokenManager.RedgifsToken token = RedgifsTokenManager.refreshToken(userAgent);
|
||||
|
||||
// Emulate response for old OAuth endpoint
|
||||
if (request.url().encodedPath().equals("/v2/oauth/client")) {
|
||||
String responseBody = RedgifsTokenManager.getEmulatedOAuthResponseBody(token);
|
||||
return new Response.Builder()
|
||||
.message("OK")
|
||||
.code(HttpURLConnection.HTTP_OK)
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.request(request)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(ResponseBody.create(
|
||||
responseBody, MediaType.get("application/json")))
|
||||
.build();
|
||||
}
|
||||
|
||||
Request modifiedRequest = request.newBuilder()
|
||||
.header("Authorization", "Bearer " + token.getAccessToken())
|
||||
.header("User-Agent", userAgent)
|
||||
.build();
|
||||
return chain.proceed(modifiedRequest);
|
||||
} catch (JSONException ex) {
|
||||
Logger.printException(() -> "Could not parse Redgifs response", ex);
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package app.revanced.extension.shared.fixes.redgifs;
|
||||
|
||||
import static app.revanced.extension.shared.requests.Route.Method.GET;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.requests.Requester;
|
||||
|
||||
|
||||
/**
|
||||
* Manages Redgifs token lifecycle.
|
||||
*/
|
||||
public class RedgifsTokenManager {
|
||||
public static class RedgifsToken {
|
||||
// Expire after 23 hours to provide some breathing room
|
||||
private static final long EXPIRY_SECONDS = 23 * 60 * 60;
|
||||
|
||||
private final String accessToken;
|
||||
private final long refreshTimeInSeconds;
|
||||
|
||||
public RedgifsToken(String accessToken, long refreshTime) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshTimeInSeconds = refreshTime;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public long getExpiryTimeInSeconds() {
|
||||
return refreshTimeInSeconds + EXPIRY_SECONDS;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
if (accessToken == null) return false;
|
||||
return getExpiryTimeInSeconds() >= System.currentTimeMillis() / 1000;
|
||||
}
|
||||
}
|
||||
public static final String REDGIFS_API_HOST = "https://api.redgifs.com";
|
||||
private static final String GET_TEMPORARY_TOKEN = REDGIFS_API_HOST + "/v2/auth/temporary";
|
||||
@GuardedBy("itself")
|
||||
private static final Map<String, RedgifsToken> tokenMap = new HashMap<>();
|
||||
|
||||
private static String getToken(String userAgent) throws IOException, JSONException {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(GET_TEMPORARY_TOKEN).openConnection();
|
||||
connection.setFixedLengthStreamingMode(0);
|
||||
connection.setRequestMethod(GET.name());
|
||||
connection.setRequestProperty("User-Agent", userAgent);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setUseCaches(false);
|
||||
|
||||
JSONObject responseObject = Requester.parseJSONObject(connection);
|
||||
return responseObject.getString("token");
|
||||
}
|
||||
|
||||
public static RedgifsToken refreshToken(String userAgent) throws IOException, JSONException {
|
||||
synchronized(tokenMap) {
|
||||
// Reference: https://github.com/JeffreyCA/Apollo-ImprovedCustomApi/pull/67
|
||||
RedgifsToken token = tokenMap.get(userAgent);
|
||||
if (token != null && token.isValid()) {
|
||||
return token;
|
||||
}
|
||||
|
||||
// Copy user agent from original request if present because Redgifs verifies
|
||||
// that the user agent in subsequent requests matches the one in the OAuth token.
|
||||
String accessToken = getToken(userAgent);
|
||||
long refreshTime = System.currentTimeMillis() / 1000;
|
||||
token = new RedgifsToken(accessToken, refreshTime);
|
||||
tokenMap.put(userAgent, token);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getEmulatedOAuthResponseBody(RedgifsToken token) throws JSONException {
|
||||
// Reference: https://github.com/JeffreyCA/Apollo-ImprovedCustomApi/pull/67
|
||||
JSONObject responseObject = new JSONObject();
|
||||
responseObject.put("access_token", token.accessToken);
|
||||
responseObject.put("expiry_time", token.getExpiryTimeInSeconds() - (System.currentTimeMillis() / 1000));
|
||||
responseObject.put("scope", "read");
|
||||
responseObject.put("token_type", "Bearer");
|
||||
return responseObject.toString();
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,5 @@ dependencies {
|
||||
compileOnly(project(":extensions:shared:library"))
|
||||
compileOnly(project(":extensions:syncforreddit:stub"))
|
||||
compileOnly(libs.annotation)
|
||||
compileOnly(libs.okhttp)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.extension.syncforreddit;
|
||||
|
||||
import app.revanced.extension.shared.fixes.redgifs.BaseFixRedgifsApiPatch;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* @noinspection unused
|
||||
*/
|
||||
public class FixRedgifsApiPatch extends BaseFixRedgifsApiPatch {
|
||||
static {
|
||||
INSTANCE = new FixRedgifsApiPatch();
|
||||
}
|
||||
|
||||
public String getDefaultUserAgent() {
|
||||
// To be filled in by patch
|
||||
return "";
|
||||
}
|
||||
|
||||
public static OkHttpClient install(OkHttpClient.Builder builder) {
|
||||
return builder.addInterceptor(INSTANCE).build();
|
||||
}
|
||||
}
|
||||
@@ -513,6 +513,9 @@ public final class VideoInformation {
|
||||
Logger.printDebug(() -> "VideoQualities: " + Arrays.toString(currentQualities));
|
||||
}
|
||||
|
||||
// On extremely slow internet connections the index can initially be -1
|
||||
originalQualityIndex = Math.max(0, originalQualityIndex);
|
||||
|
||||
VideoQuality updatedCurrentQuality = qualities[originalQualityIndex];
|
||||
if (updatedCurrentQuality.patch_getResolution() != AUTOMATIC_VIDEO_QUALITY_VALUE
|
||||
&& (currentQuality == null || currentQuality != updatedCurrentQuality)) {
|
||||
|
||||
@@ -194,7 +194,7 @@ public final class LayoutComponentsFilter extends Filter {
|
||||
// Playable horizontal shelf header.
|
||||
playablesBuffer = new ByteArrayFilterGroup(
|
||||
Settings.HIDE_PLAYABLES,
|
||||
"mini_game"
|
||||
"FEmini_app_destination"
|
||||
);
|
||||
|
||||
final var quickActions = new StringFilterGroup(
|
||||
|
||||
@@ -436,6 +436,9 @@ public class Settings extends BaseSettings {
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT = new StringSetting("sb_highlight", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_HIGHLIGHT_COLOR = new StringSetting("sb_highlight_color", "#FF1684");
|
||||
public static final FloatSetting SB_CATEGORY_HIGHLIGHT_OPACITY = new FloatSetting("sb_highlight_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_HOOK = new StringSetting("sb_hook", IGNORE.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_HOOK_COLOR = new StringSetting("sb_hook_color", "#395699");
|
||||
public static final FloatSetting SB_CATEGORY_HOOK_OPACITY = new FloatSetting("sb_hook_opacity", 0.8f);
|
||||
public static final StringSetting SB_CATEGORY_INTRO = new StringSetting("sb_intro", MANUAL_SKIP.reVancedKeyValue);
|
||||
public static final StringSetting SB_CATEGORY_INTRO_COLOR = new StringSetting("sb_intro_color", "#00FFFF");
|
||||
public static final FloatSetting SB_CATEGORY_INTRO_OPACITY = new FloatSetting("sb_intro_opacity", 0.8f);
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.graphics.drawable.shapes.RoundRectShape;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Range;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
@@ -167,6 +168,11 @@ public class SegmentPlaybackController {
|
||||
*/
|
||||
private static WeakReference<Dialog> toastDialogRef = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Visibility of the ad progress UI component.
|
||||
*/
|
||||
private static volatile int adProgressTextVisibility = -1;
|
||||
|
||||
static {
|
||||
// Dismiss toast if app changes to PiP while undo skip is shown.
|
||||
PlayerType.getOnChange().addObserver((PlayerType type) -> {
|
||||
@@ -336,6 +342,7 @@ public class SegmentPlaybackController {
|
||||
*/
|
||||
static void executeDownloadSegments(String videoId) {
|
||||
Objects.requireNonNull(videoId);
|
||||
Utils.verifyOffMainThread();
|
||||
|
||||
SponsorSegment[] segments = SBRequester.getSegments(videoId);
|
||||
|
||||
@@ -367,6 +374,35 @@ public class SegmentPlaybackController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static void setAdProgressTextVisibility(int visibility) {
|
||||
if (adProgressTextVisibility != visibility) {
|
||||
adProgressTextVisibility = visibility;
|
||||
|
||||
Logger.printDebug(() -> {
|
||||
String visibilityMessage = switch (visibility) {
|
||||
case View.VISIBLE -> "VISIBLE";
|
||||
case View.GONE -> "GONE";
|
||||
case View.INVISIBLE -> "INVISIBLE";
|
||||
default -> "UNKNOWN";
|
||||
};
|
||||
return "AdProgressText visibility changed to: " + visibilityMessage;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a video ad is playing in a regular video player, segments or the Skip button should be hidden.
|
||||
* @return Whether the Ad Progress TextView is visible in the regular video player.
|
||||
*/
|
||||
public static boolean isAdProgressTextVisible() {
|
||||
return adProgressTextVisibility == View.VISIBLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Updates SponsorBlock every 1000ms.
|
||||
@@ -376,7 +412,8 @@ public class SegmentPlaybackController {
|
||||
try {
|
||||
if (!Settings.SB_ENABLED.get()
|
||||
|| PlayerType.getCurrent().isNoneOrHidden() // Shorts playback.
|
||||
|| segments == null || segments.length == 0) {
|
||||
|| segments == null || segments.length == 0
|
||||
|| isAdProgressTextVisible()) {
|
||||
return;
|
||||
}
|
||||
Logger.printDebug(() -> "setVideoTime: " + millis);
|
||||
@@ -671,7 +708,14 @@ public class SegmentPlaybackController {
|
||||
// Check for any smaller embedded segments, and count those as auto-skipped.
|
||||
final boolean showSkipToast = Settings.SB_TOAST_ON_SKIP.get();
|
||||
for (SponsorSegment otherSegment : Objects.requireNonNull(segments)) {
|
||||
if (segmentToSkip.end < otherSegment.start) {
|
||||
if (otherSegment.end <= segmentToSkip.start) {
|
||||
// Other segment does not overlap, and is before this skipped segment.
|
||||
// This situation can only happen if a video is opened and adjusted to
|
||||
// a later time in the video where earlier auto skip segments
|
||||
// have not been encountered yet.
|
||||
continue;
|
||||
}
|
||||
if (segmentToSkip.end <= otherSegment.start) {
|
||||
break; // No other segments can be contained.
|
||||
}
|
||||
|
||||
@@ -922,7 +966,8 @@ public class SegmentPlaybackController {
|
||||
public static String appendTimeWithoutSegments(String totalTime) {
|
||||
try {
|
||||
if (Settings.SB_ENABLED.get() && Settings.SB_VIDEO_LENGTH_WITHOUT_SEGMENTS.get()
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)) {
|
||||
&& !TextUtils.isEmpty(totalTime) && !TextUtils.isEmpty(timeWithoutSegments)
|
||||
&& !isAdProgressTextVisible()) {
|
||||
// Force LTR layout, to match the same LTR video time/length layout YouTube uses for all languages
|
||||
return "\u202D" + totalTime + timeWithoutSegments; // u202D = left to right override
|
||||
}
|
||||
@@ -983,7 +1028,7 @@ public class SegmentPlaybackController {
|
||||
@SuppressWarnings("unused")
|
||||
public static void drawSponsorTimeBars(final Canvas canvas, final float posY) {
|
||||
try {
|
||||
if (segments == null) return;
|
||||
if (segments == null || isAdProgressTextVisible()) return;
|
||||
final long videoLength = VideoInformation.getVideoLength();
|
||||
if (videoLength <= 0) return;
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ public enum SegmentCategory {
|
||||
sf("revanced_sb_skip_button_preview_beginning"), sf("revanced_sb_skip_button_preview_middle"), sf("revanced_sb_skip_button_preview_end"),
|
||||
sf("revanced_sb_skipped_preview_beginning"), sf("revanced_sb_skipped_preview_middle"), sf("revanced_sb_skipped_preview_end"),
|
||||
SB_CATEGORY_PREVIEW, SB_CATEGORY_PREVIEW_COLOR, SB_CATEGORY_PREVIEW_OPACITY),
|
||||
HOOK("hook", sf("revanced_sb_segments_hook"), sf("revanced_sb_segments_hook_sum"), sf("revanced_sb_skip_button_hook"), sf("revanced_sb_skipped_hook"),
|
||||
SB_CATEGORY_HOOK, SB_CATEGORY_HOOK_COLOR, SB_CATEGORY_HOOK_OPACITY),
|
||||
FILLER("filler", sf("revanced_sb_segments_filler"), sf("revanced_sb_segments_filler_sum"), sf("revanced_sb_skip_button_filler"), sf("revanced_sb_skipped_filler"),
|
||||
SB_CATEGORY_FILLER, SB_CATEGORY_FILLER_COLOR, SB_CATEGORY_FILLER_OPACITY),
|
||||
MUSIC_OFFTOPIC("music_offtopic", sf("revanced_sb_segments_nomusic"), sf("revanced_sb_segments_nomusic_sum"), sf("revanced_sb_skip_button_nomusic"), sf("revanced_sb_skipped_nomusic"),
|
||||
@@ -69,6 +71,7 @@ public enum SegmentCategory {
|
||||
INTRO,
|
||||
OUTRO,
|
||||
PREVIEW,
|
||||
HOOK,
|
||||
FILLER,
|
||||
MUSIC_OFFTOPIC,
|
||||
};
|
||||
@@ -81,6 +84,7 @@ public enum SegmentCategory {
|
||||
INTRO,
|
||||
OUTRO,
|
||||
PREVIEW,
|
||||
HOOK,
|
||||
FILLER,
|
||||
MUSIC_OFFTOPIC,
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import app.revanced.extension.shared.Logger;
|
||||
import app.revanced.extension.youtube.settings.Settings;
|
||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -26,7 +27,7 @@ public class CreateSegmentButton {
|
||||
controlsView,
|
||||
"revanced_sb_create_segment_button",
|
||||
null,
|
||||
CreateSegmentButton::shouldBeShown,
|
||||
CreateSegmentButton::isButtonEnabled,
|
||||
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
|
||||
null
|
||||
);
|
||||
@@ -56,7 +57,8 @@ public class CreateSegmentButton {
|
||||
if (instance != null) instance.setVisibility(visible, animated);
|
||||
}
|
||||
|
||||
private static boolean shouldBeShown() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get();
|
||||
private static boolean isButtonEnabled() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get()
|
||||
&& !SegmentPlaybackController.isAdProgressTextVisible();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class VotingButton {
|
||||
controlsView,
|
||||
"revanced_sb_voting_button",
|
||||
null,
|
||||
VotingButton::shouldBeShown,
|
||||
VotingButton::isButtonEnabled,
|
||||
v -> SponsorBlockUtils.onVotingClicked(v.getContext()),
|
||||
null
|
||||
);
|
||||
@@ -58,8 +58,9 @@ public class VotingButton {
|
||||
if (instance != null) instance.setVisibility(visible, animated);
|
||||
}
|
||||
|
||||
private static boolean shouldBeShown() {
|
||||
private static boolean isButtonEnabled() {
|
||||
return Settings.SB_ENABLED.get() && Settings.SB_VOTING_BUTTON.get()
|
||||
&& SegmentPlaybackController.videoHasSegments();
|
||||
&& SegmentPlaybackController.videoHasSegments()
|
||||
&& !SegmentPlaybackController.isAdProgressTextVisible();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ org.gradle.jvmargs = -Xms512M -Xmx2048M
|
||||
org.gradle.parallel = true
|
||||
android.useAndroidX = true
|
||||
kotlin.code.style = official
|
||||
version = 5.35.0-dev.1
|
||||
version = 5.36.0-dev.1
|
||||
|
||||
@@ -268,6 +268,10 @@ public final class app/revanced/patches/instagram/hide/navigation/HideNavigation
|
||||
public static final fun getHideNavigationButtonsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/hide/stories/HideStoriesKt {
|
||||
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -512,6 +516,13 @@ public final class app/revanced/patches/reddit/ad/general/HideAdsPatchKt {
|
||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/FixRedgifsApiPatchKt {
|
||||
public static final field CREATE_NEW_CLIENT_METHOD Ljava/lang/String;
|
||||
public static final field INSTALL_NEW_CLIENT_METHOD Ljava/lang/String;
|
||||
public static final fun fixRedgifsApiPatch (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
public static synthetic fun fixRedgifsApiPatch$default (Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/FixSLinksPatchKt {
|
||||
public static final field RESOLVE_S_LINK_METHOD Ljava/lang/String;
|
||||
public static final field SET_ACCESS_TOKEN_METHOD Ljava/lang/String;
|
||||
@@ -528,6 +539,14 @@ public final class app/revanced/patches/reddit/customclients/baconreader/api/Spo
|
||||
public static final fun getSpoofClientPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/baconreader/fix/redgifs/FixRedgifsApiPatchKt {
|
||||
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/baconreader/misc/extension/SharedExtensionPatchKt {
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/boostforreddit/ads/DisableAdsPatchKt {
|
||||
public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
@@ -540,6 +559,10 @@ public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/
|
||||
public static final fun getFixAudioMissingInDownloadsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/redgifs/FixRedgifsApiPatchKt {
|
||||
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/boostforreddit/fix/slink/FixSLinksPatchKt {
|
||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
||||
public static final fun getFixSlinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
@@ -610,6 +633,10 @@ public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/
|
||||
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/FixRedgifsApiPatchKt {
|
||||
public static final fun getFixRedgifsApi ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/slink/FixSLinksPatchKt {
|
||||
public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String;
|
||||
public static final fun getFixSLinksPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||
|
||||
@@ -19,14 +19,16 @@ val disableAdsPatch = bytecodePatch(
|
||||
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
|
||||
//
|
||||
// MonetizationDebugSettings seems to be the most general setting to work fine.
|
||||
initializeMonetizationDebugSettingsFingerprint.method.apply {
|
||||
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
initializeMonetizationDebugSettingsFingerprint
|
||||
.match(monetizationDebugSettingsToStringFingerprint.classDef)
|
||||
.method.apply {
|
||||
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"const/4 v$register, 0x1",
|
||||
)
|
||||
}
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"const/4 v$register, 0x1",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,11 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
internal val initializeMonetizationDebugSettingsFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
returns("V")
|
||||
parameters(
|
||||
"Z", // disableAds
|
||||
"Z", // useDebugBilling
|
||||
"Z", // showManageSubscriptions
|
||||
"Z", // alwaysShowSuperAds
|
||||
// matches "Lcom/duolingo/debug/FamilyQuestOverride;" or "Lcom/duolingo/data/debug/monetization/FamilyQuestOverride;"
|
||||
"Lcom/duolingo/",
|
||||
)
|
||||
// Parameters have not been reliable for fingerprinting between versions.
|
||||
opcodes(Opcode.IPUT_BOOLEAN)
|
||||
}
|
||||
|
||||
internal val monetizationDebugSettingsToStringFingerprint = fingerprint {
|
||||
strings("MonetizationDebugSettings(") // Partial string match.
|
||||
custom { method, _ -> method.name == "toString" }
|
||||
}
|
||||
@@ -20,13 +20,15 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
||||
val hideReels by booleanOption(
|
||||
key = "hideReels",
|
||||
default = true,
|
||||
title = "Hide Reels"
|
||||
title = "Hide Reels",
|
||||
description = "Permanently hides the Reels button."
|
||||
)
|
||||
|
||||
val hideCreate by booleanOption(
|
||||
key = "hideCreate",
|
||||
default = true,
|
||||
title = "Hide Create"
|
||||
title = "Hide Create",
|
||||
description = "Permanently hides the Create button."
|
||||
)
|
||||
|
||||
execute {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.instagram.hide.stories
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
|
||||
internal val getOrCreateAvatarViewFingerprint = fingerprint {
|
||||
parameters()
|
||||
returns("L")
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/instagram/reels/ui/views/reelavatar/RecyclerReelAvatarView;"
|
||||
}
|
||||
opcodes(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL // Add View (Story)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.instagram.hide.stories
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
val hideStoriesPatch = bytecodePatch(
|
||||
name = "Hide Stories from Home",
|
||||
description = "Hides Stories from the main page, by removing the buttons.",
|
||||
use = false
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
val addStoryMethod = getOrCreateAvatarViewFingerprint.method // Creates Story
|
||||
val addStoryEndIndex = getOrCreateAvatarViewFingerprint.patternMatch!!.endIndex
|
||||
|
||||
// Remove addView of Story.
|
||||
addStoryMethod.removeInstruction(addStoryEndIndex)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.reddit.customclients
|
||||
|
||||
import app.revanced.patcher.patch.BytecodePatchBuilder
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
const val INSTALL_NEW_CLIENT_METHOD = "install(Lokhttp3/OkHttpClient${'$'}Builder;)Lokhttp3/OkHttpClient;"
|
||||
const val CREATE_NEW_CLIENT_METHOD = "createClient()Lokhttp3/OkHttpClient;"
|
||||
|
||||
fun fixRedgifsApiPatch(
|
||||
extensionPatch: Patch<*>,
|
||||
block: BytecodePatchBuilder.() -> Unit = {},
|
||||
) = bytecodePatch(name = "Fix Redgifs API") {
|
||||
dependsOn(extensionPatch)
|
||||
|
||||
block()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
internal val getOkHttpClientFingerprint = fingerprint {
|
||||
returns("Lokhttp3/OkHttpClient;")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
classDef.type == "Lcom/onelouder/baconreader/media/gfycat/RedGifsManager;" && method.name == "getOkhttpClient"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package app.revanced.patches.reddit.customclients.baconreader.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.INSTALL_NEW_CLIENT_METHOD
|
||||
import app.revanced.patches.reddit.customclients.baconreader.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
|
||||
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.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/baconreader/FixRedgifsApiPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
extensionPatch = sharedExtensionPatch
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.onelouder.baconreader",
|
||||
"com.onelouder.baconreader.premium",
|
||||
)
|
||||
|
||||
execute {
|
||||
// region Patch Redgifs OkHttp3 client.
|
||||
|
||||
getOkHttpClientFingerprint.method.apply {
|
||||
// Remove conflicting OkHttp interceptors.
|
||||
val originalInterceptorInstallIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.NEW_INSTANCE && getReference<TypeReference>()?.type == "Lcom/onelouder/baconreader/media/gfycat/RedGifsManager\$HeaderInterceptor;"
|
||||
}
|
||||
removeInstructions(originalInterceptorInstallIndex, 5)
|
||||
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
|
||||
}
|
||||
val register = getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package app.revanced.patches.reddit.customclients.baconreader.misc.extension
|
||||
|
||||
import app.revanced.patches.reddit.customclients.baconreader.misc.extension.hooks.initHook
|
||||
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||
|
||||
val sharedExtensionPatch = sharedExtensionPatch("baconreader", initHook)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.reddit.customclients.baconreader.misc.extension.hooks
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
|
||||
internal val initHook = extensionHook {
|
||||
custom { method, _ ->
|
||||
method.definingClass == "Lcom/onelouder/baconreader/BaconReader;" && method.name == "onCreate"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val createOkHttpClientFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE)
|
||||
opcodes(
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
)
|
||||
custom { _, classDef -> classDef.sourceFile == "RedGifsAPIv2.java" }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.CREATE_NEW_CLIENT_METHOD
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/boostforreddit/FixRedgifsApiPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
extensionPatch = sharedExtensionPatch
|
||||
) {
|
||||
compatibleWith("com.rubenmayayo.reddit")
|
||||
|
||||
execute {
|
||||
// region Patch Redgifs OkHttp3 client.
|
||||
|
||||
createOkHttpClientFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
|
||||
}
|
||||
replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { }, ${EXTENSION_CLASS_DESCRIPTOR}->$CREATE_NEW_CLIENT_METHOD
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.writeRegister
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11n
|
||||
|
||||
|
||||
internal val createOkHttpClientFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
// There are four functions (each creating a client) defined in this file with very similar fingerprints.
|
||||
// We're looking for the one that only creates one object (the builder) and sets client options true
|
||||
// (thus never reloading the register with a 0).
|
||||
classDef.sourceFile == "OkHttpHelper.java" &&
|
||||
method.instructions.count { it.opcode == Opcode.NEW_INSTANCE } == 1 &&
|
||||
method.indexOfFirstInstruction {
|
||||
opcode == Opcode.CONST_4 && writeRegister == 1 && (this as Instruction11n).narrowLiteral == 0
|
||||
} == -1
|
||||
}
|
||||
}
|
||||
|
||||
internal val getDefaultUserAgentFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "getDefaultUserAgent" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
||||
}
|
||||
}
|
||||
|
||||
internal val getOriginalUserAgentFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
parameters()
|
||||
custom { _, classDef -> classDef.sourceFile == "AccountSingleton.java" }
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.redgifs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patches.reddit.customclients.INSTALL_NEW_CLIENT_METHOD
|
||||
import app.revanced.patches.reddit.customclients.fixRedgifsApiPatch
|
||||
import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/syncforreddit/FixRedgifsApiPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val fixRedgifsApi = fixRedgifsApiPatch(
|
||||
extensionPatch = sharedExtensionPatch
|
||||
) {
|
||||
compatibleWith(
|
||||
"com.laurencedawson.reddit_sync",
|
||||
"com.laurencedawson.reddit_sync.pro",
|
||||
"com.laurencedawson.reddit_sync.dev",
|
||||
)
|
||||
|
||||
execute {
|
||||
// region Patch Redgifs OkHttp3 client.
|
||||
|
||||
createOkHttpClientFingerprint.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.name == "build" && reference.definingClass == "Lokhttp3/OkHttpClient\$Builder;"
|
||||
}
|
||||
val register = getInstruction<FiveRegisterInstruction>(index).registerC
|
||||
replaceInstruction(
|
||||
index,
|
||||
"""
|
||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$INSTALL_NEW_CLIENT_METHOD
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
getDefaultUserAgentFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, ${getOriginalUserAgentFingerprint.method}
|
||||
move-result-object v0
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package app.revanced.patches.youtube.layout.sponsorblock
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionReversed
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@@ -56,3 +59,20 @@ internal val rectangleFieldInvalidatorFingerprint = fingerprint {
|
||||
reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method
|
||||
}
|
||||
}
|
||||
|
||||
internal val adProgressTextViewVisibilityFingerprint = fingerprint {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("V")
|
||||
parameters("Z")
|
||||
custom { method, _ ->
|
||||
indexOfAdProgressTextViewVisibilityInstruction(method) >= 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun indexOfAdProgressTextViewVisibilityInstruction(method: Method) =
|
||||
method.indexOfFirstInstructionReversed {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.definingClass ==
|
||||
"Lcom/google/android/libraries/youtube/ads/player/ui/AdProgressTextView;"
|
||||
&& reference.name =="setVisibility"
|
||||
}
|
||||
|
||||
@@ -252,5 +252,16 @@ val sponsorBlockPatch = bytecodePatch(
|
||||
}
|
||||
} ?: throw PatchException("Could not find the method which contains the replaceMeWith* strings")
|
||||
}
|
||||
|
||||
adProgressTextViewVisibilityFingerprint.method.apply {
|
||||
val index = indexOfAdProgressTextViewVisibilityInstruction(this)
|
||||
val register = getInstruction<FiveRegisterInstruction>(index).registerD
|
||||
|
||||
addInstructionsAtControlFlowLabel(
|
||||
index,
|
||||
"invoke-static { v$register }, $EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setAdProgressTextVisibility(I)V"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ internal val Instruction.registersUsed: List<Int>
|
||||
get() = when (this) {
|
||||
is FiveRegisterInstruction -> {
|
||||
when (registerCount) {
|
||||
0 -> listOf()
|
||||
1 -> listOf(registerC)
|
||||
2 -> listOf(registerC, registerD)
|
||||
3 -> listOf(registerC, registerD, registerE)
|
||||
|
||||
@@ -987,13 +987,13 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_restore_old_seekbar_thumbnails_summary_off">シーク中のサムネイルはプレーヤー画面全体に表示されます</string>
|
||||
</patch>
|
||||
<patch id="layout.sponsorblock.sponsorBlockResourcePatch">
|
||||
<string name="revanced_sb_enable_sb">SponsorBlock を有効にする</string>
|
||||
<string name="revanced_sb_enable_sb_sum">SponsorBlock は、ユーザーからの情報提供により YouTube 動画のわずらわしい部分を定義してスキップする機能です</string>
|
||||
<string name="revanced_sb_enable_sb">SponsorBlock を有効化</string>
|
||||
<string name="revanced_sb_enable_sb_sum">SponsorBlock は、ユーザーからの情報提供により YouTube 動画のわずらわしい部分をスキップする機能です</string>
|
||||
<string name="revanced_sb_appearance_category">外観</string>
|
||||
<string name="revanced_sb_enable_voting">投票ボタンを表示する</string>
|
||||
<string name="revanced_sb_enable_voting_sum_on">セグメントへの投票ボタンは、プレーヤー オーバーレイに表示されます</string>
|
||||
<string name="revanced_sb_enable_voting_sum_off">セグメントへの投票ボタンは、プレーヤー オーバーレイに表示されません</string>
|
||||
<string name="revanced_sb_square_layout">四角ボタンを使用する</string>
|
||||
<string name="revanced_sb_enable_voting">投票ボタンを表示</string>
|
||||
<string name="revanced_sb_enable_voting_sum_on">セグメントへの投票ボタンがプレーヤー オーバーレイに表示されます</string>
|
||||
<string name="revanced_sb_enable_voting_sum_off">セグメントへの投票ボタンはプレーヤー オーバーレイに表示されません</string>
|
||||
<string name="revanced_sb_square_layout">四角ボタンを使用</string>
|
||||
<string name="revanced_sb_square_layout_sum_on">ボタンとコントロールの角は直角です</string>
|
||||
<string name="revanced_sb_square_layout_sum_off">ボタンとコントロールの角は丸角です</string>
|
||||
<!-- Translations should use language similar to 'revanced_ryd_compact_layout_title'. -->
|
||||
@@ -1005,11 +1005,11 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_enable_auto_hide_skip_segment_button_sum_off">スキップボタンは、セグメントの開始から終了まで表示されます</string>
|
||||
<string name="revanced_sb_auto_hide_skip_button_duration">スキップボタンの表示時間</string>
|
||||
<string name="revanced_sb_auto_hide_skip_button_duration_sum">自動非表示設定のスキップボタンと「ハイライトまでスキップ」ボタンが表示される時間の長さ</string>
|
||||
<string name="revanced_sb_general_skiptoast">スキップ取り消しトーストを表示</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_on">セグメントが自動的にスキップされたとき、トーストが表示されます。このトースト通知をタップすると、スキップが取り消されます</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_off">セグメントが自動的にスキップされたとき、トーストは表示されません</string>
|
||||
<string name="revanced_sb_general_skiptoast">自動スキップ時にトーストを表示</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_on">セグメントが自動的にスキップされたときにトースト通知が表示されます。このトースト通知をタップすると、スキップを取り消すことができます</string>
|
||||
<string name="revanced_sb_general_skiptoast_sum_off">セグメントが自動的にスキップされたときにトースト通知は表示されません。このトースト通知をタップすると、スキップを取り消すことができます</string>
|
||||
<string name="revanced_sb_toast_on_skip_duration">スキップ トーストの表示時間</string>
|
||||
<string name="revanced_sb_toast_on_skip_duration_sum">スキップ取り消しトーストが表示される時間の長さ</string>
|
||||
<string name="revanced_sb_toast_on_skip_duration_sum">自動スキップ時にトースト通知が表示される時間の長さ</string>
|
||||
<string name="revanced_sb_duration_1s">1 秒</string>
|
||||
<string name="revanced_sb_duration_2s">2 秒</string>
|
||||
<string name="revanced_sb_duration_3s">3 秒</string>
|
||||
@@ -1023,11 +1023,11 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_general_time_without">セグメントを除いた再生時間を表示</string>
|
||||
<string name="revanced_sb_general_time_without_sum_on">すべてのセグメントを除いた再生時間がシークバーに表示されます</string>
|
||||
<string name="revanced_sb_general_time_without_sum_off">動画全体の再生時間のみがシークバーに表示されます</string>
|
||||
<string name="revanced_sb_create_segment_category">セグメントの作成</string>
|
||||
<string name="revanced_sb_create_segment_category">新しいセグメントの作成</string>
|
||||
<string name="revanced_sb_enable_create_segment">セグメント作成ボタンを表示</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">セグメント作成ボタンはプレーヤー オーバーレイに表示されます</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_on">セグメント作成ボタンがプレーヤー オーバーレイに表示されます</string>
|
||||
<string name="revanced_sb_enable_create_segment_sum_off">セグメント作成ボタンはプレーヤー オーバーレイに表示されません</string>
|
||||
<string name="revanced_sb_general_adjusting">セグメントの時間調整幅</string>
|
||||
<string name="revanced_sb_general_adjusting">セグメントの位置調整幅</string>
|
||||
<string name="revanced_sb_general_adjusting_sum">セグメント作成メニュー内の早送り / 巻き戻しボタンで移動する時間 (ミリ秒)</string>
|
||||
<string name="revanced_sb_general_adjusting_invalid">値は正の整数でなければなりません</string>
|
||||
<string name="revanced_sb_guidelines_preference_title">ガイドラインを見る</string>
|
||||
@@ -1037,15 +1037,15 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_guidelines_popup_already_read">既読</string>
|
||||
<string name="revanced_sb_guidelines_popup_open">表示する</string>
|
||||
<string name="revanced_sb_general">その他</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_title">API 利用不可時にトーストを表示する</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_on">SponsorBlock が利用できない場合は、トーストが表示されます</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_off">SponsorBlock が利用できない場合でも、トーストは表示されません</string>
|
||||
<string name="revanced_sb_general_skipcount">スキップデータを送信する</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_title">API 利用不可時にトーストを表示</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_on">SponsorBlock が利用できない場合にトースト通知が表示されます</string>
|
||||
<string name="revanced_sb_toast_on_connection_error_summary_off">SponsorBlock が利用できない場合にトースト通知は表示されません</string>
|
||||
<string name="revanced_sb_general_skipcount">スキップデータの収集を有効化</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_on">SponsorBlock リーダーボード にスキップによって節約した時間を送信します。セグメントをスキップする度にデータが送信されます</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_off">スキップデータは送信されません</string>
|
||||
<string name="revanced_sb_general_skipcount_sum_off">スキップデータの収集は無効です</string>
|
||||
<string name="revanced_sb_general_min_duration">セグメントの長さのしきい値</string>
|
||||
<string name="revanced_sb_general_min_duration_sum">この値 (秒) よりも短い時間のセグメントは、スキップもプレーヤーに表示もされません</string>
|
||||
<string name="revanced_sb_general_min_duration_invalid">時間の値が無効です</string>
|
||||
<string name="revanced_sb_general_min_duration_invalid">時間 (長さ) の値が無効です</string>
|
||||
<string name="revanced_sb_general_uuid">非公開ユーザー ID</string>
|
||||
<string name="revanced_sb_general_uuid_sum">この ID は公開すべきではありません。パスワードのようなものであり、誰とも共有すべきではありません。もし誰かがこの ID を手に入れた場合、あなたになりすますことができます</string>
|
||||
<string name="revanced_sb_general_uuid_invalid">非公開ユーザー ID は 30 文字以上必要です</string>
|
||||
@@ -1061,9 +1061,11 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_settings_import_successful">設定のインポートに成功しました</string>
|
||||
<string name="revanced_sb_settings_import_failed">インポートに失敗しました: %s</string>
|
||||
<string name="revanced_sb_settings_export_failed">エクスポートに失敗しました: %s</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning">"設定には、SponsorBlock の非公開ユーザー ID が含まれています。この ID はパスワードのようなものであり、決して共有すべきではありません。"</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning">"設定には、SponsorBlock の非公開ユーザー ID が含まれています。
|
||||
|
||||
このユーザー ID は、パスワードのようなものであり、決して共有すべきではありません。"</string>
|
||||
<string name="revanced_sb_settings_revanced_export_user_id_warning_dismiss">今後表示しない</string>
|
||||
<string name="revanced_sb_diff_segments">セグメントの挙動を変更</string>
|
||||
<string name="revanced_sb_diff_segments">セグメントに対する動作を変更</string>
|
||||
<string name="revanced_sb_segments_sponsor">スポンサー</string>
|
||||
<string name="revanced_sb_segments_sponsor_sum">有料の宣伝 、有料の紹介、直接的な広告。自己宣伝や好意をもって行う、慈善活動、クリエーター、ウェブサイト、製品などの無償の紹介は含まれません</string>
|
||||
<string name="revanced_sb_segments_selfpromo">無報酬の宣伝 / 自己宣伝</string>
|
||||
@@ -1073,7 +1075,7 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_segments_highlight">ハイライト</string>
|
||||
<string name="revanced_sb_segments_highlight_sum">動画の中で最も重要な場面</string>
|
||||
<string name="revanced_sb_segments_intro">幕間 / オープニング</string>
|
||||
<string name="revanced_sb_segments_intro_sum">実際のコンテンツを含まない区間。このカテゴリーは、一時停止、静止画、繰り返しアニメーションなどを含みます。情報を含むトランジッション (場面転換) は含まれません</string>
|
||||
<string name="revanced_sb_segments_intro_sum">実際のコンテンツを含まない区間。一時停止、静止画、繰り返しアニメーションなど。情報を含むトランジッション (場面転換) は、このカテゴリーではありません</string>
|
||||
<string name="revanced_sb_segments_outro">終了画面 / クレジット</string>
|
||||
<string name="revanced_sb_segments_outro_sum">クレジット、または YouTube の終了画面が表示される場面。情報を含む結論、まとめ部分は、このカテゴリーには含まれません</string>
|
||||
<string name="revanced_sb_segments_preview">予告編 / 総集編 / フック</string>
|
||||
@@ -1081,7 +1083,7 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_segments_filler">尺稼ぎの余談 / 冗談</string>
|
||||
<string name="revanced_sb_segments_filler_sum">動画の本筋を理解するために必要のない、尺稼ぎやユーモアのみを目的として追加された脱線的な場面。コンテキストや背景情報を提供する場面は、このカテゴリーに含まれません</string>
|
||||
<string name="revanced_sb_segments_nomusic">音楽: 楽曲以外の区間</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">ミュージック ビデオ専用。ミュージック ビデオの中で楽曲が流れていない区間。このカテゴリーのセグメントは、他のカテゴリーのセグメントと重なる場合があります</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">ミュージック ビデオ専用。ミュージック ビデオの中で楽曲が流れていない区間であり、公式や他のメディアの音源に存在しない区間</string>
|
||||
<string name="revanced_sb_skip_button_compact">スキップ</string>
|
||||
<string name="revanced_sb_skip_button_compact_highlight">ハイライト</string>
|
||||
<string name="revanced_sb_skip_button_sponsor"> スポンサーをスキップ</string>
|
||||
@@ -1136,19 +1138,19 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
<string name="revanced_sb_vote_upvote">高評価</string>
|
||||
<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_vote_no_segments">投票先のセグメントが指定されていません</string>
|
||||
<!-- A segment start and end time, such as "02:10 to 03:40". -->
|
||||
<string name="revanced_sb_vote_segment_time_to_from">%1$s ~ %2$s</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">セグメント作成</string>
|
||||
<string name="revanced_sb_new_segment_mark_time_as_question">%s を新しいセグメントの開始時間 / 終了時間に設定しますか?</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>
|
||||
<string name="revanced_sb_new_segment_time_start">セグメントの開始時間</string>
|
||||
<string name="revanced_sb_new_segment_time_end">セグメントの終了時間</string>
|
||||
<string name="revanced_sb_new_segment_confirm_title">時間は正確ですか?</string>
|
||||
<string name="revanced_sb_new_segment_disabled_category">カテゴリーが設定で無効になっています。送信するには、このカテゴリーを有効にしてください。</string>
|
||||
<string name="revanced_sb_new_segment_title">新しいセグメント</string>
|
||||
<string name="revanced_sb_new_segment_mark_time_as_question">%s を新しいセグメント (SponsorBlock) の開始位置 / 終了位置に設定しますか?</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>
|
||||
<string name="revanced_sb_new_segment_time_start">セグメントの開始位置</string>
|
||||
<string name="revanced_sb_new_segment_time_end">セグメントの終了位置</string>
|
||||
<string name="revanced_sb_new_segment_confirm_title">範囲は正確ですか?</string>
|
||||
<string name="revanced_sb_new_segment_confirm_content">"セグメントの範囲:
|
||||
|
||||
%1$s
|
||||
@@ -1158,12 +1160,12 @@ GmsCore の電池の最適化を無効にしても、バッテリーの使用に
|
||||
(%3$s)
|
||||
|
||||
送信しますか?"</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_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_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>
|
||||
<string name="revanced_sb_new_segment_edit_by_hand_content">セグメントの開始位置または終了位置を編集しますか?</string>
|
||||
<string name="revanced_sb_new_segment_edit_by_hand_parse_error">時間 (位置) の値が無効です</string>
|
||||
<string name="revanced_sb_stats_title">統計</string>
|
||||
<!-- Shown in the settings preferences, and translations can be any text length. -->
|
||||
<string name="revanced_sb_stats_connection_failure">統計情報は一時的に利用できません (API がダウンしています)</string>
|
||||
|
||||
@@ -402,7 +402,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
||||
<string name="revanced_hide_fullscreen_ads_title">전체 화면 광고 숨기기</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_on">"전체 화면 광고가 숨겨집니다
|
||||
|
||||
이 설정은 구형 기기에서만 사용할 수 있습니다"</string>
|
||||
이 기능은 구형 기기에서만 사용할 수 있습니다"</string>
|
||||
<string name="revanced_hide_fullscreen_ads_summary_off">전체 화면 광고가 표시됩니다</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_fullscreen_ads_feature_not_available_toast">\'전체 화면 광고 숨기기\'는 구형 기기에서만 사용할 수 있습니다</string>
|
||||
@@ -823,15 +823,15 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
||||
<string name="revanced_hide_shorts_tagged_products_title">태그된 제품 숨기기</string>
|
||||
<string name="revanced_hide_shorts_tagged_products_summary_on">태그된 제품이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_tagged_products_summary_off">태그된 제품이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_title">예정 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">예정 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">예정 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_title">\'이 사운드 사용\' 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_on">\'이 사운드 사용\' 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_off">\'이 사운드 사용\' 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_title">\'이 템플릿 사용\' 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_on">\'이 템플릿 사용\' 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">\'이 템플릿 사용\' 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_title">예정된 라이브 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_on">예정된 라이브 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_upcoming_button_summary_off">예정된 라이브 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_title">이 사운드 사용 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_on">이 사운드 사용 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_use_sound_button_summary_off">이 사운드 사용 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_title">템플릿 사용 버튼 숨기기</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_on">템플릿 사용 버튼이 숨겨집니다</string>
|
||||
<string name="revanced_hide_shorts_use_template_button_summary_off">템플릿 사용 버튼이 표시됩니다</string>
|
||||
<string name="revanced_hide_shorts_like_fountain_title">좋아요 버튼 애니메이션을 비활성화하기</string>
|
||||
<string name="revanced_hide_shorts_like_fountain_summary_on">좋아요 버튼 상단에 표시되는 애니메이션을 비활성화합니다</string>
|
||||
<string name="revanced_hide_shorts_like_fountain_summary_off">좋아요 버튼 상단에 표시되는 애니메이션을 활성화합니다</string>
|
||||
@@ -975,11 +975,11 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_summary_off">일반 화질 재생바 썸네일을 활성화합니다</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_on">전체 화면 고화질 재생바 썸네일을 활성화합니다</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_legacy_summary_off">전체 화면 일반 화질 재생바 썸네일을 활성화합니다</string>
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"이 설정을 활성화하면 재생바 썸네일이 없는 실시간 스트림의 썸네일도 복원됩니다.
|
||||
<string name="revanced_seekbar_thumbnails_high_quality_dialog_message">"이 기능을 활성화하면 재생바 썸네일이 없는 실시간 스트림의 썸네일도 복원됩니다.
|
||||
|
||||
재생바 썸네일에는 현재 동영상과 동일한 화질 값이 사용됩니다.
|
||||
|
||||
이 설정은 동영상 화질 값이 720p 이하이고 인터넷 연결 상태가 매우 빠를 때 가장 잘 작동합니다."</string>
|
||||
이 기능은 동영상 화질 값이 720p 이하이고 인터넷 연결 상태가 매우 빠를 때 가장 잘 작동합니다."</string>
|
||||
<string name="revanced_restore_old_seekbar_thumbnails_title">이전 재생바 썸네일 복원하기</string>
|
||||
<string name="revanced_restore_old_seekbar_thumbnails_summary_on">재생바 상단에서 최소화된 썸네일을 표시합니다</string>
|
||||
<string name="revanced_restore_old_seekbar_thumbnails_summary_off">플레이어에서 전체 화면으로 된 썸네일을 표시합니다</string>
|
||||
@@ -1214,7 +1214,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
||||
|
||||
이 경우 앱 레이아웃과 기능이 변경되지만 알려지지 않은 부작용이 발생할 수 있습니다.
|
||||
|
||||
나중에 이 설정을 비활성화하면 앱 레이아웃 버그를 방지하기 위해 앱 데이터를 지우는 것이 좋습니다."</string>
|
||||
나중에 이 기능을 비활성화하면 앱 레이아웃 버그를 방지하기 위해 앱 데이터를 지우는 것이 좋습니다."</string>
|
||||
<string name="revanced_spoof_app_version_target_title">변경할 앱 버전</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_1">19.35.36 - 이전 Shorts 플레이어 아이콘을 복원합니다</string>
|
||||
<string name="revanced_spoof_app_version_target_entry_2">19.01.34 - 이전 하단바 아이콘을 복원합니다</string>
|
||||
@@ -1352,7 +1352,7 @@ MicroG 앱 배터리 최적화를 비활성화(제한 없음)하더라도, 배
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_on">이미지 호스트로 yt4.ggpht.com를 사용합니다</string>
|
||||
<string name="revanced_bypass_image_region_restrictions_summary_off">"기본 이미지 호스트를 사용합니다
|
||||
|
||||
이 설정을 활성화하면 일부 국가에서 차단된 이미지를 수신할 수 있습니다"</string>
|
||||
이 기능을 활성화하면 일부 국가에서 차단된 이미지를 수신할 수 있습니다"</string>
|
||||
</patch>
|
||||
<patch id="layout.thumbnails.alternativeThumbnailsPatch">
|
||||
<!-- 'Home' should be translated using the same localized wording YouTube displays for the Home tab. -->
|
||||
@@ -1461,7 +1461,7 @@ DeArrow에 대해 자세히 알아보려면 여기를 탭하세요"</string>
|
||||
<string name="revanced_force_original_audio_summary_on">원본 오디오 스트림 언어를 사용 중입니다</string>
|
||||
<string name="revanced_force_original_audio_summary_off">기본 오디오 스트림 언어를 사용 중입니다</string>
|
||||
<!-- 'Spoof video streams' should be the same translation used for 'revanced_spoof_video_streams_screen_title'. -->
|
||||
<string name="revanced_force_original_audio_not_available">이 설정을 사용하려면, \'동영상 스트림 변경하기\'에서 기본 클라이언트를 iOS TV로 변경하세요</string>
|
||||
<string name="revanced_force_original_audio_not_available">이 기능을 사용하려면, \'동영상 스트림 변경하기\'에서 기본 클라이언트를 iOS TV로 변경하세요</string>
|
||||
</patch>
|
||||
<patch id="video.quality.rememberVideoQualityPatch">
|
||||
<!-- Translations should use the same text as 'revanced_custom_playback_speeds_auto'. -->
|
||||
|
||||
@@ -917,7 +917,7 @@ Inställningar → Uppspelning → Spela upp nästa video automatiskt"</string>
|
||||
</patch>
|
||||
<patch id="layout.returnyoutubedislike.returnYouTubeDislikePatch">
|
||||
<!-- 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">Ogilla-mark. är ej tillg. just nu (API-tidsgräns nådd)</string>
|
||||
<string name="revanced_ryd_failure_connection_timeout">Ogilla-markeringar är för tillfället inte tillgängliga (API-tidsgräns nådd)</string>
|
||||
<string name="revanced_ryd_failure_connection_status_code">Ogilla-markeringar är inte tillgängliga (status %d)</string>
|
||||
<string name="revanced_ryd_failure_client_rate_limit_requested">Ogilla-markeringar är inte tillgängliga (API-gräns för klienten)</string>
|
||||
<string name="revanced_ryd_failure_generic">Ogilla-markeringar är inte tillgängliga (%s)</string>
|
||||
@@ -1125,7 +1125,7 @@ Ditt användar-id är som ett lösenord och det bör aldrig delas."</string>
|
||||
Finns redan"</string>
|
||||
<string name="revanced_sb_submit_succeeded">Segmentet har skickats</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_sb_sponsorblock_connection_failure_timeout">SponsorBlock ej tillgängligt just nu (API-tidsgräns nådd)</string>
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_timeout">SponsorBlock är för tillfället inte tillgängligt (API-tidsgräns nådd)</string>
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_status">SponsorBlock är för tillfället inte tillgängligt (status %d)</string>
|
||||
<string name="revanced_sb_sponsorblock_connection_failure_generic">SponsorBlock är för tillfället inte tillgängligt</string>
|
||||
<string name="revanced_sb_vote_failed_timeout">Det gick inte att rösta på segment (API-tidsgräns nådd)</string>
|
||||
|
||||
@@ -1143,10 +1143,12 @@ Your user id is like a password and it should never be shared.
|
||||
<string name="revanced_sb_segments_intro_sum">An interval without actual content. Could be a pause, static frame, or repeating animation. Does not include transitions containing information</string>
|
||||
<string name="revanced_sb_segments_outro">Endcards / Credits</string>
|
||||
<string name="revanced_sb_segments_outro_sum">Credits or when the YouTube endcards appear. Not for conclusions with information</string>
|
||||
<string name="revanced_sb_segments_preview">Preview / Recap / Hook</string>
|
||||
<string name="revanced_sb_segments_hook">Hook / Greeting</string>
|
||||
<string name="revanced_sb_segments_hook_sum">Narrated trailers for the upcoming video, greetings and goodbyes. This should not skip conclusions with information</string>
|
||||
<string name="revanced_sb_segments_preview">Preview / Recap</string>
|
||||
<string name="revanced_sb_segments_preview_sum">Collection of clips that show what is coming up or what happened in the video or in other videos of a series, where all information is repeated elsewhere</string>
|
||||
<string name="revanced_sb_segments_filler">Filler Tangent / Jokes</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangential scenes added only for filler or humor that are not required to understand the main content of the video. Does not include segments providing context or background details</string>
|
||||
<string name="revanced_sb_segments_filler">Tangent / Jokes</string>
|
||||
<string name="revanced_sb_segments_filler_sum">Tangential scenes or jokes that are not required to understand the main content of the video. This should not include segments providing context or background details</string>
|
||||
<string name="revanced_sb_segments_nomusic">Music: Non-Music Section</string>
|
||||
<string name="revanced_sb_segments_nomusic_sum">Only for use in music videos. Sections of music videos without music, that aren\'t already covered by another category</string>
|
||||
<string name="revanced_sb_skip_button_compact">Skip</string>
|
||||
@@ -1159,10 +1161,11 @@ Your user id is like a password and it should never be shared.
|
||||
<string name="revanced_sb_skip_button_intro_middle">Skip intermission</string>
|
||||
<string name="revanced_sb_skip_button_intro_end">Skip intermission</string>
|
||||
<string name="revanced_sb_skip_button_outro">Skip outro</string>
|
||||
<string name="revanced_sb_skip_button_hook">Skip hook</string>
|
||||
<string name="revanced_sb_skip_button_preview_beginning">Skip preview</string>
|
||||
<string name="revanced_sb_skip_button_preview_middle">Skip preview</string>
|
||||
<string name="revanced_sb_skip_button_preview_end">Skip recap</string>
|
||||
<string name="revanced_sb_skip_button_filler">Skip filler</string>
|
||||
<string name="revanced_sb_skip_button_filler">Skip tangent</string>
|
||||
<string name="revanced_sb_skip_button_nomusic">Skip non-music</string>
|
||||
<string name="revanced_sb_skip_button_unsubmitted">Skip segment</string>
|
||||
<string name="revanced_sb_skipped_sponsor">Skipped sponsor</string>
|
||||
@@ -1173,10 +1176,11 @@ Your user id is like a password and it should never be shared.
|
||||
<string name="revanced_sb_skipped_intro_middle">Skipped intermission</string>
|
||||
<string name="revanced_sb_skipped_intro_end">Skipped intermission</string>
|
||||
<string name="revanced_sb_skipped_outro">Skipped outro</string>
|
||||
<string name="revanced_sb_skipped_hook">Skipped hook</string>
|
||||
<string name="revanced_sb_skipped_preview_beginning">Skipped preview</string>
|
||||
<string name="revanced_sb_skipped_preview_middle">Skipped preview</string>
|
||||
<string name="revanced_sb_skipped_preview_end">Skipped recap</string>
|
||||
<string name="revanced_sb_skipped_filler">Skipped filler</string>
|
||||
<string name="revanced_sb_skipped_filler">Skipped tangent</string>
|
||||
<string name="revanced_sb_skipped_nomusic">Skipped a non-music section</string>
|
||||
<string name="revanced_sb_skipped_unsubmitted">Skipped unsubmitted segment</string>
|
||||
<string name="revanced_sb_skipped_multiple_segments">Skipped multiple segments</string>
|
||||
|
||||
Reference in New Issue
Block a user