frontend client for gemstone. decentralised workplace app
1import { GmstnLogoColor } from "@/components/icons/gmstn/GmstnLogoColor";
2import { Text } from "@/components/primitives/Text";
3import { useFacet } from "@/lib/facet";
4import { lighten } from "@/lib/facet/src/lib/colors";
5import { useOAuthSetter, useOAuthValue } from "@/providers/OAuthProvider";
6import { useCurrentPalette } from "@/providers/ThemeProvider";
7import { Agent } from "@atproto/api";
8import { ArrowRight } from "lucide-react-native";
9import { useState } from "react";
10import { Pressable, TextInput, View } from "react-native";
11
12export const Login = () => {
13 const { semantic } = useCurrentPalette();
14 const { atoms, typography } = useFacet();
15 const [atprotoHandle, setAtprotoHandle] = useState("");
16 const oAuth = useOAuthValue();
17 const setOAuth = useOAuthSetter();
18 const providedOAuthClient = oAuth.client;
19
20 const handlePress = async () => {
21 const session = await providedOAuthClient.signIn(atprotoHandle);
22
23 const agent = new Agent(session);
24 setOAuth({
25 session,
26 agent,
27 client: providedOAuthClient,
28 isLoading: false,
29 });
30 };
31
32 const handleSubmit = () => {
33 handlePress()
34 .then()
35 .catch((e: unknown) => {
36 console.log(e);
37 });
38 };
39
40 return (
41 <View
42 style={{
43 flex: 1,
44 flexDirection: "column",
45 alignItems: "center",
46 justifyContent: "center",
47 gap: 16,
48 }}
49 >
50 <View style={{ alignItems: "center" }}>
51 <View style={{ padding: 8, paddingLeft: 12, paddingTop: 12 }}>
52 <GmstnLogoColor height={36} width={36} />
53 </View>
54 <Text
55 style={[
56 typography.sizes.xl,
57 typography.weights.byName.medium,
58 ]}
59 >
60 Gemstone
61 </Text>
62 </View>
63 <View style={{ gap: 10 }}>
64 <TextInput
65 style={[{
66 flex: 1,
67 borderWidth: 1,
68 borderColor: semantic.border,
69 borderRadius: atoms.radii.lg,
70 paddingHorizontal: 14,
71 paddingVertical: 12,
72 marginRight: 8,
73 fontSize: 16,
74 color: semantic.text
75 }, typography.weights.byName.light]}
76 value={atprotoHandle}
77 onChangeText={setAtprotoHandle}
78 placeholder="alice.bsky.social"
79 onSubmitEditing={handleSubmit}
80 placeholderTextColor={semantic.textPlaceholder}
81 />
82 <Pressable onPress={handleSubmit}>
83 {({ hovered }) => (
84 <View
85 style={{
86 backgroundColor: hovered
87 ? lighten(semantic.primary, 7)
88 : semantic.primary,
89 flexDirection: "row",
90 gap: 4,
91 alignItems: "center",
92 justifyContent: "center",
93 paddingVertical: 10,
94 borderRadius: atoms.radii.lg,
95 }}
96 >
97 <Text
98 style={[
99 { color: semantic.textInverse },
100 typography.weights.byName.normal,
101 ]}
102 >
103 Log in with ATProto
104 </Text>
105 <ArrowRight
106 height={16}
107 width={16}
108 color={semantic.textInverse}
109 />
110 </View>
111 )}
112 </Pressable>
113 </View>
114 </View>
115 );
116};