From 4b79d35854cc2ea55be32054bfa5fb9a747c9d47 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Sun, 24 Sep 2023 11:47:42 +0200 Subject: [PATCH 1/4] feat(settings/filter): allow passing words --- .../android/fragments/settings/EditFilterFragment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/EditFilterFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/EditFilterFragment.java index 4655c4169d..e1a69acacf 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/EditFilterFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/EditFilterFragment.java @@ -68,6 +68,10 @@ public class EditFilterFragment extends BaseSettingsFragment implements On public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); filter=Parcels.unwrap(getArguments().getParcelable("filter")); + ArrayList words=getArguments().getParcelableArrayList("words"); + if (words != null) { + words.stream().map(p->(FilterKeyword)Parcels.unwrap(p)).forEach(keywords::add); + } setTitle(filter==null ? R.string.settings_add_filter : R.string.settings_edit_filter); onDataLoaded(List.of( durationItem=new ListItem<>(R.string.settings_filter_duration, 0, this::onDurationClick), From f293619189ec7b537964fe6eb2bddf8b2a49f188 Mon Sep 17 00:00:00 2001 From: FineFindus Date: Sun, 24 Sep 2023 12:33:17 +0200 Subject: [PATCH 2/4] feat: add mute hashtag option Fixes https://github.com/LucasGGamerM/moshidon/issues/260, by opening the create filter page --- .../android/fragments/HashtagTimelineFragment.java | 14 ++++++++++++++ mastodon/src/main/res/menu/hashtag_timeline.xml | 4 ++++ mastodon/src/main/res/values/strings_mo.xml | 3 +++ 3 files changed, 21 insertions(+) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java index de127bd7a8..87e6a59caf 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java @@ -13,17 +13,23 @@ import org.joinmastodon.android.E; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.filters.GetFilters; import org.joinmastodon.android.api.requests.tags.GetHashtag; import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed; import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline; import org.joinmastodon.android.events.HashtagUpdatedEvent; +import org.joinmastodon.android.fragments.settings.EditFilterFragment; +import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.FilterContext; +import org.joinmastodon.android.model.FilterKeyword; import org.joinmastodon.android.model.Hashtag; import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.TimelineDefinition; import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.utils.StatusFilterPredicate; +import org.parceler.Parcels; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -116,6 +122,14 @@ public void onError(ErrorResponse error) { } }).exec(accountID); return true; + } else if (item.getItemId() == R.id.mute_hashtag) { + Bundle args=new Bundle(); + args.putString("account", accountID); + FilterKeyword hashtagFilter=new FilterKeyword(); + hashtagFilter.wholeWord=true; + hashtagFilter.keyword=hashtag; + args.putParcelableArrayList("words", new ArrayList<>(List.of(Parcels.wrap(hashtagFilter)))); + Nav.go(getActivity(), EditFilterFragment.class, args); } return false; } diff --git a/mastodon/src/main/res/menu/hashtag_timeline.xml b/mastodon/src/main/res/menu/hashtag_timeline.xml index efc7cc2e21..0050f39ae6 100644 --- a/mastodon/src/main/res/menu/hashtag_timeline.xml +++ b/mastodon/src/main/res/menu/hashtag_timeline.xml @@ -10,4 +10,8 @@ android:icon="@drawable/ic_fluent_person_add_24_regular" android:showAsAction="always" android:title="@string/button_follow"/> + \ No newline at end of file diff --git a/mastodon/src/main/res/values/strings_mo.xml b/mastodon/src/main/res/values/strings_mo.xml index bc6c5c33f5..350324d7a3 100644 --- a/mastodon/src/main/res/values/strings_mo.xml +++ b/mastodon/src/main/res/values/strings_mo.xml @@ -106,4 +106,7 @@ Confirm to unfollow %s Recent emoji cleared Show media preview in timelines + + + Mute Hashtag \ No newline at end of file From 4f8c4c67d258aa2200ef7794d6ceed2f444740bd Mon Sep 17 00:00:00 2001 From: FineFindus Date: Mon, 25 Sep 2023 20:22:06 +0200 Subject: [PATCH 3/4] feat(hashtag): allow unmuting hashtag --- .../fragments/HashtagTimelineFragment.java | 71 ++++++++++++++++--- mastodon/src/main/res/values/strings_mo.xml | 8 ++- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java index 87e6a59caf..ca5c5f6231 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java @@ -13,6 +13,8 @@ import org.joinmastodon.android.E; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.filters.CreateFilter; +import org.joinmastodon.android.api.requests.filters.DeleteFilter; import org.joinmastodon.android.api.requests.filters.GetFilters; import org.joinmastodon.android.api.requests.tags.GetHashtag; import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed; @@ -20,6 +22,7 @@ import org.joinmastodon.android.events.HashtagUpdatedEvent; import org.joinmastodon.android.fragments.settings.EditFilterFragment; import org.joinmastodon.android.model.Filter; +import org.joinmastodon.android.model.FilterAction; import org.joinmastodon.android.model.FilterContext; import org.joinmastodon.android.model.FilterKeyword; import org.joinmastodon.android.model.Hashtag; @@ -30,7 +33,9 @@ import org.parceler.Parcels; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import me.grishka.appkit.Nav; @@ -47,6 +52,8 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment { private boolean following; private boolean localOnly; private MenuItem followButton; + private MenuItem muteButton; + private Optional filter = Optional.empty(); @Override protected boolean wantsComposeButton() { @@ -78,13 +85,18 @@ private void updateFollowingState(boolean newFollowing) { E.post(new HashtagUpdatedEvent(hashtag, following)); } + private void updateMuteState(boolean newMute) { + muteButton.setTitle(getString(newMute ? R.string.unmute_user : R.string.mute_user, "#" + hashtag)); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.hashtag_timeline, menu); super.onCreateOptionsMenu(menu, inflater); followButton = menu.findItem(R.id.follow_hashtag); updateFollowingState(following); - + muteButton = menu.findItem(R.id.mute_hashtag); + updateMuteState(filter.isPresent()); new GetHashtag(hashtag).setCallback(new Callback<>() { @Override public void onSuccess(Hashtag hashtag) { @@ -98,6 +110,20 @@ public void onError(ErrorResponse error) { error.showToast(getActivity()); } }).exec(accountID); + + new GetFilters().setCallback(new Callback<>() { + @Override + public void onSuccess(List filters) { + if (getActivity() == null) return; + filter=filters.stream().filter(filter->filter.title.equals("#"+hashtag)).findAny(); + updateMuteState(filter.isPresent()); + } + + @Override + public void onError(ErrorResponse error) { + error.showToast(getActivity()); + } + }).exec(accountID); } @@ -123,17 +149,46 @@ public void onError(ErrorResponse error) { }).exec(accountID); return true; } else if (item.getItemId() == R.id.mute_hashtag) { - Bundle args=new Bundle(); - args.putString("account", accountID); - FilterKeyword hashtagFilter=new FilterKeyword(); - hashtagFilter.wholeWord=true; - hashtagFilter.keyword=hashtag; - args.putParcelableArrayList("words", new ArrayList<>(List.of(Parcels.wrap(hashtagFilter)))); - Nav.go(getActivity(), EditFilterFragment.class, args); + showMuteDialog(filter.isPresent()); + return true; } return false; } + private void showMuteDialog(boolean mute) { + UiUtils.showConfirmationAlert(getContext(), + mute ? R.string.mo_unmute_hashtag : R.string.mo_mute_hashtag, + mute ? R.string.mo_confirm_to_unmute_hashtag : R.string.mo_confirm_to_mute_hashtag, + mute ? R.string.do_unmute : R.string.do_mute, + mute ? R.drawable.ic_fluent_speaker_2_28_regular : R.drawable.ic_fluent_speaker_off_28_regular, + mute ? this::unmuteHashtag : this::muteHashtag + ); + } + private void unmuteHashtag() { + //safe to get, this only called if filter is present + new DeleteFilter(filter.get().id).exec(accountID); + } + + private void muteHashtag() { + FilterKeyword hashtagFilter=new FilterKeyword(); + hashtagFilter.wholeWord=true; + hashtagFilter.keyword=hashtag; + new CreateFilter("#"+hashtag, EnumSet.of(FilterContext.HOME), FilterAction.HIDE, 0 , List.of(hashtagFilter)).setCallback(new Callback(){ + @Override + public void onSuccess(Filter result){ + filter = Optional.of(result); + updateMuteState(true); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getContext()); + } + }).exec(accountID); + } + + + @Override protected TimelineDefinition makeTimelineDefinition() { return TimelineDefinition.ofHashtag(hashtag); diff --git a/mastodon/src/main/res/values/strings_mo.xml b/mastodon/src/main/res/values/strings_mo.xml index 350324d7a3..e8dbdd2ad1 100644 --- a/mastodon/src/main/res/values/strings_mo.xml +++ b/mastodon/src/main/res/values/strings_mo.xml @@ -43,7 +43,11 @@ Unmute conversation Are you sure you want to mute this conversation? Are you sure you want to unmute this conversation? - + Mute hashtag + Unmute hashtag + Are you sure you want to mute this hashtag? + Are you sure you want to unmute this hashtag? + Add new poll option Compose @@ -107,6 +111,4 @@ Recent emoji cleared Show media preview in timelines - - Mute Hashtag \ No newline at end of file From ac8562aaa2efbca136e5e57fb9d46a9158e75a5c Mon Sep 17 00:00:00 2001 From: FineFindus Date: Mon, 25 Sep 2023 20:31:29 +0200 Subject: [PATCH 4/4] fix(hashtag/mute): mute hashtag with prefixed #-symbol --- .../joinmastodon/android/fragments/HashtagTimelineFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java index ca5c5f6231..a9a74c4204 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java @@ -172,7 +172,7 @@ private void unmuteHashtag() { private void muteHashtag() { FilterKeyword hashtagFilter=new FilterKeyword(); hashtagFilter.wholeWord=true; - hashtagFilter.keyword=hashtag; + hashtagFilter.keyword="#"+hashtag; new CreateFilter("#"+hashtag, EnumSet.of(FilterContext.HOME), FilterAction.HIDE, 0 , List.of(hashtagFilter)).setCallback(new Callback(){ @Override public void onSuccess(Filter result){