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 6ff24b7b7..24f2286d8 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java @@ -337,10 +337,60 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist } protected void onStatusCreated(StatusCreatedEvent ev){ - if(ev.status.inReplyToId!=null && getStatusByID(ev.status.inReplyToId)!=null){ - data.add(ev.status); - onAppendItems(Collections.singletonList(ev.status)); + if (ev.status.inReplyToId == null) return; + Status repliedToStatus = getStatusByID(ev.status.inReplyToId); + if (repliedToStatus == null) return; + NeighborAncestryInfo ancestry = ancestryMap.get(repliedToStatus.id); + + int nextDisplayItemsIndex = -1, indexOfPreviousDisplayItem = -1; + + for (int i = 0; i < displayItems.size(); i++) { + StatusDisplayItem item = displayItems.get(i); + if (repliedToStatus.id.equals(item.parentID)) { + // saving the replied-to status' display items index to eventually reach the last one + indexOfPreviousDisplayItem = i; + item.hasDescendantNeighbor = true; + } else if (indexOfPreviousDisplayItem >= 0 && nextDisplayItemsIndex == -1) { + // previous display item was the replied-to status' display items + nextDisplayItemsIndex = i; + // nothing left to do if there's no other reply to that status + if (ancestry.descendantNeighbor == null) break; + } + if (ancestry.descendantNeighbor != null && item.parentID.equals(ancestry.descendantNeighbor.id)) { + // existing reply shall no longer have the replied-to status as its neighbor + item.hasAncestoringNeighbor = false; + } } + + // fall back to inserting the item at the end + nextDisplayItemsIndex = nextDisplayItemsIndex >= 0 ? nextDisplayItemsIndex : displayItems.size(); + int nextDataIndex = data.indexOf(repliedToStatus) + 1; + + // if replied-to status already has another reply... + if (ancestry.descendantNeighbor != null) { + // update the reply's ancestry to remove its ancestoring neighbor (as we did above) + ancestryMap.get(ancestry.descendantNeighbor.id).ancestoringNeighbor = null; + // make sure the existing reply has a reply line + if (nextDataIndex < data.size() && + !(displayItems.get(nextDisplayItemsIndex) instanceof ReblogOrReplyLineStatusDisplayItem)) { + Status nextStatus = data.get(nextDataIndex); + if (!nextStatus.account.id.equals(repliedToStatus.account.id)) { + // create reply line manually since we're not building that status' items + displayItems.add(nextDisplayItemsIndex, StatusDisplayItem.buildReplyLine( + this, nextStatus, accountID, nextStatus, repliedToStatus.account, false + )); + } + } + } + + // update replied-to status' ancestry + ancestry.descendantNeighbor = ev.status; + + // add ancestry for newly created status before building its display items + ancestryMap.put(ev.status.id, new NeighborAncestryInfo(ev.status, null, repliedToStatus)); + displayItems.addAll(nextDisplayItemsIndex, buildDisplayItems(ev.status)); + data.add(nextDataIndex, ev.status); + adapter.notifyDataSetChanged(); } @Override 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 b1bd67d3a..f0f0fc6a0 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 @@ -105,6 +105,21 @@ public abstract class StatusDisplayItem{ return buildItems(fragment, status, accountID, parentObject, knownAccounts, inset, addFooter, notification, false, filterContext); } + public static ReblogOrReplyLineStatusDisplayItem buildReplyLine(BaseStatusListFragment fragment, Status status, String accountID, DisplayItemsParent parent, Account account, boolean threadReply) { + String parentID = parent.getID(); + String text = threadReply ? fragment.getString(R.string.sk_show_thread) + : account == null ? fragment.getString(R.string.sk_in_reply) + : GlobalUserPreferences.compactReblogReplyLine && status.reblog != null ? account.displayName + : fragment.getString(R.string.in_reply_to, account.displayName); + String fullText = threadReply ? fragment.getString(R.string.sk_show_thread) + : account == null ? fragment.getString(R.string.sk_in_reply) + : fragment.getString(R.string.in_reply_to, account.displayName); + return new ReblogOrReplyLineStatusDisplayItem( + parentID, fragment, text, account == null ? List.of() : account.emojis, + R.drawable.ic_fluent_arrow_reply_20sp_filled, null, null, fullText + ); + } + public static ArrayList buildItems(BaseStatusListFragment fragment, Status status, String accountID, DisplayItemsParent parentObject, Map knownAccounts, boolean inset, boolean addFooter, Notification notification, boolean disableTranslate, Filter.FilterContext filterContext){ String parentID=parentObject.getID(); ArrayList items=new ArrayList<>(); @@ -120,17 +135,7 @@ public abstract class StatusDisplayItem{ if(statusForContent.inReplyToAccountId!=null && !(threadReply && fragment instanceof ThreadFragment)){ Account account = knownAccounts.get(statusForContent.inReplyToAccountId); - String text = threadReply ? fragment.getString(R.string.sk_show_thread) - : account == null ? fragment.getString(R.string.sk_in_reply) - : GlobalUserPreferences.compactReblogReplyLine && status.reblog != null ? account.displayName - : fragment.getString(R.string.in_reply_to, account.displayName); - String fullText = threadReply ? fragment.getString(R.string.sk_show_thread) - : account == null ? fragment.getString(R.string.sk_in_reply) - : fragment.getString(R.string.in_reply_to, account.displayName); - replyLine = new ReblogOrReplyLineStatusDisplayItem( - parentID, fragment, text, account == null ? List.of() : account.emojis, - R.drawable.ic_fluent_arrow_reply_20sp_filled, null, null, fullText - ); + replyLine = buildReplyLine(fragment, status, accountID, parentObject, account, threadReply); } if(status.reblog!=null){