Merge branch 'feature/follow_hashtags' into fork

Fixes #31, mastodon#233
This commit is contained in:
sk
2022-11-09 15:48:18 +01:00
10 changed files with 104 additions and 5 deletions

View File

@@ -0,0 +1,11 @@
package org.joinmastodon.android.api.requests.tags;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Hashtag;
public class GetHashtag extends MastodonAPIRequest<Hashtag> {
public GetHashtag(String name){
super(HttpMethod.GET, "/tags/"+name, Hashtag.class);
}
}

View File

@@ -0,0 +1,11 @@
package org.joinmastodon.android.api.requests.tags;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Hashtag;
public class SetHashtagFollowed extends MastodonAPIRequest<Hashtag>{
public SetHashtagFollowed(String name, boolean followed){
super(HttpMethod.POST, "/tags/"+name+"/"+(followed ? "follow" : "unfollow"), Hashtag.class);
setRequestBody(new Object());
}
}

View File

@@ -2,23 +2,34 @@ package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;
import org.joinmastodon.android.R;
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.model.Hashtag;
import org.joinmastodon.android.model.Status;
import java.util.List;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.utils.V;
public class HashtagTimelineFragment extends StatusListFragment{
private String hashtag;
private boolean following;
private ImageButton fab;
private MenuItem followButton;
public HashtagTimelineFragment(){
setListLayoutId(R.layout.recycler_fragment_with_fab);
@@ -27,10 +38,61 @@ public class HashtagTimelineFragment extends StatusListFragment{
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
hashtag=getArguments().getString("hashtag");
updateTitle(getArguments().getString("hashtag"));
following=getArguments().getBoolean("following", false);
setHasOptionsMenu(true);
}
private void updateTitle(String hashtagName) {
hashtag = hashtagName;
setTitle('#'+hashtag);
}
private void updateFollowingState(boolean newFollowing) {
this.following = newFollowing;
followButton.setTitle(getString(newFollowing ? R.string.unfollow_user : R.string.follow_user, "#" + hashtag));
followButton.setIcon(newFollowing ? R.drawable.ic_fluent_person_delete_24_filled : R.drawable.ic_fluent_person_add_24_regular);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.hashtag_timeline, menu);
followButton = menu.findItem(R.id.follow_hashtag);
updateFollowingState(following);
followButton.setOnMenuItemClickListener(i -> {
updateFollowingState(!following);
new SetHashtagFollowed(hashtag, following).setCallback(new Callback<>() {
@Override
public void onSuccess(Hashtag i) {
updateFollowingState(i.following);
Toast.makeText(getActivity(), getString(i.following ? R.string.followed_user : R.string.unfollowed_user, "#" + i.name), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(ErrorResponse error) {
error.showToast(getActivity());
updateFollowingState(!following);
}
}).exec(accountID);
return true;
});
new GetHashtag(hashtag).setCallback(new Callback<>() {
@Override
public void onSuccess(Hashtag hashtag) {
updateTitle(hashtag.name);
updateFollowingState(hashtag.following);
}
@Override
public void onError(ErrorResponse error) {
error.showToast(getActivity());
}
}).exec(accountID);
}
@Override
protected void doLoadData(int offset, int count){
currentRequest=new GetHashtagTimeline(hashtag, offset==0 ? null : getMaxID(), null, count)

View File

@@ -100,7 +100,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
args.putParcelable("profileAccount", Parcels.wrap(res.account));
Nav.go(getActivity(), ProfileFragment.class, args);
}
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name);
case HASHTAG -> UiUtils.openHashtagTimeline(getActivity(), accountID, res.hashtag.name, res.hashtag.following);
case STATUS -> {
Status status=res.status.getContentStatus();
Bundle args=new Bundle();

View File

@@ -107,7 +107,7 @@ public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> impl
@Override
public void onClick(){
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name);
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name, item.following);
}
}
}

View File

@@ -11,6 +11,7 @@ public class Hashtag extends BaseModel{
public String name;
@RequiredField
public String url;
public boolean following;
public List<History> history;
@Override
@@ -18,6 +19,7 @@ public class Hashtag extends BaseModel{
return "Hashtag{"+
"name='"+name+'\''+
", url='"+url+'\''+
", following="+following+
", history="+history+
'}';
}

View File

@@ -34,7 +34,7 @@ public class LinkSpan extends CharacterStyle {
switch(getType()){
case URL -> UiUtils.openURL(context, accountID, link);
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link);
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null);
}
}

View File

@@ -80,6 +80,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import androidx.annotation.AttrRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.recyclerview.widget.DiffUtil;
@@ -309,10 +310,11 @@ public class UiUtils{
Nav.go((Activity)context, ProfileFragment.class, args);
}
public static void openHashtagTimeline(Context context, String accountID, String hashtag){
public static void openHashtagTimeline(Context context, String accountID, String hashtag, @Nullable Boolean following){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putString("hashtag", hashtag);
if (following != null) args.putBoolean("following", following);
Nav.go((Activity)context, HashtagTimelineFragment.class, args);
}