import React from 'react'; import {createContext, ReactNode, useContext, useState} from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; import moment from 'moment'; import {SdkService} from '@services/AffinidiSDKService'; const LOGIN_TOKEN = '@LOGIN_TOKEN'; const TOKEN_EXPIRES_IN = '@TOKEN_EXPIRES_IN'; const PASSWORD = '@PASSWORD'; const ENCRYPTED_SEED = '@ENCRYPTED_SEED'; const PHONE_NUMBER = '@PHONE_NUMBER'; const IS_RETURNING_USER = '@IS_RETURNING_USER'; export const PREV_READ_NOTIFICATIONS = '@PREV_READ_NOTIFICATIONS'; export const ACCESS_TOKEN = '@ACCESS_TOKEN'; interface IValueProps { accessToken: string | undefined | null; hasNewNotifications: boolean; } export interface IUserProps { user: IValueProps; sdk: SdkService | undefined; credentials: any[] | undefined; credentialRequests: any; setCredentials: (credentials: any[] | undefined) => void; setCredentialRequests: (credentials: any) => void; initiateSdk: (sdk: SdkService) => void; setUser: (data: IValueProps) => void; setLoginToken: (loginToken: string) => void; getLoginToken: () => Promise; setAccessToken: (loginToken: string) => void; getAccessToken: () => Promise; setTokenExpiresIn: (timestamp: number) => void; getTokenExpiresIn: () => Promise; isTokenExpired: () => Promise; setPassword: (password: string) => void; getPassword: () => Promise; setEncryptedSeed: (encryptedSeed: string) => void; getEncryptedSeed: () => Promise; setPhoneNumber: (phoneNumber: string) => void; getPhoneNumber: () => Promise; isReturningUser: () => Promise; logout: () => void; } const contextDefaultValues: IUserProps = { user: {accessToken: undefined, hasNewNotifications: false}, sdk: undefined, credentials: undefined, credentialRequests: undefined, initiateSdk: (sdk: SdkService) => sdk, setUser: (data: IValueProps) => data, setLoginToken: async (loginToken: string) => loginToken, getLoginToken: async () => '', setAccessToken: async (loginToken: string) => loginToken, getAccessToken: async () => '', setTokenExpiresIn: async (timestamp: number) => timestamp, getTokenExpiresIn: async () => undefined, setPassword: async (password: string) => password, getPassword: async () => undefined, isTokenExpired: async () => true, setEncryptedSeed: async (encryptedSeed: string) => encryptedSeed, getEncryptedSeed: async () => undefined, setCredentials: (credentials: any[] | undefined) => credentials, setCredentialRequests: (credentials: any) => credentials, setPhoneNumber: async (phoneNumber: string) => phoneNumber, getPhoneNumber: async () => undefined, isReturningUser: async () => false, logout: async () => {}, }; const UserContext = createContext(contextDefaultValues); const setLocalValue = async (key: string, value: string) => { try { await AsyncStorage.setItem(key, value); } catch (error) { console.error(error); } }; const getLocalValue = async (key: string) => { try { const value = await AsyncStorage.getItem(key); return value; } catch (error) { console.error(error); } }; export const UserProvider = ({children}: {children: ReactNode}) => { const [user, setUser] = useState(contextDefaultValues.user); const [sdk, setSdk] = useState(contextDefaultValues.sdk); const [credentials, setCredentials] = useState( contextDefaultValues.credentials, ); const [credentialRequests, setCredentialRequests] = useState( contextDefaultValues.credentialRequests, ); const setLoginToken = async (loginToken: string) => { await setLocalValue(LOGIN_TOKEN, loginToken); await setLocalValue(IS_RETURNING_USER, 'TRUE'); }; const getLoginToken = async () => await getLocalValue(LOGIN_TOKEN); const setAccessToken = React.useCallback( async (accessToken: string) => { setUser({...user, accessToken}); await setLocalValue(ACCESS_TOKEN, accessToken); }, [user], ); const getAccessToken = React.useCallback(async () => { const accessToken = await getLocalValue(ACCESS_TOKEN); if (!user?.accessToken && !!accessToken) { setUser({...user, accessToken}); } return accessToken; }, [user]); const setTokenExpiresIn = async (time: number) => await setLocalValue(TOKEN_EXPIRES_IN, time?.toString()); const getTokenExpiresIn = async () => await getLocalValue(TOKEN_EXPIRES_IN); const isTokenExpired = React.useCallback(async () => { const tokenExpiresInValue = await getTokenExpiresIn(); if (!tokenExpiresInValue) { return true; } // return moment().utc().valueOf() > Number(tokenExpiresInValue); return moment().unix() > Number(tokenExpiresInValue); }, []); const setPassword = async (password: string) => await setLocalValue(PASSWORD, password); const getPassword = async () => await getLocalValue(PASSWORD); const setEncryptedSeed = async (encryptedSeed: string) => await setLocalValue(ENCRYPTED_SEED, encryptedSeed); const getEncryptedSeed = async () => await getLocalValue(ENCRYPTED_SEED); const initiateSdk = (v: SdkService) => setSdk(v); const logout = async () => { await AsyncStorage.multiRemove([ LOGIN_TOKEN, ACCESS_TOKEN, TOKEN_EXPIRES_IN, PASSWORD, PHONE_NUMBER, ENCRYPTED_SEED, ]); setUser(contextDefaultValues.user); setSdk(contextDefaultValues.sdk); setCredentials(contextDefaultValues.credentials); }; const setPhoneNumber = async (phoneNumber: string) => await setLocalValue(PHONE_NUMBER, phoneNumber); const getPhoneNumber = async () => await getLocalValue(PHONE_NUMBER); const isReturningUser = async () => { const value = await getLocalValue(IS_RETURNING_USER); return value === 'TRUE' ? true : false; }; return ( ({ user, sdk, setUser, setLoginToken, getLoginToken, setAccessToken, getAccessToken, setTokenExpiresIn, getTokenExpiresIn, isTokenExpired, setPassword, getPassword, setEncryptedSeed, getEncryptedSeed, initiateSdk, credentials, credentialRequests, setCredentialRequests, setCredentials, setPhoneNumber, getPhoneNumber, isReturningUser, logout, }), [ user, sdk, credentials, getAccessToken, isTokenExpired, setAccessToken, credentialRequests, ], )}> {children} ); }; export default () => useContext(UserContext);