fix paddings around dummys, text and spoilers

closes sk22#638
This commit is contained in:
sk 2023-08-23 22:12:14 +02:00
parent f5e5408d70
commit d96c3c3c8a
7 changed files with 59 additions and 31 deletions

View File

@ -164,7 +164,6 @@ public class GlobalUserPreferences{
.putBoolean("enablePreReleases", enablePreReleases) .putBoolean("enablePreReleases", enablePreReleases)
.putString("prefixReplies", prefixReplies.name()) .putString("prefixReplies", prefixReplies.name())
.putBoolean("collapseLongPosts", collapseLongPosts) .putBoolean("collapseLongPosts", collapseLongPosts)
.putBoolean("spectatorMode", spectatorMode)
.putBoolean("autoHideFab", autoHideFab) .putBoolean("autoHideFab", autoHideFab)
.putBoolean("compactReblogReplyLine", compactReblogReplyLine) .putBoolean("compactReblogReplyLine", compactReblogReplyLine)
.putString("color", color.name()) .putString("color", color.name())

View File

@ -68,6 +68,7 @@ public class AnnouncementsFragment extends BaseStatusListFragment<Announcement>
instanceUser.emojis = List.of(); instanceUser.emojis = List.of();
Status fakeStatus = a.toStatus(); Status fakeStatus = a.toStatus();
TextStatusDisplayItem textItem = new TextStatusDisplayItem(a.id, HtmlParser.parse(a.content, a.emojis, a.mentions, a.tags, accountID), this, fakeStatus, true); TextStatusDisplayItem textItem = new TextStatusDisplayItem(a.id, HtmlParser.parse(a.content, a.emojis, a.mentions, a.tags, accountID), this, fakeStatus, true);
// TODO: emoji reactions!
textItem.textSelectable = true; textItem.textSelectable = true;
return List.of( return List.of(
HeaderStatusDisplayItem.fromAnnouncement(a, fakeStatus, instanceUser, this, accountID, this::onMarkAsRead), HeaderStatusDisplayItem.fromAnnouncement(a, fakeStatus, instanceUser, this, accountID, this::onMarkAsRead),

View File

@ -4,16 +4,17 @@ import android.content.Context;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Space; import android.widget.Space;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Status;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
public class DummyStatusDisplayItem extends StatusDisplayItem { public class DummyStatusDisplayItem extends StatusDisplayItem {
private final boolean addMediaGridMargin;
public DummyStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, boolean addMediaGridMargin) { public DummyStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment) {
super(parentID, parentFragment); super(parentID, parentFragment);
this.addMediaGridMargin = addMediaGridMargin;
} }
@Override @Override
@ -22,19 +23,21 @@ public class DummyStatusDisplayItem extends StatusDisplayItem {
} }
public static class Holder extends StatusDisplayItem.Holder<DummyStatusDisplayItem> { public static class Holder extends StatusDisplayItem.Holder<DummyStatusDisplayItem> {
private final RecyclerView.LayoutParams params;
public Holder(Context context) { public Holder(Context context) {
super(new Space(context)); super(new Space(context));
} params=new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
@Override
public void onBind(DummyStatusDisplayItem item) {
// BetterItemAnimator appears not to handle InsetStatusItemDecoration's getItemOffsets // BetterItemAnimator appears not to handle InsetStatusItemDecoration's getItemOffsets
// correctly, causing removed inset views to jump while animating. i don't quite // correctly, causing removed inset views to jump while animating. i don't quite
// understand it, but this workaround appears to work. // understand it, but this workaround appears to work.
// see InsetStatusItemDecoration#getItemOffsets // see InsetStatusItemDecoration#getItemOffsets
ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0); params.setMargins(0, 0, 0, V.dp(16));
params.setMargins(0, item.addMediaGridMargin ? V.dp(0) : 0, 0, V.dp(16));
itemView.setLayoutParams(params); itemView.setLayoutParams(params);
} }
@Override
public void onBind(DummyStatusDisplayItem item) {}
} }
} }

View File

