-
-
Notifications
You must be signed in to change notification settings - Fork 7k
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
Revamp post filtering system #18058
Revamp post filtering system #18058
Conversation
1fc65f9
to
4f71f67
Compare
I like it a lot, but it looks a bit too large in my opinion. I have currently 33 filters, which could probably be changed into 10 groups, and I don’t want to scroll too much. I feel like keywords should be between title and «metadata» (places where filter is applied, expiration time). Also, the longest metadata line in English will overflow; maybe metadata should be placed on its own line below title/keywords/action buttons so that metadata line never overflows on desktop (and separated into two different lines on mobile?). |
I honestly have the same concern :/
I am not sure about that, I want to eventually have other kinds of filters, e.g. filtering specific conversations (see the following mockup):
Also a good point. |
@ariasuni reworked a bit that design by moving things around and reducing some margins, I think it addresses most of your concerns |
cbc16f0
to
0794b17
Compare
It much better in my opinion! Keyword list and conversation count could be side-to-side, though. |
245fcf2
to
fc648fb
Compare
fc648fb
to
84bed86
Compare
84bed86
to
fb0d34e
Compare
Bug: When creating a new filter i get an error message upon trying to save this including a set keyword. The error does not appear, when not setting a keyword. However, thank you much for all you do. |
What error message do you get? This is likely #18742
When no keyword is set, the filter does nothing. There are other filter types planned, but maybe the UI should be tweaked to make it clearer that the filter won't do anything without a keyword.
I'm split on this one. I can understand how the one-line display may be more usable if you have many different filters, but I think this one is more usable if your keywords are logically grouped, which I think fits the general case more. |
Thanks for getting into this, ClearlyClaire.
It is similar, but i get the server error already upon creating a new filter when adding a keyword at all (v. 3.5.3 on mastodon.online that is).
I suppose i cannot currently create any new and working filters then, as setting a keyword produces that error. Uhm.
Why not give the user a choice of display? That way you'll satisfy both power filterers as well as people, who use only a few. I am filtering a lot. It is one of my most used tools to regulate the flood into a lean experience. The current display turns out to be a major scroll monster for me :). Thank you again for anything you do. |
Yeah, it's likely the same thing then. It can occur whenever adding a keyword, whether there are keywords in the filter or not.
Yes, unfortunately, this issue may prevent you from creating any new filter… I think you can retry over and over again and eventually it should work… but you may need to retry a lot of times :/
Because it's not just the display that changed, but the whole model, and the old display would not quite work with the new model… |
When Revamp the filter system, has it been considered that filter rules created in versions below v4.0 can be migrated to the new scheme from v4.0 onwards without loss as users? This means that the user does not have to create the filters again. |
I have the new filter system and my old filters are still here. |
Okay, that sounds good, are they then "uncategorised" or how are the old filters ordered? |
They are all added as their own category. |
Hi @ClearlyClaire I tried this:
public static class KeywordsAttributes implements Serializable {
@SerializedName("id")
public String id;
@SerializedName("keyword")
public String keyword;
@SerializedName("whole_word")
public boolean whole_word;
@SerializedName("_destroy")
public boolean _destroy;
} But Keywords are not added If I use the |
That is weird, those should work… or at least I can't see anything immediately wrong with it. Are you sure you are hitting |
@stom79 unsure if related, but i can't replicate any issues with a raw curl |
yes I use @Field("keywords_attributes[][id]") List<String> keywordId,
@Field("keywords_attributes[][keyword]") List<String> keywords,
@Field("keywords_attributes[][whole_word]") List<Boolean> wholeWords instead of @Field("keywords_attributes[]") List<Filter.KeywordsAttributes> keywordsAttributes But
---------- All is working fine. Thank you. |
* Add model for custom filter keywords * Use CustomFilterKeyword internally Does not change the API * Fix /filters/edit and /filters/new * Add migration tests * Remove whole_word column from custom_filters (covered by custom_filter_keywords) * Redesign /filters Instead of a list, present a card that displays more information and handles multiple keywords per filter. * Redesign /filters/new and /filters/edit to add and remove keywords This adds a new gem dependency: cocoon, as well as a npm dependency: cocoon-js-vanilla. Those are used to easily populate and remove form fields from the user interface when manipulating multiple keyword filters at once. * Add /api/v2/filters to edit filter with multiple keywords Entities: - `Filter`: `id`, `title`, `filter_action` (either `hide` or `warn`), `context` `keywords` - `FilterKeyword`: `id`, `keyword`, `whole_word` API endpoits: - `GET /api/v2/filters` to list filters (including keywords) - `POST /api/v2/filters` to create a new filter `keywords_attributes` can also be passed to create keywords in one request - `GET /api/v2/filters/:id` to read a particular filter - `PUT /api/v2/filters/:id` to update a new filter `keywords_attributes` can also be passed to edit, delete or add keywords in one request - `DELETE /api/v2/filters/:id` to delete a particular filter - `GET /api/v2/filters/:id/keywords` to list keywords for a filter - `POST /api/v2/filters/:filter_id/keywords/:id` to add a new keyword to a filter - `GET /api/v2/filter_keywords/:id` to read a particular keyword - `PUT /api/v2/filter_keywords/:id` to edit a particular keyword - `DELETE /api/v2/filter_keywords/:id` to delete a particular keyword * Change from `irreversible` boolean to `action` enum * Remove irrelevent `irreversible_must_be_within_context` check * Fix /filters/new and /filters/edit with update for filter_action * Fix Rubocop/Codeclimate complaining about task names * Refactor FeedManager#phrase_filtered? This moves regexp building and filter caching to the `CustomFilter` class. This does not change the functional behavior yet, but this changes how the cache is built, doing per-custom_filter regexps so that filters can be matched independently, while still offering caching. * Perform server-side filtering and output result in REST API * Fix numerous filters_changed events being sent when editing multiple keywords at once * Add some tests * Use the new API in the WebUI - use client-side logic for filters we have fetched rules for. This is so that filter changes can be retroactively applied without reloading the UI. - use server-side logic for filters we haven't fetched rules for yet (e.g. network error, or initial timeline loading) * Minor optimizations and refactoring * Perform server-side filtering on the streaming server * Change the wording of filter action labels * Fix issues pointed out by linter * Change design of “Show anyway” link in accordence to review comments * Drop “irreversible” filtering behavior * Move /api/v2/filter_keywords to /api/v1/filters/keywords * Rename `filter_results` attribute to `filtered` * Rename REST::LegacyFilterSerializer to REST::V1::FilterSerializer * Fix systemChannelId value in streaming server * Simplify code by removing client-side filtering code The simplifcation comes at a cost though: filters aren't retroactively applied anymore.
@stom79 I'm seeing a similar issue here, also using retrofit, can you clarify what ended up working for you? |
@Tak Our endpoints are here for filters And our activity that manages filters We created objects for retrofit We use them directly with retrofit for POST/PUT calls Currently, I am not with my computer, but I will check that more carefully tomorrow. @Tak I just checked. The only way we made it work was to use POST/PUT calls: https://codeberg.org/tom79/Fedilab/src/branch/main/app/src/main/java/app/fedilab/android/client/endpoints/MastodonFiltersService.java#L48-L63 In the activity we loop through existing keywords to attach them to the filter params (when editing): And new ones are added on the flow: |
* Add model for custom filter keywords * Use CustomFilterKeyword internally Does not change the API * Fix /filters/edit and /filters/new * Add migration tests * Remove whole_word column from custom_filters (covered by custom_filter_keywords) * Redesign /filters Instead of a list, present a card that displays more information and handles multiple keywords per filter. * Redesign /filters/new and /filters/edit to add and remove keywords This adds a new gem dependency: cocoon, as well as a npm dependency: cocoon-js-vanilla. Those are used to easily populate and remove form fields from the user interface when manipulating multiple keyword filters at once. * Add /api/v2/filters to edit filter with multiple keywords Entities: - `Filter`: `id`, `title`, `filter_action` (either `hide` or `warn`), `context` `keywords` - `FilterKeyword`: `id`, `keyword`, `whole_word` API endpoits: - `GET /api/v2/filters` to list filters (including keywords) - `POST /api/v2/filters` to create a new filter `keywords_attributes` can also be passed to create keywords in one request - `GET /api/v2/filters/:id` to read a particular filter - `PUT /api/v2/filters/:id` to update a new filter `keywords_attributes` can also be passed to edit, delete or add keywords in one request - `DELETE /api/v2/filters/:id` to delete a particular filter - `GET /api/v2/filters/:id/keywords` to list keywords for a filter - `POST /api/v2/filters/:filter_id/keywords/:id` to add a new keyword to a filter - `GET /api/v2/filter_keywords/:id` to read a particular keyword - `PUT /api/v2/filter_keywords/:id` to edit a particular keyword - `DELETE /api/v2/filter_keywords/:id` to delete a particular keyword * Change from `irreversible` boolean to `action` enum * Remove irrelevent `irreversible_must_be_within_context` check * Fix /filters/new and /filters/edit with update for filter_action * Fix Rubocop/Codeclimate complaining about task names * Refactor FeedManager#phrase_filtered? This moves regexp building and filter caching to the `CustomFilter` class. This does not change the functional behavior yet, but this changes how the cache is built, doing per-custom_filter regexps so that filters can be matched independently, while still offering caching. * Perform server-side filtering and output result in REST API * Fix numerous filters_changed events being sent when editing multiple keywords at once * Add some tests * Use the new API in the WebUI - use client-side logic for filters we have fetched rules for. This is so that filter changes can be retroactively applied without reloading the UI. - use server-side logic for filters we haven't fetched rules for yet (e.g. network error, or initial timeline loading) * Minor optimizations and refactoring * Perform server-side filtering on the streaming server * Change the wording of filter action labels * Fix issues pointed out by linter * Change design of “Show anyway” link in accordence to review comments * Drop “irreversible” filtering behavior * Move /api/v2/filter_keywords to /api/v1/filters/keywords * Rename `filter_results` attribute to `filtered` * Rename REST::LegacyFilterSerializer to REST::V1::FilterSerializer * Fix systemChannelId value in streaming server * Simplify code by removing client-side filtering code The simplifcation comes at a cost though: filters aren't retroactively applied anymore.
Fixes #18035
New filter management UI
It's now possible to regroup filter keywords in categories.
New filtered post UI
Instead of just displaying “Filtered”, the filter category name is displayed, and an opportunity is given to show the filtered post:
test.mp4
API changes and implementation guidelines
Note that everything described here is subject to change before the feature actually gets released.
Backward compatibility
This PR provides limited backward compatibility with the
/api/v1/filters
API:GET /api/v1/filters
is supported and will return all keywords, including when multiple keywords are in a single category. Existing pre-update keywords should retain their identifier, though there is no guarantee this will be the case.GET /api/v1/filters/:id
is supported and will return a keyword, even if that keyword shares a category with other keywords. If that keyword was created pre-update, it should retain its identifier, though there is no guarantee this will be the case.POST /api/v1/filters
is supported, and will create a one-keyword filter with a title matching the keywordPUT /api/v1/filters/:id
is partially supported, and will error out if it attempts to changeexpires_in
,irreversible
orcontext
for a filter shared by multiple keywords.New API
New entities
Filter
: has attributesid
,title
,context
,expires_at
,filter_action
(currently eitherhide
orwarn
), and optionallykeywords
(list ofFilterKeyword
entities).This entity will likely be extended in the future with attributes for other rule types (e.g.
conversations
).FilterKeyword
: has attributesid
,keyword
andwhole_word
FilterResult
: has attributesfilter
(aFilter
without akeywords
attribute) as well askeyword_matches
.This entity will likely be extended in the future with attributes for other rule types (e.g.
conversation_matches
).Changes to other entities
Status
entities now optionally have afiltered
attribute which is a list ofFilterResult
entities.New API endpoints
GET /api/v2/filters
to list filters (including keywords)POST /api/v2/filters
to create a new filterkeywords_attributes
can also be passed to create keywords in one requestGET /api/v2/filters/:id
to read a particular filterPUT /api/v2/filters/:id
to update a filterkeywords_attributes
can also be passed to edit, delete or add keywords in one requestDELETE /api/v2/filters/:id
to delete a particular filterGET /api/v2/filters/:id/keywords
to list keywords for a filterPOST /api/v2/filters/:filter_id/keywords/:id
to add a new keyword to a filterGET /api/v1/filters/keywords/:id
to read a particular keywordPUT /api/v1/filters/keywords/:id
to edit a particular keywordDELETE /api/v1/filters/keywords/:id
to delete a particular keywordImplementation guidelines
Determining matched filters
Since the server provides a
filtered
attribute onStatus
entities, that can be used to check which filters apply without implementations needing to implement the rule matching themselves.However, client implementations may still want to perform rule matching client-side, as this would allow retroactively apply filter changes without re-fetching posts from the server. When doing so, they should take care of not ignoring
filtered
entries for which there are other attributes thankeyword_matches
, so as to handle future extensions of the filtering system.Applying actions on matched rules
Matched filters need to be filtered based on context (
home
,notifications
,public
,thread
orprofile
) and expiration date.When at least one active matched filter has
hide
forfilter_action
, the post should not be shown at all. Otherwise, if at least one active matched filter haswarn
forfilter_action
, the post should be hidden with a warning, and the user should be able to reveal the post after being informed of which filters matched (identified bytitle
rather than the exact matched keywords).For extension purposes, unknown values for
filter_action
should be treated aswarn
.TODO
/filters
controllers and viewsirreversible
to multiple actions/api/v2/filters
(list and manage filters)This project was funded through the NGI0 Discovery Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825322.