From 9beb04b01d83149a2b31232f958e80c58af9fea2 Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 6 May 2022 19:07:51 +0200 Subject: [PATCH] implement pinning and unpinning posts --- .../requests/statuses/SetStatusPinned.java | 11 ++++++++ .../android/events/StatusUnpinnedEvent.java | 11 ++++++++ .../fragments/AccountTimelineFragment.java | 22 +++++++++++++++ .../android/fragments/StatusListFragment.java | 8 ++++++ .../displayitems/HeaderStatusDisplayItem.java | 4 +++ .../android/ui/utils/UiUtils.java | 28 ++++++++++++++++++- mastodon/src/main/res/menu/post.xml | 2 ++ mastodon/src/main/res/values/strings.xml | 8 ++++++ 8 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusPinned.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/events/StatusUnpinnedEvent.java diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusPinned.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusPinned.java new file mode 100644 index 000000000..e7c55e63f --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusPinned.java @@ -0,0 +1,11 @@ +package org.joinmastodon.android.api.requests.statuses; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.Status; + +public class SetStatusPinned extends MastodonAPIRequest{ + public SetStatusPinned(String id, boolean pinned){ + super(HttpMethod.POST, "/statuses/"+id+"/"+(pinned ? "pin" : "unpin"), Status.class); + setRequestBody(new Object()); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/events/StatusUnpinnedEvent.java b/mastodon/src/main/java/org/joinmastodon/android/events/StatusUnpinnedEvent.java new file mode 100644 index 000000000..54925c076 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/events/StatusUnpinnedEvent.java @@ -0,0 +1,11 @@ +package org.joinmastodon.android.events; + +public class StatusUnpinnedEvent { + public final String id; + public final String accountID; + + public StatusUnpinnedEvent(String id, String accountID){ + this.id=id; + this.accountID=accountID; + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index 7924e9c93..fe1c004cd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -8,8 +8,10 @@ import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.events.StatusCreatedEvent; +import org.joinmastodon.android.events.StatusUnpinnedEvent; import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem; import org.parceler.Parcels; import java.util.Collections; @@ -86,4 +88,24 @@ public class AccountTimelineFragment extends StatusListFragment{ } prependItems(Collections.singletonList(ev.status), true); } + + protected void onStatusUnpinned(StatusUnpinnedEvent ev){ + if(!ev.accountID.equals(accountID) || filter!=GetAccountStatuses.Filter.PINNED) + return; + + Status status=getStatusByID(ev.id); + data.remove(status); + preloadedData.remove(status); + HeaderStatusDisplayItem item=findItemOfType(ev.id, HeaderStatusDisplayItem.class); + if(item==null) + return; + int index=displayItems.indexOf(item); + int lastIndex; + for(lastIndex=index;lastIndex{ protected void onStatusCreated(StatusCreatedEvent ev){} + protected void onStatusUnpinned(StatusUnpinnedEvent ev){} + protected Status getContentStatusByID(String id){ Status s=getStatusByID(id); return s==null ? null : s.getContentStatus(); @@ -131,6 +134,11 @@ public abstract class StatusListFragment extends BaseStatusListFragment{ StatusListFragment.this.onStatusCreated(ev); } + @Subscribe + public void onStatusUnpinned(StatusUnpinnedEvent ev){ + StatusListFragment.this.onStatusUnpinned(ev); + } + @Subscribe public void onPollUpdated(PollUpdatedEvent ev){ if(!ev.accountID.equals(accountID)) diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java index 468abe32f..7c70621de 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java @@ -137,6 +137,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ int id=menuItem.getItemId(); if(id==R.id.delete){ UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{}); + }else if(id==R.id.pin || id==R.id.unpin){ + UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s->{}); }else if(id==R.id.mute){ UiUtils.confirmToggleMuteUser(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), account, relationship!=null && relationship.muting, r->{}); }else if(id==R.id.block){ @@ -250,6 +252,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ Menu menu=optionsMenu.getMenu(); boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account); menu.findItem(R.id.delete).setVisible(item.status!=null && isOwnPost); + menu.findItem(R.id.pin).setVisible(item.status!=null && isOwnPost && !item.status.pinned); + menu.findItem(R.id.unpin).setVisible(item.status!=null && isOwnPost && item.status.pinned); menu.findItem(R.id.open_in_browser).setVisible(item.status!=null); MenuItem blockDomain=menu.findItem(R.id.block_domain); MenuItem mute=menu.findItem(R.id.mute); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java index a689ae93e..b0f332063 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java @@ -11,7 +11,6 @@ import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; @@ -42,8 +41,10 @@ import org.joinmastodon.android.api.requests.accounts.SetAccountMuted; import org.joinmastodon.android.api.requests.accounts.SetDomainBlocked; import org.joinmastodon.android.api.requests.statuses.DeleteStatus; import org.joinmastodon.android.api.requests.statuses.GetStatusByID; +import org.joinmastodon.android.api.requests.statuses.SetStatusPinned; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.events.StatusDeletedEvent; +import org.joinmastodon.android.events.StatusUnpinnedEvent; import org.joinmastodon.android.fragments.HashtagTimelineFragment; import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ThreadFragment; @@ -349,6 +350,31 @@ public class UiUtils{ }); } + public static void confirmPinPost(Activity activity, String accountID, Status status, boolean pinned, Consumer resultCallback){ + showConfirmationAlert(activity, + pinned ? R.string.confirm_pin_post_title : R.string.confirm_unpin_post_title, + pinned ? R.string.confirm_pin_post : R.string.confirm_unpin_post, + pinned ? R.string.pin_post : R.string.unpin_post, + ()->{ + new SetStatusPinned(status.id, pinned) + .setCallback(new Callback<>() { + @Override + public void onSuccess(Status result) { + resultCallback.accept(result); + if (!result.pinned) + E.post(new StatusUnpinnedEvent(status.id, accountID)); + } + + @Override + public void onError(ErrorResponse error) { + error.showToast(activity); + } + }) + .wrapProgress(activity, pinned ? R.string.pinning : R.string.unpinning, false) + .exec(accountID); + }); + } + public static void setRelationshipToActionButton(Relationship relationship, Button button){ boolean secondaryStyle; if(relationship.blocking){ diff --git a/mastodon/src/main/res/menu/post.xml b/mastodon/src/main/res/menu/post.xml index 877bd3e26..cc620956f 100644 --- a/mastodon/src/main/res/menu/post.xml +++ b/mastodon/src/main/res/menu/post.xml @@ -1,6 +1,8 @@ + + diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index 809990425..2e7cfdf13 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -130,6 +130,14 @@ Delete Post Are you sure you want to delete this post? Deleting… + Pin to profile + Pin post to profile + Do you want to pin this post to your profile? + Pinning post… + Unpin from profile + Unpin post from profile + Are you sure you want to unpin this post? + Unpinning post… Audio playback Play Pause