fix: Create hashtag filters with the `#` character (#3)
Previous code created hashtag filters without the `#`, so muting the tag `#something` would filter all posts that contained `something`, with or without the `#`. Fix this when creating filters, and only remove filters (when unmuting) if the title and contents match. Show a snackbar when hashtags are successfully muted/unmuted, so the user is aware something happened.
This commit is contained in:
parent
4879f0449f
commit
8a9dd7dc60
|
@ -41,6 +41,10 @@ import kotlinx.coroutines.launch
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a list of statuses of a particular type; containing a particular hashtag,
|
||||||
|
* the user's favourites, bookmarks, etc.
|
||||||
|
*/
|
||||||
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -51,6 +55,11 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
|
|
||||||
private val binding: ActivityStatuslistBinding by viewBinding(ActivityStatuslistBinding::inflate)
|
private val binding: ActivityStatuslistBinding by viewBinding(ActivityStatuslistBinding::inflate)
|
||||||
private lateinit var timelineKind: TimelineKind
|
private lateinit var timelineKind: TimelineKind
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If showing statuses with a hashtag, the hashtag being used, without the
|
||||||
|
* leading `#`.
|
||||||
|
*/
|
||||||
private var hashtag: String? = null
|
private var hashtag: String? = null
|
||||||
private var followTagItem: MenuItem? = null
|
private var followTagItem: MenuItem? = null
|
||||||
private var unfollowTagItem: MenuItem? = null
|
private var unfollowTagItem: MenuItem? = null
|
||||||
|
@ -168,7 +177,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
* Determine if the current hashtag is muted, and update the UI state accordingly.
|
* Determine if the current hashtag is muted, and update the UI state accordingly.
|
||||||
*/
|
*/
|
||||||
private fun updateMuteTagMenuItems() {
|
private fun updateMuteTagMenuItems() {
|
||||||
val tag = hashtag ?: return
|
val tagWithHash = hashtag?.let { "#$it" } ?: return
|
||||||
|
|
||||||
muteTagItem?.isVisible = true
|
muteTagItem?.isVisible = true
|
||||||
muteTagItem?.isEnabled = false
|
muteTagItem?.isEnabled = false
|
||||||
|
@ -179,7 +188,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
{ filters ->
|
{ filters ->
|
||||||
mutedFilter = filters.firstOrNull { filter ->
|
mutedFilter = filters.firstOrNull { filter ->
|
||||||
filter.context.contains(Filter.Kind.HOME.kind) && filter.keywords.any {
|
filter.context.contains(Filter.Kind.HOME.kind) && filter.keywords.any {
|
||||||
it.keyword == tag
|
it.keyword == tagWithHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateTagMuteState(mutedFilter != null)
|
updateTagMuteState(mutedFilter != null)
|
||||||
|
@ -189,7 +198,7 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
mastodonApi.getFiltersV1().fold(
|
mastodonApi.getFiltersV1().fold(
|
||||||
{ filters ->
|
{ filters ->
|
||||||
mutedFilterV1 = filters.firstOrNull { filter ->
|
mutedFilterV1 = filters.firstOrNull { filter ->
|
||||||
tag == filter.phrase && filter.context.contains(FilterV1.HOME)
|
tagWithHash == filter.phrase && filter.context.contains(FilterV1.HOME)
|
||||||
}
|
}
|
||||||
updateTagMuteState(mutedFilterV1 != null)
|
updateTagMuteState(mutedFilterV1 != null)
|
||||||
},
|
},
|
||||||
|
@ -218,29 +227,30 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun muteTag(): Boolean {
|
private fun muteTag(): Boolean {
|
||||||
val tag = hashtag ?: return true
|
val tagWithHash = hashtag?.let { "#$it" } ?: return true
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
mastodonApi.createFilter(
|
mastodonApi.createFilter(
|
||||||
title = "#$tag",
|
title = tagWithHash,
|
||||||
context = listOf(FilterV1.HOME),
|
context = listOf(FilterV1.HOME),
|
||||||
filterAction = Filter.Action.WARN.action,
|
filterAction = Filter.Action.WARN.action,
|
||||||
expiresInSeconds = null,
|
expiresInSeconds = null,
|
||||||
).fold(
|
).fold(
|
||||||
{ filter ->
|
{ filter ->
|
||||||
if (mastodonApi.addFilterKeyword(filterId = filter.id, keyword = tag, wholeWord = true).isSuccess) {
|
if (mastodonApi.addFilterKeyword(filterId = filter.id, keyword = tagWithHash, wholeWord = true).isSuccess) {
|
||||||
mutedFilter = filter
|
mutedFilter = filter
|
||||||
updateTagMuteState(true)
|
updateTagMuteState(true)
|
||||||
eventHub.dispatch(PreferenceChangedEvent(filter.context[0]))
|
eventHub.dispatch(PreferenceChangedEvent(filter.context[0]))
|
||||||
|
Snackbar.make(binding.root, getString(R.string.confirmation_hashtag_muted, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
Log.e(TAG, "Failed to mute #$tag")
|
Log.e(TAG, "Failed to mute $tagWithHash")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ throwable ->
|
{ throwable ->
|
||||||
if (throwable is HttpException && throwable.code() == 404) {
|
if (throwable is HttpException && throwable.code() == 404) {
|
||||||
mastodonApi.createFilterV1(
|
mastodonApi.createFilterV1(
|
||||||
tag,
|
tagWithHash,
|
||||||
listOf(FilterV1.HOME),
|
listOf(FilterV1.HOME),
|
||||||
irreversible = false,
|
irreversible = false,
|
||||||
wholeWord = true,
|
wholeWord = true,
|
||||||
|
@ -250,15 +260,16 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
mutedFilterV1 = filter
|
mutedFilterV1 = filter
|
||||||
updateTagMuteState(true)
|
updateTagMuteState(true)
|
||||||
eventHub.dispatch(PreferenceChangedEvent(filter.context[0]))
|
eventHub.dispatch(PreferenceChangedEvent(filter.context[0]))
|
||||||
|
Snackbar.make(binding.root, getString(R.string.confirmation_hashtag_muted, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
},
|
},
|
||||||
{ throwable ->
|
{ throwable ->
|
||||||
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
Log.e(TAG, "Failed to mute #$tag", throwable)
|
Log.e(TAG, "Failed to mute $tagWithHash", throwable)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(binding.root, getString(R.string.error_muting_hashtag_format, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
Log.e(TAG, "Failed to mute #$tag", throwable)
|
Log.e(TAG, "Failed to mute $tagWithHash", throwable)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -269,7 +280,8 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
|
|
||||||
private fun unmuteTag(): Boolean {
|
private fun unmuteTag(): Boolean {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val tag = hashtag
|
val tagWithHash = hashtag?.let { "#$it" } ?: return@launch
|
||||||
|
|
||||||
val result = if (mutedFilter != null) {
|
val result = if (mutedFilter != null) {
|
||||||
val filter = mutedFilter!!
|
val filter = mutedFilter!!
|
||||||
if (filter.context.size > 1) {
|
if (filter.context.size > 1) {
|
||||||
|
@ -304,13 +316,14 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
|
||||||
result?.fold(
|
result?.fold(
|
||||||
{
|
{
|
||||||
updateTagMuteState(false)
|
updateTagMuteState(false)
|
||||||
|
Snackbar.make(binding.root, getString(R.string.confirmation_hashtag_unmuted, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
eventHub.dispatch(PreferenceChangedEvent(Filter.Kind.HOME.kind))
|
eventHub.dispatch(PreferenceChangedEvent(Filter.Kind.HOME.kind))
|
||||||
mutedFilterV1 = null
|
mutedFilterV1 = null
|
||||||
mutedFilter = null
|
mutedFilter = null
|
||||||
},
|
},
|
||||||
{ throwable ->
|
{ throwable ->
|
||||||
Snackbar.make(binding.root, getString(R.string.error_unmuting_hashtag_format, tag), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(binding.root, getString(R.string.error_unmuting_hashtag_format, hashtag), Snackbar.LENGTH_SHORT).show()
|
||||||
Log.e(TAG, "Failed to unmute #$tag", throwable)
|
Log.e(TAG, "Failed to unmute $tagWithHash", throwable)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,8 @@
|
||||||
<string name="confirmation_unblocked">User unblocked</string>
|
<string name="confirmation_unblocked">User unblocked</string>
|
||||||
<string name="confirmation_unmuted">User unmuted</string>
|
<string name="confirmation_unmuted">User unmuted</string>
|
||||||
<string name="confirmation_domain_unmuted">%s unhidden</string>
|
<string name="confirmation_domain_unmuted">%s unhidden</string>
|
||||||
|
<string name="confirmation_hashtag_muted">#%s hidden</string>
|
||||||
|
<string name="confirmation_hashtag_unmuted">#%s unhidden</string>
|
||||||
<string name="confirmation_hashtag_unfollowed">#%s unfollowed</string>
|
<string name="confirmation_hashtag_unfollowed">#%s unfollowed</string>
|
||||||
|
|
||||||
<string name="post_sent">Sent!</string>
|
<string name="post_sent">Sent!</string>
|
||||||
|
|
Loading…
Reference in New Issue