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 c2aa2f6b..f92c9cfd 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java @@ -40,7 +40,7 @@ import kotlin.text.Regex; public class Utils { @SuppressLint("StaticFieldLeak") - public static Context context; + private static Context context; private static String versionName; @@ -233,6 +233,11 @@ public class Utils { return context; } + public static void setContext(Context appContext) { + context = appContext; + Logger.printDebug(() -> "Set context: " + appContext); // Cannot log before context is set. + } + public static void setClipboard(@NonNull String text) { android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData.newPlainText("ReVanced", text); diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/DownloadsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/DownloadsPatch.java index 7147284d..9904ff75 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/DownloadsPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/DownloadsPatch.java @@ -1,27 +1,84 @@ package app.revanced.integrations.youtube.patches; +import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import java.lang.ref.WeakReference; + import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.StringRef; import app.revanced.integrations.shared.Utils; +import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch; import app.revanced.integrations.youtube.settings.Settings; +@SuppressWarnings("unused") public final class DownloadsPatch { - public static boolean inAppDownloadButtonOnClick() { - if (!Settings.USE_IN_APP_DOWNLOAD_BUTTON.get()) - return false; - launchExternalDownloader(); - return true; + private static WeakReference activityRef = new WeakReference<>(null); + + /** + * Injection point. + */ + public static void activityCreated(Activity mainActivity) { + activityRef = new WeakReference<>(mainActivity); } - public static void launchExternalDownloader() { - Logger.printDebug(() -> "Launching external downloader"); + /** + * Injection point. + * + * Call if download playlist is pressed, or if download button is used + * for old spoofed version (both playlists and the player action button). + * + * Downloading playlists is not supported yet, + * as the hooked code does not easily expose the playlist id. + */ + public static boolean inAppDownloadPlaylistLegacyOnClick(@Nullable String videoId) { + if (videoId == null || videoId.isEmpty()) { + // videoId is null or empty if download playlist is pressed. + Logger.printDebug(() -> "Ignoring playlist download button press"); + return false; + } + return inAppDownloadButtonOnClick(); + } - final var context = Utils.getContext(); + /** + * Injection point. + */ + public static boolean inAppDownloadButtonOnClick() { + try { + if (!Settings.EXTERNAL_DOWNLOADER_ACTION_BUTTON.get()) { + return false; + } + + // If possible, use the main activity as the context. + // Otherwise fall back on using the application context. + Context context = activityRef.get(); + boolean isActivityContext = true; + if (context == null) { + // Utils context is the application context, and not an activity context. + context = Utils.getContext(); + isActivityContext = false; + } + + launchExternalDownloader(context, isActivityContext); + return true; + } catch (Exception ex) { + Logger.printException(() -> "inAppDownloadButtonOnClick failure", ex); + } + return false; + } + + /** + * @param isActivityContext If the context parameter is for an Activity. If this is false, then + * the downloader is opened as a new task (which forces YT to minimize). + */ + public static void launchExternalDownloader(@NonNull Context context, boolean isActivityContext) { + Logger.printDebug(() -> "Launching external downloader with context: " + context); // Trim string to avoid any accidental whitespace. var downloaderPackageName = Settings.EXTERNAL_DOWNLOADER_PACKAGE_NAME.get().trim(); @@ -47,11 +104,13 @@ public final class DownloadsPatch { intent.setType("text/plain"); intent.setPackage(downloaderPackageName); intent.putExtra("android.intent.extra.TEXT", content); + if (!isActivityContext) { + Logger.printDebug(() -> "Using new task intent"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } context.startActivity(intent); - - Logger.printDebug(() -> "Launched the intent with the content: " + content); } catch (Exception error) { - Logger.printException(() -> "Failed to launch the intent: " + error, error); + Logger.printException(() -> "Failed to launch intent: " + error, error); } } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java index fe9e57c0..bd6d89fa 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/HideBreakingNewsPatch.java @@ -16,7 +16,7 @@ public class HideBreakingNewsPatch { * Breaking news does not appear to be present in these older versions anyways. */ private static final boolean isSpoofingOldVersionWithHorizontalCardListWatchHistory = - SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("17.31.00"); + SpoofAppVersionPatch.isSpoofingToLessThan("18.01.00"); /** * Injection point. diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java index 7070d8a5..32732cdc 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/PlayerOverlaysHookPatch.java @@ -6,24 +6,12 @@ import androidx.annotation.Nullable; import app.revanced.integrations.youtube.shared.PlayerOverlays; -/** - * Hook receiver class for 'player-overlays-hook' patch - * - * @usedBy app.revanced.patches.youtube.misc.playeroverlay.patch.PlayerOverlaysHookPatch - * @smali Lapp/revanced/integrations/patches/PlayerOverlaysHookPatch; - */ @SuppressWarnings("unused") public class PlayerOverlaysHookPatch { /** * Injection point. - * - * @param thisRef reference to the view - * @smali YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava / lang / Object ;)V */ - public static void YouTubePlayerOverlaysLayout_onFinishInflateHook(@Nullable Object thisRef) { - if (thisRef == null) return; - if (thisRef instanceof ViewGroup) { - PlayerOverlays.attach((ViewGroup) thisRef); - } + public static void playerOverlayInflated(ViewGroup group) { + PlayerOverlays.attach(group); } } \ No newline at end of file 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 0cb687f6..4938fb37 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 @@ -46,7 +46,7 @@ import static app.revanced.integrations.youtube.returnyoutubedislike.ReturnYouTu public class ReturnYouTubeDislikePatch { public static final boolean IS_SPOOFING_TO_NON_LITHO_SHORTS_PLAYER = - SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.33.40"); + SpoofAppVersionPatch.isSpoofingToLessThan("18.34.00"); /** * RYD data for the current video on screen. 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 93219797..3f9f850b 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,26 +1,12 @@ 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; - 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(); - } + 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(); /** * Injection point @@ -30,8 +16,8 @@ public class SpoofAppVersionPatch { return version; } - public static boolean isSpoofingToEqualOrLessThan(String version) { - return SPOOF_APP_VERSION_ENABLED && SPOOF_APP_VERSION_TARGET.compareTo(version) <= 0; + public static boolean isSpoofingToLessThan(String version) { + return SPOOF_APP_VERSION_ENABLED && SPOOF_APP_VERSION_TARGET.compareTo(version) < 0; } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java index 7e7fe68a..bfff1b15 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/youtube/returnyoutubedislike/ReturnYouTubeDislike.java @@ -91,7 +91,7 @@ public class ReturnYouTubeDislike { private static final char MIDDLE_SEPARATOR_CHARACTER = '◎'; // 'bullseye' private static final boolean IS_SPOOFING_TO_OLD_SEPARATOR_COLOR - = SpoofAppVersionPatch.isSpoofingToEqualOrLessThan("18.09.39"); + = SpoofAppVersionPatch.isSpoofingToLessThan("18.10.00"); /** * Cached lookup of all video ids. 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 2ed879db..6122e8af 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 @@ -1,7 +1,9 @@ package app.revanced.integrations.youtube.settings; +import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.settings.*; import app.revanced.integrations.shared.settings.preference.SharedPrefCategory; +import app.revanced.integrations.youtube.patches.spoof.SpoofAppVersionPatch; import app.revanced.integrations.youtube.sponsorblock.SponsorBlockSettings; import java.util.Arrays; @@ -16,9 +18,9 @@ import static java.lang.Boolean.TRUE; public class Settings extends BaseSettings { // External downloader public static final BooleanSetting EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_external_downloader", FALSE); + public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action_button", FALSE); public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_name", - "org.schabi.newpipe" /* NewPipe */, parent(EXTERNAL_DOWNLOADER)); - public static final BooleanSetting USE_IN_APP_DOWNLOAD_BUTTON = new BooleanSetting("revanced_use_in_app_download_button", TRUE); + "org.schabi.newpipe" /* NewPipe */, parentsAny(EXTERNAL_DOWNLOADER, EXTERNAL_DOWNLOADER_ACTION_BUTTON)); // Copy video URL public static final BooleanSetting COPY_VIDEO_URL = new BooleanSetting("revanced_copy_video_url", FALSE); @@ -335,6 +337,14 @@ public class Settings extends BaseSettings { // and more time should be given for users who rarely upgrade. migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID); + + // Old spoof versions that no longer work reliably. + if (SpoofAppVersionPatch.isSpoofingToLessThan("17.33.00")) { + Logger.printInfo(() -> "Resetting spoof app version target"); + Settings.SPOOF_APP_VERSION_TARGET.resetToDefault(); + } + + // endregion } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java index 5542d61a..1f3bd6c0 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/preference/ReVancedPreferenceFragment.java @@ -1,8 +1,15 @@ package app.revanced.integrations.youtube.settings.preference; +import android.os.Build; import android.preference.ListPreference; import android.preference.Preference; +import android.preference.PreferenceGroup; + +import androidx.annotation.RequiresApi; + +import app.revanced.integrations.shared.Logger; import app.revanced.integrations.shared.settings.preference.AbstractPreferenceFragment; +import app.revanced.integrations.youtube.patches.DownloadsPatch; import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSpeedPatch; import app.revanced.integrations.youtube.settings.Settings; @@ -12,14 +19,20 @@ import app.revanced.integrations.youtube.settings.Settings; * @noinspection deprecation */ public class ReVancedPreferenceFragment extends AbstractPreferenceFragment { + + @RequiresApi(api = Build.VERSION_CODES.O) @Override protected void initialize() { super.initialize(); - // If the preference was included, then initialize it based on the available playback speed - Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key); - if (defaultSpeedPreference instanceof ListPreference) { - CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); + try { + // If the preference was included, then initialize it based on the available playback speed. + Preference defaultSpeedPreference = findPreference(Settings.PLAYBACK_SPEED_DEFAULT.key); + if (defaultSpeedPreference instanceof ListPreference) { + CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference); + } + } catch (Exception ex) { + Logger.printException(() -> "initialize failure", ex); } } } diff --git a/app/src/main/java/app/revanced/integrations/youtube/videoplayer/ExternalDownloadButton.java b/app/src/main/java/app/revanced/integrations/youtube/videoplayer/ExternalDownloadButton.java index a02c2023..378cde3e 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/videoplayer/ExternalDownloadButton.java +++ b/app/src/main/java/app/revanced/integrations/youtube/videoplayer/ExternalDownloadButton.java @@ -5,10 +5,9 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; -import app.revanced.integrations.youtube.patches.DownloadsPatch; -import app.revanced.integrations.youtube.patches.VideoInformation; -import app.revanced.integrations.youtube.settings.Settings; import app.revanced.integrations.shared.Logger; +import app.revanced.integrations.youtube.patches.DownloadsPatch; +import app.revanced.integrations.youtube.settings.Settings; @SuppressWarnings("unused") public class ExternalDownloadButton extends BottomControlButton { @@ -44,7 +43,7 @@ public class ExternalDownloadButton extends BottomControlButton { } private static void onDownloadClick(View view) { - DownloadsPatch.launchExternalDownloader(); + DownloadsPatch.launchExternalDownloader(view.getContext(), true); } }