Skip to content

Commit

Permalink
feat: improved error activity ui (#1776)
Browse files Browse the repository at this point in the history
  • Loading branch information
ammarahm-ed committed Oct 6, 2023
1 parent d21d6aa commit ee3e354
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 100 deletions.
107 changes: 94 additions & 13 deletions test-app/app/src/debug/java/com/tns/ErrorReport.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,33 @@
import android.app.PendingIntent.CanceledException;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import com.google.android.material.tabs.TabLayout;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -42,7 +54,6 @@
import android.widget.TextView;
import android.widget.Toast;


class ErrorReport implements TabLayout.OnTabSelectedListener {
public static final String ERROR_FILE_NAME = "hasError";
private static AppCompatActivity activity;
Expand Down Expand Up @@ -349,26 +360,96 @@ public int getCount() {
}
}

public static class ExceptionTab extends Fragment {

public static class ExceptionTab extends Fragment {

public SpannableStringBuilder getStyledStacktrace(String trace) {
if (trace == null) return null;
String[] traceLines = trace.trim().split("\n");
SpannableStringBuilder builder = new SpannableStringBuilder();
boolean firstLine = true;
for (String line: traceLines) {
if (firstLine) {
firstLine = false;
} else {
builder.append("\n");
builder.append("\n");
}

String[] nameAndPath = line.trim().split("\\(");
SpannableString nameSpan = new SpannableString(nameAndPath[0]);
nameSpan.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, nameAndPath[0].length(), 0);
builder.append(nameSpan);

builder.append(" ");
if (nameAndPath.length > 1) {
SpannableString pathSpan = new SpannableString("(" + nameAndPath[1]);
pathSpan.setSpan(new AbsoluteSizeSpan(13, true),0, nameAndPath[1].length() + 1, 0);
pathSpan.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
Log.d("JS", line.trim());
}
}, 0,nameAndPath[1].length() + 1, 0);
pathSpan.setSpan(new ForegroundColorSpan(Color.GRAY),0, nameAndPath[1].length() + 1, 0);

builder.append(pathSpan);
}
}
return builder;
}

public static void restartApp(Context context) {
PackageManager packageManager = context.getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
ComponentName componentName = intent.getComponent();
Intent mainIntent = Intent.makeRestartActivityTask(componentName);
context.startActivity(mainIntent);
java.lang.Runtime.getRuntime().exit(0);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int exceptionTabId = container.getContext().getResources().getIdentifier("exception_tab", "layout", container.getContext().getPackageName());
View view = inflater.inflate(exceptionTabId, container, false);

int txtViewId = container.getContext().getResources().getIdentifier("txtErrorMsg", "id", container.getContext().getPackageName());
TextView txtErrorMsg = (TextView) view.findViewById(txtViewId);
txtErrorMsg.setText(exceptionMsg);
txtErrorMsg.setMovementMethod(new ScrollingMovementMethod());
int errorExceptionViewId = activity.getResources().getIdentifier("errorException", "id", activity.getPackageName());
TextView errorExceptionView = (TextView) activity.findViewById(errorExceptionViewId);
errorExceptionView.setMovementMethod(new ScrollingMovementMethod());

int errorStackTraceViewId = container.getContext().getResources().getIdentifier("errorStacktrace", "id", container.getContext().getPackageName());
TextView errorStackTraceView = (TextView) view.findViewById(errorStackTraceViewId);

String[] exceptionParts = exceptionMsg.split("StackTrace:");
String error = exceptionParts[0];
String trace = "";

if (exceptionParts.length > 1) {
for (int i=0;i < exceptionParts.length;i++) {
if (i == 0) continue;
trace += exceptionParts[i];
}
}

errorExceptionView.setText(error.trim());

errorStackTraceView.setText(trace != null ? getStyledStacktrace(trace) : "", TextView.BufferType.SPANNABLE);
errorStackTraceView.setMovementMethod(new ScrollingMovementMethod());
errorStackTraceView.setMovementMethod(LinkMovementMethod.getInstance());
errorStackTraceView.setEnabled(true);

int btnCopyExceptionId = container.getContext().getResources().getIdentifier("btnCopyException", "id", container.getContext().getPackageName());
Button copyToClipboard = (Button) view.findViewById(btnCopyExceptionId);
copyToClipboard.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("nsError", exceptionMsg);
clipboard.setPrimaryClip(clip);
}

