fix long toots not collapsing correctly in timelines (#976)

This commit is contained in:
Konrad Pozniak 2019-01-11 20:05:15 +01:00 committed by GitHub
parent 20f257c35b
commit 15ca16e06f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 31 deletions

View File

@ -45,8 +45,6 @@ import at.connyduck.sparkbutton.SparkButton;
import at.connyduck.sparkbutton.SparkEventListener; import at.connyduck.sparkbutton.SparkEventListener;
abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private static final InputFilter[] COLLAPSE_INPUT_FILTER = new InputFilter[]{SmartLengthInputFilter.INSTANCE};
private static final InputFilter[] NO_INPUT_FILTER = new InputFilter[0];
private TextView displayName; private TextView displayName;
private TextView username; private TextView username;
@ -62,7 +60,6 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private View sensitiveMediaShow; private View sensitiveMediaShow;
private TextView mediaLabel; private TextView mediaLabel;
private ToggleButton contentWarningButton; private ToggleButton contentWarningButton;
private ToggleButton contentCollapseButton;
ImageView avatar; ImageView avatar;
TextView timestampInfo; TextView timestampInfo;
@ -103,7 +100,6 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
mediaLabel = itemView.findViewById(R.id.status_media_label); mediaLabel = itemView.findViewById(R.id.status_media_label);
contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description); contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description);
contentWarningButton = itemView.findViewById(R.id.status_content_warning_button); contentWarningButton = itemView.findViewById(R.id.status_content_warning_button);
contentCollapseButton = itemView.findViewById(R.id.button_toggle_content);
this.useAbsoluteTime = useAbsoluteTime; this.useAbsoluteTime = useAbsoluteTime;
shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); shortSdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
@ -541,28 +537,5 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
setSpoilerAndContent(status, listener); setSpoilerAndContent(status, listener);
// When viewing threads this ViewHolder is used and the main post does not have a collapse
// button by design so avoid crashing the app when that happens
if (contentCollapseButton != null) {
if (status.isCollapsible() && (status.isExpanded() || status.getSpoilerText() == null || status.getSpoilerText().isEmpty())) {
contentCollapseButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION)
listener.onContentCollapsedChange(isChecked, position);
});
contentCollapseButton.setVisibility(View.VISIBLE);
if (status.isCollapsed()) {
contentCollapseButton.setChecked(true);
content.setFilters(COLLAPSE_INPUT_FILTER);
} else {
contentCollapseButton.setChecked(false);
content.setFilters(NO_INPUT_FILTER);
}
} else {
contentCollapseButton.setVisibility(View.GONE);
content.setFilters(NO_INPUT_FILTER);
}
}
} }
} }

View File

@ -17,25 +17,35 @@ package com.keylesspalace.tusky.adapter;
import android.content.Context; import android.content.Context;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.text.InputFilter;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.ToggleButton;
import com.keylesspalace.tusky.R; import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.util.SmartLengthInputFilter;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import androidx.recyclerview.widget.RecyclerView;
import at.connyduck.sparkbutton.helpers.Utils; import at.connyduck.sparkbutton.helpers.Utils;
public class StatusViewHolder extends StatusBaseViewHolder { public class StatusViewHolder extends StatusBaseViewHolder {
private static final InputFilter[] COLLAPSE_INPUT_FILTER = new InputFilter[]{SmartLengthInputFilter.INSTANCE};
private static final InputFilter[] NO_INPUT_FILTER = new InputFilter[0];
private ImageView avatarReblog; private ImageView avatarReblog;
private TextView rebloggedBar; private TextView rebloggedBar;
private ToggleButton contentCollapseButton;
StatusViewHolder(View itemView, boolean useAbsoluteTime) { StatusViewHolder(View itemView, boolean useAbsoluteTime) {
super(itemView, useAbsoluteTime); super(itemView, useAbsoluteTime);
avatarReblog = itemView.findViewById(R.id.status_avatar_reblog); avatarReblog = itemView.findViewById(R.id.status_avatar_reblog);
rebloggedBar = itemView.findViewById(R.id.status_reblogged); rebloggedBar = itemView.findViewById(R.id.status_reblogged);
contentCollapseButton = itemView.findViewById(R.id.button_toggle_content);
} }
@Override @Override
@ -71,6 +81,7 @@ public class StatusViewHolder extends StatusBaseViewHolder {
showContent(false); showContent(false);
} else { } else {
showContent(true); showContent(true);
setupCollapsedState(status, listener);
super.setupWithStatus(status, listener, mediaPreviewEnabled); super.setupWithStatus(status, listener, mediaPreviewEnabled);
String rebloggedByDisplayName = status.getRebloggedByUsername(); String rebloggedByDisplayName = status.getRebloggedByUsername();
@ -80,14 +91,13 @@ public class StatusViewHolder extends StatusBaseViewHolder {
setRebloggedByDisplayName(rebloggedByDisplayName); setRebloggedByDisplayName(rebloggedByDisplayName);
} }
// I think it's not efficient to create new object every time we bind a holder.
// More efficient approach would be creating View.OnClickListener during holder creation
// and storing StatusActionListener in a variable after binding.
rebloggedBar.setOnClickListener(v -> listener.onOpenReblog(getAdapterPosition())); rebloggedBar.setOnClickListener(v -> listener.onOpenReblog(getAdapterPosition()));
} }
} }
private void setRebloggedByDisplayName(String name) { private void setRebloggedByDisplayName(final String name) {
Context context = rebloggedBar.getContext(); Context context = rebloggedBar.getContext();
String boostedText = context.getString(R.string.status_boosted_format, name); String boostedText = context.getString(R.string.status_boosted_format, name);
rebloggedBar.setText(boostedText); rebloggedBar.setText(boostedText);
@ -100,4 +110,27 @@ public class StatusViewHolder extends StatusBaseViewHolder {
} }
rebloggedBar.setVisibility(View.GONE); rebloggedBar.setVisibility(View.GONE);
} }
private void setupCollapsedState(final StatusViewData.Concrete status, final StatusActionListener listener) {
/* input filter for TextViews have to be set before text */
if (status.isCollapsible() && (status.isExpanded() || status.getSpoilerText() == null || status.getSpoilerText().isEmpty())) {
contentCollapseButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION)
listener.onContentCollapsedChange(isChecked, position);
});
contentCollapseButton.setVisibility(View.VISIBLE);
if (status.isCollapsed()) {
contentCollapseButton.setChecked(true);
content.setFilters(COLLAPSE_INPUT_FILTER);
} else {
contentCollapseButton.setChecked(false);
content.setFilters(NO_INPUT_FILTER);
}
} else {
contentCollapseButton.setVisibility(View.GONE);
content.setFilters(NO_INPUT_FILTER);
}
}
} }