@umituz/react-native-auth 2.7.3 → 2.7.6

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.
Files changed (42) hide show
  1. package/package.json +40 -16
  2. package/src/application/ports/IAuthRepository.ts +11 -0
  3. package/src/infrastructure/adapters/StorageProviderAdapter.ts +26 -10
  4. package/src/infrastructure/adapters/UIProviderAdapter.ts +20 -9
  5. package/src/infrastructure/providers/FirebaseAuthProvider.ts +3 -2
  6. package/src/infrastructure/repositories/AuthRepository.ts +91 -0
  7. package/src/infrastructure/services/AuthPackage.ts +14 -6
  8. package/src/infrastructure/services/AuthService.ts +67 -119
  9. package/src/infrastructure/services/GuestModeService.ts +1 -6
  10. package/src/infrastructure/utils/AuthValidation.ts +15 -14
  11. package/src/infrastructure/utils/auth-tracker.util.ts +28 -0
  12. package/src/presentation/components/AccountActions.tsx +38 -50
  13. package/src/presentation/components/AuthBottomSheet.tsx +4 -4
  14. package/src/presentation/components/AuthDivider.tsx +0 -1
  15. package/src/presentation/components/AuthGradientBackground.tsx +1 -1
  16. package/src/presentation/components/AuthLegalLinks.tsx +7 -8
  17. package/src/presentation/components/EditProfileActions.tsx +53 -0
  18. package/src/presentation/components/EditProfileAvatar.tsx +33 -0
  19. package/src/presentation/components/EditProfileForm.tsx +55 -0
  20. package/src/presentation/components/LoginForm.tsx +1 -1
  21. package/src/presentation/components/PasswordMatchIndicator.tsx +6 -14
  22. package/src/presentation/components/PasswordStrengthIndicator.tsx +11 -17
  23. package/src/presentation/components/ProfileBenefitsList.tsx +47 -0
  24. package/src/presentation/components/ProfileSection.tsx +20 -85
  25. package/src/presentation/components/RegisterForm.tsx +6 -6
  26. package/src/presentation/components/SocialLoginButtons.tsx +11 -15
  27. package/src/presentation/hooks/mutations/useAuthMutations.ts +50 -0
  28. package/src/presentation/hooks/useAccountManagement.ts +1 -0
  29. package/src/presentation/hooks/useAuthActions.ts +19 -35
  30. package/src/presentation/hooks/useAuthState.ts +3 -1
  31. package/src/presentation/hooks/useLoginForm.ts +6 -8
  32. package/src/presentation/hooks/useProfileUpdate.ts +7 -7
  33. package/src/presentation/hooks/useRegisterForm.ts +16 -17
  34. package/src/presentation/hooks/useUserProfile.ts +3 -3
  35. package/src/presentation/navigation/AuthNavigator.tsx +10 -6
  36. package/src/presentation/screens/AccountScreen.tsx +9 -1
  37. package/src/presentation/screens/EditProfileScreen.tsx +40 -185
  38. package/src/presentation/screens/LoginScreen.tsx +4 -6
  39. package/src/presentation/screens/RegisterScreen.tsx +4 -6
  40. package/src/presentation/stores/authModalStore.ts +2 -1
  41. package/src/types/external.d.ts +31 -45
  42. package/src/infrastructure/services/AuthCoreService.ts +0 -138
@@ -6,162 +6,133 @@
6
6
  import type { Auth } from "firebase/auth";
7
7
  import type { IAuthService, SignUpParams, SignInParams } from "../../application/ports/IAuthService";
8
8
  import type { IAuthProvider } from "../../application/ports/IAuthProvider";
9
+ import { FirebaseAuthProvider } from "../providers/FirebaseAuthProvider";
9
10
  import type { AuthUser } from "../../domain/entities/AuthUser";
10
11
  import type { AuthConfig } from "../../domain/value-objects/AuthConfig";
11
12
  import { DEFAULT_AUTH_CONFIG } from "../../domain/value-objects/AuthConfig";
12
- import { AuthCoreService } from "./AuthCoreService";
13
- import { GuestModeService, type IStorageProvider } from "./GuestModeService";
13
+ import { AuthRepository } from "../repositories/AuthRepository";
14
+ import { GuestModeService } from "./GuestModeService";
14
15
  import { authEventService } from "./AuthEventService";
