diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerComponentsFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerComponentsFilter.java index 81a6d4b91d..2a88d9f2e7 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/PlayerComponentsFilter.java @@ -56,6 +56,12 @@ public PlayerComponentsFilter() { "single_item_information_panel" ); + final StringFilterGroup liveChat = new StringFilterGroup( + Settings.HIDE_LIVE_CHAT_MESSAGES, + "live_chat_text_message", + "viewer_engagement_message" // message about poll, not poll itself + ); + final StringFilterGroup medicalPanel = new StringFilterGroup( Settings.HIDE_MEDICAL_PANEL, "emergency_onebox", @@ -79,6 +85,7 @@ public PlayerComponentsFilter() { channelWaterMark, infoCards, infoPanel, + liveChat, medicalPanel, suggestedActions, timedReactions diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/components/QuickActionFilter.java b/app/src/main/java/app/revanced/integrations/youtube/patches/components/QuickActionFilter.java index 0a9b4b432c..badf0690e1 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/components/QuickActionFilter.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/components/QuickActionFilter.java @@ -16,6 +16,8 @@ public final class QuickActionFilter extends Filter { private final StringFilterGroup bufferFilterPathRule; private final ByteArrayFilterGroupList bufferButtonsGroupList = new ByteArrayFilterGroupList(); + private final StringFilterGroup liveChatReplay; + public QuickActionFilter() { quickActionRule = new StringFilterGroup(null, QUICK_ACTION_PATH); addIdentifierCallbacks(quickActionRule); @@ -24,6 +26,11 @@ public QuickActionFilter() { "|ContainerType|button.eml|" ); + liveChatReplay = new StringFilterGroup( + Settings.HIDE_LIVE_CHAT_REPLAY_BUTTON, + "live_chat_ep_entrypoint" + ); + addPathCallbacks( new StringFilterGroup( Settings.HIDE_QUICK_ACTIONS_LIKE_BUTTON, @@ -49,7 +56,8 @@ public QuickActionFilter() { Settings.HIDE_QUICK_ACTIONS_RELATED_VIDEO, "fullscreen_related_videos" ), - bufferFilterPathRule + bufferFilterPathRule, + liveChatReplay ); bufferButtonsGroupList.addAll( @@ -88,7 +96,10 @@ private boolean isEveryFilterGroupEnabled() { @Override public boolean isFiltered(String path, @Nullable String identifier, String allValue, byte[] protobufBufferArray, - StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { + StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { + if (matchedGroup == liveChatReplay) { + return super.isFiltered(path, identifier, allValue, protobufBufferArray, matchedGroup, contentType, contentIndex); + } if (!path.startsWith(QUICK_ACTION_PATH)) { return false; } diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/SpeedDialog.java b/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/SpeedDialog.java index 4173ff32d7..aaa49d91d9 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/SpeedDialog.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/SpeedDialog.java @@ -25,8 +25,16 @@ public SpeedDialog(ViewGroup bottomControlsViewGroup) { Settings.OVERLAY_BUTTON_SPEED_DIALOG, view -> VideoUtils.showPlaybackSpeedDialog(view.getContext()), view -> { - VideoInformation.overridePlaybackSpeed(1.0f); - showToastShort(str("revanced_overlay_button_speed_dialog_reset")); + if (!Settings.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.get() || + VideoInformation.getPlaybackSpeed() == Settings.DEFAULT_PLAYBACK_SPEED.get()) { + VideoInformation.overridePlaybackSpeed(1.0f); + showToastShort(str("revanced_overlay_button_speed_dialog_reset", "1.0")); + } else { + float defaultSpeed = Settings.DEFAULT_PLAYBACK_SPEED.get(); + VideoInformation.overridePlaybackSpeed(defaultSpeed); + showToastShort(str("revanced_overlay_button_speed_dialog_reset", defaultSpeed)); + } + return true; } ); diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/TimeOrderedPlaylist.java b/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/TimeOrderedPlaylist.java new file mode 100644 index 0000000000..4d6716d6c6 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/overlaybutton/TimeOrderedPlaylist.java @@ -0,0 +1,54 @@ +package app.revanced.integrations.youtube.patches.overlaybutton; + +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import app.revanced.integrations.shared.utils.Logger; +import app.revanced.integrations.youtube.settings.Settings; +import app.revanced.integrations.youtube.utils.VideoUtils; + +@SuppressWarnings("unused") +public class TimeOrderedPlaylist extends BottomControlButton { + @Nullable + private static TimeOrderedPlaylist instance; + + public TimeOrderedPlaylist(ViewGroup bottomControlsViewGroup) { + super( + bottomControlsViewGroup, + "time_ordered_playlist_button", + Settings.OVERLAY_BUTTON_TIME_ORDERED_PLAYLIST, + view -> VideoUtils.playlistFromChannelVideosListener(true), + view -> { + VideoUtils.playlistFromChannelVideosListener(false); + return true; + } + ); + } + + /** + * Injection point. + */ + public static void initialize(View bottomControlsViewGroup) { + try { + if (bottomControlsViewGroup instanceof ViewGroup viewGroup) { + instance = new TimeOrderedPlaylist(viewGroup); + } + } catch (Exception ex) { + Logger.printException(() -> "initialize failure", ex); + } + } + + /** + * Injection point. + */ + public static void changeVisibility(boolean showing, boolean animation) { + if (instance != null) instance.setVisibility(showing, animation); + } + + public static void changeVisibilityNegatedImmediate() { + if (instance != null) instance.setVisibilityNegatedImmediate(); + } + +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/patches/player/PlayerPatch.java b/app/src/main/java/app/revanced/integrations/youtube/patches/player/PlayerPatch.java index 9653e7bf66..35e9993f06 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/patches/player/PlayerPatch.java +++ b/app/src/main/java/app/revanced/integrations/youtube/patches/player/PlayerPatch.java @@ -22,8 +22,6 @@ import java.lang.ref.WeakReference; import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import app.revanced.integrations.shared.settings.BaseSettings; import app.revanced.integrations.shared.settings.BooleanSetting; @@ -112,7 +110,7 @@ public static void onVideoDescriptionCreate(RecyclerView recyclerView) { if (contentView.getId() != contentId) { return; } - // This method is invoked whenever the Engagement panel is opened. (Description, Chapters, Comments, etc) + // This method is invoked whenever the Engagement panel is opened. (Description, Chapters, Comments, etc.) // Check the title of the Engagement panel to prevent unnecessary clicking. if (!isDescriptionPanel) { return; @@ -511,30 +509,20 @@ public static boolean hidePiPModeMenu(boolean original) { public static final int ORIGINAL_SEEKBAR_COLOR = 0xFFFF0000; public static String appendTimeStampInformation(String original) { - if (!Settings.APPEND_TIME_STAMP_INFORMATION.get()) - return original; + if (!Settings.APPEND_TIME_STAMP_INFORMATION.get()) return original; - final String regex = "\\((.*?)\\)"; - final Matcher matcher = Pattern.compile(regex).matcher(original); + String appendString = Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get() + ? VideoUtils.getFormattedQualityString(null) + : VideoUtils.getFormattedSpeedString(null); - if (matcher.find()) { - String matcherGroup = matcher.group(1); - String appendString = String.format( - "\u2009(%s)", - Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get() - ? VideoUtils.getFormattedQualityString(matcherGroup) - : VideoUtils.getFormattedSpeedString(matcherGroup) - ); - return original.replaceAll(regex, "") + appendString; - } else { - String appendString = String.format( - "\u2009(%s)", - Settings.APPEND_TIME_STAMP_INFORMATION_TYPE.get() - ? VideoUtils.getFormattedQualityString(null) - : VideoUtils.getFormattedSpeedString(null) - ); - return original + appendString; - } + // Encapsulate the entire appendString with bidi control characters + appendString = "\u2066" + appendString + "\u2069"; + + // Format the original string with the appended timestamp information + return String.format( + "%s\u2009•\u2009%s", // Add the separator and the appended information + original, appendString + ); } public static void setContainerClickListener(View view) { diff --git a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java index 29db8ce9a4..d3966f883a 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java +++ b/app/src/main/java/app/revanced/integrations/youtube/settings/Settings.java @@ -187,6 +187,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting HIDE_FILMSTRIP_OVERLAY = new BooleanSetting("revanced_hide_filmstrip_overlay", FALSE, true); public static final BooleanSetting HIDE_INFO_CARDS = new BooleanSetting("revanced_hide_info_cards", FALSE, true); public static final BooleanSetting HIDE_INFO_PANEL = new BooleanSetting("revanced_hide_info_panel", TRUE); + public static final BooleanSetting HIDE_LIVE_CHAT_MESSAGES = new BooleanSetting("revanced_hide_live_chat_messages", FALSE); public static final BooleanSetting HIDE_MEDICAL_PANEL = new BooleanSetting("revanced_hide_medical_panel", TRUE); public static final BooleanSetting HIDE_SEEK_MESSAGE = new BooleanSetting("revanced_hide_seek_message", FALSE, true); public static final BooleanSetting HIDE_SEEK_UNDO_MESSAGE = new BooleanSetting("revanced_hide_seek_undo_message", FALSE, true); @@ -257,6 +258,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting DISABLE_ENGAGEMENT_PANEL = new BooleanSetting("revanced_disable_engagement_panel", FALSE, true); public static final BooleanSetting SHOW_VIDEO_TITLE_SECTION = new BooleanSetting("revanced_show_video_title_section", TRUE, true, parent(DISABLE_ENGAGEMENT_PANEL)); public static final BooleanSetting HIDE_AUTOPLAY_PREVIEW = new BooleanSetting("revanced_hide_autoplay_preview", FALSE, true); + public static final BooleanSetting HIDE_LIVE_CHAT_REPLAY_BUTTON = new BooleanSetting("revanced_hide_live_chat_replay_button", FALSE); public static final BooleanSetting HIDE_RELATED_VIDEO_OVERLAY = new BooleanSetting("revanced_hide_related_video_overlay", FALSE, true); public static final BooleanSetting HIDE_QUICK_ACTIONS = new BooleanSetting("revanced_hide_quick_actions", FALSE, true); @@ -301,6 +303,7 @@ public class Settings extends BaseSettings { public static final BooleanSetting OVERLAY_BUTTON_COPY_VIDEO_URL_TIMESTAMP = new BooleanSetting("revanced_overlay_button_copy_video_url_timestamp", FALSE); public static final BooleanSetting OVERLAY_BUTTON_EXTERNAL_DOWNLOADER = new BooleanSetting("revanced_overlay_button_external_downloader", FALSE); public static final BooleanSetting OVERLAY_BUTTON_SPEED_DIALOG = new BooleanSetting("revanced_overlay_button_speed_dialog", FALSE); + public static final BooleanSetting OVERLAY_BUTTON_TIME_ORDERED_PLAYLIST = new BooleanSetting("revanced_overlay_button_time_ordered_playlist", FALSE); public static final StringSetting EXTERNAL_DOWNLOADER_PACKAGE_NAME = new StringSetting("revanced_external_downloader_package_name", "com.deniscerri.ytdl"); public static final BooleanSetting EXTERNAL_DOWNLOADER_ACTION_BUTTON = new BooleanSetting("revanced_external_downloader_action", FALSE); @@ -376,7 +379,8 @@ public class Settings extends BaseSettings { public static final BooleanSetting SWIPE_LOCK_MODE = new BooleanSetting("revanced_swipe_gestures_lock_mode", FALSE, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); public static final IntegerSetting SWIPE_MAGNITUDE_THRESHOLD = new IntegerSetting("revanced_swipe_magnitude_threshold", 0, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); public static final IntegerSetting SWIPE_OVERLAY_BACKGROUND_ALPHA = new IntegerSetting("revanced_swipe_overlay_background_alpha", 127, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); - public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_overlay_text_size", 27, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); + public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_overlay_text_size", 20, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); + public static final IntegerSetting SWIPE_OVERLAY_RECT_SIZE = new IntegerSetting("revanced_swipe_overlay_rect_size", 20, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true, parentsAny(ENABLE_SWIPE_BRIGHTNESS, ENABLE_SWIPE_VOLUME)); /** @noinspection DeprecatedIsStillUsed*/ diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/SwipeZonesController.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/SwipeZonesController.kt index 1f7b569825..030e84ea56 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/SwipeZonesController.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/controller/SwipeZonesController.kt @@ -5,6 +5,9 @@ import android.util.TypedValue import android.view.ViewGroup import app.revanced.integrations.shared.utils.ResourceUtils.ResourceType import app.revanced.integrations.shared.utils.ResourceUtils.getIdentifier +import app.revanced.integrations.shared.utils.StringRef.str +import app.revanced.integrations.shared.utils.Utils +import app.revanced.integrations.youtube.settings.Settings import app.revanced.integrations.youtube.swipecontrols.misc.Rectangle import app.revanced.integrations.youtube.swipecontrols.misc.applyDimension import kotlin.math.min @@ -39,6 +42,20 @@ class SwipeZonesController( private val host: Activity, private val fallbackScreenRect: () -> Rectangle ) { + /** + * rect size for the overlay + */ + private val MAXIMUM_OVERLAY_RECT_SIZE = 50 + + private var overlayRectSize = Settings.SWIPE_OVERLAY_RECT_SIZE.get() + set(value) { + field = value + validateOverlayRectSize() + } + + init { + validateOverlayRectSize() + } /** * 20dp, in pixels */ @@ -64,6 +81,17 @@ class SwipeZonesController( */ private var playerRect: Rectangle? = null + /** + * validate if provided rect size is not bigger than MAX available size + */ + private fun validateOverlayRectSize() { + if (overlayRectSize <= 0 || overlayRectSize > MAXIMUM_OVERLAY_RECT_SIZE) { + Utils.showToastLong(str("revanced_swipe_overlay_rect_size_warning", MAXIMUM_OVERLAY_RECT_SIZE.toString())) + Settings.SWIPE_OVERLAY_RECT_SIZE.resetToDefault() + overlayRectSize = Settings.SWIPE_OVERLAY_RECT_SIZE.get() + } + } + /** * rectangle of the area that is effectively usable for swipe controls */ @@ -84,13 +112,12 @@ class SwipeZonesController( */ val volume: Rectangle get() { - val eRect = effectiveSwipeRect - val zoneWidth = (eRect.width * 3) / 8 + val zoneWidth = effectiveSwipeRect.width * overlayRectSize / 100 return Rectangle( - eRect.right - zoneWidth, - eRect.top, + effectiveSwipeRect.right - zoneWidth, + effectiveSwipeRect.top, zoneWidth, - eRect.height + effectiveSwipeRect.height ) } @@ -99,7 +126,7 @@ class SwipeZonesController( */ val brightness: Rectangle get() { - val zoneWidth = (effectiveSwipeRect.width * 3) / 8 + val zoneWidth = effectiveSwipeRect.width * overlayRectSize / 100 return Rectangle( effectiveSwipeRect.left, effectiveSwipeRect.top, @@ -142,4 +169,4 @@ class SwipeZonesController( ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt index bc628a9e94..9e6bf6bd60 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt +++ b/app/src/main/java/app/revanced/integrations/youtube/swipecontrols/views/SwipeControlsOverlayLayout.kt @@ -56,7 +56,8 @@ class SwipeControlsOverlayLayout( init { // init views - val feedbackTextViewPadding = 2.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP) + val feedbackYTextViewPadding = 5.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP) + val feedbackXTextViewPadding = 12.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP) val compoundIconPadding = 4.applyDimension(context, TypedValue.COMPLEX_UNIT_DIP) feedbackTextView = TextView(context).apply { layoutParams = LayoutParams( @@ -65,14 +66,14 @@ class SwipeControlsOverlayLayout( ).apply { addRule(CENTER_IN_PARENT, TRUE) setPadding( - feedbackTextViewPadding, - feedbackTextViewPadding, - feedbackTextViewPadding, - feedbackTextViewPadding + feedbackXTextViewPadding, + feedbackYTextViewPadding, + feedbackXTextViewPadding, + feedbackYTextViewPadding ) } background = GradientDrawable().apply { - cornerRadius = 8f + cornerRadius = 30f setColor(config.overlayTextBackgroundColor) } setTextColor(config.overlayForegroundColor) @@ -145,4 +146,4 @@ class SwipeControlsOverlayLayout( ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/app/revanced/integrations/youtube/utils/VideoUtils.java b/app/src/main/java/app/revanced/integrations/youtube/utils/VideoUtils.java index 52a17b4b45..35e32da90f 100644 --- a/app/src/main/java/app/revanced/integrations/youtube/utils/VideoUtils.java +++ b/app/src/main/java/app/revanced/integrations/youtube/utils/VideoUtils.java @@ -106,6 +106,20 @@ public static void launchExternalDownloader(@NonNull String videoId) { } } + /** + * Create playlist from all channel videos from oldest to newest, + * starting from the video where button is clicked. + */ + public static void playlistFromChannelVideosListener(boolean activated) { + final String videoId = VideoInformation.getVideoId(); + String baseUri = "vnd.youtube://" + videoId + "?start=" + VideoInformation.getVideoTime() / 1000; + if (activated) { + baseUri += "&list=UL" + videoId; + } + + launchView(baseUri, getContext().getPackageName()); + } + public static void showPlaybackSpeedDialog(@NonNull Context context) { final String[] playbackSpeedWithAutoEntries = CustomPlaybackSpeedPatch.getListEntries(); final String[] playbackSpeedWithAutoEntryValues = CustomPlaybackSpeedPatch.getListEntryValues();