fix long toots not collapsing correctly in timelines (#976)
This commit is contained in:
parent
62b0efc1f5
commit
7969f9cc4d
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue