Repository: tuskyapp/Tusky (language: kotlin)

Issue:
Filters with Hashtags not working
I think we had this issue in the past, but here it is again. :)

A filter for a hastag:

![image](https://user-images.githubusercontent.com/42511384/183861683-31fb6792-6346-46dd-a9e9-cf9dc172388c.png)

It works in web:

![image](https://user-images.githubusercontent.com/42511384/183861808-7196af5e-7734-49d6-b64a-557fb2abfb42.png)

but not in the app:

![image](https://user-images.githubusercontent.com/42511384/183862106-4d623a37-4e06-4851-bf80-5d67c1b555e1.png)

Things I've tried:

- Restarting the phone
- Restarting the app (force stop & cache delete)
- Deleting and recreating the filter
- Turning the "whole word" option on and off

* * * *
- Tusky Version: Tusky 19.0
- Android Version: 12
- Android Device: Samsung S21
- Mastodon instance (if applicable):

- [X] I searched or browsed the repo’s other (open) issues to ensure this is not a duplicate.


Discussion hints:
nan

Pull request: Parse html tags out of status content before applying filters
Fixes #2660

Test command: ./gradlew :app:testBlueDebugUnitTest --tests "com.keylesspalace.tusky.FilterTest"

Fix patch:
diff --git a/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt b/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt
index db47beaf08..16a439d950 100644
--- a/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/network/FilterModel.kt
@@ -3,6 +3,7 @@ package com.keylesspalace.tusky.network
 import android.text.TextUtils
 import com.keylesspalace.tusky.entity.Filter
 import com.keylesspalace.tusky.entity.Status
+import com.keylesspalace.tusky.util.parseAsMastodonHtml
 import java.util.Date
 import java.util.regex.Pattern
 import javax.inject.Inject
@@ -34,7 +35,7 @@ class FilterModel @Inject constructor() {
             .mapNotNull { it.description }
 
         return (
-            matcher.reset(status.actionableStatus.content).find() ||
+            matcher.reset(status.actionableStatus.content.parseAsMastodonHtml().toString()).find() ||
                 (spoilerText.isNotEmpty() && matcher.reset(spoilerText).find()) ||
                 (
                     attachmentsDescriptions.isNotEmpty() &&


Test patch:
diff --git a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
index b28f6c9a07..b8ca181e9f 100644
--- a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
@@ -53,6 +53,14 @@ class FilterTest {
                 irreversible = false,
                 wholeWord = true
             ),
+            Filter(
+                id = "123",
+                phrase = "#hashtag",
+                context = listOf(Filter.HOME),
+                expiresAt = null,
+                irreversible = false,
+                wholeWord = true
+            ),
             Filter(
                 id = "123",
                 phrase = "expired",
@@ -69,6 +77,14 @@ class FilterTest {
                 irreversible = false,
                 wholeWord = true
             ),
+            Filter(
+                id = "123",
+                phrase = "href",
+                context = listOf(Filter.HOME),
+                expiresAt = null,
+                irreversible = false,
+                wholeWord = false
+            ),
         )
 
         filterModel.initWithFilters(filters)
@@ -166,6 +182,33 @@ class FilterTest {
         )
     }
 
+    @Test
+    fun shouldFilterHashtags() {
+        assertTrue(
+            filterModel.shouldFilterStatus(
+                mockStatus(content = "#hashtag one two three")
+            )
+        )
+    }
+
+    @Test
+    fun shouldFilterHashtags_whenContentIsMarkedUp() {
+        assertTrue(
+            filterModel.shouldFilterStatus(
+                mockStatus(content = "<p><a href=\"https://foo.bar/tags/hashtag\" class=\"mention hashtag\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">#<span>hashtag</span></a>one two three</p>")
+            )
+        )
+    }
+
+    @Test
+    fun shouldNotFilterHtmlAttributes() {
+        assertFalse(
+            filterModel.shouldFilterStatus(
+                mockStatus(content = "<p><a href=\"https://foo.bar/\">https://foo.bar/</a> one two three</p>")
+            )
+        )
+    }
+
     @Test
     fun shouldNotFilter_whenFilterIsExpired() {
         assertFalse(