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:
parent
b38c78c50a
commit
14e6187efc
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in New Issue