/**
* Copyright (c) 650 Industries.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { LogBoxInspectorSection } from './LogBoxInspectorSection';
import { LogBoxInspectorSourceMapStatus } from './LogBoxInspectorSourceMapStatus';
import { LogBoxInspectorStackFrame } from './LogBoxInspectorStackFrame';
import type { StackType } from '../Data/LogBoxLog';
import type { Stack } from '../Data/LogBoxSymbolication';
import { useSelectedLog } from '../Data/LogContext';
import { LogBoxButton } from '../UI/LogBoxButton';
import * as LogBoxStyle from '../UI/LogBoxStyle';
import openFileInEditor from '../modules/openFileInEditor';
type Props = {
type: StackType;
onRetry: () => void;
};
export function getCollapseMessage(stackFrames: Stack, collapsed: boolean): string {
if (stackFrames.length === 0) {
return 'No frames to show';
}
const collapsedCount = stackFrames.reduce((count, { collapse }) => {
if (collapse === true) {
return count + 1;
}
return count;
}, 0);
if (collapsedCount === 0) {
return 'Showing all frames';
}
const framePlural = `frame${collapsedCount > 1 ? 's' : ''}`;
if (collapsedCount === stackFrames.length) {
return collapsed
? `See${collapsedCount > 1 ? ' all ' : ' '}${collapsedCount} collapsed ${framePlural}`
: `Collapse${collapsedCount > 1 ? ' all ' : ' '}${collapsedCount} ${framePlural}`;
} else {
return collapsed
? `See ${collapsedCount} more ${framePlural}`
: `Collapse ${collapsedCount} ${framePlural}`;
}
}
export function LogBoxInspectorStackFrames({ onRetry, type }: Props) {
const log = useSelectedLog();
const [collapsed, setCollapsed] = useState(() => {
// Only collapse frames initially if some frames are not collapsed.
return log.getAvailableStack(type)?.some(({ collapse }) => !collapse);
});
function getStackList() {
if (collapsed === true) {
return log.getAvailableStack(type)?.filter(({ collapse }) => !collapse);
} else {
return log.getAvailableStack(type);
}
}
if (log.getAvailableStack(type)?.length === 0) {
return null;
}
return (
}>
{log.symbolicated[type].status !== 'COMPLETE' && (
This call stack is not symbolicated. Some features are unavailable such as viewing the
function name or tapping to open files.
)}
setCollapsed(!collapsed)}
message={getCollapseMessage(log.getAvailableStack(type)!, !!collapsed)}
/>
);
}
function StackFrameList({
list,
status,
}: {
list: Stack;
status: 'NONE' | 'PENDING' | 'COMPLETE' | 'FAILED';
}): any {
return list.map((frame, index) => {
const { file, lineNumber } = frame;
return (
openFileInEditor(file, lineNumber)
: undefined
}
/>
);
});
}
function StackFrameFooter({ message, onPress }: { message: string; onPress: () => void }) {
return (
{message}
);
}
const stackStyles = StyleSheet.create({
section: {
marginTop: 15,
},
heading: {
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 12,
marginBottom: 10,
},
headingText: {
color: LogBoxStyle.getTextColor(1),
flex: 1,
fontSize: 20,
fontWeight: '600',
includeFontPadding: false,
lineHeight: 20,
},
body: {
paddingBottom: 10,
},
bodyText: {
color: LogBoxStyle.getTextColor(1),
fontSize: 14,
includeFontPadding: false,
lineHeight: 18,
fontWeight: '500',
paddingHorizontal: 27,
},
hintText: {
color: LogBoxStyle.getTextColor(0.7),
fontSize: 13,
includeFontPadding: false,
lineHeight: 18,
fontWeight: '400',
marginHorizontal: 10,
},
hintBox: {
backgroundColor: LogBoxStyle.getBackgroundColor(),
marginHorizontal: 10,
paddingHorizontal: 5,
paddingVertical: 10,
borderRadius: 5,
marginBottom: 5,
},
collapseContainer: {
marginLeft: 15,
flexDirection: 'row',
},
collapseButton: {
borderRadius: 5,
},
collapse: {
color: LogBoxStyle.getTextColor(0.7),
fontSize: 12,
fontWeight: '300',
lineHeight: 20,
marginTop: 0,
paddingHorizontal: 10,
paddingVertical: 5,
},
});