From 114c77a66539b078108f71634397670b0fc491b8 Mon Sep 17 00:00:00 2001 From: Grishka Date: Wed, 18 Sep 2024 19:25:59 +0300 Subject: [PATCH] Inline statuses --- .../BaseNotificationsListFragment.java | 18 ++- .../fragments/StatusEditHistoryFragment.java | 7 +- .../InlineStatusStatusDisplayItem.java | 115 ++++++++++++++++++ .../ui/displayitems/StatusDisplayItem.java | 4 +- .../main/res/drawable/bg_inline_status.xml | 5 + .../ic_photo_library_wght700_20px.xml | 9 ++ .../res/layout/display_item_inline_status.xml | 66 ++++++++++ mastodon/src/main/res/values/strings.xml | 4 + 8 files changed, 216 insertions(+), 12 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/InlineStatusStatusDisplayItem.java create mode 100644 mastodon/src/main/res/drawable/bg_inline_status.xml create mode 100644 mastodon/src/main/res/drawable/ic_photo_library_wght700_20px.xml create mode 100644 mastodon/src/main/res/layout/display_item_inline_status.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseNotificationsListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseNotificationsListFragment.java index 81df11309..ecaf63885 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseNotificationsListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseNotificationsListFragment.java @@ -7,12 +7,11 @@ import android.view.View; import org.joinmastodon.android.R; import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.displayitems.InlineStatusStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.NotificationHeaderStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; import org.parceler.Parcels; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import me.grishka.appkit.Nav; @@ -34,16 +33,15 @@ public abstract class BaseNotificationsListFragment extends BaseStatusListFragme } } if(n.status!=null){ - // TODO - int flags=titleItem==null ? 0 : (StatusDisplayItem.FLAG_NO_FOOTER | StatusDisplayItem.FLAG_NO_HEADER); - ArrayList items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, flags); - if(titleItem!=null) - items.add(0, titleItem); - return items; + if(titleItem!=null){ + return List.of(titleItem, new InlineStatusStatusDisplayItem(n.id, this, n.status)); + }else{ + return StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, 0); + } }else if(titleItem!=null){ - return Collections.singletonList(titleItem); + return List.of(titleItem); }else{ - return Collections.emptyList(); + return List.of(); } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java index db8ffc8c9..6cdf61a57 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java @@ -6,11 +6,13 @@ import android.os.Bundle; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.statuses.GetStatusEditHistory; import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.displayitems.InlineStatusStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; import org.joinmastodon.android.ui.utils.UiUtils; import java.time.ZoneId; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; @@ -52,7 +54,10 @@ public class StatusEditHistoryFragment extends StatusListFragment{ @Override protected List buildDisplayItems(Status s){ - List items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false); + List items=new ArrayList<>(); + InlineStatusStatusDisplayItem inlineItem=new InlineStatusStatusDisplayItem(s.getID(), this, s); + inlineItem.fullWidth=true; + items.add(inlineItem); int idx=data.indexOf(s); if(idx>=0){ String date=UiUtils.DATE_TIME_FORMATTER.format(s.createdAt.atZone(ZoneId.systemDefault())); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/InlineStatusStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/InlineStatusStatusDisplayItem.java new file mode 100644 index 000000000..13afb01de --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/InlineStatusStatusDisplayItem.java @@ -0,0 +1,115 @@ +package org.joinmastodon.android.ui.displayitems; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.text.SpannableStringBuilder; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import org.joinmastodon.android.GlobalUserPreferences; +import org.joinmastodon.android.R; +import org.joinmastodon.android.api.session.AccountSessionManager; +import org.joinmastodon.android.fragments.BaseStatusListFragment; +import org.joinmastodon.android.model.Status; +import org.joinmastodon.android.ui.OutlineProviders; +import org.joinmastodon.android.ui.text.CustomEmojiSpan; +import org.joinmastodon.android.ui.text.HtmlParser; +import org.joinmastodon.android.ui.utils.CustomEmojiHelper; +import org.joinmastodon.android.ui.utils.UiUtils; + +import me.grishka.appkit.imageloader.ImageLoaderViewHolder; +import me.grishka.appkit.imageloader.requests.ImageLoaderRequest; +import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest; +import me.grishka.appkit.utils.V; + +public class InlineStatusStatusDisplayItem extends StatusDisplayItem{ + public final Status status; + private CustomEmojiHelper emojiHelper=new CustomEmojiHelper(); + private SpannableStringBuilder parsedName; + private SpannableStringBuilder parsedPostText; + private UrlImageLoaderRequest avaRequest; + + public InlineStatusStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){ + super(parentID, parentFragment); + this.status=status; + + parsedName=new SpannableStringBuilder(status.account.displayName); + if(AccountSessionManager.get(parentFragment.getAccountID()).getLocalPreferences().customEmojiInNames) + HtmlParser.parseCustomEmoji(parsedName, status.account.emojis); + + parsedPostText=HtmlParser.parse(status.content, status.emojis, status.mentions, status.tags, parentFragment.getAccountID(), status.getContentStatus()); + for(Object span:parsedPostText.getSpans(0, parsedPostText.length(), Object.class)){ + if(!(span instanceof CustomEmojiSpan)) + parsedPostText.removeSpan(span); + } + + SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName); + ssb.append(parsedPostText); + emojiHelper.setText(ssb); + + avaRequest=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? status.account.avatar : status.account.avatarStatic, V.dp(50), V.dp(50)); + } + + @Override + public Type getType(){ + return Type.INLINE_STATUS; + } + + @Override + public int getImageCount(){ + return emojiHelper.getImageCount()+1; + } + + @Override + public ImageLoaderRequest getImageRequest(int index){ + if(index==0) + return avaRequest; + return emojiHelper.getImageRequest(index-1); + } + + public static class Holder extends StatusDisplayItem.Holder implements ImageLoaderViewHolder{ + private final TextView name, username, text; + private final ImageView ava; + + public Holder(Context context, ViewGroup parent){ + super(context, R.layout.display_item_inline_status, parent); + name=findViewById(R.id.name); + username=findViewById(R.id.username); + text=findViewById(R.id.text); + ava=findViewById(R.id.ava); + + ava.setOutlineProvider(OutlineProviders.roundedRect(4)); + ava.setClipToOutline(true); + } + + @Override + public void onBind(InlineStatusStatusDisplayItem item){ + itemView.setPaddingRelative(V.dp(item.fullWidth ? 16 : 64), itemView.getPaddingTop(), itemView.getPaddingEnd(), itemView.getPaddingBottom()); + name.setText(item.parsedName); + username.setText(item.status.account.getDisplayUsername()); + if(item.parsedPostText.length()==0){ + text.setTextColor(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3Outline)); + text.setText(itemView.getContext().getResources().getQuantityString(R.plurals.x_attachments, item.status.mediaAttachments.size(), item.status.mediaAttachments.size())); + Drawable icon=itemView.getContext().getDrawable(R.drawable.ic_photo_library_wght700_20px); + icon.setBounds(0, 0, V.dp(16), V.dp(16)); + text.setCompoundDrawablesRelative(icon, null, null, null); + }else{ + text.setTextColor(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3OnSurfaceVariant)); + text.setCompoundDrawables(null, null, null, null); + text.setText(item.parsedPostText); + } + } + + @Override + public void setImage(int index, Drawable image){ + if(index==0){ + ava.setImageDrawable(image); + }else{ + item.emojiHelper.setImageDrawable(index-1, image); + text.invalidate(); + name.invalidate(); + } + } + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java index 59eea28f7..229c58d12 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java @@ -80,6 +80,7 @@ public abstract class StatusDisplayItem{ case SPOILER, FILTER_SPOILER -> new SpoilerStatusDisplayItem.Holder(activity, parent, type); case SECTION_HEADER -> new SectionHeaderStatusDisplayItem.Holder(activity, parent); case NOTIFICATION_HEADER -> new NotificationHeaderStatusDisplayItem.Holder(activity, parent); + case INLINE_STATUS -> new InlineStatusStatusDisplayItem.Holder(activity, parent); }; } @@ -224,7 +225,8 @@ public abstract class StatusDisplayItem{ SECTION_HEADER, HEADER_CHECKABLE, NOTIFICATION_HEADER, - FILTER_SPOILER + FILTER_SPOILER, + INLINE_STATUS } public static abstract class Holder extends BindableViewHolder implements UsableRecyclerView.DisableableClickable{ diff --git a/mastodon/src/main/res/drawable/bg_inline_status.xml b/mastodon/src/main/res/drawable/bg_inline_status.xml new file mode 100644 index 000000000..16fc65613 --- /dev/null +++ b/mastodon/src/main/res/drawable/bg_inline_status.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mastodon/src/main/res/drawable/ic_photo_library_wght700_20px.xml b/mastodon/src/main/res/drawable/ic_photo_library_wght700_20px.xml new file mode 100644 index 000000000..b68d78364 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_photo_library_wght700_20px.xml @@ -0,0 +1,9 @@ + + + diff --git a/mastodon/src/main/res/layout/display_item_inline_status.xml b/mastodon/src/main/res/layout/display_item_inline_status.xml new file mode 100644 index 000000000..5a3c1a213 --- /dev/null +++ b/mastodon/src/main/res/layout/display_item_inline_status.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + \ 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 b8bfbfd24..b4485591e 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -780,4 +780,8 @@ Couldn’t load image See results Hide results + + %d attachment + %d attachments + \ No newline at end of file