diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
similarity index 100%
rename from .github/ISSUE_TEMPLATE/bug-report.yml
rename to .github/ISSUE_TEMPLATE/bug_report.yml
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
similarity index 100%
rename from .github/ISSUE_TEMPLATE/feature-request.yml
rename to .github/ISSUE_TEMPLATE/feature_request.yml
diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml
new file mode 100644
index 0000000000..cab9162326
--- /dev/null
+++ b/.github/workflows/build_pull_request.yml
@@ -0,0 +1,28 @@
+name: Build pull request
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches:
+ - dev
+
+jobs:
+ release:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Cache Gradle
+ uses: burrunan/gradle-cache-action@v1
+
+ - name: Setup Java
+ run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV
+
+ - name: Build
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: ./gradlew build --no-daemon
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/open_pull_request.yml
similarity index 100%
rename from .github/workflows/pull_request.yml
rename to .github/workflows/open_pull_request.yml
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e98b39d889..edb9d1b8af 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -6,10 +6,6 @@ on:
branches:
- main
- dev
- pull_request:
- branches:
- - main
- - dev
jobs:
release:
@@ -44,6 +40,13 @@ jobs:
- name: Install dependencies
run: npm install
+ - name: Import GPG key
+ uses: crazy-max/ghaction-import-gpg@v6
+ with:
+ gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
+ passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ fingerprint: ${{ env.GPG_FINGERPRINT }}
+
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
diff --git a/.gitignore b/.gitignore
index 754c2ef48c..facee09b70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +1,12 @@
*.iml
.gradle
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/assetWizardSettings.xml
+/.idea
+/.vscode
+.DS_Store
/build
/captures
.externalNativeBuild
.cxx
-/.idea
-/.vscode
-/*.log
-node_modules
\ No newline at end of file
+local.properties
+node_modules
diff --git a/.releaserc b/.releaserc
index 02d9c7fad7..ceee0e49d5 100644
--- a/.releaserc
+++ b/.releaserc
@@ -25,7 +25,7 @@
{
"assets": [
{
- "path": "app/build/outputs/apk/release/*.apk"
+ "path": "app/build/outputs/apk/release/revanced-integrations*"
}
],
successComment: false
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3d413fc21..8449633081 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,67 @@
+# [1.4.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.8...v1.4.0-dev.9) (2024-03-02)
+
+
+### Features
+
+* **YouTube:** Reorganize settings menu ([#571](https://github.com/ReVanced/revanced-integrations/issues/571)) ([eea4a48](https://github.com/ReVanced/revanced-integrations/commit/eea4a48cd565712c09d0ddd35ae256871ebe1964))
+
+# [1.4.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.7...v1.4.0-dev.8) (2024-03-02)
+
+
+### Features
+
+* **YouTube - Spoof app version:** Add target versions ([#574](https://github.com/ReVanced/revanced-integrations/issues/574)) ([da57fb9](https://github.com/ReVanced/revanced-integrations/commit/da57fb95233ed251518fbd5c56a92bc39c4e0015))
+
+# [1.4.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.6...v1.4.0-dev.7) (2024-02-29)
+
+
+### Bug Fixes
+
+* **YouTube - Spoof app version:** Remove broken versions ([#573](https://github.com/ReVanced/revanced-integrations/issues/573)) ([fb4aab7](https://github.com/ReVanced/revanced-integrations/commit/fb4aab792ae93fc7e7decbc19bd71ae700d5d235))
+
+# [1.4.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.5...v1.4.0-dev.6) (2024-02-28)
+
+
+### Bug Fixes
+
+* **YouTube - Hide Shorts:** Hide Shorts in feed when using tablet layout ([#572](https://github.com/ReVanced/revanced-integrations/issues/572)) ([7f5e7df](https://github.com/ReVanced/revanced-integrations/commit/7f5e7dfd68ad0200e9ea36d45f18a85ddfe534f8))
+
+# [1.4.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.4...v1.4.0-dev.5) (2024-02-25)
+
+
+### Bug Fixes
+
+* **Twitter - Hide ads:** Hide ads in search ([b40687c](https://github.com/ReVanced/revanced-integrations/commit/b40687c5c7fa301c78035219b27c0bd85c968bb2))
+* **YouTube - Disable suggested end screen:** Reliably hide end screen ([b4ab5f6](https://github.com/ReVanced/revanced-integrations/commit/b4ab5f65d5607678a000783aae14257b845706b5))
+
+# [1.4.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.3...v1.4.0-dev.4) (2024-02-21)
+
+
+### Features
+
+* **X:** Add `Open links as query` patch ([#570](https://github.com/ReVanced/revanced-integrations/issues/570)) ([95ca632](https://github.com/ReVanced/revanced-integrations/commit/95ca632d40b90ea8160dbbf33fd5d7f2281cf711))
+
+# [1.4.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.2...v1.4.0-dev.3) (2024-02-13)
+
+
+### Bug Fixes
+
+* **YouTube - Hide ads:** Do not show error toast and hide full screen ads ([#569](https://github.com/ReVanced/revanced-integrations/issues/569)) ([0b0d46f](https://github.com/ReVanced/revanced-integrations/commit/0b0d46f5183c88f73d58c8f7b9320d38976ddd4e))
+
+# [1.4.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.4.0-dev.1...v1.4.0-dev.2) (2024-02-09)
+
+
+### Features
+
+* **Sync for Reddit:** Add `Fix /s/ links` patch ([a8c82ad](https://github.com/ReVanced/revanced-integrations/commit/a8c82ad27b74e929311536227dee0909ebc27ee1))
+
+# [1.4.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.3.2...v1.4.0-dev.1) (2024-02-09)
+
+
+### Features
+
+* **YouTube - Change start page:** Add more start pages ([27421fb](https://github.com/ReVanced/revanced-integrations/commit/27421fb5783e677075ab0c220030d6af64cfaa18))
+
## [1.3.2](https://github.com/ReVanced/revanced-integrations/compare/v1.3.1...v1.3.2) (2024-02-08)
diff --git a/app/.gitignore b/app/.gitignore
index 3543521e9f..42afabfd2a 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1 @@
-/build
+/build
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2b425557e6..69489b444e 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,18 +1,27 @@
plugins {
- id("com.android.application")
- id("org.jetbrains.kotlin.android")
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin)
+ publishing
}
android {
- compileSdk = 33
namespace = "app.revanced.integrations"
+ compileSdk = 33
+
+ applicationVariants.all {
+ outputs.all {
+ this as com.android.build.gradle.internal.api.ApkVariantOutputImpl
+
+ outputFileName = "${rootProject.name}-$versionName.apk"
+ }
+ }
defaultConfig {
applicationId = "app.revanced.integrations"
minSdk = 23
targetSdk = 33
multiDexEnabled = false
- versionName = project.version as String
+ versionName = version as String
}
buildTypes {
@@ -20,32 +29,52 @@ android {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
- "proguard-rules.pro"
+ "proguard-rules.pro",
)
}
- applicationVariants.all {
- outputs.all {
- this as com.android.build.gradle.internal.api.ApkVariantOutputImpl
-
- outputFileName = "${rootProject.name}-$versionName.apk"
- }
- }
}
+
compileOptions {
- sourceCompatibility(JavaVersion.VERSION_11)
- targetCompatibility(JavaVersion.VERSION_11)
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
}
+
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
}
dependencies {
- compileOnly(project(mapOf("path" to ":dummy")))
- compileOnly("androidx.annotation:annotation:1.7.0")
- compileOnly("androidx.appcompat:appcompat:1.7.0-alpha03")
- compileOnly("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
- compileOnly("com.squareup.retrofit2:retrofit:2.9.0")
+ compileOnly(libs.appcompat)
+ compileOnly(libs.annotation)
+ compileOnly(libs.okhttp)
+ compileOnly(libs.retrofit)
+
+ compileOnly(project(":stub"))
}
-tasks.register("publish") { dependsOn("build") }
+tasks {
+ // Because the signing plugin doesn't support signing APKs, do it manually.
+ register("sign") {
+ group = "signing"
+
+ dependsOn(build)
+
+ doLast {
+ val outputDirectory = layout.buildDirectory.dir("outputs/apk/release").get().asFile
+ val integrationsApk = outputDirectory.resolve("${rootProject.name}-$version.apk")
+
+ org.gradle.security.internal.gnupg.GnupgSignatoryFactory().createSignatory(project).sign(
+ integrationsApk.inputStream(),
+ outputDirectory.resolve("${integrationsApk.name}.asc").outputStream(),
+ )
+ }
+ }
+
+ // Needed by gradle-semantic-release-plugin.
+ // Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
+ publish {
+ dependsOn(build)
+ dependsOn("sign")
+ }
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 214329989d..8f804140d6 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -1,27 +1,6 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
-dontobfuscate
-dontoptimize
--keepattributes * # https://www.guardsquare.com/manual/configuration/attributes
+-keepattributes *
-keep class app.revanced.** {
*;
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 431b54ad65..e52a1167f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
+
-
diff --git a/app/src/main/java/app/revanced/integrations/shared/Utils.java b/app/src/main/java/app/revanced/integrations/shared/Utils.java
index 279abdead2..c2aa2f6bdc 100644
--- a/app/src/main/java/app/revanced/integrations/shared/Utils.java
+++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java
@@ -12,6 +12,7 @@
import android.os.Looper;
import android.preference.Preference;
import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
@@ -26,10 +27,7 @@
import androidx.annotation.Nullable;
import java.text.Bidi;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
@@ -102,7 +100,6 @@ public static void hideViewUnderCondition(BooleanSetting condition, View view) {
view.setVisibility(View.GONE);
}
-
/**
* General purpose pool for network calls and other background tasks.
* All tasks run at max thread priority.
@@ -205,7 +202,9 @@ public static float getResourceDimension(@NonNull String resourceIdentifierName)
public static T getChildView(@NonNull ViewGroup viewGroup, @NonNull MatchFilter filter) {
for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) {
View childAt = viewGroup.getChildAt(i);
+ //noinspection unchecked
if (filter.matches(childAt)) {
+ //noinspection unchecked
return (T) childAt;
}
}
@@ -345,6 +344,12 @@ public static void verifyOffMainThread() throws IllegalStateException {
}
}
+ public enum NetworkType {
+ NONE,
+ MOBILE,
+ OTHER,
+ }
+
public static boolean isNetworkConnected() {
NetworkType networkType = getNetworkType();
return networkType == NetworkType.MOBILE
@@ -393,48 +398,104 @@ public static void hideViewByLayoutParams(View view) {
}
}
+ /**
+ * {@link PreferenceScreen} and {@link PreferenceGroup} sorting styles.
+ */
+ private enum Sort {
+ /**
+ * Sort by the localized preference title.
+ */
+ BY_TITLE("_sort_by_title"),
+
+ /**
+ * Sort by the preference keys.
+ */
+ BY_KEY("_sort_by_key"),
+
+ /**
+ * Unspecified sorting.
+ */
+ UNSORTED("_sort_by_unsorted");
+
+ final String keySuffix;
+
+ Sort(String keySuffix) {
+ this.keySuffix = keySuffix;
+ }
+
+ /**
+ * Defaults to {@link #UNSORTED} if key is null or has no sort suffix.
+ */
+ @NonNull
+ static Sort fromKey(@Nullable String key) {
+ if (key != null) {
+ for (Sort sort : values()) {
+ if (key.endsWith(sort.keySuffix)) {
+ return sort;
+ }
+ }
+ }
+ return UNSORTED;
+ }
+ }
+
private static final Regex punctuationRegex = new Regex("\\p{P}+");
/**
- * Sort the preferences by title and ignore the casing.
+ * Strips all punctuation and converts to lower case. A null parameter returns an empty string.
+ */
+ public static String removePunctuationConvertToLowercase(@Nullable CharSequence original) {
+ if (original == null) return "";
+ return punctuationRegex.replace(original, "").toLowerCase();
+ }
+
+ /**
+ * Sort a PreferenceGroup and all it's sub groups by title or key.
*
- * Android Preferences are automatically sorted by title,
- * but if using a localized string key it sorts on the key and not the actual title text that's used at runtime.
+ * Sort order is determined by the preferences key {@link Sort} suffix.
*
- * @param menuDepthToSort Maximum menu depth to sort. Menus deeper than this value
- * will show preferences in the order created in patches.
+ * If a preference has no key or no {@link Sort} suffix,
+ * then the preferences are left unsorted.
*/
- public static void sortPreferenceGroupByTitle(PreferenceGroup group, int menuDepthToSort) {
- if (menuDepthToSort == 0) return;
-
+ public static void sortPreferenceGroups(@NonNull PreferenceGroup group) {
+ Sort sort = Sort.fromKey(group.getKey());
SortedMap preferences = new TreeMap<>();
+
for (int i = 0, prefCount = group.getPreferenceCount(); i < prefCount; i++) {
Preference preference = group.getPreference(i);
+
if (preference instanceof PreferenceGroup) {
- sortPreferenceGroupByTitle((PreferenceGroup) preference, menuDepthToSort - 1);
+ sortPreferenceGroups((PreferenceGroup) preference);
}
- preferences.put(removePunctuationConvertToLowercase(preference.getTitle()), preference);
- }
- int prefIndex = 0;
- for (Preference pref : preferences.values()) {
- int indexToSet = prefIndex++;
- if (pref instanceof PreferenceGroup || pref.getIntent() != null) {
- // Place preference groups last.
- // Use an offset to push the group to the end.
- indexToSet += 1000;
+ final String sortValue;
+ switch (sort) {
+ case BY_TITLE:
+ sortValue = removePunctuationConvertToLowercase(preference.getTitle());
+ break;
+ case BY_KEY:
+ sortValue = preference.getKey();
+ break;
+ case UNSORTED:
+ continue; // Keep original sorting.
+ default:
+ throw new IllegalStateException();
}
- pref.setOrder(indexToSet);
+
+ preferences.put(sortValue, preference);
}
- }
- public static String removePunctuationConvertToLowercase(CharSequence original) {
- return punctuationRegex.replace(original, "").toLowerCase();
- }
+ int index = 0;
+ for (Preference pref : preferences.values()) {
+ int order = index++;
- public enum NetworkType {
- NONE,
- MOBILE,
- OTHER,
+ // If the preference is a PreferenceScreen or is an intent preference, move to the top.
+ if (pref instanceof PreferenceScreen || pref.getIntent() != null) {
+ // Arbitrary high number.
+ order -= 1000;
+ }
+
+ pref.setOrder(order);
+ }
}
}
diff --git a/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java
index 6ef0c7785c..dc1fcbd934 100644
--- a/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java
+++ b/app/src/main/java/app/revanced/integrations/shared/settings/preference/AbstractPreferenceFragment.java
@@ -85,7 +85,7 @@ protected void initialize() {
if (identifier == 0) return;
addPreferencesFromResource(identifier);
- Utils.sortPreferenceGroupByTitle(getPreferenceScreen(), 2);
+ Utils.sortPreferenceGroups(getPreferenceScreen());
}
private void showSettingUserDialogConfirmation(SwitchPreference switchPref, BooleanSetting setting) {
diff --git a/app/src/main/java/app/revanced/integrations/syncforreddit/FixSLinksPatch.java b/app/src/main/java/app/revanced/integrations/syncforreddit/FixSLinksPatch.java
new file mode 100644
index 0000000000..a3c04ad616
--- /dev/null
+++ b/app/src/main/java/app/revanced/integrations/syncforreddit/FixSLinksPatch.java
@@ -0,0 +1,42 @@
+package app.revanced.integrations.syncforreddit;
+
+import android.os.StrictMode;
+import app.revanced.integrations.shared.Logger;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public final class FixSLinksPatch {
+ public static String resolveSLink(String link) {
+ if (link.matches(".*reddit\\.com/r/[^/]+/s/[^/]+")) {
+ Logger.printInfo(() -> "Resolving " + link);
+ try {
+ URL url = new URL(link);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setRequestMethod("HEAD");
+
+ // Disable strict mode in order to allow network access on the main thread.
+ // This is not ideal, but it's the easiest solution for now.
+ final var currentPolicy = StrictMode.getThreadPolicy();
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+
+ connection.connect();
+ String location = connection.getHeaderField("location");
+ connection.disconnect();
+
+ // Restore the original strict mode policy.
+ StrictMode.setThreadPolicy(currentPolicy);
+
+ Logger.printInfo(() -> "Resolved " + link + " -> " + location);
+
+ return location;
+ } catch (Exception e) {
+ Logger.printException(() -> "Failed to resolve " + link, e);
+ }
+ }
+
+ return link;
+ }
+}
diff --git a/app/src/main/java/app/revanced/integrations/twitch/settings/AppCompatActivityHook.java b/app/src/main/java/app/revanced/integrations/twitch/settings/AppCompatActivityHook.java
index f08fec13b2..42da779848 100644
--- a/app/src/main/java/app/revanced/integrations/twitch/settings/AppCompatActivityHook.java
+++ b/app/src/main/java/app/revanced/integrations/twitch/settings/AppCompatActivityHook.java
@@ -28,7 +28,7 @@ public class AppCompatActivityHook {
public static void startSettingsActivity() {
Logger.printDebug(() -> "Launching ReVanced settings");
- final var context = app.revanced.integrations.shared.Utils.getContext();
+ final var context = Utils.getContext();
if (context != null) {
Intent intent = new Intent(context, SettingsActivity.class);
diff --git a/app/src/main/java/app/revanced/integrations/twitter/patches/hook/twifucker/TwiFucker.kt b/app/src/main/java/app/revanced/integrations/twitter/patches/hook/twifucker/TwiFucker.kt
index 247ef0a344..3e0f7550b6 100644
--- a/app/src/main/java/app/revanced/integrations/twitter/patches/hook/twifucker/TwiFucker.kt
+++ b/app/src/main/java/app/revanced/integrations/twitter/patches/hook/twifucker/TwiFucker.kt
@@ -9,8 +9,7 @@ import org.json.JSONObject
// https://raw.githubusercontent.com/Dr-TSNG/TwiFucker/880cdf1c1622e54ab45561ffcb4f53d94ed97bae/app/src/main/java/icu/nullptr/twifucker/hook/JsonHook.kt
internal object TwiFucker {
// root
- private fun JSONObject.jsonGetInstructions(): JSONArray? =
- optJSONObject("timeline")?.optJSONArray("instructions")
+ private fun JSONObject.jsonGetInstructions(): JSONArray? = optJSONObject("timeline")?.optJSONArray("instructions")
private fun JSONObject.jsonGetData(): JSONObject? = optJSONObject("data")
@@ -42,10 +41,12 @@ internal object TwiFucker {
// data
private fun JSONObject.dataGetInstructions(): JSONArray? {
- val timeline = optJSONObject("user_result")?.optJSONObject("result")
- ?.optJSONObject("timeline_response")?.optJSONObject("timeline")
- ?: optJSONObject("timeline_response")?.optJSONObject("timeline")
- ?: optJSONObject("timeline_response")
+ val timeline =
+ optJSONObject("user_result")?.optJSONObject("result")
+ ?.optJSONObject("timeline_response")?.optJSONObject("timeline")
+ ?: optJSONObject("timeline_response")?.optJSONObject("timeline")
+ ?: optJSONObject("search")?.optJSONObject("timeline_response")?.optJSONObject("timeline")
+ ?: optJSONObject("timeline_response")
return timeline?.optJSONArray("instructions")
}
@@ -64,7 +65,6 @@ internal object TwiFucker {
}
}?.optJSONObject("legacy")
-
// entry
private fun JSONObject.entryHasPromotedMetadata(): Boolean =
optJSONObject("content")?.optJSONObject("item")?.optJSONObject("content")
@@ -77,11 +77,9 @@ internal object TwiFucker {
optJSONObject("content")?.optJSONArray("items")
?: optJSONObject("content")?.optJSONObject("timelineModule")?.optJSONArray("items")
- private fun JSONObject.entryIsTweetDetailRelatedTweets(): Boolean =
- optString("entryId").startsWith("tweetdetailrelatedtweets-")
+ private fun JSONObject.entryIsTweetDetailRelatedTweets(): Boolean = optString("entryId").startsWith("tweetdetailrelatedtweets-")
- private fun JSONObject.entryGetTrends(): JSONArray? =
- optJSONObject("content")?.optJSONObject("timelineModule")?.optJSONArray("items")
+ private fun JSONObject.entryGetTrends(): JSONArray? = optJSONObject("content")?.optJSONObject("timelineModule")?.optJSONArray("items")
// trend
private fun JSONObject.trendHasPromotedMetadata(): Boolean =
@@ -104,8 +102,7 @@ internal object TwiFucker {
// instruction
private fun JSONObject.instructionTimelineAddEntries(): JSONArray? = optJSONArray("entries")
- private fun JSONObject.instructionGetAddEntries(): JSONArray? =
- optJSONObject("addEntries")?.optJSONArray("entries")
+ private fun JSONObject.instructionGetAddEntries(): JSONArray? = optJSONObject("addEntries")?.optJSONArray("entries")
private fun JSONObject.instructionCheckAndRemove(action: (JSONArray) -> Unit) {
instructionTimelineAddEntries()?.let(action)
@@ -164,9 +161,10 @@ internal object TwiFucker {
entriesRemoveTweetDetailRelatedTweets()
}
- private fun JSONObject.entryIsWhoToFollow(): Boolean = optString("entryId").let {
- it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-")
- }
+ private fun JSONObject.entryIsWhoToFollow(): Boolean =
+ optString("entryId").let {
+ it.startsWith("whoToFollow-") || it.startsWith("who-to-follow-") || it.startsWith("connect-module-")
+ }
private fun JSONObject.itemContainsPromotedUser(): Boolean =
optJSONObject("item")?.optJSONObject("content")
@@ -217,4 +215,4 @@ internal object TwiFucker {
instruction.instructionCheckAndRemove(action)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/app/revanced/integrations/twitter/patches/links/OpenLinksWithAppChooserPatch.java b/app/src/main/java/app/revanced/integrations/twitter/patches/links/OpenLinksWithAppChooserPatch.java
new file mode 100644
index 0000000000..e781f19af7
--- /dev/null
+++ b/app/src/main/java/app/revanced/integrations/twitter/patches/links/OpenLinksWithAppChooserPatch.java
@@ -0,0 +1,12 @@
+package app.revanced.integrations.twitter.patches.links;
+
+import android.content.Context;
+import android.content.Intent;
+
+public final class OpenLinksWithAppChooserPatch {
+ public static void openWithChooser(final Context context, final Intent intent) {
+ intent.setAction("android.intent.action.VIEW");
+
+ context.startActivity(Intent.createChooser(intent, null));
+ }
+}
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java
index 9cedb96e2e..a16d481ae1 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/AlternativeThumbnailsPatch.java
@@ -422,7 +422,7 @@ private static class VerifiedQualities {
private static final int CACHE_LIMIT = 1000;
@Override
- protected boolean removeEldestEntry(Map.Entry eldest) {
+ protected boolean removeEldestEntry(Entry eldest) {
return size() > CACHE_LIMIT; // Evict the oldest entry if over the cache limit.
}
};
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/ChangeStartPagePatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/ChangeStartPagePatch.java
index 2e3f007a41..f31af61b1b 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/ChangeStartPagePatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/ChangeStartPagePatch.java
@@ -1,9 +1,9 @@
package app.revanced.integrations.youtube.patches;
import android.content.Intent;
-
-import app.revanced.integrations.youtube.settings.Settings;
+import android.net.Uri;
import app.revanced.integrations.shared.Logger;
+import app.revanced.integrations.youtube.settings.Settings;
@SuppressWarnings("unused")
public final class ChangeStartPagePatch {
@@ -12,6 +12,10 @@ public static void changeIntent(final Intent intent) {
if (startPage.isEmpty()) return;
Logger.printDebug(() -> "Changing start page to " + startPage);
- intent.setAction("com.google.android.youtube.action." + startPage);
+
+ if (startPage.startsWith("www"))
+ intent.setData(Uri.parse(startPage));
+ else
+ intent.setAction("com.google.android.youtube.action." + startPage);
}
}
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java
index 3ceea0cc14..0b7897bac0 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/DisableSuggestedVideoEndScreenPatch.java
@@ -3,29 +3,27 @@
import android.annotation.SuppressLint;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
+import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings;
/** @noinspection unused*/
public final class DisableSuggestedVideoEndScreenPatch {
@SuppressLint("StaticFieldLeak")
- private static View lastView;
+ private static ImageView lastView;
public static void closeEndScreen(final ImageView imageView) {
if (!Settings.DISABLE_SUGGESTED_VIDEO_END_SCREEN.get()) return;
- // Get a parent view which can be listened to for layout changes.
- final var parent = imageView.getParent().getParent();
-
// Prevent adding the listener multiple times.
- if (lastView == parent) return;
+ if (lastView == imageView) return;
+ lastView = imageView;
- lastView = (ViewGroup)parent;
- lastView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- // Disable sound effects to prevent the click sound.
- imageView.setSoundEffectsEnabled(false);
- imageView.performClick();
+ imageView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
+ if (imageView.isShown()) imageView.callOnClick();
});
}
}
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java
index 51774f04ea..0cb687f638 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/ReturnYouTubeDislikePatch.java
@@ -667,7 +667,7 @@ private static boolean videoIdIsSame(@Nullable ReturnYouTubeDislike fetch, @Null
*
* Called when the user likes or dislikes.
*
- * @param vote int that matches {@link ReturnYouTubeDislike.Vote#value}
+ * @param vote int that matches {@link Vote#value}
*/
public static void sendVote(int vote) {
try {
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java
index b1d38c6eb5..c122cd914e 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/AdsFilter.java
@@ -14,7 +14,7 @@
@SuppressWarnings("unused")
public final class AdsFilter extends Filter {
// region Fullscreen ad
- private static long lastTimeClosedFullscreenAd = 0;
+ private static volatile long lastTimeClosedFullscreenAd;
private static final Instrumentation instrumentation = new Instrumentation();
private final StringFilterGroup fullscreenAd;
@@ -168,6 +168,9 @@ private static void closeFullscreenAd() {
Logger.printDebug(() -> "Closing fullscreen ad");
- Utils.runOnMainThreadDelayed(() -> instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK), 1000);
+ Utils.runOnMainThreadDelayed(() -> {
+ // Must run off main thread (Odd, but whatever).
+ Utils.runOnBackgroundThread(() -> instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK));
+ }, 1000);
}
}
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ButtonsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ButtonsFilter.java
index 5db9a8a841..c92cba972d 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ButtonsFilter.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ButtonsFilter.java
@@ -49,10 +49,6 @@ public ButtonsFilter() {
);
bufferButtonsGroupList.addAll(
- new ByteArrayFilterGroup(
- Settings.HIDE_LIVE_CHAT_BUTTON,
- "yt_outline_message_bubble_overlap"
- ),
new ByteArrayFilterGroup(
Settings.HIDE_REPORT_BUTTON,
"yt_outline_flag"
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java
index f8ac724b74..605b48beac 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java
@@ -45,7 +45,7 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
private static final int NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK = 5;
@Override
- protected boolean removeEldestEntry(Map.Entry eldest) {
+ protected boolean removeEldestEntry(Entry eldest) {
return size() > NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK;
}
};
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java
index 6782223c91..c0c8d8c519 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/ShortsFilter.java
@@ -17,6 +17,9 @@ public final class ShortsFilter extends Filter {
public static PivotBar pivotBar; // Set by patch.
private final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml";
+ private final StringFilterGroup shortsCompactFeedVideoPath;
+ private final ByteArrayFilterGroup shortsCompactFeedVideoBuffer;
+
private final StringFilterGroup channelBar;
private final StringFilterGroup subscribeButton;
private final StringFilterGroup subscribeButtonPaused;
@@ -35,7 +38,6 @@ public ShortsFilter() {
"shorts_grid",
"shorts_video_cell",
"shorts_pivot_item"
-
);
// Feed Shorts shelf header.
// Use a different filter group for this pattern, as it requires an additional check after matching.
@@ -52,6 +54,15 @@ public ShortsFilter() {
addIdentifierCallbacks(shorts, shelfHeader, thanksButton);
+ // Shorts that appear in the feed/search when the device is using tablet layout.
+ shortsCompactFeedVideoPath = new StringFilterGroup(Settings.HIDE_SHORTS,
+ "compact_video.eml");
+ // Filter out items that use the 'frame0' thumbnail.
+ // This is a valid thumbnail for both regular videos and Shorts,
+ // but it appears these thumbnails are used only for Shorts.
+ shortsCompactFeedVideoBuffer = new ByteArrayFilterGroup(Settings.HIDE_SHORTS,
+ "/frame0.jpg");
+
// Shorts player components.
var joinButton = new StringFilterGroup(
Settings.HIDE_SHORTS_JOIN_BUTTON,
@@ -89,6 +100,7 @@ public ShortsFilter() {
);
addPathCallbacks(
+ shortsCompactFeedVideoPath,
joinButton, subscribeButton, subscribeButtonPaused,
channelBar, soundButton, infoPanel, videoActionButton
);
@@ -122,6 +134,13 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff
matchedGroup == subscribeButtonPaused
) return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
+ if (matchedGroup == shortsCompactFeedVideoPath) {
+ if (contentIndex == 0 && shortsCompactFeedVideoBuffer.check(protobufBufferArray).isFiltered()) {
+ return super.isFiltered(identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex);
+ }
+ return false;
+ }
+
// Video action buttons (comment, share, remix) have the same path.
if (matchedGroup == videoActionButton) {
if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) return super.isFiltered(
@@ -132,10 +151,11 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff
// Filter other path groups from pathFilterGroupList, only when reelChannelBar is visible
// to avoid false positives.
- if (path.startsWith(REEL_CHANNEL_BAR_PATH))
- if (matchedGroup == subscribeButton) return super.isFiltered(
+ if (matchedGroup == subscribeButton) {
+ if (path.startsWith(REEL_CHANNEL_BAR_PATH)) return super.isFiltered(
identifier, path, protobufBufferArray, matchedGroup, contentType, contentIndex
);
+ }
return false;
} else if (matchedGroup == shelfHeader) {
diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch.java
index c57bf0fc6f..93219797da 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/patches/spoof/SpoofAppVersionPatch.java
@@ -1,12 +1,26 @@
package app.revanced.integrations.youtube.patches.spoof;
+import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings;
@SuppressWarnings("unused")
public class SpoofAppVersionPatch {
- private static final boolean SPOOF_APP_VERSION_ENABLED = Settings.SPOOF_APP_VERSION.get();
- private static final String SPOOF_APP_VERSION_TARGET = Settings.SPOOF_APP_VERSION_TARGET.get();
+ private static final boolean SPOOF_APP_VERSION_ENABLED;
+ private static final String SPOOF_APP_VERSION_TARGET;
+
+ static {
+ // TODO: remove this migration code
+ // Spoof targets below 17.33 that no longer reliably work.
+ if (Settings.SPOOF_APP_VERSION_TARGET.get().compareTo("17.33.01") < 0) {
+ Logger.printInfo(() -> "Resetting spoof app version target");
+ Settings.SPOOF_APP_VERSION_TARGET.resetToDefault();
+ }
+ // End migration
+
+ SPOOF_APP_VERSION_ENABLED = Settings.SPOOF_APP_VERSION.get();
+ SPOOF_APP_VERSION_TARGET = Settings.SPOOF_APP_VERSION_TARGET.get();
+ }
/**
* Injection point
diff --git a/app/src/main/java/app/revanced/integrations/youtube/requests/Route.java b/app/src/main/java/app/revanced/integrations/youtube/requests/Route.java
index 877a364c90..afbc24506f 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/requests/Route.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/requests/Route.java
@@ -2,10 +2,10 @@
public class Route {
private final String route;
- private final Route.Method method;
+ private final Method method;
private final int paramCount;
- public Route(Route.Method method, String route) {
+ public Route(Method method, String route) {
this.method = method;
this.route = route;
this.paramCount = countMatches(route, '{');
@@ -14,11 +14,11 @@ public Route(Route.Method method, String route) {
throw new IllegalArgumentException("Not enough parameters");
}
- public Route.Method getMethod() {
+ public Method getMethod() {
return method;
}
- public Route.CompiledRoute compile(String... params) {
+ public CompiledRoute compile(String... params) {
if (params.length != paramCount)
throw new IllegalArgumentException("Error compiling route [" + route + "], incorrect amount of parameters provided. " +
"Expected: " + paramCount + ", provided: " + params.length);
@@ -29,7 +29,7 @@ public Route.CompiledRoute compile(String... params) {
int paramEnd = compiledRoute.indexOf("}");
compiledRoute.replace(paramStart, paramEnd + 1, params[i]);
}
- return new Route.CompiledRoute(this, compiledRoute.toString());
+ return new CompiledRoute(this, compiledRoute.toString());
}
public static class CompiledRoute {
@@ -45,7 +45,7 @@ public String getCompiledRoute() {
return compiledRoute;
}
- public Route.Method getMethod() {
+ public Method getMethod() {
return baseRoute.method;
}
}
diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java
index bbf11fba38..e011f941f1 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java
@@ -15,15 +15,14 @@
import java.util.HashSet;
import java.util.Set;
-import app.revanced.integrations.shared.Logger;
+import app.revanced.integrations.shared.settings.BaseSettings;
import app.revanced.integrations.shared.settings.BooleanSetting;
import app.revanced.integrations.shared.settings.FloatSetting;
import app.revanced.integrations.shared.settings.IntegerSetting;
import app.revanced.integrations.shared.settings.LongSetting;
import app.revanced.integrations.shared.settings.Setting;
-import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
-import app.revanced.integrations.shared.settings.BaseSettings;
import app.revanced.integrations.shared.settings.StringSetting;
+import app.revanced.integrations.shared.settings.preference.SharedPrefCategory;
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings;
public class Settings extends BaseSettings {
@@ -129,7 +128,7 @@ public class Settings extends BaseSettings {
public static final IntegerSetting PLAYER_OVERLAY_OPACITY = new IntegerSetting("revanced_player_overlay_opacity",100, true);
public static final BooleanSetting PLAYER_POPUP_PANELS = new BooleanSetting("revanced_hide_player_popup_panels", FALSE);
public static final BooleanSetting SPOOF_APP_VERSION = new BooleanSetting("revanced_spoof_app_version", FALSE, true, "revanced_spoof_app_version_user_dialog_message");
- public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", "17.08.35", true, parent(SPOOF_APP_VERSION));
+ public static final StringSetting SPOOF_APP_VERSION_TARGET = new StringSetting("revanced_spoof_app_version_target", "17.33.42", true, parent(SPOOF_APP_VERSION));
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true);
public static final BooleanSetting TABLET_LAYOUT = new BooleanSetting("revanced_tablet_layout", FALSE, true, "revanced_tablet_layout_user_dialog_message");
public static final BooleanSetting USE_TABLET_MINIPLAYER = new BooleanSetting("revanced_tablet_miniplayer", FALSE, true);
@@ -167,7 +166,6 @@ public class Settings extends BaseSettings {
// Action buttons
public static final BooleanSetting HIDE_LIKE_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_like_dislike_button", FALSE);
- public static final BooleanSetting HIDE_LIVE_CHAT_BUTTON = new BooleanSetting("revanced_hide_live_chat_button", FALSE);
public static final BooleanSetting HIDE_SHARE_BUTTON = new BooleanSetting("revanced_hide_share_button", FALSE);
public static final BooleanSetting HIDE_REPORT_BUTTON = new BooleanSetting("revanced_hide_report_button", FALSE);
public static final BooleanSetting HIDE_REMIX_BUTTON = new BooleanSetting("revanced_hide_remix_button", TRUE);
diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
index 50b0a78bb8..117c2f9945 100644
--- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
+++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReturnYouTubeDislikePreferenceFragment.java
@@ -150,7 +150,7 @@ public void onCreate(Bundle savedInstanceState) {
pref.getContext().startActivity(i);
return false;
});
- preferenceScreen.addPreference(aboutWebsitePreference);
+ aboutCategory.addPreference(aboutWebsitePreference);
// RYD API connection statistics
diff --git a/build.gradle.kts b/build.gradle.kts
index 14233df2aa..2e8dffc6bc 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,28 +1,5 @@
-buildscript {
- repositories {
- google()
- mavenCentral()
- }
- dependencies {
- classpath("com.android.tools.build:gradle:8.0.2")
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
- }
-}
-
-allprojects {
- repositories {
- google()
- maven { url = uri("https://jitpack.io") }
- mavenCentral()
- }
-}
-
-// Tracking issue https://github.com/semantic-release/semantic-release/issues/963
-tasks.register("publish", DefaultTask::class) {
- group = "publish"
- description = "Dummy publish to pass the verification phase of the gradle-semantic-release-plugin"
-}
-
-tasks.register("clean", Delete::class) {
- delete(rootProject.buildDir)
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.android.library) apply false
+ alias(libs.plugins.kotlin) apply false
}
diff --git a/dummy/src/main/AndroidManifest.xml b/dummy/src/main/AndroidManifest.xml
deleted file mode 100644
index a5918e68ab..0000000000
--- a/dummy/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 65b50c7edf..0d118f6836 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
android.useAndroidX = true
-version = 1.3.2
+version = 1.4.0-dev.9
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000000..5bd1fbd4f4
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,18 @@
+[versions]
+agp = "8.2.2"
+annotation = "1.7.1"
+kotlin = "1.9.22"
+appcompat = "1.7.0-alpha03"
+okhttp = "5.0.0-alpha.12"
+retrofit = "2.9.0"
+
+[libraries]
+annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
+appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
+retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+android-library = { id = "com.android.library", version.ref = "agp" }
+kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 033e24c4cd..e708b1c023 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a59d94b7a1..6e3d0903f9 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
-distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dist
\ No newline at end of file
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index fcb6fca147..4f906e0c81 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/usr/bin/env sh
#
-# Copyright © 2015-2021 the original authors.
+# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,98 +17,67 @@
#
##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh Gradle
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
+##
+## Gradle start up script for UN*X
+##
##############################################################################
# Attempt to set APP_HOME
-
# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
-# This is normally unused
-# shellcheck disable=SC2034
-APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
+MAX_FD="maximum"
warn () {
echo "$*"
-} >&2
+}
die () {
echo
echo "$*"
echo
exit 1
-} >&2
+}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -118,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
+ JAVACMD="$JAVA_HOME/jre/sh/java"
else
- JAVACMD=$JAVA_HOME/bin/java
+ JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -129,120 +98,88 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD=java
- if ! command -v java >/dev/null 2>&1
- then
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
- fi
fi
# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
fi
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
+ i=`expr $i + 1`
done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
fi
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
-
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
-
-# Stop when "xargs" is not available.
-if ! command -v xargs >/dev/null 2>&1
-then
- die "xargs is not available"
-fi
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 93e3f59f13..107acd32c4 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
-@if "%DEBUG%"=="" @echo off
+@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,8 +25,7 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
+if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -41,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -76,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
+if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b06d31dfe4..61d1baa72a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,5 +1,21 @@
rootProject.name = "revanced-integrations"
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+@Suppress("UnstableApiUsage")
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
buildCache {
local {
isEnabled = "CI" !in System.getenv()
@@ -7,4 +23,4 @@ buildCache {
}
include(":app")
-include(":dummy")
+include(":stub")
diff --git a/dummy/.gitignore b/stub/.gitignore
similarity index 100%
rename from dummy/.gitignore
rename to stub/.gitignore
diff --git a/dummy/build.gradle.kts b/stub/build.gradle.kts
similarity index 78%
rename from dummy/build.gradle.kts
rename to stub/build.gradle.kts
index 60bab80733..d16c19b7a5 100644
--- a/dummy/build.gradle.kts
+++ b/stub/build.gradle.kts
@@ -1,15 +1,14 @@
plugins {
- id("com.android.library")
+ alias(libs.plugins.android.library)
}
android {
- namespace = "app.revanced.dummy"
+ namespace = "app.revanced.integrations.stub"
compileSdk = 33
- buildToolsVersion = "33.0.1"
defaultConfig {
+ multiDexEnabled = false
minSdk = 23
- targetSdk = 33
}
buildTypes {
@@ -25,4 +24,4 @@ android {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
-}
\ No newline at end of file
+}
diff --git a/dummy/proguard-rules.pro b/stub/proguard-rules.pro
similarity index 100%
rename from dummy/proguard-rules.pro
rename to stub/proguard-rules.pro
diff --git a/stub/src/main/AndroidManifest.xml b/stub/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..568741e54f
--- /dev/null
+++ b/stub/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/dummy/src/main/java/android/support/constraint/ConstraintLayout.java b/stub/src/main/java/android/support/constraint/ConstraintLayout.java
similarity index 100%
rename from dummy/src/main/java/android/support/constraint/ConstraintLayout.java
rename to stub/src/main/java/android/support/constraint/ConstraintLayout.java
diff --git a/dummy/src/main/java/android/support/v7/widget/RecyclerView.java b/stub/src/main/java/android/support/v7/widget/RecyclerView.java
similarity index 100%
rename from dummy/src/main/java/android/support/v7/widget/RecyclerView.java
rename to stub/src/main/java/android/support/v7/widget/RecyclerView.java
diff --git a/dummy/src/main/java/com/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity.java b/stub/src/main/java/com/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity.java
similarity index 100%
rename from dummy/src/main/java/com/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity.java
rename to stub/src/main/java/com/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity.java
diff --git a/dummy/src/main/java/com/google/android/apps/youtube/app/ui/SlimMetadataScrollableButtonContainerLayout.java b/stub/src/main/java/com/google/android/apps/youtube/app/ui/SlimMetadataScrollableButtonContainerLayout.java
similarity index 100%
rename from dummy/src/main/java/com/google/android/apps/youtube/app/ui/SlimMetadataScrollableButtonContainerLayout.java
rename to stub/src/main/java/com/google/android/apps/youtube/app/ui/SlimMetadataScrollableButtonContainerLayout.java
diff --git a/dummy/src/main/java/com/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar.java b/stub/src/main/java/com/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar.java
similarity index 100%
rename from dummy/src/main/java/com/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar.java
rename to stub/src/main/java/com/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar.java
diff --git a/dummy/src/main/java/com/reddit/domain/model/ILink.java b/stub/src/main/java/com/reddit/domain/model/ILink.java
similarity index 100%
rename from dummy/src/main/java/com/reddit/domain/model/ILink.java
rename to stub/src/main/java/com/reddit/domain/model/ILink.java
diff --git a/dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/Aweme.java b/stub/src/main/java/com/ss/android/ugc/aweme/feed/model/Aweme.java
similarity index 100%
rename from dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/Aweme.java
rename to stub/src/main/java/com/ss/android/ugc/aweme/feed/model/Aweme.java
diff --git a/dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/AwemeStatistics.java b/stub/src/main/java/com/ss/android/ugc/aweme/feed/model/AwemeStatistics.java
similarity index 100%
rename from dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/AwemeStatistics.java
rename to stub/src/main/java/com/ss/android/ugc/aweme/feed/model/AwemeStatistics.java
diff --git a/dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/FeedItemList.java b/stub/src/main/java/com/ss/android/ugc/aweme/feed/model/FeedItemList.java
similarity index 100%
rename from dummy/src/main/java/com/ss/android/ugc/aweme/feed/model/FeedItemList.java
rename to stub/src/main/java/com/ss/android/ugc/aweme/feed/model/FeedItemList.java
diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java b/stub/src/main/java/com/tumblr/rumblr/model/TimelineObject.java
similarity index 100%
rename from dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java
rename to stub/src/main/java/com/tumblr/rumblr/model/TimelineObject.java
diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java b/stub/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java
similarity index 100%
rename from dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java
rename to stub/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java
diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java b/stub/src/main/java/com/tumblr/rumblr/model/Timelineable.java
similarity index 100%
rename from dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java
rename to stub/src/main/java/com/tumblr/rumblr/model/Timelineable.java
diff --git a/dummy/src/main/java/org/chromium/net/UrlRequest.java b/stub/src/main/java/org/chromium/net/UrlRequest.java
similarity index 100%
rename from dummy/src/main/java/org/chromium/net/UrlRequest.java
rename to stub/src/main/java/org/chromium/net/UrlRequest.java
diff --git a/dummy/src/main/java/org/chromium/net/UrlResponseInfo.java b/stub/src/main/java/org/chromium/net/UrlResponseInfo.java
similarity index 100%
rename from dummy/src/main/java/org/chromium/net/UrlResponseInfo.java
rename to stub/src/main/java/org/chromium/net/UrlResponseInfo.java
diff --git a/dummy/src/main/java/org/chromium/net/impl/CronetUrlRequest.java b/stub/src/main/java/org/chromium/net/impl/CronetUrlRequest.java
similarity index 100%
rename from dummy/src/main/java/org/chromium/net/impl/CronetUrlRequest.java
rename to stub/src/main/java/org/chromium/net/impl/CronetUrlRequest.java
diff --git a/dummy/src/main/java/tv/twitch/android/feature/settings/menu/SettingsMenuGroup.java b/stub/src/main/java/tv/twitch/android/feature/settings/menu/SettingsMenuGroup.java
similarity index 100%
rename from dummy/src/main/java/tv/twitch/android/feature/settings/menu/SettingsMenuGroup.java
rename to stub/src/main/java/tv/twitch/android/feature/settings/menu/SettingsMenuGroup.java
diff --git a/dummy/src/main/java/tv/twitch/android/settings/SettingsActivity.java b/stub/src/main/java/tv/twitch/android/settings/SettingsActivity.java
similarity index 100%
rename from dummy/src/main/java/tv/twitch/android/settings/SettingsActivity.java
rename to stub/src/main/java/tv/twitch/android/settings/SettingsActivity.java
diff --git a/dummy/src/main/java/tv/twitch/android/shared/chat/util/ClickableUsernameSpan.java b/stub/src/main/java/tv/twitch/android/shared/chat/util/ClickableUsernameSpan.java
similarity index 100%
rename from dummy/src/main/java/tv/twitch/android/shared/chat/util/ClickableUsernameSpan.java
rename to stub/src/main/java/tv/twitch/android/shared/chat/util/ClickableUsernameSpan.java