ATProto forum built with ESAV
1import React, { createContext, useState, useEffect, useContext } from 'react';
2import { AtpAgent, type AtpSessionData } from '@atproto/api';
3
4interface AuthContextValue {
5 agent: AtpAgent | null;
6 loginStatus: boolean;
7 login: (user: string, password: string, service?: string) => Promise<void>;
8 logout: () => Promise<void>;
9 loading: boolean;
10 authed: boolean | undefined;
11 }
12
13const AuthContext = createContext<AuthContextValue>({} as AuthContextValue);
14
15export const AuthProvider = ({ children } : { children: React.ReactNode }) => {
16 const [agent, setAgent] = useState<AtpAgent | null>(null);
17 const [loginStatus, setLoginStatus] = useState(false);
18 const [loading, setLoading] = useState(true);
19 const [increment, setIncrement] = useState(0);
20 const [authed, setAuthed] = useState<boolean | undefined>(undefined);
21
22 useEffect(() => {
23 const initialize = async () => {
24 try {
25 const service = localStorage.getItem('service');
26 // const user = await AsyncStorage.getItem('user');
27 // const password = await AsyncStorage.getItem('password');
28 const session = localStorage.getItem("sess");
29
30 if (service && session) {
31 console.log("Auto-login service is:", service);
32 const apiAgent = new AtpAgent({ service });
33 try {
34 if (!apiAgent) {
35 console.log("Agent is null or undefined");
36 return;
37 }
38 let sess: AtpSessionData = JSON.parse(session);
39 console.log("resuming session is:", sess);
40 const { data } = await apiAgent.resumeSession(sess);
41 console.log("!!!8!!! agent resume session")
42 setAgent(apiAgent);
43 setLoginStatus(true);
44 setLoading(false);
45 setAuthed(true);
46 } catch (e) {
47 console.log("Failed to resume session" + e);
48 setLoginStatus(true);
49 localStorage.removeItem("sess");
50 localStorage.removeItem('service');
51 const apiAgent = new AtpAgent({ service: 'https://api.bsky.app' });
52 setAgent(apiAgent);
53 setLoginStatus(true);
54 setLoading(false);
55 setAuthed(false);
56 return;
57 }
58 }
59 else {
60 const apiAgent = new AtpAgent({ service: 'https://api.bsky.app' });
61 setAgent(apiAgent);
62 setLoginStatus(true);
63 setLoading(false);
64 setAuthed(false);
65 }
66 } catch (e) {
67 console.log('Failed to auto-login:', e);
68 } finally {
69 setLoading(false);
70 }
71 };
72
73 initialize();
74 }, [increment]);
75
76 const login = async (user: string, password: string, service: string = 'https://bsky.social') => {
77 try {
78 let sessionthing
79 const apiAgent = new AtpAgent({
80 service: service,
81 persistSession: (evt, sess) => {
82 sessionthing = sess;
83 },
84 });
85 await apiAgent.login({ identifier: user, password });
86 console.log("!!!8!!! agent logged on")
87
88 localStorage.setItem('service', service);
89 // await AsyncStorage.setItem('user', user);
90 // await AsyncStorage.setItem('password', password);
91 if (sessionthing) {
92 localStorage.setItem('sess', JSON.stringify(sessionthing));
93 } else {
94 localStorage.setItem('sess', '{}');
95 }
96
97 setAgent(apiAgent);
98 setLoginStatus(true);
99 setAuthed(true);
100 } catch (e) {
101 console.error('Login failed:', e);
102 }
103 };
104
105 const logout = async () => {
106 if (!agent) {
107 console.error("Agent is null or undefined");
108 return;
109 }
110 setLoading(true);
111 try {
112 // check if its even in async storage before removing
113 if (localStorage.getItem('service') && localStorage.getItem('sess')) {
114 localStorage.removeItem('service');
115 localStorage.removeItem('sess');
116 }
117 await agent.logout();
118 console.log("!!!8!!! agent logout")
119 setLoginStatus(false);
120 setAuthed(undefined);
121 await agent.com.atproto.server.deleteSession();
122 console.log("!!!8!!! agent deltesession")
123 //setAgent(null);
124 setIncrement(increment + 1);
125 } catch (e) {
126 console.error("Logout failed:", e);
127 } finally {
128 setLoading(false);
129 }
130 };
131
132 // why the hell are we doing this
133 /*if (loading) {
134 return <div><span>Laoding...ae</span></div>;
135 }*/
136
137 return (
138 <AuthContext.Provider value={{ agent, loginStatus, login, logout, loading, authed }}>
139 {children}
140 </AuthContext.Provider>
141 );
142};
143
144export const useAuth = () => useContext(AuthContext);