1import React from 'react'; 2import { View, TouchableOpacity, Text, Image } from 'react-native'; 3 4const statusToSubtitle: Record<string, string> = { 5 cancel: 'Cancelled', 6 dismiss: 'Cancelled', 7 error: 'Failed', 8 success: 'Success', 9}; 10 11const providers: Record<string, any> = { 12 facebook: { 13 name: 'Facebook', 14 image: 15 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/facebook.png?raw=true', 16 color: '#1877F2', 17 }, 18 imgur: { 19 name: 'Imgur', 20 image: 21 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/imgur.png?raw=true', 22 color: '#1BB76E', 23 }, 24 uber: { 25 name: 'Uber', 26 image: 27 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/uber.png?raw=true', 28 color: '#000', 29 }, 30 google: { 31 name: 'Google', 32 image: 33 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/google.png?raw=true', 34 color: '#4285F4', 35 }, 36 google_firebase: { 37 name: 'Google Firebase', 38 image: 39 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/google.png?raw=true', 40 color: '#4285F4', 41 }, 42 azure: { 43 name: 'Azure', 44 image: 45 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/azure.png?raw=true', 46 color: '#0089D6', 47 }, 48 fitbit: { 49 name: 'FitBit', 50 image: 51 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/fitbit.png?raw=true', 52 color: '#00B0B9', 53 }, 54 reddit: { 55 name: 'Reddit', 56 image: 57 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/reddit.png?raw=true', 58 color: '#FF4500', 59 }, 60 dropbox: { 61 name: 'Dropbox', 62 image: 63 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/dropbox.png?raw=true', 64 color: '#0061FF', 65 }, 66 coinbase: { 67 name: 'Coinbase', 68 image: 69 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/coinbase.png?raw=true', 70 color: '#0667D0', 71 }, 72 github: { 73 name: 'Github', 74 image: 75 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/github.png?raw=true', 76 color: '#181717', 77 }, 78 slack: { 79 name: 'Slack', 80 image: 81 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/slack.png?raw=true', 82 color: '#4A154B', 83 }, 84 spotify: { 85 name: 'Spotify', 86 image: 87 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/spotify.png?raw=true', 88 color: '#1ED760', 89 }, 90 strava: { 91 name: 'Strava', 92 image: 93 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/strava.png?raw=true', 94 color: '#FC4C02', 95 }, 96 twitch: { 97 name: 'Twitch', 98 image: 99 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/twitch.png?raw=true', 100 color: '#9146FF', 101 }, 102 okta: { 103 name: 'Okta', 104 image: 105 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/okta.png?raw=true', 106 color: '#007DC1', 107 }, 108 identity4: { 109 name: 'Identity 4', 110 image: 111 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/identity4.png?raw=true', 112 color: '#F78C40', 113 }, 114 beyondidentity: { 115 name: 'Beyond Identity', 116 image: 117 'https://github.com/expo/expo/blob/main/docs/public/static/images/sdk/auth-session/beyondidentity.png?raw=true', 118 color: '#4673D3', 119 }, 120}; 121 122function SocialImage({ image }: any) { 123 const size = 48; 124 return ( 125 <Image 126 style={{ 127 width: size, 128 height: size, 129 borderRadius: size / 2, 130 backgroundColor: 'white', 131 resizeMode: 'cover', 132 borderWidth: 1, 133 borderColor: 'white', 134 }} 135 source={image} 136 /> 137 ); 138} 139 140function Card({ style, ...props }: any) { 141 return ( 142 <TouchableOpacity 143 activeOpacity={0.6} 144 style={[ 145 { 146 backgroundColor: 'white', 147 paddingHorizontal: 12, 148 paddingVertical: 8, 149 borderRadius: 5, 150 flexDirection: 'row', 151 alignItems: 'center', 152 shadowColor: '#000', 153 shadowOffset: { 154 width: 0, 155 height: 2, 156 }, 157 shadowOpacity: 0.25, 158 shadowRadius: 3.84, 159 160 elevation: 5, 161 }, 162 style, 163 ]} 164 {...props} 165 /> 166 ); 167} 168 169export default function AuthCard({ 170 name, 171 disabled, 172 status = '', 173 url, 174 onPress, 175}: { 176 name: string; 177 url?: string | null; 178 disabled?: boolean; 179 status?: string; 180 onPress: (color: string) => void; 181}) { 182 const provider = providers[name]; 183 const subtitle = statusToSubtitle[status]; 184 185 return ( 186 <Card 187 disabled={disabled} 188 style={{ backgroundColor: provider.color, opacity: disabled ? 0.6 : 1 }} 189 onPress={() => onPress(provider.color)}> 190 <SocialImage image={{ uri: provider.image }} /> 191 <View style={{ marginLeft: 8 }}> 192 <Text style={{ fontWeight: 'bold', color: 'white' }}> 193 {disabled ? `${provider.name} is disabled` : `Sign In with ${provider.name}`} 194 </Text> 195 {subtitle && ( 196 <Text 197 style={{ 198 opacity: 0.9, 199 marginTop: 2, 200 fontSize: 14, 201 color: 'white', 202 }}> 203 {subtitle} 204 </Text> 205 )} 206 {url && ( 207 <Text 208 style={{ 209 opacity: 0.9, 210 marginTop: 2, 211 fontSize: 14, 212 color: 'white', 213 }}> 214 {url} 215 </Text> 216 )} 217 </View> 218 </Card> 219 ); 220} 221