From 9c89abf1c45ca74e1dfe2e00ed37d816c3f6e999 Mon Sep 17 00:00:00 2001 From: sk Date: Sat, 21 May 2022 19:27:44 +0200 Subject: [PATCH 1/5] implement bookmark button --- .../api/StatusInteractionController.java | 32 +++++++++++++++++++ .../displayitems/FooterStatusDisplayItem.java | 15 ++++++++- .../main/res/layout/display_item_footer.xml | 22 +++++++++++++ mastodon/src/main/res/values/colors.xml | 1 + mastodon/src/main/res/values/strings.xml | 1 + 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/StatusInteractionController.java b/mastodon/src/main/java/org/joinmastodon/android/api/StatusInteractionController.java index a2a72e902..08a5dbd66 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/StatusInteractionController.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/StatusInteractionController.java @@ -4,6 +4,7 @@ import android.os.Looper; import org.joinmastodon.android.E; import org.joinmastodon.android.MastodonApp; +import org.joinmastodon.android.api.requests.statuses.SetStatusBookmarked; import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited; import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged; import org.joinmastodon.android.events.StatusCountersUpdatedEvent; @@ -18,6 +19,7 @@ public class StatusInteractionController{ private final String accountID; private final HashMap runningFavoriteRequests=new HashMap<>(); private final HashMap runningReblogRequests=new HashMap<>(); + private final HashMap runningBookmarkRequests=new HashMap<>(); public StatusInteractionController(String accountID){ this.accountID=accountID; @@ -61,6 +63,36 @@ public class StatusInteractionController{ E.post(new StatusCountersUpdatedEvent(status)); } + public void setBookmarked(Status status, boolean bookmarked){ + if(!Looper.getMainLooper().isCurrentThread()) + throw new IllegalStateException("Can only be called from main thread"); + + SetStatusBookmarked current=runningBookmarkRequests.remove(status.id); + if(current!=null){ + current.cancel(); + } + SetStatusBookmarked req=(SetStatusBookmarked) new SetStatusBookmarked(status.id, bookmarked) + .setCallback(new Callback<>(){ + @Override + public void onSuccess(Status result){ + runningBookmarkRequests.remove(status.id); + E.post(new StatusCountersUpdatedEvent(result)); + } + + @Override + public void onError(ErrorResponse error){ + runningBookmarkRequests.remove(status.id); + error.showToast(MastodonApp.context); + status.bookmarked=!bookmarked; + E.post(new StatusCountersUpdatedEvent(status)); + } + }) + .exec(accountID); + runningBookmarkRequests.put(status.id, req); + status.bookmarked=bookmarked; + E.post(new StatusCountersUpdatedEvent(status)); + } + public void setReblogged(Status status, boolean reblogged){ if(!Looper.getMainLooper().isCurrentThread()) throw new IllegalStateException("Can only be called from main thread"); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java index 776585cd7..145726021 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java @@ -43,7 +43,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ } public static class Holder extends StatusDisplayItem.Holder{ - private final TextView reply, boost, favorite; + private final TextView reply, boost, favorite, bookmark; private final ImageView share; private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){ @@ -60,22 +60,27 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{ reply=findViewById(R.id.reply); boost=findViewById(R.id.boost); favorite=findViewById(R.id.favorite); + bookmark=findViewById(R.id.bookmark); share=findViewById(R.id.share); if(Build.VERSION.SDK_INT + + + + + + #18000000 @color/warning_500 + @color/success_500 @color/primary_500 @color/gray_100 diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index 813814edf..9f172dec6 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -278,6 +278,7 @@ Reblog Favorite Share + Bookmark Media without description Add media Add a poll From 11905513b7ec543c2f3745c59345a04fa7953e6a Mon Sep 17 00:00:00 2001 From: sk Date: Sat, 21 May 2022 19:40:49 +0200 Subject: [PATCH 2/5] add missing icons --- .../src/main/res/drawable/ic_fluent_bookmark_24_filled.xml | 3 +++ .../src/main/res/drawable/ic_fluent_bookmark_24_regular.xml | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 mastodon/src/main/res/drawable/ic_fluent_bookmark_24_filled.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_bookmark_24_regular.xml diff --git a/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_filled.xml b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_filled.xml new file mode 100644 index 000000000..35c47a11b --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_filled.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_regular.xml new file mode 100644 index 000000000..629304636 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_regular.xml @@ -0,0 +1,3 @@ + + + From f9d0632a85ce27683e3a715f8789f60401bcbbac Mon Sep 17 00:00:00 2001 From: sk Date: Sat, 21 May 2022 19:42:29 +0200 Subject: [PATCH 3/5] add missing files --- .../api/requests/statuses/SetStatusBookmarked.java | 11 +++++++++++ mastodon/src/main/res/color/bookmark_icon.xml | 5 +++++ .../res/drawable/ic_fluent_bookmark_24_selector.xml | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusBookmarked.java create mode 100644 mastodon/src/main/res/color/bookmark_icon.xml create mode 100644 mastodon/src/main/res/drawable/ic_fluent_bookmark_24_selector.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusBookmarked.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusBookmarked.java new file mode 100644 index 000000000..3b010e24b --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/SetStatusBookmarked.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 SetStatusBookmarked extends MastodonAPIRequest{ + public SetStatusBookmarked(String id, boolean bookmarked){ + super(HttpMethod.POST, "/statuses/"+id+"/"+(bookmarked ? "bookmark" : "unbookmark"), Status.class); + setRequestBody(new Object()); + } +} diff --git a/mastodon/src/main/res/color/bookmark_icon.xml b/mastodon/src/main/res/color/bookmark_icon.xml new file mode 100644 index 000000000..085890f67 --- /dev/null +++ b/mastodon/src/main/res/color/bookmark_icon.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_selector.xml b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_selector.xml new file mode 100644 index 000000000..8cd4d4e92 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_bookmark_24_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + From 8fddaa8c8258b97ce1f8a4c936f9b438abd0dc7b Mon Sep 17 00:00:00 2001 From: sk Date: Sun, 22 May 2022 02:03:29 +0200 Subject: [PATCH 4/5] implement bookmarks list!! --- .../api/requests/accounts/GetBookmarks.java | 52 ++++++++++++++++++ .../fragments/BookmarksListFragment.java | 53 +++++++++++++++++++ .../android/fragments/ProfileFragment.java | 11 ++-- mastodon/src/main/res/menu/profile.xml | 6 +++ mastodon/src/main/res/values/strings.xml | 1 + 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetBookmarks.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarksListFragment.java diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetBookmarks.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetBookmarks.java new file mode 100644 index 000000000..fb1311225 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetBookmarks.java @@ -0,0 +1,52 @@ +package org.joinmastodon.android.api.requests.accounts; + +import androidx.annotation.NonNull; + +import com.google.gson.reflect.TypeToken; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.Status; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import okhttp3.Response; + +public class GetBookmarks extends MastodonAPIRequest>{ + private String maxId; + + public GetBookmarks(String maxID, String minID, int limit){ + super(HttpMethod.GET, "/bookmarks", new TypeToken<>(){}); + if(maxID!=null) + addQueryParameter("max_id", maxID); + if(minID!=null) + addQueryParameter("min_id", minID); + if(limit>0) + addQueryParameter("limit", ""+limit); + } + + @Override + public void validateAndPostprocessResponse(List respObj, Response httpResponse) throws IOException { + super.validateAndPostprocessResponse(respObj, httpResponse); + // ; rel="next", + // ; rel="prev" + String link=httpResponse.header("link"); + // parsing link header by hand; using a library would be cleaner + // (also, the functionality should be part of the max id logics and implemented in MastodonAPIRequest) + if(link==null) return; + String maxIdEq="max_id="; + for(String s : link.split(",")) { + if(s.contains("rel=\"next\"")) { + int start=s.indexOf(maxIdEq)+maxIdEq.length(); + int end=s.indexOf('>'); + if(start<0 || start>end) return; + this.maxId=s.substring(start, end); + } + } + } + + public String getMaxId() { + return maxId; + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarksListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarksListFragment.java new file mode 100644 index 000000000..cd26bd980 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BookmarksListFragment.java @@ -0,0 +1,53 @@ +package org.joinmastodon.android.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.accounts.GetBookmarks; +import org.joinmastodon.android.api.session.AccountSession; +import org.joinmastodon.android.api.session.AccountSessionManager; +import org.joinmastodon.android.model.Account; +import org.joinmastodon.android.model.Status; + +import java.util.List; + +import me.grishka.appkit.api.SimpleCallback; + +public class BookmarksListFragment extends StatusListFragment{ + + private String accountID; + private Account self; + private String lastMaxId=null; + + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + accountID=getArguments().getString("account"); + AccountSession session=AccountSessionManager.getInstance().getAccount(accountID); + self=session.self; + setTitle(R.string.bookmarks); + } + + @Override + protected void onShown(){ + super.onShown(); + if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading) + loadData(); + } + + @Override + protected void doLoadData(int offset, int count) { + GetBookmarks b=new GetBookmarks(offset>0 ? lastMaxId : null, null, count); + currentRequest=b.setCallback(new SimpleCallback<>(this){ + @Override + public void onSuccess(List result){ + onDataLoaded(result, b.getMaxId()!=null); + lastMaxId=b.getMaxId(); + } + }) + .exec(accountID); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index 724396c61..d34e7b4de 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -516,7 +516,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList if(isOwnProfile){ for(int i=0;i + \ No newline at end of file diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index 9f172dec6..ff37c0ee6 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -279,6 +279,7 @@ Favorite Share Bookmark + Bookmarks Media without description Add media Add a poll From ed7242217afc6e0d3f445c8e6f3bc5be8f83cbd8 Mon Sep 17 00:00:00 2001 From: sk Date: Sun, 22 May 2022 02:03:54 +0200 Subject: [PATCH 5/5] add missing icon --- .../res/drawable/ic_fluent_bookmark_multiple_24_filled.xml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 mastodon/src/main/res/drawable/ic_fluent_bookmark_multiple_24_filled.xml diff --git a/mastodon/src/main/res/drawable/ic_fluent_bookmark_multiple_24_filled.xml b/mastodon/src/main/res/drawable/ic_fluent_bookmark_multiple_24_filled.xml new file mode 100644 index 000000000..b3ff6ab89 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_bookmark_multiple_24_filled.xml @@ -0,0 +1,3 @@ + + +