From dfbd1678db76d1ea6e0022c27b9ca2d733625ce9 Mon Sep 17 00:00:00 2001 From: Shreyaschorge Date: Tue, 21 May 2024 17:16:36 +0530 Subject: [PATCH] Add programatic logout --- package.json | 2 +- src/components/NeynarAuthButton/index.tsx | 25 +++++++++-------------- src/contexts/AuthContextProvider.tsx | 3 ++- src/contexts/NeynarContextProvider.tsx | 23 +++++++++++++++++++-- src/hooks/index.ts | 2 +- src/hooks/use-local-storage-state.ts | 19 ++++++++++------- 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index ef6e233..3794297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neynar/react", - "version": "0.2.8", + "version": "0.3.0", "description": "Farcaster frontend component library powered by Neynar", "main": "dist/bundle.cjs.js", "module": "dist/bundle.es.js", diff --git a/src/components/NeynarAuthButton/index.tsx b/src/components/NeynarAuthButton/index.tsx index ed40b26..b6ec4b7 100644 --- a/src/components/NeynarAuthButton/index.tsx +++ b/src/components/NeynarAuthButton/index.tsx @@ -4,6 +4,7 @@ import PlanetBlackIcon from "./icons/PlanetBlackIcon"; import { useNeynarContext } from "../../contexts"; import { useAuth } from "../../contexts/AuthContextProvider"; import { useLocalStorage } from "../../hooks"; +import { LocalStorageKeys } from "../../hooks/use-local-storage-state"; import { INeynarAuthenticatedUser } from "../../types/common"; import { SIWN_variant } from "../../enums"; import { FarcasterIcon } from "./icons/FarcasterIcon"; @@ -94,16 +95,12 @@ export const NeynarAuthButton: React.FC = ({ modalButtonStyle = {}, ...rest }) => { - const { client_id, user } = useNeynarContext(); - const { - setIsAuthenticated, - isAuthenticated, - setUser, - onAuthSuccess, - onSignout, - } = useAuth(); + const { client_id, user, isAuthenticated } = useNeynarContext(); + const { setIsAuthenticated, setUser, onAuthSuccess, onSignout } = useAuth(); const [_, setNeynarAuthenticatedUser, removeNeynarAuthenticatedUser] = - useLocalStorage("neynar_authenticated_user"); + useLocalStorage( + LocalStorageKeys.NEYNAR_AUTHENTICATED_USER + ); const [showModal, setShowModal] = useState(false); // Using useRef to store the authWindow reference @@ -247,12 +244,10 @@ export const NeynarAuthButton: React.FC = ({ ) : ( - user && ( - <> - {user?.username} - @{user?.username} - - ) + <> + {user?.username} + @{user?.username} + )} diff --git a/src/contexts/AuthContextProvider.tsx b/src/contexts/AuthContextProvider.tsx index ebf1386..7af8204 100644 --- a/src/contexts/AuthContextProvider.tsx +++ b/src/contexts/AuthContextProvider.tsx @@ -8,6 +8,7 @@ import React, { } from "react"; import { INeynarAuthenticatedUser, IUser, SetState } from "../types/common"; import { useLocalStorage } from "../hooks"; +import { LocalStorageKeys } from "../hooks/use-local-storage-state"; interface IAuthContext { isAuthenticated: boolean; @@ -38,7 +39,7 @@ export const AuthContextProvider: React.FC = ({ const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(null); const [neynarAuthenticatedUser] = useLocalStorage( - "neynar_authenticated_user" + LocalStorageKeys.NEYNAR_AUTHENTICATED_USER ); useEffect(() => { diff --git a/src/contexts/NeynarContextProvider.tsx b/src/contexts/NeynarContextProvider.tsx index 47300be..8121da2 100644 --- a/src/contexts/NeynarContextProvider.tsx +++ b/src/contexts/NeynarContextProvider.tsx @@ -9,7 +9,12 @@ import React, { import { Theme } from "../enums"; import { INeynarAuthenticatedUser, IUser, SetState } from "../types/common"; import { AuthContextProvider } from "./AuthContextProvider"; -import { ToastContainer, ToastItem, ToastType } from "../components/shared/Toast"; +import { + ToastContainer, + ToastItem, + ToastType, +} from "../components/shared/Toast"; +import { LocalStorageKeys } from "../hooks/use-local-storage-state"; interface INeynarContext { client_id: string; @@ -18,6 +23,7 @@ interface INeynarContext { isAuthenticated: boolean; showToast: (type: ToastType, message: string) => void; user: INeynarAuthenticatedUser | null; + logoutUser: () => void; } const NeynarContext = createContext(undefined); @@ -78,6 +84,18 @@ export const NeynarContextProvider: React.FC = ({ setUser(_user); }; + const logoutUser = () => { + if (user) { + const { signer_uuid, ...rest } = user; + setUser(null); + setIsAuthenticated(false); + localStorage.removeItem(LocalStorageKeys.NEYNAR_AUTHENTICATED_USER); + if (eventsCallbacks?.onSignout) { + eventsCallbacks.onSignout(rest); + } + } + }; + const value = useMemo( () => ({ client_id, @@ -86,8 +104,9 @@ export const NeynarContextProvider: React.FC = ({ user, setTheme, showToast, + logoutUser, }), - [client_id, theme, isAuthenticated] + [client_id, theme, isAuthenticated, user, setTheme, showToast, logoutUser] ); return ( diff --git a/src/hooks/index.ts b/src/hooks/index.ts index d8abfd4..3a41ae0 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1 +1 @@ -export * from "./use-local-storage-state"; +export { useLocalStorage } from "./use-local-storage-state"; diff --git a/src/hooks/use-local-storage-state.ts b/src/hooks/use-local-storage-state.ts index d820cb2..7fcd496 100644 --- a/src/hooks/use-local-storage-state.ts +++ b/src/hooks/use-local-storage-state.ts @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState } from "react"; type SerializeFunction = (value: T) => string; type DeserializeFunction = (value: string) => T; @@ -17,27 +17,28 @@ export function useLocalStorage( }: UseLocalStorageStateOptions = {} ): [T, (value: T) => void, () => void] { const [storedValue, setStoredValue] = useState(() => { - if (typeof window === 'undefined') { + if (typeof window === "undefined") { return defaultValue; } try { const item = window.localStorage.getItem(key); return item ? deserialize(item) : defaultValue; } catch (error) { - console.error('Error reading from localStorage', error); + console.error("Error reading from localStorage", error); return defaultValue; } }); const setValue = (value: T) => { try { - const valueToStore = value instanceof Function ? value(storedValue) : value; + const valueToStore = + value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { window.localStorage.setItem(key, serialize(valueToStore)); } } catch (error) { - console.error('Error writing to localStorage', error); + console.error("Error writing to localStorage", error); } }; @@ -46,9 +47,13 @@ export function useLocalStorage( window.localStorage.removeItem(key); setStoredValue(defaultValue); } catch (error) { - console.error('Error removing from localStorage', error); + console.error("Error removing from localStorage", error); } }; return [storedValue, setValue, removeItem]; } + +export enum LocalStorageKeys { + NEYNAR_AUTHENTICATED_USER = "neynar_authenticated_user", +}