From ab3d3ff06896338aaf3664bcbaf1c1bf920f67b5 Mon Sep 17 00:00:00 2001 From: notfire Date: Wed, 19 Mar 2025 20:57:31 -0400 Subject: [PATCH] add support for sending bites --- mastodon/build.gradle | 4 ++-- .../android/api/MastodonAPIRequest.java | 2 +- .../api/requests/accounts/BiteAccount.java | 14 ++++++++++++ .../api/requests/statuses/BitePost.java | 9 ++++++++ .../android/fragments/ProfileFragment.java | 15 ++++++++++++- .../android/model/Notification.java | 4 +++- .../android/ui/CustomEmojiPopupKeyboard.java | 22 ++++++++++++++----- .../EmojiReactionsStatusDisplayItem.java | 2 +- .../displayitems/HeaderStatusDisplayItem.java | 16 ++++++++++++++ .../NotificationHeaderStatusDisplayItem.java | 2 ++ .../ui/viewholders/AccountViewHolder.java | 6 +++-- mastodon/src/main/res/menu/post.xml | 1 + mastodon/src/main/res/menu/profile.xml | 1 + mastodon/src/main/res/values/strings_sk.xml | 3 +++ 14 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/BiteAccount.java create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/BitePost.java diff --git a/mastodon/build.gradle b/mastodon/build.gradle index 154b3073f..8f49c775a 100644 --- a/mastodon/build.gradle +++ b/mastodon/build.gradle @@ -13,11 +13,11 @@ android { defaultConfig { manifestPlaceholders = [oAuthScheme:"moshidon-android-auth"] archivesBaseName = "moshidon" - applicationId "org.joinmastodon.android.moshinda" + applicationId "org.joinmastodon.android.moshinda.luke" minSdk 23 targetSdk 34 versionCode 108 - versionName "2.3.0+fork.108.moshinda" + versionName "2.3.0+fork.108.moshinda.luke" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" resourceConfigurations += ['ar-rSA', 'ar-rDZ', 'be-rBY', 'bn-rBD', 'bs-rBA', 'ca-rES', 'cs-rCZ', 'da-rDK', 'de-rDE', 'el-rGR', 'es-rES', 'eu-rES', 'fa-rIR', 'fi-rFI', 'fil-rPH', 'fr-rFR', 'ga-rIE', 'gd-rGB', 'gl-rES', 'hi-rIN', 'hr-rHR', 'hu-rHU', 'hy-rAM', 'ig-rNG', 'in-rID', 'is-rIS', 'it-rIT', 'iw-rIL', 'ja-rJP', 'kab', 'ko-rKR', 'my-rMM', 'nl-rNL', 'no-rNO', 'oc-rFR', 'pl-rPL', 'pt-rBR', 'pt-rPT', 'ro-rRO', 'ru-rRU', 'si-rLK', 'sl-rSI', 'sv-rSE', 'th-rTH', 'tr-rTR', 'uk-rUA', 'ur-rIN', 'vi-rVN', 'zh-rCN', 'zh-rTW'] } diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java b/mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java index f7610292b..4609014b0 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java @@ -139,7 +139,7 @@ public abstract class MastodonAPIRequest extends APIRequest{ return this; } - protected void setRequestBody(Object body){ + public void setRequestBody(Object body){ requestBody=body; } diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/BiteAccount.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/BiteAccount.java new file mode 100644 index 000000000..eeed31735 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/BiteAccount.java @@ -0,0 +1,14 @@ +package org.joinmastodon.android.api.requests.accounts; + +import com.google.gson.reflect.TypeToken; + +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.FollowList; + +import java.util.List; + +public class BiteAccount extends MastodonAPIRequest{ + public BiteAccount(String id){ + super(HttpMethod.POST, "/users/"+id+"/bite", BiteAccount.class); + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/BitePost.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/BitePost.java new file mode 100644 index 000000000..a4722e955 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/BitePost.java @@ -0,0 +1,9 @@ +package org.joinmastodon.android.api.requests.statuses; + +import org.joinmastodon.android.api.MastodonAPIRequest; + +public class BitePost extends MastodonAPIRequest{ + public BitePost(String id){ + super(HttpMethod.POST, "/statuses/"+id+"/bite", BitePost.class); + } +} 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 6c062a7e0..c9a57f35a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -60,6 +60,7 @@ import androidx.viewpager2.widget.ViewPager2; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.accounts.BiteAccount; import org.joinmastodon.android.api.requests.accounts.GetAccountByID; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses; @@ -816,7 +817,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList if(isOwnProfile){ UiUtils.enableOptionsMenuIcons(getActivity(), menu, R.id.scheduled, R.id.bookmarks); }else{ - UiUtils.enableOptionsMenuIcons(getActivity(), menu, R.id.edit_note); + UiUtils.enableOptionsMenuIcons(getActivity(), menu, R.id.edit_note, R.id.biteuser_btn); } boolean hasMultipleAccounts = AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1; menu.findItem(R.id.open_with_account).setVisible(hasMultipleAccounts); @@ -933,6 +934,18 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList }else if(id==R.id.save){ if(isInEditMode) saveAndExitEditMode(); + }else if(id==R.id.biteuser_btn){ + new BiteAccount(profileAccountID).setCallback(new Callback<>(){ + @Override + public void onSuccess(Object result){ + Toast.makeText(getContext(), "User was bitten", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getContext()); + } + }).exec(accountID).setRequestBody(new Object()); }else if(id==R.id.edit_note){ if(noteWrap.getVisibility()==View.GONE){ showPrivateNote(); diff --git a/mastodon/src/main/java/org/joinmastodon/android/model/Notification.java b/mastodon/src/main/java/org/joinmastodon/android/model/Notification.java index 3353eea9c..06bd13619 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/model/Notification.java +++ b/mastodon/src/main/java/org/joinmastodon/android/model/Notification.java @@ -65,7 +65,9 @@ public class Notification extends BaseModel implements DisplayItemsParent{ @SerializedName("admin.sign_up") SIGN_UP, @SerializedName("admin.report") - REPORT + REPORT, + @SerializedName("bite") + BITE } @Parcel diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java b/mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java index 16a1ae52e..31a4709c6 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java @@ -111,12 +111,13 @@ public class CustomEmojiPopupKeyboard extends PopupKeyboard{ list.setPadding(V.dp(16), 0, V.dp(16), 0); imgLoader=new ListImageLoaderWrapper(activity, list, new RecyclerViewDelegate(list), null); - List recentEmoji=new ArrayList<>(lp.recentCustomEmoji); - if(!recentEmoji.isEmpty()) - adapter.addAdapter(new SingleCategoryAdapter(recentEmojiCategory=new EmojiCategory(activity.getString(R.string.mo_emoji_recent), recentEmoji))); - - for(EmojiCategory category:emojis) - adapter.addAdapter(new SingleCategoryAdapter(category)); + if (!forReaction){ + List recentEmoji=new ArrayList<>(lp.recentCustomEmoji); + if(!recentEmoji.isEmpty()) + adapter.addAdapter(new SingleCategoryAdapter(recentEmojiCategory=new EmojiCategory(activity.getString(R.string.mo_emoji_recent), recentEmoji))); + for(EmojiCategory category : emojis) + adapter.addAdapter(new SingleCategoryAdapter(category)); + } list.setAdapter(adapter); list.addItemDecoration(new RecyclerView.ItemDecoration(){ @Override @@ -229,6 +230,15 @@ public class CustomEmojiPopupKeyboard extends PopupKeyboard{ } } + public void customToggleKeyboardPopup(){ + List recentEmoji=new ArrayList<>(lp.recentCustomEmoji); + if(!recentEmoji.isEmpty()) + adapter.addAdapter(new SingleCategoryAdapter(recentEmojiCategory=new EmojiCategory(activity.getString(R.string.mo_emoji_recent), recentEmoji))); + for(EmojiCategory category : emojis) + adapter.addAdapter(new SingleCategoryAdapter(category)); + super.toggleKeyboardPopup(null); + } + private class SingleCategoryAdapter extends UsableRecyclerView.Adapter implements ImageLoaderRecyclerAdapter, Filterable{ private EmojiCategory category; diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java index f0555f6f0..be6017060 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java @@ -317,7 +317,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem { public void onBackspace() {} private void onReactClick(View v){ - emojiKeyboard.toggleKeyboardPopup(null); + emojiKeyboard.customToggleKeyboardPopup(); v.setSelected(emojiKeyboard.isVisible()); space.setVisibility(emojiKeyboard.isVisible() ? View.VISIBLE : View.GONE); DisplayMetrics displayMetrics = new DisplayMetrics(); 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 98e4d0e05..0f3bd2935 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 @@ -22,9 +22,12 @@ import android.widget.TextView; import android.widget.Toast; import org.joinmastodon.android.GlobalUserPreferences; +import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.accounts.BiteAccount; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; import org.joinmastodon.android.api.requests.announcements.DismissAnnouncement; +import org.joinmastodon.android.api.requests.statuses.BitePost; import org.joinmastodon.android.api.requests.statuses.CreateStatus; import org.joinmastodon.android.api.requests.statuses.GetStatusSourceText; import org.joinmastodon.android.api.session.AccountSession; @@ -263,6 +266,18 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ UiUtils.launchWebBrowser(activity, item.status.url); }else if(id==R.id.copy_link){ UiUtils.copyText(parent, item.status.url); + }else if(id==R.id.bitepost_btn){ + new BitePost(item.status.id).setCallback(new Callback<>(){ + @Override + public void onSuccess(Object result){ + Toast.makeText(MastodonApp.context, "Post was bitten", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(MastodonApp.context); + } + }).exec(item.parentFragment.getAccountID()).setRequestBody(new Object()); }else if(id==R.id.follow){ if(relationship==null) return true; @@ -513,6 +528,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ menu.findItem(R.id.unmute_conversation).setVisible(item.status!=null && item.status.muted); menu.findItem(R.id.open_in_browser).setVisible(!isPostScheduled && item.status!=null); menu.findItem(R.id.copy_link).setVisible(!isPostScheduled && item.status!=null); + menu.findItem(R.id.bitepost_btn).setVisible(!isOwnPost && !isPostScheduled && item.status!=null); MenuItem blockDomain=menu.findItem(R.id.block_domain); MenuItem mute=menu.findItem(R.id.mute); MenuItem block=menu.findItem(R.id.block); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java index bb90911fd..e8ade22a4 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java @@ -75,6 +75,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{ case REPORT -> R.string.sk_reported; case REACTION, PLEROMA_EMOJI_REACTION -> !TextUtils.isEmpty(notification.emoji) ? R.string.sk_reacted_with : R.string.sk_reacted; + case BITE -> R.string.sk_bit_you; default -> throw new IllegalStateException("Unexpected value: "+notification.type); }); @@ -170,6 +171,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{ case SIGN_UP -> R.drawable.ic_fluent_person_available_24_filled; case UPDATE -> R.drawable.ic_fluent_edit_24_filled; case REACTION, PLEROMA_EMOJI_REACTION -> R.drawable.ic_fluent_add_24_filled; + case BITE -> R.drawable.ic_fluent_animal_cat_24_regular; default -> throw new IllegalStateException("Unexpected value: "+item.notification.type); }); icon.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(item.parentFragment.getActivity(), switch(item.notification.type){ diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java b/mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java index 724cb34c0..2fbee577c 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java @@ -3,7 +3,6 @@ package org.joinmastodon.android.ui.viewholders; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Fragment; -import android.content.Intent; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.os.Build; @@ -25,6 +24,7 @@ import android.widget.TextView; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.accounts.BiteAccount; import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.fragments.AddAccountToListsFragment; @@ -66,6 +66,7 @@ public class AccountViewHolder extends BindableViewHolder impl private final View checkbox; private final ProgressBar actionProgress; private final ImageButton menuButton; + private final ImageButton biteUserButton; private final String accountID; private final Fragment fragment; @@ -102,6 +103,7 @@ public class AccountViewHolder extends BindableViewHolder impl checkbox=findViewById(R.id.checkbox); actionProgress=findViewById(R.id.action_progress); menuButton=findViewById(R.id.options_btn); + biteUserButton=findViewById(R.id.biteuser_btn); avatar.setOutlineProvider(OutlineProviders.roundedRect(10)); avatar.setClipToOutline(true); @@ -112,7 +114,7 @@ public class AccountViewHolder extends BindableViewHolder impl contextMenu=new PopupMenu(fragment.getActivity(), menuAnchor); contextMenu.inflate(R.menu.profile); contextMenu.setOnMenuItemClickListener(this::onContextMenuItemSelected); - menuButton.setOnClickListener(v->showMenuFromButton()); + menuButton.setOnClickListener(v -> showMenuFromButton()); if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P && !UiUtils.isEMUI() && !UiUtils.isMagic()) contextMenu.getMenu().setGroupDividerEnabled(true); UiUtils.enablePopupMenuIcons(fragment.getContext(), contextMenu); diff --git a/mastodon/src/main/res/menu/post.xml b/mastodon/src/main/res/menu/post.xml index 1beb3d464..9474ff02a 100644 --- a/mastodon/src/main/res/menu/post.xml +++ b/mastodon/src/main/res/menu/post.xml @@ -8,6 +8,7 @@ + diff --git a/mastodon/src/main/res/menu/profile.xml b/mastodon/src/main/res/menu/profile.xml index 043e96312..021733692 100644 --- a/mastodon/src/main/res/menu/profile.xml +++ b/mastodon/src/main/res/menu/profile.xml @@ -2,6 +2,7 @@ + diff --git a/mastodon/src/main/res/values/strings_sk.xml b/mastodon/src/main/res/values/strings_sk.xml index 9795f7cc9..f28901365 100644 --- a/mastodon/src/main/res/values/strings_sk.xml +++ b/mastodon/src/main/res/values/strings_sk.xml @@ -438,4 +438,7 @@ Multiple choices Show results Hide results + %s bit you + Bite + Bite this post