diff --git a/app/src/main/java/fi/razerman/youtube/XGlobals.java b/app/src/main/java/fi/razerman/youtube/XGlobals.java new file mode 100644 index 00000000..7bc8ec22 --- /dev/null +++ b/app/src/main/java/fi/razerman/youtube/XGlobals.java @@ -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; +} diff --git a/app/src/main/java/fi/vanced/libraries/youtube/player/PlayerType.java b/app/src/main/java/fi/vanced/libraries/youtube/player/PlayerType.java new file mode 100644 index 00000000..448ebe0c --- /dev/null +++ b/app/src/main/java/fi/vanced/libraries/youtube/player/PlayerType.java @@ -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); + } +} diff --git a/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/NewSegmentLayout.java b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/NewSegmentLayout.java new file mode 100644 index 00000000..72eadd73 --- /dev/null +++ b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/NewSegmentLayout.java @@ -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()); + } +} diff --git a/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SkipSponsorButton.java b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SkipSponsorButton.java new file mode 100644 index 00000000..17446b90 --- /dev/null +++ b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SkipSponsorButton.java @@ -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()); + } +} diff --git a/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SponsorBlockView.java b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SponsorBlockView.java new file mode 100644 index 00000000..af1d011f --- /dev/null +++ b/app/src/main/java/fi/vanced/libraries/youtube/sponsors/player/ui/SponsorBlockView.java @@ -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 = new WeakReference<>(null); + static WeakReference _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()); + } +} diff --git a/app/src/main/java/pl/jakubweg/NewSegmentHelperLayout.java b/app/src/main/java/pl/jakubweg/NewSegmentHelperLayout.java index 5c0ac4c3..6aca22f9 100644 --- a/app/src/main/java/pl/jakubweg/NewSegmentHelperLayout.java +++ b/app/src/main/java/pl/jakubweg/NewSegmentHelperLayout.java @@ -1,139 +1,28 @@ package pl.jakubweg; -import android.annotation.SuppressLint; import android.content.Context; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import java.lang.ref.WeakReference; +import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.hideNewSegmentLayout; +import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.showNewSegmentLayout; -public class NewSegmentHelperLayout extends LinearLayout implements View.OnClickListener { - private static final int rewindBtnId = 1235; - private static final int forwardBtnId = 1236; - private static final int publishBtnId = 1237; - private static final int hideBtnId = 1238; - private static final int markLocationBtnId = 1239; - private static final int previewBtnId = 1240; - private static final int editByHandBtnId = 1241; - private static WeakReference INSTANCE = new WeakReference<>(null); +public class NewSegmentHelperLayout { + public static Context context; private static boolean isShown = false; - private final int padding; - private final int iconSize; - private final int rippleEffectId; - private final String packageName; - - @SuppressLint({"DefaultLocale", "SetTextI18n"}) - public NewSegmentHelperLayout(Context context) { - super(context); - INSTANCE = new WeakReference<>(this); - isShown = false; - setVisibility(GONE); - - packageName = context.getPackageName(); - padding = (int) SkipSegmentView.convertDpToPixel(4f, context); - iconSize = (int) SkipSegmentView.convertDpToPixel(40f, context); - - TypedValue rippleEffect = new TypedValue(); - getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, rippleEffect, true); - rippleEffectId = rippleEffect.resourceId; - - - setOrientation(VERTICAL); - @SuppressLint("RtlHardcoded") - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT, - Gravity.START | Gravity.LEFT | Gravity.CENTER_VERTICAL - ); - this.setBackgroundColor(0x66000000); - this.bringToFront(); - this.setLayoutParams(layoutParams); - this.setPadding(padding, padding, padding, padding); - - final LinearLayout topLayout = new LinearLayout(context); - final LinearLayout bottomLayout = new LinearLayout(context); - topLayout.setOrientation(HORIZONTAL); - bottomLayout.setOrientation(HORIZONTAL); - this.addView(topLayout); - this.addView(bottomLayout); - - topLayout.addView(createTextViewBtn(rewindBtnId, "player_fast_rewind")); - topLayout.addView(createTextViewBtn(forwardBtnId, "player_fast_forward")); - topLayout.addView(createTextViewBtn(markLocationBtnId, "ic_sb_adjust")); - bottomLayout.addView(createTextViewBtn(previewBtnId, "ic_sb_compare")); - bottomLayout.addView(createTextViewBtn(editByHandBtnId, "ic_sb_edit")); - bottomLayout.addView(createTextViewBtn(publishBtnId, "ic_sb_publish")); -// bottomLayout.addView(createTextViewBtn(hideBtnId,"btn_close_light")); - } public static void show() { if (isShown) return; isShown = true; - NewSegmentHelperLayout i = INSTANCE.get(); - if (i == null) return; - i.setVisibility(VISIBLE); - i.bringToFront(); - i.requestLayout(); - i.invalidate(); + showNewSegmentLayout(); } public static void hide() { if (!isShown) return; isShown = false; - NewSegmentHelperLayout i = INSTANCE.get(); - if (i != null) - i.setVisibility(GONE); + hideNewSegmentLayout(); } public static void toggle() { if (isShown) hide(); else show(); } - - private View createTextViewBtn(int id, String drawableName) { - int drawableId = getResources().getIdentifier(drawableName, "drawable", packageName); - final ImageView view = new ImageView(getContext()); - view.setPadding(padding, padding, padding, padding); - view.setLayoutParams(new LayoutParams(iconSize, iconSize, 1)); - view.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - view.setImageResource(drawableId); - view.setId(id); - view.setClickable(true); - view.setFocusable(true); - view.setBackgroundResource(rippleEffectId); - view.setOnClickListener(this); - return view; - } - - - @Override - public void onClick(View v) { - switch (v.getId()) { - case forwardBtnId: - PlayerController.skipRelativeMilliseconds(SponsorBlockSettings.adjustNewSegmentMillis); - break; - case rewindBtnId: - PlayerController.skipRelativeMilliseconds(-SponsorBlockSettings.adjustNewSegmentMillis); - break; - case markLocationBtnId: - SponsorBlockUtils.onMarkLocationClicked(getContext()); - break; - case publishBtnId: - SponsorBlockUtils.onPublishClicked(getContext()); - break; - case previewBtnId: - SponsorBlockUtils.onPreviewClicked(getContext()); - break; - case editByHandBtnId: - SponsorBlockUtils.onEditByHandClicked(getContext()); - break; - case hideBtnId: - hide(); - break; - } - } } diff --git a/app/src/main/java/pl/jakubweg/PlayerController.java b/app/src/main/java/pl/jakubweg/PlayerController.java index 94a3d131..fe547ac8 100644 --- a/app/src/main/java/pl/jakubweg/PlayerController.java +++ b/app/src/main/java/pl/jakubweg/PlayerController.java @@ -104,11 +104,6 @@ public class PlayerController { SkipSegmentView.hide(); NewSegmentHelperLayout.hide(); - - // add image button when starting new video - Activity activity = playerActivity.get(); - if (activity != null) - SponsorBlockUtils.addImageButton(activity, 5); } catch (Exception e) { Log.e(TAG, "Exception while initializing skip method", e); } @@ -344,14 +339,13 @@ public class PlayerController { playerActivity = new WeakReference<>((Activity) view.getContext()); if (VERBOSE) Log.d(TAG, "addSkipSponsorView15: view=" + view.toString()); + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) view).getChildAt(2); Activity context = ((Activity) viewGroup.getContext()); - viewGroup.addView(new SkipSegmentView(context)); - viewGroup.addView(new NewSegmentHelperLayout(context)); - SponsorBlockUtils.addImageButton(context, 40); + NewSegmentHelperLayout.context = context; } }, 500); } @@ -365,15 +359,7 @@ public class PlayerController { public void run() { final ViewGroup viewGroup = (ViewGroup) view.getParent(); Activity activity = (Activity) viewGroup.getContext(); - viewGroup.addView(new SkipSegmentView(activity)); - viewGroup.addView(new NewSegmentHelperLayout(activity)); - - // add image button when creating new activity - SponsorBlockUtils.addImageButton(activity, 5); - -// InjectedPlugin.printViewStack(viewGroup, 0); - -// SponsorBlockUtils.addImageButton(activity); + NewSegmentHelperLayout.context = activity; } }, 500); } diff --git a/app/src/main/java/pl/jakubweg/ShieldButton.java b/app/src/main/java/pl/jakubweg/ShieldButton.java index f6b7bc38..fb9e7c3f 100644 --- a/app/src/main/java/pl/jakubweg/ShieldButton.java +++ b/app/src/main/java/pl/jakubweg/ShieldButton.java @@ -13,8 +13,9 @@ import com.google.android.apps.youtube.app.YouTubeApplication; import java.lang.ref.WeakReference; +import static fi.razerman.youtube.XGlobals.debug; + public class ShieldButton { - static boolean debug = true; static String TAG = "SHIELD"; static RelativeLayout _youtubeControlsLayout; static WeakReference _shieldBtn = new WeakReference<>(null); @@ -54,7 +55,7 @@ public class ShieldButton { changeVisibilityImmediate(false); } catch (Exception ex) { - Log.e("XError", "Unable to set RelativeLayout", ex); + Log.e(TAG, "Unable to set RelativeLayout", ex); } } @@ -78,7 +79,7 @@ public class ShieldButton { if (_youtubeControlsLayout == null || iView == null) return; if (visible && shouldBeShown()) { - if (debug){ + if (debug) { Log.d(TAG, "Fading in"); } iView.setVisibility(View.VISIBLE); @@ -88,7 +89,7 @@ public class ShieldButton { } if (iView.getVisibility() == View.VISIBLE) { - if (debug){ + if (debug) { Log.d(TAG, "Fading out"); } if (!immediate) diff --git a/app/src/main/java/pl/jakubweg/SkipSegmentView.java b/app/src/main/java/pl/jakubweg/SkipSegmentView.java index 2c9edeae..cd1a891b 100644 --- a/app/src/main/java/pl/jakubweg/SkipSegmentView.java +++ b/app/src/main/java/pl/jakubweg/SkipSegmentView.java @@ -4,69 +4,28 @@ import android.annotation.SuppressLint; import android.content.Context; import android.util.DisplayMetrics; import android.util.Log; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; import android.widget.Toast; +import com.google.android.apps.youtube.app.YouTubeApplication; + import java.lang.ref.WeakReference; +import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.hideSkipButton; +import static fi.vanced.libraries.youtube.sponsors.player.ui.SponsorBlockView.showSkipButton; import static pl.jakubweg.PlayerController.VERBOSE; import static pl.jakubweg.StringRef.str; @SuppressLint({"RtlHardcoded", "SetTextI18n", "LongLogTag", "AppCompatCustomView"}) -public class SkipSegmentView extends TextView implements View.OnClickListener { +public class SkipSegmentView { public static final String TAG = "jakubweg.SkipSegmentView"; - private static boolean isVisible = false; - private static WeakReference view = new WeakReference<>(null); private static SponsorSegment lastNotifiedSegment; - public SkipSegmentView(Context context) { - super(context); - isVisible = false; - setVisibility(GONE); - view = new WeakReference<>(this); - - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT, - Gravity.END | Gravity.RIGHT | Gravity.CENTER_VERTICAL - ); - this.setLayoutParams(layoutParams); - this.setBackgroundColor(0x66000000); -// this.setBackgroundColor(Color.MAGENTA); - this.setTextColor(0xFFFFFFFF); - int padding = (int) convertDpToPixel(4, context); - setPadding(padding, padding, padding, padding); - - this.setText(str("tap_skip")); - - setOnClickListener(this); - } - public static void show() { - if (isVisible) return; - SkipSegmentView view = SkipSegmentView.view.get(); - if (VERBOSE) - Log.d(TAG, "show; view=" + view); - if (view != null) { - view.setVisibility(VISIBLE); - view.bringToFront(); - view.requestLayout(); - view.invalidate(); - } - isVisible = true; + showSkipButton(); } public static void hide() { - if (!isVisible) return; - SkipSegmentView view = SkipSegmentView.view.get(); - if (VERBOSE) - Log.d(TAG, "hide; view=" + view); - if (view != null) - view.setVisibility(GONE); - isVisible = false; + hideSkipButton(); } public static void notifySkipped(SponsorSegment segment) { @@ -77,19 +36,15 @@ public class SkipSegmentView extends TextView implements View.OnClickListener { } lastNotifiedSegment = segment; String skipMessage = segment.category.skipMessage.toString(); - SkipSegmentView view = SkipSegmentView.view.get(); + Context context = YouTubeApplication.getAppContext(); if (VERBOSE) - Log.d(TAG, String.format("notifySkipped; view=%s, message=%s", view, skipMessage)); - if (view != null) - Toast.makeText(view.getContext(), skipMessage, Toast.LENGTH_SHORT).show(); + Log.d(TAG, String.format("notifySkipped; message=%s", skipMessage)); + + if (context != null) + Toast.makeText(context, skipMessage, Toast.LENGTH_SHORT).show(); } public static float convertDpToPixel(float dp, Context context) { return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT); } - - @Override - public void onClick(View v) { - PlayerController.onSkipSponsorClicked(); - } } diff --git a/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java b/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java index 0d3c1f9b..844c7253 100644 --- a/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java +++ b/app/src/main/java/pl/jakubweg/SponsorBlockUtils.java @@ -46,6 +46,7 @@ import java.util.TimeZone; import static android.view.View.GONE; import static android.view.View.VISIBLE; +import static fi.razerman.youtube.XGlobals.debug; import static pl.jakubweg.PlayerController.VERBOSE; import static pl.jakubweg.PlayerController.getCurrentVideoId; import static pl.jakubweg.PlayerController.getLastKnownVideoTime; @@ -64,6 +65,9 @@ public abstract class SponsorBlockUtils { public static final View.OnClickListener sponsorBlockBtnListener = new View.OnClickListener() { @Override public void onClick(View v) { + if (debug) { + Log.d(TAG, "Shield button clicked"); + } NewSegmentHelperLayout.toggle(); } }; @@ -280,102 +284,6 @@ public abstract class SponsorBlockUtils { i.setVisibility(GONE); } - @SuppressLint("LongLogTag") - public static void addImageButton(final Activity activity, final int attemptsWhenFail) { - if (VERBOSE) - Log.d(TAG, "addImageButton activity=" + activity + ",attemptsWhenFail=" + attemptsWhenFail); - - if (activity == null) - return; - - final View existingSponsorBtn = activity.findViewById(sponsorBtnId); - if (existingSponsorBtn != null) { - if (VERBOSE) - Log.d(TAG, "addImageButton: sponsorBtn exists"); - if (/*isAddNewSegmentEnabled*/false) - showButton(); - return; - } - - String packageName = activity.getPackageName(); - Resources R = activity.getResources(); - shareBtnId = R.getIdentifier("player_share_button", "id", packageName); -// final int addToBtnId = R.getIdentifier("player_addto_button", "id", packageName); - final int addToBtnId = R.getIdentifier("live_chat_overlay_button", "id", packageName); - int titleViewId = R.getIdentifier("player_video_title_view", "id", packageName); -// final int iconId = R.getIdentifier("player_fast_forward", "drawable", packageName); - final int iconId = R.getIdentifier("ic_sb_logo", "drawable", packageName); - - - final View addToBtn = activity.findViewById(addToBtnId); - final ImageView shareBtn = activity.findViewById(shareBtnId); - final TextView titleView = activity.findViewById(titleViewId); - - if (addToBtn == null || shareBtn == null || titleView == null) { - if (VERBOSE) - Log.e(TAG, String.format("one of following is null: addToBtn=%s shareBtn=%s titleView=%s", - addToBtn, shareBtn, titleView)); - - if (attemptsWhenFail > 0) - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - if (VERBOSE) - Log.i(TAG, "Retrying addImageButton"); - addImageButton(PlayerController.playerActivity.get(), attemptsWhenFail - 1); - } - }, 5000); - return; - } - - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - try { - - Class touchImageViewClass = Class.forName("com.google.android.libraries.youtube.common.ui.TouchImageView"); - Constructor constructor = touchImageViewClass.getConstructor(Context.class); - final ImageView instance = ((ImageView) constructor.newInstance(activity)); - instance.setImageResource(iconId); - instance.setId(sponsorBtnId); - - RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(shareBtn.getLayoutParams()); - layoutParams.addRule(RelativeLayout.LEFT_OF, addToBtnId); - - instance.setLayoutParams(layoutParams); - ((ViewGroup) shareBtn.getParent()).addView(instance, 0); - - - instance.setPadding(shareBtn.getPaddingLeft(), - shareBtn.getPaddingTop(), - shareBtn.getPaddingRight(), - shareBtn.getPaddingBottom()); - - - RelativeLayout.LayoutParams titleViewLayoutParams = (RelativeLayout.LayoutParams) titleView.getLayoutParams(); - titleViewLayoutParams.addRule(RelativeLayout.START_OF, sponsorBtnId); - titleView.requestLayout(); - - instance.setClickable(true); - instance.setFocusable(true); - Drawable.ConstantState constantState = shareBtn.getBackground().mutate().getConstantState(); - if (constantState != null) - instance.setBackground(constantState.newDrawable()); - - instance.setOnClickListener(sponsorBlockBtnListener); - sponsorBlockBtn = new WeakReference<>(instance); - isShown = true; - if (!/*isAddNewSegmentEnabled*/false) - hideButton(); - if (VERBOSE) - Log.i(TAG, "Image Button added"); - } catch (Exception e) { - Log.e(TAG, "Error while adding button", e); - } - } - }); - } - @SuppressLint("DefaultLocale") public static void onMarkLocationClicked(Context context) { newSponsorSegmentDialogShownMillis = PlayerController.getLastKnownVideoTime(); diff --git a/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_grey600_36.png b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_grey600_36.png new file mode 100644 index 00000000..9bf15075 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_grey600_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_white_36.png b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_white_36.png new file mode 100644 index 00000000..6900f436 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_forward_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_grey600_36.png b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_grey600_36.png new file mode 100644 index 00000000..a6b4168f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_grey600_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_white_36.png b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_white_36.png new file mode 100644 index 00000000..e1baaa33 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/quantum_ic_fast_rewind_white_36.png differ diff --git a/app/src/main/res/drawable/player_fast_forward.xml b/app/src/main/res/drawable/player_fast_forward.xml new file mode 100644 index 00000000..7b063c32 --- /dev/null +++ b/app/src/main/res/drawable/player_fast_forward.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/player_fast_rewind.xml b/app/src/main/res/drawable/player_fast_rewind.xml new file mode 100644 index 00000000..dcfeee5b --- /dev/null +++ b/app/src/main/res/drawable/player_fast_rewind.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/inline_sponsor_overlay.xml b/app/src/main/res/layout/inline_sponsor_overlay.xml new file mode 100644 index 00000000..9d67ac57 --- /dev/null +++ b/app/src/main/res/layout/inline_sponsor_overlay.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/new_segment.xml b/app/src/main/res/layout/new_segment.xml new file mode 100644 index 00000000..18fad916 --- /dev/null +++ b/app/src/main/res/layout/new_segment.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/skip_sponsor_button.xml b/app/src/main/res/layout/skip_sponsor_button.xml new file mode 100644 index 00000000..fc7e3e65 --- /dev/null +++ b/app/src/main/res/layout/skip_sponsor_button.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 05de3704..71e9c244 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -214,6 +214,8 @@ Already read Show me + Skip sponsor +