@rownd/react-native 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +213 -0
- package/android/build.gradle +59 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/reactnative/ReactNativePackage.java +22 -0
- package/android/src/main/java/com/reactnative/ReactNativeViewManager.java +31 -0
- package/ios/ReactNative.xcodeproj/project.pbxproj +282 -0
- package/ios/ReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/ReactNativeViewManager.m +34 -0
- package/lib/commonjs/assets/images/checkmark--filled.svg +12 -0
- package/lib/commonjs/assets/images/email-verify-waiting.svg +36 -0
- package/lib/commonjs/assets/images/phone-verify-waiting.svg +26 -0
- package/lib/commonjs/components/AuthenticatedComponent.js +35 -0
- package/lib/commonjs/components/AuthenticatedComponent.js.map +1 -0
- package/lib/commonjs/components/AutoSigninDialog.js +119 -0
- package/lib/commonjs/components/AutoSigninDialog.js.map +1 -0
- package/lib/commonjs/components/DefaultContext.js +269 -0
- package/lib/commonjs/components/DefaultContext.js.map +1 -0
- package/lib/commonjs/components/GlobalContext.js +340 -0
- package/lib/commonjs/components/GlobalContext.js.map +1 -0
- package/lib/commonjs/components/RowndComponents.js +29 -0
- package/lib/commonjs/components/RowndComponents.js.map +1 -0
- package/lib/commonjs/components/RowndProvider.js +55 -0
- package/lib/commonjs/components/RowndProvider.js.map +1 -0
- package/lib/commonjs/components/SignIn.js +622 -0
- package/lib/commonjs/components/SignIn.js.map +1 -0
- package/lib/commonjs/data/actions.js +26 -0
- package/lib/commonjs/data/actions.js.map +1 -0
- package/lib/commonjs/hooks/api.js +157 -0
- package/lib/commonjs/hooks/api.js.map +1 -0
- package/lib/commonjs/hooks/debounce.js +38 -0
- package/lib/commonjs/hooks/debounce.js.map +1 -0
- package/lib/commonjs/hooks/fingerprint.js +176 -0
- package/lib/commonjs/hooks/fingerprint.js.map +1 -0
- package/lib/commonjs/hooks/index.js +48 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/interval.js +31 -0
- package/lib/commonjs/hooks/interval.js.map +1 -0
- package/lib/commonjs/hooks/nav.js +39 -0
- package/lib/commonjs/hooks/nav.js.map +1 -0
- package/lib/commonjs/hooks/rownd.js +163 -0
- package/lib/commonjs/hooks/rownd.js.map +1 -0
- package/lib/commonjs/index.js +32 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/index.tsx.bak +26 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/config.js +28 -0
- package/lib/commonjs/utils/config.js.map +1 -0
- package/lib/commonjs/utils/events.js +57 -0
- package/lib/commonjs/utils/events.js.map +1 -0
- package/lib/commonjs/utils/form.js +46 -0
- package/lib/commonjs/utils/form.js.map +1 -0
- package/lib/commonjs/utils/queue.js +117 -0
- package/lib/commonjs/utils/queue.js.map +1 -0
- package/lib/commonjs/utils/storage.js +15 -0
- package/lib/commonjs/utils/storage.js.map +1 -0
- package/lib/commonjs/utils/tailwind.js +17 -0
- package/lib/commonjs/utils/tailwind.js.map +1 -0
- package/lib/commonjs/utils/tokens.js +35 -0
- package/lib/commonjs/utils/tokens.js.map +1 -0
- package/lib/commonjs/utils/user-data.js +21 -0
- package/lib/commonjs/utils/user-data.js.map +1 -0
- package/lib/module/assets/images/checkmark--filled.svg +12 -0
- package/lib/module/assets/images/email-verify-waiting.svg +36 -0
- package/lib/module/assets/images/phone-verify-waiting.svg +26 -0
- package/lib/module/components/AuthenticatedComponent.js +24 -0
- package/lib/module/components/AuthenticatedComponent.js.map +1 -0
- package/lib/module/components/AutoSigninDialog.js +100 -0
- package/lib/module/components/AutoSigninDialog.js.map +1 -0
- package/lib/module/components/DefaultContext.js +244 -0
- package/lib/module/components/DefaultContext.js.map +1 -0
- package/lib/module/components/GlobalContext.js +318 -0
- package/lib/module/components/GlobalContext.js.map +1 -0
- package/lib/module/components/RowndComponents.js +14 -0
- package/lib/module/components/RowndComponents.js.map +1 -0
- package/lib/module/components/RowndProvider.js +39 -0
- package/lib/module/components/RowndProvider.js.map +1 -0
- package/lib/module/components/SignIn.js +593 -0
- package/lib/module/components/SignIn.js.map +1 -0
- package/lib/module/data/actions.js +19 -0
- package/lib/module/data/actions.js.map +1 -0
- package/lib/module/hooks/api.js +138 -0
- package/lib/module/hooks/api.js.map +1 -0
- package/lib/module/hooks/debounce.js +29 -0
- package/lib/module/hooks/debounce.js.map +1 -0
- package/lib/module/hooks/fingerprint.js +157 -0
- package/lib/module/hooks/fingerprint.js.map +1 -0
- package/lib/module/hooks/index.js +7 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/interval.js +23 -0
- package/lib/module/hooks/interval.js.map +1 -0
- package/lib/module/hooks/nav.js +30 -0
- package/lib/module/hooks/nav.js.map +1 -0
- package/lib/module/hooks/rownd.js +148 -0
- package/lib/module/hooks/rownd.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.tsx.bak +26 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/config.js +17 -0
- package/lib/module/utils/config.js.map +1 -0
- package/lib/module/utils/events.js +45 -0
- package/lib/module/utils/events.js.map +1 -0
- package/lib/module/utils/form.js +34 -0
- package/lib/module/utils/form.js.map +1 -0
- package/lib/module/utils/queue.js +109 -0
- package/lib/module/utils/queue.js.map +1 -0
- package/lib/module/utils/storage.js +6 -0
- package/lib/module/utils/storage.js.map +1 -0
- package/lib/module/utils/tailwind.js +5 -0
- package/lib/module/utils/tailwind.js.map +1 -0
- package/lib/module/utils/tokens.js +24 -0
- package/lib/module/utils/tokens.js.map +1 -0
- package/lib/module/utils/user-data.js +14 -0
- package/lib/module/utils/user-data.js.map +1 -0
- package/lib/typescript/example2/App.d.ts +11 -0
- package/lib/typescript/src/components/AuthenticatedComponent.d.ts +7 -0
- package/lib/typescript/src/components/AutoSigninDialog.d.ts +1 -0
- package/lib/typescript/src/components/DefaultContext.d.ts +12 -0
- package/lib/typescript/src/components/GlobalContext.d.ts +111 -0
- package/lib/typescript/src/components/RowndComponents.d.ts +1 -0
- package/lib/typescript/src/components/RowndProvider.d.ts +8 -0
- package/lib/typescript/src/components/SignIn.d.ts +1 -0
- package/lib/typescript/src/data/actions.d.ts +20 -0
- package/lib/typescript/src/hooks/api.d.ts +12 -0
- package/lib/typescript/src/hooks/debounce.d.ts +5 -0
- package/lib/typescript/src/hooks/fingerprint.d.ts +12 -0
- package/lib/typescript/src/hooks/index.d.ts +6 -0
- package/lib/typescript/src/hooks/interval.d.ts +2 -0
- package/lib/typescript/src/hooks/nav.d.ts +6 -0
- package/lib/typescript/src/hooks/rownd.d.ts +37 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/types.d.ts +26 -0
- package/lib/typescript/src/utils/config.d.ts +18 -0
- package/lib/typescript/src/utils/events.d.ts +22 -0
- package/lib/typescript/src/utils/form.d.ts +17 -0
- package/lib/typescript/src/utils/queue.d.ts +21 -0
- package/lib/typescript/src/utils/storage.d.ts +3 -0
- package/lib/typescript/src/utils/tailwind.d.ts +2 -0
- package/lib/typescript/src/utils/tokens.d.ts +4 -0
- package/lib/typescript/src/utils/user-data.d.ts +3 -0
- package/lib/typescript/tailwind.config.d.ts +10 -0
- package/package.json +177 -0
- package/react-native.podspec +19 -0
- package/src/assets/images/checkmark--filled.svg +12 -0
- package/src/assets/images/email-verify-waiting.svg +36 -0
- package/src/assets/images/phone-verify-waiting.svg +26 -0
- package/src/components/AuthenticatedComponent.tsx +30 -0
- package/src/components/AutoSigninDialog.tsx +125 -0
- package/src/components/DefaultContext.tsx +278 -0
- package/src/components/GlobalContext.tsx +485 -0
- package/src/components/RowndComponents.tsx +21 -0
- package/src/components/RowndProvider.tsx +56 -0
- package/src/components/SignIn.tsx +770 -0
- package/src/data/actions.ts +21 -0
- package/src/hooks/api.ts +163 -0
- package/src/hooks/debounce.ts +36 -0
- package/src/hooks/fingerprint.ts +217 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/interval.ts +25 -0
- package/src/hooks/nav.tsx +29 -0
- package/src/hooks/rownd.ts +184 -0
- package/src/index.tsx +6 -0
- package/src/index.tsx.bak +26 -0
- package/src/types.ts +27 -0
- package/src/utils/config.ts +36 -0
- package/src/utils/events.ts +54 -0
- package/src/utils/form.tsx +64 -0
- package/src/utils/queue.ts +75 -0
- package/src/utils/storage.ts +7 -0
- package/src/utils/tailwind.ts +6 -0
- package/src/utils/tokens.ts +26 -0
- package/src/utils/user-data.ts +15 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Linking","React","useCallback","useEffect","useMemo","useReducer","useRef","useState","differenceInMinutes","View","Text","StyleSheet","Pressable","Image","ActivityIndicator","SvgCssUri","tw","phone","jwt_decode","BottomSheetBackdrop","BottomSheetModal","BottomSheetTextInput","useApi","useInterval","useNav","useDeviceFingerprint","useGlobalContext","ActionType","renderField","ImageEmailVerifyWaiting","ImagePhoneVerifyWaiting","ImageCheckmarkFilled","LoginStep","LoginVerificationStatus","SignIn","navTo","getFingerprint","getChallengeIfPresent","clearFingerprint","state","dispatch","config","nav","app","user","decodedAccessToken","auth","access_token","userIdentifier","setUserIdentifier","fieldError","setFieldError","step","setStep","SUCCESS","INIT","error","setError","allowedIdentifiers","requestId","setRequestId","loginPollStart","setLoginPollStart","isSubmitting","setIsSubmitting","loginType","setLoginType","_phoneDetails","setPhoneDetails","isValidUserIdentifier","setIsValidUserIdentifier","requiresAdditionalFields","setRequiresAdditionalFields","options","init_data","bottomSheetModalRef","current","present","addlFieldInit","currentState","addlFields","hub","additional_fields","addlInputs","default_values","newState","length","field","name","value","fieldReducer","action","console","log","type","payload","addlFieldValues","addlFieldDispatch","client","api","validateEmail","email","re","isValid","test","String","toLowerCase","isValidPhone","phoneResult","phoneNumber","isValidEmail","emailAtIdx","indexOf","emailSuffixIdx","substring","validateInput","validations","includes","push","some","fn","pollLoginStatus","resp","post","headers","appKey","json","challenge_id","err","status","Error","code","PENDING","LOGIN_SUCCESS","Date","now","ERROR","FAILURE","WAITING","post_login_redirect","postLoginUrl","openURL","CHANGE_ROUTE","route","is_verified_user","initSignIn","return_url","user_data","Object","values","data","f","undefined","default_user_id_format","user_id","fingerprint","challengeEntry","id","hash","visitorId","challenge","auth_tokens","app_id","response","message","launchRowndWebsite","handleAddlFieldChange","evt","target","handleClose","setTimeout","hide","snapPoints","renderBackdrop","cbProps","styles","bottomSheet","innerContainer","show_app_icon","icon","icon_content_type","appLogo","uri","dialogHeading","inputLabel","identifierInput","text","trim","map","pressed","button","buttonDisabled","buttonPressed","buttonSubmitting","buttonText","buttonContent","buttonDisabledText","signInNoticeText","style","link","signInVerificationImage","create","modal","shadowColor","shadowOffset","width","height","shadowOpacity","shadowRadius","elevation","borderRadius","borderColor","borderWidth","padding","container","flex","header","alignItems","backgroundColor","paddingVertical","borderTopLeftRadius","borderTopRightRadius","panelHandle","resizeMode","textAlign","marginLeft","marginRight","marginBottom","fontSize","marginTop","display","justifyContent","opacity","color","paddingLeft","buttonTextInner","loadingIndicator","textAlignVertical","margin"],"sources":["SignIn.tsx"],"sourcesContent":["import * as Linking from 'expo-linking';\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n useState,\n} from 'react';\nimport { differenceInMinutes } from 'date-fns';\nimport {\n View,\n Text,\n StyleSheet,\n Pressable,\n Image,\n ActivityIndicator,\n} from 'react-native';\nimport { SvgCssUri } from 'react-native-svg';\nimport tw from '../utils/tailwind';\nimport phone, { type PhoneResult } from 'phone';\nimport jwt_decode from 'jwt-decode';\nimport {\n BottomSheetBackdrop,\n BottomSheetBackdropProps,\n BottomSheetModal,\n BottomSheetTextInput,\n} from '@gorhom/bottom-sheet';\n\nimport { useApi, useInterval, useNav, useDeviceFingerprint } from '../hooks';\nimport { useGlobalContext } from './GlobalContext';\nimport { ActionType } from '../data/actions';\nimport { renderField } from '../utils/form';\n\n// Image imports\nimport ImageEmailVerifyWaiting from '../assets/images/email-verify-waiting.svg';\nimport ImagePhoneVerifyWaiting from '../assets/images/phone-verify-waiting.svg';\nimport ImageCheckmarkFilled from '../assets/images/checkmark--filled.svg';\n\nenum LoginStep {\n INIT = 'init',\n WAITING = 'waiting',\n SUCCESS = 'success',\n FAILURE = 'failure',\n ERROR = 'error',\n}\n\ntype LoginInitBody = {\n challenge_id: string;\n message: string;\n auth_tokens?: {\n access_token: string;\n refresh_token: string;\n };\n registration_status: string;\n init_data?: Record<string, any>;\n};\n\ntype LoginSuccessBody = {\n access_token: string;\n refresh_token: string;\n app_user_id: string;\n app_id: string;\n status: string;\n};\n\nenum LoginVerificationStatus {\n PENDING = 'pending',\n EXPIRED = 'expired',\n VERIFIED = 'verified',\n}\n\nexport function SignIn() {\n const navTo = useNav();\n const { getFingerprint, getChallengeIfPresent, clearFingerprint } =\n useDeviceFingerprint();\n const { state, dispatch } = useGlobalContext();\n const { config, nav, app, user } = state;\n\n let decodedAccessToken: any;\n if (state.auth.access_token) {\n decodedAccessToken = jwt_decode(state.auth.access_token);\n }\n\n const [userIdentifier, setUserIdentifier] = useState('');\n const [fieldError, setFieldError] = useState<string | null>(null);\n const [step, setStep] = useState(\n state.auth.access_token &&\n decodedAccessToken?.['https://auth.rownd.io/is_verified_user'] !== false\n ? LoginStep.SUCCESS\n : LoginStep.INIT\n );\n const [error, setError] = useState('');\n const allowedIdentifiers = useMemo(() => ['email', 'phone'], []);\n const [requestId, setRequestId] = useState<string | null>(null);\n const [loginPollStart, setLoginPollStart] = useState<number | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [loginType, setLoginType] = useState<'email' | 'phone' | null>(null);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [_phoneDetails, setPhoneDetails] = useState<PhoneResult | null>(null); // TODO: For parity with web, need to use `phoneDetails` to update the input visuals\n const [isValidUserIdentifier, setIsValidUserIdentifier] = useState(false);\n const [requiresAdditionalFields, setRequiresAdditionalFields] = useState(\n nav?.options?.init_data\n );\n\n const bottomSheetModalRef = useRef<BottomSheetModal>(null);\n useEffect(() => {\n if (bottomSheetModalRef.current) {\n bottomSheetModalRef.current.present();\n }\n }, []);\n\n const addlFieldInit = useCallback(\n (currentState: Record<string, string>) => {\n const addlFields = app?.config?.hub?.auth?.additional_fields;\n const addlInputs =\n nav?.options?.init_data || nav?.options?.default_values || {};\n\n const newState: Record<string, string> = {};\n if (addlFields?.length) {\n for (const field of addlFields) {\n if (field?.options) {\n newState[field.name] =\n addlInputs?.[field.name] || field.options[0].value;\n }\n }\n }\n\n return {\n ...currentState,\n ...newState,\n };\n },\n [\n app?.config?.hub?.auth?.additional_fields,\n nav?.options?.default_values,\n nav?.options?.init_data,\n ]\n );\n\n const fieldReducer = useCallback(\n (\n currentState: any,\n action: { type: string; payload?: Record<string, string> }\n ) => {\n console.log('fieldReducer', action);\n switch (action.type) {\n case 'reset':\n return addlFieldInit(currentState);\n\n default:\n return {\n ...currentState,\n ...action.payload,\n };\n }\n },\n [addlFieldInit]\n );\n\n const [addlFieldValues, addlFieldDispatch] = useReducer(\n fieldReducer,\n {},\n addlFieldInit\n );\n\n const { client: api } = useApi();\n\n function validateEmail(email: string): boolean {\n const re =\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n const isValid = re.test(String(email).toLowerCase());\n\n if (!isValid) {\n setFieldError('Invalid email address');\n return false;\n }\n\n setFieldError(null);\n return true;\n }\n\n const isValidPhone = useCallback((): boolean => {\n const phoneResult = phone(userIdentifier);\n if (!phoneResult.isValid) {\n setLoginType(null);\n setPhoneDetails(null);\n return false;\n }\n\n setLoginType('phone');\n setPhoneDetails(phoneResult);\n setUserIdentifier(phoneResult.phoneNumber);\n return true;\n }, [userIdentifier]);\n\n const isValidEmail = useCallback((): boolean => {\n const emailAtIdx = userIdentifier?.indexOf('@');\n const emailSuffixIdx = userIdentifier?.substring(emailAtIdx).indexOf('.');\n if (\n emailAtIdx > 0 &&\n emailSuffixIdx > 0 &&\n userIdentifier?.substring(emailAtIdx + emailSuffixIdx).length >= 3\n ) {\n return validateEmail(userIdentifier);\n }\n\n return false;\n }, [userIdentifier]);\n\n const validateInput = useCallback(() => {\n const validations = [];\n if (allowedIdentifiers.includes('phone')) {\n validations.push(isValidPhone);\n }\n\n if (allowedIdentifiers.includes('email')) {\n validations.push(isValidEmail);\n }\n\n if (!validations.some((fn) => fn())) {\n setIsValidUserIdentifier(false);\n } else {\n setIsValidUserIdentifier(true);\n }\n }, [allowedIdentifiers, isValidEmail, isValidPhone]);\n\n // Fire validation as data changes in field\n useEffect(validateInput, [validateInput]);\n\n const pollLoginStatus = useCallback(async () => {\n try {\n const resp: LoginSuccessBody = await api\n .post(`hub/auth/challenge_status`, {\n headers: {\n 'x-rownd-app-key': config?.appKey,\n },\n json: {\n challenge_id: requestId,\n [loginType === 'phone' ? 'phone' : 'email']: userIdentifier,\n },\n })\n .json();\n\n let err: any;\n switch (resp.status) {\n case 'pending':\n err = new Error('Login challenge is still pending');\n err.code = LoginVerificationStatus.PENDING;\n throw err;\n\n case 'expired':\n err = new Error('Login challenge is still pending');\n err.code = LoginVerificationStatus.PENDING;\n throw err;\n\n case 'verified':\n break;\n\n default:\n err = new Error('Unknown login challenge status');\n throw err;\n }\n\n dispatch({\n type: ActionType.LOGIN_SUCCESS,\n payload: resp,\n });\n\n setStep(LoginStep.SUCCESS);\n } catch (err: any) {\n // logger.log('login poll error', err);\n\n // If network error, try again up to 1 minute, else fail\n if (!err.code && differenceInMinutes(Date.now(), loginPollStart!) > 0) {\n setStep(LoginStep.ERROR);\n setError('Network error. Please try again later.');\n return;\n }\n\n // If request expires, then fail (assume > 6 mins is a failure/expiration)\n if (\n (err.status || err.code) &&\n differenceInMinutes(Date.now(), loginPollStart!) > 6\n ) {\n setStep(LoginStep.ERROR);\n setError('The sign in request expired.');\n return;\n }\n\n if (err.status && err.status >= 400) {\n setStep(LoginStep.FAILURE);\n setError('Sign in unsuccessful.');\n }\n }\n }, [\n api,\n config?.appKey,\n dispatch,\n loginPollStart,\n loginType,\n requestId,\n userIdentifier,\n ]);\n\n // Polling when a login flow is in progress\n useInterval(pollLoginStatus, step === LoginStep.WAITING ? 5000 : null);\n\n // login polling manager\n useEffect(() => {\n if (step === LoginStep.SUCCESS) {\n if (nav?.options?.post_login_redirect || state.config?.postLoginUrl) {\n Linking.openURL(\n nav?.options?.post_login_redirect || state.config?.postLoginUrl\n );\n }\n\n dispatch({\n type: ActionType.CHANGE_ROUTE,\n payload: {\n route: '/',\n },\n });\n\n // Reset modal state if this user is unverified, since we'll need to re-submit at some point\n if (!state.auth.is_verified_user) {\n setStep(LoginStep.INIT);\n }\n }\n }, [\n dispatch,\n nav?.options?.post_login_redirect,\n pollLoginStatus,\n state.auth.is_verified_user,\n state.config?.postLoginUrl,\n step,\n ]);\n\n const initSignIn = useCallback(async () => {\n if (step === LoginStep.WAITING) {\n return;\n }\n\n // Validation\n if (fieldError) {\n return;\n }\n\n const payload = {\n [loginType === 'phone' ? 'phone' : 'email']: userIdentifier,\n return_url:\n nav?.options?.post_login_redirect || state.config?.postLoginUrl,\n user_data: Object.values(user.data).some(\n (f) => f !== null && f !== undefined\n )\n ? user.data\n : {}, // Include user.data if at least one field is defined\n };\n\n // Set the user_id to the application's default user id format if it is defined\n if (app.config?.default_user_id_format) {\n payload.user_id = app.config?.default_user_id_format;\n }\n\n if (requiresAdditionalFields) {\n payload.user_data = {\n ...payload.user_data,\n ...addlFieldValues,\n };\n }\n\n // Submission\n try {\n setIsSubmitting(true);\n\n // Get the browser fingerprint for future sign-ins that don't require re-verification\n const fingerprint = await getFingerprint();\n const challengeEntry = await getChallengeIfPresent(app.id, [\n userIdentifier,\n ]);\n payload.fingerprint = {\n hash: fingerprint.visitorId,\n challenge: challengeEntry?.value,\n };\n\n const resp: LoginInitBody = await api\n .post('hub/auth/init', {\n headers: {\n 'x-rownd-app-key': config?.appKey,\n },\n json: payload,\n })\n .json();\n\n // This will only be true when a user is signing in for the very first time and\n // the app allows unverified users OR the user was successfully fingerprinted.\n if (resp.auth_tokens) {\n dispatch({\n type: ActionType.LOGIN_SUCCESS,\n payload: {\n ...resp.auth_tokens,\n app_id: app.id,\n },\n });\n\n setStep(LoginStep.SUCCESS);\n return;\n } else if (payload?.fingerprint?.challenge) {\n // The fingerprint is probably expired, so delete the challenge for re-registration\n try {\n clearFingerprint(payload.fingerprint.challenge);\n } catch (err) {\n // no-op, but not likely to throw anyway\n }\n }\n\n setRequestId(resp.challenge_id);\n setStep(LoginStep.WAITING);\n setLoginPollStart(Date.now());\n } catch (err: any) {\n // logger.error(err);\n\n if (err.response.status === 400) {\n setStep(LoginStep.INIT);\n setRequiresAdditionalFields(true);\n return;\n }\n\n setStep(LoginStep.ERROR);\n setError(err.message);\n } finally {\n setIsSubmitting(false);\n }\n }, [\n step,\n fieldError,\n loginType,\n userIdentifier,\n nav?.options?.post_login_redirect,\n state.config?.postLoginUrl,\n user.data,\n app.config?.default_user_id_format,\n app.id,\n requiresAdditionalFields,\n addlFieldValues,\n getFingerprint,\n getChallengeIfPresent,\n api,\n config?.appKey,\n dispatch,\n clearFingerprint,\n ]);\n\n const launchRowndWebsite = () => {\n Linking.openURL('https://rownd.io');\n };\n\n const handleAddlFieldChange = (evt: Event) => {\n const target = evt.target as HTMLInputElement;\n const { value, name } = target;\n\n addlFieldDispatch({\n type: 'default',\n payload: {\n [name]: value,\n },\n });\n };\n\n const handleClose = useCallback(() => {\n setTimeout(() => {\n navTo({ hide: true });\n }, 150);\n }, [navTo]);\n\n const snapPoints = useMemo(() => ['25%', '70%'], []);\n\n const renderBackdrop = useCallback(\n (cbProps: BottomSheetBackdropProps) => (\n <BottomSheetBackdrop {...cbProps} pressBehavior=\"close\" />\n ),\n []\n );\n\n return (\n <BottomSheetModal\n snapPoints={snapPoints}\n index={1}\n backdropComponent={renderBackdrop}\n keyboardBehavior=\"fillParent\"\n android_keyboardInputMode=\"adjustResize\"\n enablePanDownToClose={true}\n onDismiss={handleClose}\n style={styles.bottomSheet}\n ref={bottomSheetModalRef}\n >\n <View style={styles.innerContainer}>\n {step === LoginStep.INIT && (\n <>\n {app?.config?.hub?.auth?.show_app_icon &&\n app?.icon &&\n (app.icon_content_type === 'image/svg+xml' ? (\n <SvgCssUri uri={app.icon} style={styles.appLogo} />\n ) : (\n <Image style={styles.appLogo} source={{ uri: app.icon }} />\n ))}\n <Text style={styles.dialogHeading}>Sign in or sign up</Text>\n <Text style={styles.inputLabel}>Email or phone number</Text>\n <BottomSheetTextInput\n style={styles.identifierInput}\n placeholder=\"Enter here\"\n keyboardType=\"email-address\"\n textContentType=\"emailAddress\"\n returnKeyLabel=\"Sign in\"\n returnKeyType=\"go\"\n enablesReturnKeyAutomatically={true}\n autoCapitalize=\"none\"\n onChangeText={(text) => setUserIdentifier(text.trim())}\n onBlur={validateInput}\n value={userIdentifier}\n onSubmitEditing={initSignIn}\n />\n {requiresAdditionalFields &&\n app?.config?.hub?.auth?.additional_fields.map((field) => {\n return renderField({\n ...field,\n value: addlFieldValues[field.name] || '',\n [['input', 'text', 'tel', 'email'].includes(field.type)\n ? 'onInput'\n : 'onChange']: handleAddlFieldChange,\n });\n })}\n <Pressable\n style={({ pressed }: { pressed: boolean }) => [\n styles.button,\n !isValidUserIdentifier && styles.buttonDisabled,\n pressed && styles.buttonPressed,\n isSubmitting && styles.buttonSubmitting,\n ]}\n disabled={!isValidUserIdentifier || isSubmitting}\n onPress={initSignIn}\n >\n <Text>\n {isSubmitting && (\n <ActivityIndicator size=\"small\" color=\"#efefef\" />\n )}\n <View style={styles.buttonText}>\n <Text\n style={\n isValidUserIdentifier\n ? styles.buttonContent\n : {\n ...styles.buttonContent,\n ...styles.buttonDisabledText,\n }\n }\n >\n {isSubmitting ? 'Just a sec...' : 'Continue'}\n </Text>\n </View>\n </Text>\n </Pressable>\n <Text style={styles.signInNoticeText}>\n By continuing, you're agreeing to the terms of service that govern\n this app and to receive email or text messages for verification\n purposes.\n </Text>\n </>\n )}\n\n {step === LoginStep.WAITING && (\n <>\n <Text style={styles.dialogHeading}>\n Thanks! Verify your{' '}\n {loginType === 'phone' ? 'phone number' : 'email'} to finish\n </Text>\n <Text style={tw.style('py-6')}>\n Click the link in the message we just sent to{' '}\n <Text style={tw.style('italic')}>{userIdentifier}</Text> to verify\n and finish.\n <Text\n style={[styles.link]}\n onPress={() => setStep(LoginStep.INIT)}\n >\n Re-send message\n </Text>\n </Text>\n\n <View style={styles.signInVerificationImage}>\n {loginType === 'phone' ? (\n <ImagePhoneVerifyWaiting />\n ) : (\n <ImageEmailVerifyWaiting />\n )}\n </View>\n\n <Pressable\n style={({ pressed }: { pressed: boolean }) => [\n styles.button,\n pressed && styles.buttonPressed,\n ]}\n onPress={() => setStep(LoginStep.INIT)}\n >\n <Text style={styles.buttonContent}>\n Try a different{' '}\n {loginType === 'phone' ? 'phone number' : 'email'}\n </Text>\n </Pressable>\n </>\n )}\n\n {step === LoginStep.SUCCESS && (\n <>\n <View style={styles.signInVerificationImage}>\n <ImageCheckmarkFilled />\n </View>\n </>\n )}\n\n {step === LoginStep.FAILURE && (\n <>\n <Text style={tw.style('text-base')}>Whoops, that didn't work!</Text>\n <Pressable\n style={styles.button}\n onPress={() => setStep(LoginStep.INIT)}\n >\n <Text style={styles.buttonContent}>Try again</Text>\n </Pressable>\n </>\n )}\n\n {step === LoginStep.ERROR && (\n <>\n <Text style={tw.style('text-base')}>\n An error occurred while signing you in.\n </Text>\n {!!error && <Text style={tw.style('text-rose-800')}>{error}</Text>}\n <Pressable\n style={styles.button}\n onPress={() => setStep(LoginStep.INIT)}\n >\n <Text style={styles.buttonContent}>Try again</Text>\n </Pressable>\n </>\n )}\n <Text>\n Powered by{' '}\n <Text style={styles.link} onPress={launchRowndWebsite}>\n Rownd\n </Text>\n </Text>\n </View>\n </BottomSheetModal>\n );\n}\n\nconst styles = StyleSheet.create({\n modal: {\n // flex: 1,\n },\n bottomSheet: {\n shadowColor: '#000',\n shadowOffset: {\n width: 0,\n height: 12,\n },\n shadowOpacity: 0.58,\n shadowRadius: 16.0,\n\n elevation: 24,\n },\n innerContainer: {\n borderRadius: 20,\n borderColor: 'transparent',\n borderWidth: 0,\n padding: 25,\n },\n container: {\n flex: 1,\n padding: 24,\n },\n header: {\n alignItems: 'center',\n backgroundColor: 'white',\n paddingVertical: 20,\n borderTopLeftRadius: 20,\n borderTopRightRadius: 20,\n },\n panelHandle: {\n width: 40,\n height: 2,\n backgroundColor: 'rgba(0,0,0,0.3)',\n borderRadius: 4,\n },\n appLogo: {\n padding: 50,\n width: 75,\n height: 75,\n resizeMode: 'center',\n textAlign: 'center',\n marginLeft: 'auto',\n marginRight: 'auto',\n marginBottom: 20,\n },\n dialogHeading: {\n fontSize: 24,\n },\n inputLabel: {\n marginTop: 20,\n marginBottom: 5,\n },\n identifierInput: {\n backgroundColor: '#eee',\n borderRadius: 8,\n padding: 10,\n fontSize: 18,\n },\n button: {\n borderRadius: 10,\n padding: 10,\n marginTop: 20,\n marginBottom: 30,\n elevation: 0,\n backgroundColor: '#5b0ae0',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n buttonDisabled: {\n backgroundColor: '#eee',\n },\n buttonPressed: {\n opacity: 0.5,\n },\n buttonContent: {\n textAlign: 'center',\n fontSize: 18,\n color: '#fff',\n },\n buttonText: {\n marginLeft: 10,\n paddingLeft: 10,\n fontSize: 18,\n },\n buttonTextInner: {\n fontSize: 18,\n },\n buttonDisabledText: {\n color: '#8e8e8e',\n },\n buttonSubmitting: {\n backgroundColor: '#2f0492',\n color: '#c7c7c7',\n },\n loadingIndicator: {\n textAlignVertical: 'center',\n padding: 20,\n margin: 20,\n },\n signInNoticeText: {\n fontSize: 12,\n marginBottom: 20,\n },\n signInVerificationImage: {\n alignItems: 'center',\n },\n link: {\n color: '#6114e1',\n },\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export let ActionType;
|
|
2
|
+
|
|
3
|
+
(function (ActionType) {
|
|
4
|
+
ActionType["SET_CONTAINER_VISIBLE"] = "SET_CONTAINER_VISIBLE";
|
|
5
|
+
ActionType["CHANGE_ROUTE"] = "CHANGE_ROUTE";
|
|
6
|
+
ActionType["LOGIN_SUCCESS"] = "LOGIN_SUCCESS";
|
|
7
|
+
ActionType["LOAD_USER"] = "LOAD_USER";
|
|
8
|
+
ActionType["REFRESH_TOKEN"] = "REFRESH_TOKEN";
|
|
9
|
+
ActionType["SIGN_OUT"] = "SIGN_OUT";
|
|
10
|
+
ActionType["UPDATE_LOCAL_ACLS"] = "UPDATE_LOCAL_ACLS";
|
|
11
|
+
ActionType["SET_USER_DATA_FIELD"] = "SET_USER_DATA_FIELD";
|
|
12
|
+
ActionType["SET_USER_DATA"] = "SET_USER_DATA";
|
|
13
|
+
ActionType["SET_REFRESH_USER_DATA"] = "SET_REFRESH_USER_DATA";
|
|
14
|
+
ActionType["LOAD_STATE"] = "LOAD_STATE";
|
|
15
|
+
ActionType["SET_SECTION"] = "SET_SECTION";
|
|
16
|
+
ActionType["SET_IS_SAVING_USER_DATA"] = "SET_IS_SAVING_USER_DATA";
|
|
17
|
+
ActionType["SET_APP_CONFIG"] = "SET_APP_CONFIG";
|
|
18
|
+
})(ActionType || (ActionType = {}));
|
|
19
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ActionType"],"sources":["actions.ts"],"sourcesContent":["export enum ActionType {\n SET_CONTAINER_VISIBLE = 'SET_CONTAINER_VISIBLE',\n CHANGE_ROUTE = 'CHANGE_ROUTE',\n LOGIN_SUCCESS = 'LOGIN_SUCCESS',\n LOAD_USER = 'LOAD_USER',\n REFRESH_TOKEN = 'REFRESH_TOKEN',\n SIGN_OUT = 'SIGN_OUT',\n UPDATE_LOCAL_ACLS = 'UPDATE_LOCAL_ACLS',\n SET_USER_DATA_FIELD = 'SET_USER_DATA_FIELD',\n SET_USER_DATA = 'SET_USER_DATA',\n SET_REFRESH_USER_DATA = 'SET_REFRESH_USER_DATA',\n LOAD_STATE = 'LOAD_STATE',\n SET_SECTION = 'SET_SECTION',\n SET_IS_SAVING_USER_DATA = 'SET_IS_SAVING_USER_DATA',\n SET_APP_CONFIG = 'SET_APP_CONFIG',\n}\n\nexport type TAction = {\n type: ActionType;\n payload?: any;\n};\n"],"mappings":"AAAA,WAAYA,UAAZ;;WAAYA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;EAAAA,U;GAAAA,U,KAAAA,U"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import ky from 'ky';
|
|
2
|
+
import jwt_decode from 'jwt-decode';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { useGlobalContext } from '../components/GlobalContext';
|
|
5
|
+
import AutoQueue from '../utils/queue';
|
|
6
|
+
import { useRef, useEffect } from 'react';
|
|
7
|
+
import { Platform } from 'react-native';
|
|
8
|
+
import { ActionType } from '../data/actions';
|
|
9
|
+
|
|
10
|
+
const packageJson = require(path.join(__dirname, '../../package.json'));
|
|
11
|
+
|
|
12
|
+
const refreshQueue = new AutoQueue();
|
|
13
|
+
export const DEFAULT_USER_AGENT = `Rownd SDK for React Native/${packageJson.version} (Language: TypeScript/JavaScript; Platform=${Platform.OS};)`;
|
|
14
|
+
export default function useApi() {
|
|
15
|
+
var _state$config;
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
state,
|
|
19
|
+
dispatch
|
|
20
|
+
} = useGlobalContext();
|
|
21
|
+
const authRef = useRef({
|
|
22
|
+
access_token: state.auth.access_token,
|
|
23
|
+
refresh_token: state.auth.refresh_token
|
|
24
|
+
});
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
authRef.current = {
|
|
27
|
+
access_token: state.auth.access_token,
|
|
28
|
+
refresh_token: state.auth.refresh_token
|
|
29
|
+
};
|
|
30
|
+
}, [state.auth.access_token, state.auth.refresh_token]);
|
|
31
|
+
|
|
32
|
+
function isNewAccessTokenNeeded(request) {
|
|
33
|
+
var _authRef$current, _authRef$current2;
|
|
34
|
+
|
|
35
|
+
// stateCopy = stateCopy || state;
|
|
36
|
+
// Skip requests that don't need authentication
|
|
37
|
+
if (!!request && !(request !== null && request !== void 0 && request.headers.get('authorization')) || !((_authRef$current = authRef.current) !== null && _authRef$current !== void 0 && _authRef$current.access_token)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const tokenPayload = jwt_decode((_authRef$current2 = authRef.current) === null || _authRef$current2 === void 0 ? void 0 : _authRef$current2.access_token); // Shave 5 minutes off the token expiration to account for clock skew
|
|
42
|
+
|
|
43
|
+
const tokenExpiration = (tokenPayload.exp - 5 * 60) * 1000;
|
|
44
|
+
|
|
45
|
+
if (tokenExpiration > Date.now()) {
|
|
46
|
+
return false; // shouldn't be expired
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function _newAccessTokenFromRefreshToken(stateCopy) {
|
|
53
|
+
var _this$_cache;
|
|
54
|
+
|
|
55
|
+
stateCopy = stateCopy || state;
|
|
56
|
+
|
|
57
|
+
if (this !== null && this !== void 0 && (_this$_cache = this._cache) !== null && _this$_cache !== void 0 && _this$_cache.resp) {
|
|
58
|
+
// logger.log('using cached refresh response');
|
|
59
|
+
return this._cache.resp;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
var _stateCopy$config, _stateCopy$auth;
|
|
64
|
+
|
|
65
|
+
// logger.log('requesting new refresh token');
|
|
66
|
+
const resp = await ky.post(`${(_stateCopy$config = stateCopy.config) === null || _stateCopy$config === void 0 ? void 0 : _stateCopy$config.apiUrl}/hub/auth/token`, {
|
|
67
|
+
json: {
|
|
68
|
+
refresh_token: (_stateCopy$auth = stateCopy.auth) === null || _stateCopy$auth === void 0 ? void 0 : _stateCopy$auth.refresh_token
|
|
69
|
+
}
|
|
70
|
+
}).json();
|
|
71
|
+
this._cache.resp = resp; // Update local cache ref immediately to prevent stale auth checks
|
|
72
|
+
|
|
73
|
+
authRef.current = {
|
|
74
|
+
access_token: resp.access_token,
|
|
75
|
+
refresh_token: resp.refresh_token
|
|
76
|
+
};
|
|
77
|
+
dispatch({
|
|
78
|
+
type: ActionType.REFRESH_TOKEN,
|
|
79
|
+
payload: resp
|
|
80
|
+
});
|
|
81
|
+
return resp;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
dispatch({
|
|
84
|
+
type: ActionType.SIGN_OUT
|
|
85
|
+
});
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function newAccessTokenFromRefreshToken(stateCopy) {
|
|
91
|
+
return await refreshQueue.enqueue(_newAccessTokenFromRefreshToken.bind(refreshQueue, stateCopy));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const client = useRef(ky.extend({
|
|
95
|
+
prefixUrl: (_state$config = state.config) === null || _state$config === void 0 ? void 0 : _state$config.apiUrl,
|
|
96
|
+
headers: {
|
|
97
|
+
'Content-Type': 'application/json',
|
|
98
|
+
'User-Agent': DEFAULT_USER_AGENT
|
|
99
|
+
},
|
|
100
|
+
retry: {
|
|
101
|
+
limit: 2,
|
|
102
|
+
statusCodes: [401, 408, 429, 500, 502, 503, 504]
|
|
103
|
+
},
|
|
104
|
+
hooks: {
|
|
105
|
+
beforeRequest: [// Auto-refresh tokens
|
|
106
|
+
async request => {
|
|
107
|
+
// Skip requests that don't need authentication
|
|
108
|
+
if (!isNewAccessTokenNeeded(request)) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const tokenResp = await newAccessTokenFromRefreshToken();
|
|
113
|
+
request.headers.set('Authorization', `Bearer ${tokenResp.access_token}`);
|
|
114
|
+
}],
|
|
115
|
+
beforeRetry: [async _ref => {
|
|
116
|
+
let {
|
|
117
|
+
request
|
|
118
|
+
/*, options, error, retryCount*/
|
|
119
|
+
|
|
120
|
+
} = _ref;
|
|
121
|
+
|
|
122
|
+
// Skip requests that don't need authentication
|
|
123
|
+
if (!isNewAccessTokenNeeded(request)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const tokenResp = await newAccessTokenFromRefreshToken();
|
|
128
|
+
request.headers.set('Authorization', `Bearer ${tokenResp.access_token}`);
|
|
129
|
+
}]
|
|
130
|
+
}
|
|
131
|
+
})).current;
|
|
132
|
+
return {
|
|
133
|
+
client,
|
|
134
|
+
newAccessTokenFromRefreshToken,
|
|
135
|
+
isNewAccessTokenNeeded
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ky","jwt_decode","path","useGlobalContext","AutoQueue","useRef","useEffect","Platform","ActionType","packageJson","require","join","__dirname","refreshQueue","DEFAULT_USER_AGENT","version","OS","useApi","state","dispatch","authRef","access_token","auth","refresh_token","current","isNewAccessTokenNeeded","request","headers","get","tokenPayload","tokenExpiration","exp","Date","now","_newAccessTokenFromRefreshToken","stateCopy","_cache","resp","post","config","apiUrl","json","type","REFRESH_TOKEN","payload","err","SIGN_OUT","newAccessTokenFromRefreshToken","enqueue","bind","client","extend","prefixUrl","retry","limit","statusCodes","hooks","beforeRequest","tokenResp","set","beforeRetry"],"sources":["api.ts"],"sourcesContent":["import ky from 'ky';\nimport jwt_decode, { JwtPayload } from 'jwt-decode';\nimport path from 'path';\n\nimport { useGlobalContext, GlobalState } from '../components/GlobalContext';\nimport AutoQueue from '../utils/queue';\nimport { useRef, useEffect } from 'react';\nimport { Platform } from 'react-native';\nimport { ActionType } from '../data/actions';\n\nconst packageJson = require(path.join(__dirname, '../../package.json'));\n\ntype RefreshTokenResp = {\n access_token: string;\n refresh_token: string;\n};\n\nconst refreshQueue = new AutoQueue<RefreshTokenResp>();\n\nexport const DEFAULT_USER_AGENT = `Rownd SDK for React Native/${packageJson.version} (Language: TypeScript/JavaScript; Platform=${Platform.OS};)`;\n\nexport default function useApi() {\n const { state, dispatch } = useGlobalContext();\n\n const authRef = useRef({\n access_token: state.auth.access_token,\n refresh_token: state.auth.refresh_token,\n });\n\n useEffect(() => {\n authRef.current = {\n access_token: state.auth.access_token,\n refresh_token: state.auth.refresh_token,\n };\n }, [state.auth.access_token, state.auth.refresh_token]);\n\n function isNewAccessTokenNeeded(request?: Request) {\n // stateCopy = stateCopy || state;\n // Skip requests that don't need authentication\n if (\n (!!request && !request?.headers.get('authorization')) ||\n !authRef.current?.access_token\n ) {\n return false;\n }\n\n const tokenPayload: JwtPayload = jwt_decode(authRef.current?.access_token);\n\n // Shave 5 minutes off the token expiration to account for clock skew\n const tokenExpiration = (tokenPayload.exp! - 5 * 60) * 1000;\n if (tokenExpiration > Date.now()) {\n return false; // shouldn't be expired\n }\n\n return true;\n }\n\n async function _newAccessTokenFromRefreshToken(\n this: AutoQueue<RefreshTokenResp>,\n stateCopy?: GlobalState\n ) {\n stateCopy = stateCopy || state;\n if (this?._cache?.resp) {\n // logger.log('using cached refresh response');\n return this._cache.resp;\n }\n\n try {\n // logger.log('requesting new refresh token');\n const resp: RefreshTokenResp = await ky\n .post(`${stateCopy.config?.apiUrl}/hub/auth/token`, {\n json: {\n refresh_token: stateCopy.auth?.refresh_token,\n },\n })\n .json();\n\n this._cache.resp = resp;\n\n // Update local cache ref immediately to prevent stale auth checks\n authRef.current = {\n access_token: resp.access_token,\n refresh_token: resp.refresh_token,\n };\n\n dispatch({\n type: ActionType.REFRESH_TOKEN,\n payload: resp,\n });\n\n return resp;\n } catch (err) {\n dispatch({\n type: ActionType.SIGN_OUT,\n });\n\n throw err;\n }\n }\n\n async function newAccessTokenFromRefreshToken(\n stateCopy?: GlobalState\n ): Promise<RefreshTokenResp> {\n return await refreshQueue.enqueue(\n _newAccessTokenFromRefreshToken.bind(refreshQueue, stateCopy)\n );\n }\n\n const client = useRef(\n ky.extend({\n prefixUrl: state.config?.apiUrl,\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': DEFAULT_USER_AGENT,\n },\n retry: {\n limit: 2,\n statusCodes: [401, 408, 429, 500, 502, 503, 504],\n },\n hooks: {\n beforeRequest: [\n // Auto-refresh tokens\n async (request) => {\n // Skip requests that don't need authentication\n if (!isNewAccessTokenNeeded(request)) {\n return;\n }\n\n const tokenResp: RefreshTokenResp =\n await newAccessTokenFromRefreshToken();\n\n request.headers.set(\n 'Authorization',\n `Bearer ${tokenResp.access_token}`\n );\n },\n ],\n beforeRetry: [\n async ({ request /*, options, error, retryCount*/ }) => {\n // Skip requests that don't need authentication\n if (!isNewAccessTokenNeeded(request)) {\n return;\n }\n\n const tokenResp: RefreshTokenResp =\n await newAccessTokenFromRefreshToken();\n\n request.headers.set(\n 'Authorization',\n `Bearer ${tokenResp.access_token}`\n );\n },\n ],\n },\n })\n ).current;\n\n return {\n client,\n newAccessTokenFromRefreshToken,\n isNewAccessTokenNeeded,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { debounce } from 'debounce';
|
|
2
|
+
import { useMemo, useEffect, useRef } from 'react';
|
|
3
|
+
export default function useDebounce(cb, delay) {
|
|
4
|
+
const immediate = false;
|
|
5
|
+
const inputsRef = useRef(cb);
|
|
6
|
+
const isMounted = useIsMounted();
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
inputsRef.current = {
|
|
9
|
+
cb,
|
|
10
|
+
delay
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
return useMemo(() => debounce(function () {
|
|
14
|
+
// Don't execute callback, if (1) component in the meanwhile
|
|
15
|
+
// has been unmounted or (2) delay has changed
|
|
16
|
+
if (inputsRef.current.delay === delay && isMounted()) inputsRef.current.cb(...arguments);
|
|
17
|
+
}, delay, immediate), [delay, immediate, isMounted]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function useIsMounted() {
|
|
21
|
+
const isMountedRef = useRef(true);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
return () => {
|
|
24
|
+
isMountedRef.current = false;
|
|
25
|
+
};
|
|
26
|
+
}, []);
|
|
27
|
+
return () => isMountedRef.current;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=debounce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["debounce","useMemo","useEffect","useRef","useDebounce","cb","delay","immediate","inputsRef","isMounted","useIsMounted","current","isMountedRef"],"sources":["debounce.ts"],"sourcesContent":["import { debounce } from 'debounce';\nimport { useMemo, useEffect, useRef } from 'react';\n\nexport default function useDebounce(cb: any, delay: any) {\n const immediate = false;\n const inputsRef = useRef(cb);\n const isMounted = useIsMounted();\n useEffect(() => {\n inputsRef.current = { cb, delay };\n });\n\n return useMemo(\n () =>\n debounce(\n (...args: any) => {\n // Don't execute callback, if (1) component in the meanwhile\n // has been unmounted or (2) delay has changed\n if (inputsRef.current.delay === delay && isMounted())\n inputsRef.current.cb(...args);\n },\n delay,\n immediate\n ),\n [delay, immediate, isMounted]\n );\n}\n\nfunction useIsMounted() {\n const isMountedRef = useRef(true);\n useEffect(() => {\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n return () => isMountedRef.current;\n}\n"],"mappings":"AAAA,SAASA,QAAT,QAAyB,UAAzB;AACA,SAASC,OAAT,EAAkBC,SAAlB,EAA6BC,MAA7B,QAA2C,OAA3C;AAEA,eAAe,SAASC,WAAT,CAAqBC,EAArB,EAA8BC,KAA9B,EAA0C;EACvD,MAAMC,SAAS,GAAG,KAAlB;EACA,MAAMC,SAAS,GAAGL,MAAM,CAACE,EAAD,CAAxB;EACA,MAAMI,SAAS,GAAGC,YAAY,EAA9B;EACAR,SAAS,CAAC,MAAM;IACdM,SAAS,CAACG,OAAV,GAAoB;MAAEN,EAAF;MAAMC;IAAN,CAApB;EACD,CAFQ,CAAT;EAIA,OAAOL,OAAO,CACZ,MACED,QAAQ,CACN,YAAkB;IAChB;IACA;IACA,IAAIQ,SAAS,CAACG,OAAV,CAAkBL,KAAlB,KAA4BA,KAA5B,IAAqCG,SAAS,EAAlD,EACED,SAAS,CAACG,OAAV,CAAkBN,EAAlB,CAAqB,YAArB;EACH,CANK,EAONC,KAPM,EAQNC,SARM,CAFE,EAYZ,CAACD,KAAD,EAAQC,SAAR,EAAmBE,SAAnB,CAZY,CAAd;AAcD;;AAED,SAASC,YAAT,GAAwB;EACtB,MAAME,YAAY,GAAGT,MAAM,CAAC,IAAD,CAA3B;EACAD,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACXU,YAAY,CAACD,OAAb,GAAuB,KAAvB;IACD,CAFD;EAGD,CAJQ,EAIN,EAJM,CAAT;EAKA,OAAO,MAAMC,YAAY,CAACD,OAA1B;AACD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import DeviceInfo from 'react-native-device-info';
|
|
2
|
+
import { useEffect, useCallback } from 'react';
|
|
3
|
+
import useApi from './api';
|
|
4
|
+
import { useGlobalContext } from '../components/GlobalContext';
|
|
5
|
+
import storage from '../utils/storage';
|
|
6
|
+
import { sha256 } from 'react-native-sha256';
|
|
7
|
+
let isFingerprintingInProgress = false;
|
|
8
|
+
export default function () {
|
|
9
|
+
var _state$user5, _state$user5$data, _state$user6, _state$user6$data, _state$user9, _state$user9$data, _state$user10, _state$user10$data;
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
state
|
|
13
|
+
} = useGlobalContext();
|
|
14
|
+
const {
|
|
15
|
+
client: api
|
|
16
|
+
} = useApi();
|
|
17
|
+
/**
|
|
18
|
+
* Computes hashes for all possible lookup fields values coupled with the app ID
|
|
19
|
+
* @param appId
|
|
20
|
+
* @param rawLookupValues
|
|
21
|
+
* @returns array of challenge hashes
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
async function computePossibleChallengeLookupValues(appId, rawLookupValues) {
|
|
25
|
+
const lookupHashes = [];
|
|
26
|
+
|
|
27
|
+
for (const value of rawLookupValues) {
|
|
28
|
+
lookupHashes.push(await sha256(`${appId}:${value}`));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return lookupHashes;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Looks for a challenge in storage based on presented lookup values
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const getChallengeIfPresent = useCallback(async (appId, challengeLookupValues) => {
|
|
39
|
+
if (!appId) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const challenges = JSON.parse(storage.getString('challenges') || '{}');
|
|
44
|
+
|
|
45
|
+
if (!Object.keys(challenges).length) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let challengeKey = '';
|
|
50
|
+
let challengeValue = '';
|
|
51
|
+
|
|
52
|
+
for (const value of challengeLookupValues) {
|
|
53
|
+
const hash = await sha256(`${appId}:${value}`);
|
|
54
|
+
const challenge = Object.entries(challenges).find(_ref => {
|
|
55
|
+
let [, hashes] = _ref;
|
|
56
|
+
return hashes.includes(hash);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (challenge) {
|
|
60
|
+
challengeKey = hash;
|
|
61
|
+
challengeValue = challenge[0];
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!challengeKey || !challengeValue) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
key: challengeKey,
|
|
72
|
+
value: challengeValue
|
|
73
|
+
};
|
|
74
|
+
}, []);
|
|
75
|
+
const getFingerprint = useCallback(async () => {
|
|
76
|
+
const visitorId = DeviceInfo.getDeviceId();
|
|
77
|
+
return {
|
|
78
|
+
visitorId
|
|
79
|
+
};
|
|
80
|
+
}, []);
|
|
81
|
+
const registerFingerprint = useCallback(async () => {
|
|
82
|
+
if (!state.auth.access_token || !state.auth.is_verified_user || !state.app.id || isFingerprintingInProgress) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
isFingerprintingInProgress = true;
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
var _state$user, _state$user$data, _state$user2, _state$user2$data, _state$user3, _state$user3$data, _state$user4, _state$user4$data;
|
|
90
|
+
|
|
91
|
+
// Check for existing challenge
|
|
92
|
+
const challengeEntry = await getChallengeIfPresent(state.app.id, [(_state$user = state.user) === null || _state$user === void 0 ? void 0 : (_state$user$data = _state$user.data) === null || _state$user$data === void 0 ? void 0 : _state$user$data.email, (_state$user2 = state.user) === null || _state$user2 === void 0 ? void 0 : (_state$user2$data = _state$user2.data) === null || _state$user2$data === void 0 ? void 0 : _state$user2$data.phone_number].filter(Boolean));
|
|
93
|
+
const fingerprint = await getFingerprint();
|
|
94
|
+
const payload = await api.post('hub/auth/fingerprints', {
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `Bearer ${state.auth.access_token}`
|
|
97
|
+
},
|
|
98
|
+
json: {
|
|
99
|
+
hash: fingerprint.visitorId,
|
|
100
|
+
challenge: (challengeEntry === null || challengeEntry === void 0 ? void 0 : challengeEntry.value) || null // Might exist from a previous run, in which case this request will be a no-op
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
}).json();
|
|
104
|
+
|
|
105
|
+
if (payload.challenge === (challengeEntry === null || challengeEntry === void 0 ? void 0 : challengeEntry.key)) {
|
|
106
|
+
// This is a no-op
|
|
107
|
+
console.debug('Fingerprint already registered');
|
|
108
|
+
return;
|
|
109
|
+
} // Save the challenge for future sign-ins if we don't have one already or we got a new one from the server
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
const challengeLookupHashes = await computePossibleChallengeLookupValues(state.app.id, [(_state$user3 = state.user) === null || _state$user3 === void 0 ? void 0 : (_state$user3$data = _state$user3.data) === null || _state$user3$data === void 0 ? void 0 : _state$user3$data.email, (_state$user4 = state.user) === null || _state$user4 === void 0 ? void 0 : (_state$user4$data = _state$user4.data) === null || _state$user4$data === void 0 ? void 0 : _state$user4$data.phone_number].filter(Boolean));
|
|
113
|
+
|
|
114
|
+
if (payload.challenge && challengeLookupHashes.length > 0) {
|
|
115
|
+
const challenges = JSON.parse(storage.getString('challenges') || '{}');
|
|
116
|
+
storage.set('challenges', JSON.stringify({ ...challenges,
|
|
117
|
+
[payload.challenge]: challengeLookupHashes
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
} catch (err) {
|
|
121
|
+
console.warn('Failed to register fingerprint', err);
|
|
122
|
+
} finally {
|
|
123
|
+
isFingerprintingInProgress = false;
|
|
124
|
+
}
|
|
125
|
+
}, [api, state.app.id, state.auth.access_token, state.auth.is_verified_user, (_state$user5 = state.user) === null || _state$user5 === void 0 ? void 0 : (_state$user5$data = _state$user5.data) === null || _state$user5$data === void 0 ? void 0 : _state$user5$data.email, (_state$user6 = state.user) === null || _state$user6 === void 0 ? void 0 : (_state$user6$data = _state$user6.data) === null || _state$user6$data === void 0 ? void 0 : _state$user6$data.phone_number, getChallengeIfPresent, getFingerprint]);
|
|
126
|
+
const clearFingerprint = useCallback(challenge => {
|
|
127
|
+
const challenges = JSON.parse(storage.getString('challenges') || '{}');
|
|
128
|
+
delete challenges[challenge];
|
|
129
|
+
storage.set('challenges', JSON.stringify(challenges));
|
|
130
|
+
}, []);
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (!state.auth.access_token) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
(async () => {
|
|
137
|
+
var _state$user7, _state$user7$data, _state$user8, _state$user8$data;
|
|
138
|
+
|
|
139
|
+
// If already fingerprinted, don't try again
|
|
140
|
+
const existingChallenge = await getChallengeIfPresent(state.app.id, [(_state$user7 = state.user) === null || _state$user7 === void 0 ? void 0 : (_state$user7$data = _state$user7.data) === null || _state$user7$data === void 0 ? void 0 : _state$user7$data.email, (_state$user8 = state.user) === null || _state$user8 === void 0 ? void 0 : (_state$user8$data = _state$user8.data) === null || _state$user8$data === void 0 ? void 0 : _state$user8$data.phone_number].filter(Boolean)); // Don't need to re-register a fingerprint if we already have one registered
|
|
141
|
+
|
|
142
|
+
if (existingChallenge) {
|
|
143
|
+
console.debug('Found existing challenge, so not requesting fingerprint registration.');
|
|
144
|
+
return;
|
|
145
|
+
} // We have an access token, so we can use it to get the fingerprint
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
registerFingerprint();
|
|
149
|
+
})();
|
|
150
|
+
}, [getChallengeIfPresent, registerFingerprint, state.app.id, state.auth.access_token, (_state$user9 = state.user) === null || _state$user9 === void 0 ? void 0 : (_state$user9$data = _state$user9.data) === null || _state$user9$data === void 0 ? void 0 : _state$user9$data.email, (_state$user10 = state.user) === null || _state$user10 === void 0 ? void 0 : (_state$user10$data = _state$user10.data) === null || _state$user10$data === void 0 ? void 0 : _state$user10$data.phone_number]);
|
|
151
|
+
return {
|
|
152
|
+
getFingerprint,
|
|
153
|
+
getChallengeIfPresent,
|
|
154
|
+
clearFingerprint
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DeviceInfo","useEffect","useCallback","useApi","useGlobalContext","storage","sha256","isFingerprintingInProgress","state","client","api","computePossibleChallengeLookupValues","appId","rawLookupValues","lookupHashes","value","push","getChallengeIfPresent","challengeLookupValues","challenges","JSON","parse","getString","Object","keys","length","challengeKey","challengeValue","hash","challenge","entries","find","hashes","includes","key","getFingerprint","visitorId","getDeviceId","registerFingerprint","auth","access_token","is_verified_user","app","id","challengeEntry","user","data","email","phone_number","filter","Boolean","fingerprint","payload","post","headers","Authorization","json","console","debug","challengeLookupHashes","set","stringify","err","warn","clearFingerprint","existingChallenge"],"sources":["fingerprint.ts"],"sourcesContent":["import DeviceInfo from 'react-native-device-info';\nimport { useEffect, useCallback } from 'react';\nimport useApi from './api';\nimport { useGlobalContext } from '../components/GlobalContext';\nimport storage from '../utils/storage';\nimport { sha256 } from 'react-native-sha256';\n\ninterface IFingerprint {\n message: string;\n hash: string;\n challenge: string;\n}\n\ninterface IChallenge {\n key: string;\n value: string;\n}\n\nlet isFingerprintingInProgress = false;\n\nexport default function () {\n const { state } = useGlobalContext();\n const { client: api } = useApi();\n\n /**\n * Computes hashes for all possible lookup fields values coupled with the app ID\n * @param appId\n * @param rawLookupValues\n * @returns array of challenge hashes\n */\n async function computePossibleChallengeLookupValues(\n appId: string,\n rawLookupValues: string[]\n ): Promise<string[]> {\n const lookupHashes = [];\n for (const value of rawLookupValues) {\n lookupHashes.push(await sha256(`${appId}:${value}`));\n }\n return lookupHashes;\n }\n\n /**\n * Looks for a challenge in storage based on presented lookup values\n */\n const getChallengeIfPresent = useCallback(\n async (\n appId: string | undefined,\n challengeLookupValues: string[]\n ): Promise<IChallenge | null> => {\n if (!appId) {\n return null;\n }\n\n const challenges: Record<string, string[]> = JSON.parse(\n storage.getString('challenges') || '{}'\n );\n\n if (!Object.keys(challenges).length) {\n return null;\n }\n\n let challengeKey = '';\n let challengeValue = '';\n for (const value of challengeLookupValues) {\n const hash = await sha256(`${appId}:${value}`);\n const challenge = Object.entries(challenges).find(([, hashes]) =>\n hashes.includes(hash)\n );\n\n if (challenge) {\n challengeKey = hash;\n challengeValue = challenge[0];\n break;\n }\n }\n\n if (!challengeKey || !challengeValue) {\n return null;\n }\n\n return {\n key: challengeKey,\n value: challengeValue,\n };\n },\n []\n );\n\n const getFingerprint = useCallback(async () => {\n const visitorId = DeviceInfo.getDeviceId();\n\n return {\n visitorId,\n };\n }, []);\n\n const registerFingerprint = useCallback(async () => {\n if (\n !state.auth.access_token ||\n !state.auth.is_verified_user ||\n !state.app.id ||\n isFingerprintingInProgress\n ) {\n return;\n }\n\n isFingerprintingInProgress = true;\n\n try {\n // Check for existing challenge\n const challengeEntry = await getChallengeIfPresent(\n state.app.id,\n [state.user?.data?.email, state.user?.data?.phone_number].filter(\n Boolean\n )\n );\n\n const fingerprint = await getFingerprint();\n const payload: IFingerprint = await api\n .post('hub/auth/fingerprints', {\n headers: {\n Authorization: `Bearer ${state.auth.access_token}`,\n },\n json: {\n hash: fingerprint.visitorId,\n challenge: challengeEntry?.value || null, // Might exist from a previous run, in which case this request will be a no-op\n },\n })\n .json();\n\n if (payload.challenge === challengeEntry?.key) {\n // This is a no-op\n console.debug('Fingerprint already registered');\n return;\n }\n\n // Save the challenge for future sign-ins if we don't have one already or we got a new one from the server\n const challengeLookupHashes = await computePossibleChallengeLookupValues(\n state.app.id,\n [state.user?.data?.email, state.user?.data?.phone_number].filter(\n Boolean\n )\n );\n if (payload.challenge && challengeLookupHashes.length > 0) {\n const challenges = JSON.parse(storage.getString('challenges') || '{}');\n storage.set(\n 'challenges',\n JSON.stringify({\n ...challenges,\n [payload.challenge]: challengeLookupHashes,\n })\n );\n }\n } catch (err) {\n console.warn('Failed to register fingerprint', err);\n } finally {\n isFingerprintingInProgress = false;\n }\n }, [\n api,\n state.app.id,\n state.auth.access_token,\n state.auth.is_verified_user,\n state.user?.data?.email,\n state.user?.data?.phone_number,\n getChallengeIfPresent,\n getFingerprint,\n ]);\n\n const clearFingerprint = useCallback((challenge: string) => {\n const challenges: Record<string, string[]> = JSON.parse(\n storage.getString('challenges') || '{}'\n );\n delete challenges[challenge];\n storage.set('challenges', JSON.stringify(challenges));\n }, []);\n\n useEffect(() => {\n if (!state.auth.access_token) {\n return;\n }\n\n (async () => {\n // If already fingerprinted, don't try again\n const existingChallenge = await getChallengeIfPresent(\n state.app.id,\n [state.user?.data?.email, state.user?.data?.phone_number].filter(\n Boolean\n )\n );\n\n // Don't need to re-register a fingerprint if we already have one registered\n if (existingChallenge) {\n console.debug(\n 'Found existing challenge, so not requesting fingerprint registration.'\n );\n return;\n }\n\n // We have an access token, so we can use it to get the fingerprint\n registerFingerprint();\n })();\n }, [\n getChallengeIfPresent,\n registerFingerprint,\n state.app.id,\n state.auth.access_token,\n state.user?.data?.email,\n state.user?.data?.phone_number,\n ]);\n\n return {\n getFingerprint,\n getChallengeIfPresent,\n clearFingerprint,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import useApi from './api';
|
|
2
|
+
import useDebounce from './debounce';
|
|
3
|
+
import useInterval from './interval';
|
|
4
|
+
import useNav from './nav';
|
|
5
|
+
import useDeviceFingerprint from './fingerprint';
|
|
6
|
+
export { useApi, useDebounce, useInterval, useNav, useDeviceFingerprint };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useApi","useDebounce","useInterval","useNav","useDeviceFingerprint"],"sources":["index.ts"],"sourcesContent":["import useApi from './api';\nimport useDebounce from './debounce';\nimport useInterval from './interval';\nimport useNav from './nav';\nimport useDeviceFingerprint from './fingerprint';\n\nexport { useApi, useDebounce, useInterval, useNav, useDeviceFingerprint };\n"],"mappings":"AAAA,OAAOA,MAAP,MAAmB,OAAnB;AACA,OAAOC,WAAP,MAAwB,YAAxB;AACA,OAAOC,WAAP,MAAwB,YAAxB;AACA,OAAOC,MAAP,MAAmB,OAAnB;AACA,OAAOC,oBAAP,MAAiC,eAAjC;AAEA,SAASJ,MAAT,EAAiBC,WAAjB,EAA8BC,WAA9B,EAA2CC,MAA3C,EAAmDC,oBAAnD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
function useInterval(callback, delay) {
|
|
4
|
+
const savedCallback = useRef(callback); // Remember the latest callback if it changes.
|
|
5
|
+
|
|
6
|
+
useLayoutEffect(() => {
|
|
7
|
+
savedCallback.current = callback;
|
|
8
|
+
}, [callback]); // Set up the interval.
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
// Don't schedule if no delay is specified.
|
|
12
|
+
// Note: 0 is a valid value for delay.
|
|
13
|
+
if (!delay && delay !== 0) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const id = setInterval(() => savedCallback.current(), delay);
|
|
18
|
+
return () => clearInterval(id);
|
|
19
|
+
}, [delay]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default useInterval;
|
|
23
|
+
//# sourceMappingURL=interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useEffect","useLayoutEffect","useRef","useInterval","callback","delay","savedCallback","current","id","setInterval","clearInterval"],"sources":["interval.ts"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef } from 'react';\n\nfunction useInterval(callback: () => void, delay: number | null) {\n const savedCallback = useRef(callback);\n\n // Remember the latest callback if it changes.\n useLayoutEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval.\n useEffect(() => {\n // Don't schedule if no delay is specified.\n // Note: 0 is a valid value for delay.\n if (!delay && delay !== 0) {\n return;\n }\n\n const id = setInterval(() => savedCallback.current(), delay);\n\n return () => clearInterval(id);\n }, [delay]);\n}\n\nexport default useInterval;\n"],"mappings":"AAAA,SAASA,SAAT,EAAoBC,eAApB,EAAqCC,MAArC,QAAmD,OAAnD;;AAEA,SAASC,WAAT,CAAqBC,QAArB,EAA2CC,KAA3C,EAAiE;EAC/D,MAAMC,aAAa,GAAGJ,MAAM,CAACE,QAAD,CAA5B,CAD+D,CAG/D;;EACAH,eAAe,CAAC,MAAM;IACpBK,aAAa,CAACC,OAAd,GAAwBH,QAAxB;EACD,CAFc,EAEZ,CAACA,QAAD,CAFY,CAAf,CAJ+D,CAQ/D;;EACAJ,SAAS,CAAC,MAAM;IACd;IACA;IACA,IAAI,CAACK,KAAD,IAAUA,KAAK,KAAK,CAAxB,EAA2B;MACzB;IACD;;IAED,MAAMG,EAAE,GAAGC,WAAW,CAAC,MAAMH,aAAa,CAACC,OAAd,EAAP,EAAgCF,KAAhC,CAAtB;IAEA,OAAO,MAAMK,aAAa,CAACF,EAAD,CAA1B;EACD,CAVQ,EAUN,CAACH,KAAD,CAVM,CAAT;AAWD;;AAED,eAAeF,WAAf"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useGlobalContext } from '../components/GlobalContext';
|
|
2
|
+
import { ActionType } from '../data/actions';
|
|
3
|
+
export default function useNav() {
|
|
4
|
+
const {
|
|
5
|
+
dispatch
|
|
6
|
+
} = useGlobalContext();
|
|
7
|
+
return _ref => {
|
|
8
|
+
let {
|
|
9
|
+
route,
|
|
10
|
+
hide
|
|
11
|
+
} = _ref;
|
|
12
|
+
|
|
13
|
+
if (hide) {
|
|
14
|
+
dispatch({
|
|
15
|
+
type: ActionType.SET_CONTAINER_VISIBLE,
|
|
16
|
+
payload: {
|
|
17
|
+
isVisible: false
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
} else if (route) {
|
|
21
|
+
dispatch({
|
|
22
|
+
type: ActionType.CHANGE_ROUTE,
|
|
23
|
+
payload: {
|
|
24
|
+
current_route: route
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=nav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useGlobalContext","ActionType","useNav","dispatch","route","hide","type","SET_CONTAINER_VISIBLE","payload","isVisible","CHANGE_ROUTE","current_route"],"sources":["nav.tsx"],"sourcesContent":["import { useGlobalContext } from '../components/GlobalContext';\nimport { ActionType } from '../data/actions';\n\ninterface INavOpts {\n route?: string;\n hide?: boolean;\n}\n\nexport default function useNav() {\n const { dispatch } = useGlobalContext();\n\n return ({ route, hide }: INavOpts) => {\n if (hide) {\n dispatch({\n type: ActionType.SET_CONTAINER_VISIBLE,\n payload: {\n isVisible: false,\n },\n });\n } else if (route) {\n dispatch({\n type: ActionType.CHANGE_ROUTE,\n payload: {\n current_route: route,\n },\n });\n }\n };\n}\n"],"mappings":"AAAA,SAASA,gBAAT,QAAiC,6BAAjC;AACA,SAASC,UAAT,QAA2B,iBAA3B;AAOA,eAAe,SAASC,MAAT,GAAkB;EAC/B,MAAM;IAAEC;EAAF,IAAeH,gBAAgB,EAArC;EAEA,OAAO,QAA+B;IAAA,IAA9B;MAAEI,KAAF;MAASC;IAAT,CAA8B;;IACpC,IAAIA,IAAJ,EAAU;MACRF,QAAQ,CAAC;QACPG,IAAI,EAAEL,UAAU,CAACM,qBADV;QAEPC,OAAO,EAAE;UACPC,SAAS,EAAE;QADJ;MAFF,CAAD,CAAR;IAMD,CAPD,MAOO,IAAIL,KAAJ,EAAW;MAChBD,QAAQ,CAAC;QACPG,IAAI,EAAEL,UAAU,CAACS,YADV;QAEPF,OAAO,EAAE;UACPG,aAAa,EAAEP;QADR;MAFF,CAAD,CAAR;IAMD;EACF,CAhBD;AAiBD"}
|