From d0cf9e46c7d5197770273867aae7ea307135174c Mon Sep 17 00:00:00 2001 From: Evan Kaloudis Date: Thu, 3 Oct 2024 14:34:41 -0400 Subject: [PATCH] tsc: fix components Co-authored-by: shubham --- components/Amount.tsx | 8 +- components/AmountInput.tsx | 5 +- components/Button.tsx | 4 +- components/Channels/ChannelItem.tsx | 9 +- components/Channels/ChannelsFilter.tsx | 25 +- components/Channels/ChannelsHeader.tsx | 10 +- components/CopyBox.tsx | 2 +- components/DropdownSetting.tsx | 2 +- components/Header.tsx | 11 +- components/HopPicker.tsx | 2 +- .../LayerBalances/LightningSwipeableRow.tsx | 17 +- .../LayerBalances/OnchainSwipeableRow.tsx | 11 +- components/LayerBalances/index.tsx | 9 +- components/LightningIndicator.tsx | 2 +- components/ModalBox.tsx | 196 +++++++++--- components/Modals/AlertModal.tsx | 2 +- components/NodeIdenticon.tsx | 1 + components/OnchainFeeInput.tsx | 2 +- components/PaymentPath.tsx | 43 ++- components/SuccessErrorMessage.tsx | 2 +- components/SwipeButton.tsx | 30 +- components/TextInput.tsx | 289 +++++++++--------- components/WalletHeader.tsx | 6 +- components/text/Body.tsx | 9 +- stores/UnitsStore.ts | 1 + tsc.json | 26 ++ 26 files changed, 459 insertions(+), 265 deletions(-) create mode 100644 tsc.json diff --git a/components/Amount.tsx b/components/Amount.tsx index 9b8242b3d4..218b3fd449 100644 --- a/components/Amount.tsx +++ b/components/Amount.tsx @@ -36,6 +36,10 @@ interface AmountDisplayProps { accessibilityLabel?: string; } +interface FiatSymbolProps { + accessible?: boolean; +} + function AmountDisplay({ amount, unit, @@ -75,7 +79,7 @@ function AmountDisplay({ ); - const FiatSymbol = () => ( + const FiatSymbol: React.FC = ({ accessible }) => ( { const rate = fiat && fiatRates && fiatEntry ? fiatEntry.rate : 0; - let satAmount: string | number; + let satAmount: string | number = 0; switch (units) { case 'sats': satAmount = value; @@ -68,6 +68,9 @@ const getSatAmount = (amount: string | number) => { .toFixed(0) : 0; break; + default: + satAmount = 0; + break; } return satAmount; diff --git a/components/Button.tsx b/components/Button.tsx index 0c6030fe3f..4fe505b9a3 100644 --- a/components/Button.tsx +++ b/components/Button.tsx @@ -90,12 +90,12 @@ function Button(props: ButtonProps) { : warning ? themeColor('delete') : themeColor('text'), - ...buttonStyle + ...(buttonStyle as object) }} titleStyle={ titleStyle ? { - ...titleStyle, + ...(titleStyle as object), textTransform: noUppercase ? 'none' : 'uppercase', fontFamily: 'PPNeueMontreal-Book' } diff --git a/components/Channels/ChannelItem.tsx b/components/Channels/ChannelItem.tsx index 05a526fd96..50af0d411d 100644 --- a/components/Channels/ChannelItem.tsx +++ b/components/Channels/ChannelItem.tsx @@ -33,8 +33,8 @@ export function ChannelItem({ }: { title?: string; secondTitle?: string; - inbound: number; - outbound: number; + inbound: string | number; + outbound: string | number; largestTotal?: number; status?: Status; pendingHTLCs?: boolean; @@ -79,7 +79,10 @@ export function ChannelItem({ } bold={selected} > - {PrivacyUtils.sensitiveValue(title)} + {`${ + typeof title === 'string' && + PrivacyUtils.sensitiveValue(title) + }`} )} diff --git a/components/Channels/ChannelsFilter.tsx b/components/Channels/ChannelsFilter.tsx index 9d90c12bc7..0e7635736f 100644 --- a/components/Channels/ChannelsFilter.tsx +++ b/components/Channels/ChannelsFilter.tsx @@ -102,20 +102,21 @@ const getChannelsSortKeys = (closed?: boolean) => { }; interface ChannelsFilterProps { - width?: string | number; + width?: number; } const ChannelsFilter = (props: ChannelsFilterProps) => { const { channelsStore } = stores; const { search, setSort, channelsType } = channelsStore; const windowWidth = Dimensions.get('window').width; + return ( - channelsStore!.setSearch(value) + onChangeText={(value?: string) => + channelsStore!.setSearch(value ?? '') } value={search} inputStyle={{ @@ -124,7 +125,7 @@ const ChannelsFilter = (props: ChannelsFilterProps) => { }} placeholderTextColor={themeColor('secondaryText')} containerStyle={{ - backgroundColor: null, + backgroundColor: 'transparent', borderTopWidth: 0, borderBottomWidth: 0, width: props.width || windowWidth - 55 @@ -134,6 +135,22 @@ const ChannelsFilter = (props: ChannelsFilterProps) => { backgroundColor: themeColor('secondary') }} autoCapitalize="none" + platform="default" + showLoading={false} + round={false} + lightTheme={false} + loadingProps={{}} + onClear={() => channelsStore!.setSearch('')} + onFocus={() => {}} + onBlur={() => {}} + onCancel={() => { + channelsStore!.setSearch(''); + }} + cancelButtonTitle="Cancel" + cancelButtonProps={{}} + searchIcon={{ name: 'search', type: 'font-awesome' }} + clearIcon={{ name: 'close', type: 'font-awesome' }} + showCancel={true} /> { diff --git a/components/Channels/ChannelsHeader.tsx b/components/Channels/ChannelsHeader.tsx index a5c21378c8..4a45b672f2 100644 --- a/components/Channels/ChannelsHeader.tsx +++ b/components/Channels/ChannelsHeader.tsx @@ -9,13 +9,19 @@ import { Spacer } from '../layout/Spacer'; import Amount from '../Amount'; import { localeString } from '../../utils/LocaleUtils'; +interface ChannelsHeaderProps { + totalInbound: number; + totalOutbound: number; + totalOffline: number; +} + function TotalRow({ kind, amount, color }: { kind: string; - amount: number; + amount: number | string; color: string; }) { return ( @@ -39,7 +45,7 @@ function TotalRow({ ); } -export function ChannelsHeader(props) { +export function ChannelsHeader(props: ChannelsHeaderProps) { const { totalInbound, totalOutbound, totalOffline } = props; return ( diff --git a/components/CopyBox.tsx b/components/CopyBox.tsx index 7664c79bf4..a9de8b836a 100644 --- a/components/CopyBox.tsx +++ b/components/CopyBox.tsx @@ -34,7 +34,7 @@ function CopyBox(props: CopyBoxProps) { : themeColor('background') }} onPress={() => { - Clipboard.setString(URL); + Clipboard.setString(URL || ''); setCopied(true); setCurrentTheme('light'); setTimeout(function () { diff --git a/components/DropdownSetting.tsx b/components/DropdownSetting.tsx index eff4f1382a..9dbd4ac232 100644 --- a/components/DropdownSetting.tsx +++ b/components/DropdownSetting.tsx @@ -14,7 +14,7 @@ import { localeString } from './../utils/LocaleUtils'; interface DropdownSettingProps { title: string; - selectedValue: string | boolean; + selectedValue: string | number; onValueChange: (value: any) => void; values: Array; disabled?: boolean; diff --git a/components/Header.tsx b/components/Header.tsx index d8915e3e59..173cb66eb9 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -1,10 +1,5 @@ import React from 'react'; -import { - StyleProp, - TextStyle, - ViewStyle, - TouchableOpacity -} from 'react-native'; +import { StyleProp, ViewStyle, TouchableOpacity } from 'react-native'; import { Header, TextProps } from 'react-native-elements'; import { IconObject } from 'react-native-elements/dist/icons/Icon'; @@ -19,7 +14,7 @@ interface HeaderIcon extends IconObject { icon?: string; text?: string; color?: string; - style?: StyleProp; + style?: StyleProp; } interface HeaderProps { @@ -31,7 +26,7 @@ interface HeaderProps { | 'Close'; centerComponent?: React.ReactElement<{}> | TextProps | HeaderIcon; rightComponent?: React.ReactElement<{}> | TextProps | HeaderIcon; - containerStyle?: ViewStyle; + containerStyle?: ViewStyle | any; placement?: 'left' | 'center' | 'right' | undefined; navigation?: StackNavigationProp; onBack?: () => void; diff --git a/components/HopPicker.tsx b/components/HopPicker.tsx index 3c10a1d28a..a2d4e0c37a 100644 --- a/components/HopPicker.tsx +++ b/components/HopPicker.tsx @@ -226,7 +226,7 @@ export default class ChannelPicker extends React.Component< )} - + ) => { const transTranslateX = progress.interpolate({ inputRange: [0.25, 1], @@ -130,7 +131,9 @@ export default class LightningSwipeableRow extends Component< ); }; - private renderActions = (progress: Animated.AnimatedInterpolation) => { + private renderActions = ( + progress: Animated.AnimatedInterpolation + ) => { const width = BackendUtils.supportsRouting() && BackendUtils.supportsLightningSends() && @@ -185,11 +188,15 @@ export default class LightningSwipeableRow extends Component< }; private close = () => { - this.swipeableRow.close(); + if (this.swipeableRow) { + this.swipeableRow.close(); + } }; private open = () => { - this.swipeableRow.openLeft(); + if (this.swipeableRow) { + this.swipeableRow.openLeft(); + } }; private fetchLnInvoice = () => { @@ -245,7 +252,7 @@ export default class LightningSwipeableRow extends Component< ); }); } else { - invoicesStore.getPayReq(this.props.lightning); + invoicesStore.getPayReq(lightning ?? ''); this.props.navigation.navigate('PaymentRequest', {}); } }; diff --git a/components/LayerBalances/OnchainSwipeableRow.tsx b/components/LayerBalances/OnchainSwipeableRow.tsx index f55095aa76..22ab3f70e7 100644 --- a/components/LayerBalances/OnchainSwipeableRow.tsx +++ b/components/LayerBalances/OnchainSwipeableRow.tsx @@ -26,6 +26,7 @@ interface OnchainSwipeableRowProps { locked?: boolean; account?: string; hidden?: boolean; + children?: React.ReactNode; } export default class OnchainSwipeableRow extends Component< @@ -35,7 +36,7 @@ export default class OnchainSwipeableRow extends Component< private renderAction = ( text: string, x: number, - progress: Animated.AnimatedInterpolation + progress: Animated.AnimatedInterpolation ) => { const { account, navigation } = this.props; const transTranslateX = progress.interpolate({ @@ -120,7 +121,9 @@ export default class OnchainSwipeableRow extends Component< ); }; - private renderActions = (progress: Animated.AnimatedInterpolation) => ( + private renderActions = ( + progress: Animated.AnimatedInterpolation + ) => ( { - this.swipeableRow.close(); + if (this.swipeableRow) this.swipeableRow.close(); }; private open = () => { - this.swipeableRow.openLeft(); + if (this.swipeableRow) this.swipeableRow.openLeft(); }; private sendToAddress = () => { diff --git a/components/LayerBalances/index.tsx b/components/LayerBalances/index.tsx index 2842c8ca69..11bb8188a0 100644 --- a/components/LayerBalances/index.tsx +++ b/components/LayerBalances/index.tsx @@ -58,7 +58,7 @@ type DataRow = { subtitle?: string; balance: string | number; // TODO check if exists - count: number; + count?: number; watchOnly?: boolean; hidden?: boolean; }; @@ -147,7 +147,7 @@ const Row = ({ item }: { item: DataRow }) => { color: themeColor('buttonText') }} > - {`+${item.count - 1}`} + {item.count && `+${item.count - 1}`} )} @@ -169,7 +169,7 @@ const SwipeableRow = ({ item: DataRow; index: number; navigation: StackNavigationProp; - selectMode: boolean; + // selectMode: boolean; // not used for now value?: string; amount?: string; lightning?: string; @@ -326,7 +326,8 @@ export default class LayerBalances extends Component { if (Object.keys(otherAccounts).length > 1 && consolidated) { DATA.push({ layer: localeString('components.LayerBalances.moreAccounts'), - count: Object.keys(otherAccounts).length + count: Object.keys(otherAccounts).length, + balance: 0 }); } diff --git a/components/LightningIndicator.tsx b/components/LightningIndicator.tsx index 8536bec001..dab16a2aac 100644 --- a/components/LightningIndicator.tsx +++ b/components/LightningIndicator.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Image } from 'react-native'; -import Loading from './../assets/images/GIF/Loading.gif'; +const Loading = require('../assets/images/GIF/Loading.gif'); interface LightningIndicatorProps { size?: number; diff --git a/components/ModalBox.tsx b/components/ModalBox.tsx index a851441ed9..cc4d725957 100644 --- a/components/ModalBox.tsx +++ b/components/ModalBox.tsx @@ -14,7 +14,10 @@ import { BackHandler, Platform, Modal, - Keyboard + Keyboard, + ViewStyle, + StyleProp, + LayoutChangeEvent } from 'react-native'; const { @@ -40,7 +43,59 @@ const styles = StyleSheet.create({ } }); -export default class ModalBox extends React.PureComponent { +interface ModalBoxProps { + isOpen: boolean; + isDisabled?: boolean; + startOpen: boolean; + backdropPressToClose?: boolean; + swipeToClose?: boolean; + swipeThreshold?: number; + swipeArea?: number; + position?: string; + entry?: string; + backdrop?: boolean; + backdropOpacity?: number; + backdropColor?: string; + backdropContent?: React.ReactNode; + animationDuration?: number; + backButtonClose?: boolean; + easing?: (value: number) => number; + coverScreen?: boolean; + keyboardTopOffset?: number; + onClosed?: () => void; + onOpened?: () => void; + onClosingState?: (state: boolean) => void; + style?: StyleProp; + children?: React.ReactNode; + useNativeDriver?: boolean; + onLayout?: (event: LayoutChangeEvent) => void; +} + +interface ModalBoxState { + position: Animated.Value; + backdropOpacity: Animated.Value; + isOpen: boolean; + isAnimateClose: boolean; + isAnimateOpen: boolean; + swipeToClose: boolean; + height: number; + width: number; + containerHeight: number; + containerWidth: number; + isInitialized: boolean; + keyboardOffset: number; + pan: any; + isAnimateBackdrop: boolean; + animBackdrop?: Animated.CompositeAnimation; + animOpen?: Animated.CompositeAnimation; + animClose?: Animated.CompositeAnimation; + positionDest?: number; +} + +export default class ModalBox extends React.PureComponent< + ModalBoxProps, + ModalBoxState +> { static propTypes = { isOpen: PropTypes.bool, isDisabled: PropTypes.bool, @@ -62,7 +117,8 @@ export default class ModalBox extends React.PureComponent { keyboardTopOffset: PropTypes.number, onClosed: PropTypes.func, onOpened: PropTypes.func, - onClosingState: PropTypes.func + onClosingState: PropTypes.func, + children: PropTypes.node }; static defaultProps = { @@ -83,7 +139,10 @@ export default class ModalBox extends React.PureComponent { useNativeDriver: true }; - constructor(props: any) { + subscriptions: any[] = []; + onViewLayoutCalculated: (() => void) | null; // Can be either a function or null + + constructor(props: ModalBoxProps) { super(props); this.onBackPress = this.onBackPress.bind(this); @@ -113,7 +172,7 @@ export default class ModalBox extends React.PureComponent { this.state = { position, backdropOpacity: new Animated.Value(0), - isOpen: props.startOpen, + isOpen: props.startOpen || false, isAnimateClose: false, isAnimateOpen: false, swipeToClose: false, @@ -123,7 +182,12 @@ export default class ModalBox extends React.PureComponent { containerWidth: SCREEN_WIDTH, isInitialized: false, keyboardOffset: 0, - pan: this.createPanResponder(position) + pan: this.createPanResponder(position), + isAnimateBackdrop: false, + animBackdrop: undefined, + animOpen: undefined, + animClose: undefined, + positionDest: undefined }; // Needed for iOS because the keyboard covers the screen @@ -206,18 +270,18 @@ export default class ModalBox extends React.PureComponent { toValue: 1, duration: this.props.animationDuration, easing: this.props.easing, - useNativeDriver: this.props.useNativeDriver - }).start(() => { + useNativeDriver: this.props.useNativeDriver ?? true + }); + + this.setState({ animBackdrop }); + + animBackdrop.start(() => { this.setState({ - isAnimateBackdrop: false, - animBackdrop + isAnimateBackdrop: false }); }); } - /* - * Close animation for the backdrop, will fade out - */ animateBackdropClose() { if (this.state.isAnimateBackdrop && this.state.animBackdrop) { this.state.animBackdrop.stop(); @@ -228,11 +292,14 @@ export default class ModalBox extends React.PureComponent { toValue: 0, duration: this.props.animationDuration, easing: this.props.easing, - useNativeDriver: this.props.useNativeDriver - }).start(() => { + useNativeDriver: this.props.useNativeDriver ?? true + }); + + this.setState({ animBackdrop }); + + animBackdrop.start(() => { this.setState({ - isAnimateBackdrop: false, - animBackdrop + isAnimateBackdrop: false }); }); } @@ -265,27 +332,38 @@ export default class ModalBox extends React.PureComponent { requestAnimationFrame(() => { // Detecting modal position let positionDest = this.calculateModalPosition( - this.state.containerHeight - this.state.keyboardOffset, - this.state.containerWidth + this.state.containerHeight - this.state.keyboardOffset ); if ( this.state.keyboardOffset && - positionDest < this.props.keyboardTopOffset + positionDest !== undefined && + positionDest < (this.props.keyboardTopOffset ?? 0) ) { - positionDest = this.props.keyboardTopOffset; + positionDest = this.props.keyboardTopOffset ?? 0; } + + // Fallback for undefined positionDest + positionDest = positionDest ?? 0; + const animOpen = Animated.timing(this.state.position, { toValue: positionDest, duration: this.props.animationDuration, easing: this.props.easing, - useNativeDriver: this.props.useNativeDriver - }).start(() => { + useNativeDriver: this.props.useNativeDriver ?? true + }); + + this.setState({ animOpen }); + + animOpen.start(() => { this.setState({ isAnimateOpen: false, animOpen, positionDest }); - if (this.props.onOpened) this.props.onOpened(); + + if (this.props.onOpened) { + this.props.onOpened(); + } }); }); } @@ -324,9 +402,10 @@ export default class ModalBox extends React.PureComponent { : this.state.containerHeight, duration: this.props.animationDuration, easing: this.props.easing, - useNativeDriver: this.props.useNativeDriver - }).start(() => { - // Keyboard.dismiss(); // make this optional. Easily user defined in .onClosed() callback + useNativeDriver: this.props.useNativeDriver ?? true + }); + // Keyboard.dismiss(); // make this optional. Easily user defined in .onClosed() callback + animClose.start(() => { this.setState( { isAnimateClose: false, @@ -341,8 +420,8 @@ export default class ModalBox extends React.PureComponent { ); } ); - if (this.props.onClosed) this.props.onClosed(); }); + if (this.props.onClosed) this.props.onClosed(); } ); } @@ -370,14 +449,22 @@ export default class ModalBox extends React.PureComponent { createPanResponder(position: any) { let closingState = false; let inSwipeArea = false; + const { + swipeThreshold = 50, + entry, + swipeToClose, + isDisabled, + swipeArea, + onClosingState + } = this.props; const onPanStart = (evt: any) => { if ( - !this.props.swipeToClose || - this.props.isDisabled || - (this.props.swipeArea && - evt.nativeEvent.pageY - this.state.positionDest > - this.props.swipeArea) + !swipeToClose || + isDisabled || + (swipeArea && + this.state.positionDest != undefined && + evt.nativeEvent.pageY - this.state.positionDest > swipeArea) ) { inSwipeArea = false; return false; @@ -392,26 +479,25 @@ export default class ModalBox extends React.PureComponent { const onPanMove = (evt: any, state: any) => { const newClosingState = - this.props.entry === 'top' - ? -state.dy > this.props.swipeThreshold - : state.dy > this.props.swipeThreshold; - if (this.props.entry === 'top' ? state.dy > 0 : state.dy < 0) - return; - if (newClosingState != closingState && this.props.onClosingState) - this.props.onClosingState(newClosingState); + entry === 'top' + ? -state.dy > swipeThreshold + : state.dy > swipeThreshold; + if (entry === 'top' ? state.dy > 0 : state.dy < 0) return; + if (newClosingState != closingState && onClosingState) + onClosingState(newClosingState); closingState = newClosingState; state.customY = state.dy + this.state.positionDest; animEvt(evt, state); }; - const onPanRelease = (evt: any, state: any) => { + const onPanRelease = (_evt: any, state: any) => { if (!inSwipeArea) return; inSwipeArea = false; if ( - this.props.entry === 'top' - ? -state.dy > this.props.swipeThreshold - : state.dy > this.props.swipeThreshold + entry === 'top' + ? -state.dy > swipeThreshold + : state.dy > swipeThreshold ) { this.close(); } else if (!this.state.isOpen) { @@ -435,7 +521,10 @@ export default class ModalBox extends React.PureComponent { const width = evt.nativeEvent.layout.width; // If the dimensions are still the same we're done - const newState = {}; + const newState: { height: number; width: number } = { + height, + width + }; if (height !== this.state.height) newState.height = height; if (width !== this.state.width) newState.width = width; this.setState(newState); @@ -481,7 +570,7 @@ export default class ModalBox extends React.PureComponent { backdrop = ( } = this.props; const size = { height: this.state.containerHeight, width: this.state.containerWidth }; const offsetX = (this.state.containerWidth - this.state.width) / 2; + const customHeightStyle = + style && + typeof style === 'object' && + 'height' in style && + style.height + ? { height: (style.height as number) * FONT_SCALE } + : undefined; + return ( { ); }); - const ref = createRef(); + const ref = createRef(); return ( { ? PrivacyUtils.sensitiveValue( aliasMap.get(hop.pubKey) ) - : hop.node.length >= 66 + : typeof hop.node === 'string' && + hop.node.length >= 66 ? `${ - PrivacyUtils.sensitiveValue( + typeof PrivacyUtils.sensitiveValue( hop.node - ).slice(0, 14) + - '...' + - PrivacyUtils.sensitiveValue( + ) === 'string' + ? ( + PrivacyUtils.sensitiveValue( + hop.node + ) as string + ).slice(0, 14) + : '' + }...${ + typeof PrivacyUtils.sensitiveValue( hop.node - ).slice(-14) + ) === 'string' + ? ( + PrivacyUtils.sensitiveValue( + hop.node + ) as string + ).slice(-14) + : '' }` - : PrivacyUtils.sensitiveValue(hop.node) + : typeof PrivacyUtils.sensitiveValue( + hop.node + ) === 'string' + ? PrivacyUtils.sensitiveValue(hop.node) + : '' }`} )} @@ -247,13 +264,13 @@ export default class PaymentPath extends React.Component< path.forEach((hop) => { const displayName = aliasMap.get(hop.pubKey) || hop.node; title += ', '; + const sensitiveDisplayName = + PrivacyUtils.sensitiveValue(displayName); title += - displayName.length >= 66 - ? `${PrivacyUtils.sensitiveValue(displayName).slice( - 0, - 6 - )}...` - : PrivacyUtils.sensitiveValue(displayName); + typeof sensitiveDisplayName === 'string' && + sensitiveDisplayName.length >= 66 + ? `${(sensitiveDisplayName as string).slice(0, 6)}...` + : sensitiveDisplayName ?? ''; }); if (enhancedPath.length > 1) { hops.push( diff --git a/components/SuccessErrorMessage.tsx b/components/SuccessErrorMessage.tsx index b59bdd386c..c7b1d1737a 100644 --- a/components/SuccessErrorMessage.tsx +++ b/components/SuccessErrorMessage.tsx @@ -20,7 +20,7 @@ const Message = ({ onPress }: MessageProps) => { const [isDismissed, setDismissed] = useState(false); - if (isDismissed) return; + if (isDismissed) return <>; return onPress ? ( = ({ extrapolate: 'clamp' }); + const [offset, setOffset] = useState(0); + const panResponder = useRef( PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderGrant: () => { - pan.setOffset(pan._value); + pan.setOffset(offset); pan.setValue(0); }, - onPanResponderMove: (e, gesture) => { + onPanResponderMove: (_e, gesture) => { const newValue = gesture.dx; if (newValue >= 0 && newValue <= maxTranslation) { pan.setValue(newValue); } }, onPanResponderRelease: ( - e: GestureResponderEvent, + _e: GestureResponderEvent, gesture: PanResponderGestureState ) => { - if (gesture.dx > maxTranslation * 0.95) { + const finalValue = + gesture.dx > maxTranslation * 0.95 ? maxTranslation : 0; + if (finalValue === maxTranslation) { onSwipeSuccess(); - Animated.spring(pan, { - toValue: maxTranslation, - useNativeDriver: false - }).start(); - } else { - Animated.spring(pan, { - toValue: 0, - useNativeDriver: false - }).start(); } + + Animated.spring(pan, { + toValue: finalValue, + useNativeDriver: false + }).start(() => { + setOffset(finalValue); + }); } }) ).current; diff --git a/components/TextInput.tsx b/components/TextInput.tsx index 728819cc4b..adaeab29bf 100644 --- a/components/TextInput.tsx +++ b/components/TextInput.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { + KeyboardTypeOptions, StyleProp, StyleSheet, Text, @@ -20,8 +21,8 @@ interface TextInputProps { textInputStyle?: StyleProp; placeholderTextColor?: string; locked?: boolean; - keyboardType?: string; - autoCapitalize?: string; + keyboardType?: KeyboardTypeOptions; + autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters'; autoCorrect?: boolean; multiline?: boolean; autoFocus?: boolean; @@ -36,152 +37,154 @@ interface TextInputProps { error?: boolean; } -const TextInput: React.FC = ( - { - placeholder, - value, - onChangeText, - numberOfLines, - style, - textInputStyle, - placeholderTextColor, - locked, - keyboardType, - autoCapitalize, - autoCorrect, - multiline, - autoFocus, - secureTextEntry, - prefix, - prefixStyle, - suffix, - toggleUnits, - onPressIn, - right, - error - }, - ref -) => { - const defaultStyle = numberOfLines - ? { - paddingTop: 10 - } - : multiline - ? {} - : { - height: 60 - }; +const TextInput = React.forwardRef( + ( + { + placeholder, + value, + onChangeText, + numberOfLines, + style, + textInputStyle, + placeholderTextColor, + locked, + keyboardType, + autoCapitalize, + autoCorrect, + multiline, + autoFocus, + secureTextEntry, + prefix, + prefixStyle, + suffix, + toggleUnits, + onPressIn, + right, + error + }, + ref + ) => { + const defaultStyle = numberOfLines + ? { + paddingTop: 10 + } + : multiline + ? {} + : { + height: 60 + }; - const Prefix = () => ( - - {prefix} - - ); + const Prefix = () => ( + + {prefix} + + ); - const Suffix = () => ( - - {suffix} - - ); + const Suffix = () => ( + + {suffix} + + ); - return ( - - {prefix ? ( - toggleUnits ? ( - toggleUnits && toggleUnits()} - > - - - ) : ( - - ) - ) : null} - - {suffix ? ( - toggleUnits ? ( - toggleUnits && toggleUnits()} - > + > + {prefix ? ( + toggleUnits ? ( + toggleUnits && toggleUnits()} + > + + + ) : ( + + ) + ) : null} + + {suffix ? ( + toggleUnits ? ( + toggleUnits && toggleUnits()} + > + + + ) : ( - - ) : ( - - ) - ) : null} - - ); -}; + ) + ) : null} + + ); + } +); const styles = StyleSheet.create({ wrapper: { @@ -205,4 +208,4 @@ const styles = StyleSheet.create({ } }); -export default React.forwardRef(TextInput); +export default TextInput; diff --git a/components/WalletHeader.tsx b/components/WalletHeader.tsx index ad8fe2befa..0f8237dc7e 100644 --- a/components/WalletHeader.tsx +++ b/components/WalletHeader.tsx @@ -406,7 +406,7 @@ export default class WalletHeader extends React.Component< const AlertButton = () => ( ModalStore.toggleAlertModal(true)} + onPress={() => ModalStore?.toggleAlertModal(true)} accessibilityLabel={localeString('general.search')} > )} - {!loading && AlertStore.hasError && } + {!loading && AlertStore?.hasError && ( + + )} {posEnabled === PosEnabled.Disabled && ( diff --git a/components/text/Body.tsx b/components/text/Body.tsx index 3ca651df80..a49bb6cadc 100644 --- a/components/text/Body.tsx +++ b/components/text/Body.tsx @@ -25,7 +25,14 @@ export function Body({ // These should only be keys available on the theme // TODO: enforce this with some global ThemeKey enum? colorOverride?: string; - color?: 'text' | 'success' | 'warning' | 'highlight' | 'secondaryText'; + color?: + | 'text' + | 'success' + | 'warning' + | 'highlight' + | 'secondaryText' + | 'outbound' + | 'inbound'; children: React.ReactNode; accessible?: boolean; accessibilityLabel?: string; diff --git a/stores/UnitsStore.ts b/stores/UnitsStore.ts index 9be68fe870..38b7334081 100644 --- a/stores/UnitsStore.ts +++ b/stores/UnitsStore.ts @@ -20,6 +20,7 @@ interface ValueDisplayProps { plural?: boolean; rtl?: boolean; space?: boolean; + error?: boolean; } export default class UnitsStore { diff --git a/tsc.json b/tsc.json new file mode 100644 index 0000000000..a0a23e7f23 --- /dev/null +++ b/tsc.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "isolatedModules": false, + "jsx": "react-native", + "lib": ["es6"], + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strict": true, + "target": "esnext", + "strictPropertyInitialization": false, + "skipLibCheck": true, + "baseUrl": "./", + "paths": { + "*" : ["typings/*"] + } + }, + // "include": ["**/*.ts", "**/*.tsx"], + "exclude": ["node_modules", "assets", "backends", "models", "views", "zeus_modules"] +}