@umituz/react-native-auth 4.3.14 → 4.3.16
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/package.json +1 -1
- package/src/application/services/ValidationService.ts +0 -28
- package/src/domain/value-objects/AuthConfig.ts +2 -2
- package/src/infrastructure/adapters/StorageProviderAdapter.ts +1 -1
- package/src/infrastructure/services/AuthEventService.ts +3 -10
- package/src/infrastructure/utils/AuthValidation.ts +2 -2
- package/src/infrastructure/utils/UserMapper.ts +1 -1
- package/src/infrastructure/utils/authConversionDetector.ts +1 -1
- package/src/infrastructure/utils/authStateHandler.ts +1 -1
- package/src/infrastructure/utils/listener/anonymousSignInHandler.ts +3 -3
- package/src/infrastructure/utils/listener/cleanupHandlers.ts +1 -1
- package/src/infrastructure/utils/listener/listenerLifecycle.util.ts +0 -7
- package/src/infrastructure/utils/listener/listenerState.util.ts +3 -23
- package/src/init/index.ts +1 -6
- package/src/presentation/components/AccountActions.tsx +1 -1
- package/src/presentation/components/AuthHeader.tsx +1 -1
- package/src/presentation/components/AuthLegalLinks.tsx +1 -1
- package/src/presentation/components/EditProfileActions.tsx +1 -1
- package/src/presentation/components/EditProfileAvatar.tsx +1 -1
- package/src/presentation/components/EditProfileForm.tsx +1 -1
- package/src/presentation/components/LoginForm.tsx +1 -1
- package/src/presentation/components/PasswordMatchIndicator.tsx +1 -1
- package/src/presentation/components/PasswordStrengthIndicator.tsx +1 -1
- package/src/presentation/components/ProfileBenefitsList.tsx +3 -3
- package/src/presentation/components/RegisterForm.tsx +1 -1
- package/src/presentation/components/SocialLoginButtons.tsx +1 -1
- package/src/presentation/components/form/FormEmailInput.tsx +1 -1
- package/src/presentation/components/form/FormPasswordInput.tsx +1 -1
- package/src/presentation/components/form/FormTextInput.tsx +1 -1
- package/src/presentation/components/form/index.ts +0 -3
- package/src/presentation/hooks/useAuthRequired.ts +1 -1
- package/src/presentation/hooks/useGoogleAuth.ts +0 -2
- package/src/presentation/hooks/useLoginForm.ts +1 -1
- package/src/presentation/hooks/useSocialLogin.ts +0 -1
- package/src/presentation/navigation/AuthNavigator.tsx +27 -25
- package/src/presentation/providers/AuthProvider.tsx +1 -1
- package/src/presentation/screens/EditProfileScreen.tsx +2 -2
- package/src/presentation/screens/PasswordPromptScreen.tsx +0 -1
- package/src/presentation/stores/authModalStore.ts +1 -1
- package/src/presentation/stores/authStore.ts +1 -47
- package/src/presentation/utils/authTransition.util.ts +2 -14
- package/src/presentation/utils/commonStyles.ts +0 -45
- package/src/presentation/utils/form/formErrorUtils.ts +0 -55
- package/src/presentation/utils/form/formValidation.util.ts +0 -12
- package/src/presentation/utils/form/useFormField.hook.ts +1 -51
- package/src/presentation/utils/form/usePasswordValidation.hook.ts +2 -16
- package/src/presentation/utils/passwordPromptCallback.ts +0 -2
- package/src/presentation/utils/socialAuthHandler.util.ts +1 -55
- package/src/infrastructure/utils/AuthErrorMapper.ts +0 -93
- package/src/infrastructure/utils/error/errorCodeMapping.constants.ts +0 -23
- package/src/infrastructure/utils/error/errorExtraction.ts +0 -80
- package/src/infrastructure/utils/error/mappings/actionCodeErrorMappings.ts +0 -26
- package/src/infrastructure/utils/error/mappings/authErrorMappings.ts +0 -69
- package/src/infrastructure/utils/error/mappings/configErrorMappings.ts +0 -31
- package/src/infrastructure/utils/error/mappings/errorMapping.types.ts +0 -12
- package/src/infrastructure/utils/error/mappings/networkErrorMappings.ts +0 -22
- package/src/presentation/utils/authOperation.util.ts +0 -67
- package/src/presentation/utils/form/formFieldState.util.ts +0 -82
- package/src/presentation/utils/form/validation/formValidation.hook.ts +0 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.16",
|
|
4
4
|
"description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -4,41 +4,13 @@
|
|
|
4
4
|
* Follows DDD architecture - presentation imports from application, not infrastructure
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
// Validation functions
|
|
8
7
|
export {
|
|
9
8
|
validateEmail,
|
|
10
9
|
validatePasswordForLogin,
|
|
11
10
|
validatePasswordForRegister,
|
|
12
11
|
validatePasswordConfirmation,
|
|
13
|
-
validateDisplayName,
|
|
14
12
|
} from "../../infrastructure/utils/AuthValidation";
|
|
15
13
|
|
|
16
|
-
// validation types
|
|
17
14
|
export type {
|
|
18
|
-
ValidationResult,
|
|
19
|
-
PasswordStrengthResult,
|
|
20
15
|
PasswordRequirements,
|
|
21
|
-
BaseValidationResult,
|
|
22
|
-
FormValidationError,
|
|
23
|
-
FormValidationResult,
|
|
24
16
|
} from "../../infrastructure/utils/validation/types";
|
|
25
|
-
|
|
26
|
-
// validation helpers
|
|
27
|
-
export {
|
|
28
|
-
isEmpty,
|
|
29
|
-
isEmptyEmail,
|
|
30
|
-
isEmptyPassword,
|
|
31
|
-
isEmptyName,
|
|
32
|
-
isNotEmpty,
|
|
33
|
-
hasContent,
|
|
34
|
-
} from "../../infrastructure/utils/validation/validationHelpers";
|
|
35
|
-
|
|
36
|
-
// Sanitization functions
|
|
37
|
-
export {
|
|
38
|
-
sanitizeEmail,
|
|
39
|
-
sanitizePassword,
|
|
40
|
-
sanitizeName,
|
|
41
|
-
SECURITY_LIMITS,
|
|
42
|
-
} from "../../infrastructure/utils/validation/sanitization";
|
|
43
|
-
|
|
44
|
-
export type { SecurityLimitKey } from "../../infrastructure/utils/validation/sanitization";
|
|
@@ -41,14 +41,14 @@ export const DEFAULT_AUTH_CONFIG: AuthConfig = {
|
|
|
41
41
|
social: DEFAULT_SOCIAL_CONFIG,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
class AuthConfigValidationError extends Error {
|
|
45
45
|
constructor(message: string, public readonly field: string) {
|
|
46
46
|
super(message);
|
|
47
47
|
this.name = "AuthConfigValidationError";
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
function validateAuthConfig(config: Partial<AuthConfig>): void {
|
|
52
52
|
if (config.password) {
|
|
53
53
|
if (typeof config.password.minLength !== "number") {
|
|
54
54
|
throw new AuthConfigValidationError("Password minLength must be a number", "password.minLength");
|
|
@@ -9,7 +9,7 @@ import type { IStorageProvider } from "../types/Storage.types";
|
|
|
9
9
|
* Interface that describes the shape of common storage implementations
|
|
10
10
|
* to avoid using 'any' and resolve lint errors.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
interface StorageLike {
|
|
13
13
|
getString?: (
|
|
14
14
|
key: string,
|
|
15
15
|
defaultValue?: string | null
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
import { DeviceEventEmitter } from "react-native";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
interface AuthEventPayload {
|
|
9
9
|
userId?: string;
|
|
10
10
|
error?: string;
|
|
11
11
|
timestamp: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
interface AuthEventListener {
|
|
15
15
|
(payload: AuthEventPayload): void;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
class AuthEventService {
|
|
19
19
|
private static instance: AuthEventService;
|
|
20
20
|
private listeners: Map<string, AuthEventListener[]> = new Map();
|
|
21
21
|
|
|
@@ -102,14 +102,7 @@ export class AuthEventService {
|
|
|
102
102
|
|
|
103
103
|
export const authEventService = AuthEventService.getInstance();
|
|
104
104
|
|
|
105
|
-
export function emitUserAuthenticated(userId: string): void {
|
|
106
|
-
authEventService.emitUserAuthenticated(userId);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
105
|
export function emitAnonymousModeEnabled(): void {
|
|
110
106
|
authEventService.emitAnonymousModeEnabled();
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
export function emitAuthError(error: string): void {
|
|
114
|
-
authEventService.emitAuthError(error);
|
|
115
|
-
}
|
|
@@ -13,12 +13,12 @@ export type {
|
|
|
13
13
|
PasswordRequirements,
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
interface ValidationConfig {
|
|
17
17
|
emailRegex: RegExp;
|
|
18
18
|
displayNameMinLength: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
const DEFAULT_VAL_CONFIG: ValidationConfig = {
|
|
22
22
|
// More robust email validation:
|
|
23
23
|
// - Local part: alphanumeric, dots (not consecutive), hyphens, underscores, plus
|
|
24
24
|
// - Domain: alphanumeric and hyphens
|
|
@@ -22,7 +22,7 @@ interface FirebaseUserLike {
|
|
|
22
22
|
/**
|
|
23
23
|
* Extract auth provider from Firebase user's providerData
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
function extractProvider(user: FirebaseUserLike): AuthProviderType {
|
|
26
26
|
if (user.isAnonymous) {
|
|
27
27
|
return "anonymous";
|
|
28
28
|
}
|
|
@@ -8,7 +8,7 @@ import { ensureUserDocument } from "@umituz/react-native-firebase";
|
|
|
8
8
|
import { detectConversion, type ConversionState } from "./authConversionDetector";
|
|
9
9
|
import { safeCallback } from "./safeCallback";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface AuthStateHandlerOptions {
|
|
12
12
|
onUserConverted?: (anonymousId: string, authenticatedId: string) => void | Promise<void>;
|
|
13
13
|
onAuthStateChange?: (user: User | null) => void | Promise<void>;
|
|
14
14
|
}
|
|
@@ -11,13 +11,13 @@ const MAX_ANONYMOUS_RETRIES = 2;
|
|
|
11
11
|
const ANONYMOUS_RETRY_DELAY_MS = 1000;
|
|
12
12
|
const ANONYMOUS_SIGNIN_TIMEOUT_MS = 10000;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
interface AnonymousSignInCallbacks {
|
|
15
15
|
onSignInStart: () => void;
|
|
16
16
|
onSignInSuccess: () => void;
|
|
17
17
|
onSignInFailure: (error: Error) => void;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
interface AnonymousSignInOptions {
|
|
21
21
|
maxRetries?: number;
|
|
22
22
|
retryDelay?: number;
|
|
23
23
|
timeout?: number;
|
|
@@ -29,7 +29,7 @@ export interface AnonymousSignInOptions {
|
|
|
29
29
|
* @param callbacks - Callback functions for sign-in events
|
|
30
30
|
* @param options - Configuration options
|
|
31
31
|
*/
|
|
32
|
-
|
|
32
|
+
async function attemptAnonymousSignIn(
|
|
33
33
|
auth: Auth,
|
|
34
34
|
callbacks: AnonymousSignInCallbacks,
|
|
35
35
|
options: AnonymousSignInOptions = {}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
/**
|
|
14
14
|
* Create unsubscribe function that decrements ref count
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
function createUnsubscribeHandler(): () => void {
|
|
17
17
|
return () => {
|
|
18
18
|
const { shouldCleanup } = decrementRefCount();
|
|
19
19
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
// Cleanup handlers
|
|
7
7
|
export {
|
|
8
|
-
createUnsubscribeHandler,
|
|
9
8
|
handleExistingInitialization,
|
|
10
9
|
handleInitializationInProgress,
|
|
11
10
|
} from "./cleanupHandlers";
|
|
@@ -13,12 +12,6 @@ export {
|
|
|
13
12
|
// Setup listener
|
|
14
13
|
export { setupAuthListener } from "./setupListener";
|
|
15
14
|
|
|
16
|
-
// Auth state handler
|
|
17
|
-
export { handleAuthStateChange } from "./authListenerStateHandler";
|
|
18
|
-
|
|
19
|
-
// Anonymous mode handler
|
|
20
|
-
export { handleAnonymousMode } from "./anonymousHandler";
|
|
21
|
-
|
|
22
15
|
// Initialization handlers
|
|
23
16
|
export {
|
|
24
17
|
handleNoFirebaseAuth,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Manages the state of Firebase auth listener initialization and lifecycle
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
interface ListenerState {
|
|
7
7
|
initialized: boolean;
|
|
8
8
|
refCount: number;
|
|
9
9
|
initializationInProgress: boolean;
|
|
@@ -28,27 +28,6 @@ export function isListenerInitialized(): boolean {
|
|
|
28
28
|
return state.initialized;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/**
|
|
32
|
-
* Check if initialization is in progress
|
|
33
|
-
*/
|
|
34
|
-
export function isInitializationInProgress(): boolean {
|
|
35
|
-
return state.initializationInProgress;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Check if anonymous sign-in is in progress
|
|
40
|
-
*/
|
|
41
|
-
export function isAnonymousSignInInProgress(): boolean {
|
|
42
|
-
return state.anonymousSignInInProgress;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Get current reference count
|
|
47
|
-
*/
|
|
48
|
-
export function getRefCount(): number {
|
|
49
|
-
return state.refCount;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
31
|
/**
|
|
53
32
|
* Mark initialization as started
|
|
54
33
|
*/
|
|
@@ -105,7 +84,8 @@ export function decrementRefCount(): { shouldCleanup: boolean; count: number } {
|
|
|
105
84
|
state.unsubscribe !== null &&
|
|
106
85
|
!state.cleanupInProgress;
|
|
107
86
|
|
|
108
|
-
// If cleanup should happen, mark as in progress to prevent concurrent cleanup
|
|
87
|
+
// If cleanup should happen, mark as in progress to prevent concurrent cleanup.
|
|
88
|
+
// This flag is reset in resetListenerState() which MUST be called after cleanup.
|
|
109
89
|
if (shouldCleanup) {
|
|
110
90
|
state.cleanupInProgress = true;
|
|
111
91
|
}
|
package/src/init/index.ts
CHANGED
|
@@ -3,9 +3,4 @@
|
|
|
3
3
|
* Provides factory for creating app initialization modules
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export {
|
|
7
|
-
createAuthInitModule,
|
|
8
|
-
type AuthInitModuleConfig,
|
|
9
|
-
} from './createAuthInitModule';
|
|
10
|
-
|
|
11
|
-
export type { InitModule } from '@umituz/react-native-design-system';
|
|
6
|
+
export { createAuthInitModule } from './createAuthInitModule';
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface AuthHeaderProps {
|
|
6
6
|
title: string;
|
|
7
7
|
subtitle?: string;
|
|
8
8
|
}
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicButton } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface EditProfileActionsProps {
|
|
6
6
|
isSaving?: boolean;
|
|
7
7
|
onSave: () => void;
|
|
8
8
|
onCancel?: () => void;
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicAvatar } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface EditProfileAvatarProps {
|
|
6
6
|
photoURL: string | null;
|
|
7
7
|
displayName: string;
|
|
8
8
|
onPress?: () => void;
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
3
|
import { AtomicInput } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface EditProfileFormProps {
|
|
6
6
|
displayName: string;
|
|
7
7
|
email: string;
|
|
8
8
|
onChangeDisplayName: (value: string) => void;
|
|
@@ -7,7 +7,7 @@ export interface PasswordStrengthTranslations {
|
|
|
7
7
|
minLength: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface PasswordStrengthIndicatorProps {
|
|
11
11
|
translations: PasswordStrengthTranslations;
|
|
12
12
|
requirements: PasswordRequirements;
|
|
13
13
|
showLabels?: boolean;
|
|
@@ -7,7 +7,7 @@ import React from "react";
|
|
|
7
7
|
import { View, StyleSheet } from "react-native";
|
|
8
8
|
import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ProfileBenefitsListProps {
|
|
11
11
|
benefits: string[];
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -15,8 +15,8 @@ export const ProfileBenefitsList: React.FC<ProfileBenefitsListProps> = ({ benefi
|
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
17
|
<View style={styles.benefitsContainer}>
|
|
18
|
-
{benefits.map((benefit
|
|
19
|
-
<View key={
|
|
18
|
+
{benefits.map((benefit) => (
|
|
19
|
+
<View key={benefit} style={styles.benefitItem}>
|
|
20
20
|
<AtomicIcon name="checkmark-circle" size="sm" color="primary" />
|
|
21
21
|
<AtomicText
|
|
22
22
|
type="bodyMedium"
|
|
@@ -27,7 +27,7 @@ export interface RegisterFormTranslations {
|
|
|
27
27
|
passwordMatch: PasswordMatchTranslations;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
interface RegisterFormProps {
|
|
31
31
|
translations: RegisterFormTranslations;
|
|
32
32
|
onNavigateToLogin: () => void;
|
|
33
33
|
termsUrl?: string;
|
|
@@ -9,7 +9,7 @@ export interface SocialLoginButtonsTranslations {
|
|
|
9
9
|
apple: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
interface SocialLoginButtonsProps {
|
|
13
13
|
translations: SocialLoginButtonsTranslations;
|
|
14
14
|
enabledProviders: SocialAuthProvider[];
|
|
15
15
|
onGooglePress?: () => void;
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
|
|
|
2
2
|
import { TextInput, StyleSheet, ViewStyle } from "react-native";
|
|
3
3
|
import { AtomicInput } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface FormEmailInputProps {
|
|
6
6
|
value: string;
|
|
7
7
|
onChangeText: (text: string) => void;
|
|
8
8
|
label: string;
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
|
|
|
2
2
|
import { TextInput, StyleSheet, ViewStyle } from "react-native";
|
|
3
3
|
import { AtomicInput } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface FormPasswordInputProps {
|
|
6
6
|
value: string;
|
|
7
7
|
onChangeText: (text: string) => void;
|
|
8
8
|
label: string;
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
|
|
|
2
2
|
import { TextInput, StyleSheet, ViewStyle } from "react-native";
|
|
3
3
|
import { AtomicInput } from "@umituz/react-native-design-system";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
interface FormTextInputProps {
|
|
6
6
|
value: string;
|
|
7
7
|
onChangeText: (text: string) => void;
|
|
8
8
|
label: string;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
export { FormEmailInput } from "./FormEmailInput";
|
|
2
2
|
export { FormPasswordInput } from "./FormPasswordInput";
|
|
3
3
|
export { FormTextInput } from "./FormTextInput";
|
|
4
|
-
export type { FormEmailInputProps } from "./FormEmailInput";
|
|
5
|
-
export type { FormPasswordInputProps } from "./FormPasswordInput";
|
|
6
|
-
export type { FormTextInputProps } from "./FormTextInput";
|
|
@@ -22,7 +22,7 @@ import { selectIsAuthenticated, selectLoading, selectFirebaseUserId } from "../s
|
|
|
22
22
|
import { useAuthModalStore } from "../stores/authModalStore";
|
|
23
23
|
import { selectShowAuthModal } from "../stores/auth.selectors";
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
interface UseAuthRequiredResult {
|
|
26
26
|
/** Whether user is authenticated (not anonymous) */
|
|
27
27
|
isAllowed: boolean;
|
|
28
28
|
/** Whether auth is still loading */
|
|
@@ -7,7 +7,7 @@ import { sanitizeEmail } from "../../infrastructure/utils/validation/sanitizatio
|
|
|
7
7
|
import { useAuthErrorHandler } from "./useAuthErrorHandler";
|
|
8
8
|
import { useLocalError } from "./useLocalError";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface LoginFormTranslations {
|
|
11
11
|
successTitle: string;
|
|
12
12
|
signInSuccess: string;
|
|
13
13
|
errors: Record<string, string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
StackNavigator,
|
|
4
4
|
useAppDesignTokens,
|
|
@@ -17,12 +17,12 @@ export type AuthStackParamList = {
|
|
|
17
17
|
|
|
18
18
|
const SHOW_REGISTER_KEY = "auth_show_register";
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
interface AuthNavigatorTranslations {
|
|
21
21
|
login: LoginScreenTranslations;
|
|
22
22
|
register: RegisterScreenTranslations;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
interface AuthNavigatorProps {
|
|
26
26
|
translations: AuthNavigatorTranslations;
|
|
27
27
|
termsUrl?: string;
|
|
28
28
|
privacyUrl?: string;
|
|
@@ -57,32 +57,34 @@ export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
|
|
|
57
57
|
void checkInitialRoute();
|
|
58
58
|
}, []);
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{...props}
|
|
69
|
-
translations={translations.login}
|
|
70
|
-
/>
|
|
60
|
+
const LoginScreenWrapper = useCallback(
|
|
61
|
+
(props: StackScreenProps<AuthStackParamList, "Login">) => (
|
|
62
|
+
<LoginScreen
|
|
63
|
+
{...props}
|
|
64
|
+
translations={translations.login}
|
|
65
|
+
/>
|
|
66
|
+
),
|
|
67
|
+
[translations.login]
|
|
71
68
|
);
|
|
72
69
|
|
|
73
|
-
const RegisterScreenWrapper = (
|
|
74
|
-
props: StackScreenProps<AuthStackParamList, "Register">
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
const RegisterScreenWrapper = useCallback(
|
|
71
|
+
(props: StackScreenProps<AuthStackParamList, "Register">) => (
|
|
72
|
+
<RegisterScreen
|
|
73
|
+
{...props}
|
|
74
|
+
translations={translations.register}
|
|
75
|
+
termsUrl={termsUrl}
|
|
76
|
+
privacyUrl={privacyUrl}
|
|
77
|
+
onTermsPress={onTermsPress}
|
|
78
|
+
onPrivacyPress={onPrivacyPress}
|
|
79
|
+
/>
|
|
80
|
+
),
|
|
81
|
+
[translations.register, termsUrl, privacyUrl, onTermsPress, onPrivacyPress]
|
|
84
82
|
);
|
|
85
83
|
|
|
84
|
+
if (initialRouteName === undefined) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
86
88
|
const stackConfig: StackNavigatorConfig<AuthStackParamList> = {
|
|
87
89
|
initialRouteName,
|
|
88
90
|
screenOptions: {
|
|
@@ -14,7 +14,7 @@ import { useEffect, useState, type ReactNode } from "react";
|
|
|
14
14
|
import { View, Text } from "react-native";
|
|
15
15
|
import { initializeAuthListener } from "../stores/initializeAuthListener";
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
interface AuthProviderProps {
|
|
18
18
|
children: ReactNode;
|
|
19
19
|
/**
|
|
20
20
|
* Custom error component to display when auth initialization fails
|
|
@@ -10,7 +10,7 @@ import { EditProfileAvatar } from "../components/EditProfileAvatar";
|
|
|
10
10
|
import { EditProfileForm } from "../components/EditProfileForm";
|
|
11
11
|
import { EditProfileActions } from "../components/EditProfileActions";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
interface EditProfileLabels {
|
|
14
14
|
title: string;
|
|
15
15
|
displayNameLabel: string;
|
|
16
16
|
displayNamePlaceholder: string;
|
|
@@ -22,7 +22,7 @@ export interface EditProfileLabels {
|
|
|
22
22
|
cancelButton: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
interface EditProfileConfig {
|
|
26
26
|
displayName: string;
|
|
27
27
|
email: string;
|
|
28
28
|
photoURL: string | null;
|
|
@@ -101,7 +101,6 @@ export const PasswordPromptScreen: React.FC<PasswordPromptScreenProps> = ({
|
|
|
101
101
|
}}
|
|
102
102
|
placeholder="Password"
|
|
103
103
|
secureTextEntry
|
|
104
|
-
autoFocus
|
|
105
104
|
state={error ? 'error' : 'default'}
|
|
106
105
|
helperText={error}
|
|
107
106
|
style={{ marginBottom: tokens.spacing.md }}
|