Player overlay buttons redone

This commit is contained in:
xfileFIN 2020-10-15 18:53:00 +03:00
parent d38afae3a7
commit 2d44d81747
20 changed files with 541 additions and 291 deletions

View file

@ -0,0 +1,6 @@
package fi.razerman.youtube;
// Ignore this file, the implementation is in another repository
public class XGlobals {
public static Boolean debug = false;
}

View file

@ -0,0 +1,9 @@
package fi.vanced.libraries.youtube.player;
import fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView;
public class PlayerType {
public static void playerTypeChanged(String playerType) {
SponsorBlockView.playerTypeChanged(playerType);
}
}

View file

@ -0,0 +1,153 @@
package fi.vanced.libraries.youtube.sponsors.player.ui;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import pl.jakubweg.NewSegmentHelperLayout;
import pl.jakubweg.PlayerController;
import pl.jakubweg.SponsorBlockSettings;
import pl.jakubweg.SponsorBlockUtils;
import static fi.razerman.youtube.XGlobals.debug;
public class NewSegmentLayout extends FrameLayout {
static String TAG = "NewSegmentLayout";
private LinearLayout newSegmentContainer;
public int defaultBottomMargin;
public int ctaBottomMargin;
public ImageButton rewindButton;
public ImageButton forwardButton;
public ImageButton adjustButton;
public ImageButton compareButton;
public ImageButton editButton;
public ImageButton publishButton;
private int rippleEffectId;
public NewSegmentLayout(Context context) {
super(context);
this.initialize(context);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.initialize(context);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet, int defStyleAttr) {
super(context, attributeSet, defStyleAttr);
this.initialize(context);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet, int defStyleAttr, int defStyleRes) {
super(context, attributeSet, defStyleAttr, defStyleRes);
this.initialize(context);
}
private final void initialize(Context context) {
LayoutInflater.from(context).inflate(getIdentifier(context, "new_segment", "layout"), this, true);
Resources resources = context.getResources();
TypedValue rippleEffect = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, rippleEffect, true);
rippleEffectId = rippleEffect.resourceId;
this.newSegmentContainer = (LinearLayout)this.findViewById(getIdentifier(context, "new_segment_container", "id"));
this.rewindButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_rewind", "id"));
if (this.rewindButton != null) {
setClickEffect(this.rewindButton);
this.rewindButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Rewind button clicked"); }
PlayerController.skipRelativeMilliseconds(-SponsorBlockSettings.adjustNewSegmentMillis);
}
});
}
this.forwardButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_forward", "id"));
if (this.forwardButton != null) {
setClickEffect(this.forwardButton);
this.forwardButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Forward button clicked"); }
PlayerController.skipRelativeMilliseconds(SponsorBlockSettings.adjustNewSegmentMillis);
}
});
}
this.adjustButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_adjust", "id"));
if (this.adjustButton != null) {
setClickEffect(this.adjustButton);
this.adjustButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Adjust button clicked"); }
SponsorBlockUtils.onMarkLocationClicked(NewSegmentHelperLayout.context);
}
});
}
this.compareButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_compare", "id"));
if (this.compareButton != null) {
setClickEffect(this.compareButton);
this.compareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Compare button clicked"); }
SponsorBlockUtils.onPreviewClicked(NewSegmentHelperLayout.context);
}
});
}
this.editButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_edit", "id"));
if (this.editButton != null) {
setClickEffect(this.editButton);
this.editButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Edit button clicked"); }
SponsorBlockUtils.onEditByHandClicked(NewSegmentHelperLayout.context);
}
});
}
this.publishButton = (ImageButton)this.findViewById(getIdentifier(context, "new_segment_publish", "id"));
if (this.publishButton != null) {
setClickEffect(this.publishButton);
this.publishButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) { Log.d(TAG, "Publish button clicked"); }
SponsorBlockUtils.onPublishClicked(NewSegmentHelperLayout.context);
}
});
}
this.defaultBottomMargin = resources.getDimensionPixelSize(getIdentifier(context, "brand_interaction_default_bottom_margin", "dimen"));
this.ctaBottomMargin = resources.getDimensionPixelSize(getIdentifier(context, "brand_interaction_cta_bottom_margin", "dimen"));
}
private void setClickEffect(ImageButton btn) {
btn.setBackgroundResource(rippleEffectId);
RippleDrawable rippleDrawable = (RippleDrawable)btn.getBackground();
int[][] states = new int[][] { new int[] { android.R.attr.state_enabled } };
int[] colors = new int[] { 0x33ffffff }; // sets the ripple color to white
ColorStateList colorStateList = new ColorStateList(states, colors);
rippleDrawable.setColor(colorStateList);
}
private int getIdentifier(Context context, String name, String defType) {
return context.getResources().getIdentifier(name, defType, context.getPackageName());
}
}

