mirror of
https://github.com/revanced/revanced-integrations.git
synced 2025-01-06 01:55:50 +01:00
chore: Merge branch dev
to main
(#700)
This commit is contained in:
commit
9b570824db
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,3 +1,31 @@
|
|||||||
|
# [1.15.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.15.0-dev.1...v1.15.0-dev.2) (2024-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Hide Shorts components:** Add `Hide save music`, `Hide stickers` ([#703](https://github.com/ReVanced/revanced-integrations/issues/703)) ([a87456e](https://github.com/ReVanced/revanced-integrations/commit/a87456e49995e2ed5f4788e71db8f2387bc241f9))
|
||||||
|
|
||||||
|
# [1.15.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.14.3-dev.2...v1.15.0-dev.1) (2024-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **YouTube - Disable precise seeking gesture:** Hide "pull up" label that shows up when swiping ([#696](https://github.com/ReVanced/revanced-integrations/issues/696)) ([0b9afd0](https://github.com/ReVanced/revanced-integrations/commit/0b9afd022dbf622478bb931124ac41a969610c64))
|
||||||
|
|
||||||
|
## [1.14.3-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.14.3-dev.1...v1.14.3-dev.2) (2024-09-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Check watch history domain name resolution:** Do not show warning if network connection is flaky ([#702](https://github.com/ReVanced/revanced-integrations/issues/702)) ([80482df](https://github.com/ReVanced/revanced-integrations/commit/80482df3fae05cd5bd9e3b430022f07cf118565c))
|
||||||
|
|
||||||
|
## [1.14.3-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.14.2...v1.14.3-dev.1) (2024-09-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube:** Show video chapter titles without clipping when overlay buttons are enabled ([#699](https://github.com/ReVanced/revanced-integrations/issues/699)) ([325cc17](https://github.com/ReVanced/revanced-integrations/commit/325cc179001bb79366f4ed6a5f84f717fbff66b6))
|
||||||
|
|
||||||
## [1.14.2](https://github.com/ReVanced/revanced-integrations/compare/v1.14.1...v1.14.2) (2024-09-23)
|
## [1.14.2](https://github.com/ReVanced/revanced-integrations/compare/v1.14.1...v1.14.2) (2024-09-23)
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,10 +386,10 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ignore this class. It must be public to satisfy Android requirement.
|
* Ignore this class. It must be public to satisfy Android requirements.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static class DialogFragmentWrapper extends DialogFragment {
|
public static final class DialogFragmentWrapper extends DialogFragment {
|
||||||
|
|
||||||
private Dialog dialog;
|
private Dialog dialog;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -20,7 +20,6 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
|
|||||||
private static final String SINKHOLE_IPV4 = "0.0.0.0";
|
private static final String SINKHOLE_IPV4 = "0.0.0.0";
|
||||||
private static final String SINKHOLE_IPV6 = "::";
|
private static final String SINKHOLE_IPV6 = "::";
|
||||||
|
|
||||||
/** @noinspection SameParameterValue */
|
|
||||||
private static boolean domainResolvesToValidIP(String host) {
|
private static boolean domainResolvesToValidIP(String host) {
|
||||||
try {
|
try {
|
||||||
InetAddress address = InetAddress.getByName(host);
|
InetAddress address = InetAddress.getByName(host);
|
||||||
@ -50,7 +49,16 @@ public class CheckWatchHistoryDomainNameResolutionPatch {
|
|||||||
|
|
||||||
Utils.runOnBackgroundThread(() -> {
|
Utils.runOnBackgroundThread(() -> {
|
||||||
try {
|
try {
|
||||||
if (domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)) {
|
// If the user has a flaky DNS server, or they just lost internet connectivity
|
||||||
|
// and the isNetworkConnected() check has not detected it yet (it can take a few
|
||||||
|
// seconds after losing connection), then the history tracking endpoint will
|
||||||
|
// show a resolving error but it's actually an internet connection problem.
|
||||||
|
//
|
||||||
|
// Prevent this false positive by verify youtube.com resolves.
|
||||||
|
// If youtube.com does not resolve, then it's not a watch history domain resolving error
|
||||||
|
// because the entire app will not work since no domains are resolving.
|
||||||
|
if (domainResolvesToValidIP(HISTORY_TRACKING_ENDPOINT)
|
||||||
|
|| !domainResolvesToValidIP("youtube.com")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
package app.revanced.integrations.youtube.patches;
|
package app.revanced.integrations.youtube.patches;
|
||||||
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.VelocityTracker;
|
|
||||||
|
|
||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class DisablePreciseSeekingGesturePatch {
|
public final class DisablePreciseSeekingGesturePatch {
|
||||||
/**
|
public static boolean isGestureDisabled() {
|
||||||
* Disables the gesture that is used to seek precisely.
|
return Settings.DISABLE_PRECISE_SEEKING_GESTURE.get();
|
||||||
* @param tracker The velocity tracker that is used to determine the gesture.
|
|
||||||
* @param event The motion event that is used to determine the gesture.
|
|
||||||
*/
|
|
||||||
public static void disableGesture(VelocityTracker tracker, MotionEvent event) {
|
|
||||||
if (Settings.DISABLE_PRECISE_SEEKING_GESTURE.get()) return;
|
|
||||||
|
|
||||||
tracker.addMovement(event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package app.revanced.integrations.youtube.patches;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import app.revanced.integrations.shared.Logger;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class PlayerControlsPatch {
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static void setFullscreenCloseButton(ImageView imageButton) {
|
||||||
|
// Add a global listener, since the protected method
|
||||||
|
// View#onVisibilityChanged() does not have any call backs.
|
||||||
|
imageButton.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
|
int lastVisibility = View.VISIBLE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGlobalLayout() {
|
||||||
|
try {
|
||||||
|
final int visibility = imageButton.getVisibility();
|
||||||
|
if (lastVisibility != visibility) {
|
||||||
|
lastVisibility = visibility;
|
||||||
|
|
||||||
|
Logger.printDebug(() -> "fullscreen button visibility: "
|
||||||
|
+ (visibility == View.VISIBLE ? "VISIBLE" :
|
||||||
|
visibility == View.GONE ? "GONE" : "INVISIBLE"));
|
||||||
|
|
||||||
|
fullscreenButtonVisibilityChanged(visibility == View.VISIBLE);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printDebug(() -> "OnGlobalLayoutListener failure", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// noinspection EmptyMethod
|
||||||
|
public static void fullscreenButtonVisibilityChanged(boolean isVisible) {
|
||||||
|
// Code added during patching.
|
||||||
|
}
|
||||||
|
}
|
@ -145,10 +145,8 @@ public final class LayoutComponentsFilter extends Filter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// The player audio track button does the exact same function as the audio track flyout menu option.
|
// The player audio track button does the exact same function as the audio track flyout menu option.
|
||||||
// But if the copy url button is shown, these button clashes and the the audio button does not work.
|
|
||||||
// Previously this was a setting to show/hide the player button.
|
// Previously this was a setting to show/hide the player button.
|
||||||
// But it was decided it's simpler to always hide this button because:
|
// But it was decided it's simpler to always hide this button because:
|
||||||
// - it doesn't work with copy video url feature
|
|
||||||
// - the button is rare
|
// - the button is rare
|
||||||
// - always hiding makes the ReVanced settings simpler and easier to understand
|
// - always hiding makes the ReVanced settings simpler and easier to understand
|
||||||
// - nobody is going to notice the redundant button is always hidden
|
// - nobody is going to notice the redundant button is always hidden
|
||||||
|
@ -112,6 +112,11 @@ public final class ShortsFilter extends Filter {
|
|||||||
"shorts_info_panel_overview"
|
"shorts_info_panel_overview"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
StringFilterGroup stickers = new StringFilterGroup(
|
||||||
|
Settings.HIDE_SHORTS_STICKERS,
|
||||||
|
"stickers_layer.eml"
|
||||||
|
);
|
||||||
|
|
||||||
joinButton = new StringFilterGroup(
|
joinButton = new StringFilterGroup(
|
||||||
Settings.HIDE_SHORTS_JOIN_BUTTON,
|
Settings.HIDE_SHORTS_JOIN_BUTTON,
|
||||||
"sponsor_button"
|
"sponsor_button"
|
||||||
@ -140,7 +145,7 @@ public final class ShortsFilter extends Filter {
|
|||||||
addPathCallbacks(
|
addPathCallbacks(
|
||||||
shortsCompactFeedVideoPath, suggestedAction, actionBar, joinButton, subscribeButton,
|
shortsCompactFeedVideoPath, suggestedAction, actionBar, joinButton, subscribeButton,
|
||||||
paidPromotionButton, pausedOverlayButtons, channelBar, fullVideoLinkLabel, videoTitle,
|
paidPromotionButton, pausedOverlayButtons, channelBar, fullVideoLinkLabel, videoTitle,
|
||||||
reelSoundMetadata, soundButton, infoPanel
|
reelSoundMetadata, soundButton, infoPanel, stickers
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -193,7 +198,13 @@ public final class ShortsFilter extends Filter {
|
|||||||
),
|
),
|
||||||
new ByteArrayFilterGroup(
|
new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_SHORTS_SAVE_SOUND_BUTTON,
|
Settings.HIDE_SHORTS_SAVE_SOUND_BUTTON,
|
||||||
"yt_outline_list_add_"
|
"yt_outline_bookmark_",
|
||||||
|
// 'Save sound' button. It seems this has been removed and only 'Save music' is used.
|
||||||
|
// Still hide this in case it's still present.
|
||||||
|
"yt_outline_list_add_",
|
||||||
|
// 'Use this sound' button. It seems this has been removed and only 'Save music' is used.
|
||||||
|
// Still hide this in case it's still present.
|
||||||
|
"yt_outline_camera_"
|
||||||
),
|
),
|
||||||
new ByteArrayFilterGroup(
|
new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS,
|
Settings.HIDE_SHORTS_SEARCH_SUGGESTIONS,
|
||||||
@ -202,10 +213,6 @@ public final class ShortsFilter extends Filter {
|
|||||||
new ByteArrayFilterGroup(
|
new ByteArrayFilterGroup(
|
||||||
Settings.HIDE_SHORTS_SUPER_THANKS_BUTTON,
|
Settings.HIDE_SHORTS_SUPER_THANKS_BUTTON,
|
||||||
"yt_outline_dollar_sign_heart_"
|
"yt_outline_dollar_sign_heart_"
|
||||||
),
|
|
||||||
new ByteArrayFilterGroup(
|
|
||||||
Settings.HIDE_SHORTS_USE_THIS_SOUND_BUTTON,
|
|
||||||
"yt_outline_camera_"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -219,10 +219,9 @@ public class Settings extends BaseSettings {
|
|||||||
public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SHOP_BUTTON = new BooleanSetting("revanced_hide_shorts_shop_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_TAGGED_PRODUCTS = new BooleanSetting("revanced_hide_shorts_tagged_products", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_LOCATION_LABEL = new BooleanSetting("revanced_hide_shorts_location_label", FALSE);
|
||||||
// Save sound to playlist and Search suggestions may have been A/B tests that were abandoned by YT, and it's not clear if these are still used.
|
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SAVE_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_save_sound_button", FALSE);
|
|
||||||
public static final BooleanSetting HIDE_SHORTS_USE_THIS_SOUND_BUTTON = new BooleanSetting("revanced_hide_shorts_use_this_sound_button", TRUE);
|
|
||||||
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_SEARCH_SUGGESTIONS = new BooleanSetting("revanced_hide_shorts_search_suggestions", FALSE);
|
||||||
|
public static final BooleanSetting HIDE_SHORTS_STICKERS = new BooleanSetting("revanced_hide_shorts_stickers", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE);
|
public static final BooleanSetting HIDE_SHORTS_SUPER_THANKS_BUTTON = new BooleanSetting("revanced_hide_shorts_super_thanks_button", TRUE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_LIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_like_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_LIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_like_button", FALSE);
|
||||||
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
|
public static final BooleanSetting HIDE_SHORTS_DISLIKE_BUTTON = new BooleanSetting("revanced_hide_shorts_dislike_button", FALSE);
|
||||||
|
@ -12,8 +12,9 @@ import app.revanced.integrations.youtube.patches.VideoInformation;
|
|||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
import app.revanced.integrations.shared.Utils;
|
import app.revanced.integrations.shared.Utils;
|
||||||
import app.revanced.integrations.youtube.videoplayer.BottomControlButton;
|
import app.revanced.integrations.youtube.videoplayer.PlayerControlButton;
|
||||||
|
|
||||||
|
// Edit: This should be a subclass of PlayerControlButton
|
||||||
public class CreateSegmentButtonController {
|
public class CreateSegmentButtonController {
|
||||||
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
||||||
private static boolean isShowing;
|
private static boolean isShowing;
|
||||||
@ -27,9 +28,7 @@ public class CreateSegmentButtonController {
|
|||||||
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
||||||
getResourceIdentifier("revanced_sb_create_segment_button", "id")));
|
getResourceIdentifier("revanced_sb_create_segment_button", "id")));
|
||||||
imageView.setVisibility(View.GONE);
|
imageView.setVisibility(View.GONE);
|
||||||
imageView.setOnClickListener(v -> {
|
imageView.setOnClickListener(v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility());
|
||||||
SponsorBlockViewController.toggleNewSegmentLayoutVisibility();
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonReference = new WeakReference<>(imageView);
|
buttonReference = new WeakReference<>(imageView);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -37,25 +36,30 @@ public class CreateSegmentButtonController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
changeVisibility(visible, true);
|
if (visible) {
|
||||||
|
// Fix button flickering, by pushing this call to the back of
|
||||||
|
// the main thread and letting other layout code run first.
|
||||||
|
Utils.runOnMainThread(() -> setVisibility(true, false));
|
||||||
|
} else {
|
||||||
|
setVisibility(false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityNegatedImmediate(boolean visible) {
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
changeVisibility(!visible, true);
|
// Ignore this call, otherwise with full screen thumbnails the buttons are visible while seeking.
|
||||||
|
if (visible && !animated) return;
|
||||||
|
|
||||||
|
setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static void setVisibility(boolean visible, boolean animated) {
|
||||||
* injection point
|
|
||||||
*/
|
|
||||||
public static void changeVisibility(boolean visible) {
|
|
||||||
changeVisibility(visible, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void changeVisibility(boolean visible, boolean immediate) {
|
|
||||||
try {
|
try {
|
||||||
if (isShowing == visible) return;
|
if (isShowing == visible) return;
|
||||||
isShowing = visible;
|
isShowing = visible;
|
||||||
@ -68,8 +72,8 @@ public class CreateSegmentButtonController {
|
|||||||
if (!shouldBeShown()) {
|
if (!shouldBeShown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!immediate) {
|
if (animated) {
|
||||||
iView.startAnimation(BottomControlButton.getButtonFadeIn());
|
iView.startAnimation(PlayerControlButton.getButtonFadeIn());
|
||||||
}
|
}
|
||||||
iView.setVisibility(View.VISIBLE);
|
iView.setVisibility(View.VISIBLE);
|
||||||
return;
|
return;
|
||||||
@ -77,8 +81,8 @@ public class CreateSegmentButtonController {
|
|||||||
|
|
||||||
if (iView.getVisibility() == View.VISIBLE) {
|
if (iView.getVisibility() == View.VISIBLE) {
|
||||||
iView.clearAnimation();
|
iView.clearAnimation();
|
||||||
if (!immediate) {
|
if (animated) {
|
||||||
iView.startAnimation(BottomControlButton.getButtonFadeOut());
|
iView.startAnimation(PlayerControlButton.getButtonFadeOut());
|
||||||
}
|
}
|
||||||
iView.setVisibility(View.GONE);
|
iView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,9 @@ import app.revanced.integrations.youtube.sponsorblock.SegmentPlaybackController;
|
|||||||
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockUtils;
|
import app.revanced.integrations.youtube.sponsorblock.SponsorBlockUtils;
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
import app.revanced.integrations.shared.Utils;
|
import app.revanced.integrations.shared.Utils;
|
||||||
import app.revanced.integrations.youtube.videoplayer.BottomControlButton;
|
import app.revanced.integrations.youtube.videoplayer.PlayerControlButton;
|
||||||
|
|
||||||
|
// Edit: This should be a subclass of PlayerControlButton
|
||||||
public class VotingButtonController {
|
public class VotingButtonController {
|
||||||
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
private static WeakReference<ImageView> buttonReference = new WeakReference<>(null);
|
||||||
private static boolean isShowing;
|
private static boolean isShowing;
|
||||||
@ -29,35 +30,41 @@ public class VotingButtonController {
|
|||||||
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
ImageView imageView = Objects.requireNonNull(youtubeControlsLayout.findViewById(
|
||||||
getResourceIdentifier("revanced_sb_voting_button", "id")));
|
getResourceIdentifier("revanced_sb_voting_button", "id")));
|
||||||
imageView.setVisibility(View.GONE);
|
imageView.setVisibility(View.GONE);
|
||||||
imageView.setOnClickListener(v -> {
|
imageView.setOnClickListener(v -> SponsorBlockUtils.onVotingClicked(v.getContext()));
|
||||||
SponsorBlockUtils.onVotingClicked(v.getContext());
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonReference = new WeakReference<>(imageView);
|
buttonReference = new WeakReference<>(imageView);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "Unable to set RelativeLayout", ex);
|
Logger.printException(() -> "initialize failure", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
changeVisibility(visible, true);
|
if (visible) {
|
||||||
|
// Fix button flickering, by pushing this call to the back of
|
||||||
|
// the main thread and letting other layout code run first.
|
||||||
|
Utils.runOnMainThread(() -> setVisibility(true, false));
|
||||||
|
} else {
|
||||||
|
setVisibility(false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityNegatedImmediate(boolean visible) {
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
changeVisibility(!visible, true);
|
// Ignore this call, otherwise with full screen thumbnails the buttons are visible while seeking.
|
||||||
|
if (visible && !animated) return;
|
||||||
|
|
||||||
|
setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible) {
|
private static void setVisibility(boolean visible, boolean animated) {
|
||||||
changeVisibility(visible, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void changeVisibility(boolean visible, boolean immediate) {
|
|
||||||
try {
|
try {
|
||||||
if (isShowing == visible) return;
|
if (isShowing == visible) return;
|
||||||
isShowing = visible;
|
isShowing = visible;
|
||||||
@ -70,8 +77,8 @@ public class VotingButtonController {
|
|||||||
if (!shouldBeShown()) {
|
if (!shouldBeShown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!immediate) {
|
if (animated) {
|
||||||
iView.startAnimation(BottomControlButton.getButtonFadeIn());
|
iView.startAnimation(PlayerControlButton.getButtonFadeIn());
|
||||||
}
|
}
|
||||||
iView.setVisibility(View.VISIBLE);
|
iView.setVisibility(View.VISIBLE);
|
||||||
return;
|
return;
|
||||||
@ -79,8 +86,8 @@ public class VotingButtonController {
|
|||||||
|
|
||||||
if (iView.getVisibility() == View.VISIBLE) {
|
if (iView.getVisibility() == View.VISIBLE) {
|
||||||
iView.clearAnimation();
|
iView.clearAnimation();
|
||||||
if (!immediate) {
|
if (animated) {
|
||||||
iView.startAnimation(BottomControlButton.getButtonFadeOut());
|
iView.startAnimation(PlayerControlButton.getButtonFadeOut());
|
||||||
}
|
}
|
||||||
iView.setVisibility(View.GONE);
|
iView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
package app.revanced.integrations.youtube.videoplayer;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import app.revanced.integrations.shared.Logger;
|
|
||||||
import app.revanced.integrations.shared.Utils;
|
|
||||||
import app.revanced.integrations.shared.settings.BooleanSetting;
|
|
||||||
|
|
||||||
public abstract class BottomControlButton {
|
|
||||||
private static final Animation fadeIn;
|
|
||||||
private static final Animation fadeOut;
|
|
||||||
|
|
||||||
private final WeakReference<ImageView> buttonRef;
|
|
||||||
private final BooleanSetting setting;
|
|
||||||
protected boolean isVisible;
|
|
||||||
|
|
||||||
static {
|
|
||||||
// TODO: check if these durations are correct.
|
|
||||||
fadeIn = Utils.getResourceAnimation("fade_in");
|
|
||||||
fadeIn.setDuration(Utils.getResourceInteger("fade_duration_fast"));
|
|
||||||
|
|
||||||
fadeOut = Utils.getResourceAnimation("fade_out");
|
|
||||||
fadeOut.setDuration(Utils.getResourceInteger("fade_duration_scheduled"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static Animation getButtonFadeIn() {
|
|
||||||
return fadeIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static Animation getButtonFadeOut() {
|
|
||||||
return fadeOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BottomControlButton(@NonNull ViewGroup bottomControlsViewGroup, @NonNull String imageViewButtonId,
|
|
||||||
@NonNull BooleanSetting booleanSetting, @NonNull View.OnClickListener onClickListener,
|
|
||||||
@Nullable View.OnLongClickListener longClickListener) {
|
|
||||||
Logger.printDebug(() -> "Initializing button: " + imageViewButtonId);
|
|
||||||
|
|
||||||
setting = booleanSetting;
|
|
||||||
|
|
||||||
// Create the button.
|
|
||||||
ImageView imageView = Objects.requireNonNull(bottomControlsViewGroup.findViewById(
|
|
||||||
Utils.getResourceIdentifier(imageViewButtonId, "id")
|
|
||||||
));
|
|
||||||
imageView.setOnClickListener(onClickListener);
|
|
||||||
if (longClickListener != null) {
|
|
||||||
imageView.setOnLongClickListener(longClickListener);
|
|
||||||
}
|
|
||||||
imageView.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
buttonRef = new WeakReference<>(imageView);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVisibility(boolean visible) {
|
|
||||||
if (isVisible == visible) return;
|
|
||||||
isVisible = visible;
|
|
||||||
|
|
||||||
ImageView imageView = buttonRef.get();
|
|
||||||
if (imageView == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
imageView.clearAnimation();
|
|
||||||
if (visible && setting.get()) {
|
|
||||||
imageView.startAnimation(fadeIn);
|
|
||||||
imageView.setVisibility(View.VISIBLE);
|
|
||||||
} else if (imageView.getVisibility() == View.VISIBLE) {
|
|
||||||
imageView.startAnimation(fadeOut);
|
|
||||||
imageView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,8 @@ import app.revanced.integrations.youtube.patches.CopyVideoUrlPatch;
|
|||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
|
|
||||||
public class CopyVideoUrlButton extends BottomControlButton {
|
@SuppressWarnings("unused")
|
||||||
|
public class CopyVideoUrlButton extends PlayerControlButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CopyVideoUrlButton instance;
|
private static CopyVideoUrlButton instance;
|
||||||
|
|
||||||
@ -38,9 +39,16 @@ public class CopyVideoUrlButton extends BottomControlButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,8 @@ import app.revanced.integrations.youtube.patches.CopyVideoUrlPatch;
|
|||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
|
|
||||||
public class CopyVideoUrlTimestampButton extends BottomControlButton {
|
@SuppressWarnings("unused")
|
||||||
|
public class CopyVideoUrlTimestampButton extends PlayerControlButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CopyVideoUrlTimestampButton instance;
|
private static CopyVideoUrlTimestampButton instance;
|
||||||
|
|
||||||
@ -38,10 +39,16 @@ public class CopyVideoUrlTimestampButton extends BottomControlButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ import app.revanced.integrations.youtube.patches.VideoInformation;
|
|||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class ExternalDownloadButton extends BottomControlButton {
|
public class ExternalDownloadButton extends PlayerControlButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static ExternalDownloadButton instance;
|
private static ExternalDownloadButton instance;
|
||||||
|
|
||||||
@ -37,10 +37,17 @@ public class ExternalDownloadButton extends BottomControlButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onDownloadClick(View view) {
|
private static void onDownloadClick(View view) {
|
||||||
|
@ -9,7 +9,8 @@ import app.revanced.integrations.youtube.patches.playback.speed.CustomPlaybackSp
|
|||||||
import app.revanced.integrations.youtube.settings.Settings;
|
import app.revanced.integrations.youtube.settings.Settings;
|
||||||
import app.revanced.integrations.shared.Logger;
|
import app.revanced.integrations.shared.Logger;
|
||||||
|
|
||||||
public class PlaybackSpeedDialogButton extends BottomControlButton {
|
@SuppressWarnings("unused")
|
||||||
|
public class PlaybackSpeedDialogButton extends PlayerControlButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static PlaybackSpeedDialogButton instance;
|
private static PlaybackSpeedDialogButton instance;
|
||||||
|
|
||||||
@ -35,9 +36,16 @@ public class PlaybackSpeedDialogButton extends BottomControlButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean showing) {
|
public static void changeVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibility(showing);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
|
public static void changeVisibility(boolean visible, boolean animated) {
|
||||||
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package app.revanced.integrations.youtube.videoplayer;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import app.revanced.integrations.shared.Logger;
|
||||||
|
import app.revanced.integrations.shared.Utils;
|
||||||
|
import app.revanced.integrations.shared.settings.BooleanSetting;
|
||||||
|
|
||||||
|
public abstract class PlayerControlButton {
|
||||||
|
private static final Animation fadeIn;
|
||||||
|
private static final Animation fadeOut;
|
||||||
|
private static final Animation fadeOutImmediate;
|
||||||
|
|
||||||
|
private final WeakReference<ImageView> buttonRef;
|
||||||
|
protected final BooleanSetting setting;
|
||||||
|
protected boolean isVisible;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// TODO: check if these durations are correct.
|
||||||
|
fadeIn = Utils.getResourceAnimation("fade_in");
|
||||||
|
fadeIn.setDuration(Utils.getResourceInteger("fade_duration_fast"));
|
||||||
|
|
||||||
|
fadeOut = Utils.getResourceAnimation("fade_out");
|
||||||
|
fadeOut.setDuration(Utils.getResourceInteger("fade_duration_scheduled"));
|
||||||
|
|
||||||
|
fadeOutImmediate = Utils.getResourceAnimation("abc_fade_out");
|
||||||
|
fadeOutImmediate.setDuration(Utils.getResourceInteger("fade_duration_fast"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static Animation getButtonFadeIn() {
|
||||||
|
return fadeIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static Animation getButtonFadeOut() {
|
||||||
|
return fadeOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static Animation getButtonFadeOutImmediately() {
|
||||||
|
return fadeOutImmediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerControlButton(@NonNull ViewGroup bottomControlsViewGroup, @NonNull String imageViewButtonId,
|
||||||
|
@NonNull BooleanSetting booleanSetting, @NonNull View.OnClickListener onClickListener,
|
||||||
|
@Nullable View.OnLongClickListener longClickListener) {
|
||||||
|
Logger.printDebug(() -> "Initializing button: " + imageViewButtonId);
|
||||||
|
|
||||||
|
ImageView imageView = Objects.requireNonNull(bottomControlsViewGroup.findViewById(
|
||||||
|
Utils.getResourceIdentifier(imageViewButtonId, "id")
|
||||||
|
));
|
||||||
|
imageView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
imageView.setOnClickListener(onClickListener);
|
||||||
|
if (longClickListener != null) {
|
||||||
|
imageView.setOnLongClickListener(longClickListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
setting = booleanSetting;
|
||||||
|
buttonRef = new WeakReference<>(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibilityImmediate(boolean visible) {
|
||||||
|
if (visible) {
|
||||||
|
// Fix button flickering, by pushing this call to the back of
|
||||||
|
// the main thread and letting other layout code run first.
|
||||||
|
Utils.runOnMainThread(() -> private_setVisibility(true, false));
|
||||||
|
} else {
|
||||||
|
private_setVisibility(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(boolean visible, boolean animated) {
|
||||||
|
// Ignore this call, otherwise with full screen thumbnails the buttons are visible while seeking.
|
||||||
|
if (visible && !animated) return;
|
||||||
|
|
||||||
|
private_setVisibility(visible, animated);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void private_setVisibility(boolean visible, boolean animated) {
|
||||||
|
try {
|
||||||
|
if (isVisible == visible) return;
|
||||||
|
isVisible = visible;
|
||||||
|
|
||||||
|
ImageView iView = buttonRef.get();
|
||||||
|
if (iView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visible && setting.get()) {
|
||||||
|
iView.clearAnimation();
|
||||||
|
if (animated) {
|
||||||
|
iView.startAnimation(PlayerControlButton.getButtonFadeIn());
|
||||||
|
}
|
||||||
|
iView.setVisibility(View.VISIBLE);
|
||||||
|
} else if (iView.getVisibility() == View.VISIBLE) {
|
||||||
|
iView.clearAnimation();
|
||||||
|
if (animated) {
|
||||||
|
iView.startAnimation(PlayerControlButton.getButtonFadeOut());
|
||||||
|
}
|
||||||
|
iView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "setVisibility failure", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
android.useAndroidX = true
|
android.useAndroidX = true
|
||||||
version = 1.14.2
|
version = 1.15.0-dev.2
|
||||||
|
Loading…
Reference in New Issue
Block a user