Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import android.widget.FrameLayout
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.R
import android.util.Log

/** Dialog for displaying JS errors in LogBox. */
internal class LogBoxDialog(context: Activity, private val reactRootView: View?) :
Expand All @@ -30,6 +31,7 @@ internal class LogBoxDialog(context: Activity, private val reactRootView: View?)
}

override fun onCreate(savedInstanceState: Bundle?) {
Log.d("LogBoxDialog", "onCreate")
super.onCreate(savedInstanceState)
// set background color so it will show below transparent system bars on forced edge-to-edge
this.window?.setBackgroundDrawable(ColorDrawable(Color.BLACK))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.facebook.react.devsupport

import android.content.Context
import android.graphics.Color
import android.view.Gravity
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.Nullable
import com.facebook.react.devsupport.interfaces.DevSupportManager
import com.facebook.react.devsupport.interfaces.RedBoxHandler

internal class ModernRedBoxContentView(context: Context) : LinearLayout(context) {

private var devSupportManager: DevSupportManager? = null
private var redBoxHandler: RedBoxHandler? = null
private var redBackgroundColor = Color.parseColor("#F35369")
private var errorTitleColor = Color.parseColor("#F35369")
private var basePadding = 32

init {
orientation = VERTICAL
setBackgroundColor(Color.parseColor("#474747"))

val headerView =
TextView(context).apply {
setTextColor(Color.WHITE)
textSize = 18f
text = "Failed to compile"
gravity = Gravity.CENTER
setTypeface(typeface, android.graphics.Typeface.BOLD)
setBackgroundColor(redBackgroundColor)
setPadding(basePadding, 40, basePadding, 40)
}
addView(headerView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))

val titleAndMessageContainer =
LinearLayout(context).apply {
orientation = VERTICAL
setBackgroundColor(Color.parseColor("#333333"))
setPadding(basePadding, basePadding, basePadding, basePadding)

val titleView =
TextView(context).apply {
setTextColor(errorTitleColor)
textSize = 18f
text = "Runtime Error"
setTypeface(typeface, android.graphics.Typeface.BOLD)
}
addView(titleView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))

val messageView =
TextView(context).apply {
setTextColor(Color.WHITE)
textSize = 14f
text = "Something went wrong"
setTypeface(typeface, android.graphics.Typeface.BOLD)
setPadding(0, basePadding / 2, 0, basePadding / 2)
}
addView(
messageView,
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
)
}
addView(
titleAndMessageContainer,
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
)
}

fun setDevSupportManager(devSupportManager: DevSupportManager): ModernRedBoxContentView {
this.devSupportManager = devSupportManager
return this
}

fun setRedBoxHandler(@Nullable redBoxHandler: RedBoxHandler?): ModernRedBoxContentView {
this.redBoxHandler = redBoxHandler
return this
}

fun init() {
// Placeholder for initialization logic if needed
}

fun refreshContentView() {
val title = "Runtime Error"
val message = devSupportManager?.lastErrorTitle ?: "Something went wrong"

getChildAt(1).let {
if (it is LinearLayout) {
(it.getChildAt(0) as TextView).text = title
(it.getChildAt(1) as TextView).text = message
}
}
}

