feat(ErrorDisplayItem): improve UI/UX with new design

Updates the design of the ErrorStatusDisplayItem to be more
user-friendly. The new design displays an error message indicating that
an error has occurred while attempting to display the item. It then
offers the choice of either view the item in the browser or copy the
error details.
This commit is contained in:
FineFindus 2024-06-13 20:42:16 +02:00
parent b38c78c50a
commit 14e6187efc
No known key found for this signature in database
GPG Key ID: 64873EE210FF8E6B
4 changed files with 110 additions and 18 deletions

View File

@ -1,23 +1,26 @@
package org.joinmastodon.android.ui.displayitems; package org.joinmastodon.android.ui.displayitems;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.os.Build;
import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
public class ErrorStatusDisplayItem extends StatusDisplayItem{ public class ErrorStatusDisplayItem extends StatusDisplayItem{
private final Exception exception; private final Exception exception;
public ErrorStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Exception exception) { public ErrorStatusDisplayItem(String parentID, Status status, BaseStatusListFragment<?> parentFragment, Exception exception) {
super(parentID, parentFragment); super(parentID, parentFragment);
this.exception=exception; this.exception=exception;
this.status=status;
} }
@Override @Override
@ -26,24 +29,30 @@ public class ErrorStatusDisplayItem extends StatusDisplayItem{
} }
public static class Holder extends StatusDisplayItem.Holder<ErrorStatusDisplayItem> { public static class Holder extends StatusDisplayItem.Holder<ErrorStatusDisplayItem> {
private final TextView title, domain;
public Holder(Context context, ViewGroup parent) { public Holder(Context context, ViewGroup parent) {
super(context, R.layout.display_item_file, parent); super(context, R.layout.display_item_error, parent);
title=findViewById(R.id.title); findViewById(R.id.button_open_browser).setOnClickListener(v -> UiUtils.launchWebBrowser(v.getContext(), item.status.url));
domain=findViewById(R.id.domain); findViewById(R.id.button_copy_error_details).setOnClickListener(this::copyErrorDetails);
findViewById(R.id.inner).setOnClickListener(this::onClick);
} }
@Override @Override
public void onBind(ErrorStatusDisplayItem item) { public void onBind(ErrorStatusDisplayItem item) {}
title.setText(item.exception.getMessage());
// title.setEllipsize(item.attachment.description != null ? TextUtils.TruncateAt.END : TextUtils.TruncateAt.MIDDLE);
// domain.setText(url.getHost());
}
private void onClick(View v) { private void copyErrorDetails(View v) {
// UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), getUrl()); StringWriter stringWriter=new StringWriter();
PrintWriter printWriter=new PrintWriter(stringWriter);
item.exception.printStackTrace(printWriter);
String stackTrace=stringWriter.toString();
String errorDetails=String.format(
"App Version: %s\nOS Version: %s\nStatus URL: %s\nException: %s",
v.getContext().getString(R.string.mo_settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE),
"Android " + Build.VERSION.RELEASE,
item.status.url,
stackTrace
);
UiUtils.copyText(v, errorDetails);
} }
} }
} }

View File

@ -10,6 +10,7 @@ import android.graphics.drawable.ColorDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -379,7 +380,8 @@ public abstract class StatusDisplayItem{
: Collections.singletonList(warning) : Collections.singletonList(warning)
); );
} catch(Exception e) { } catch(Exception e) {
return new ArrayList<>(Collections.singletonList(new ErrorStatusDisplayItem(parentID, fragment, e))); Log.e("StatusDisplayItem", "buildItems: failed to build StatusDisplayItem " + e);
return new ArrayList<>(Collections.singletonList(new ErrorStatusDisplayItem(parentID, statusForContent, fragment, e)));
} }
} }

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:layout_marginHorizontal="16dp"
android:padding="16dp"
android:clipToPadding="false"
android:background="@drawable/bg_settings_banner">
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="16dp"
android:scaleType="center"
android:importantForAccessibility="no"
android:tint="?colorM3OnPrimaryContainer"
android:background="@drawable/white_circle"
android:backgroundTint="?colorM3PrimaryContainer"
android:src="@drawable/ic_fluent_warning_24_regular" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_toEndOf="@id/icon"
android:layout_marginBottom="2dp"
android:textAppearance="@style/m3_title_medium"
android:textColor="?colorM3OnSurface"
android:singleLine="true"
android:gravity="center_vertical"
android:text="@string/mo_error_display_title"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/icon"
android:layout_below="@id/title"
android:textAppearance="@style/m3_body_medium"
android:minHeight="20dp"
android:gravity="center_vertical"
android:textColor="?colorM3OnSurface"
android:text="@string/mo_error_display_text"/>
<Button
android:id="@+id/button_open_browser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text"
android:layout_toEndOf="@id/icon"
android:layout_marginStart="-16dp"
android:layout_marginBottom="-10dp"
style="@style/Widget.Mastodon.M3.Button.Text"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:minWidth="0dp"
android:text="@string/open_in_browser"
tools:text="@string/resume_notifications_now"/>
<Button
android:id="@+id/button_copy_error_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text"
android:layout_toEndOf="@id/button_open_browser"
android:layout_marginBottom="-10dp"
style="@style/Widget.Mastodon.M3.Button.Text"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:minWidth="0dp"
android:text="@string/mo_error_display_copy_error_details"/>
</RelativeLayout>

View File

@ -133,4 +133,9 @@
<string name="export_settings_summary">Export all logged-in accounts\' settings and timelines</string> <string name="export_settings_summary">Export all logged-in accounts\' settings and timelines</string>
<string name="import_settings_title">Import settings</string> <string name="import_settings_title">Import settings</string>
<string name="import_settings_summary">Import previously exported settings and timelines</string> <string name="import_settings_summary">Import previously exported settings and timelines</string>
<!-- error display item -->
<string name="mo_error_display_title">Failed to display post</string>
<string name="mo_error_display_text">Something went wrong while loading this post. If the problem persists, please report it on our Issues page along with the error details.</string>
<string name="mo_error_display_copy_error_details">Copy details</string>
</resources> </resources>