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
22 changes: 22 additions & 0 deletions packages/react-native/Libraries/LogBox/LogBoxInspectorContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type LogBoxLog from './Data/LogBoxLog';

import View from '../Components/View/View';
import StyleSheet from '../StyleSheet/StyleSheet';
import BackHandler from '../Utilities/BackHandler';
import * as LogBoxData from './Data/LogBoxData';
import LogBoxInspector from './UI/LogBoxInspector';
import * as React from 'react';
Expand All @@ -23,6 +24,27 @@ type Props = Readonly<{
}>;

export class _LogBoxInspectorContainer extends React.Component<Props> {
_backHandler: ?{remove: () => void, ...} = null;

componentDidMount() {
this._backHandler = BackHandler.addEventListener(
'hardwareBackPress',
() => {
if (this.props.selectedLogIndex < 0) {
return false;
}
this._handleMinimize();
return true;
},
);
}

componentWillUnmount() {
if (this._backHandler) {
this._backHandler.remove();
}
}

render(): React.Node {
return (
<View style={StyleSheet.absoluteFill}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import SafeAreaView from '../../src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE';
import View from '../Components/View/View';
import StyleSheet from '../StyleSheet/StyleSheet';
import BackHandler from '../Utilities/BackHandler';
import * as LogBoxData from './Data/LogBoxData';
import LogBoxLog from './Data/LogBoxLog';
import LogBoxLogNotification from './UI/LogBoxNotification';
Expand All @@ -22,8 +23,28 @@ type Props = Readonly<{
isDisabled?: ?boolean,
}>;

export function _LogBoxNotificationContainer(props: Props): React.Node {
function useLogBoxBackHandler(focused: boolean, logCount: number): void {
React.useEffect(() => {
if (!focused || logCount === 0) {
return;
}
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
LogBoxData.clearWarnings();
LogBoxData.clearErrors();
return true;
},
);
return () => subscription.remove();
}, [focused, logCount]);
}

export function LogBoxNotificationContainer(props: Props): React.Node {
const {logs} = props;
const [focused, setFocused] = React.useState(false);

useLogBoxBackHandler(focused, logs.length);

const onDismissWarns = () => {
LogBoxData.clearWarnings();
Expand Down Expand Up @@ -68,6 +89,7 @@ export function _LogBoxNotificationContainer(props: Props): React.Node {
totalLogCount={warnings.length}
onPressOpen={() => openLog(warnings[warnings.length - 1])}
onPressDismiss={onDismissWarns}
onFocusChange={setFocused}
/>
</View>
)}
Expand All @@ -79,6 +101,7 @@ export function _LogBoxNotificationContainer(props: Props): React.Node {
totalLogCount={errors.length}
onPressOpen={() => openLog(errors[errors.length - 1])}
onPressDismiss={onDismissErrors}
onFocusChange={setFocused}
/>
</View>
)}
Expand All @@ -101,5 +124,5 @@ const styles = StyleSheet.create({
});

export default LogBoxData.withSubscription(
_LogBoxNotificationContainer,
LogBoxNotificationContainer,
) as React.ComponentType<{}>;
71 changes: 47 additions & 24 deletions packages/react-native/Libraries/LogBox/UI/LogBoxButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
import type {GestureResponderEvent} from '../../Types/CoreEventTypes';

import TouchableWithoutFeedback from '../../Components/Touchable/TouchableWithoutFeedback';
import Pressable from '../../Components/Pressable/Pressable';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import * as LogBoxStyle from './LogBoxStyle';
Expand All @@ -28,9 +28,10 @@ component LogBoxButton(
children?: React.Node,
hitSlop?: ?EdgeInsetsProp,
onPress?: ?(event: GestureResponderEvent) => void,
onFocusChange?: ?(focused: boolean) => void,
style?: ViewStyleProp,
) {
const [pressed, setPressed] = useState(false);
const [focused, setFocused] = useState(false);

let resolvedBackgroundColor = backgroundColor;
if (!resolvedBackgroundColor) {
Expand All @@ -40,32 +41,54 @@ component LogBoxButton(
};
}

const content = (
<View
id={id}
style={StyleSheet.compose(
{
backgroundColor: pressed
? resolvedBackgroundColor.pressed
: resolvedBackgroundColor.default,
},
style,
)}>
{children}
</View>
);
if (onPress == null) {
return (
<View
id={id}
style={StyleSheet.compose(
{backgroundColor: resolvedBackgroundColor.default},
style,
)}>
{children}
</View>
);
}

return onPress == null ? (
content
) : (
<TouchableWithoutFeedback
return (
<Pressable
id={id}
focusable={true}
hitSlop={hitSlop}
onPress={onPress}
onPressIn={() => setPressed(true)}
onPressOut={() => setPressed(false)}>
{content}
</TouchableWithoutFeedback>
onFocus={() => {
setFocused(true);
onFocusChange?.(true);
}}
onBlur={() => {
setFocused(false);
onFocusChange?.(false);
}}
style={({pressed}) =>
StyleSheet.compose(
{
backgroundColor: pressed
? resolvedBackgroundColor.pressed
: resolvedBackgroundColor.default,
},
focused ? StyleSheet.compose(style, styles.focusRing) : style,
)
}>
{children}
</Pressable>
);
}

const styles = StyleSheet.create({
focusRing: {
borderWidth: 2,
borderColor: LogBoxStyle.getTextColor(0.6),
borderRadius: 4,
},
});

export default LogBoxButton;
5 changes: 4 additions & 1 deletion packages/react-native/Libraries/LogBox/UI/LogBoxInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export default function LogBoxInspector(props: Props): React.Node {
}, []);

useEffect(() => {
if (log == null) {
return;
}
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
Expand All @@ -65,7 +68,7 @@ export default function LogBoxInspector(props: Props): React.Node {
},
);
return () => subscription.remove();
}, [onMinimize]);
}, [log, onMinimize]);

