Skip to content
This repository was archived by the owner on Dec 29, 2025. It is now read-only.

Commit 77f0941

Browse files
anddeainotia00
andauthored
feat(YouTube): Update Overlay buttons, add Hide live chat messages and more Start page options (#39)
* feat(YouTube): Add `Hide live chat messages` * feat(YouTube/Overlay buttons): Add ability to reset speed back to default on second tap and hold * feat(YouTube/Overlay buttons): Add `Time-ordered playlist` from channel videos * feat(YouTube): Add `Hide live chat replay` * fix(YouTube/Swipe controls): Add paddings and corner radius for better design * fix(YouTube/Seekbar components): Use middle dot separator for append timestamp information * feat(YouTube/Swipe controls): Add adjustable `Swipe overlay screen size` * fix(YouTube/Swipe controls): Normalize default text size --------- Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
1 parent 31366b6 commit 77f0941

File tree

9 files changed

+158
-44
lines changed

9 files changed

+158
-44
lines changed

app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerComponentsFilter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public PlayerComponentsFilter() {
5656
"single_item_information_panel"
5757
);
5858

59+
final StringFilterGroup liveChat = new StringFilterGroup(
60+
Settings.HIDE_LIVE_CHAT_MESSAGES,
61+
"live_chat_text_message",
62+
"viewer_engagement_message" // message about poll, not poll itself
63+
);
64+
5965
final StringFilterGroup medicalPanel = new StringFilterGroup(
6066
Settings.HIDE_MEDICAL_PANEL,
6167
"emergency_onebox",
@@ -79,6 +85,7 @@ public PlayerComponentsFilter() {
7985
channelWaterMark,
8086
infoCards,
8187
infoPanel,
88+
liveChat,
8289
medicalPanel,
8390
suggestedActions,
8491
timedReactions

app/src/main/java/app/revanced/integrations/youtube/patches/components/QuickActionFilter.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public final class QuickActionFilter extends Filter {
1616
private final StringFilterGroup bufferFilterPathRule;
1717
private final ByteArrayFilterGroupList bufferButtonsGroupList = new ByteArrayFilterGroupList();
1818

19+
private final StringFilterGroup liveChatReplay;
20+
1921
public QuickActionFilter() {
2022
quickActionRule = new StringFilterGroup(null, QUICK_ACTION_PATH);
2123
addIdentifierCallbacks(quickActionRule);
@@ -24,6 +26,11 @@ public QuickActionFilter() {
2426
"|ContainerType|button.eml|"
2527
);
2628

29+
liveChatReplay = new StringFilterGroup(
30+
Settings.HIDE_LIVE_CHAT_REPLAY_BUTTON,
31+
"live_chat_ep_entrypoint"
32+
);
33+
2734
addPathCallbacks(
2835
new StringFilterGroup(
2936
Settings.HIDE_QUICK_ACTIONS_LIKE_BUTTON,
@@ -49,7 +56,8 @@ public QuickActionFilter() {
4956
Settings.HIDE_QUICK_ACTIONS_RELATED_VIDEO,
5057
"fullscreen_related_videos"
5158
),
52-
bufferFilterPathRule
59+
bufferFilterPathRule,
60+
liveChatReplay
5361
);
5462

5563
bufferButtonsGroupList.addAll(
@@ -88,7 +96,10 @@ private boolean isEveryFilterGroupEnabled() {
8896

8997
@Override
9098
public boolean isFiltered(String path, @Nullable String identifier, String allValue, byte[] protobufBufferArray,
91-
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
99+
StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) {
100+
if (matchedGroup == liveChatReplay) {
101+
return super.isFiltered(path, identifier, allValue, protobufBufferArray, matchedGroup, contentType, contentIndex);
102+
}
92103
if (!path.startsWith(QUICK_ACTION_PATH)) {
93104
return false;
94105
}

app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/SpeedDialog.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@ public SpeedDialog(ViewGroup bottomControlsViewGroup) {
2525
Settings.OVERLAY_BUTTON_SPEED_DIALOG,
2626
view -> VideoUtils.showPlaybackSpeedDialog(view.getContext()),
2727
view -> {
28-
VideoInformation.overridePlaybackSpeed(1.0f);
29-
showToastShort(str("revanced_overlay_button_speed_dialog_reset"));
28+
if (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get() ||
29+
VideoInformation.getPlaybackSpeed() == Settings.DEFAULT_PLAYBACK_SPEED.get()) {
30+
VideoInformation.overridePlaybackSpeed(1.0f);
31+
showToastShort(str("revanced_overlay_button_speed_dialog_reset", "1.0"));
32+
} else {
33+
float defaultSpeed = Settings.DEFAULT_PLAYBACK_SPEED.get();
34+
VideoInformation.overridePlaybackSpeed(defaultSpeed);
35+
showToastShort(str("revanced_overlay_button_speed_dialog_reset", defaultSpeed));
36+
}
37+
3038
return true;
3139
}
3240
);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package app.revanced.integrations.youtube.patches.overlaybutton;
2+
3+
import android.view.View;
4+
import android.view.ViewGroup;
5+
6+
import androidx.annotation.Nullable;
7+
8+
import app.revanced.integrations.shared.utils.Logger;
9+
import app.revanced.integrations.youtube.settings.Settings;
10+
import app.revanced.integrations.youtube.utils.VideoUtils;
11+
12+
@SuppressWarnings("unused")
13+
public class TimeOrderedPlaylist extends BottomControlButton {
14+
@Nullable
15+
private static TimeOrderedPlaylist instance;
16+
17+
public TimeOrderedPlaylist(ViewGroup bottomControlsViewGroup) {
18+
super(
19+
bottomControlsViewGroup,
20+
"time_ordered_playlist_button",
21+
Settings.OVERLAY_BUTTON_TIME_ORDERED_PLAYLIST,
22+
view -> VideoUtils.playlistFromChannelVideosListener(true),
23+
view -> {
24+
VideoUtils.playlistFromChannelVideosListener(false);
25+
return true;
26+
}
27+
);
28+
}
29+
30+
/**
31+
* Injection point.
32+
*/
33+
public static void initialize(View bottomControlsViewGroup) {
34+
try {
35+
if (bottomControlsViewGroup instanceof ViewGroup viewGroup) {
36+
instance = new TimeOrderedPlaylist(viewGroup);
37+
}
38+
} catch (Exception ex) {
39+
Logger.printException(() -> "initialize failure", ex);
40+
}
41+
}
42+
43+
/**
44+
* Injection point.
45+
*/
46+
public static void changeVisibility(boolean showing, boolean animation) {
47+
if (instance != null) instance.setVisibility(showing, animation);
48+
}
49+
50+
public static void changeVisibilityNegatedImmediate() {
51+
if (instance != null) instance.setVisibilityNegatedImmediate();
52+
}
53+
54+
}

app/src/main/java/app/revanced/integrations/youtube/patches/player/PlayerPatch.java

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
import java.lang.ref.WeakReference;
2424
import java.util.Objects;
25-
import java.util.regex.Matcher;
26-
import java.util.regex.Pattern;
2725

2826
import app.revanced.integrations.shared.settings.BaseSettings;
2927
import app.revanced.integrations.shared.settings.BooleanSetting;
@@ -112,7 +110,7 @@ public static void onVideoDescriptionCreate(RecyclerView recyclerView) {
112110
if (contentView.getId() != contentId) {
113111
return;
114112
}
115-
// This method is invoked whenever the Engagement panel is opened. (Description, Chapters, Comments, etc)
113+
// This method is invoked whenever the Engagement panel is opened. (Description, Chapters, Comments, etc.)
116114
// Check the title of the Engagement panel to prevent unnecessary clicking.
117115
if (!isDescriptionPanel) {
118116
return;
@@ -511,30 +509,20 @@ public static boolean hidePiPModeMenu(boolean original) {
511509
public static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000;
512510

513511
public static String appendTimeStampInformation(String original) {
514-
if (!Settings.APPEND_TIME_STAMP_INFORMATION.get())
515-
return original;
512+
if (!Settings.APPEND_TIME_STAMP_INFORMATION.get()) return original;
516513

517-
final String regex = "\\((.*?)\\)";
518-
final Matcher matcher = Pattern.compile(regex).matcher(original);
514+
String appendString = Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get()
515+
? VideoUtils.getFormattedQualityString(null)
516+
: VideoUtils.getFormattedSpeedString(null);
519517

520-
if (matcher.find()) {
521-
String matcherGroup = matcher.group(1);
522-
String appendString = String.format(
523-
"\u2009(%s)",
524-
Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get()
525-
? VideoUtils.getFormattedQualityString(matcherGroup)
526-
: VideoUtils.getFormattedSpeedString(matcherGroup)
527-
);
528-
return original.replaceAll(regex, "") + appendString;
529-
} else {
530-
String appendString = String.format(
531-
"\u2009(%s)",
532-
Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get()
533-
? VideoUtils.getFormattedQualityString(null)
534-
: VideoUtils.getFormattedSpeedString(null)
535-
);
536-
return original + appendString;
537-
}
518+
// Encapsulate the entire appendString with bidi control characters
519+
appendString = "\u2066" + appendString + "\u2069";
520+
521+
// Format the original string with the appended timestamp information
522+
return String.format(
523+
"%s\u2009\u2009%s", // Add the separator and the appended information
524+
original, appendString
525+
);
538526
}
539527

540528
public static void setContainerClickListener(View view) {

app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ public class Settings extends BaseSettings {
186186
public static final BooleanSetting HIDE_FILMSTRIP_OVERLAY = new BooleanSetting("revanced_hide_filmstrip_overlay", FALSE, true);
187187
public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", FALSE, true);
188188
public static final BooleanSetting HIDE_INFO_PANEL = new BooleanSetting("revanced_hide_info_panel", TRUE);
189+
public static final BooleanSetting HIDE_LIVE_CHAT_MESSAGES = new BooleanSetting("revanced_hide_live_chat_messages", FALSE);
189190
public static final BooleanSetting HIDE_MEDICAL_PANEL = new BooleanSetting("revanced_hide_medical_panel", TRUE);
190191
public static final BooleanSetting HIDE_SEEK_MESSAGE = new BooleanSetting("revanced_hide_seek_message", FALSE, true);
191192
public static final BooleanSetting HIDE_SEEK_UNDO_MESSAGE = new BooleanSetting("revanced_hide_seek_undo_message", FALSE, true);
@@ -256,6 +257,7 @@ public class Settings extends BaseSettings {
256257
public static final BooleanSetting DISABLE_ENGAGEMENT_PANEL = new BooleanSetting("revanced_disable_engagement_panel", FALSE, true);
257258
public static final BooleanSetting SHOW_VIDEO_TITLE_SECTION = new BooleanSetting("revanced_show_video_title_section", TRUE, true, parent(DISABLE_ENGAGEMENT_PANEL));
258259
public static final BooleanSetting HIDE_AUTOPLAY_PREVIEW = new BooleanSetting("revanced_hide_autoplay_preview", FALSE, true);
260+
public static final BooleanSetting HIDE_LIVE_CHAT_REPLAY_BUTTON = new BooleanSetting("revanced_hide_live_chat_replay_button", FALSE);
259261
public static final BooleanSetting HIDE_RELATED_VIDEO_OVERLAY = new BooleanSetting("revanced_hide_related_video_overlay", FALSE, true);
260262

261263
public static final BooleanSetting HIDE_QUICK_ACTIONS = new BooleanSetting("revanced_hide_quick_actions", FALSE, true);
@@ -300,6 +302,7 @@ public class Settings extends BaseSettings {
300302
public static final BooleanSetting OVERLAY_BUTTON_COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_overlay_button_copy_video_url_timestamp", FALSE);
301303
public static final BooleanSetting OVERLAY_BUTTON_EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_overlay_button_external_downloader", FALSE);
302304
public static final BooleanSetting OVERLAY_BUTTON_SPEED_DIALOG = new BooleanSetting("revanced_overlay_button_speed_dialog", FALSE);
305+
public static final BooleanSetting OVERLAY_BUTTON_TIME_ORDERED_PLAYLIST = new BooleanSetting("revanced_overlay_button_time_ordered_playlist", FALSE);
303306
public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_package_name", "com.deniscerri.ytdl");
304307
public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action", FALSE);
305308

@@ -375,7 +378,8 @@ public class Settings extends BaseSettings {
375378
public static final BooleanSetting SWIPE_LOCK_MODE = new BooleanSetting("revanced_swipe_gestures_lock_mode", FALSE, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
376379
public static final IntegerSetting SWIPE_MAGNITUDE_THRESHOLD = new IntegerSetting("revanced_swipe_magnitude_threshold", 0, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
377380
public static final IntegerSetting SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
378-
public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_overlay_text_size", 27, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
381+
public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_overlay_text_size", 20, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
382+
public static final IntegerSetting SWIPE_OVERLAY_RECT_SIZE = new IntegerSetting("revanced_swipe_overlay_rect_size", 20, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
379383
public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME));
380384

381385
/** @noinspection DeprecatedIsStillUsed*/

app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/SwipeZonesController.kt

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import android.util.TypedValue
55
import android.view.ViewGroup
66
import app.revanced.integrations.shared.utils.ResourceUtils.ResourceType
77
import app.revanced.integrations.shared.utils.ResourceUtils.getIdentifier
8+
import app.revanced.integrations.shared.utils.StringRef.str
9+
import app.revanced.integrations.shared.utils.Utils
10+
import app.revanced.integrations.youtube.settings.Settings
811
import app.revanced.integrations.youtube.swipecontrols.misc.Rectangle
912
import app.revanced.integrations.youtube.swipecontrols.misc.applyDimension
1013
import kotlin.math.min
@@ -39,6 +42,20 @@ class SwipeZonesController(
3942
private val host: Activity,
4043
private val fallbackScreenRect: () -> Rectangle
4144
) {
45+
/**
46+
* rect size for the overlay
47+
*/
48+
private val MAXIMUM_OVERLAY_RECT_SIZE = 50
49+
50+
private var overlayRectSize = Settings.SWIPE_OVERLAY_RECT_SIZE.get()
51+
set(value) {
52+
field = value
53+
validateOverlayRectSize()
54+
}
55+
56+
init {
57+
validateOverlayRectSize()
58+
}
4259
/**
4360
* 20dp, in pixels
4461
*/
@@ -64,6 +81,17 @@ class SwipeZonesController(
6481
*/
6582
private var playerRect: Rectangle? = null
6683

84+
/**
85+
* validate if provided rect size is not bigger than MAX available size
86+
*/
87+
private fun validateOverlayRectSize() {
88+
if (overlayRectSize <= 0 || overlayRectSize > MAXIMUM_OVERLAY_RECT_SIZE) {
89+
Utils.showToastLong(str("revanced_swipe_overlay_rect_size_warning", MAXIMUM_OVERLAY_RECT_SIZE.toString()))
90+
Settings.SWIPE_OVERLAY_RECT_SIZE.resetToDefault()
91+
overlayRectSize = Settings.SWIPE_OVERLAY_RECT_SIZE.get()
92+
}
93+
}
94+
6795
/**
6896
* rectangle of the area that is effectively usable for swipe controls
6997
*/
@@ -84,13 +112,12 @@ class SwipeZonesController(
84112
*/
85113
val volume: Rectangle
86114
get() {
87-
val eRect = effectiveSwipeRect
88-
val zoneWidth = (eRect.width * 3) / 8
115+
val zoneWidth = effectiveSwipeRect.width * overlayRectSize / 100
89116
return Rectangle(
90-
eRect.right - zoneWidth,
91-
eRect.top,
117+
effectiveSwipeRect.right - zoneWidth,
118+
effectiveSwipeRect.top,
92119
zoneWidth,
93-
eRect.height
120+
effectiveSwipeRect.height
94121
)
95122
}
96123

@@ -99,7 +126,7 @@ class SwipeZonesController(
99126
*/
100127
val brightness: Rectangle
101128
get() {
102-
val zoneWidth = (effectiveSwipeRect.width * 3) / 8
129+
val zoneWidth = effectiveSwipeRect.width * overlayRectSize / 100
103130
return Rectangle(
104131
effectiveSwipeRect.left,
105132
effectiveSwipeRect.top,
@@ -142,4 +169,4 @@ class SwipeZonesController(
142169
)
143170
}
144171
}
145-
}
172+
}

app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class SwipeControlsOverlayLayout(
5656

5757
init {
5858
// init views
59-
val feedbackTextViewPadding = 2.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
59+
val feedbackYTextViewPadding = 5.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
60+
val feedbackXTextViewPadding = 12.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
6061
val compoundIconPadding = 4.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP)
6162
feedbackTextView = TextView(context).apply {
6263
layoutParams = LayoutParams(
@@ -65,14 +66,14 @@ class SwipeControlsOverlayLayout(
6566
).apply {
6667
addRule(CENTER_IN_PARENT, TRUE)
6768
setPadding(
68-
feedbackTextViewPadding,
69-
feedbackTextViewPadding,
70-
feedbackTextViewPadding,
71-
feedbackTextViewPadding
69+
feedbackXTextViewPadding,
70+
feedbackYTextViewPadding,
71+
feedbackXTextViewPadding,
72+
feedbackYTextViewPadding
7273
)
7374
}
7475
background = GradientDrawable().apply {
75-
cornerRadius = 8f
76+
cornerRadius = 30f
7677
setColor(config.overlayTextBackgroundColor)
7778
}
7879
setTextColor(config.overlayForegroundColor)
@@ -145,4 +146,4 @@ class SwipeControlsOverlayLayout(
145146
)
146147
}
147148
}
148-
}
149+
}

app/src/main/java/app/revanced/integrations/youtube/utils/VideoUtils.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@ public static void launchExternalDownloader(@NonNull String videoId) {
106106
}
107107
}
108108

109+
/**
110+
* Create playlist from all channel videos from oldest to newest,
111+
* starting from the video where button is clicked.
112+
*/
113+
public static void playlistFromChannelVideosListener(boolean activated) {
114+
final String videoId = VideoInformation.getVideoId();
115+
String baseUri = "vnd.youtube://" + videoId + "?start=" + VideoInformation.getVideoTime() / 1000;
116+
if (activated) {
117+
baseUri += "&list=UL" + videoId;
118+
}
119+
120+
launchView(baseUri, getContext().getPackageName());
121+
}
122+
109123
public static void showPlaybackSpeedDialog(@NonNull Context context) {
110124
final String[] playbackSpeedWithAutoEntries = CustomPlaybackSpeedPatch.getListEntries();
111125
final String[] playbackSpeedWithAutoEntryValues = CustomPlaybackSpeedPatch.getListEntryValues();

0 commit comments

Comments
 (0)