15
- import { initializeAuthPackage, getAuthPackage } from "./AuthPackage";
16
- import {
17
- trackPackageError,
18
- addPackageBreadcrumb,
19
- } from "@umituz/react-native-sentry";
16
+ import { authTracker } from "../utils/auth-tracker.util";
17
+ import type { IStorageProvider } from "./AuthPackage";
20
18
 
21
19
  export class AuthService implements IAuthService {
22
- private coreService: AuthCoreService;
20
+ private repository!: AuthRepository;
23
21
  private guestModeService: GuestModeService;
24
22
  private storageProvider?: IStorageProvider;
25
23
  private initialized: boolean = false;
24
+ private config: AuthConfig;
26
25
 
27
26
  constructor(config: Partial<AuthConfig> = {}, storageProvider?: IStorageProvider) {
28
- const authConfig = {
27
+ this.config = {
29
28
  ...DEFAULT_AUTH_CONFIG,
30
29
  ...config,
31
- password: {
32
- ...DEFAULT_AUTH_CONFIG.password,
33
- ...config.password,
34
- },
30
+ password: { ...DEFAULT_AUTH_CONFIG.password, ...config.password },
35
31
  };
32
+ // Initialize with a dummy provider effectively, or null?
33
+ // AuthRepository needs a provider. We can't init it without one.
34
+ // We'll initialize it properly in initialize()
35
+ // For now we can cast null or strict init check.
36
+ // Better: Allow repository to be nullable or initialize with a dummy/proxy.
37
+ // To satisfy strict TS, let's delay repository creation or create a NotInitializedProvider.
38
+ // But since initialize() sets it up, we can use a ! or optional.
36
39
 
37
- this.coreService = new AuthCoreService(authConfig);
38
40
  this.guestModeService = new GuestModeService();
39
41
  this.storageProvider = storageProvider;
42
+
43
+ // We can't instantiate AuthRepository yet if we don't have provider.
44
+ // So we'll have to keep it optional or allow late init.
45
+ }
46
+
47
+ private get repositoryInstance(): AuthRepository {
48
+ if (!this.initialized) throw new Error("AuthService not initialized");
49
+ return this.repository;
40
50
  }
41
51
 
42
52
  async initialize(providerOrAuth: IAuthProvider | Auth): Promise<void> {
43
- if (this.initialized) {
44
- return;
53
+ if (this.initialized) return;
54
+
55
+ let provider: IAuthProvider;
56
+
57
+ // Check if it's a Firebase Auth instance (has currentUser property)
58
+ if ("currentUser" in providerOrAuth) {
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
60
+ const firebaseProvider = new FirebaseAuthProvider(providerOrAuth as any);
61
+ await firebaseProvider.initialize();
62
+ provider = firebaseProvider as unknown as IAuthProvider;
63
+ } else {
64
+ provider = providerOrAuth;
65
+ await provider.initialize();
45
66
  }
46
67
 
47
- // Initialize core service
48
- await this.coreService.initialize(providerOrAuth);
68
+ this.repository = new AuthRepository(provider, this.config);
49
69
 
50
- // Initialize guest mode if storage provider is available
51
70
  if (this.storageProvider) {
52
71
  await this.guestModeService.load(this.storageProvider);
53
72
  }
54
-
55
73
  this.initialized = true;
56
74
  }
57
75
 
58
76
  isInitialized(): boolean {
59
- return this.initialized && this.coreService.isInitialized();
77
+ return this.initialized;
60
78
  }
61
79
 
62
80
  async signUp(params: SignUpParams): Promise<AuthUser> {
63
- addPackageBreadcrumb("auth", "Sign up started", {
64
- email: params.email,
65
- });
66
-
81
+ authTracker.logOperationStarted("Sign up", { email: params.email });
67
82
  try {
68
- const user = await this.coreService.signUp(params);
69
-
70
- // Clear guest mode when user signs up
71
- if (this.guestModeService.getIsGuestMode() && this.storageProvider) {
72
- await this.guestModeService.clear(this.storageProvider);
73
- }
74
-
75
- addPackageBreadcrumb("auth", "Sign up successful", {
76
- userId: user.uid,
77
- });
78
-
83
+ const user = await this.repositoryInstance.signUp(params);
84
+ await this.clearGuestModeIfNeeded();
85
+ authTracker.logOperationSuccess("Sign up", { userId: user.uid });
79
86
  authEventService.emitUserAuthenticated(user.uid);
80
87
  return user;
81
88
  } catch (error) {
82
- trackPackageError(
83
- error instanceof Error ? error : new Error("Sign up failed"),
84
- {
85
- packageName: "auth",
86
- operation: "sign-up",
87
- email: params.email,
88
- }
89
- );
89
+ authTracker.logOperationError("sign-up", error, { email: params.email });
90
90
  throw error;
91
91
  }
92
92
  }
93
93
 
94
94
  async signIn(params: SignInParams): Promise<AuthUser> {
95
- addPackageBreadcrumb("auth", "Sign in started", {
96
- email: params.email,
97
- });
98
-
95
+ authTracker.logOperationStarted("Sign in", { email: params.email });
99
96
  try {
100
- const user = await this.coreService.signIn(params);
101
-
102
- // Clear guest mode when user signs in
103
- if (this.guestModeService.getIsGuestMode() && this.storageProvider) {
104
- await this.guestModeService.clear(this.storageProvider);
105
- }
106
-
107
- addPackageBreadcrumb("auth", "Sign in successful", {
108
- userId: user.uid,
109
- });
110
-
97
+ const user = await this.repositoryInstance.signIn(params);
98
+ await this.clearGuestModeIfNeeded();
99
+ authTracker.logOperationSuccess("Sign in", { userId: user.uid });
111
100
  authEventService.emitUserAuthenticated(user.uid);
112
101
  return user;
113
102
  } catch (error) {
114
- trackPackageError(
115
- error instanceof Error ? error : new Error("Sign in failed"),
116
- {
117
- packageName: "auth",
118
- operation: "sign-in",
119
- email: params.email,
120
- }
121
- );
103
+ authTracker.logOperationError("sign-in", error, { email: params.email });
122
104
  throw error;
123
105
  }
124
106
  }
125
107
 
126
108
  async signOut(): Promise<void> {
127
- addPackageBreadcrumb("auth", "Sign out started");
128
-
109
+ authTracker.logOperationStarted("Sign out");
129
110
  try {
130
- await this.coreService.signOut();
131
-
132
- // Clear guest mode if signing out explicitly
133
- if (this.guestModeService.getIsGuestMode() && this.storageProvider) {
134
- await this.guestModeService.clear(this.storageProvider);
135
- }
136
-
137
- addPackageBreadcrumb("auth", "Sign out successful");
111
+ await this.repositoryInstance.signOut();
112
+ await this.clearGuestModeIfNeeded();
113
+ authTracker.logOperationSuccess("Sign out");
138
114
  } catch (error) {
139
- trackPackageError(
140
- error instanceof Error ? error : new Error("Sign out failed"),
141
- {
142
- packageName: "auth",
143
- operation: "sign-out",
144
- }
145
- );
115
+ authTracker.logOperationError("sign-out", error);
146
116
  throw error;
147
117
  }
148
118
  }
149
119
 
120
+ private async clearGuestModeIfNeeded(): Promise<void> {
121
+ if (this.guestModeService.getIsGuestMode() && this.storageProvider) {
122
+ await this.guestModeService.clear(this.storageProvider);
123
+ }
124
+ }
125
+
150
126
  async setGuestMode(): Promise<void> {
151
127
  if (!this.storageProvider) {
152
128
  throw new Error("Storage provider is required for guest mode");
153
129
  }
154
-
155
- // No provider needed for guest mode enablement
156
-
157
130
  await this.guestModeService.enable(this.storageProvider);
158
131
  }
159
132
 
160
133
  getCurrentUser(): AuthUser | null {
161
- if (this.guestModeService.getIsGuestMode()) {
162
- return null;
163
- }
164
- return this.coreService.getCurrentUser();
134
+ if (!this.initialized) return null;
135
+ return this.guestModeService.getIsGuestMode() ? null : this.repositoryInstance.getCurrentUser();
165
136
  }
166
137
 
167
138
  getIsGuestMode(): boolean {
@@ -170,55 +141,32 @@ export class AuthService implements IAuthService {
170
141
 
171
142
  onAuthStateChange(callback: (user: AuthUser | null) => void): () => void {
172
143
  const wrappedCallback = this.guestModeService.wrapAuthStateCallback(callback);
173
- return this.coreService.onAuthStateChange(wrappedCallback);
174
- }
175
-
176
- getConfig(): AuthConfig {
177
- return this.coreService.getConfig();
178
- }
179
-
180
- getCoreService(): AuthCoreService {
181
- return this.coreService;
144
+ return this.repositoryInstance.onAuthStateChange(wrappedCallback);
182
145
  }
183
146
 
184
- getGuestModeService(): GuestModeService {
185
- return this.guestModeService;
186
- }
147
+ getConfig(): AuthConfig { return this.config; }
148
+ getGuestModeService(): GuestModeService { return this.guestModeService; }
149
+ getRepository(): AuthRepository { return this.repositoryInstance; }
187
150
  }
188
151
 
189
- // Singleton instance
190
152
  let authServiceInstance: AuthService | null = null;
191
153
 
192
- /**
193
- * Initialize auth service with provider or Firebase Auth instance
194
- */
195
154
  export async function initializeAuthService(
196
155
  providerOrAuth: IAuthProvider | Auth,
197
156
  config?: Partial<AuthConfig>,
198
157
  storageProvider?: IStorageProvider
199
158
  ): Promise<AuthService> {
200
159
  if (!authServiceInstance) {
201
- // Initialize package if not already done
202
- const packageConfig = getAuthPackage()?.getConfig();
203
160
  authServiceInstance = new AuthService(config, storageProvider);
204
161
  }
205
162
  await authServiceInstance.initialize(providerOrAuth);
206
163
  return authServiceInstance;
207
164
  }
208
165
 
209
- /**
210
- * Get auth service instance
211
- */
212
166
  export function getAuthService(): AuthService | null {
213
- if (!authServiceInstance || !authServiceInstance.isInitialized()) {
214
- return null;
215
- }
216
- return authServiceInstance;
167
+ return (authServiceInstance && authServiceInstance.isInitialized()) ? authServiceInstance : null;
217
168
  }
218
169
 
219
- /**
220
- * Reset auth service (useful for testing)
221
- */
222
170
  export function resetAuthService(): void {
223
171
  authServiceInstance = null;
224
172
  }
@@ -6,12 +6,7 @@
6
6
  import type { IAuthProvider } from "../../application/ports/IAuthProvider";
7
7
  import type { AuthUser } from "../../domain/entities/AuthUser";
8
8
  import { emitGuestModeEnabled } from "../utils/AuthEventEmitter";
9
-
10
- export interface IStorageProvider {
11
- get(key: string): Promise<string | null>;
12
- set(key: string, value: string): Promise<void>;
13
- remove(key: string): Promise<void>;
14
- }
9
+ import type { IStorageProvider } from "./AuthPackage";
15
10
 
16
11
  export class GuestModeService {
17
12
  private isGuestMode: boolean = false;
@@ -8,7 +8,7 @@ import { getAuthPackage } from "../services/AuthPackage";
8
8
 
9
9
  export interface ValidationResult {
10
10
  isValid: boolean;
11
- error?: string;
11
+ error?: string; // This should be a localization key
12
12
  }
13
13
 
14
14
  export interface PasswordStrengthResult extends ValidationResult {
@@ -58,12 +58,12 @@ function getValidationConfig(): ValidationConfig {
58
58
  */
59
59
  export function validateEmail(email: string): ValidationResult {
60
60
  if (!email || email.trim() === "") {
61
- return { isValid: false, error: "Email is required" };
61
+ return { isValid: false, error: "auth.validation.emailRequired" };
62
62
  }
63
63
 
64
64
  const config = getValidationConfig();
65
65
  if (!config.emailRegex.test(email.trim())) {
66
- return { isValid: false, error: "Please enter a valid email address" };
66
+ return { isValid: false, error: "auth.validation.invalidEmail" };
67
67
  }
68
68
 
69
69
  return { isValid: true };
@@ -75,7 +75,7 @@ export function validateEmail(email: string): ValidationResult {
75
75
  */
76
76
  export function validatePasswordForLogin(password: string): ValidationResult {
77
77
  if (!password || password.length === 0) {
78
- return { isValid: false, error: "Password is required" };
78
+ return { isValid: false, error: "auth.validation.passwordRequired" };
79
79
  }
80
80
 
81
81
  return { isValid: true };
@@ -102,7 +102,7 @@ export function validatePasswordForRegister(
102
102
  if (!password || password.length === 0) {
103
103
  return {
104
104
  isValid: false,
105
- error: "Password is required",
105
+ error: "auth.validation.passwordRequired",
106
106
  requirements,
107
107
  };
108
108
  }
@@ -110,7 +110,7 @@ export function validatePasswordForRegister(
110
110
  if (!requirements.hasMinLength) {
111
111
  return {
112
112
  isValid: false,
113
- error: `Password must be at least ${config.minLength} characters`,
113
+ error: "auth.validation.passwordTooShort",
114
114
  requirements,
115
115
  };
116
116
  }
@@ -118,7 +118,7 @@ export function validatePasswordForRegister(
118
118
  if (config.requireUppercase && !validationConfig.uppercaseRegex.test(password)) {
119
119
  return {
120
120
  isValid: false,
121
- error: "Password must contain at least one uppercase letter",
121
+ error: "auth.validation.passwordRequireUppercase",
122
122
  requirements,
123
123
  };
124
124
  }
@@ -126,7 +126,7 @@ export function validatePasswordForRegister(
126
126
  if (config.requireLowercase && !validationConfig.lowercaseRegex.test(password)) {
127
127
  return {
128
128
  isValid: false,
129
- error: "Password must contain at least one lowercase letter",
129
+ error: "auth.validation.passwordRequireLowercase",
130
130
  requirements,
131
131
  };
132
132
  }
@@ -134,7 +134,7 @@ export function validatePasswordForRegister(
134
134
  if (config.requireNumber && !validationConfig.numberRegex.test(password)) {
135
135
  return {
136
136
  isValid: false,
137
- error: "Password must contain at least one number",
137
+ error: "auth.validation.passwordRequireNumber",
138
138
  requirements,
139
139
  };
140
140
  }
@@ -142,7 +142,7 @@ export function validatePasswordForRegister(
142
142
  if (config.requireSpecialChar && !validationConfig.specialCharRegex.test(password)) {
143
143
  return {
144
144
  isValid: false,
145
- error: "Password must contain at least one special character",
145
+ error: "auth.validation.passwordRequireSpecialChar",
146
146
  requirements,
147
147
  };
148
148
  }
@@ -158,11 +158,11 @@ export function validatePasswordConfirmation(
158
158
  confirmPassword: string
159
159
  ): ValidationResult {
160
160
  if (!confirmPassword) {
161
- return { isValid: false, error: "Please confirm your password" };
161
+ return { isValid: false, error: "auth.validation.confirmPasswordRequired" };
162
162
  }
163
163
 
164
164
  if (password !== confirmPassword) {
165
- return { isValid: false, error: "Passwords do not match" };
165
+ return { isValid: false, error: "auth.validation.passwordsDoNotMatch" };
166
166
  }
167
167
 
168
168
  return { isValid: true };
@@ -176,7 +176,7 @@ export function validateDisplayName(
176
176
  minLength?: number
177
177
  ): ValidationResult {
178
178
  if (!displayName || displayName.trim() === "") {
179
- return { isValid: false, error: "Name is required" };
179
+ return { isValid: false, error: "auth.validation.nameRequired" };
180
180
  }
181
181
 
182
182
  const config = getValidationConfig();
@@ -185,10 +185,11 @@ export function validateDisplayName(
185
185
  if (displayName.trim().length < actualMinLength) {
186
186
  return {
187
187
  isValid: false,
188
- error: `Name must be at least ${actualMinLength} characters`,
188
+ error: "auth.validation.nameTooShort",
189
189
  };
190
190
  }
191
191
 
192
192
  return { isValid: true };
193
193
  }
194
194
 
195
+
@@ -0,0 +1,28 @@
1
+ import {
2
+ trackPackageError as sentryTrack,
3
+ addPackageBreadcrumb as sentryBreadcrumb
4
+ } from "@umituz/react-native-sentry";
5
+
6
+ export const authTracker = {
7
+ logOperationStarted: (operation: string, data?: Record<string, unknown>) => {
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call
9
+ (sentryBreadcrumb as any)("auth", `${operation} started`, data);
10
+ },
11
+
12
+ logOperationSuccess: (operation: string, data?: Record<string, unknown>) => {
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call
14
+ (sentryBreadcrumb as any)("auth", `${operation} successful`, data);
15
+ },
16
+
17
+ logOperationError: (operation: string, error: unknown, metadata?: Record<string, unknown>) => {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-call
19
+ (sentryTrack as any)(
20
+ error instanceof Error ? error : new Error(`${operation} failed`),
21
+ {
22
+ packageName: "auth",
23
+ operation,
24
+ ...metadata,
25
+ }
26
+ );
27
+ }
28
+ };
@@ -5,16 +5,16 @@
5
5
  */
6
6
 
7
7
  import React from "react";
8
- import { View, Text, TouchableOpacity, StyleSheet, Alert } from "react-native";
9
- import { useAppDesignTokens } from "@umituz/react-native-design-system";
8
+ import { View, TouchableOpacity, StyleSheet, Alert } from "react-native";
9
+ import { useAppDesignTokens, AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
10
10
 
11
11
  export interface AccountActionsConfig {
12
- logoutText?: string;
13
- deleteAccountText?: string;
14
- logoutConfirmTitle?: string;
15
- logoutConfirmMessage?: string;
16
- deleteConfirmTitle?: string;
17
- deleteConfirmMessage?: string;
12
+ logoutText: string;
13
+ deleteAccountText: string;
14
+ logoutConfirmTitle: string;
15
+ logoutConfirmMessage: string;
16
+ deleteConfirmTitle: string;
17
+ deleteConfirmMessage: string;
18
18
  onLogout: () => Promise<void>;
19
19
  onDeleteAccount: () => Promise<void>;
20
20
  }
@@ -26,13 +26,12 @@ export interface AccountActionsProps {
26
26
  export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
27
27
  const tokens = useAppDesignTokens();
28
28
  const {
29
- logoutText = "Log Out",
30
- deleteAccountText = "Delete Account",
31
- logoutConfirmTitle = "Log Out?",
32
- logoutConfirmMessage = "Are you sure you want to log out?",
33
- deleteConfirmTitle = "Delete Account?",
34
- deleteConfirmMessage =
35
- "This will permanently delete your account and all data. This action cannot be undone.",
29
+ logoutText,
30
+ deleteAccountText,
31
+ logoutConfirmTitle,
32
+ logoutConfirmMessage,
33
+ deleteConfirmTitle,
34
+ deleteConfirmMessage,
36
35
  onLogout,
37
36
  onDeleteAccount,
38
37
  } = config;
@@ -43,12 +42,14 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
43
42
  {
44
43
  text: logoutText,
45
44
  style: "destructive",
46
- onPress: async () => {
47
- try {
48
- await onLogout();
49
- } catch (error) {
50
- // Silent error handling
51
- }
45
+ onPress: () => {
46
+ void (async () => {
47
+ try {
48
+ await onLogout();
49
+ } catch (error) {
50
+ // Silent error handling
51
+ }
52
+ })();
52
53
  },
53
54
  },
54
55
  ]);
@@ -60,12 +61,14 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
60
61
  {
61
62
  text: deleteAccountText,
62
63
  style: "destructive",
63
- onPress: async () => {
64
- try {
65
- await onDeleteAccount();
66
- } catch (error) {
67
- // Silent error handling
68
- }
64
+ onPress: () => {
65
+ void (async () => {
66
+ try {
67
+ await onDeleteAccount();
68
+ } catch (error) {
69
+ // Silent error handling
70
+ }
71
+ })();
69
72
  },
70
73
  },
71
74
  ]);
@@ -79,15 +82,11 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
79
82
  onPress={handleLogout}
80
83
  activeOpacity={0.7}
81
84
  >
82
- <Text style={[styles.actionIcon, { color: tokens.colors.error }]}>
83
-
84
- </Text>
85
- <Text style={[styles.actionText, { color: tokens.colors.error }]}>
85
+ <AtomicIcon name="logout" size="md" color="error" />
86
+ <AtomicText style={[styles.actionText, { color: tokens.colors.error }]}>
86
87
  {logoutText}
87
- </Text>
88
- <Text style={[styles.chevron, { color: tokens.colors.textTertiary }]}>
89
-
90
- </Text>
88
+ </AtomicText>
89
+ <AtomicIcon name="chevron-right" size="sm" color="secondary" />
91
90
  </TouchableOpacity>
92
91
 
93
92
  {/* Delete Account */}
@@ -96,15 +95,11 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
96
95
  onPress={handleDeleteAccount}
97
96
  activeOpacity={0.7}
98
97
  >
99
- <Text style={[styles.actionIcon, { color: tokens.colors.error }]}>
100
- 🗑
101
- </Text>
102
- <Text style={[styles.actionText, { color: tokens.colors.error }]}>
98
+ <AtomicIcon name="trash-2" size="md" color="error" />
99
+ <AtomicText style={[styles.actionText, { color: tokens.colors.error }]}>
103
100
  {deleteAccountText}
104
- </Text>
105
- <Text style={[styles.chevron, { color: tokens.colors.textTertiary }]}>
106
-
107
- </Text>
101
+ </AtomicText>
102
+ <AtomicIcon name="chevron-right" size="sm" color="secondary" />
108
103
  </TouchableOpacity>
109
104
  </View>
110
105
  );
@@ -123,16 +118,9 @@ const styles = StyleSheet.create({
123
118
  borderWidth: 1,
124
119
  gap: 12,
125
120
  },
126
- actionIcon: {
127
- fontSize: 20,
128
- },
129
121
  actionText: {
130
122
  flex: 1,
131
123
  fontSize: 16,
132
124
  fontWeight: "500",
133
125
  },
134
- chevron: {
135
- fontSize: 24,
136
- fontWeight: "400",
137
- },
138
126
  });
@@ -45,7 +45,7 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
45
45
  }) => {
46
46
  const tokens = useAppDesignTokens();
47
47
  const { t } = useLocalization();
48
- const modalRef = useRef<any>(null);
48
+ const modalRef = useRef<BottomSheetModal>(null);
49
49
 
50
50
  const [googleLoading, setGoogleLoading] = useState(false);
51
51
  const [appleLoading, setAppleLoading] = useState(false);
@@ -138,7 +138,7 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
138
138
  style={styles.closeButton}
139
139
  onPress={handleClose}
140
140
  hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
141
- accessibilityLabel={t("common.close") || "Close"}
141
+ accessibilityLabel={t("common.close")}
142
142
  accessibilityRole="button"
143
143
  >
144
144
  <AtomicIcon name="close" size="md" color="secondary" />
@@ -169,8 +169,8 @@ export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
169
169
  {socialProviders.length > 0 && (
170
170
  <SocialLoginButtons
171
171
  enabledProviders={socialProviders}
172
- onGooglePress={handleGoogleSignIn}
173
- onApplePress={handleAppleSignIn}
172
+ onGooglePress={() => { void handleGoogleSignIn(); }}
173
+ onApplePress={() => { void handleAppleSignIn(); }}
174
174
  googleLoading={googleLoading}
175
175
  appleLoading={appleLoading}
176
176
  />
@@ -21,7 +21,6 @@ export const AuthDivider: React.FC = () => {
21
21
  ]}
22
22
  />
23
23
  <AtomicText
24
- type="caption"
25
24
  style={{
26
25
  color: tokens.colors.textSecondary,
27
26
  marginHorizontal: tokens.spacing.sm,
@@ -13,7 +13,7 @@ export const AuthGradientBackground: React.FC = () => {
13
13
 
14
14
  return (
15
15
  <LinearGradient
16
- colors={[tokens.colors.primary, tokens.colors.secondary]}
16
+ colors={[tokens.colors.primary, tokens.colors.surfaceSecondary]}
17
17
  start={{ x: 0, y: 0 }}
18
18
  end={{ x: 1, y: 1 }}
19
19
  style={StyleSheet.absoluteFill}