Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto

change branding to 'sign in with your PDS'

+45 -27
+1 -1
app/auth/options.tsx
··· 34 }} 35 > 36 37 - <Text>Sign in with Bluesky</Text> 38 </Button> 39 </Link> 40 <Link href="/signup" className="text-secondary">
··· 34 }} 35 > 36 37 + <Text>Sign in with ATProto</Text> 38 </Button> 39 </Link> 40 <Link href="/signup" className="text-secondary">
+44 -26
app/login.tsx
··· 11 import { Text } from "@/components/ui/text"; 12 import { Button } from "@/components/ui/button"; 13 import { Icon } from "@/lib/icons/iconWithClassName"; 14 - import { Check, ChevronRight, AtSign } from "lucide-react-native"; 15 import { Input } from "@/components/ui/input"; 16 import { cn } from "@/lib/utils"; 17 import { Link, Stack, router } from "expo-router"; ··· 23 24 const LoginScreen = () => { 25 const [handle, setHandle] = useState(""); 26 const [isRedirecting, setIsRedirecting] = useState(false); 27 const [isLoading, setIsLoading] = useState(false); 28 ··· 30 31 const handleLogin = async () => { 32 if (!handle) { 33 - Alert.alert("Error", "Please enter your handle"); 34 return; 35 } 36 37 setIsLoading(true); 38 39 - let redirUrl = await getLoginUrl(handle.replace("@", "")); 40 - if (!redirUrl) { 41 - // TODO: better error handling lulw 42 - Alert.alert("Error", "Failed to get login URL"); 43 - return; 44 - } 45 - if (Platform.OS === "web") { 46 - // redirect to redir url page without authsession 47 - // shyould! redirect to /auth/callback 48 - router.navigate(redirUrl.toString()); 49 - 50 - } else { 51 - const res = await openAuthSessionAsync( 52 - redirUrl.toString(), 53 - "http://127.0.0.1:8081/login" 54 - ); 55 - if (res.type === "success") { 56 - const params = new URLSearchParams(res.url.split("?")[1]); 57 - await oauthCallback(params); 58 } 59 } 60 61 // try { ··· 107 }; 108 109 return ( 110 - <SafeAreaView className="flex-1"> 111 <Stack.Screen 112 options={{ 113 title: "Sign in", ··· 115 headerShown: false, 116 }} 117 /> 118 - <View className="flex-1 justify-center align-center p-8 gap-4 pb-32 max-w-screen-sm"> 119 <View className="flex items-center"> 120 <Icon icon={AtSign} className="color-bsky" name="at" size={64} /> 121 </View> 122 <Text className="text-3xl font-semibold text-center text-foreground"> 123 Sign in with your PDS 124 </Text> 125 - <Text className="text-sm font-serif-old text-muted-foreground"> 126 - Status: {status} 127 - </Text> 128 <View> 129 <Text className="text-sm text-muted-foreground">Handle</Text> 130 <Input 131 placeholder="alice.bsky.social" 132 value={handle} 133 onChangeText={setHandle} 134 autoCapitalize="none" 135 autoCorrect={false} 136 /> 137 </View> 138 <View className="flex flex-row justify-between items-center"> 139 <Link href="https://bsky.app/signup">
··· 11 import { Text } from "@/components/ui/text"; 12 import { Button } from "@/components/ui/button"; 13 import { Icon } from "@/lib/icons/iconWithClassName"; 14 + import { Check, ChevronRight, AtSign, AlertCircle } from "lucide-react-native"; 15 import { Input } from "@/components/ui/input"; 16 import { cn } from "@/lib/utils"; 17 import { Link, Stack, router } from "expo-router"; ··· 23 24 const LoginScreen = () => { 25 const [handle, setHandle] = useState(""); 26 + const [err, setErr] = useState<string | undefined>(); 27 const [isRedirecting, setIsRedirecting] = useState(false); 28 const [isLoading, setIsLoading] = useState(false); 29 ··· 31 32 const handleLogin = async () => { 33 if (!handle) { 34 + setErr("Please enter a handle"); 35 return; 36 } 37 38 setIsLoading(true); 39 40 + try { 41 + let redirUrl = await getLoginUrl(handle.replace("@", "")); 42 + if (!redirUrl) { 43 + // TODO: better error handling lulw 44 + throw new Error("Does not resolve to a DID"); 45 } 46 + setIsRedirecting(true); 47 + if (Platform.OS === "web") { 48 + // redirect to redir url page without authsession 49 + // shyould! redirect to /auth/callback 50 + router.navigate(redirUrl.toString()); 51 + } else { 52 + const res = await openAuthSessionAsync( 53 + redirUrl.toString(), 54 + "http://127.0.0.1:8081/login" 55 + ); 56 + if (res.type === "success") { 57 + const params = new URLSearchParams(res.url.split("?")[1]); 58 + await oauthCallback(params); 59 + } 60 + } 61 + } catch (e: any) { 62 + console.error(e); 63 + setErr(e.message); 64 + setIsLoading(false); 65 + setIsRedirecting(false); 66 + return; 67 } 68 69 // try { ··· 115 }; 116 117 return ( 118 + <SafeAreaView className="flex-1 flex items-center justify-center w-full"> 119 <Stack.Screen 120 options={{ 121 title: "Sign in", ··· 123 headerShown: false, 124 }} 125 /> 126 + <View className="flex-1 justify-center align-center p-8 gap-4 pb-32 max-w-screen-sm min-w-full"> 127 <View className="flex items-center"> 128 <Icon icon={AtSign} className="color-bsky" name="at" size={64} /> 129 </View> 130 <Text className="text-3xl font-semibold text-center text-foreground"> 131 Sign in with your PDS 132 </Text> 133 <View> 134 <Text className="text-sm text-muted-foreground">Handle</Text> 135 <Input 136 + className={err && `border-red-500 border-2`} 137 placeholder="alice.bsky.social" 138 value={handle} 139 onChangeText={setHandle} 140 autoCapitalize="none" 141 autoCorrect={false} 142 /> 143 + {err ? ( 144 + <Text className="text-red-500 justify-baseline mt-1 text-xs"> 145 + <Icon 146 + icon={AlertCircle} 147 + className="mr-1 inline -mt-0.5 text-xs" 148 + size={20} 149 + /> 150 + {err} 151 + </Text> 152 + ) : ( 153 + <View className="h-6" /> 154 + )} 155 </View> 156 <View className="flex flex-row justify-between items-center"> 157 <Link href="https://bsky.app/signup">