Inline statuses

This commit is contained in:
Grishka
2024-09-18 19:25:59 +03:00
parent 0627644019
commit 114c77a665
8 changed files with 216 additions and 12 deletions

View File

@@ -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<StatusDisplayItem> 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();
}
}

View File

@@ -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<StatusDisplayItem> buildDisplayItems(Status s){
List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false);
List<StatusDisplayItem> 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()));

View File

@@ -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<InlineStatusStatusDisplayItem> 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();
}
}
}
}

View File

@@ -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<T> extends BindableViewHolder<T> implements UsableRecyclerView.DisableableClickable{

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:color="?colorM3OutlineVariant" android:width="1dp"/>
<corners android:radius="8dp"/>
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M383,553L767,553L641,385L551,505L485,417L383,553ZM347,731Q297.3,731 263.15,696.85Q229,662.7 229,613L229,157Q229,107.3 263.15,73.15Q297.3,39 347,39L803,39Q852.7,39 886.85,73.15Q921,107.3 921,157L921,613Q921,662.7 886.85,696.85Q852.7,731 803,731L347,731ZM347,613L803,613Q803,613 803,613Q803,613 803,613L803,157Q803,157 803,157Q803,157 803,157L347,157Q347,157 347,157Q347,157 347,157L347,613Q347,613 347,613Q347,613 347,613ZM157,921Q107.3,921 73.15,886.85Q39,852.7 39,803L39,229L157,229L157,803Q157,803 157,803Q157,803 157,803L731,803L731,921L157,921ZM347,157L347,157Q347,157 347,157Q347,157 347,157L347,613Q347,613 347,613Q347,613 347,613L347,613Q347,613 347,613Q347,613 347,613L347,157Q347,157 347,157Q347,157 347,157Z"/>
</vector>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="12dp"
android:paddingTop="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/bg_inline_status">
<ImageView
android:id="@+id/ava"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginVertical="2dp"
android:importantForAccessibility="no"
tools:src="#0f0"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_toEndOf="@id/ava"
android:layout_marginStart="4dp"
android:textAppearance="@style/m3_title_small"
android:textColor="?colorM3OnSurface"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center_vertical"
tools:text="Name"/>
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_toEndOf="@id/name"
android:layout_marginStart="4dp"
android:textAppearance="@style/m3_body_medium"
android:textColor="?colorM3Outline"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center_vertical"
tools:text="\@username@server"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_marginTop="4dp"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurfaceVariant"
android:maxLines="3"
android:ellipsize="end"
android:drawableTint="?colorM3Outline"
android:drawablePadding="4dp"
tools:text="Post text goes here"/>
</RelativeLayout>
</FrameLayout>

View File

@@ -780,4 +780,8 @@
<string name="cant_load_image">Couldnt load image</string>
<string name="poll_see_results">See results</string>
<string name="poll_hide_results">Hide results</string>
<plurals name="x_attachments">
<item quantity="one">%d attachment</item>
<item quantity="other">%d attachments</item>
</plurals>
</resources>