diff --git a/.storybook/storybook.requires.js b/.storybook/storybook.requires.js index 3cf9b0ebd..2141f88bc 100644 --- a/.storybook/storybook.requires.js +++ b/.storybook/storybook.requires.js @@ -54,7 +54,6 @@ const getStories = () => { "./app/components/set-lightning-address-modal/set-lightning-address-modal.stories.tsx": require("../app/components/set-lightning-address-modal/set-lightning-address-modal.stories.tsx"), "./app/components/totp-export/totp-copy.stories.tsx": require("../app/components/totp-export/totp-copy.stories.tsx"), "./app/components/totp-export/totp-qr.stories.tsx": require("../app/components/totp-export/totp-qr.stories.tsx"), - "./app/components/upgrade-account-modal/upgrade-account-modal.stories.tsx": require("../app/components/upgrade-account-modal/upgrade-account-modal.stories.tsx"), "./app/components/wallet-overview/wallet-overview.stories.tsx": require("../app/components/wallet-overview/wallet-overview.stories.tsx"), "./app/components/wallet-summary/wallet-summary.stories.tsx": require("../app/components/wallet-summary/wallet-summary.stories.tsx"), "./app/rne-theme/colors.stories.tsx": require("../app/rne-theme/colors.stories.tsx"), diff --git a/app/app.tsx b/app/app.tsx index 8f75beef2..5628576b9 100644 --- a/app/app.tsx +++ b/app/app.tsx @@ -37,7 +37,7 @@ import { FeatureFlagContextProvider } from "./config/feature-flags-context" import "./utils/logs" import { GestureHandlerRootView } from "react-native-gesture-handler" import { Provider } from "react-redux" -import { store } from "./store/redux" +import { persistor, store } from "./store/redux" import PolyfillCrypto from "react-native-webview-crypto" import { ActivityIndicatorProvider } from "./contexts/ActivityIndicatorContext" import { BreezProvider } from "./contexts/BreezContext" @@ -46,6 +46,7 @@ import { NotificationsProvider } from "./components/notification" import { SafeAreaProvider } from "react-native-safe-area-context" import { FlashcardProvider } from "./contexts/Flashcard" import { NostrGroupChatProvider } from "./screens/chat/GroupChat/GroupChatProvider" +import { PersistGate } from "redux-persist/integration/react" import { useEffect } from "react" import { nostrRuntime } from "./nostr/runtime/NostrRuntime" import { AppState } from "react-native" @@ -87,14 +88,15 @@ export const App = () => { - - - - + + + + + @@ -122,11 +124,12 @@ export const App = () => { - - - - - + + + + + + ) diff --git a/app/components/account-upgrade-flow/AddressField.tsx b/app/components/account-upgrade-flow/AddressField.tsx new file mode 100644 index 000000000..023951b00 --- /dev/null +++ b/app/components/account-upgrade-flow/AddressField.tsx @@ -0,0 +1,136 @@ +import React, { useEffect, useRef, useState } from "react" +import { Modal, Platform, TouchableOpacity, View } from "react-native" +import { makeStyles, Text, useTheme } from "@rneui/themed" +import { + GooglePlaceData, + GooglePlaceDetail, + GooglePlacesAutocomplete, + GooglePlacesAutocompleteRef, +} from "react-native-google-places-autocomplete" +import { useSafeAreaInsets } from "react-native-safe-area-context" + +// components +import { PrimaryBtn } from "../buttons" + +// env +import { GOOGLE_PLACE_API_KEY } from "@env" + +type Props = { + label: string + placeholder: string + value?: string + errorMsg?: string + onAddressSelect: (data: GooglePlaceData, details: GooglePlaceDetail | null) => void +} + +const AddressField: React.FC = ({ + label, + placeholder, + value, + errorMsg, + onAddressSelect, +}) => { + const styles = useStyles() + const { colors } = useTheme().theme + const { bottom, top } = useSafeAreaInsets() + + const ref = useRef(null) + const [isFocused, setIsFocused] = useState(false) + const [isVisible, setIsVisible] = useState(false) + + useEffect(() => { + if (isVisible && ref.current) { + ref.current.focus() + } + }, [isVisible, ref.current]) + + return ( + + + {label} + + setIsVisible(true)}> + + {!!value ? value : placeholder} + + + {!!errorMsg && ( + + {errorMsg} + + )} + setIsVisible(false)} + > + + console.log("Google places auto complete", err)} + onNotFound={() => console.log("Google places auto complete not found")} + fetchDetails={true} + onPress={(data, details) => { + setIsVisible(false) + onAddressSelect(data, details) + }} + query={{ + key: GOOGLE_PLACE_API_KEY, + language: "en", + }} + styles={{ + textInput: [ + styles.googlePlace, + isFocused ? { borderColor: colors.primary } : {}, + ], + }} + textInputProps={{ + onFocus: () => setIsFocused(true), + onBlur: () => setIsFocused(false), + }} + /> + setIsVisible(false)} /> + + + + ) +} + +export default AddressField + +const useStyles = makeStyles(({ colors }) => ({ + container: { + marginBottom: 15, + }, + input: { + paddingHorizontal: 15, + paddingVertical: 20, + marginTop: 5, + marginBottom: 2, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + }, + modal: { + flex: 1, + backgroundColor: colors.white, + paddingHorizontal: 20, + }, + googlePlace: { + height: Platform.OS === "ios" ? 51 : 60, + paddingHorizontal: 15, + padding: 20, + marginTop: 5, + marginBottom: 15, + borderWidth: 1, + borderRadius: 10, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + fontSize: 16, + fontFamily: "Sora-Regular", + }, +})) diff --git a/app/components/account-upgrade-flow/CheckBoxField.tsx b/app/components/account-upgrade-flow/CheckBoxField.tsx new file mode 100644 index 000000000..f17c6c940 --- /dev/null +++ b/app/components/account-upgrade-flow/CheckBoxField.tsx @@ -0,0 +1,58 @@ +import React, { useState } from "react" +import { View, TouchableOpacity } from "react-native" +import { Icon, makeStyles, Text, useTheme } from "@rneui/themed" +import Tooltip from "react-native-walkthrough-tooltip" +import { useI18nContext } from "@app/i18n/i18n-react" + +type Props = { + isChecked?: boolean + onCheck: () => void +} + +const CheckBoxField: React.FC = ({ isChecked, onCheck }) => { + const styles = useStyles() + const { colors } = useTheme().theme + const { LL } = useI18nContext() + + const [tooltipVisible, setTooltipVisible] = useState(false) + + return ( + + + + {LL.AccountUpgrade.flashTerminal()} + + {LL.AccountUpgrade.flashTerminalTooltip()}} + placement="top" + onClose={() => setTooltipVisible(false)} + > + setTooltipVisible(true)}> + + + + + ) +} + +export default CheckBoxField + +const useStyles = makeStyles(() => ({ + container: { + flexDirection: "row", + alignItems: "center", + }, +})) diff --git a/app/components/account-upgrade-flow/DropDownField.tsx b/app/components/account-upgrade-flow/DropDownField.tsx new file mode 100644 index 000000000..d4a58fb04 --- /dev/null +++ b/app/components/account-upgrade-flow/DropDownField.tsx @@ -0,0 +1,81 @@ +import React from "react" +import { View } from "react-native" +import { makeStyles, Text, useTheme } from "@rneui/themed" +import { Dropdown } from "react-native-element-dropdown" +import { useI18nContext } from "@app/i18n/i18n-react" + +type Props = { + label: string + placeholder: string + data: any[] + value: string + errorMsg?: string + isOptional?: boolean + onChange: (val: string) => void +} + +const DropDownField: React.FC = ({ + label, + placeholder, + data, + value, + errorMsg, + isOptional, + onChange, +}) => { + const styles = useStyles() + const { colors } = useTheme().theme + const { LL } = useI18nContext() + + return ( + + + {label} + {isOptional && ( + + {LL.AccountUpgrade.optional()} + + )} + + onChange(item.value)} + /> + {!!errorMsg && ( + + {errorMsg} + + )} + + ) +} + +export default DropDownField + +const useStyles = makeStyles(({ colors }) => ({ + wrapper: { + marginBottom: 15, + }, + dropdown: { + padding: 15, + marginTop: 5, + marginBottom: 2, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + fontSize: 16, + fontFamily: "Sora-Regular", + }, + container: { + marginTop: 5, + }, +})) diff --git a/app/components/account-upgrade-flow/InputField.tsx b/app/components/account-upgrade-flow/InputField.tsx new file mode 100644 index 000000000..e804856d3 --- /dev/null +++ b/app/components/account-upgrade-flow/InputField.tsx @@ -0,0 +1,77 @@ +import React, { useState } from "react" +import { makeStyles, Text, useTheme } from "@rneui/themed" +import { TextInput, TextInputProps, View } from "react-native" +import { useI18nContext } from "@app/i18n/i18n-react" + +type Props = { + label: string + errorMsg?: string + isOptional?: boolean +} & TextInputProps + +const InputField: React.FC = ({ + label, + errorMsg, + isOptional, + placeholder, + value, + editable, + autoCapitalize, + keyboardType, + onChangeText, +}) => { + const styles = useStyles() + const { colors } = useTheme().theme + const { LL } = useI18nContext() + + const [isFocused, setIsFocused] = useState(false) + + return ( + + + {label} + {isOptional && ( + + {LL.AccountUpgrade.optional()} + + )} + + setIsFocused(true)} + onBlur={() => setIsFocused(false)} + autoCapitalize={autoCapitalize} + keyboardType={keyboardType} + /> + {!!errorMsg && ( + + {errorMsg} + + )} + + ) +} + +export default InputField + +const useStyles = makeStyles(({ colors }) => ({ + container: { + marginBottom: 15, + }, + input: { + padding: 15, + marginTop: 5, + marginBottom: 2, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + fontSize: 16, + fontFamily: "Sora-Regular", + }, +})) diff --git a/app/components/account-upgrade-flow/PhoneNumber.tsx b/app/components/account-upgrade-flow/PhoneNumber.tsx new file mode 100644 index 000000000..7fa6f2b3e --- /dev/null +++ b/app/components/account-upgrade-flow/PhoneNumber.tsx @@ -0,0 +1,139 @@ +import React, { useState } from "react" +import { TextInput, View } from "react-native" +import { makeStyles, useTheme, Text } from "@rneui/themed" +import { TouchableOpacity } from "react-native-gesture-handler" +import { FlagButtonProps } from "react-native-country-picker-modal/lib/FlagButton" +import { + CountryCode as PhoneNumberCountryCode, + getCountryCallingCode, +} from "libphonenumber-js/mobile" +import CountryPicker, { + CountryCode, + DARK_THEME, + DEFAULT_THEME, + Flag, +} from "react-native-country-picker-modal" + +// hooks +import { useI18nContext } from "@app/i18n/i18n-react" + +type Props = { + countryCode?: string + phoneNumber?: string + errorMsg?: string + disabled?: boolean + supportedCountries: CountryCode[] + setPhoneNumber: (number: string) => void + setCountryCode: (countryCode: PhoneNumberCountryCode) => void +} + +const PhoneNumber: React.FC = ({ + countryCode, + phoneNumber, + errorMsg, + disabled, + supportedCountries, + setPhoneNumber, + setCountryCode, +}) => { + const styles = useStyles() + const { mode, colors } = useTheme().theme + const { LL } = useI18nContext() + + const [isFocused, setIsFocused] = useState(false) + + const renderCountryCode = ({ countryCode, onOpen }: FlagButtonProps) => { + return ( + countryCode && ( + + + + +{getCountryCallingCode(countryCode as PhoneNumberCountryCode)} + + + ) + ) + } + + return ( + + + {LL.AccountUpgrade.phoneNumber()} + + + setCountryCode(country.cca2 as PhoneNumberCountryCode)} + renderFlagButton={renderCountryCode} + withCallingCodeButton={true} + withFilter={true} + filterProps={{ autoFocus: true }} + withCallingCode={true} + /> + setIsFocused(true)} + onBlur={() => setIsFocused(false)} + /> + + {!!errorMsg && ( + + {errorMsg} + + )} + + ) +} + +export default PhoneNumber + +const useStyles = makeStyles(({ colors }) => ({ + wrapper: { + marginBottom: 15, + }, + container: { + flexDirection: "row", + marginTop: 5, + marginBottom: 2, + }, + countryPicker: { + flex: 1, + paddingHorizontal: 15, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + flexDirection: "row", + alignItems: "center", + }, + input: { + flex: 1, + padding: 15, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + fontSize: 16, + fontFamily: "Sora-Regular", + marginLeft: 10, + }, +})) diff --git a/app/components/account-upgrade-flow/PhotoUploadField.tsx b/app/components/account-upgrade-flow/PhotoUploadField.tsx new file mode 100644 index 000000000..8e1fbb41f --- /dev/null +++ b/app/components/account-upgrade-flow/PhotoUploadField.tsx @@ -0,0 +1,284 @@ +import React, { useCallback, useEffect, useRef, useState } from "react" +import { Alert, Image, Linking, Modal, TouchableOpacity, View } from "react-native" +import { Icon, makeStyles, Text, useTheme } from "@rneui/themed" +import { Asset, launchImageLibrary } from "react-native-image-picker" +import { + Camera, + CameraRuntimeError, + useCameraDevice, + useCameraPermission, +} from "react-native-vision-camera" + +// component +import { Screen } from "../screen" +import { PrimaryBtn } from "../buttons" + +// hooks +import { useI18nContext } from "@app/i18n/i18n-react" +import { useSafeAreaInsets } from "react-native-safe-area-context" + +// assets +import PhotoAdd from "@app/assets/icons/photo-add.svg" + +// utils +import { toastShow } from "@app/utils/toast" + +const MAX_FILE_SIZE = 5 * 1024 * 1024 // File size limit in bytes (5MB) +const ALLOWED_FILE_TYPES = ["image/jpeg", "image/png", "image/jpg", "image/heic"] + +type Props = { + label: string + photo?: Asset + errorMsg?: string + isOptional?: boolean + onPhotoUpload: (val: Asset) => void + setErrorMsg: (val: string) => void +} + +const PhotoUploadField: React.FC = ({ + label, + photo, + errorMsg, + isOptional, + onPhotoUpload, + setErrorMsg, +}) => { + const styles = useStyles() + const { colors } = useTheme().theme + const { LL } = useI18nContext() + const { top, bottom } = useSafeAreaInsets() + + const { hasPermission, requestPermission } = useCameraPermission() + const device = useCameraDevice("back", { + physicalDevices: ["wide-angle-camera", "telephoto-camera"], + }) + + const camera = useRef(null) + const [isCameraVisible, setIsCameraVisible] = useState(false) + + useEffect(() => { + if (!hasPermission) { + requestPermission() + } + }, [hasPermission, requestPermission]) + + const openSettings = () => { + Linking.openSettings().catch(() => { + Alert.alert(LL.ScanningQRCodeScreen.unableToOpenSettings()) + }) + } + + const onError = useCallback((error: CameraRuntimeError) => { + console.error(error) + }, []) + + const showImagePicker = async () => { + try { + const result = await launchImageLibrary({ mediaType: "photo" }) + setIsCameraVisible(false) + if (result.errorCode === "permission") { + toastShow({ + message: (translations) => + translations.ScanningQRCodeScreen.imageLibraryPermissionsNotGranted(), + }) + } + if ( + result.assets && + result.assets.length > 0 && + result.assets[0].uri && + result.assets[0].type && + result.assets[0].fileSize + ) { + if (!ALLOWED_FILE_TYPES.includes(result.assets[0].type)) { + setErrorMsg("Please upload a valid image (JPG, PNG, or HEIC)") + } else if (result?.assets[0]?.fileSize > MAX_FILE_SIZE) { + setErrorMsg("File size exceeds 5MB limit") + } else { + onPhotoUpload(result.assets[0]) + } + } + } catch (err: unknown) { + console.log("Image Picker Error: ", err) + } + } + + const takePhoto = async () => { + try { + const file = await camera?.current?.takePhoto() + setIsCameraVisible(false) + + if (file) { + const result = await fetch(`file://${file?.path}`) + const data = await result.blob() + + if (!ALLOWED_FILE_TYPES.includes(data.type)) { + setErrorMsg("Please upload a valid image (JPG, PNG, or HEIC)") + } else if (data.size > MAX_FILE_SIZE) { + setErrorMsg("File size exceeds 5MB limit") + } else { + onPhotoUpload({ + uri: `file://${file?.path}`, + type: data.type, + fileSize: data.size, + fileName: file.path.split("/").pop(), + }) + } + } + } catch (err) { + console.log("Take Photo Error", err) + } + } + + return ( + + + {label} + {isOptional && ( + + {LL.AccountUpgrade.optional()} + + )} + + setIsCameraVisible(true)}> + {!!photo && } + + + {!!errorMsg && ( + + {errorMsg} + + )} + setIsCameraVisible(false)} + > + + + setIsCameraVisible(false)} + > + + + + {!hasPermission ? ( + <> + + + {LL.ScanningQRCodeScreen.permissionCamera()} + + + + + ) : device === null || device === undefined ? ( + + {LL.ScanningQRCodeScreen.noCamera()} + + ) : ( + + + + + + + + + )} + + + + + + + + + ) +} + +export default PhotoUploadField + +const useStyles = makeStyles(({ colors }) => ({ + wrapper: { + marginBottom: 15, + }, + container: { + width: "100%", + height: 150, + alignItems: "center", + justifyContent: "center", + marginTop: 5, + marginBottom: 2, + borderRadius: 10, + borderWidth: 1, + borderColor: colors.grey4, + backgroundColor: colors.grey5, + overflow: "hidden", + }, + img: { + position: "absolute", + width: "100%", + height: "100%", + }, + caption: { + textAlign: "center", + marginHorizontal: 30, + marginBottom: 10, + color: colors._orange, + }, + row: { + flexDirection: "row", + justifyContent: "flex-end", + backgroundColor: "#000", + }, + close: { + paddingHorizontal: 20, + paddingVertical: 10, + }, + center: { + flex: 1, + alignItems: "center", + justifyContent: "center", + }, + camera: { + flex: 1, + }, + captureWrapper: { + position: "absolute", + width: "100%", + alignItems: "center", + bottom: 20, + }, + captureOutline: { + borderWidth: 3, + borderRadius: 100, + borderColor: "#fff", + padding: 5, + }, + capture: { + width: 50, + height: 50, + borderRadius: 100, + backgroundColor: "#FFF", + }, + permissionMissingText: { + width: "80%", + textAlign: "center", + }, + photoLibrary: { + padding: 20, + }, +})) diff --git a/app/components/account-upgrade-flow/ProgressSteps.tsx b/app/components/account-upgrade-flow/ProgressSteps.tsx new file mode 100644 index 000000000..e252cf0c9 --- /dev/null +++ b/app/components/account-upgrade-flow/ProgressSteps.tsx @@ -0,0 +1,90 @@ +import React from "react" +import { View } from "react-native" +import { Icon, makeStyles, Text, useTheme } from "@rneui/themed" + +type Props = { + numOfSteps: number + currentStep: number +} + +const ProgressSteps: React.FC = ({ numOfSteps, currentStep }) => { + const styles = useStyles() + const { colors } = useTheme().theme + + const renderStep = (i: number) => { + if (currentStep === i + 1) { + return ( + + + {i + 1} + + + ) + } else if (currentStep > i + 1) { + return ( + + ) + } else { + return ( + + + {i + 1} + + + ) + } + } + + return ( + + {Array(numOfSteps) + .fill(0) + .map((_, i) => ( + <> + {renderStep(i)} + {i + 1 < numOfSteps && ( + + )} + + ))} + + ) +} + +export default ProgressSteps + +const useStyles = makeStyles(({ colors }) => ({ + wrapper: { + flexDirection: "row", + alignItems: "center", + marginHorizontal: 20, + marginVertical: 10, + }, + separator: { + flex: 1, + height: 3, + backgroundColor: colors._lightBlue, + marginHorizontal: 5, + }, + step: { + width: 35, + height: 35, + alignItems: "center", + justifyContent: "center", + borderRadius: 1000, + borderWidth: 2, + borderColor: colors.grey2, + }, + currentStep: { + backgroundColor: colors._lightBlue, + borderColor: colors._borderBlue, + }, + currentStepText: { + color: "#fff", + }, +})) diff --git a/app/components/account-upgrade-flow/index.ts b/app/components/account-upgrade-flow/index.ts new file mode 100644 index 000000000..68a7decf6 --- /dev/null +++ b/app/components/account-upgrade-flow/index.ts @@ -0,0 +1,17 @@ +import PhoneNumber from "./PhoneNumber" +import InputField from "./InputField" +import DropDownField from "./DropDownField" +import PhotoUploadField from "./PhotoUploadField" +import AddressField from "./AddressField" +import ProgressSteps from "./ProgressSteps" +import CheckBoxField from "./CheckBoxField" + +export { + PhoneNumber, + InputField, + DropDownField, + PhotoUploadField, + AddressField, + ProgressSteps, + CheckBoxField, +} diff --git a/app/components/home-screen/QuickStart.tsx b/app/components/home-screen/QuickStart.tsx index aad7936de..e6c3bf9a6 100644 --- a/app/components/home-screen/QuickStart.tsx +++ b/app/components/home-screen/QuickStart.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useRef, useState } from "react" +import { RootStackParamList } from "@app/navigation/stack-param-lists" import { Dimensions, Linking, TouchableOpacity, View } from "react-native" +import { Icon, makeStyles, Text, useTheme } from "@rneui/themed" import { StackNavigationProp } from "@react-navigation/stack" import Carousel from "react-native-reanimated-carousel" -import { Icon, makeStyles, Text, useTheme } from "@rneui/themed" -import { RootStackParamList } from "@app/navigation/stack-param-lists" import * as Keychain from "react-native-keychain" // assets @@ -16,10 +16,11 @@ import SecureWallet from "@app/assets/illustrations/secure-wallet.svg" import SocialChat from "@app/assets/illustrations/social-chat.svg" // components -import { UpgradeAccountModal } from "../upgrade-account-modal" import { AdvancedModeModal } from "../advanced-mode-modal" // hooks +import { useAccountUpgrade } from "@app/hooks" +import { useAppSelector } from "@app/store/redux" import { useI18nContext } from "@app/i18n/i18n-react" import { useNavigation } from "@react-navigation/native" import { usePersistentStateContext } from "@app/store/persistent-state" @@ -36,6 +37,8 @@ type RenderItemProps = { title: string description: string image: any + pending?: boolean + disabled?: boolean onPress: () => void } index: number @@ -47,14 +50,16 @@ const QuickStart = () => { const { colors } = useTheme().theme const { LL } = useI18nContext() const { persistentState, updateState } = usePersistentStateContext() + const { status } = useAppSelector((state) => state.accountUpgrade) const ref = useRef(null) const [advanceModalVisible, setAdvanceModalVisible] = useState(false) - const [upgradeAccountModalVisible, setUpgradeAccountModalVisible] = useState(false) const [hasRecoveryPhrase, setHasRecoveryPhrase] = useState(false) const { data, loading } = useHomeAuthedQuery() + useAccountUpgrade() + useEffect(() => { checkRecoveryPhrase() }, []) @@ -64,13 +69,21 @@ const QuickStart = () => { if (credentials) setHasRecoveryPhrase(true) } + const upgradePending = status === "Pending" + let carouselData = [ { type: "upgrade", - title: LL.HomeScreen.upgradeTitle(), - description: LL.HomeScreen.upgradeDesc(), + title: !upgradePending + ? LL.HomeScreen.upgradeTitle() + : LL.HomeScreen.upgradeTitlePending(), + description: !upgradePending + ? LL.HomeScreen.upgradeDesc() + : LL.HomeScreen.upgradePendingDesc(), image: Account, - onPress: () => setUpgradeAccountModalVisible(true), + pending: upgradePending, + disabled: upgradePending, + onPress: () => navigation.navigate("AccountType"), }, { type: "currency", @@ -129,7 +142,7 @@ const QuickStart = () => { ] if ( - data?.me?.defaultAccount.level !== AccountLevel.Zero || + data?.me?.defaultAccount.level === AccountLevel.Three || persistentState?.closedQuickStartTypes?.includes("upgrade") ) { carouselData = carouselData.filter((el) => el.type !== "upgrade") @@ -194,17 +207,31 @@ const QuickStart = () => { const renderItem = ({ item, index }: RenderItemProps) => { const Image = item.image return ( - + - + {item.title} {item.description} - onHide(item.type)}> - - + {!item.pending && ( + onHide(item.type)}> + + + )} ) } @@ -222,10 +249,6 @@ const QuickStart = () => { loop={carouselData.length !== 1} containerStyle={{ marginTop: 10 }} /> - setUpgradeAccountModalVisible(false)} - /> ( - - {Story()} - - ), - ], -} as Meta - -export const Default = () => { - const [isVisible, setIsVisible] = React.useState(true) - return ( - -