Skip to content
This repository has been archived by the owner on Dec 9, 2024. It is now read-only.

Commit

Permalink
Add programatic logout
Browse files Browse the repository at this point in the history
  • Loading branch information
Shreyaschorge committed May 21, 2024
1 parent 6e29a90 commit dfbd167
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 27 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
25 changes: 10 additions & 15 deletions src/components/NeynarAuthButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -94,16 +95,12 @@ export const NeynarAuthButton: React.FC<ButtonProps> = ({
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<INeynarAuthenticatedUser>("neynar_authenticated_user");
useLocalStorage<INeynarAuthenticatedUser>(
LocalStorageKeys.NEYNAR_AUTHENTICATED_USER
);
const [showModal, setShowModal] = useState(false);

// Using useRef to store the authWindow reference
Expand Down Expand Up @@ -247,12 +244,10 @@ export const NeynarAuthButton: React.FC<ButtonProps> = ({
</span>
</>
) : (
user && (
<>
<Img src={user?.pfp_url} alt={user?.username} />
<span style={{ marginLeft: "10px" }}>@{user?.username}</span>
</>
)
<>
<Img src={user?.pfp_url} alt={user?.username} />
<span style={{ marginLeft: "10px" }}>@{user?.username}</span>
</>
)}
</Button>
</>
Expand Down
3 changes: 2 additions & 1 deletion src/contexts/AuthContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -38,7 +39,7 @@ export const AuthContextProvider: React.FC<AuthContextProviderProps> = ({
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const [user, setUser] = useState<INeynarAuthenticatedUser | null>(null);
const [neynarAuthenticatedUser] = useLocalStorage<INeynarAuthenticatedUser>(
"neynar_authenticated_user"
LocalStorageKeys.NEYNAR_AUTHENTICATED_USER
);

useEffect(() => {
Expand Down
23 changes: 21 additions & 2 deletions src/contexts/NeynarContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,6 +23,7 @@ interface INeynarContext {
isAuthenticated: boolean;
showToast: (type: ToastType, message: string) => void;
user: INeynarAuthenticatedUser | null;
logoutUser: () => void;
}

const NeynarContext = createContext<INeynarContext | undefined>(undefined);
Expand Down Expand Up @@ -78,6 +84,18 @@ export const NeynarContextProvider: React.FC<NeynarContextProviderProps> = ({
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,
Expand All @@ -86,8 +104,9 @@ export const NeynarContextProvider: React.FC<NeynarContextProviderProps> = ({
user,
setTheme,
showToast,
logoutUser,
}),
[client_id, theme, isAuthenticated]
[client_id, theme, isAuthenticated, user, setTheme, showToast, logoutUser]
);

return (
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./use-local-storage-state";
export { useLocalStorage } from "./use-local-storage-state";
19 changes: 12 additions & 7 deletions src/hooks/use-local-storage-state.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState } from "react";

type SerializeFunction<T> = (value: T) => string;
type DeserializeFunction<T> = (value: string) => T;
Expand All @@ -17,27 +17,28 @@ export function useLocalStorage<T>(
}: UseLocalStorageStateOptions<T> = {}
): [T, (value: T) => void, () => void] {
const [storedValue, setStoredValue] = useState<T>(() => {
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);
}
};

Expand All @@ -46,9 +47,13 @@ export function useLocalStorage<T>(
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",
}

0 comments on commit dfbd167

Please sign in to comment.