@ -56,6 +56,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
private final Drawable placeholder; private final Drawable placeholder;
private final boolean hideAdd; private final boolean hideAdd;
private final String accountID; private final String accountID;
private boolean hidden;
public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, String accountID, boolean hideAdd) { public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, String accountID, boolean hideAdd) {
super(parentID, parentFragment); super(parentID, parentFragment);
@ -64,6 +65,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
this.accountID=accountID; this.accountID=accountID;
placeholder=parentFragment.getContext().getDrawable(R.drawable.image_placeholder).mutate(); placeholder=parentFragment.getContext().getDrawable(R.drawable.image_placeholder).mutate();
placeholder.setBounds(0, 0, V.sp(24), V.sp(24)); placeholder.setBounds(0, 0, V.sp(24), V.sp(24));
updateHidden();
} }
@Override @Override
@ -81,7 +83,15 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
return Type.EMOJI_REACTIONS; return Type.EMOJI_REACTIONS;
} }
public static class Holder extends StatusDisplayItem.Holder<EmojiReactionsStatusDisplayItem> implements ImageLoaderViewHolder, CustomEmojiPopupKeyboard.Listener { public boolean isHidden(){
return hidden;
}
private void updateHidden(){
hidden=status.reactions.isEmpty() && hideAdd;
}
public static class Holder extends StatusDisplayItem.Holder<EmojiReactionsStatusDisplayItem> implements ImageLoaderViewHolder, CustomEmojiPopupKeyboard.Listener {
private final UsableRecyclerView list; private final UsableRecyclerView list;
private final LinearLayout root, line; private final LinearLayout root, line;
private CustomEmojiPopupKeyboard emojiKeyboard; private CustomEmojiPopupKeyboard emojiKeyboard;
@ -116,10 +126,10 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
emojiKeyboard.setListener(this); emojiKeyboard.setListener(this);
space.setVisibility(View.GONE); space.setVisibility(View.GONE);
root.addView(emojiKeyboard.getView()); root.addView(emojiKeyboard.getView());
boolean nothingToShow=item.status.reactions.isEmpty() && item.hideAdd; item.updateHidden();
root.setVisibility(nothingToShow ? View.GONE : View.VISIBLE); root.setVisibility(item.hidden ? View.GONE : View.VISIBLE);
line.setVisibility(nothingToShow ? View.GONE : View.VISIBLE); line.setVisibility(item.hidden ? View.GONE : View.VISIBLE);
line.setPadding(list.getPaddingLeft(), nothingToShow ? 0 : V.dp(8), list.getPaddingRight(), 0); line.setPadding(list.getPaddingLeft(), item.hidden ? 0 : V.dp(8), list.getPaddingRight(), 0);
imgLoader.updateImages(); imgLoader.updateImages();
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
} }

View File

@ -92,7 +92,7 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
itemView.getPaddingLeft(), itemView.getPaddingLeft(),
itemView.getPaddingTop(), itemView.getPaddingTop(),
itemView.getPaddingRight(), itemView.getPaddingRight(),
item.inset || GlobalUserPreferences.spectatorMode ? itemView.getPaddingTop() : 0 item.inset ? itemView.getPaddingTop() : 0
); );
} }

View File

