-
-
Notifications
You must be signed in to change notification settings - Fork 102
feat(YouTube): Introduce Litho text component and span filtering framework #1277
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
Open
ILoveOpenSourceApplications
wants to merge
7
commits into
dev
Choose a base branch
from
feat/add-spans
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2f59df5
feat(YouTube): Introduce Litho text component and span filtering fram…
ILoveOpenSourceApplications ae703c1
refactor: Use Java `record` and simplify `if else`
ILoveOpenSourceApplications 1ec6590
Formatting, no functional changes
LisoUseInAIKyrios 356c884
refactor
LisoUseInAIKyrios f5e6736
feat(YouTube): Introduce Litho text component and span filtering fram…
ILoveOpenSourceApplications 56e192f
Merge branch 'dev' into feat/add-spans
ILoveOpenSourceApplications e2ef914
Revert "feat(YouTube): Introduce Litho text component and span filter…
ILoveOpenSourceApplications File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
extensions/youtube/src/main/java/app/morphe/extension/youtube/patches/spans/Filter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /* | ||
| * Copyright 2026 Morphe. | ||
| * https://github.com/MorpheApp/morphe-patches | ||
| * | ||
| * Original hard forked code: | ||
| * https://github.com/ReVanced/revanced-patches/commit/724e6d61b2ecd868c1a9a37d465a688e83a74799 | ||
| * | ||
| * See the included NOTICE file for GPLv3 §7(b) and §7(c) terms that apply to Morphe contributions. | ||
| */ | ||
|
|
||
| package app.morphe.extension.youtube.patches.spans; | ||
|
|
||
| import android.graphics.Color; | ||
| import android.graphics.drawable.ColorDrawable; | ||
| import android.graphics.drawable.Drawable; | ||
| import android.text.SpannableString; | ||
| import android.text.style.ImageSpan; | ||
| import android.text.style.RelativeSizeSpan; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * Filters litho based components. | ||
| * <p> | ||
| * All callbacks must be registered before the constructor completes. | ||
| */ | ||
| abstract class Filter { | ||
| private static final RelativeSizeSpan relativeSizeSpanDummy = new RelativeSizeSpan(0f); | ||
| private static final Drawable transparentDrawable = new ColorDrawable(Color.TRANSPARENT); | ||
| private static final ImageSpan imageSpanDummy = new ImageSpan(transparentDrawable); | ||
|
|
||
| /** | ||
| * Path callbacks. Do not add to this instance, | ||
| * and instead use {@link #addCallbacks(StringFilterGroup...)}. | ||
| */ | ||
| protected final List<StringFilterGroup> callbacks = new ArrayList<>(); | ||
|
|
||
| /** | ||
| * Adds callbacks to {@link #skip(String, SpannableString, Object, int, int, int, boolean, SpanType, StringFilterGroup)} | ||
| * if any of the groups are found. | ||
| */ | ||
| protected final void addCallbacks(StringFilterGroup... groups) { | ||
| callbacks.addAll(Arrays.asList(groups)); | ||
| } | ||
|
|
||
| protected final void hideSpan(SpannableString spannableString, int start, int end, int flags) { | ||
| spannableString.setSpan(relativeSizeSpanDummy, start, end, flags); | ||
| } | ||
|
|
||
| protected final void hideImageSpan(SpannableString spannableString, int start, int end, int flags) { | ||
| spannableString.setSpan(imageSpanDummy, start, end, flags); | ||
| } | ||
|
|
||
| /** | ||
| * Called after an enabled filter has been matched. | ||
| * Default implementation is to always filter the matched component and log the action. | ||
| * Subclasses can perform additional or different checks if needed. | ||
| * <p> | ||
| * Method is called off the main thread. | ||
| * | ||
| * @param matchedGroup The actual filter that matched. | ||
| */ | ||
| boolean skip(String conversionContext, SpannableString spannableString, Object span, int start, int end, | ||
| int flags, boolean isWord, SpanType spanType, StringFilterGroup matchedGroup) { | ||
| return true; | ||
| } | ||
| } | ||
96 changes: 96 additions & 0 deletions
96
extensions/youtube/src/main/java/app/morphe/extension/youtube/patches/spans/FilterGroup.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| /* | ||
| * Copyright 2026 Morphe. | ||
| * https://github.com/MorpheApp/morphe-patches | ||
| * | ||
| * Original hard forked code: | ||
| * https://github.com/ReVanced/revanced-patches/commit/724e6d61b2ecd868c1a9a37d465a688e83a74799 | ||
| * | ||
| * See the included NOTICE file for GPLv3 §7(b) and §7(c) terms that apply to Morphe contributions. | ||
| */ | ||
|
|
||
| package app.morphe.extension.youtube.patches.spans; | ||
|
|
||
| import androidx.annotation.NonNull; | ||
|
|
||
| import app.morphe.extension.shared.settings.BooleanSetting; | ||
|
|
||
| abstract class FilterGroup<T> { | ||
| final static class FilterGroupResult { | ||
| private BooleanSetting setting; | ||
| private int matchedIndex; | ||
|
|
||
| FilterGroupResult() { | ||
| this(null, -1); | ||
| } | ||
|
|
||
| FilterGroupResult(BooleanSetting setting, int matchedIndex) { | ||
| setValues(setting, matchedIndex); | ||
| } | ||
|
|
||
| public void setValues(BooleanSetting setting, int matchedIndex) { | ||
| this.setting = setting; | ||
| this.matchedIndex = matchedIndex; | ||
| } | ||
|
|
||
| public BooleanSetting getSetting() { | ||
| return setting; | ||
| } | ||
|
|
||
| public boolean isFiltered() { | ||
| return matchedIndex >= 0; | ||
| } | ||
| } | ||
|
|
||
| protected final BooleanSetting setting; | ||
| protected final T[] filters; | ||
|
|
||
| @SafeVarargs | ||
| public FilterGroup(final BooleanSetting setting, final T... filters) { | ||
| this.setting = setting; | ||
| this.filters = filters; | ||
| if (filters.length == 0) { | ||
| throw new IllegalArgumentException("Must use one or more filter patterns (zero specified)"); | ||
| } | ||
| } | ||
|
|
||
| public boolean isEnabled() { | ||
| return setting == null || setting.get(); | ||
| } | ||
|
|
||
| @SuppressWarnings("BooleanMethodIsAlwaysInverted") | ||
| public boolean includeInSearch() { | ||
| return isEnabled() || !setting.rebootApp; | ||
| } | ||
|
|
||
| @NonNull | ||
| @Override | ||
| public String toString() { | ||
| return getClass().getSimpleName() + ": " + (setting == null ? "(null setting)" : setting); | ||
| } | ||
|
|
||
| public abstract FilterGroupResult check(final T stack); | ||
| } | ||
|
|
||
| class StringFilterGroup extends FilterGroup<String> { | ||
|
|
||
| public StringFilterGroup(final BooleanSetting setting, final String... filters) { | ||
| super(setting, filters); | ||
| } | ||
|
|
||
| @Override | ||
| public FilterGroupResult check(final String string) { | ||
| int matchedIndex = -1; | ||
| if (isEnabled()) { | ||
| for (String pattern : filters) { | ||
| if (!string.isEmpty()) { | ||
| final int indexOf = string.indexOf(pattern); | ||
| if (indexOf >= 0) { | ||
| matchedIndex = indexOf; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return new FilterGroupResult(setting, matchedIndex); | ||
| } | ||
| } |
82 changes: 82 additions & 0 deletions
82
...ons/youtube/src/main/java/app/morphe/extension/youtube/patches/spans/FilterGroupList.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /* | ||
| * Copyright 2026 Morphe. | ||
| * https://github.com/MorpheApp/morphe-patches | ||
| * | ||
| * Original hard forked code: | ||
| * https://github.com/ReVanced/revanced-patches/commit/724e6d61b2ecd868c1a9a37d465a688e83a74799 | ||
| * | ||
| * See the included NOTICE file for GPLv3 §7(b) and §7(c) terms that apply to Morphe contributions. | ||
| */ | ||
|
|
||
| package app.morphe.extension.youtube.patches.spans; | ||
|
|
||
| import androidx.annotation.NonNull; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Iterator; | ||
| import java.util.List; | ||
| import java.util.Spliterator; | ||
| import java.util.function.Consumer; | ||
|
|
||
| import app.morphe.extension.shared.StringTrieSearch; | ||
| import app.morphe.extension.shared.TrieSearch; | ||
|
|
||
| abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<T> { | ||
|
|
||
| private final List<T> filterGroups = new ArrayList<>(); | ||
| private final TrieSearch<V> search = createSearchGraph(); | ||
|
|
||
| @SafeVarargs | ||
| protected final void addAll(final T... groups) { | ||
| filterGroups.addAll(Arrays.asList(groups)); | ||
|
|
||
| for (T group : groups) { | ||
| if (!group.includeInSearch()) { | ||
| continue; | ||
| } | ||
| for (V pattern : group.filters) { | ||
| search.addPattern(pattern, (textSearched, matchedStartIndex, matchedLength, callbackParameter) -> { | ||
| if (group.isEnabled()) { | ||
| FilterGroup.FilterGroupResult result = (FilterGroup.FilterGroupResult) callbackParameter; | ||
| result.setValues(group.setting, matchedStartIndex); | ||
| return true; | ||
| } | ||
| return false; | ||
| }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @NonNull | ||
| @Override | ||
| public Iterator<T> iterator() { | ||
| return filterGroups.iterator(); | ||
| } | ||
|
|
||
| @Override | ||
| public void forEach(@NonNull Consumer<? super T> action) { | ||
| filterGroups.forEach(action); | ||
| } | ||
|
|
||
| @NonNull | ||
| @Override | ||
| public Spliterator<T> spliterator() { | ||
| return filterGroups.spliterator(); | ||
| } | ||
|
|
||
| protected FilterGroup.FilterGroupResult check(V stack) { | ||
| FilterGroup.FilterGroupResult result = new FilterGroup.FilterGroupResult(); | ||
| search.matches(stack, result); | ||
| return result; | ||
| } | ||
|
|
||
| protected abstract TrieSearch<V> createSearchGraph(); | ||
| } | ||
|
|
||
| final class StringFilterGroupList extends FilterGroupList<String, StringFilterGroup> { | ||
| @Override | ||
| protected StringTrieSearch createSearchGraph() { | ||
| return new StringTrieSearch(); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.