View file

@ -0,0 +1,134 @@
package fi.vanced.libraries.youtube.sponsors.player.ui;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import pl.jakubweg.PlayerController;
import static fi.razerman.youtube.XGlobals.debug;
public class SkipSponsorButton extends FrameLayout {
String TAG = "SkipSponsorButton";
public CharSequence skipSponsorTextViewText;
public CharSequence skipSponsorText;
public ImageView skipSponsorButtonIcon;
public TextView skipSponsorTextView;
public int currentTextColor;
public int invertedButtonForegroundColor;
public int backgroundColor;
public int invertedBackgroundColor;
public ColorDrawable backgroundColorDrawable;
public int defaultBottomMargin;
public int ctaBottomMargin;
private LinearLayout skipSponsorBtnContainer;
private final Paint background;
private final Paint border;
private boolean highContrast = true;
public SkipSponsorButton(Context context) {
super(context);
this.background = new Paint();
this.border = new Paint();
this.initialize(context);
}
public SkipSponsorButton(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
this.background = new Paint();
this.border = new Paint();
this.initialize(context);
}
public SkipSponsorButton(Context context, AttributeSet attributeSet, int defStyleAttr) {
super(context, attributeSet, defStyleAttr);
this.background = new Paint();
this.border = new Paint();
this.initialize(context);
}
public SkipSponsorButton(Context context, AttributeSet attributeSet, int defStyleAttr, int defStyleRes) {
super(context, attributeSet, defStyleAttr, defStyleRes);
this.background = new Paint();
this.border = new Paint();
this.initialize(context);
}
private final void initialize(Context context) {
LayoutInflater.from(context).inflate(getIdentifier(context, "skip_sponsor_button", "layout"), this, true); // layout:skip_ad_button
this.setMinimumHeight(this.getResources().getDimensionPixelSize(getIdentifier(context, "ad_skip_ad_button_min_height", "dimen"))); // dimen:ad_skip_ad_button_min_height
this.skipSponsorBtnContainer = (LinearLayout)this.findViewById(getIdentifier(context, "skip_sponsor_button_container", "id")); // id:skip_ad_button_container
this.skipSponsorButtonIcon = (ImageView)this.findViewById(getIdentifier(context, "skip_sponsor_button_icon", "id")); // id:skip_ad_button_icon
this.backgroundColor = getColor(context, getIdentifier(context, "skip_ad_button_background_color", "color")); // color:skip_ad_button_background_color
this.invertedBackgroundColor = getColor(context, getIdentifier(context, "skip_ad_button_inverted_background_color", "color")); // color:skip_ad_button_inverted_background_color
this.background.setColor(this.backgroundColor);
this.background.setStyle(Paint.Style.FILL);
int borderColor = getColor(context, getIdentifier(context, "skip_ad_button_border_color", "color")); // color:skip_ad_button_border_color
this.border.setColor(borderColor);
float borderWidth = this.getResources().getDimension(getIdentifier(context, "ad_skip_ad_button_border_width", "dimen")); // dimen:ad_skip_ad_button_border_width
this.border.setStrokeWidth(borderWidth);
this.border.setStyle(Paint.Style.STROKE);
TextView skipSponsorText = (TextView)this.findViewById(getIdentifier(context, "skip_sponsor_button_text", "id")); // id:skip_ad_button_text
this.skipSponsorTextView = skipSponsorText;
this.skipSponsorTextViewText = skipSponsorText.getText();
this.currentTextColor = this.skipSponsorTextView.getCurrentTextColor();
this.invertedButtonForegroundColor = getColor(context, getIdentifier(context, "skip_ad_button_inverted_foreground_color", "color")); // color:skip_ad_button_inverted_foreground_color
this.backgroundColorDrawable = new ColorDrawable(this.backgroundColor);
Resources resources = context.getResources();
this.defaultBottomMargin = resources.getDimensionPixelSize(getIdentifier(context, "skip_button_default_bottom_margin", "dimen")); // dimen:skip_button_default_bottom_margin
this.ctaBottomMargin = resources.getDimensionPixelSize(getIdentifier(context, "skip_button_cta_bottom_margin", "dimen")); // dimen:skip_button_cta_bottom_margin
this.skipSponsorText = resources.getText(getIdentifier(context, "skip_sponsor", "string")); // string:skip_ads "Skip ads"
this.skipSponsorBtnContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (debug) {
Log.d(TAG, "Skip button clicked");
}
PlayerController.onSkipSponsorClicked();
}
});
}
@Override // android.view.ViewGroup
protected final void dispatchDraw(Canvas canvas) {
int width = this.skipSponsorBtnContainer.getWidth();
int height = this.skipSponsorBtnContainer.getHeight();
int top = this.skipSponsorBtnContainer.getTop();
int left = this.skipSponsorBtnContainer.getLeft();
float floatLeft = (float)left;
float floatTop = (float)top;
float floatWidth = (float)(left + width);
float floatHeight = (float)(top + height);
canvas.drawRect(floatLeft, floatTop, floatWidth, floatHeight, this.background);
if (!this.highContrast) {
canvas.drawLines(new float[] { floatWidth, floatTop, floatLeft, floatTop, floatLeft, floatTop, floatLeft, floatHeight, floatLeft, floatHeight, floatWidth, floatHeight }, this.border);
}
super.dispatchDraw(canvas);
}
public static int getColor(Context context, int arg3) {
return Build.VERSION.SDK_INT < 23 ? context.getResources().getColor(arg3) : context.getColor(arg3);
}
private int getIdentifier(Context context, String name, String defType) {
return context.getResources().getIdentifier(name, defType, context.getPackageName());
}
}

