Add Report Button for Android Redbox, enabled in Ads Manager, Groups and FB4A

Reviewed By: foghina

Differential Revision: D3542780

fbshipit-source-id: a0dfb8b8af7a5ae0ca696e84ec4b8795a293c26f
This commit is contained in:
Siqi Liu 2016-08-01 08:08:46 -07:00 коммит произвёл Facebook Github Bot 6
Родитель 42fc2e80db
Коммит 75e404bdde
5 изменённых файлов: 186 добавлений и 14 удалений

Просмотреть файл

@ -252,6 +252,7 @@ public class DevSupportManagerImpl implements DevSupportManager {
// JS errors are reported here after source mapping.
if (mRedBoxHandler != null) {
mRedBoxHandler.handleRedbox(message, stack, RedBoxHandler.ErrorType.JS);
mRedBoxDialog.resetReporting(true);
}
mRedBoxDialog.show();
}
@ -276,7 +277,7 @@ public class DevSupportManagerImpl implements DevSupportManager {
@Override
public void run() {
if (mRedBoxDialog == null) {
mRedBoxDialog = new RedBoxDialog(mApplicationContext, DevSupportManagerImpl.this);
mRedBoxDialog = new RedBoxDialog(mApplicationContext, DevSupportManagerImpl.this, mRedBoxHandler);
mRedBoxDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
if (mRedBoxDialog.isShowing()) {
@ -290,6 +291,9 @@ public class DevSupportManagerImpl implements DevSupportManager {
// inside {@link #updateJSError} after source mapping.
if (mRedBoxHandler != null && errorType == ErrorType.NATIVE) {
mRedBoxHandler.handleRedbox(message, stack, RedBoxHandler.ErrorType.NATIVE);
mRedBoxDialog.resetReporting(true);
} else {
mRedBoxDialog.resetReporting(false);
}
mRedBoxDialog.show();
}

Просмотреть файл

@ -9,10 +9,15 @@
package com.facebook.react.devsupport;
import javax.annotation.Nullable;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.text.SpannedString;
import android.text.method.LinkMovementMethod;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@ -22,6 +27,7 @@ import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.facebook.common.logging.FLog;
@ -30,6 +36,7 @@ import com.facebook.react.R;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.devsupport.StackTraceHelper.StackFrame;
import com.facebook.react.devsupport.RedBoxHandler.ReportCompletedListener;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
@ -44,11 +51,59 @@ import org.json.JSONObject;
private final DevSupportManager mDevSupportManager;
private final DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
private final @Nullable RedBoxHandler mRedBoxHandler;
private ListView mStackView;
private Button mReloadJs;
private Button mDismiss;
private Button mCopyToClipboard;
private Button mReloadJsButton;
private Button mDismissButton;
private Button mCopyToClipboardButton;
private @Nullable Button mReportButton;
private @Nullable TextView mReportTextView;
private @Nullable ProgressBar mLoadingIndicator;
private @Nullable View mLineSeparator;
private boolean isReporting = false;
private ReportCompletedListener mReportCompletedListener = new ReportCompletedListener() {
@Override
public void onReportSuccess(final SpannedString spannedString) {
isReporting = false;
Assertions.assertNotNull(mReportButton).setEnabled(true);
Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE);
Assertions.assertNotNull(mReportTextView).setText(spannedString);
}
@Override
public void onReportError(final SpannedString spannedString) {
isReporting = false;
Assertions.assertNotNull(mReportButton).setEnabled(true);
Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE);
Assertions.assertNotNull(mReportTextView).setText(spannedString);
}
};
private View.OnClickListener mReportButtonOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mRedBoxHandler == null || !mRedBoxHandler.isReportEnabled() || isReporting) {
return;
}
isReporting = true;
Assertions.assertNotNull(mReportTextView).setText("Reporting...");
Assertions.assertNotNull(mReportTextView).setVisibility(View.VISIBLE);
Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.VISIBLE);
Assertions.assertNotNull(mLineSeparator).setVisibility(View.VISIBLE);
Assertions.assertNotNull(mReportButton).setEnabled(false);
String title = Assertions.assertNotNull(mDevSupportManager.getLastErrorTitle());
StackFrame[] stack = Assertions.assertNotNull(mDevSupportManager.getLastErrorStack());
String sourceUrl = mDevSupportManager.getSourceUrl();
mRedBoxHandler.reportRedbox(
title,
stack,
sourceUrl,
Assertions.assertNotNull(mReportCompletedListener));
}
};
private static class StackAdapter extends BaseAdapter {
private static final int VIEW_TYPE_COUNT = 2;
@ -203,7 +258,10 @@ import org.json.JSONObject;
}
}
protected RedBoxDialog(Context context, DevSupportManager devSupportManager) {
protected RedBoxDialog(
Context context,
DevSupportManager devSupportManager,
@Nullable RedBoxHandler redBoxHandler) {
super(context, R.style.Theme_Catalyst_RedBox);
requestWindowFeature(Window.FEATURE_NO_TITLE);
@ -212,25 +270,27 @@ import org.json.JSONObject;
mDevSupportManager = devSupportManager;
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
mRedBoxHandler = redBoxHandler;
mStackView = (ListView) findViewById(R.id.rn_redbox_stack);
mStackView.setOnItemClickListener(this);
mReloadJs = (Button) findViewById(R.id.rn_redbox_reload_button);
mReloadJs.setOnClickListener(new View.OnClickListener() {
mReloadJsButton = (Button) findViewById(R.id.rn_redbox_reload_button);
mReloadJsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDevSupportManager.handleReloadJS();
}
});
mDismiss = (Button) findViewById(R.id.rn_redbox_dismiss_button);
mDismiss.setOnClickListener(new View.OnClickListener() {
mDismissButton = (Button) findViewById(R.id.rn_redbox_dismiss_button);
mDismissButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
mCopyToClipboard = (Button) findViewById(R.id.rn_redbox_copy_button);
mCopyToClipboard.setOnClickListener(new View.OnClickListener() {
mCopyToClipboardButton = (Button) findViewById(R.id.rn_redbox_copy_button);
mCopyToClipboardButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String title = mDevSupportManager.getLastErrorTitle();
@ -242,12 +302,38 @@ import org.json.JSONObject;
StackTraceHelper.formatStackTrace(title, stack));
}
});
if (mRedBoxHandler != null && mRedBoxHandler.isReportEnabled()) {
mLoadingIndicator = (ProgressBar) findViewById(R.id.rn_redbox_loading_indicator);
mLineSeparator = (View) findViewById(R.id.rn_redbox_line_separator);
mReportTextView = (TextView) findViewById(R.id.rn_redbox_report_label);
mReportTextView.setMovementMethod(LinkMovementMethod.getInstance());
mReportTextView.setHighlightColor(Color.TRANSPARENT);
mReportButton = (Button) findViewById(R.id.rn_redbox_report_button);
mReportButton.setOnClickListener(mReportButtonOnClickListener);
}
}
public void setExceptionDetails(String title, StackFrame[] stack) {
mStackView.setAdapter(new StackAdapter(title, stack));
}
/**
* Show the report button, hide the report textview and the loading indicator.
*/
public void resetReporting(boolean enabled) {
if (mRedBoxHandler == null || !mRedBoxHandler.isReportEnabled()) {
return;
}
isReporting = false;
Assertions.assertNotNull(mReportTextView).setVisibility(View.GONE);
Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE);
Assertions.assertNotNull(mLineSeparator).setVisibility(View.GONE);
Assertions.assertNotNull(mReportButton).setVisibility(
enabled ? View.VISIBLE : View.GONE);
Assertions.assertNotNull(mReportButton).setEnabled(true);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
new OpenStackFrameTask(mDevSupportManager).executeOnExecutor(

Просмотреть файл

@ -9,12 +9,14 @@
package com.facebook.react.devsupport;
import android.text.SpannedString;
import com.facebook.react.devsupport.StackTraceHelper.StackFrame;
/**
* Interface used by {@link DevSupportManagerImpl} to allow interception on any redboxes
* during development and handling the information from the redbox.
* The implementation should be passed by {@link #setRedBoxHandler} in {@link ReactInstanceManager}.
* The implementation should be passed by setRedBoxHandler in ReactInstanceManager.
*/
public interface RedBoxHandler {
enum ErrorType {
@ -29,5 +31,31 @@ public interface RedBoxHandler {
return name;
}
}
/**
* Callback interface for {@link #reportRedbox}.
*/
interface ReportCompletedListener {
void onReportSuccess(SpannedString spannedString);
void onReportError(SpannedString spannedString);
}
/**
* Handle the information from the redbox.
*/
void handleRedbox(String title, StackFrame[] stack, ErrorType errorType);
/**
* Whether the report feature is enabled.
*/
boolean isReportEnabled();
/**
* Report the information from the redbox and set up a callback listener.
*/
void reportRedbox(
String title,
StackFrame[] stack,
String sourceUrl,
ReportCompletedListener reportCompletedListener);
}

Просмотреть файл

@ -11,6 +11,42 @@
android:layout_height="0dp"
android:layout_weight="1"
/>
<View
android:id="@+id/rn_redbox_line_separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray"
android:visibility="gone"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ProgressBar
android:id="@+id/rn_redbox_loading_indicator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@android:style/Widget.ProgressBar.Small"
android:indeterminateOnly="true"
android:visibility="gone"
android:paddingLeft="16dp"
/>
<TextView
android:id="@+id/rn_redbox_report_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="14sp"
android:fontFamily="monospace"
android:visibility="gone"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:lineSpacingExtra="4dp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -27,6 +63,7 @@
android:textSize="14sp"
android:alpha="0.5"
style="?android:attr/borderlessButtonStyle"
android:gravity="center_horizontal|top"
/>
<Button
android:id="@+id/rn_redbox_reload_button"
@ -39,6 +76,7 @@
android:textSize="14sp"
android:alpha="0.5"
style="?android:attr/borderlessButtonStyle"
android:gravity="center_horizontal|top"
/>
<Button
android:id="@+id/rn_redbox_copy_button"
@ -51,6 +89,21 @@
android:textSize="14sp"
android:alpha="0.5"
style="?android:attr/borderlessButtonStyle"
android:gravity="center_horizontal|top"
/>
<Button
android:id="@+id/rn_redbox_report_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="4dp"
android:text="@string/catalyst_report_button"
android:textColor="@android:color/white"
android:textSize="14sp"
android:alpha="0.5"
style="?android:attr/borderlessButtonStyle"
android:visibility="gone"
android:gravity="center_horizontal|top"
/>
</LinearLayout>
</LinearLayout>

Просмотреть файл

@ -18,7 +18,8 @@
<string name="catalyst_remotedbg_error" project="catalyst" translatable="false">Unable to connect with remote debugger</string>
<string name="catalyst_element_inspector" project="catalyst" translatable="false">Toggle Inspector</string>
<string name="catalyst_heap_capture" project="catalyst" translatable="false">Capture Heap</string>
<string name="catalyst_dismiss_button" project="catalyst" translatable="false">Dismiss (ESC)</string>
<string name="catalyst_reload_button" project="catalyst" translatable="false">Reload (R,\u00A0R)</string>
<string name="catalyst_dismiss_button" project="catalyst" translatable="false">Dismiss\n(ESC)</string>
<string name="catalyst_reload_button" project="catalyst" translatable="false">Reload\n(R,\u00A0R)</string>
<string name="catalyst_copy_button" project="catalyst" translatable="false">Copy</string>
<string name="catalyst_report_button" project="catalyst" translatable="false">Report</string>
</resources>