fun resetReporting() {
// No-op for now
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class RedBoxContentView extends LinearLayout implements AdapterView.OnIte
private @Nullable ProgressBar mLoadingIndicator;
private @Nullable View mLineSeparator;
private boolean isReporting = false;
private boolean mShowStack = true;

private ReportCompletedListener mReportCompletedListener =
new ReportCompletedListener() {
Expand Down Expand Up @@ -283,6 +284,11 @@ public void onClick(View v) {
}

public void setExceptionDetails(String title, StackFrame[] stack) {
if (title != null && title.startsWith("Unable to load script")) {
mStackView.setAdapter(new StackAdapter(title, new StackFrame[0]));
return; // Exit the method
}

mStackView.setAdapter(new StackAdapter(title, stack));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class RedBoxDialogSurfaceDelegate implements SurfaceDelegate {

private @Nullable Dialog mDialog;
private @Nullable RedBoxContentView mRedBoxContentView;
private @Nullable ModernRedBoxContentView mModernRedBoxContentView;
private boolean mUseModernRedBox = true;

public RedBoxDialogSurfaceDelegate(DevSupportManager devSupportManager) {
mDevSupportManager = devSupportManager;
Expand All @@ -62,20 +64,35 @@ public void createContentView(String appKey) {
return;
}
// Create a new RedBox when currentActivity get updated
mRedBoxContentView = new RedBoxContentView(context);
mRedBoxContentView
.setDevSupportManager(mDevSupportManager)
.setRedBoxHandler(redBoxHandler)
.init();
if (mUseModernRedBox) {
mModernRedBoxContentView = new ModernRedBoxContentView(context);
mModernRedBoxContentView
.setDevSupportManager(mDevSupportManager)
.setRedBoxHandler(redBoxHandler)
.init();
} else {
mRedBoxContentView = new RedBoxContentView(context);
mRedBoxContentView
.setDevSupportManager(mDevSupportManager)
.setRedBoxHandler(redBoxHandler)
.init();
}
}

@Override
public boolean isContentViewReady() {
if (mUseModernRedBox) {
return mModernRedBoxContentView != null;
}
return mRedBoxContentView != null;
}

@Override
public void destroyContentView() {
if (mUseModernRedBox) {
mModernRedBoxContentView = null;
return;
}
mRedBoxContentView = null;
}

Expand All @@ -102,12 +119,21 @@ public void show() {
return;
}

if (mRedBoxContentView == null || mRedBoxContentView.getContext() != context) {
// Create a new RedBox when currentActivity get updated
createContentView("RedBox");
}
if (mUseModernRedBox) {
if (mModernRedBoxContentView == null || mModernRedBoxContentView.getContext() != context) {
// Create a new RedBox when currentActivity get updated
createContentView("ModernRedBox");
}

mRedBoxContentView.refreshContentView();
mModernRedBoxContentView.refreshContentView();
} else {
if (mRedBoxContentView == null || mRedBoxContentView.getContext() != context) {
// Create a new RedBox when currentActivity get updated
createContentView("RedBox");
}

mRedBoxContentView.refreshContentView();
}
if (mDialog == null) {
mDialog =
new Dialog(context, R.style.Theme_Catalyst_RedBox) {
Expand All @@ -134,20 +160,38 @@ protected void onCreate(Bundle savedInstanceState) {
int insetsType =
WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout();

ViewCompat.setOnApplyWindowInsetsListener(
mRedBoxContentView,
(view, windowInsetsCompat) -> {
Insets insets = windowInsetsCompat.getInsets(insetsType);

FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams();
lp.setMargins(insets.left, insets.top, insets.right, insets.bottom);

return WindowInsetsCompat.CONSUMED;
});
if (mUseModernRedBox) {
ViewCompat.setOnApplyWindowInsetsListener(
mModernRedBoxContentView,
(view, windowInsetsCompat) -> {
Insets insets = windowInsetsCompat.getInsets(insetsType);

FrameLayout.LayoutParams lp =
(FrameLayout.LayoutParams) view.getLayoutParams();
lp.setMargins(insets.left, insets.top, insets.right, insets.bottom);

return WindowInsetsCompat.CONSUMED;
});
} else {
ViewCompat.setOnApplyWindowInsetsListener(
mRedBoxContentView,
(view, windowInsetsCompat) -> {
Insets insets = windowInsetsCompat.getInsets(insetsType);

FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) view.getLayoutParams();
lp.setMargins(insets.left, insets.top, insets.right, insets.bottom);

return WindowInsetsCompat.CONSUMED;
});
}
}
};
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setContentView(mRedBoxContentView);
if (mUseModernRedBox) {
mDialog.setContentView(mModernRedBoxContentView);
} else {
mDialog.setContentView(mRedBoxContentView);
}
}
mDialog.show();
}
Expand Down
13 changes: 12 additions & 1 deletion packages/rn-tester/js/examples/Playground/RNTesterPlayground.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,29 @@
* @oncall react_native
*/

import type {RNTesterModuleExample} from '../../types/RNTesterTypes';

Check warning on line 12 in packages/rn-tester/js/examples/Playground/RNTesterPlayground.js

View workflow job for this annotation

GitHub Actions / test_js (20)

Requires should be sorted alphabetically

Check warning on line 12 in packages/rn-tester/js/examples/Playground/RNTesterPlayground.js

View workflow job for this annotation

GitHub Actions / test_js (18)

Requires should be sorted alphabetically

import RNTesterText from '../../components/RNTesterText';

import * as React from 'react';
import {StyleSheet, View} from 'react-native';
import {Button, StyleSheet, View, LogBox} from 'react-native';

function Playground() {
const onShowWarning = () => {
throw new Error('This is a warning');
};

React.useEffect(() => {
LogBox.install();
}, []);

return (
<View style={styles.container}>
<RNTesterText>
Edit "RNTesterPlayground.js" to change this file
</RNTesterText>

<Button onPress={onShowWarning} title="Show Warning" />
</View>
);
}
Expand Down
Loading