From de763ab6f7d9dd0db8220659f78fff779c8d8b57 Mon Sep 17 00:00:00 2001 From: Grishka Date: Wed, 18 Sep 2024 04:59:12 +0300 Subject: [PATCH] Reply lines --- .../fragments/BaseStatusListFragment.java | 6 +- .../android/fragments/ThreadFragment.java | 84 ++++++++++++++++++- .../ui/displayitems/StatusDisplayItem.java | 3 +- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 6f70f68b..c67e7985 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -349,7 +349,11 @@ public abstract class BaseStatusListFragment exten protected void drawDivider(View child, View bottomSibling, RecyclerView.ViewHolder holder, RecyclerView.ViewHolder siblingHolder, RecyclerView parent, Canvas c, Paint paint){ parent.getDecoratedBoundsWithMargins(child, tmpRect); tmpRect.offset(0, Math.round(child.getTranslationY())); - float y=tmpRect.bottom-V.dp(.5f); + float y=tmpRect.bottom; + int strokeWidth=V.dp(0.5f); + if(strokeWidth%2==1){ + y-=0.5f; + } paint.setAlpha(Math.round(255*child.getAlpha())); c.drawLine(0, y, parent.getWidth(), y, paint); } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java index 6b05c31e..9a16bdc6 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java @@ -1,6 +1,8 @@ package org.joinmastodon.android.fragments; import android.content.res.ColorStateList; +import android.graphics.Canvas; +import android.graphics.Paint; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -22,6 +24,7 @@ import org.joinmastodon.android.model.StatusContext; import org.joinmastodon.android.ui.OutlineProviders; import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem; +import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem; @@ -31,7 +34,9 @@ import org.parceler.Parcels; import java.util.Collections; import java.util.List; +import java.util.Objects; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import me.grishka.appkit.Nav; import me.grishka.appkit.api.SimpleCallback; @@ -49,6 +54,7 @@ public class ThreadFragment extends StatusListFragment{ private ImageView replyButtonAva; private TextView replyButtonText; private int lastBottomInset; + private Paint replyLinePaint=new Paint(Paint.ANTI_ALIAS_FLAG); @Override public void onCreate(Bundle savedInstanceState){ @@ -68,7 +74,7 @@ public class ThreadFragment extends StatusListFragment{ @Override protected List buildDisplayItems(Status s){ - List items=super.buildDisplayItems(s); + List items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, StatusDisplayItem.FLAG_NO_IN_REPLY_TO); if(s.id.equals(mainStatus.id)){ for(StatusDisplayItem item:items){ item.fullWidth=true; @@ -158,6 +164,8 @@ public class ThreadFragment extends StatusListFragment{ showContent(); if(!loaded) footerProgress.setVisibility(View.VISIBLE); + + list.addItemDecoration(new ReplyLinesItemDecoration()); } protected void onStatusCreated(Status status){ @@ -223,4 +231,78 @@ public class ThreadFragment extends StatusListFragment{ public int getSnackbarOffset(){ return replyContainer.getHeight()-lastBottomInset; } + + @Override + protected void drawDivider(View child, View bottomSibling, RecyclerView.ViewHolder holder, RecyclerView.ViewHolder siblingHolder, RecyclerView parent, Canvas c, Paint paint){ + if(holder instanceof StatusDisplayItem.Holder statusHolder && siblingHolder instanceof StatusDisplayItem.Holder siblingStatusHolder){ + Status siblingStatus=getStatusByID(siblingStatusHolder.getItemID()); + if(statusHolder.getItemID().equals(siblingStatus.inReplyToId) && siblingStatus!=mainStatus && !statusHolder.getItemID().equals(mainStatus.id)) + return; + } + super.drawDivider(child, bottomSibling, holder, siblingHolder, parent, c, paint); + } + + private Status findPreviousStatus(String id){ + for(int i=0;i0 ? data.get(i-1) : null; + } + return null; + } + + private Status findNextStatus(String id){ + for(int i=0;i holder) || holder.getItemID().equals(mainStatus.id)) + continue; + String itemID=holder.getItemID(); + if(!Objects.equals(currentID, itemID)){ + currentID=itemID; + Status current=getStatusByID(currentID); + Status previous=findPreviousStatus(currentID); + Status next=findNextStatus(currentID); + + connectUp=previous!=null && previous.id.equals(current.inReplyToId); + connectToRoot=mainStatus.id.equals(current.inReplyToId); + connectReply=next!=null && itemID.equals(next.inReplyToId); + } + + if(!connectUp && !connectToRoot && !connectReply) + continue; + + float lineX=V.dp(36); + c.save(); + c.clipRect(child.getX(), child.getY(), child.getX()+child.getWidth(), child.getY()+child.getHeight()); + if(holder instanceof HeaderStatusDisplayItem.Holder){ + if(connectUp || connectToRoot){ + c.drawLine(lineX, child.getY()-V.dp(2), lineX, child.getY()+V.dp(14), paint); + } + if(connectReply){ + c.drawLine(lineX, child.getY()+V.dp(62), lineX, child.getY()+child.getHeight()+V.dp(2), paint); + } + }else if(connectReply){ + c.drawLine(lineX, child.getY(), lineX, child.getY()+child.getHeight(), paint); + } + c.restore(); + } + } + } } 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 1dc9dcb1..835efa9a 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 @@ -43,6 +43,7 @@ public abstract class StatusDisplayItem{ public static final int FLAG_CHECKABLE=1 << 2; public static final int FLAG_MEDIA_FORCE_HIDDEN=1 << 3; public static final int FLAG_NO_HEADER=1 << 4; + public static final int FLAG_NO_IN_REPLY_TO=1 << 5; public StatusDisplayItem(String parentID, BaseStatusListFragment parentFragment){ this.parentID=parentID; @@ -98,7 +99,7 @@ public abstract class StatusDisplayItem{ if((flags & FLAG_NO_HEADER)==0){ if(status.reblog!=null){ items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_repeat_wght700_20px)); - }else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)){ + }else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId) && (flags & FLAG_NO_IN_REPLY_TO)==0){ Account account=Objects.requireNonNull(knownAccounts.get(status.inReplyToAccountId)); items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_reply_wght700_20px)); }