guard against the status of a notification being null in rare cases (#2449)
* guard against the status of a notification being null in rare cases * improve code, fix bug when payloads is not null * remove findViewById * add comments in NotificationsAdapter
This commit is contained in:
parent
43709532d6
commit
db7eac0a8d
4 changed files with 55 additions and 13 deletions
|
@ -180,8 +180,16 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||||
case VIEW_TYPE_STATUS: {
|
case VIEW_TYPE_STATUS: {
|
||||||
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
StatusViewHolder holder = (StatusViewHolder) viewHolder;
|
||||||
StatusViewData.Concrete status = concreteNotificaton.getStatusViewData();
|
StatusViewData.Concrete status = concreteNotificaton.getStatusViewData();
|
||||||
holder.setupWithStatus(status,
|
if (status == null) {
|
||||||
statusListener, statusDisplayOptions, payloadForHolder);
|
/* in some very rare cases servers sends null status even though they should not,
|
||||||
|
* we have to handle it somehow */
|
||||||
|
holder.showStatusContent(false);
|
||||||
|
} else {
|
||||||
|
if (payloads == null) {
|
||||||
|
holder.showStatusContent(true);
|
||||||
|
}
|
||||||
|
holder.setupWithStatus(status, statusListener, statusDisplayOptions, payloadForHolder);
|
||||||
|
}
|
||||||
if (concreteNotificaton.getType() == Notification.Type.POLL) {
|
if (concreteNotificaton.getType() == Notification.Type.POLL) {
|
||||||
holder.setPollInfo(accountId.equals(concreteNotificaton.getAccount().getId()));
|
holder.setPollInfo(accountId.equals(concreteNotificaton.getAccount().getId()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -194,6 +202,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
|
||||||
StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData();
|
StatusViewData.Concrete statusViewData = concreteNotificaton.getStatusViewData();
|
||||||
if (payloadForHolder == null) {
|
if (payloadForHolder == null) {
|
||||||
if (statusViewData == null) {
|
if (statusViewData == null) {
|
||||||
|
/* in some very rare cases servers sends null status even though they should not,
|
||||||
|
* we have to handle it somehow */
|
||||||
holder.showNotificationContent(false);
|
holder.showNotificationContent(false);
|
||||||
} else {
|
} else {
|
||||||
holder.showNotificationContent(true);
|
holder.showNotificationContent(true);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.core.text.HtmlCompat;
|
import androidx.core.text.HtmlCompat;
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
@ -76,6 +77,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||||
private SparkButton favouriteButton;
|
private SparkButton favouriteButton;
|
||||||
private SparkButton bookmarkButton;
|
private SparkButton bookmarkButton;
|
||||||
private ImageButton moreButton;
|
private ImageButton moreButton;
|
||||||
|
private ConstraintLayout mediaContainer;
|
||||||
protected MediaPreviewImageView[] mediaPreviews;
|
protected MediaPreviewImageView[] mediaPreviews;
|
||||||
private ImageView[] mediaOverlays;
|
private ImageView[] mediaOverlays;
|
||||||
private TextView sensitiveMediaWarning;
|
private TextView sensitiveMediaWarning;
|
||||||
|
@ -124,7 +126,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||||
bookmarkButton = itemView.findViewById(R.id.status_bookmark);
|
bookmarkButton = itemView.findViewById(R.id.status_bookmark);
|
||||||
moreButton = itemView.findViewById(R.id.status_more);
|
moreButton = itemView.findViewById(R.id.status_more);
|
||||||
|
|
||||||
itemView.findViewById(R.id.status_media_preview_container).setClipToOutline(true);
|
mediaContainer = itemView.findViewById(R.id.status_media_preview_container);
|
||||||
|
mediaContainer.setClipToOutline(true);
|
||||||
|
|
||||||
mediaPreviews = new MediaPreviewImageView[]{
|
mediaPreviews = new MediaPreviewImageView[]{
|
||||||
itemView.findViewById(R.id.status_media_preview_0),
|
itemView.findViewById(R.id.status_media_preview_0),
|
||||||
|
@ -719,9 +722,9 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||||
this.setupWithStatus(status, listener, statusDisplayOptions, null);
|
this.setupWithStatus(status, listener, statusDisplayOptions, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupWithStatus(StatusViewData.Concrete status,
|
public void setupWithStatus(@NonNull StatusViewData.Concrete status,
|
||||||
final StatusActionListener listener,
|
@NonNull final StatusActionListener listener,
|
||||||
StatusDisplayOptions statusDisplayOptions,
|
@NonNull StatusDisplayOptions statusDisplayOptions,
|
||||||
@Nullable Object payloads) {
|
@Nullable Object payloads) {
|
||||||
if (payloads == null) {
|
if (payloads == null) {
|
||||||
Status actionable = status.getActionable();
|
Status actionable = status.getActionable();
|
||||||
|
@ -1133,6 +1136,28 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showStatusContent(boolean show) {
|
||||||
|
int visibility = show ? View.VISIBLE : View.GONE;
|
||||||
|
avatar.setVisibility(visibility);
|
||||||
|
avatarInset.setVisibility(visibility);
|
||||||
|
displayName.setVisibility(visibility);
|
||||||
|
username.setVisibility(visibility);
|
||||||
|
timestampInfo.setVisibility(visibility);
|
||||||
|
contentWarningDescription.setVisibility(visibility);
|
||||||
|
contentWarningButton.setVisibility(visibility);
|
||||||
|
content.setVisibility(visibility);
|
||||||
|
cardView.setVisibility(visibility);
|
||||||
|
mediaContainer.setVisibility(visibility);
|
||||||
|
pollOptions.setVisibility(visibility);
|
||||||
|
pollButton.setVisibility(visibility);
|
||||||
|
pollDescription.setVisibility(visibility);
|
||||||
|
replyButton.setVisibility(visibility);
|
||||||
|
reblogButton.setVisibility(visibility);
|
||||||
|
favouriteButton.setVisibility(visibility);
|
||||||
|
bookmarkButton.setVisibility(visibility);
|
||||||
|
moreButton.setVisibility(visibility);
|
||||||
|
}
|
||||||
|
|
||||||
private static String formatDuration(double durationInSeconds) {
|
private static String formatDuration(double durationInSeconds) {
|
||||||
int seconds = (int) Math.round(durationInSeconds) % 60;
|
int seconds = (int) Math.round(durationInSeconds) % 60;
|
||||||
int minutes = (int) durationInSeconds % 3600 / 60;
|
int minutes = (int) durationInSeconds % 3600 / 60;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -101,10 +102,10 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupWithStatus(final StatusViewData.Concrete status,
|
public void setupWithStatus(@NonNull final StatusViewData.Concrete status,
|
||||||
final StatusActionListener listener,
|
@NonNull final StatusActionListener listener,
|
||||||
StatusDisplayOptions statusDisplayOptions,
|
@NonNull StatusDisplayOptions statusDisplayOptions,
|
||||||
@Nullable Object payloads) {
|
@Nullable Object payloads) {
|
||||||
super.setupWithStatus(status, listener, statusDisplayOptions, payloads);
|
super.setupWithStatus(status, listener, statusDisplayOptions, payloads);
|
||||||
setupCard(status, CardViewMode.FULL_WIDTH, statusDisplayOptions, listener); // Always show card for detailed status
|
setupCard(status, CardViewMode.FULL_WIDTH, statusDisplayOptions, listener); // Always show card for detailed status
|
||||||
if (payloads == null) {
|
if (payloads == null) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
@ -58,9 +59,9 @@ public class StatusViewHolder extends StatusBaseViewHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupWithStatus(StatusViewData.Concrete status,
|
public void setupWithStatus(@NonNull StatusViewData.Concrete status,
|
||||||
final StatusActionListener listener,
|
@NonNull final StatusActionListener listener,
|
||||||
StatusDisplayOptions statusDisplayOptions,
|
@NonNull StatusDisplayOptions statusDisplayOptions,
|
||||||
@Nullable Object payloads) {
|
@Nullable Object payloads) {
|
||||||
if (payloads == null) {
|
if (payloads == null) {
|
||||||
|
|
||||||
|
@ -129,4 +130,9 @@ public class StatusViewHolder extends StatusBaseViewHolder {
|
||||||
content.setFilters(NO_INPUT_FILTER);
|
content.setFilters(NO_INPUT_FILTER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showStatusContent(boolean show) {
|
||||||
|
super.showStatusContent(show);
|
||||||
|
contentCollapseButton.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue