import { useCallback, useEffect, useRef, useState } from "react"; import { Animated, Dimensions, Easing, KeyboardAvoidingView, Modal, Pressable, StyleSheet, View, } from "react-native"; import { parseTheme } from "../../../core/design-system/CustomThemeProvider.js"; import { useSiweAuth } from "../../../core/hooks/auth/useSiweAuth.js"; import type { ConnectButtonProps } from "../../../core/hooks/connection/ConnectButtonProps.js"; import { useActiveAccount } from "../../../core/hooks/wallets/useActiveAccount.js"; import { useActiveWallet } from "../../../core/hooks/wallets/useActiveWallet.js"; import { useActiveWalletConnectionStatus } from "../../../core/hooks/wallets/useActiveWalletConnectionStatus.js"; import { useConnectionManager } from "../../../core/providers/connection-manager.js"; import { getDefaultWallets } from "../../wallets/defaultWallets.js"; import { AutoConnect } from "../AutoConnect/AutoConnect.js"; import { ThemedButton } from "../components/button.js"; import { ThemedSpinner } from "../components/spinner.js"; import { ThemedText } from "../components/text.js"; import { ConnectedButton } from "./ConnectedButton.js"; import { ConnectedModal } from "./ConnectedModal.js"; import { ConnectModal } from "./ConnectModal.js"; /** * A component that allows the user to connect their wallet. * It renders a button which when clicked opens a modal to allow users to connect to wallets specified in `wallets` prop. * @example * ```tsx * * ``` * @param props * Props for the `ConnectButton` component * * Refer to [ConnectButtonProps](https://portal.thirdweb.com/references/typescript/v5/ConnectButtonProps) to see the available props. * @component */ export function ConnectButton(props: ConnectButtonProps) { const theme = parseTheme(props.theme); const [visible, setVisible] = useState(false); const wallet = useActiveWallet(); const account = useActiveAccount(); const status = useActiveWalletConnectionStatus(); const connectionManager = useConnectionManager(); const siweAuth = useSiweAuth(wallet, account, props.auth); const fadeAnim = useRef(new Animated.Value(0)); // For background opacity const slideAnim = useRef(new Animated.Value(screenHeight)); // For bottom sheet position const openModal = useCallback(() => { setVisible(true); Animated.parallel([ Animated.timing(fadeAnim.current, { duration: 300, toValue: 1, useNativeDriver: true, }), Animated.timing(slideAnim.current, { duration: 300, easing: Easing.out(Easing.exp), toValue: 0, useNativeDriver: true, }), ]).start(); }, []); // Add props.chain and props.chains to defined chains store useEffect(() => { if (props.chain) { connectionManager.defineChains([props.chain]); } }, [props.chain, connectionManager]); useEffect(() => { if (props.chains) { connectionManager.defineChains(props.chains); } }, [props.chains, connectionManager]); const closeModal = useCallback(() => { Animated.parallel([ Animated.timing(fadeAnim.current, { duration: 300, toValue: 0, useNativeDriver: true, }), Animated.timing(slideAnim.current, { duration: 300, easing: Easing.in(Easing.exp), toValue: screenHeight, useNativeDriver: true, }), ]).start(() => { setVisible(false); fadeAnim.current.setValue(0); slideAnim.current.setValue(screenHeight); }); }, []); const needsAuth = siweAuth.requiresAuth && !siweAuth.isLoggedIn; const isConnected = wallet && account; const isConnectedAndNotAuth = isConnected && needsAuth; const isConnectedAndAuth = isConnected && !needsAuth; const wallets = props.wallets || getDefaultWallets(props); const autoConnectComp = props.autoConnect !== false && ( ); return ( {isConnectedAndAuth ? ( openModal()} wallet={wallet} {...props} /> ) : ( openModal()} theme={theme}> {status === "connecting" || siweAuth.isLoggingIn || siweAuth.isLoading || siweAuth.isLoggingOut ? ( ) : ( {isConnectedAndNotAuth ? props.signInButton?.label || "Sign In" : props.connectButton?.label || "Connect Wallet"} )} )} {isConnectedAndAuth ? ( ) : ( )} {autoConnectComp} ); } const screenHeight = Dimensions.get("window").height; const modalHeight = 520; const screenWidth = Dimensions.get("window").width; const styles = StyleSheet.create({ bottomSheetContainer: { flexDirection: "column", height: modalHeight, width: screenWidth, }, dismissArea: { flex: 1, width: "100%", }, modalOverlay: { backgroundColor: "rgba(0,0,0,0.8)", height: screenHeight, position: "absolute", width: screenWidth, }, });