Skip to content

Commit

Permalink
feat: Add first time login dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
bruce-glazier committed May 1, 2024
1 parent 9f9de01 commit 604d2d8
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 6 deletions.
1 change: 1 addition & 0 deletions example/AppDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function App() {
primaryColor: '#fb5607',
},
apiBaseURL: baseURL,
showPreLoginWarning: false,
}}
>
<RootProviders account="mockaccount" authConfig={authConfig}>
Expand Down
1 change: 1 addition & 0 deletions src/common/DeveloperConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export type DeveloperConfig = {
navigationLinking?: LinkingOptions<any>;
skipInviteParams?: boolean;
tileListMode?: 'list' | 'column';
showPreLoginWarning?: boolean;
};

export type LogoHeaderConfig = { [key in Route]?: LogoHeaderOptions };
Expand Down
49 changes: 44 additions & 5 deletions src/components/OAuthLoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,35 @@ import { useStyles } from '../hooks/useStyles';
import { LoginParams, useOAuthFlow } from '../hooks/useOAuthFlow';
import { tID } from '../common/testID';
import { createStyles } from './BrandConfigProvider';
import { useStoredValue } from '../hooks/useStoredValue';
import { useDeveloperConfig } from '../hooks/useDeveloperConfig';
import { t } from 'i18next';
import { Alert } from 'react-native';
import { usePendingInvite } from './Invitations/InviteProvider';

type Props = Omit<ButtonProps, 'onPress' | 'style' | 'children'> &
LoginParams & {
label: string;
style?: OAuthLoginButtonStyles;
};

const newLoginAlert = () => {
return new Promise<Boolean>((resolve) => {
Alert.alert(
t('new-login-title', 'New Login Notice'),
t(
'new-login-notice',
'NOTE: This device has not yet been used to login to the app.\nIf this is your first time using this app then you must first be invited to use this app via email.',
),
[
{ text: 'Proceed Anyway', onPress: () => resolve(true) },
{ text: 'Return', onPress: () => resolve(false) },
],
{ cancelable: false },
);
});
};

export function OAuthLoginButton({
onSuccess,
onFail,
Expand All @@ -21,13 +43,30 @@ export function OAuthLoginButton({
}: Props) {
const { styles } = useStyles(defaultStyles, instanceStyles);
const { login } = useOAuthFlow();
const [priorLoginDetected] = useStoredValue('loginDetected');
const { showPreLoginWarning } = useDeveloperConfig();
const pendingInvite = usePendingInvite();

const handleOnPress = useCallback(async () => {
await login({
onSuccess,
onFail,
});
}, [login, onSuccess, onFail]);
if (showPreLoginWarning && !pendingInvite && !priorLoginDetected) {
// If attempting to login for the first time without a pending invite
// let the user know that they are probably making a mistake
// This can be disabled via developerConfig
const result = await newLoginAlert();
if (result) {
await login({ onSuccess, onFail });
}
} else {
await login({ onSuccess, onFail });
}
}, [
pendingInvite,
priorLoginDetected,
showPreLoginWarning,
login,
onSuccess,
onFail,
]);

return (
<Button
Expand Down
11 changes: 10 additions & 1 deletion src/hooks/useOAuthFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { usePendingInvite } from '../components/Invitations/InviteProvider';
import { useQueryClient } from '@tanstack/react-query';
import { _sdkAnalyticsEvent } from '../common/Analytics';
import { useDeveloperConfig } from './useDeveloperConfig';
import { useStoredValue } from './useStoredValue';

export interface OAuthConfig {
login: (params: LoginParams) => Promise<void>;
Expand Down Expand Up @@ -78,6 +79,7 @@ export const OAuthContextProvider = ({
const pendingInvite = usePendingInvite();
const queryClient = useQueryClient();
const { skipInviteParams } = useDeveloperConfig();
const [_, setLoginDetected] = useStoredValue('loginDetected');

const authConfig = useMemo(
() =>
Expand Down Expand Up @@ -159,6 +161,7 @@ export const OAuthContextProvider = ({
try {
const result = await authorize(authConfig);
await storeAuthResult(result);
setLoginDetected('detected');
_sdkAnalyticsEvent.track('Login', { usedInvite: !!pendingInvite?.evc });
onSuccess?.(result);
} catch (error) {
Expand All @@ -170,7 +173,13 @@ export const OAuthContextProvider = ({
onFail?.(error);
}
},
[authConfig, clearAuthResult, pendingInvite?.evc, storeAuthResult],
[
authConfig,
clearAuthResult,
pendingInvite?.evc,
setLoginDetected,
storeAuthResult,
],
);

const refreshHandler = useCallback(
Expand Down

0 comments on commit 604d2d8

Please sign in to comment.