diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java index 6c0975a90..19685e31a 100644 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch.java @@ -3,23 +3,29 @@ package app.revanced.extension.spotify.layout.hide.createbutton; import java.util.List; import app.revanced.extension.shared.Logger; -import app.revanced.extension.shared.Utils; +import app.revanced.extension.spotify.shared.ComponentFilters.*; @SuppressWarnings("unused") public final class HideCreateButtonPatch { /** - * A list of ids of resources which contain the Create button title. + * A list of component filters that match whether a navigation bar item is the Create button. + * The main approach used is matching the resource id for the Create button title. */ - private static final List CREATE_BUTTON_TITLE_RES_ID_LIST = List.of( - Integer.toString(Utils.getResourceIdentifier("navigationbar_musicappitems_create_title", "string")) + private static final List CREATE_BUTTON_COMPONENT_FILTERS = List.of( + new ResourceIdComponentFilter("navigationbar_musicappitems_create_title", "string"), + // Temporary fallback and fix for APKs merged with AntiSplit-M not having resources properly encoded, + // and thus getting the resource identifier for the Create button title always return 0. + // FIXME: Remove this once the above issue is no longer relevant. + new StringComponentFilter("spotify:create-menu") ); /** - * The old id of the resource which contained the Create button title. Used in older versions of the app. + * A component filter for the old id of the resource which contained the Create button title. + * Used in older versions of the app. */ - private static final int OLD_CREATE_BUTTON_TITLE_RES_ID = - Utils.getResourceIdentifier("bottom_navigation_bar_create_tab_title", "string"); + private static final ResourceIdComponentFilter OLD_CREATE_BUTTON_COMPONENT_FILTER = + new ResourceIdComponentFilter("bottom_navigation_bar_create_tab_title", "string"); /** * Injection point. This method is called on every navigation bar item to check whether it is the Create button. @@ -33,28 +39,20 @@ public final class HideCreateButtonPatch { String stringifiedNavigationBarItem = navigationBarItem.toString(); - boolean isCreateButton = false; - String matchedTitleResId = null; - - for (String titleResId : CREATE_BUTTON_TITLE_RES_ID_LIST) { - // In case the resource id has not been found. - if (titleResId.equals("0")) { + for (ComponentFilter componentFilter : CREATE_BUTTON_COMPONENT_FILTERS) { + if (componentFilter.filterUnavailable()) { + Logger.printInfo(() -> "returnNullIfIsCreateButton: Filter " + + componentFilter.getFilterRepresentation() + " not available, skipping"); continue; } - if (stringifiedNavigationBarItem.contains(titleResId)) { - isCreateButton = true; - matchedTitleResId = titleResId; + if (stringifiedNavigationBarItem.contains(componentFilter.getFilterValue())) { + Logger.printInfo(() -> "Hiding Create button because the navigation bar item " + navigationBarItem + + " matched the filter " + componentFilter.getFilterRepresentation()); + return null; } } - if (isCreateButton) { - String finalMatchedTitleResId = matchedTitleResId; - Logger.printInfo(() -> "Hiding Create button because the navigation bar item " + navigationBarItem + - " matched the title resource id " + finalMatchedTitleResId); - return null; - } - return navigationBarItem; } @@ -63,16 +61,15 @@ public final class HideCreateButtonPatch { * Create button. */ public static boolean isOldCreateButton(int oldNavigationBarItemTitleResId) { - // In case the resource id has not been found. - if (OLD_CREATE_BUTTON_TITLE_RES_ID == 0) { + if (OLD_CREATE_BUTTON_COMPONENT_FILTER.filterUnavailable()) { + Logger.printInfo(() -> "Skipping hiding old Create button because the resource id for " + + OLD_CREATE_BUTTON_COMPONENT_FILTER.resourceName + " is not available"); return false; } - boolean isCreateButton = oldNavigationBarItemTitleResId == OLD_CREATE_BUTTON_TITLE_RES_ID; - - if (isCreateButton) { + if (oldNavigationBarItemTitleResId == OLD_CREATE_BUTTON_COMPONENT_FILTER.getResourceId()) { Logger.printInfo(() -> "Hiding old Create button because the navigation bar item title resource id" + - " matched " + OLD_CREATE_BUTTON_TITLE_RES_ID); + " matched " + OLD_CREATE_BUTTON_COMPONENT_FILTER.getFilterRepresentation()); return true; } diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/shared/ComponentFilters.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/shared/ComponentFilters.java new file mode 100644 index 000000000..0349c713b --- /dev/null +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/shared/ComponentFilters.java @@ -0,0 +1,79 @@ +package app.revanced.extension.spotify.shared; + +import app.revanced.extension.shared.Logger; +import app.revanced.extension.shared.Utils; + +public final class ComponentFilters { + + public interface ComponentFilter { + String getFilterValue(); + String getFilterRepresentation(); + default boolean filterUnavailable() { + return false; + } + } + + public static final class ResourceIdComponentFilter implements ComponentFilter { + + public final String resourceName; + public final String resourceType; + // Android resources are always positive, so -1 is a valid sentinel value to indicate it has not been loaded. + // 0 is returned when a resource has not been found. + private int resourceId = -1; + private String stringfiedResourceId = null; + + public ResourceIdComponentFilter(String resourceName, String resourceType) { + this.resourceName = resourceName; + this.resourceType = resourceType; + } + + public int getResourceId() { + if (resourceId == -1) { + resourceId = Utils.getResourceIdentifier(resourceName, resourceType); + } + return resourceId; + } + + @Override + public String getFilterValue() { + if (stringfiedResourceId == null) { + stringfiedResourceId = Integer.toString(getResourceId()); + } + return stringfiedResourceId; + } + + @Override + public String getFilterRepresentation() { + boolean resourceFound = getResourceId() != 0; + return (resourceFound ? getFilterValue() + " (" : "") + resourceName + (resourceFound ? ")" : ""); + } + + @Override + public boolean filterUnavailable() { + boolean resourceNotFound = getResourceId() == 0; + if (resourceNotFound) { + Logger.printInfo(() -> "Resource id for " + resourceName + " was not found"); + } + return resourceNotFound; + } + } + + public static final class StringComponentFilter implements ComponentFilter { + + public final String string; + + public StringComponentFilter(String string) { + this.string = string; + } + + @Override + public String getFilterValue() { + return string; + } + + @Override + public String getFilterRepresentation() { + return string; + } + } +}