function _handleRetry() {
LogBoxData.retrySymbolicateLogNow(log);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';

const noop = () => {};

component LogBoxInspectorStackFrame(
frame: StackFrame,
onPress?: ?(event: GestureResponderEvent) => void,
Expand All @@ -38,7 +40,7 @@ component LogBoxInspectorStackFrame(
default: 'transparent',
pressed: onPress ? LogBoxStyle.getBackgroundColor(1) : 'transparent',
}}
onPress={onPress}
onPress={onPress ?? noop}
style={styles.frame}>
<Text
id="logbox_stack_frame_text"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Props = Readonly<{
level: 'warn' | 'error',
onPressOpen: () => void,
onPressDismiss: () => void,
onFocusChange?: ?(focused: boolean) => void,
}>;

export default function LogBoxNotification(props: Props): React.Node {
Expand All @@ -41,6 +42,7 @@ export default function LogBoxNotification(props: Props): React.Node {
<LogBoxButton
id={`logbox_open_button_${level}`}
onPress={props.onPressOpen}
onFocusChange={props.onFocusChange}
style={styles.press}
backgroundColor={{
default: LogBoxStyle.getBackgroundColor(1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ const LogBoxButton = require('../LogBoxButton').default;
const render = require('@react-native/jest-preset/jest/renderer');
const React = require('react');

// Mock `TouchableWithoutFeedback` because we are interested in snapshotting the
// behavior of `LogBoxButton`, not `TouchableWithoutFeedback`.
jest.mock('../../../Components/Touchable/TouchableWithoutFeedback', () => ({
// Mock `Pressable` because we are interested in snapshotting the
// behavior of `LogBoxButton`, not `Pressable`.
jest.mock('../../../Components/Pressable/Pressable', () => ({
__esModule: true,
default: 'TouchableWithoutFeedback',
default: 'Pressable',
}));

describe('LogBoxButton', () => {
Expand All @@ -36,7 +36,7 @@ describe('LogBoxButton', () => {
expect(output).toMatchSnapshot();
});

it('should render TouchableWithoutFeedback and pass through props', async () => {
it('should render Pressable and pass through props', async () => {
const output = await render.create(
<LogBoxButton
backgroundColor={{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`LogBoxButton should render TouchableWithoutFeedback and pass through props 1`] = `
<TouchableWithoutFeedback
exports[`LogBoxButton should render Pressable and pass through props 1`] = `
<Pressable
focusable={true}
hitSlop={Object {}}
onBlur={[Function]}
onFocus={[Function]}
onPress={[Function]}
onPressIn={[Function]}
onPressOut={[Function]}
style={[Function]}
>
<View
style={
Object {
"backgroundColor": "black",
}
}
>
<Text>
Press me
</Text>
</View>
</TouchableWithoutFeedback>
<Text>
Press me
</Text>
</Pressable>
`;

exports[`LogBoxButton should render only a view without an onPress 1`] = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ exports[`LogBoxInspectorStackFrame should render stack frame without press feedb
"pressed": "transparent",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,35 @@ exports[`LogBoxInspectorStackFrames should render stack frames with 1 frame coll
}
>
<View
accessibilityState={
Object {
"busy": undefined,
"checked": undefined,
"disabled": undefined,
"expanded": undefined,
"selected": undefined,
}
}
accessibilityValue={
Object {
"max": undefined,
"min": undefined,
"now": undefined,
"text": undefined,
}
}
accessible={true}
collapsable={false}
focusable={true}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Array [
Object {
Expand Down Expand Up @@ -149,9 +178,20 @@ exports[`LogBoxInspectorStackFrames should render stack frames with 1 frame coll
"selected": undefined,
}
}
accessibilityValue={
Object {
"max": undefined,
"min": undefined,
"now": undefined,
"text": undefined,
}
}
accessible={true}
collapsable={false}
focusable={true}
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
Expand Down
Loading
Loading