1*26ad19fcSEvan Bacon/** 2*26ad19fcSEvan Bacon * Copyright (c) 650 Industries. 3*26ad19fcSEvan Bacon * Copyright (c) Meta Platforms, Inc. and affiliates. 4*26ad19fcSEvan Bacon * 5*26ad19fcSEvan Bacon * This source code is licensed under the MIT license found in the 6*26ad19fcSEvan Bacon * LICENSE file in the root directory of this source tree. 7*26ad19fcSEvan Bacon */ 8*26ad19fcSEvan Baconimport React, { useEffect, useState } from 'react'; 9*26ad19fcSEvan Baconimport { Animated, Easing, GestureResponderEvent, StyleSheet, Text } from 'react-native'; 10*26ad19fcSEvan Bacon 11*26ad19fcSEvan Baconimport { LogBoxButton } from '../UI/LogBoxButton'; 12*26ad19fcSEvan Baconimport * as LogBoxStyle from '../UI/LogBoxStyle'; 13*26ad19fcSEvan Bacon 14*26ad19fcSEvan Bacontype Props = { 15*26ad19fcSEvan Bacon onPress?: ((event: GestureResponderEvent) => void) | null; 16*26ad19fcSEvan Bacon status: 'COMPLETE' | 'FAILED' | 'NONE' | 'PENDING'; 17*26ad19fcSEvan Bacon}; 18*26ad19fcSEvan Bacon 19*26ad19fcSEvan Baconexport function LogBoxInspectorSourceMapStatus(props: Props) { 20*26ad19fcSEvan Bacon const [state, setState] = useState<{ 21*26ad19fcSEvan Bacon animation: null | Animated.CompositeAnimation; 22*26ad19fcSEvan Bacon rotate: null | Animated.AnimatedInterpolation<string>; 23*26ad19fcSEvan Bacon }>({ 24*26ad19fcSEvan Bacon animation: null, 25*26ad19fcSEvan Bacon rotate: null, 26*26ad19fcSEvan Bacon }); 27*26ad19fcSEvan Bacon 28*26ad19fcSEvan Bacon useEffect(() => { 29*26ad19fcSEvan Bacon if (props.status === 'PENDING') { 30*26ad19fcSEvan Bacon if (state.animation == null) { 31*26ad19fcSEvan Bacon const animated = new Animated.Value(0); 32*26ad19fcSEvan Bacon const animation = Animated.loop( 33*26ad19fcSEvan Bacon Animated.timing(animated, { 34*26ad19fcSEvan Bacon duration: 2000, 35*26ad19fcSEvan Bacon easing: Easing.linear, 36*26ad19fcSEvan Bacon toValue: 1, 37*26ad19fcSEvan Bacon useNativeDriver: true, 38*26ad19fcSEvan Bacon }) 39*26ad19fcSEvan Bacon ); 40*26ad19fcSEvan Bacon setState({ 41*26ad19fcSEvan Bacon animation, 42*26ad19fcSEvan Bacon rotate: animated.interpolate({ 43*26ad19fcSEvan Bacon inputRange: [0, 1], 44*26ad19fcSEvan Bacon outputRange: ['0deg', '360deg'], 45*26ad19fcSEvan Bacon }), 46*26ad19fcSEvan Bacon }); 47*26ad19fcSEvan Bacon animation.start(); 48*26ad19fcSEvan Bacon } 49*26ad19fcSEvan Bacon } else { 50*26ad19fcSEvan Bacon if (state.animation != null) { 51*26ad19fcSEvan Bacon state.animation.stop(); 52*26ad19fcSEvan Bacon setState({ 53*26ad19fcSEvan Bacon animation: null, 54*26ad19fcSEvan Bacon rotate: null, 55*26ad19fcSEvan Bacon }); 56*26ad19fcSEvan Bacon } 57*26ad19fcSEvan Bacon } 58*26ad19fcSEvan Bacon 59*26ad19fcSEvan Bacon return () => { 60*26ad19fcSEvan Bacon if (state.animation != null) { 61*26ad19fcSEvan Bacon state.animation.stop(); 62*26ad19fcSEvan Bacon } 63*26ad19fcSEvan Bacon }; 64*26ad19fcSEvan Bacon }, [props.status, state.animation]); 65*26ad19fcSEvan Bacon 66*26ad19fcSEvan Bacon let image; 67*26ad19fcSEvan Bacon let color; 68*26ad19fcSEvan Bacon switch (props.status) { 69*26ad19fcSEvan Bacon case 'FAILED': 70*26ad19fcSEvan Bacon image = require('@expo/metro-runtime/assets/alert-triangle.png'); 71*26ad19fcSEvan Bacon color = LogBoxStyle.getErrorColor(1); 72*26ad19fcSEvan Bacon break; 73*26ad19fcSEvan Bacon case 'PENDING': 74*26ad19fcSEvan Bacon image = require('@expo/metro-runtime/assets/loader.png'); 75*26ad19fcSEvan Bacon color = LogBoxStyle.getWarningColor(1); 76*26ad19fcSEvan Bacon break; 77*26ad19fcSEvan Bacon } 78*26ad19fcSEvan Bacon 79*26ad19fcSEvan Bacon if (props.status === 'COMPLETE' || image == null) { 80*26ad19fcSEvan Bacon return null; 81*26ad19fcSEvan Bacon } 82*26ad19fcSEvan Bacon 83*26ad19fcSEvan Bacon return ( 84*26ad19fcSEvan Bacon <LogBoxButton 85*26ad19fcSEvan Bacon backgroundColor={{ 86*26ad19fcSEvan Bacon default: 'transparent', 87*26ad19fcSEvan Bacon pressed: LogBoxStyle.getBackgroundColor(1), 88*26ad19fcSEvan Bacon }} 89*26ad19fcSEvan Bacon hitSlop={{ bottom: 8, left: 8, right: 8, top: 8 }} 90*26ad19fcSEvan Bacon onPress={props.onPress} 91*26ad19fcSEvan Bacon style={styles.root}> 92*26ad19fcSEvan Bacon <Animated.Image 93*26ad19fcSEvan Bacon source={image} 94*26ad19fcSEvan Bacon tintColor={color ?? LogBoxStyle.getTextColor(0.4)} 95*26ad19fcSEvan Bacon style={[ 96*26ad19fcSEvan Bacon styles.image, 97*26ad19fcSEvan Bacon state.rotate == null || props.status !== 'PENDING' 98*26ad19fcSEvan Bacon ? null 99*26ad19fcSEvan Bacon : { transform: [{ rotate: state.rotate }] }, 100*26ad19fcSEvan Bacon ]} 101*26ad19fcSEvan Bacon /> 102*26ad19fcSEvan Bacon <Text style={[styles.text, { color }]}>Source Map</Text> 103*26ad19fcSEvan Bacon </LogBoxButton> 104*26ad19fcSEvan Bacon ); 105*26ad19fcSEvan Bacon} 106*26ad19fcSEvan Bacon 107*26ad19fcSEvan Baconconst styles = StyleSheet.create({ 108*26ad19fcSEvan Bacon root: { 109*26ad19fcSEvan Bacon alignItems: 'center', 110*26ad19fcSEvan Bacon borderRadius: 12, 111*26ad19fcSEvan Bacon flexDirection: 'row', 112*26ad19fcSEvan Bacon height: 24, 113*26ad19fcSEvan Bacon paddingHorizontal: 8, 114*26ad19fcSEvan Bacon }, 115*26ad19fcSEvan Bacon image: { 116*26ad19fcSEvan Bacon height: 14, 117*26ad19fcSEvan Bacon width: 16, 118*26ad19fcSEvan Bacon marginEnd: 4, 119*26ad19fcSEvan Bacon }, 120*26ad19fcSEvan Bacon text: { 121*26ad19fcSEvan Bacon fontSize: 12, 122*26ad19fcSEvan Bacon includeFontPadding: false, 123*26ad19fcSEvan Bacon lineHeight: 16, 124*26ad19fcSEvan Bacon }, 125*26ad19fcSEvan Bacon}); 126