diff --git a/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java b/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java index 84f156706..8ad1ff689 100644 --- a/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java +++ b/mastodon/src/androidTest/java/org/joinmastodon/android/utils/StatusFilterPredicateTest.java @@ -19,7 +19,9 @@ public class StatusFilterPredicateTest { private static final Status hideInHomePublic = Status.ofFake(null, "hide me, please", Instant.now()), - warnInHomePublic = Status.ofFake(null, "display me with a warning", Instant.now()); + warnInHomePublic = Status.ofFake(null, "display me with a warning", Instant.now()), + noAltText = Status.ofFake(null, "display me with a warning", Instant.now()), + withAltText = Status.ofFake(null, "display me with a warning", Instant.now()); static { hideMeFilter.phrase = "hide me"; @@ -29,6 +31,12 @@ public class StatusFilterPredicateTest { warnMeFilter.phrase = "warning"; warnMeFilter.filterAction = WARN; warnMeFilter.context = EnumSet.of(PUBLIC, HOME); + + noAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable()); + withAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable()); + for (Attachment mediaAttachment : withAltText.mediaAttachments) { + mediaAttachment.description = "Alt Text"; + } } @Test @@ -78,4 +86,16 @@ public class StatusFilterPredicateTest { assertTrue("should pass because matching filter is for hiding", new StatusFilterPredicate(allFilters, HOME, WARN).test(hideInHomePublic)); } + + @Test + public void testAltTextFilterNoPass() { + assertFalse("should not pass because of no alt text", + new StatusFilterPredicate(allFilters, HOME).test(noAltText)); + } + + @Test + public void testAltTextFilterPass() { + assertTrue("should pass because of alt text", + new StatusFilterPredicate(allFilters, HOME).test(withAltText)); + } } \ No newline at end of file diff --git a/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java b/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java index 936b4076e..7220be48b 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java +++ b/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java @@ -18,7 +18,6 @@ import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.model.ContentType; import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.TimelineDefinition; -import org.joinmastodon.android.ui.utils.ColorPalette; import java.lang.reflect.Type; import java.util.ArrayList; @@ -48,6 +47,7 @@ public class GlobalUserPreferences{ public static boolean reduceMotion; public static boolean showAltIndicator; public static boolean showNoAltIndicator; + public static boolean showPostsWithoutAlt; public static boolean enablePreReleases; public static PrefixRepliesMode prefixReplies; public static boolean collapseLongPosts; @@ -118,6 +118,7 @@ public class GlobalUserPreferences{ reduceMotion=prefs.getBoolean("reduceMotion", false); showAltIndicator=prefs.getBoolean("showAltIndicator", true); showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true); + showPostsWithoutAlt =prefs.getBoolean("showPostsWithoutAlt", true); enablePreReleases=prefs.getBoolean("enablePreReleases", false); prefixReplies=PrefixRepliesMode.valueOf(prefs.getString("prefixReplies", PrefixRepliesMode.NEVER.name())); collapseLongPosts=prefs.getBoolean("collapseLongPosts", true); @@ -195,6 +196,7 @@ public class GlobalUserPreferences{ .putBoolean("reduceMotion", reduceMotion) .putBoolean("showAltIndicator", showAltIndicator) .putBoolean("showNoAltIndicator", showNoAltIndicator) + .putBoolean("showPostsWithoutAlt", showPostsWithoutAlt) .putBoolean("enablePreReleases", enablePreReleases) .putString("prefixReplies", prefixReplies.name()) .putBoolean("collapseLongPosts", collapseLongPosts) diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java b/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java new file mode 100644 index 000000000..2353fee96 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/model/AltTextFilter.java @@ -0,0 +1,21 @@ +package org.joinmastodon.android.model; + +import org.joinmastodon.android.GlobalUserPreferences; +import org.joinmastodon.android.R; +import org.jsoup.internal.StringUtil; + +import java.util.EnumSet; + +public class AltTextFilter extends Filter { + + public AltTextFilter(FilterAction filterAction, FilterContext firstContext, FilterContext... restContexts) { + this.filterAction = filterAction; + isRemote = false; + context = EnumSet.of(firstContext, restContexts); + } + + @Override + public boolean matches(Status status) { + return status.getContentStatus().mediaAttachments.stream().map(attachment -> attachment.description).anyMatch(StringUtil::isBlank); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java index b3ccd393d..55b7782be 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java @@ -4,18 +4,13 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.ProgressBar; import android.widget.TextView; -import androidx.recyclerview.widget.RecyclerView; - import org.joinmastodon.android.R; import org.joinmastodon.android.fragments.BaseStatusListFragment; -import org.joinmastodon.android.model.LegacyFilter; +import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Status; -import org.joinmastodon.android.ui.drawables.SawtoothTearDrawable; -import java.util.ArrayList; import java.util.List; // Mind the gap! @@ -55,7 +50,8 @@ public class WarningFilteredStatusDisplayItem extends StatusDisplayItem{ @Override public void onBind(WarningFilteredStatusDisplayItem item) { filteredItems = item.filteredItems; - text.setText(item.parentFragment.getString(R.string.sk_filtered, item.applyingFilter.title)); + String title = item.applyingFilter instanceof AltTextFilter ? item.parentFragment.getString(R.string.sk_no_alt_text) : item.applyingFilter.title; + text.setText(item.parentFragment.getString(R.string.sk_filtered, title)); } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java index 814c9f8f9..35c224e88 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java +++ b/mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java @@ -14,6 +14,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public class StatusFilterPredicate implements Predicate{ + private List clientFilters; private final List filters; private final FilterContext context; private final FilterAction action; @@ -22,12 +23,14 @@ public class StatusFilterPredicate implements Predicate{ /** * @param context null makes the predicate pass automatically * @param action defines what the predicate should check: - * status should not be hidden or should not display with warning + * status should not be hidden or should not display with warning */ public StatusFilterPredicate(List filters, FilterContext context, FilterAction action){ this.filters = filters; this.context = context; this.action = action; + this.clientFilters = GlobalUserPreferences.showPostsWithoutAlt ? List.of() + : List.of(new AltTextFilter(HIDE, HOME, PUBLIC, ACCOUNT), new AltTextFilter(WARN, THREAD, NOTIFICATIONS)); } public StatusFilterPredicate(List filters, FilterContext context){ @@ -54,7 +57,7 @@ public class StatusFilterPredicate implements Predicate{ /** * @return whether the status should be displayed without being hidden/warned about. - * will always return true if the context is null. + * will always return true if the context is null. * true = display this status, * false = filter this status */ @@ -77,6 +80,15 @@ public class StatusFilterPredicate implements Predicate{ .filter(filter -> filter.filterAction == null ? action == FilterAction.HIDE : filter.filterAction == action) .findAny(); + //Apply client filters if no server filter is triggered + if (applyingFilter.isEmpty()) { + applyingFilter = clientFilters.stream() + .filter(filter -> filter.context.contains(context)) + .filter(filter -> filter.filterAction == null ? action == HIDE : filter.filterAction == action) + .filter(filter -> filter.matches(status)) + .findAny(); + } + this.applyingFilter = applyingFilter.orElse(null); return applyingFilter.isEmpty(); } diff --git a/mastodon/src/main/res/drawable/ic_fluent_eye_tracking_on_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_eye_tracking_on_24_regular.xml new file mode 100644 index 000000000..46f2eebbc --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_eye_tracking_on_24_regular.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/values-de-rDE/strings_mo.xml b/mastodon/src/main/res/values-de-rDE/strings_mo.xml index 9ed2cc5f0..d177a6836 100644 --- a/mastodon/src/main/res/values-de-rDE/strings_mo.xml +++ b/mastodon/src/main/res/values-de-rDE/strings_mo.xml @@ -75,6 +75,8 @@ App-Symbol für alle Benachrichtigungen verwenden Animationen für Interaktionen deaktivieren GIFs in Profilbildern und Emojis automatisch abspielen + Zeige Medienbeiträge ohne Bildbeschreibung + Beiträge werden in allen Timelines ausgeblendet, können aber in Threads und Benachrichtungen angezeigt werden Schwarz und Weiß Haptisches Feedback Vibrieren beim Interagieren mit Posts diff --git a/mastodon/src/main/res/values/strings_mo.xml b/mastodon/src/main/res/values/strings_mo.xml index b9b2263f6..680f20bb4 100644 --- a/mastodon/src/main/res/values/strings_mo.xml +++ b/mastodon/src/main/res/values/strings_mo.xml @@ -82,9 +82,11 @@ Swipe to change viewed timeline Vibrate when interacting with posts Bookmark or reblog posts from the notification + Posts will be hidden in all timelines, but can be revealed in threads and notifications Notification Audience + Show media posts with missing alt text Double tap to swipe between tabs Haptic feedback Swap bookmark with reblog action