View file

@ -0,0 +1,157 @@
package fi.vanced.libraries.youtube.sponsors.player.ui;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import com.google.android.apps.youtube.app.YouTubeApplication;
import java.lang.ref.WeakReference;
import static fi.razerman.youtube.XGlobals.debug;
public class SponsorBlockView {
static String TAG = "SponsorBlockView";
static RelativeLayout inlineSponsorOverlay;
static ViewGroup _youtubeOverlaysLayout;
static WeakReference<SkipSponsorButton> _skipSponsorButton = new WeakReference<>(null);
static WeakReference<NewSegmentLayout> _newSegmentLayout = new WeakReference<>(null);
static boolean shouldShowOnPlayerType = true;
public static void initialize(Object viewGroup) {
try {
if(debug){
Log.d(TAG, "initializing");
}
_youtubeOverlaysLayout = (ViewGroup) viewGroup;
addView();
}
catch (Exception ex) {
Log.e(TAG, "Unable to set ViewGroup", ex);
}
}
public static void showSkipButton() {
skipSponsorButtonVisibility(true);
}
public static void hideSkipButton() {
skipSponsorButtonVisibility(false);
}
public static void showNewSegmentLayout() {
newSegmentLayoutVisibility(true);
}
public static void hideNewSegmentLayout() {
newSegmentLayoutVisibility(false);
}
public static void playerTypeChanged(String playerType) {
try {
shouldShowOnPlayerType = playerType.equalsIgnoreCase("WATCH_WHILE_FULLSCREEN") || playerType.equalsIgnoreCase("WATCH_WHILE_MAXIMIZED");
if (playerType.equalsIgnoreCase("WATCH_WHILE_FULLSCREEN")) {
setSkipBtnMargins(true);
setNewSegmentLayoutMargins(true);
return;
}
setSkipBtnMargins(false);
setNewSegmentLayoutMargins(false);
}
catch (Exception ex) {
Log.e(TAG, "Player type changed caused a crash.", ex);
}
}
private static void addView() {
inlineSponsorOverlay = new RelativeLayout(YouTubeApplication.getAppContext());
setLayoutParams(inlineSponsorOverlay);
LayoutInflater.from(YouTubeApplication.getAppContext()).inflate(getIdentifier("inline_sponsor_overlay", "layout"), inlineSponsorOverlay);
_youtubeOverlaysLayout.addView(inlineSponsorOverlay, _youtubeOverlaysLayout.getChildCount() - 2);
SkipSponsorButton skipSponsorButton = (SkipSponsorButton) inlineSponsorOverlay.findViewById(getIdentifier("skip_sponsor_button", "id"));
_skipSponsorButton = new WeakReference<>(skipSponsorButton);
NewSegmentLayout newSegmentView = (NewSegmentLayout) inlineSponsorOverlay.findViewById(getIdentifier("new_segment_view", "id"));
_newSegmentLayout = new WeakReference<>(newSegmentView);
}
private static void setLayoutParams(RelativeLayout relativeLayout) {
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
}
private static void setSkipBtnMargins(boolean fullScreen) {
SkipSponsorButton skipSponsorButton = _skipSponsorButton.get();
if (skipSponsorButton == null) {
Log.e(TAG, "Unable to setSkipBtnMargins");
return;
}
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) skipSponsorButton.getLayoutParams();
if (params == null) {
Log.e(TAG, "Unable to setSkipBtnMargins");
return;
}
params.bottomMargin = fullScreen ? skipSponsorButton.ctaBottomMargin : skipSponsorButton.defaultBottomMargin;
skipSponsorButton.setLayoutParams(params);
}
private static void skipSponsorButtonVisibility(boolean visible) {
SkipSponsorButton skipSponsorButton = _skipSponsorButton.get();
if (skipSponsorButton == null) {
Log.e(TAG, "Unable to skipSponsorButtonVisibility");
return;
}
visible &= shouldShowOnPlayerType;
skipSponsorButton.setVisibility(visible ? View.VISIBLE : View.GONE);
bringLayoutToFront();
}
private static void setNewSegmentLayoutMargins(boolean fullScreen) {
NewSegmentLayout newSegmentLayout = _newSegmentLayout.get();
if (newSegmentLayout == null) {
Log.e(TAG, "Unable to setNewSegmentLayoutMargins");
return;
}
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) newSegmentLayout.getLayoutParams();
if (params == null) {
Log.e(TAG, "Unable to setNewSegmentLayoutMargins");
return;
}
params.bottomMargin = fullScreen ? newSegmentLayout.ctaBottomMargin : newSegmentLayout.defaultBottomMargin;
newSegmentLayout.setLayoutParams(params);
}
private static void newSegmentLayoutVisibility(boolean visible) {
NewSegmentLayout newSegmentLayout = _newSegmentLayout.get();
if (newSegmentLayout == null) {
Log.e(TAG, "Unable to newSegmentLayoutVisibility");
return;
}
visible &= shouldShowOnPlayerType;
newSegmentLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
bringLayoutToFront();
}
private static void bringLayoutToFront() {
inlineSponsorOverlay.bringToFront();
inlineSponsorOverlay.requestLayout();
inlineSponsorOverlay.invalidate();
}
private static int getIdentifier(String name, String defType) {
Context context = YouTubeApplication.getAppContext();
return context.getResources().getIdentifier(name, defType, context.getPackageName());
}
}