126ad19fcSEvan Bacon/**
226ad19fcSEvan Bacon * Copyright (c) 650 Industries.
326ad19fcSEvan Bacon * Copyright (c) Meta Platforms, Inc. and affiliates.
426ad19fcSEvan Bacon *
526ad19fcSEvan Bacon * This source code is licensed under the MIT license found in the
626ad19fcSEvan Bacon * LICENSE file in the root directory of this source tree.
726ad19fcSEvan Bacon */
826ad19fcSEvan Baconimport React from 'react';
926ad19fcSEvan Baconimport { Image, Platform, StatusBar, StyleSheet, Text, View } from 'react-native';
1026ad19fcSEvan Bacon
1126ad19fcSEvan Baconimport type { LogLevel } from '../Data/LogBoxLog';
1226ad19fcSEvan Baconimport { useLogs } from '../Data/LogContext';
1326ad19fcSEvan Baconimport { LogBoxButton } from '../UI/LogBoxButton';
1426ad19fcSEvan Baconimport * as LogBoxStyle from '../UI/LogBoxStyle';
1526ad19fcSEvan Bacon
1626ad19fcSEvan Bacontype Props = {
1726ad19fcSEvan Bacon  onSelectIndex: (selectedIndex: number) => void;
1826ad19fcSEvan Bacon  level: LogLevel;
1926ad19fcSEvan Bacon};
2026ad19fcSEvan Bacon
2126ad19fcSEvan Baconexport function LogBoxInspectorHeader(props: Props) {
2226ad19fcSEvan Bacon  const { selectedLogIndex: selectedIndex, logs } = useLogs();
2326ad19fcSEvan Bacon  const total = logs.length;
2426ad19fcSEvan Bacon
2526ad19fcSEvan Bacon  if (props.level === 'syntax') {
2626ad19fcSEvan Bacon    return (
2726ad19fcSEvan Bacon      <View style={[styles.safeArea, styles[props.level]]}>
2826ad19fcSEvan Bacon        <View style={styles.header}>
2926ad19fcSEvan Bacon          <View style={styles.title}>
3026ad19fcSEvan Bacon            <Text style={styles.titleText}>Failed to compile</Text>
3126ad19fcSEvan Bacon          </View>
3226ad19fcSEvan Bacon        </View>
3326ad19fcSEvan Bacon      </View>
3426ad19fcSEvan Bacon    );
3526ad19fcSEvan Bacon  }
3626ad19fcSEvan Bacon
3726ad19fcSEvan Bacon  const prevIndex = selectedIndex - 1 < 0 ? total - 1 : selectedIndex - 1;
3826ad19fcSEvan Bacon  const nextIndex = selectedIndex + 1 > total - 1 ? 0 : selectedIndex + 1;
3926ad19fcSEvan Bacon
4026ad19fcSEvan Bacon  const titleText = `Log ${selectedIndex + 1} of ${total}`;
4126ad19fcSEvan Bacon
4226ad19fcSEvan Bacon  return (
4326ad19fcSEvan Bacon    <View style={[styles.safeArea, styles[props.level]]}>
4426ad19fcSEvan Bacon      <View style={styles.header}>
4526ad19fcSEvan Bacon        <LogBoxInspectorHeaderButton
4626ad19fcSEvan Bacon          disabled={total <= 1}
4726ad19fcSEvan Bacon          level={props.level}
4826ad19fcSEvan Bacon          image={require('@expo/metro-runtime/assets/chevron-left.png')}
4926ad19fcSEvan Bacon          onPress={() => props.onSelectIndex(prevIndex)}
5026ad19fcSEvan Bacon        />
5126ad19fcSEvan Bacon        <View style={styles.title}>
5226ad19fcSEvan Bacon          <Text style={styles.titleText}>{titleText}</Text>
5326ad19fcSEvan Bacon        </View>
5426ad19fcSEvan Bacon        <LogBoxInspectorHeaderButton
5526ad19fcSEvan Bacon          disabled={total <= 1}
5626ad19fcSEvan Bacon          level={props.level}
5726ad19fcSEvan Bacon          image={require('@expo/metro-runtime/assets/chevron-right.png')}
5826ad19fcSEvan Bacon          onPress={() => props.onSelectIndex(nextIndex)}
5926ad19fcSEvan Bacon        />
6026ad19fcSEvan Bacon      </View>
6126ad19fcSEvan Bacon    </View>
6226ad19fcSEvan Bacon  );
6326ad19fcSEvan Bacon}
6426ad19fcSEvan Bacon
6526ad19fcSEvan Baconconst backgroundForLevel = (level: LogLevel) =>
6626ad19fcSEvan Bacon  ({
6726ad19fcSEvan Bacon    warn: {
6826ad19fcSEvan Bacon      default: 'transparent',
6926ad19fcSEvan Bacon      pressed: LogBoxStyle.getWarningDarkColor(),
7026ad19fcSEvan Bacon    },
7126ad19fcSEvan Bacon    error: {
7226ad19fcSEvan Bacon      default: 'transparent',
7326ad19fcSEvan Bacon      pressed: LogBoxStyle.getErrorDarkColor(),
7426ad19fcSEvan Bacon    },
7526ad19fcSEvan Bacon    fatal: {
7626ad19fcSEvan Bacon      default: 'transparent',
7726ad19fcSEvan Bacon      pressed: LogBoxStyle.getFatalDarkColor(),
7826ad19fcSEvan Bacon    },
7926ad19fcSEvan Bacon    syntax: {
8026ad19fcSEvan Bacon      default: 'transparent',
8126ad19fcSEvan Bacon      pressed: LogBoxStyle.getFatalDarkColor(),
8226ad19fcSEvan Bacon    },
8326ad19fcSEvan Bacon    static: {
8426ad19fcSEvan Bacon      default: 'transparent',
8526ad19fcSEvan Bacon      pressed: LogBoxStyle.getFatalDarkColor(),
8626ad19fcSEvan Bacon    },
87*8a424bebSJames Ide  })[level];
8826ad19fcSEvan Bacon
8926ad19fcSEvan Baconfunction LogBoxInspectorHeaderButton(props: {
9026ad19fcSEvan Bacon  disabled: boolean;
9126ad19fcSEvan Bacon  image: number;
9226ad19fcSEvan Bacon  level: LogLevel;
9326ad19fcSEvan Bacon  onPress?: () => void;
9426ad19fcSEvan Bacon}) {
9526ad19fcSEvan Bacon  return (
9626ad19fcSEvan Bacon    <LogBoxButton
9726ad19fcSEvan Bacon      backgroundColor={backgroundForLevel(props.level)}
9826ad19fcSEvan Bacon      onPress={props.disabled ? undefined : props.onPress}
9926ad19fcSEvan Bacon      style={headerStyles.button}>
10026ad19fcSEvan Bacon      {props.disabled ? null : (
10126ad19fcSEvan Bacon        <Image
10226ad19fcSEvan Bacon          source={props.image}
10326ad19fcSEvan Bacon          tintColor={LogBoxStyle.getTextColor()}
10426ad19fcSEvan Bacon          style={headerStyles.buttonImage}
10526ad19fcSEvan Bacon        />
10626ad19fcSEvan Bacon      )}
10726ad19fcSEvan Bacon    </LogBoxButton>
10826ad19fcSEvan Bacon  );
10926ad19fcSEvan Bacon}
11026ad19fcSEvan Bacon
11126ad19fcSEvan Baconconst headerStyles = StyleSheet.create({
11226ad19fcSEvan Bacon  button: {
11326ad19fcSEvan Bacon    alignItems: 'center',
11426ad19fcSEvan Bacon    justifyContent: 'center',
11526ad19fcSEvan Bacon    aspectRatio: 1,
11626ad19fcSEvan Bacon    marginRight: 6,
11726ad19fcSEvan Bacon    marginLeft: 6,
11826ad19fcSEvan Bacon    borderRadius: 3,
11926ad19fcSEvan Bacon  },
12026ad19fcSEvan Bacon  buttonImage: {
12126ad19fcSEvan Bacon    height: 14,
12226ad19fcSEvan Bacon    width: 8,
12326ad19fcSEvan Bacon  },
12426ad19fcSEvan Bacon});
12526ad19fcSEvan Bacon
12626ad19fcSEvan Baconconst styles = StyleSheet.create({
12726ad19fcSEvan Bacon  syntax: {
12826ad19fcSEvan Bacon    backgroundColor: LogBoxStyle.getFatalColor(),
12926ad19fcSEvan Bacon  },
13026ad19fcSEvan Bacon  static: {
13126ad19fcSEvan Bacon    backgroundColor: LogBoxStyle.getFatalColor(),
13226ad19fcSEvan Bacon  },
13326ad19fcSEvan Bacon  fatal: {
13426ad19fcSEvan Bacon    backgroundColor: LogBoxStyle.getFatalColor(),
13526ad19fcSEvan Bacon  },
13626ad19fcSEvan Bacon  warn: {
13726ad19fcSEvan Bacon    backgroundColor: LogBoxStyle.getWarningColor(),
13826ad19fcSEvan Bacon  },
13926ad19fcSEvan Bacon  error: {
14026ad19fcSEvan Bacon    backgroundColor: LogBoxStyle.getErrorColor(),
14126ad19fcSEvan Bacon  },
14226ad19fcSEvan Bacon  header: {
14326ad19fcSEvan Bacon    flexDirection: 'row',
14426ad19fcSEvan Bacon    alignItems: 'center',
14526ad19fcSEvan Bacon
14626ad19fcSEvan Bacon    paddingHorizontal: 8,
14726ad19fcSEvan Bacon    height: Platform.select({
14826ad19fcSEvan Bacon      default: 48,
14926ad19fcSEvan Bacon      ios: 44,
15026ad19fcSEvan Bacon    }),
15126ad19fcSEvan Bacon  },
15226ad19fcSEvan Bacon  title: {
15326ad19fcSEvan Bacon    alignItems: 'center',
15426ad19fcSEvan Bacon    flex: 1,
15526ad19fcSEvan Bacon    justifyContent: 'center',
15626ad19fcSEvan Bacon  },
15726ad19fcSEvan Bacon  titleText: {
15826ad19fcSEvan Bacon    color: LogBoxStyle.getTextColor(),
15926ad19fcSEvan Bacon    fontSize: 16,
16026ad19fcSEvan Bacon    fontWeight: '600',
16126ad19fcSEvan Bacon    includeFontPadding: false,
16226ad19fcSEvan Bacon    lineHeight: 20,
16326ad19fcSEvan Bacon  },
16426ad19fcSEvan Bacon  safeArea: {
16526ad19fcSEvan Bacon    paddingTop: Platform.OS !== 'ios' ? StatusBar.currentHeight : 40,
16626ad19fcSEvan Bacon  },
16726ad19fcSEvan Bacon});
168