Commit Diff


commit - a1a12dddfe17f2141ce31b7835a3b2fc5834554f
commit + 7b56338e1df5c9bd8057bf13183df3d2579e3b5c
blob - f7610292bfdc50ab4b77ca34141eed386b413d33
blob + 4609014b03f68944055cd2f2e89c86cd52bb3a5d
--- mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java
+++ mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIRequest.java
@@ -139,7 +139,7 @@ public abstract class MastodonAPIRequest<T> extends AP
 		return this;
 	}
 
-	protected void setRequestBody(Object body){
+	public void setRequestBody(Object body){
 		requestBody=body;
 	}
 
blob - /dev/null
blob + eeed317352506a91c524a1cd83168850f3eb345f (mode 644)
--- /dev/null
+++ 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);
+	}
+}
blob - /dev/null
blob + a4722e9557c2dc4066f5e4348d640a84a46c1827 (mode 644)
--- /dev/null
+++ 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);
+	}
+}
blob - 6c062a7e0c2c8d0f366bb5aafee4f6a6ef87f1a7
blob + c9a57f35a1561f5fb6abc77efce4bc664ddbe668
--- mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java
+++ 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 im
 		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 im
 		}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();
blob - 3353eea9c54e8a16729354a53df28c5330b0ec89
blob + 06bd136199db77ba10a611898612aedbb0bc08d9
--- mastodon/src/main/java/org/joinmastodon/android/model/Notification.java
+++ mastodon/src/main/java/org/joinmastodon/android/model/Notification.java
@@ -65,7 +65,9 @@ public class Notification extends BaseModel implements
 		@SerializedName("admin.sign_up")
 		SIGN_UP,
 		@SerializedName("admin.report")
-		REPORT
+		REPORT,
+		@SerializedName("bite")
+		BITE
 	}
 
 	@Parcel
blob - 16a1ae52e14aed4f12f3801c6625ea63a358d7dd
blob + 31a4709c63b3ef5037bd4d4d8452b6265cda5052
--- mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java
+++ mastodon/src/main/java/org/joinmastodon/android/ui/CustomEmojiPopupKeyboard.java
@@ -111,12 +111,13 @@ public class CustomEmojiPopupKeyboard extends PopupKey
 		list.setPadding(V.dp(16), 0, V.dp(16), 0);
 		imgLoader=new ListImageLoaderWrapper(activity, list, new RecyclerViewDelegate(list), null);
 
-		List<Emoji> 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<Emoji> 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 PopupKey
 		}
 	}
 
+	public void customToggleKeyboardPopup(){
+		List<Emoji> 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<RecyclerView.ViewHolder> implements ImageLoaderRecyclerAdapter, Filterable{
 		private EmojiCategory category;
 
blob - 0c0c1b99145f2405e985b49d5056debfe87ee733
blob + f3b0a6cf00e14f86059773cbe6105e4d5327074d
--- mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java
+++ mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/EmojiReactionsStatusDisplayItem.java
@@ -317,7 +317,7 @@ public class EmojiReactionsStatusDisplayItem extends S
 		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();
blob - 98e4d0e05dcba5062d59bfb950821a8b09f6f818
blob + 0f3bd2935b956619e0f89c9d67d5051e0c417465
--- mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java
+++ 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 StatusDis
 					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 StatusDis
 			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);
blob - bb90911fdc1a7521527e96496bb84621c76fbb57
blob + e8ade22a4e6a0e5855ce1b1b49261d41ee49ba77
--- mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java
+++ mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/NotificationHeaderStatusDisplayItem.java
@@ -75,6 +75,7 @@ public class NotificationHeaderStatusDisplayItem exten
 				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 exten
 				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){
blob - 724cb34c0da14756b41836b8e0078aa6668985ad
blob + 934e57b642018705ac40faf850da36e980b27313
--- mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java
+++ mastodon/src/main/java/org/joinmastodon/android/ui/viewholders/AccountViewHolder.java
@@ -25,6 +25,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 +67,7 @@ public class AccountViewHolder extends BindableViewHol
 	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 +104,7 @@ public class AccountViewHolder extends BindableViewHol
 		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);
blob - 1beb3d46493af15cc208c794eb9cd32bccab42c4
blob + 9474ff02a1117dc45a4a200d4eefed91fd5d7556
--- mastodon/src/main/res/menu/post.xml
+++ mastodon/src/main/res/menu/post.xml
@@ -8,6 +8,7 @@
 		<item android:id="@+id/unpin" android:title="@string/sk_unpin_post" android:icon="@drawable/ic_fluent_pin_off_24_regular"/>
 	</group>
 	<group android:id="@+id/menu_group2">
+		<item android:id="@+id/bitepost_btn" android:title="@string/sk_bite_post" android:icon="@drawable/ic_fluent_animal_cat_24_regular"/>
 		<item android:id="@+id/manage_user_lists" android:title="@string/add_user_to_list" android:icon="@drawable/ic_fluent_people_24_regular"/>
 		<item android:id="@+id/follow" android:title="@string/follow_user" android:icon="@drawable/ic_fluent_person_add_24_regular"/>
 		<item android:id="@+id/mute" android:title="@string/mute_user" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
blob - 043e963123057dfdb149e65e05deb57c2b14c023
blob + 0217336924483512bd76e7ae299dae36f81a64d0
--- mastodon/src/main/res/menu/profile.xml
+++ mastodon/src/main/res/menu/profile.xml
@@ -2,6 +2,7 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
 	<group android:id="@+id/menu_group1">
 		<item android:id="@+id/edit_note" android:title="@string/sk_add_note" android:icon="@drawable/ic_fluent_notepad_24_regular" android:showAsAction="ifRoom" />
+		<item android:id="@+id/biteuser_btn" android:title="@string/sk_bite_user" android:icon="@drawable/ic_fluent_animal_cat_24_regular" android:showAsAction="ifRoom" />
 	</group>
 	<group android:id="@+id/menu_group2">
 		<item android:id="@+id/manage_user_lists" android:title="@string/add_user_to_list" android:icon="@drawable/ic_fluent_people_24_regular"/>
blob - 7a258a06b5be8f19ecfdaee3226c1e3ba1f59611
blob + 3201e3f94b6f841b1b9f708d6ef08087ea644cd3
--- mastodon/src/main/res/values/strings_sk.xml
+++ mastodon/src/main/res/values/strings_sk.xml
@@ -439,4 +439,7 @@
 	<string name="sk_poll_multiple_choice">Multiple choices</string>
 	<string name="sk_poll_show_results">Show results</string>
 	<string name="sk_poll_hide_results">Hide results</string>
+	<string name="sk_bit_you">%s bit you</string>
+	<string name="sk_bite_user">Bite</string>
+	<string name="sk_bite_post">Bite this post</string>
 </resources>