Skip to content

chore: Merge branch dev to main #5428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jul 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
## [5.31.2-dev.5](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.4...v5.31.2-dev.5) (2025-07-14)


### Bug Fixes

* **Spotify - Spoof client:** Fix login failing by spoofing login request in addition ([#5448](https://github.com/ReVanced/revanced-patches/issues/5448)) ([4e59ddc](https://github.com/ReVanced/revanced-patches/commit/4e59ddc62388d09f71b89593fc8b76933d9facea))

## [5.31.2-dev.4](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.3...v5.31.2-dev.4) (2025-07-13)


### Bug Fixes

* **YouTube - Settings:** Back button/gesture closes search instead of exiting ([#5418](https://github.com/ReVanced/revanced-patches/issues/5418)) ([134b278](https://github.com/ReVanced/revanced-patches/commit/134b278baa7b90d2c4b06200cabacabf55ebc055))

## [5.31.2-dev.3](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.2...v5.31.2-dev.3) (2025-07-13)


### Bug Fixes

* **YouTube - Disable double tap actions:** Remove old incompatible targets ([857053e](https://github.com/ReVanced/revanced-patches/commit/857053e29b72ded10a84b0ac693fa107705342d9))

## [5.31.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v5.31.2-dev.1...v5.31.2-dev.2) (2025-07-12)


### Bug Fixes

* **YouTube - Hide layout components:** Show correct custom header logo if 'Hide YouTube Doodles' is enabled ([#5431](https://github.com/ReVanced/revanced-patches/issues/5431)) ([20cc141](https://github.com/ReVanced/revanced-patches/commit/20cc141e61f75de1a1749247c4f4aed167dee8ea))

## [5.31.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.1...v5.31.2-dev.1) (2025-07-12)


### Bug Fixes

* **YouTube - Hide layout components:** Hide quick actions does not work ([#5423](https://github.com/ReVanced/revanced-patches/issues/5423)) ([9c66729](https://github.com/ReVanced/revanced-patches/commit/9c6672946d44001e106bdac9041e2d79ef3f6ab2))

## [5.31.1](https://github.com/ReVanced/revanced-patches/compare/v5.31.0...v5.31.1) (2025-07-11)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,101 @@
package app.revanced.extension.youtube.patches;

import android.graphics.drawable.Drawable;

import androidx.annotation.Nullable;

import java.util.Objects;

import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings("unused")
public class ChangeHeaderPatch {

public enum HeaderLogo {
DEFAULT(null),
REGULAR("ytWordmarkHeader"),
PREMIUM("ytPremiumWordmarkHeader"),
REVANCED("revanced_header_logo"),
REVANCED_MINIMAL("revanced_header_logo_minimal"),
CUSTOM("custom_header");
DEFAULT(null, null),
REGULAR("ytWordmarkHeader", "yt_ringo2_wordmark_header"),
PREMIUM("ytPremiumWordmarkHeader", "yt_ringo2_premium_wordmark_header"),
REVANCED("revanced_header_logo", "revanced_header_logo"),
REVANCED_MINIMAL("revanced_header_logo_minimal", "revanced_header_logo_minimal"),
CUSTOM("custom_header", "custom_header");

@Nullable
private final String resourceName;
private final String attributeName;
@Nullable
private final String drawableName;

HeaderLogo(@Nullable String resourceName) {
this.resourceName = resourceName;
HeaderLogo(@Nullable String attributeName, @Nullable String drawableName) {
this.attributeName = attributeName;
this.drawableName = drawableName;
}

/**
* @return The attribute id of this header logo, or NULL if the logo should not be replaced.
*/
@Nullable
private Integer getAttributeId() {
if (resourceName == null) {
if (attributeName == null) {
return null;
}

final int identifier = Utils.getResourceIdentifier(attributeName, "attr");
if (identifier == 0) {
// Identifier is zero if custom header setting was included in imported settings
// and a custom image was not included during patching.
Logger.printDebug(() -> "Could not find attribute: " + drawableName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}

final int identifier = Utils.getResourceIdentifier(resourceName, "attr");
// Identifier is zero if custom header setting was included in imported settings
// and a custom image was not included during patching.
return identifier == 0 ? null : identifier;
return identifier;
}
}

@Nullable
private static final Integer headerLogoResource = Settings.HEADER_LOGO.get().getAttributeId();
@Nullable
public Drawable getDrawable() {
if (drawableName == null) {
return null;
}

String drawableFullName = drawableName + (Utils.isDarkModeEnabled()
? "_dark"
: "_light");

final int identifier = Utils.getResourceIdentifier(drawableFullName, "drawable");
if (identifier == 0) {
Logger.printDebug(() -> "Could not find drawable: " + drawableFullName);
Settings.HEADER_LOGO.resetToDefault();
return null;
}
return Utils.getContext().getDrawable(identifier);
}
}

/**
* Injection point.
*/
public static int getHeaderAttributeId(int original) {
return Objects.requireNonNullElse(headerLogoResource, original);
return Objects.requireNonNullElse(Settings.HEADER_LOGO.get().getAttributeId(), original);
}

public static Drawable getDrawable(Drawable original) {
Drawable logo = Settings.HEADER_LOGO.get().getDrawable();
if (logo != null) {
return logo;
}

// TODO: If 'Hide Doodles' is enabled, this will force the regular logo regardless
// what account the user has. This can be improved the next time a Doodle is
// active and the attribute id is passed to this method so the correct
// regular/premium logo is returned.
logo = HeaderLogo.REGULAR.getDrawable();
if (logo != null) {
return logo;
}

// Should never happen.
Logger.printException(() -> "Could not find regular header logo resource");
return original;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings("unused")
public final class DisableChapterSkipDoubleTapPatch {
public final class DisableDoubleTapActionsPatch {

/**
* Injection point.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.Nullable;

import app.revanced.extension.shared.Logger;
import app.revanced.extension.shared.Utils;
import app.revanced.extension.youtube.StringTrieSearch;
import app.revanced.extension.youtube.patches.ChangeHeaderPatch;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.NavigationBar;
import app.revanced.extension.youtube.shared.PlayerType;
Expand All @@ -30,7 +32,7 @@ public final class LayoutComponentsFilter extends Filter {
);

private final StringTrieSearch exceptions = new StringTrieSearch();
private final StringFilterGroup inFeedSurvey;
private final StringFilterGroup surveys;
private final StringFilterGroup notifyMe;
private final StringFilterGroup singleItemInformationPanel;
private final StringFilterGroup expandableMetadata;
Expand Down Expand Up @@ -108,8 +110,8 @@ public LayoutComponentsFilter() {
"chip_bar"
);

inFeedSurvey = new StringFilterGroup(
Settings.HIDE_FEED_SURVEY,
surveys = new StringFilterGroup(
Settings.HIDE_SURVEYS,
"in_feed_survey",
"slimline_survey",
"feed_nudge"
Expand Down Expand Up @@ -284,17 +286,18 @@ public LayoutComponentsFilter() {
forYouShelf,
horizontalShelves,
imageShelf,
inFeedSurvey,
infoPanel,
latestPosts,
medicalPanel,
notifyMe,
paidPromotion,
playables,
quickActions,
relatedVideos,
singleItemInformationPanel,
subscribersCommunityGuidelines,
subscriptionsChipBar,
surveys,
timedReactions,
videoRecommendationLabels
);
Expand All @@ -314,7 +317,7 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff

// The groups are excluded from the filter due to the exceptions list below.
// Filter them separately here.
if (matchedGroup == notifyMe || matchedGroup == inFeedSurvey || matchedGroup == expandableMetadata) {
if (matchedGroup == notifyMe || matchedGroup == surveys || matchedGroup == expandableMetadata) {
return true;
}

Expand Down Expand Up @@ -436,13 +439,11 @@ public static void hideInRelatedVideos(View chipView) {
/**
* Injection point.
*/
@Nullable
public static Drawable hideYoodles(Drawable animatedYoodle) {
if (HIDE_DOODLES_ENABLED) {
return null;
}

return animatedYoodle;
public static void setDoodleDrawable(ImageView imageView, Drawable original) {
Drawable replacement = HIDE_DOODLES_ENABLED
? ChangeHeaderPatch.getDrawable(original)
: original;
imageView.setImageDrawable(replacement);
}

private static final boolean HIDE_SHOW_MORE_BUTTON_ENABLED = Settings.HIDE_SHOW_MORE_BUTTON.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.app.Activity;
import android.content.Context;
import android.preference.PreferenceFragment;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toolbar;
Expand All @@ -24,12 +25,15 @@
* This class is responsible for injecting our own fragment by replacing the LicenseActivity.
*/
@SuppressWarnings("unused")
public class LicenseActivityHook {
public class LicenseActivityHook extends Activity {

private static int currentThemeValueOrdinal = -1; // Must initially be a non-valid enum ordinal value.

private static ViewGroup.LayoutParams toolbarLayoutParams;

@SuppressLint("StaticFieldLeak")
public static SearchViewController searchViewController;

public static void setToolbarLayoutParams(Toolbar toolbar) {
if (toolbarLayoutParams != null) {
toolbar.setLayoutParams(toolbarLayoutParams);
Expand Down Expand Up @@ -126,12 +130,13 @@ private static void createToolbar(Activity activity, PreferenceFragment fragment
view -> view instanceof TextView);
if (toolbarTextView != null) {
toolbarTextView.setTextColor(Utils.getAppForegroundColor());
toolbarTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
}
setToolbarLayoutParams(toolbar);

// Add Search Icon and EditText for ReVancedPreferenceFragment only.
// Add Search bar only for ReVancedPreferenceFragment.
if (fragment instanceof ReVancedPreferenceFragment) {
SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
searchViewController = SearchViewController.addSearchViewComponents(activity, toolbar, (ReVancedPreferenceFragment) fragment);
}

toolBarParent.addView(toolbar, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.util.Pair;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
Expand Down Expand Up @@ -51,6 +52,7 @@ public class SearchViewController {
private final Deque<String> searchHistory;
private final AutoCompleteTextView autoCompleteTextView;
private final boolean showSettingsSearchHistory;
private int currentOrientation;

/**
* Creates a background drawable for the SearchView with rounded corners.
Expand Down Expand Up @@ -83,8 +85,8 @@ public static int getSearchViewBackground() {
/**
* Adds search view components to the activity.
*/
public static void addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
new SearchViewController(activity, toolbar, fragment);
public static SearchViewController addSearchViewComponents(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
return new SearchViewController(activity, toolbar, fragment);
}

private SearchViewController(Activity activity, Toolbar toolbar, ReVancedPreferenceFragment fragment) {
Expand Down Expand Up @@ -115,6 +117,9 @@ private SearchViewController(Activity activity, Toolbar toolbar, ReVancedPrefere
searchView.getContext().getResources().getIdentifier(
"android:id/search_src_text", null, null));

// Disable fullscreen keyboard mode.
autoCompleteTextView.setImeOptions(autoCompleteTextView.getImeOptions() | EditorInfo.IME_FLAG_NO_EXTRACT_UI);

// Set background and query hint.
searchView.setBackground(createBackgroundDrawable(toolbar.getContext()));
searchView.setQueryHint(str("revanced_settings_search_hint"));
Expand Down Expand Up @@ -197,12 +202,14 @@ public boolean onQueryTextChange(String newText) {
if (isSearchActive) {
closeSearch();
} else {
activity.onBackPressed();
activity.finish();
}
} catch (Exception ex) {
Logger.printException(() -> "navigation click failure", ex);
}
});

monitorOrientationChanges();
}

/**
Expand Down Expand Up @@ -285,6 +292,21 @@ private void updateSearchHistoryAdapter() {
}
}

private void monitorOrientationChanges() {
currentOrientation = activity.getResources().getConfiguration().orientation;

searchView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
int newOrientation = activity.getResources().getConfiguration().orientation;
if (newOrientation != currentOrientation) {
currentOrientation = newOrientation;
if (autoCompleteTextView != null) {
autoCompleteTextView.dismissDropDown();
Logger.printDebug(() -> "Orientation changed, search history dismissed");
}
}
});
}

/**
* Opens the search view and shows the keyboard.
*/
Expand Down Expand Up @@ -313,7 +335,7 @@ private void openSearch() {
/**
* Closes the search view and hides the keyboard.
*/
private void closeSearch() {
public void closeSearch() {
isSearchActive = false;
toolbar.getMenu().findItem(getResourceIdentifier(
"action_search", "id")).setVisible(true);
Expand All @@ -326,6 +348,19 @@ private void closeSearch() {
imm.hideSoftInputFromWindow(searchView.getWindowToken(), 0);
}

public static boolean handleBackPress() {
if (LicenseActivityHook.searchViewController != null
&& LicenseActivityHook.searchViewController.isSearchExpanded()) {
LicenseActivityHook.searchViewController.closeSearch();
return true;
}
return false;
}

public boolean isSearchExpanded() {
return isSearchActive;
}

/**
* Custom ArrayAdapter for search history.
*/
Expand Down
Loading
Loading