From e2f6485e8c505bce37aabdab0f4dc3379f99dbbc Mon Sep 17 00:00:00 2001 From: J M Rossy Date: Mon, 4 Nov 2019 14:36:02 +0100 Subject: [PATCH] [Wallet] Create new carousel component (#1555) * Add a new carousel for user education * Remove unused verify input screen * Create new screen for first stage of new verification designs --- packages/mobile/package.json | 2 + packages/mobile/src/components/Carousel.tsx | 110 +++++ packages/mobile/src/navigator/Navigator.tsx | 4 +- packages/mobile/src/navigator/Screens.tsx | 2 +- packages/mobile/src/verify/Input.tsx | 188 -------- .../src/verify/VerificationLoadingScreen.tsx | 58 +++ packages/mobile/src/verify/Verify.test.tsx | 17 - .../verify/__snapshots__/Verify.test.tsx.snap | 446 ------------------ packages/react-components/styles/colors.tsx | 1 + yarn.lock | 24 + 10 files changed, 198 insertions(+), 654 deletions(-) create mode 100644 packages/mobile/src/components/Carousel.tsx delete mode 100644 packages/mobile/src/verify/Input.tsx create mode 100644 packages/mobile/src/verify/VerificationLoadingScreen.tsx diff --git a/packages/mobile/package.json b/packages/mobile/package.json index 330729c0b0c..19e912a23de 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -114,6 +114,7 @@ "react-native-send-intent": "git+https://github.com/celo-org/react-native-send-intent#a0f4b00", "react-native-shadow": "^1.2.2", "react-native-share": "^2.0.0", + "react-native-snap-carousel": "^3.8.4", "react-native-sms": "^1.9.0", "react-native-splash-screen": "^3.2.0", "react-native-svg": "^9.11.1", @@ -148,6 +149,7 @@ "@types/lodash": "^4.14.136", "@types/react": "^16.8.19", "@types/react-native": "^0.60.19", + "@types/react-native-snap-carousel": "^3.7.4", "@types/react-native-fs": "^2.8.1", "@types/react-native-keep-awake": "^2.0.1", "@types/react-redux": "^7.1.2", diff --git a/packages/mobile/src/components/Carousel.tsx b/packages/mobile/src/components/Carousel.tsx new file mode 100644 index 00000000000..9c6e2ba3adc --- /dev/null +++ b/packages/mobile/src/components/Carousel.tsx @@ -0,0 +1,110 @@ +/** + * A custom style carousel based on react-native-snap-carousel + */ + +import colors from '@celo/react-components/styles/colors' +import fontStyles from '@celo/react-components/styles/fonts' +import variables from '@celo/react-components/styles/variables' +import * as React from 'react' +import { StyleSheet, Text, View, ViewStyle } from 'react-native' +import { BoxShadow } from 'react-native-shadow' +import RNCarousel, { Pagination } from 'react-native-snap-carousel' + +const ITEM_WIDTH = variables.width - 70 +const ITEM_HEIGHT = 250 + +interface OwnProps { + containerStyle: ViewStyle + items: CarouselItem[] +} + +export interface CarouselItem { + text: string + icon?: React.ComponentType +} + +function renderItem({ item, index }: { item: CarouselItem; index: number }) { + return ( + + + + {item.icon} + {item.text} + + + + ) +} + +export function Carousel(props: OwnProps) { + const ref = React.useRef(null) + const [activeItem, setActiveItem] = React.useState(0) + + return ( + + {/* For some reason the carousel is adding a bunch of item height, wrapping to cut it off*/} + + + + + + ) +} + +const shadowOpt = { + width: ITEM_WIDTH, + height: ITEM_HEIGHT, + color: '#6b7b8b', + opacity: 0.03, + border: 1, + radius: 12, + x: 0, + y: 0, + style: { + padding: 3, + }, +} + +const styles = StyleSheet.create({ + itemContainer: { + backgroundColor: '#FFFFFF', + borderWidth: 2, + borderColor: 'rgba(255, 255, 255, 0.5)', + borderRadius: 12, + width: ITEM_WIDTH - 6, + height: ITEM_HEIGHT - 6, + alignItems: 'center', + justifyContent: 'center', + }, + itemText: { + ...fontStyles.bodyLarge, + }, + paginationContainer: { + marginVertical: 10, + }, + paginationDot: {}, +}) + +export default React.memo(Carousel) diff --git a/packages/mobile/src/navigator/Navigator.tsx b/packages/mobile/src/navigator/Navigator.tsx index 3dbbfb801cb..4c0022663c6 100644 --- a/packages/mobile/src/navigator/Navigator.tsx +++ b/packages/mobile/src/navigator/Navigator.tsx @@ -62,7 +62,7 @@ import SendAmount from 'src/send/SendAmount' import SendConfirmation from 'src/send/SendConfirmation' import SetClock from 'src/set-clock/SetClock' import TransactionReviewScreen from 'src/transactions/TransactionReviewScreen' -import VerifyInput from 'src/verify/Input' +import VerificationLoadingScreen from 'src/verify/VerificationLoadingScreen' import VerifyVerified from 'src/verify/Verified' import VerifyVerifying from 'src/verify/Verifying' import VerifyEducation from 'src/verify/VerifyPhoneEducation' @@ -113,7 +113,7 @@ const NuxStack = createStackNavigator( [Screens.ImportWalletEmpty]: { screen: ImportWalletEmpty }, [Screens.ImportContacts]: { screen: ImportContacts }, [Screens.VerifyEducation]: { screen: VerifyEducation }, - [Screens.VerifyInput]: { screen: VerifyInput }, + [Screens.VerificationLoadingScreen]: { screen: VerificationLoadingScreen }, [Screens.VerifyVerifying]: { screen: VerifyVerifying }, [Screens.VerifyVerified]: { screen: VerifyVerified }, ...commonScreens, diff --git a/packages/mobile/src/navigator/Screens.tsx b/packages/mobile/src/navigator/Screens.tsx index a6a7718a9b3..e680e1f602f 100644 --- a/packages/mobile/src/navigator/Screens.tsx +++ b/packages/mobile/src/navigator/Screens.tsx @@ -65,8 +65,8 @@ export enum Screens { TransactionReview = 'TransactionReview', UpgradeScreen = 'UpgradeScreen', VerifyEducation = 'VerifyEducation', - VerifyInput = 'VerifyInput', VerifyVerified = 'VerifyVerified', VerifyVerifying = 'VerifyVerifying', + VerificationLoadingScreen = 'VerificationLoadingScreen', WalletHome = 'WalletHome', } diff --git a/packages/mobile/src/verify/Input.tsx b/packages/mobile/src/verify/Input.tsx deleted file mode 100644 index 7150dcc7898..00000000000 --- a/packages/mobile/src/verify/Input.tsx +++ /dev/null @@ -1,188 +0,0 @@ -import Button, { BtnTypes } from '@celo/react-components/components/Button' -import PhoneNumberInput from '@celo/react-components/components/PhoneNumberInput' -import colors from '@celo/react-components/styles/colors' -import { fontStyles } from '@celo/react-components/styles/fonts' -import { isE164Number } from '@celo/utils/src/phoneNumbers' -import * as React from 'react' -import { WithNamespaces, withNamespaces } from 'react-i18next' -import { Platform, ScrollView, StyleSheet, Text, View } from 'react-native' -import { connect } from 'react-redux' -import { setPhoneNumber } from 'src/account/actions' -import { hideAlert, showError } from 'src/alert/actions' -import componentWithAnalytics from 'src/analytics/wrapper' -import { ErrorMessages } from 'src/app/ErrorMessages' -import DevSkipButton from 'src/components/DevSkipButton' -import { DEFAULT_COUNTRY } from 'src/config' -import NuxLogo from 'src/icons/NuxLogo' -import { startVerification } from 'src/identity/actions' -import { navigate } from 'src/navigator/NavigationService' -import { Screens } from 'src/navigator/Screens' -import { RootState } from 'src/redux/reducers' -import DisconnectBanner from 'src/shared/DisconnectBanner' - -interface StateProps { - devModeActive: boolean -} - -interface DispatchProps { - setPhoneNumber: typeof setPhoneNumber - showError: typeof showError - hideAlert: typeof hideAlert - startVerification: typeof startVerification -} - -type Props = StateProps & DispatchProps & WithNamespaces - -interface State { - e164Number: string - countryCode: string - isValidNumber: boolean -} - -const mapDispatchToProps = { - setPhoneNumber, - showError, - hideAlert, - startVerification, -} - -const mapStateToProps = (state: RootState): StateProps => { - return { - devModeActive: state.account.devModeActive || false, - } -} - -export class Input extends React.Component { - state = { - e164Number: '', - countryCode: '', - isValidNumber: false, - } - - scrollView = React.createRef() - - onInputChange = () => { - this.props.hideAlert() - } - - setE164Number = (e164Number: string) => { - this.setState({ - e164Number, - }) - } - - setCountryCode = (countryCode: string) => { - this.setState({ - countryCode, - }) - } - - setIsValidNumber = (isValidNumber: boolean) => { - this.setState({ - isValidNumber, - }) - } - - onSubmit = async () => { - const { e164Number, countryCode, isValidNumber } = this.state - if (!e164Number || !isValidNumber || !isE164Number(e164Number)) { - this.props.showError(ErrorMessages.INVALID_PHONE_NUMBER) - return - } - - this.props.setPhoneNumber(e164Number, countryCode) - this.props.startVerification() - - navigate(Screens.VerifyVerifying) - } - - scrollToEnd = () => { - // (Rossy): This does not work without a setTimeout. - // I believe the animation of the keyboard showing is the problem - setTimeout(() => { - if (this.scrollView && this.scrollView.current) { - this.scrollView.current.scrollToEnd() - } - }, 1000) - } - - render() { - const { t, lng } = this.props - // This locks the country code - const defaultCountry = this.props.devModeActive ? null : DEFAULT_COUNTRY - - return ( - - - - - - {t('enterPhoneToVerify')} - - - - -