gracefully handle null statuses in notifications

This commit is contained in:
Conny Duck 2018-03-01 21:10:10 +01:00
parent 550235d40b
commit ed60cc3a78
4 changed files with 60 additions and 21 deletions

View file

@ -132,16 +132,25 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
case REBLOG: { case REBLOG: {
StatusNotificationViewHolder holder = (StatusNotificationViewHolder) viewHolder; StatusNotificationViewHolder holder = (StatusNotificationViewHolder) viewHolder;
StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData(); StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData();
holder.setDisplayName(statusViewData.getUserFullName());
holder.setUsername(statusViewData.getNickname()); if(statusViewData == null) {
holder.setCreatedAt(statusViewData.getCreatedAt()); holder.showNotificationContent(false);
} else {
holder.showNotificationContent(true);
holder.setDisplayName(statusViewData.getUserFullName());
holder.setUsername(statusViewData.getNickname());
holder.setCreatedAt(statusViewData.getCreatedAt());
holder.setAvatars(concreteNotificaton.getStatusViewData().getAvatar(),
concreteNotificaton.getAccount().avatar);
}
holder.setMessage(concreteNotificaton, statusListener); holder.setMessage(concreteNotificaton, statusListener);
holder.setupButtons(notificationActionListener, holder.setupButtons(notificationActionListener,
concreteNotificaton.getAccount().id, concreteNotificaton.getAccount().id,
concreteNotificaton.getId()); concreteNotificaton.getId());
holder.setAvatars(concreteNotificaton.getStatusViewData().getAvatar(),
concreteNotificaton.getAccount().avatar);
break; break;
} }
case FOLLOW: { case FOLLOW: {
@ -284,6 +293,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
private static class StatusNotificationViewHolder extends RecyclerView.ViewHolder private static class StatusNotificationViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, ToggleButton.OnCheckedChangeListener { implements View.OnClickListener, ToggleButton.OnCheckedChangeListener {
private final TextView message; private final TextView message;
private final View statusNameBar;
private final TextView displayName; private final TextView displayName;
private final TextView username; private final TextView username;
private final TextView timestampInfo; private final TextView timestampInfo;
@ -303,6 +313,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
StatusNotificationViewHolder(View itemView) { StatusNotificationViewHolder(View itemView) {
super(itemView); super(itemView);
message = itemView.findViewById(R.id.notification_top_text); message = itemView.findViewById(R.id.notification_top_text);
statusNameBar = itemView.findViewById(R.id.status_name_bar);
displayName = itemView.findViewById(R.id.status_display_name); displayName = itemView.findViewById(R.id.status_display_name);
username = itemView.findViewById(R.id.status_username); username = itemView.findViewById(R.id.status_username);
timestampInfo = itemView.findViewById(R.id.status_timestamp_info); timestampInfo = itemView.findViewById(R.id.status_timestamp_info);
@ -324,6 +335,15 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
contentWarningButton.setOnCheckedChangeListener(this); contentWarningButton.setOnCheckedChangeListener(this);
} }
private void showNotificationContent(boolean show) {
statusNameBar.setVisibility(show ? View.VISIBLE : View.GONE);
contentWarningBar.setVisibility(show ? View.VISIBLE : View.GONE);
statusContent.setVisibility(show ? View.VISIBLE : View.GONE);
statusAvatar.setVisibility(show ? View.VISIBLE : View.GONE);
notificationAvatar.setVisibility(show ? View.VISIBLE : View.GONE);
}
private void setDisplayName(String name) { private void setDisplayName(String name) {
displayName.setText(name); displayName.setText(name);
} }
@ -396,9 +416,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
message.setText(str); message.setText(str);
boolean hasSpoiler = !TextUtils.isEmpty(statusViewData.getSpoilerText()); if (statusViewData != null) {
contentWarningBar.setVisibility(hasSpoiler ? View.VISIBLE : View.GONE); boolean hasSpoiler = !TextUtils.isEmpty(statusViewData.getSpoilerText());
setupContentAndSpoiler(notificationViewData, listener); contentWarningBar.setVisibility(hasSpoiler ? View.VISIBLE : View.GONE);
setupContentAndSpoiler(notificationViewData, listener);
}
} }
void setupButtons(final NotificationActionListener listener, final String accountId, void setupButtons(final NotificationActionListener listener, final String accountId,

View file

@ -10,6 +10,7 @@ import android.support.v7.widget.RecyclerView;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
@ -27,6 +28,7 @@ import com.keylesspalace.tusky.util.LinkHelper;
import com.keylesspalace.tusky.util.ThemeUtils; import com.keylesspalace.tusky.util.ThemeUtils;
import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.view.RoundedTransformation;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.mikepenz.iconics.utils.Utils;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.varunest.sparkbutton.SparkButton; import com.varunest.sparkbutton.SparkButton;
import com.varunest.sparkbutton.SparkEventListener; import com.varunest.sparkbutton.SparkEventListener;
@ -147,6 +149,15 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
timestampInfo.setContentDescription(readoutAloud); timestampInfo.setContentDescription(readoutAloud);
} }
protected void showContent(boolean show) {
if(show) {
container.setVisibility(View.VISIBLE);
container.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
container.setVisibility(View.INVISIBLE);
container.getLayoutParams().height = Utils.convertDpToPx(container.getContext(), 24);
}
}
private void setIsReply(boolean isReply) { private void setIsReply(boolean isReply) {
if(isReply) { if(isReply) {

View file

@ -78,19 +78,24 @@ public class StatusViewHolder extends StatusBaseViewHolder {
@Override @Override
void setupWithStatus(StatusViewData.Concrete status, final StatusActionListener listener, void setupWithStatus(StatusViewData.Concrete status, final StatusActionListener listener,
boolean mediaPreviewEnabled) { boolean mediaPreviewEnabled) {
super.setupWithStatus(status, listener, mediaPreviewEnabled); if(status == null) {
showContent(false);
String rebloggedByDisplayName = status.getRebloggedByUsername();
if (rebloggedByDisplayName == null) {
hideRebloggedByDisplayName();
} else { } else {
setRebloggedByDisplayName(rebloggedByDisplayName); showContent(true);
} super.setupWithStatus(status, listener, mediaPreviewEnabled);
// I think it's not efficient to create new object every time we bind a holder. String rebloggedByDisplayName = status.getRebloggedByUsername();
// More efficient approach would be creating View.OnClickListener during holder creation if (rebloggedByDisplayName == null) {
// and storing StatusActionListener in a variable after binding. hideRebloggedByDisplayName();
rebloggedBar.setOnClickListener(v -> listener.onOpenReblog(getAdapterPosition())); } else {
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()));
}
} }
private void setRebloggedByDisplayName(String name) { private void setRebloggedByDisplayName(String name) {

View file

@ -14,6 +14,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginBottom="6dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:drawablePadding="10dp" android:drawablePadding="10dp"
android:ellipsize="end" android:ellipsize="end"
@ -30,8 +31,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/notification_top_text" android:layout_below="@+id/notification_top_text"
android:layout_toEndOf="@+id/notification_status_avatar" android:layout_toEndOf="@+id/notification_status_avatar"
android:paddingBottom="4dp" android:paddingBottom="4dp">
android:paddingTop="6dp">
<TextView <TextView
android:id="@+id/status_display_name" android:id="@+id/status_display_name"