int btnRestartAppId = container.getContext().getResources().getIdentifier("btnRestartApp", "id", container.getContext().getPackageName());
Button restartApp = (Button) view.findViewById(btnRestartAppId);
restartApp.setOnClickListener(v -> {
restartApp(getContext().getApplicationContext());
});
copyToClipboard.setOnClickListener(v -> {
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("nsError", exceptionMsg);
clipboard.setPrimaryClip(clip);
});

return view;
Expand Down
87 changes: 55 additions & 32 deletions test-app/app/src/debug/res/layout/error_activity.xml
Original file line number Diff line number Diff line change
@@ -1,39 +1,62 @@
<?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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.tns.ErrorReportActivity"
android:theme="@style/Widget.AppCompat.Light.ActionBar">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"/>
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/gray"
tools:context="com.tns.ErrorReportActivity"
android:theme="@style/Widget.AppCompat.Light.ActionBar">

<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/toolbar"
android:scrollbarAlwaysDrawVerticalTrack="false">

</androidx.viewpager.widget.ViewPager>

<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
<TextView
android:id="@+id/errorException"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:tabIndicatorColor="@color/nativescript_blue"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:scrollbarStyle="insideOverlay"
android:text=""
android:background="@color/red"
android:textSize="16sp"
android:paddingLeft="16dp"
android:textIsSelectable="true"
android:maxHeight="200dp"
android:scrollbars="vertical"
tools:tabBackground="@android:color/darker_gray"
android:scrollbarAlwaysDrawVerticalTrack="false"
/>
</RelativeLayout>
android:textColor="@color/white"
android:paddingVertical="10dp"
android:paddingRight="16dp" />

<RelativeLayout
android:layout_below="@id/errorException"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize" />

<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/toolbar"
android:scrollbarAlwaysDrawVerticalTrack="false">

</androidx.viewpager.widget.ViewPager>

<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/gray"
android:minHeight="?attr/actionBarSize"
app:tabIndicatorColor="@color/nativescript_blue"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:scrollbarStyle="insideOverlay"
android:scrollbars="vertical"
tools:tabBackground="@color/gray_color"
android:scrollbarAlwaysDrawVerticalTrack="false" />
</RelativeLayout>

</RelativeLayout>
79 changes: 49 additions & 30 deletions test-app/app/src/debug/res/layout/exception_tab.xml
Original file line number Diff line number Diff line change
@@ -1,52 +1,71 @@
<?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="match_parent"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="10dp">

<Button
android:id="@+id/btnCopyException"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@color/nativescript_blue"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:text="Copy to clipboard"
android:textAlignment="textStart"
android:textColor="@android:color/white"
tools:layout_width="match_parent"/>
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="@color/gray"
android:layout_height="match_parent"
android:orientation="vertical">


<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnCopyException"
android:layout_above="@+id/bottomButtonRow"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:orientation="vertical"
android:paddingBottom="10dp"
android:weightSum="100">


<TextView
android:id="@+id/txtErrorMsg"
android:id="@+id/errorStacktrace"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:scrollbars="vertical"
android:scrollbarStyle="outsideOverlay"
android:scrollbarAlwaysDrawVerticalTrack="true"/>
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:scrollbarAlwaysDrawVerticalTrack="true" />

</LinearLayout>

<LinearLayout
android:id="@+id/bottomButtonRow"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:paddingBottom="10dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="10dp"
android:layout_height="wrap_content">

<Button
android:id="@+id/btnRestartApp"
android:text="Restart APP"
android:textAlignment="center"
android:textColor="@android:color/white"
android:background="@drawable/button_accented"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginRight="10dp" />

<Button
android:id="@+id/btnCopyException"
android:textColor="@android:color/white"
android:text="Copy"
android:background="@drawable/button"
android:textAlignment="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />


</LinearLayout>


</RelativeLayout>
</RelativeLayout>
Loading

0 comments on commit ee3e354

Please sign in to comment.