Skip to content
This repository was archived by the owner on May 30, 2025. It is now read-only.

Commit 7d38f03

Browse files
committed
Merge branch 'feature/follow_hashtags' into fork
Fixes #31, mastodon#233
2 parents f4b1629 + cf864e6 commit 7d38f03

File tree

10 files changed

+104
-5
lines changed

10 files changed

+104
-5
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.joinmastodon.android.api.requests.tags;
2+
3+
import org.joinmastodon.android.api.MastodonAPIRequest;
4+
import org.joinmastodon.android.model.Hashtag;
5+
6+
public class GetHashtag extends MastodonAPIRequest<Hashtag> {
7+
public GetHashtag(String name){
8+
super(HttpMethod.GET, "/tags/"+name, Hashtag.class);
9+
}
10+
}
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.joinmastodon.android.api.requests.tags;
2+
3+
import org.joinmastodon.android.api.MastodonAPIRequest;
4+
import org.joinmastodon.android.model.Hashtag;
5+
6+
public class SetHashtagFollowed extends MastodonAPIRequest<Hashtag>{
7+
public SetHashtagFollowed(String name, boolean followed){
8+
super(HttpMethod.POST, "/tags/"+name+"/"+(followed ? "follow" : "unfollow"), Hashtag.class);
9+
setRequestBody(new Object());
10+
}
11+
}

mastodon/src/main/java/org/joinmastodon/android/fragments/HashtagTimelineFragment.java

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,34 @@
22

33
import android.app.Activity;
44
import android.os.Bundle;
5+
import android.view.Menu;
6+
import android.view.MenuInflater;
7+
import android.view.MenuItem;
58
import android.view.View;
69
import android.view.ViewGroup;
710
import android.widget.ImageButton;
11+
import android.widget.Toast;
812

913
import org.joinmastodon.android.R;
14+
import org.joinmastodon.android.api.requests.tags.GetHashtag;
15+
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
1016
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
17+
import org.joinmastodon.android.model.Hashtag;
1118
import org.joinmastodon.android.model.Status;
1219

1320
import java.util.List;
1421

1522
import me.grishka.appkit.Nav;
23+
import me.grishka.appkit.api.Callback;
24+
import me.grishka.appkit.api.ErrorResponse;
1625
import me.grishka.appkit.api.SimpleCallback;
1726
import me.grishka.appkit.utils.V;
1827

1928
public class HashtagTimelineFragment extends StatusListFragment{
2029
private String hashtag;
30+
private boolean following;
2131
private ImageButton fab;
32+
private MenuItem followButton;
2233

2334
public HashtagTimelineFragment(){
2435
setListLayoutId(R.layout.recycler_fragment_with_fab);
@@ -27,10 +38,61 @@ public HashtagTimelineFragment(){
2738
@Override
2839
public void onAttach(Activity activity){
2940
super.onAttach(activity);
30-
hashtag=getArguments().getString("hashtag");
41+
updateTitle(getArguments().getString("hashtag"));
42+
following=getArguments().getBoolean("following", false);
43+
44+
setHasOptionsMenu(true);
45+
}
46+
47+
private void updateTitle(String hashtagName) {
48+
hashtag = hashtagName;
3149
setTitle('#'+hashtag);
3250
}
3351

52+
private void updateFollowingState(boolean newFollowing) {
53+
this.following = newFollowing;
54+
followButton.setTitle(getString(newFollowing ? R.string.unfollow_user : R.string.follow_user, "#" + hashtag));
55+
followButton.setIcon(newFollowing ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
56+
}
57+
58+
@Override
59+
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
60+
inflater.inflate(R.menu.hashtag_timeline, menu);
61+
followButton = menu.findItem(R.id.follow_hashtag);
62+
updateFollowingState(following);
63+
64+
followButton.setOnMenuItemClickListener(i -> {
65+
updateFollowingState(!following);
66+
new SetHashtagFollowed(hashtag, following).setCallback(new Callback<>() {
67+
@Override
68+
public void onSuccess(Hashtag i) {
69+
updateFollowingState(i.following);
70+
Toast.makeText(getActivity(), getString(i.following ? R.string.followed_user : R.string.unfollowed_user, "#" + i.name), Toast.LENGTH_SHORT).show();
71+
}
72+
73+
@Override
74+
public void onError(ErrorResponse error) {
75+
error.showToast(getActivity());
76+
updateFollowingState(!following);
77+
}
78+
}).exec(accountID);
79+
return true;
80+
});
81+
82+
new GetHashtag(hashtag).setCallback(new Callback<>() {
83+
@Override
84+
public void onSuccess(Hashtag hashtag) {
85+
updateTitle(hashtag.name);
86+
updateFollowingState(hashtag.following);
87+
}
88+
89+
@Override
90+
public void onError(ErrorResponse error) {
91+
error.showToast(getActivity());
92+
}
93+
}).exec(accountID);
94+
}
95+
3496
@Override
3597
protected void doLoadData(int offset, int count){
3698
currentRequest=new GetHashtagTimeline(hashtag, offset==0 ? null : getMaxID(), null, count)

mastodon/src/main/java/org/joinmastodon/android/fragments/discover/SearchFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public void onItemClick(String id){
100100
args.putParcelable("profileAccount", Parcels.wrap(res.account));
101101
Nav.go(getActivity(), ProfileFragment.class, args);
102102
}
103-
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name);
103+
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name, res.hashtag.following);
104104
case STATUS -> {
105105
Status status=res.status.getContentStatus();
106106
Bundle args=new Bundle();

mastodon/src/main/java/org/joinmastodon/android/fragments/discover/TrendingHashtagsFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void onBind(Hashtag item){
107107

108108
@Override
109109
public void onClick(){
110-
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name);
110+
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name, item.following);
111111
}
112112
}
113113
}

