mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-06-13 05:37:41 +02:00
fix(YouTube): Do not hide player controls when using double tap to skip forward (#4487)
Co-authored-by: MarcaDian <tolan.sheremeev@gmail.com>
This commit is contained in:

committed by
GitHub

parent
3d1dd06177
commit
63fe870d48
@ -126,8 +126,7 @@ public class LicenseActivityHook {
|
|||||||
// This is required to fix submenu title alignment issue with Android ASOP 15+
|
// This is required to fix submenu title alignment issue with Android ASOP 15+
|
||||||
ViewGroup toolBarParent = activity.findViewById(
|
ViewGroup toolBarParent = activity.findViewById(
|
||||||
getResourceIdentifier("revanced_toolbar_parent", "id"));
|
getResourceIdentifier("revanced_toolbar_parent", "id"));
|
||||||
ViewGroup dummyToolbar = toolBarParent.findViewById(getResourceIdentifier(
|
ViewGroup dummyToolbar = Utils.getChildViewByResourceName(toolBarParent,"revanced_toolbar");
|
||||||
"revanced_toolbar", "id"));
|
|
||||||
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
toolbarLayoutParams = dummyToolbar.getLayoutParams();
|
||||||
toolBarParent.removeView(dummyToolbar);
|
toolBarParent.removeView(dummyToolbar);
|
||||||
|
|
||||||
|
@ -21,9 +21,6 @@ enum class PlayerType {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A regular video is minimized.
|
* A regular video is minimized.
|
||||||
*
|
|
||||||
* When spoofing to 16.x YouTube and watching a short with a regular video in the background,
|
|
||||||
* the type can be this (and not [HIDDEN]).
|
|
||||||
*/
|
*/
|
||||||
WATCH_WHILE_MINIMIZED,
|
WATCH_WHILE_MINIMIZED,
|
||||||
WATCH_WHILE_MAXIMIZED,
|
WATCH_WHILE_MAXIMIZED,
|
||||||
@ -56,8 +53,7 @@ enum class PlayerType {
|
|||||||
val newType = nameToPlayerType[enumName]
|
val newType = nameToPlayerType[enumName]
|
||||||
if (newType == null) {
|
if (newType == null) {
|
||||||
Logger.printException { "Unknown PlayerType encountered: $enumName" }
|
Logger.printException { "Unknown PlayerType encountered: $enumName" }
|
||||||
} else if (current != newType) {
|
} else {
|
||||||
Logger.printDebug { "PlayerType changed to: $newType" }
|
|
||||||
current = newType
|
current = newType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,9 +64,13 @@ enum class PlayerType {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
var current
|
var current
|
||||||
get() = currentPlayerType
|
get() = currentPlayerType
|
||||||
private set(value) {
|
private set(type) {
|
||||||
currentPlayerType = value
|
if (currentPlayerType != type) {
|
||||||
onChange(currentPlayerType)
|
Logger.printDebug { "Changed to: $type" }
|
||||||
|
|
||||||
|
currentPlayerType = type
|
||||||
|
onChange(type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Volatile // Read/write from different threads.
|
@Volatile // Read/write from different threads.
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package app.revanced.extension.youtube.sponsorblock.ui;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
|
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||||
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
|
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
|
||||||
|
|
||||||
|
public class CreateSegmentButton {
|
||||||
|
@Nullable
|
||||||
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
|
public static void hideControls() {
|
||||||
|
if (instance != null) instance.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* injection point
|
||||||
|
*/
|
||||||
|
public static void initialize(View controlsView) {
|
||||||
|
try {
|
||||||
|
instance = new PlayerControlButton(
|
||||||
|
controlsView,
|
||||||
|
"revanced_sb_create_segment_button",
|
||||||
|
null,
|
||||||
|
CreateSegmentButton::shouldBeShown,
|
||||||
|
v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "initialize failure", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point
|
||||||
|
*/
|
||||||
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point
|
||||||
|
*/
|
||||||
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean shouldBeShown() {
|
||||||
|
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get()
|
||||||
|
&& !VideoInformation.isAtEndOfVideo();
|
||||||
|
}
|
||||||
|
}
|
@ -1,60 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.sponsorblock.ui;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
import app.revanced.extension.shared.Utils;
|
|
||||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
|
||||||
import app.revanced.extension.youtube.videoplayer.PlayerControlTopButton;
|
|
||||||
|
|
||||||
public class CreateSegmentButtonController extends PlayerControlTopButton {
|
|
||||||
@Nullable
|
|
||||||
private static CreateSegmentButtonController instance;
|
|
||||||
|
|
||||||
public static void hideControls() {
|
|
||||||
if (instance != null) instance.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* injection point
|
|
||||||
*/
|
|
||||||
public static void initialize(View youtubeControlsLayout) {
|
|
||||||
try {
|
|
||||||
Logger.printDebug(() -> "initializing new segment button");
|
|
||||||
ImageView imageView = Objects.requireNonNull(Utils.getChildViewByResourceName(
|
|
||||||
youtubeControlsLayout, "revanced_sb_create_segment_button"));
|
|
||||||
instance = new CreateSegmentButtonController(imageView);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "initialize failure", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* injection point
|
|
||||||
*/
|
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* injection point
|
|
||||||
*/
|
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CreateSegmentButtonController(ImageView imageView) {
|
|
||||||
super(imageView, v -> SponsorBlockViewController.toggleNewSegmentLayoutVisibility());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean shouldBeShown() {
|
|
||||||
return Settings.SB_ENABLED.get() && Settings.SB_CREATE_NEW_SEGMENT.get()
|
|
||||||
&& !VideoInformation.isAtEndOfVideo();
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,7 +19,6 @@ import app.revanced.extension.shared.Utils;
|
|||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
import app.revanced.extension.youtube.shared.PlayerType;
|
import app.revanced.extension.youtube.shared.PlayerType;
|
||||||
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
|
import app.revanced.extension.youtube.sponsorblock.objects.SponsorSegment;
|
||||||
import app.revanced.extension.youtube.videoplayer.PlayerControlTopButton;
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
|
|
||||||
public class SponsorBlockViewController {
|
public class SponsorBlockViewController {
|
||||||
@ -239,8 +238,8 @@ public class SponsorBlockViewController {
|
|||||||
// but if buttons are showing when the end of the video is reached then they need
|
// but if buttons are showing when the end of the video is reached then they need
|
||||||
// to be forcefully hidden
|
// to be forcefully hidden
|
||||||
if (!Settings.AUTO_REPEAT.get()) {
|
if (!Settings.AUTO_REPEAT.get()) {
|
||||||
CreateSegmentButtonController.hideControls();
|
CreateSegmentButton.hideControls();
|
||||||
VotingButtonController.hideControls();
|
VotingButton.hideControls();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "endOfVideoReached failure", ex);
|
Logger.printException(() -> "endOfVideoReached failure", ex);
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
package app.revanced.extension.youtube.sponsorblock.ui;
|
package app.revanced.extension.youtube.sponsorblock.ui;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.shared.Utils;
|
|
||||||
import app.revanced.extension.youtube.patches.VideoInformation;
|
import app.revanced.extension.youtube.patches.VideoInformation;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
import app.revanced.extension.youtube.sponsorblock.SegmentPlaybackController;
|
||||||
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
|
import app.revanced.extension.youtube.sponsorblock.SponsorBlockUtils;
|
||||||
import app.revanced.extension.youtube.videoplayer.PlayerControlTopButton;
|
import app.revanced.extension.youtube.videoplayer.PlayerControlButton;
|
||||||
|
|
||||||
public class VotingButtonController extends PlayerControlTopButton {
|
public class VotingButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static VotingButtonController instance;
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
public static void hideControls() {
|
public static void hideControls() {
|
||||||
if (instance != null) instance.hide();
|
if (instance != null) instance.hide();
|
||||||
@ -26,36 +22,36 @@ public class VotingButtonController extends PlayerControlTopButton {
|
|||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void initialize(View youtubeControlsLayout) {
|
public static void initialize(View controlsView) {
|
||||||
try {
|
try {
|
||||||
Logger.printDebug(() -> "initializing voting button");
|
instance = new PlayerControlButton(
|
||||||
ImageView imageView = Objects.requireNonNull(Utils.getChildViewByResourceName(
|
controlsView,
|
||||||
youtubeControlsLayout, "revanced_sb_voting_button"));
|
"revanced_sb_voting_button",
|
||||||
instance = new VotingButtonController(imageView);
|
null,
|
||||||
|
VotingButton::shouldBeShown,
|
||||||
|
v -> SponsorBlockUtils.onVotingClicked(v.getContext()),
|
||||||
|
null
|
||||||
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initialize failure", ex);
|
Logger.printException(() -> "initialize failure", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* Injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* Injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VotingButtonController(ImageView imageView) {
|
private static boolean shouldBeShown() {
|
||||||
super(imageView, v -> SponsorBlockUtils.onVotingClicked(v.getContext()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean shouldBeShown() {
|
|
||||||
return Settings.SB_ENABLED.get() && Settings.SB_VOTING_BUTTON.get()
|
return Settings.SB_ENABLED.get() && Settings.SB_VOTING_BUTTON.get()
|
||||||
&& SegmentPlaybackController.videoHasSegments() && !VideoInformation.isAtEndOfVideo();
|
&& SegmentPlaybackController.videoHasSegments() && !VideoInformation.isAtEndOfVideo();
|
||||||
}
|
}
|
@ -1,38 +1,35 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
package app.revanced.extension.youtube.videoplayer;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
|
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.youtube.shared.PlayerType;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class CopyVideoUrlButton extends PlayerControlBottomButton {
|
public class CopyVideoUrlButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CopyVideoUrlButton instance;
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
public CopyVideoUrlButton(ViewGroup viewGroup) {
|
|
||||||
super(
|
|
||||||
viewGroup,
|
|
||||||
"revanced_copy_video_url_button",
|
|
||||||
Settings.COPY_VIDEO_URL,
|
|
||||||
view -> CopyVideoUrlPatch.copyUrl(false),
|
|
||||||
view -> {
|
|
||||||
CopyVideoUrlPatch.copyUrl(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void initializeButton(View view) {
|
public static void initializeButton(View controlsView) {
|
||||||
try {
|
try {
|
||||||
instance = new CopyVideoUrlButton((ViewGroup) view);
|
instance = new PlayerControlButton(
|
||||||
|
controlsView,
|
||||||
|
"revanced_copy_video_url_button",
|
||||||
|
"revanced_copy_video_url_button_placeholder",
|
||||||
|
Settings.COPY_VIDEO_URL::get,
|
||||||
|
view -> CopyVideoUrlPatch.copyUrl(false),
|
||||||
|
view -> {
|
||||||
|
CopyVideoUrlPatch.copyUrl(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initializeButton failure", ex);
|
Logger.printException(() -> "initializeButton failure", ex);
|
||||||
}
|
}
|
||||||
@ -41,14 +38,14 @@ public class CopyVideoUrlButton extends PlayerControlBottomButton {
|
|||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,38 +1,35 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
package app.revanced.extension.youtube.videoplayer;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
|
import app.revanced.extension.youtube.patches.CopyVideoUrlPatch;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
import app.revanced.extension.shared.Logger;
|
import app.revanced.extension.youtube.shared.PlayerType;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class CopyVideoUrlTimestampButton extends PlayerControlBottomButton {
|
public class CopyVideoUrlTimestampButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static CopyVideoUrlTimestampButton instance;
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
public CopyVideoUrlTimestampButton(ViewGroup bottomControlsViewGroup) {
|
|
||||||
super(
|
|
||||||
bottomControlsViewGroup,
|
|
||||||
"revanced_copy_video_url_timestamp_button",
|
|
||||||
Settings.COPY_VIDEO_URL_TIMESTAMP,
|
|
||||||
view -> CopyVideoUrlPatch.copyUrl(true),
|
|
||||||
view -> {
|
|
||||||
CopyVideoUrlPatch.copyUrl(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void initializeButton(View bottomControlsViewGroup) {
|
public static void initializeButton(View controlsView) {
|
||||||
try {
|
try {
|
||||||
instance = new CopyVideoUrlTimestampButton((ViewGroup) bottomControlsViewGroup);
|
instance = new PlayerControlButton(
|
||||||
|
controlsView,
|
||||||
|
"revanced_copy_video_url_timestamp_button",
|
||||||
|
"revanced_copy_video_url_timestamp_button_placeholder",
|
||||||
|
Settings.COPY_VIDEO_URL_TIMESTAMP::get,
|
||||||
|
view -> CopyVideoUrlPatch.copyUrl(true),
|
||||||
|
view -> {
|
||||||
|
CopyVideoUrlPatch.copyUrl(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initializeButton failure", ex);
|
Logger.printException(() -> "initializeButton failure", ex);
|
||||||
}
|
}
|
||||||
@ -41,14 +38,14 @@ public class CopyVideoUrlTimestampButton extends PlayerControlBottomButton {
|
|||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
package app.revanced.extension.youtube.videoplayer;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@ -11,26 +10,23 @@ import app.revanced.extension.youtube.patches.VideoInformation;
|
|||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class ExternalDownloadButton extends PlayerControlBottomButton {
|
public class ExternalDownloadButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static ExternalDownloadButton instance;
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
public ExternalDownloadButton(ViewGroup viewGroup) {
|
|
||||||
super(
|
|
||||||
viewGroup,
|
|
||||||
"revanced_external_download_button",
|
|
||||||
Settings.EXTERNAL_DOWNLOADER,
|
|
||||||
ExternalDownloadButton::onDownloadClick,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void initializeButton(View view) {
|
public static void initializeButton(View controlsView) {
|
||||||
try {
|
try {
|
||||||
instance = new ExternalDownloadButton((ViewGroup) view);
|
instance = new PlayerControlButton(
|
||||||
|
controlsView,
|
||||||
|
"revanced_external_download_button",
|
||||||
|
"revanced_external_download_button_placeholder",
|
||||||
|
Settings.EXTERNAL_DOWNLOADER::get,
|
||||||
|
ExternalDownloadButton::onDownloadClick,
|
||||||
|
null
|
||||||
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initializeButton failure", ex);
|
Logger.printException(() -> "initializeButton failure", ex);
|
||||||
}
|
}
|
||||||
@ -39,14 +35,14 @@ public class ExternalDownloadButton extends PlayerControlBottomButton {
|
|||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* Injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +1,31 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
package app.revanced.extension.youtube.videoplayer;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
import app.revanced.extension.youtube.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||||
import app.revanced.extension.youtube.settings.Settings;
|
import app.revanced.extension.youtube.settings.Settings;
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class PlaybackSpeedDialogButton extends PlayerControlBottomButton {
|
public class PlaybackSpeedDialogButton {
|
||||||
@Nullable
|
@Nullable
|
||||||
private static PlaybackSpeedDialogButton instance;
|
private static PlayerControlButton instance;
|
||||||
|
|
||||||
public PlaybackSpeedDialogButton(ViewGroup viewGroup) {
|
|
||||||
super(
|
|
||||||
viewGroup,
|
|
||||||
"revanced_playback_speed_dialog_button",
|
|
||||||
Settings.PLAYBACK_SPEED_DIALOG_BUTTON,
|
|
||||||
view -> CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Injection point.
|
* Injection point.
|
||||||
*/
|
*/
|
||||||
public static void initializeButton(View view) {
|
public static void initializeButton(View controlsView) {
|
||||||
try {
|
try {
|
||||||
instance = new PlaybackSpeedDialogButton((ViewGroup) view);
|
instance = new PlayerControlButton(
|
||||||
|
controlsView,
|
||||||
|
"revanced_playback_speed_dialog_button",
|
||||||
|
"revanced_playback_speed_dialog_button_placeholder",
|
||||||
|
Settings.PLAYBACK_SPEED_DIALOG_BUTTON::get,
|
||||||
|
view -> CustomPlaybackSpeedPatch.showOldPlaybackSpeedMenu(),
|
||||||
|
null
|
||||||
|
);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "initializeButton failure", ex);
|
Logger.printException(() -> "initializeButton failure", ex);
|
||||||
}
|
}
|
||||||
@ -38,14 +34,14 @@ public class PlaybackSpeedDialogButton extends PlayerControlBottomButton {
|
|||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibilityImmediate(boolean visible) {
|
public static void setVisibilityImmediate(boolean visible) {
|
||||||
if (instance != null) instance.setVisibilityImmediate(visible);
|
if (instance != null) instance.setVisibilityImmediate(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* injection point
|
* injection point
|
||||||
*/
|
*/
|
||||||
public static void changeVisibility(boolean visible, boolean animated) {
|
public static void setVisibility(boolean visible, boolean animated) {
|
||||||
if (instance != null) instance.setVisibility(visible, animated);
|
if (instance != null) instance.setVisibility(visible, animated);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,103 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
|
||||||
|
|
||||||
import static app.revanced.extension.youtube.videoplayer.PlayerControlTopButton.fadeOutDuration;
|
|
||||||
|
|
||||||
import android.transition.Fade;
|
|
||||||
import android.transition.TransitionManager;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
import app.revanced.extension.shared.Utils;
|
|
||||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
|
||||||
|
|
||||||
public abstract class PlayerControlBottomButton {
|
|
||||||
private final WeakReference<ImageView> buttonRef;
|
|
||||||
private final BooleanSetting setting;
|
|
||||||
private boolean isVisible;
|
|
||||||
|
|
||||||
protected PlayerControlBottomButton(ViewGroup bottomControlsViewGroup, String imageViewButtonId,
|
|
||||||
BooleanSetting booleanSetting, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setVisibilityImmediate(boolean visible) {
|
|
||||||
private_setVisibility(visible, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected 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 the visibility state hasn't changed, return early.
|
|
||||||
if (isVisible == visible) return;
|
|
||||||
isVisible = visible;
|
|
||||||
|
|
||||||
ImageView iView = buttonRef.get();
|
|
||||||
if (iView == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewGroup parent = (ViewGroup) iView.getParent();
|
|
||||||
if (parent == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply transition if animation is enabled.
|
|
||||||
if (animated) {
|
|
||||||
Fade fade = visible
|
|
||||||
? PlayerControlTopButton.fadeInTransition
|
|
||||||
: PlayerControlTopButton.fadeOutTransition;
|
|
||||||
TransitionManager.beginDelayedTransition(parent, fade);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the view should be visible and the setting allows it.
|
|
||||||
if (visible && setting.get()) {
|
|
||||||
// Set the view to VISIBLE.
|
|
||||||
iView.setVisibility(View.VISIBLE);
|
|
||||||
} else if (iView.getVisibility() == View.VISIBLE) {
|
|
||||||
// First, set visibility to INVISIBLE for animation.
|
|
||||||
iView.setVisibility(View.INVISIBLE);
|
|
||||||
|
|
||||||
if (animated) {
|
|
||||||
// Set the view to GONE after the fade animation ends.
|
|
||||||
Utils.runOnMainThreadDelayed(() -> {
|
|
||||||
if (!isVisible) {
|
|
||||||
iView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}, fadeOutDuration);
|
|
||||||
} else {
|
|
||||||
// If no animation, immediately set the view to GONE.
|
|
||||||
iView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "private_setVisibility failure", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,184 @@
|
|||||||
|
package app.revanced.extension.youtube.videoplayer;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import app.revanced.extension.shared.Logger;
|
||||||
|
import app.revanced.extension.shared.Utils;
|
||||||
|
import app.revanced.extension.youtube.shared.PlayerType;
|
||||||
|
import kotlin.Unit;
|
||||||
|
|
||||||
|
public class PlayerControlButton {
|
||||||
|
public interface PlayerControlButtonVisibility {
|
||||||
|
/**
|
||||||
|
* @return If the button should be shown when the player overlay is visible.
|
||||||
|
*/
|
||||||
|
boolean shouldBeShown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int fadeInDuration;
|
||||||
|
private static final int fadeOutDuration;
|
||||||
|
|
||||||
|
private static final Animation fadeInAnimation;
|
||||||
|
private static final Animation fadeOutAnimation;
|
||||||
|
private static final Animation fadeOutImmediate;
|
||||||
|
|
||||||
|
static {
|
||||||
|
fadeInDuration = Utils.getResourceInteger("fade_duration_fast");
|
||||||
|
fadeOutDuration = Utils.getResourceInteger("fade_duration_scheduled");
|
||||||
|
|
||||||
|
fadeInAnimation = Utils.getResourceAnimation("fade_in");
|
||||||
|
fadeInAnimation.setDuration(fadeInDuration);
|
||||||
|
|
||||||
|
fadeOutAnimation = Utils.getResourceAnimation("fade_out");
|
||||||
|
fadeOutAnimation.setDuration(fadeOutDuration);
|
||||||
|
|
||||||
|
// Animation for the fast fade out after tapping the overlay.
|
||||||
|
// Currently not used but should be.
|
||||||
|
fadeOutImmediate = Utils.getResourceAnimation("abc_fade_out");
|
||||||
|
fadeOutImmediate.setDuration(Utils.getResourceInteger("fade_duration_fast"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final WeakReference<View> buttonRef;
|
||||||
|
/**
|
||||||
|
* Empty view with the same layout size as the button. Used to fill empty space while the
|
||||||
|
* fade out animation runs. Without this the chapter titles overlapping the button when fading out.
|
||||||
|
*/
|
||||||
|
private final WeakReference<View> placeHolderRef;
|
||||||
|
private final PlayerControlButtonVisibility visibilityCheck;
|
||||||
|
private boolean isVisible;
|
||||||
|
|
||||||
|
public PlayerControlButton(View controlsViewGroup,
|
||||||
|
String imageViewButtonId,
|
||||||
|
@Nullable String placeholderId,
|
||||||
|
PlayerControlButtonVisibility buttonVisibility,
|
||||||
|
View.OnClickListener onClickListener,
|
||||||
|
@Nullable View.OnLongClickListener longClickListener) {
|
||||||
|
ImageView imageView = Utils.getChildViewByResourceName(controlsViewGroup, imageViewButtonId);
|
||||||
|
imageView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
View tempPlaceholder = null;
|
||||||
|
if (placeholderId != null) {
|
||||||
|
tempPlaceholder = Utils.getChildViewByResourceName(controlsViewGroup, placeholderId);
|
||||||
|
tempPlaceholder.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
placeHolderRef = new WeakReference<>(tempPlaceholder);
|
||||||
|
|
||||||
|
imageView.setOnClickListener(onClickListener);
|
||||||
|
if (longClickListener != null) {
|
||||||
|
imageView.setOnLongClickListener(longClickListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
visibilityCheck = buttonVisibility;
|
||||||
|
buttonRef = new WeakReference<>(imageView);
|
||||||
|
isVisible = false;
|
||||||
|
|
||||||
|
// Update the visibility after the player type changes.
|
||||||
|
// This ensures that button animations are cleared and their states are updated correctly
|
||||||
|
// when switching between states like minimized, maximized, or fullscreen, preventing
|
||||||
|
// "stuck" animations or incorrect visibility. Without this fix the issue is most noticable
|
||||||
|
// when maximizing type 3 miniplayer.
|
||||||
|
PlayerType.getOnChange().addObserver((PlayerType type) -> {
|
||||||
|
playerTypeChanged(type);
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibilityImmediate(boolean visible) {
|
||||||
|
private_setVisibility(visible, 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;
|
||||||
|
|
||||||
|
View button = buttonRef.get();
|
||||||
|
if (button == null) return;
|
||||||
|
|
||||||
|
View placeholder = placeHolderRef.get();
|
||||||
|
final boolean shouldBeShown = visibilityCheck.shouldBeShown();
|
||||||
|
|
||||||
|
if (visible && shouldBeShown) {
|
||||||
|
button.clearAnimation();
|
||||||
|
if (animated) {
|
||||||
|
button.startAnimation(PlayerControlButton.fadeInAnimation);
|
||||||
|
}
|
||||||
|
button.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (placeholder != null) {
|
||||||
|
placeholder.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (button.getVisibility() == View.VISIBLE) {
|
||||||
|
button.clearAnimation();
|
||||||
|
if (animated) {
|
||||||
|
button.startAnimation(PlayerControlButton.fadeOutAnimation);
|
||||||
|
}
|
||||||
|
button.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeholder != null) {
|
||||||
|
placeholder.setVisibility(shouldBeShown
|
||||||
|
? View.VISIBLE
|
||||||
|
: View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Logger.printException(() -> "private_setVisibility failure", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes the button state after the player state changes.
|
||||||
|
*/
|
||||||
|
private void playerTypeChanged(PlayerType newType) {
|
||||||
|
if (newType != PlayerType.WATCH_WHILE_MINIMIZED && !newType.isMaximizedOrFullscreen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
View button = buttonRef.get();
|
||||||
|
if (button == null) return;
|
||||||
|
|
||||||
|
button.clearAnimation();
|
||||||
|
View placeholder = placeHolderRef.get();
|
||||||
|
|
||||||
|
if (visibilityCheck.shouldBeShown()) {
|
||||||
|
if (isVisible) {
|
||||||
|
button.setVisibility(View.VISIBLE);
|
||||||
|
if (placeholder != null) placeholder.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
button.setVisibility(View.GONE);
|
||||||
|
if (placeholder != null) placeholder.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
button.setVisibility(View.GONE);
|
||||||
|
if (placeholder != null) placeholder.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
if (!isVisible) return;
|
||||||
|
|
||||||
|
Utils.verifyOnMainThread();
|
||||||
|
View view = buttonRef.get();
|
||||||
|
if (view == null) return;
|
||||||
|
view.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
view = placeHolderRef.get();
|
||||||
|
if (view != null) view.setVisibility(View.GONE);
|
||||||
|
isVisible = false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,110 +0,0 @@
|
|||||||
package app.revanced.extension.youtube.videoplayer;
|
|
||||||
|
|
||||||
import android.transition.Fade;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.animation.Animation;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import app.revanced.extension.shared.Logger;
|
|
||||||
import app.revanced.extension.shared.Utils;
|
|
||||||
|
|
||||||
// Ideally this should be refactored into PlayerControlBottomButton,
|
|
||||||
// but the show/hide logic is not the same so keeping this as two classes might be simpler.
|
|
||||||
public abstract class PlayerControlTopButton {
|
|
||||||
static final int fadeInDuration;
|
|
||||||
static final int fadeOutDuration;
|
|
||||||
|
|
||||||
private static final Animation fadeInAnimation;
|
|
||||||
private static final Animation fadeOutAnimation;
|
|
||||||
|
|
||||||
static final Fade fadeInTransition;
|
|
||||||
static final Fade fadeOutTransition;
|
|
||||||
|
|
||||||
private final WeakReference<ImageView> buttonReference;
|
|
||||||
private boolean isShowing;
|
|
||||||
|
|
||||||
static {
|
|
||||||
fadeInDuration = Utils.getResourceInteger("fade_duration_fast");
|
|
||||||
fadeOutDuration = Utils.getResourceInteger("fade_duration_scheduled");
|
|
||||||
|
|
||||||
fadeInAnimation = Utils.getResourceAnimation("fade_in");
|
|
||||||
fadeInAnimation.setDuration(fadeInDuration);
|
|
||||||
|
|
||||||
fadeOutAnimation = Utils.getResourceAnimation("fade_out");
|
|
||||||
fadeOutAnimation.setDuration(fadeOutDuration);
|
|
||||||
|
|
||||||
fadeInTransition = new Fade();
|
|
||||||
fadeInTransition.setDuration(fadeInDuration);
|
|
||||||
|
|
||||||
fadeOutTransition = new Fade();
|
|
||||||
fadeOutTransition.setDuration(fadeOutDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected PlayerControlTopButton(ImageView imageView, View.OnClickListener onClickListener) {
|
|
||||||
imageView.setVisibility(View.GONE);
|
|
||||||
imageView.setOnClickListener(onClickListener);
|
|
||||||
|
|
||||||
buttonReference = new WeakReference<>(imageView);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setVisibilityImmediate(boolean visible) {
|
|
||||||
private_setVisibility(visible, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected 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 (isShowing == visible) return;
|
|
||||||
isShowing = visible;
|
|
||||||
|
|
||||||
ImageView iView = buttonReference.get();
|
|
||||||
if (iView == null) return;
|
|
||||||
|
|
||||||
if (visible) {
|
|
||||||
iView.clearAnimation();
|
|
||||||
if (!shouldBeShown()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (animated) {
|
|
||||||
iView.startAnimation(fadeInAnimation);
|
|
||||||
}
|
|
||||||
iView.setVisibility(View.VISIBLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iView.getVisibility() == View.VISIBLE) {
|
|
||||||
iView.clearAnimation();
|
|
||||||
if (animated) {
|
|
||||||
iView.startAnimation(fadeOutAnimation);
|
|
||||||
}
|
|
||||||
iView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Logger.printException(() -> "private_setVisibility failure", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract boolean shouldBeShown();
|
|
||||||
|
|
||||||
public void hide() {
|
|
||||||
if (!isShowing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils.verifyOnMainThread();
|
|
||||||
View v = buttonReference.get();
|
|
||||||
if (v == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
v.setVisibility(View.GONE);
|
|
||||||
isShowing = false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -82,9 +82,9 @@ private val sponsorBlockResourcePatch = resourcePatch {
|
|||||||
private const val EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
|
private const val EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/extension/youtube/sponsorblock/SegmentPlaybackController;"
|
"Lapp/revanced/extension/youtube/sponsorblock/SegmentPlaybackController;"
|
||||||
private const val EXTENSION_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
|
private const val EXTENSION_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/extension/youtube/sponsorblock/ui/CreateSegmentButtonController;"
|
"Lapp/revanced/extension/youtube/sponsorblock/ui/CreateSegmentButton;"
|
||||||
private const val EXTENSION_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
|
private const val EXTENSION_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/extension/youtube/sponsorblock/ui/VotingButtonController;"
|
"Lapp/revanced/extension/youtube/sponsorblock/ui/VotingButton;"
|
||||||
private const val EXTENSION_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR =
|
private const val EXTENSION_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR =
|
||||||
"Lapp/revanced/extension/youtube/sponsorblock/ui/SponsorBlockViewController;"
|
"Lapp/revanced/extension/youtube/sponsorblock/ui/SponsorBlockViewController;"
|
||||||
|
|
||||||
|
@ -77,12 +77,9 @@ val playerControlsResourcePatch = resourcePatch {
|
|||||||
).item(0)
|
).item(0)
|
||||||
|
|
||||||
val bottomTargetDocumentChildNodes = bottomTargetDocument.childNodes
|
val bottomTargetDocumentChildNodes = bottomTargetDocument.childNodes
|
||||||
var bottomInsertBeforeNode: Node = bottomTargetDocumentChildNodes.findElementByAttributeValue(
|
var bottomInsertBeforeNode: Node = bottomTargetDocumentChildNodes.findElementByAttributeValueOrThrow(
|
||||||
"android:inflatedId",
|
"android:inflatedId",
|
||||||
bottomLastLeftOf,
|
bottomLastLeftOf,
|
||||||
) ?: bottomTargetDocumentChildNodes.findElementByAttributeValueOrThrow(
|
|
||||||
"android:id", // Older targets use non-inflated id.
|
|
||||||
bottomLastLeftOf,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
addTopControl = { resourceDirectoryName ->
|
addTopControl = { resourceDirectoryName ->
|
||||||
@ -123,7 +120,7 @@ val playerControlsResourcePatch = resourcePatch {
|
|||||||
).item(0).childNodes
|
).item(0).childNodes
|
||||||
|
|
||||||
// Copy the patch layout xml into the target layout file.
|
// Copy the patch layout xml into the target layout file.
|
||||||
for (index in 1 until sourceElements.length) {
|
for (index in sourceElements.length - 1 downTo 1) {
|
||||||
val element = sourceElements.item(index).cloneNode(true)
|
val element = sourceElements.item(index).cloneNode(true)
|
||||||
|
|
||||||
// If the element has no attributes there's no point adding it to the destination.
|
// If the element has no attributes there's no point adding it to the destination.
|
||||||
@ -189,7 +186,7 @@ fun initializeBottomControl(descriptor: String) {
|
|||||||
fun injectVisibilityCheckCall(descriptor: String) {
|
fun injectVisibilityCheckCall(descriptor: String) {
|
||||||
visibilityMethod.addInstruction(
|
visibilityMethod.addInstruction(
|
||||||
visibilityInsertIndex++,
|
visibilityInsertIndex++,
|
||||||
"invoke-static { p1 , p2 }, $descriptor->changeVisibility(ZZ)V",
|
"invoke-static { p1 , p2 }, $descriptor->setVisibility(ZZ)V",
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!visibilityImmediateCallbacksExistModified) {
|
if (!visibilityImmediateCallbacksExistModified) {
|
||||||
@ -199,7 +196,7 @@ fun injectVisibilityCheckCall(descriptor: String) {
|
|||||||
|
|
||||||
visibilityImmediateMethod.addInstruction(
|
visibilityImmediateMethod.addInstruction(
|
||||||
visibilityImmediateInsertIndex++,
|
visibilityImmediateInsertIndex++,
|
||||||
"invoke-static { p0 }, $descriptor->changeVisibilityImmediate(Z)V",
|
"invoke-static { p0 }, $descriptor->setVisibilityImmediate(Z)V",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,10 +448,10 @@ This feature is only available for older devices"</string>
|
|||||||
<string name="revanced_share_copy_url_success">URL copied to clipboard</string>
|
<string name="revanced_share_copy_url_success">URL copied to clipboard</string>
|
||||||
<string name="revanced_share_copy_url_timestamp_success">URL with timestamp copied</string>
|
<string name="revanced_share_copy_url_timestamp_success">URL with timestamp copied</string>
|
||||||
<string name="revanced_copy_video_url_title">Show copy video URL button</string>
|
<string name="revanced_copy_video_url_title">Show copy video URL button</string>
|
||||||
<string name="revanced_copy_video_url_summary_on">Button is shown. Tap to copy video URL. Tap and hold to copy video URL with timestamp</string>
|
<string name="revanced_copy_video_url_summary_on">Button is shown. Tap to copy video URL. Tap and hold to copy with timestamp</string>
|
||||||
<string name="revanced_copy_video_url_summary_off">Button is not shown</string>
|
<string name="revanced_copy_video_url_summary_off">Button is not shown</string>
|
||||||
<string name="revanced_copy_video_url_timestamp_title">Show copy timestamp URL button</string>
|
<string name="revanced_copy_video_url_timestamp_title">Show copy timestamp URL button</string>
|
||||||
<string name="revanced_copy_video_url_timestamp_summary_on">Button is shown. Tap to copy video URL with timestamp. Tap and hold to copy video without timestamp</string>
|
<string name="revanced_copy_video_url_timestamp_summary_on">Button is shown. Tap to copy video URL with timestamp. Tap and hold to copy without timestamp</string>
|
||||||
<string name="revanced_copy_video_url_timestamp_summary_off">Button is not shown</string>
|
<string name="revanced_copy_video_url_timestamp_summary_off">Button is not shown</string>
|
||||||
</patch>
|
</patch>
|
||||||
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
<patch id="interaction.dialog.removeViewerDiscretionDialogPatch">
|
||||||
|
@ -13,12 +13,19 @@
|
|||||||
android:layout_height="60.0dip"
|
android:layout_height="60.0dip"
|
||||||
android:paddingTop="6.0dp"
|
android:paddingTop="6.0dp"
|
||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:longClickable="false"
|
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/revanced_yt_copy_timestamp"
|
android:src="@drawable/revanced_yt_copy_timestamp"
|
||||||
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/revanced_copy_video_url_timestamp_button_placeholder"
|
||||||
|
android:layout_width="48.0dip"
|
||||||
|
android:layout_height="60.0dip"
|
||||||
|
android:visibility="gone"
|
||||||
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
|
|
||||||
<com.google.android.libraries.youtube.common.ui.TouchImageView
|
<com.google.android.libraries.youtube.common.ui.TouchImageView
|
||||||
android:id="@+id/revanced_copy_video_url_button"
|
android:id="@+id/revanced_copy_video_url_button"
|
||||||
style="@style/YouTubePlayerButton"
|
style="@style/YouTubePlayerButton"
|
||||||
@ -26,9 +33,16 @@
|
|||||||
android:layout_height="60.0dip"
|
android:layout_height="60.0dip"
|
||||||
android:paddingTop="6.0dp"
|
android:paddingTop="6.0dp"
|
||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:longClickable="false"
|
|
||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/revanced_yt_copy"
|
android:src="@drawable/revanced_yt_copy"
|
||||||
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/revanced_copy_video_url_button_placeholder"
|
||||||
|
android:layout_width="48.0dip"
|
||||||
|
android:layout_height="60.0dip"
|
||||||
|
android:visibility="gone"
|
||||||
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
@ -18,4 +18,12 @@
|
|||||||
android:src="@drawable/revanced_yt_download_button"
|
android:src="@drawable/revanced_yt_download_button"
|
||||||
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/revanced_external_download_button_placeholder"
|
||||||
|
android:layout_width="48.0dip"
|
||||||
|
android:layout_height="60.0dip"
|
||||||
|
android:visibility="gone"
|
||||||
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
@ -18,4 +18,12 @@
|
|||||||
android:src="@drawable/revanced_playback_speed_dialog_button"
|
android:src="@drawable/revanced_playback_speed_dialog_button"
|
||||||
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/revanced_playback_speed_dialog_button_placeholder"
|
||||||
|
android:layout_width="48.0dip"
|
||||||
|
android:layout_height="60.0dip"
|
||||||
|
android:visibility="gone"
|
||||||
|
yt:layout_constraintBottom_toTopOf="@+id/quick_actions_container"
|
||||||
|
yt:layout_constraintRight_toLeftOf="@+id/fullscreen_button" />
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
Reference in New Issue
Block a user