Inline statuses
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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{
|
||||
|
||||
5
mastodon/src/main/res/drawable/bg_inline_status.xml
Normal file
5
mastodon/src/main/res/drawable/bg_inline_status.xml
Normal 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>
|
||||
@@ -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>
|
||||
66
mastodon/src/main/res/layout/display_item_inline_status.xml
Normal file
66
mastodon/src/main/res/layout/display_item_inline_status.xml
Normal 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>
|
||||
@@ -780,4 +780,8 @@
|
||||
<string name="cant_load_image">Couldn’t 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>
|
||||
Reference in New Issue
Block a user