mastodon/src/main/java/org/joinmastodon/android/model/Hashtag.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ public class Hashtag extends BaseModel{
1111
public String name;
1212
@RequiredField
1313
public String url;
14+
public boolean following;
1415
public List<History> history;
1516

1617
@Override
1718
public String toString(){
1819
return "Hashtag{"+
1920
"name='"+name+'\''+
2021
", url='"+url+'\''+
22+
", following="+following+
2123
", history="+history+
2224
'}';
2325
}

mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public void onClick(Context context){
3434
switch(getType()){
3535
case URL -> UiUtils.openURL(context, accountID, link);
3636
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
37-
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link);
37+
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null);
3838
}
3939
}
4040

mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import java.util.stream.Collectors;
8181

8282
import androidx.annotation.AttrRes;
83+
import androidx.annotation.Nullable;
8384
import androidx.annotation.StringRes;
8485
import androidx.browser.customtabs.CustomTabsIntent;
8586
import androidx.recyclerview.widget.DiffUtil;
@@ -309,10 +310,11 @@ public static void openProfileByID(Context context, String selfID, String id){
309310
Nav.go((Activity)context, ProfileFragment.class, args);
310311
}
311312

312-
public static void openHashtagTimeline(Context context, String accountID, String hashtag){
313+
public static void openHashtagTimeline(Context context, String accountID, String hashtag, @Nullable Boolean following){
313314
Bundle args=new Bundle();
314315
args.putString("account", accountID);
315316
args.putString("hashtag", hashtag);
317+
if (following != null) args.putBoolean("following", following);
316318
Nav.go((Activity)context, HashtagTimelineFragment.class, args);
317319
}
318320

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
2+
<path android:pathData="M17.5 12c3.037 0 5.5 2.463 5.5 5.5 0 3.038-2.463 5.5-5.5 5.5-3.038 0-5.5-2.462-5.5-5.5 0-3.037 2.462-5.5 5.5-5.5zm-5.478 2C11.375 15.01 11 16.21 11 17.5c0 1.644 0.61 3.146 1.617 4.29-0.802 0.142-1.675 0.211-2.617 0.211-2.89 0-5.128-0.656-6.691-2-0.829-0.712-1.306-1.75-1.306-2.844V16.25c0-1.242 1.008-2.25 2.25-2.25h7.77zm3.07 0.966l-0.068 0.058-0.058 0.07c-0.118 0.17-0.118 0.398 0 0.568l0.058 0.07 1.77 1.769-1.768 1.767-0.058 0.069c-0.118 0.17-0.118 0.398 0 0.569l0.058 0.069 0.07 0.058c0.17 0.118 0.398 0.118 0.568 0l0.07-0.058 1.766-1.767 1.77 1.77 0.069 0.057c0.17 0.118 0.398 0.118 0.568 0l0.07-0.058 0.057-0.07c0.118-0.17 0.118-0.397 0-0.568l-0.058-0.069-1.769-1.77 1.772-1.768 0.058-0.07c0.118-0.17 0.118-0.398 0-0.568l-0.058-0.07-0.07-0.057c-0.17-0.119-0.397-0.119-0.568 0l-0.069 0.057-1.772 1.77-1.77-1.77-0.069-0.057c-0.146-0.102-0.334-0.116-0.492-0.044l-0.076 0.043zM10 2.005c2.761 0 5 2.239 5 5s-2.239 5-5 5-5-2.239-5-5 2.239-5 5-5z" android:fillColor="@color/fluent_default_icon_tint"/>
3+
</vector>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item
4+
android:id="@+id/follow_hashtag"
5+
android:icon="@drawable/ic_fluent_person_add_24_regular"
6+
android:showAsAction="always"
7+
android:title="@string/button_follow"/>
8+
</menu>

0 commit comments

Comments
 (0)