@ -18,6 +18,7 @@ import org.joinmastodon.android.fragments.HashtagTimelineFragment;
import org.joinmastodon.android.fragments.HomeTabFragment; import org.joinmastodon.android.fragments.HomeTabFragment;
import org.joinmastodon.android.fragments.ListTimelineFragment; import org.joinmastodon.android.fragments.ListTimelineFragment;
import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ScheduledStatusListFragment;
import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Attachment;
@ -49,7 +50,7 @@ import me.grishka.appkit.views.UsableRecyclerView;
public abstract class StatusDisplayItem{ public abstract class StatusDisplayItem{
public final String parentID; public final String parentID;
public final BaseStatusListFragment parentFragment; public final BaseStatusListFragment<?> parentFragment;
public boolean inset; public boolean inset;
public int index; public int index;
public boolean public boolean
@ -78,7 +79,7 @@ public abstract class StatusDisplayItem{
this.isDirectDescendant = isDirectDescendant; this.isDirectDescendant = isDirectDescendant;
} }
public StatusDisplayItem(String parentID, BaseStatusListFragment parentFragment){ public StatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment){
this.parentID=parentID; this.parentID=parentID;
this.parentFragment=parentFragment; this.parentFragment=parentFragment;
} }
@ -254,7 +255,7 @@ public abstract class StatusDisplayItem{
}else if(!hasSpoiler && header!=null){ }else if(!hasSpoiler && header!=null){
header.needBottomPadding=true; header.needBottomPadding=true;
}else if(hasSpoiler){ }else if(hasSpoiler){
contentItems.add(new DummyStatusDisplayItem(parentID, fragment, true)); contentItems.add(new DummyStatusDisplayItem(parentID, fragment));
} }
List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList()); List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList());
@ -290,12 +291,14 @@ public abstract class StatusDisplayItem{
if(contentItems!=items && statusForContent.spoilerRevealed){ if(contentItems!=items && statusForContent.spoilerRevealed){
items.addAll(contentItems); items.addAll(contentItems);
} }
if((flags & FLAG_NO_EMOJI_REACTIONS)==0 && AccountSessionManager.get(accountID).getLocalPreferences().emojiReactionsEnabled){ if((flags & FLAG_NO_EMOJI_REACTIONS)==0
&& AccountSessionManager.get(accountID).getLocalPreferences().emojiReactionsEnabled){
boolean isMainStatus=fragment instanceof ThreadFragment t && t.getMainStatus().id.equals(statusForContent.id); boolean isMainStatus=fragment instanceof ThreadFragment t && t.getMainStatus().id.equals(statusForContent.id);
items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent, accountID, !isMainStatus)); items.add(new EmojiReactionsStatusDisplayItem(parentID, fragment, statusForContent, accountID, !isMainStatus));
} }
FooterStatusDisplayItem footer=null;
if((flags & FLAG_NO_FOOTER)==0){ if((flags & FLAG_NO_FOOTER)==0){
FooterStatusDisplayItem footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID); footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
footer.hideCounts=hideCounts; footer.hideCounts=hideCounts;
items.add(footer); items.add(footer);
if(status.hasGapAfter && !(fragment instanceof ThreadFragment)) if(status.hasGapAfter && !(fragment instanceof ThreadFragment))
@ -304,10 +307,12 @@ public abstract class StatusDisplayItem{
int i=1; int i=1;
boolean inset=(flags & FLAG_INSET)!=0; boolean inset=(flags & FLAG_INSET)!=0;
// add inset dummy so last content item doesn't clip out of inset bounds // add inset dummy so last content item doesn't clip out of inset bounds
if (inset) { if(inset || footer==null){
items.add(new DummyStatusDisplayItem(parentID, fragment, items.add(new DummyStatusDisplayItem(parentID, fragment));
!contentItems.isEmpty() && contentItems // in case we ever need the dummy to display a margin for the media grid again:
.get(contentItems.size() - 1) instanceof MediaGridStatusDisplayItem)); // (i forgot why we apparently don't need this anymore)
// !contentItems.isEmpty() && contentItems
// .get(contentItems.size() - 1) instanceof MediaGridStatusDisplayItem));
} }
for(StatusDisplayItem item:items){ for(StatusDisplayItem item:items){
item.inset=inset; item.inset=inset;

View File

@ -32,6 +32,8 @@ import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.LinkedTextView; import org.joinmastodon.android.ui.views.LinkedTextView;
import org.joinmastodon.android.utils.StatusTextEncoder; import org.joinmastodon.android.utils.StatusTextEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -195,13 +197,21 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
readMore.setText(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand); readMore.setText(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
// remove additional padding when (transparently padded) translate button is visible // remove additional padding when (transparently padded) translate button is visible
int nextPos = getAbsoluteAdapterPosition() + 1; int nextPos=getAbsoluteAdapterPosition() + 1;
int bottomPadding=V.dp(12); int bottomPadding=V.dp(12);
if(item.parentFragment.getDisplayItems().size() > nextPos){ List<StatusDisplayItem> displayItems=item.parentFragment.getDisplayItems();
if(item.parentFragment.getDisplayItems().get(nextPos) instanceof FooterStatusDisplayItem) bottomPadding=V.dp(6); if(displayItems.size() > nextPos){
if(item.parentFragment.getDisplayItems().get(nextPos) instanceof EmojiReactionsStatusDisplayItem){ StatusDisplayItem next=displayItems.get(nextPos);
boolean reactionsHidden=item.status.reactions.isEmpty() && !(item.parentFragment instanceof ThreadFragment); if(next instanceof EmojiReactionsStatusDisplayItem e && e.isHidden()){
bottomPadding=reactionsHidden ? V.dp(6) : 0; next=displayItems.size() > ++nextPos ? displayItems.get(nextPos) : null;
}
if(next instanceof FooterStatusDisplayItem){
bottomPadding=V.dp(6);
// why does java code always end up looking like this
} else if((!item.inset && next instanceof DummyStatusDisplayItem) ||
next instanceof EmojiReactionsStatusDisplayItem e && !e.isHidden()){
bottomPadding=0;
} }
} }
itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), bottomPadding); itemView.setPadding(itemView.getPaddingLeft(), itemView.getPaddingTop(), itemView.getPaddingRight(), bottomPadding);
@ -239,7 +249,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
// compensate for spoiler's bottom margin // compensate for spoiler's bottom margin
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) itemView.getLayoutParams(); ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) itemView.getLayoutParams();
params.setMargins(params.leftMargin, (item.inset || GlobalUserPreferences.spectatorMode) && hasSpoiler ? V.dp(-16) : 0, params.setMargins(params.leftMargin, item.inset && hasSpoiler ? V.dp(-16) : 0,
params.rightMargin, params.bottomMargin); params.rightMargin, params.bottomMargin);
} }