@umituz/react-native-auth 3.4.32 → 3.4.34
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/README.md +347 -348
- package/package.json +2 -3
- package/src/application/README.md +323 -442
- package/src/domain/ConfigAndErrors.md +296 -431
- package/src/domain/README.md +361 -210
- package/src/domain/entities/AuthUser.md +231 -372
- package/src/domain/entities/UserProfile.md +271 -441
- package/src/index.ts +35 -0
- package/src/infrastructure/README.md +388 -444
- package/src/infrastructure/services/README.md +386 -312
- package/src/infrastructure/utils/validation/BaseValidators.ts +35 -0
- package/src/infrastructure/utils/validation/CollectionValidators.ts +56 -0
- package/src/infrastructure/utils/validation/DateValidators.ts +63 -0
- package/src/infrastructure/utils/validation/FormValidators.ts +22 -0
- package/src/infrastructure/utils/validation/NumberValidators.ts +55 -0
- package/src/infrastructure/utils/validation/StringValidators.ts +55 -0
- package/src/infrastructure/utils/validation/sanitization.ts +98 -0
- package/src/infrastructure/utils/validation/types.ts +15 -0
- package/src/presentation/README.md +631 -563
- package/src/presentation/components/ProfileComponents.md +307 -504
- package/src/presentation/components/README.md +254 -92
- package/src/presentation/hooks/README.md +247 -83
- package/src/presentation/hooks/useAccountManagement.md +295 -344
- package/src/presentation/hooks/useAuth.md +271 -227
- package/src/presentation/hooks/useAuthBottomSheet.md +417 -367
- package/src/presentation/hooks/useAuthRequired.md +308 -194
- package/src/presentation/hooks/useProfileUpdate.md +251 -279
- package/src/presentation/hooks/useSocialLogin.md +312 -287
- package/src/presentation/hooks/useUserProfile.md +259 -192
- package/src/presentation/screens/README.md +151 -153
|
@@ -1,414 +1,464 @@
|
|
|
1
1
|
# useAuthBottomSheet
|
|
2
2
|
|
|
3
|
-
Hook for authentication bottom sheet
|
|
3
|
+
Hook for authentication bottom sheet modal management.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Login/Register mode switching
|
|
9
|
-
- Social authentication integration
|
|
10
|
-
- Auto-close on successful auth
|
|
11
|
-
- Pending callback management
|
|
7
|
+
## Strategy
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
**Purpose**: Manages authentication modal (bottom sheet) with login/register forms, social authentication, and auto-close behavior. Integrates with auth modal store for global state management.
|
|
14
10
|
|
|
11
|
+
**When to Use**:
|
|
12
|
+
- Need modal-based authentication flow
|
|
13
|
+
- Want to show login/register on demand
|
|
14
|
+
- Need social auth in modal
|
|
15
|
+
- Want auto-close after successful auth
|
|
16
|
+
- Require pending callback execution
|
|
17
|
+
|
|
18
|
+
**Import Path**:
|
|
15
19
|
```typescript
|
|
16
20
|
import { useAuthBottomSheet } from '@umituz/react-native-auth';
|
|
17
|
-
import { BottomSheetModal } from '@umituz/react-native-design-system';
|
|
18
|
-
|
|
19
|
-
function AuthBottomSheet() {
|
|
20
|
-
const {
|
|
21
|
-
modalRef,
|
|
22
|
-
mode,
|
|
23
|
-
providers,
|
|
24
|
-
googleLoading,
|
|
25
|
-
appleLoading,
|
|
26
|
-
handleDismiss,
|
|
27
|
-
handleClose,
|
|
28
|
-
handleNavigateToRegister,
|
|
29
|
-
handleNavigateToLogin,
|
|
30
|
-
handleGoogleSignIn,
|
|
31
|
-
handleAppleSignIn,
|
|
32
|
-
} = useAuthBottomSheet({
|
|
33
|
-
socialConfig: {
|
|
34
|
-
google: {
|
|
35
|
-
iosClientId: 'your-ios-client-id',
|
|
36
|
-
webClientId: 'your-web-client-id',
|
|
37
|
-
},
|
|
38
|
-
apple: { enabled: true },
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<BottomSheetModal ref={modalRef} onDismiss={handleDismiss}>
|
|
44
|
-
{mode === 'login' ? (
|
|
45
|
-
<LoginForm
|
|
46
|
-
onRegisterPress={handleNavigateToRegister}
|
|
47
|
-
onGoogleSignIn={handleGoogleSignIn}
|
|
48
|
-
onAppleSignIn={handleAppleSignIn}
|
|
49
|
-
googleLoading={googleLoading}
|
|
50
|
-
appleLoading={appleLoading}
|
|
51
|
-
/>
|
|
52
|
-
) : (
|
|
53
|
-
<RegisterForm
|
|
54
|
-
onLoginPress={handleNavigateToLogin}
|
|
55
|
-
onGoogleSignIn={handleGoogleSignIn}
|
|
56
|
-
onAppleSignIn={handleAppleSignIn}
|
|
57
|
-
googleLoading={googleLoading}
|
|
58
|
-
appleLoading={appleLoading}
|
|
59
|
-
/>
|
|
60
|
-
)}
|
|
61
|
-
</BottomSheetModal>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
21
|
```
|
|
65
22
|
|
|
66
|
-
|
|
23
|
+
**Hook Location**: `src/presentation/hooks/useAuthBottomSheet.ts`
|
|
67
24
|
|
|
68
|
-
|
|
25
|
+
**Modal Store**: `src/presentation/stores/authModalStore.ts`
|
|
69
26
|
|
|
70
|
-
|
|
71
|
-
|-------|------|----------|-------------|
|
|
72
|
-
| `socialConfig` | `SocialAuthConfiguration` | No | Social auth configuration |
|
|
73
|
-
| `onGoogleSignIn` | `() => Promise<void>` | No | Custom Google sign-in handler |
|
|
74
|
-
| `onAppleSignIn` | `() => Promise<void>` | No | Custom Apple sign-in handler |
|
|
27
|
+
**Modal Component**: `@umituz/react-native-design-system`'s `BottomSheetModal`
|
|
75
28
|
|
|
76
|
-
|
|
29
|
+
---
|
|
77
30
|
|
|
78
|
-
|
|
79
|
-
interface SocialAuthConfiguration {
|
|
80
|
-
google?: GoogleAuthConfig;
|
|
81
|
-
apple?: { enabled: boolean };
|
|
82
|
-
}
|
|
83
|
-
```
|
|
31
|
+
## Core Functionality
|
|
84
32
|
|
|
85
|
-
###
|
|
33
|
+
### Modal Reference
|
|
86
34
|
|
|
87
|
-
|
|
88
|
-
|------|------|-------------|
|
|
89
|
-
| `modalRef` | `RefObject<BottomSheetModalRef>` | Bottom sheet modal reference |
|
|
90
|
-
| `mode` | `'login' \| 'register'` | Current mode |
|
|
91
|
-
| `providers` | `SocialAuthProvider[]` | Available social providers |
|
|
92
|
-
| `googleLoading` | `boolean` | Google loading state |
|
|
93
|
-
| `appleLoading` | `boolean` | Apple loading state |
|
|
94
|
-
| `handleDismiss` | `() => void` | Dismiss modal |
|
|
95
|
-
| `handleClose` | `() => void` | Close modal and cleanup |
|
|
96
|
-
| `handleNavigateToRegister` | `() => void` | Switch to register mode |
|
|
97
|
-
| `handleNavigateToLogin` | `() => void` | Switch to login mode |
|
|
98
|
-
| `handleGoogleSignIn` | `() => Promise<void>` | Google sign-in handler |
|
|
99
|
-
| `handleAppleSignIn` | `() => Promise<void>` | Apple sign-in handler |
|
|
35
|
+
**Purpose**: Ref object for controlling bottom sheet modal.
|
|
100
36
|
|
|
101
|
-
|
|
37
|
+
**PROPERTIES**:
|
|
38
|
+
- Type: `RefObject<BottomSheetModalRef>`
|
|
39
|
+
- Used to: Open, close, and control modal
|
|
102
40
|
|
|
103
|
-
|
|
41
|
+
**Rules**:
|
|
42
|
+
- MUST pass to BottomSheetModal component
|
|
43
|
+
- MUST use for programmatic control
|
|
44
|
+
- MUST not create multiple refs
|
|
104
45
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
mode,
|
|
110
|
-
handleDismiss,
|
|
111
|
-
handleNavigateToRegister,
|
|
112
|
-
handleNavigateToLogin,
|
|
113
|
-
} = useAuthBottomSheet();
|
|
114
|
-
|
|
115
|
-
return (
|
|
116
|
-
<BottomSheetModal ref={modalRef} snapPoints={['80%']} onDismiss={handleDismiss}>
|
|
117
|
-
<View>
|
|
118
|
-
{mode === 'login' ? (
|
|
119
|
-
<>
|
|
120
|
-
<Text>Sign In</Text>
|
|
121
|
-
<LoginForm />
|
|
122
|
-
<Button onPress={handleNavigateToRegister}>
|
|
123
|
-
Don't have an account? Sign Up
|
|
124
|
-
</Button>
|
|
125
|
-
</>
|
|
126
|
-
) : (
|
|
127
|
-
<>
|
|
128
|
-
<Text>Sign Up</Text>
|
|
129
|
-
<RegisterForm />
|
|
130
|
-
<Button onPress={handleNavigateToLogin}>
|
|
131
|
-
Already have an account? Sign In
|
|
132
|
-
</Button>
|
|
133
|
-
</>
|
|
134
|
-
)}
|
|
135
|
-
</View>
|
|
136
|
-
</BottomSheetModal>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
```
|
|
46
|
+
**Constraints**:
|
|
47
|
+
- Single modal instance
|
|
48
|
+
- Managed by authModalStore
|
|
49
|
+
- Ref persists across renders
|
|
140
50
|
|
|
141
|
-
|
|
51
|
+
---
|
|
142
52
|
|
|
143
|
-
|
|
144
|
-
function AuthBottomSheetWithSocial() {
|
|
145
|
-
const {
|
|
146
|
-
modalRef,
|
|
147
|
-
mode,
|
|
148
|
-
providers,
|
|
149
|
-
googleLoading,
|
|
150
|
-
appleLoading,
|
|
151
|
-
handleDismiss,
|
|
152
|
-
handleNavigateToRegister,
|
|
153
|
-
handleNavigateToLogin,
|
|
154
|
-
handleGoogleSignIn,
|
|
155
|
-
handleAppleSignIn,
|
|
156
|
-
} = useAuthBottomSheet({
|
|
157
|
-
socialConfig: {
|
|
158
|
-
google: {
|
|
159
|
-
webClientId: Config.GOOGLE_WEB_CLIENT_ID,
|
|
160
|
-
iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
|
|
161
|
-
},
|
|
162
|
-
apple: { enabled: Platform.OS === 'ios' },
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
return (
|
|
167
|
-
<BottomSheetModal ref={modalRef} snapPoints={['90%']} onDismiss={handleDismiss}>
|
|
168
|
-
<View>
|
|
169
|
-
{mode === 'login' ? (
|
|
170
|
-
<>
|
|
171
|
-
<LoginForm />
|
|
172
|
-
|
|
173
|
-
{/* Social login buttons */}
|
|
174
|
-
{providers.includes('google') && (
|
|
175
|
-
<SocialButton
|
|
176
|
-
provider="google"
|
|
177
|
-
onPress={handleGoogleSignIn}
|
|
178
|
-
loading={googleLoading}
|
|
179
|
-
/>
|
|
180
|
-
)}
|
|
181
|
-
|
|
182
|
-
{providers.includes('apple') && (
|
|
183
|
-
<SocialButton
|
|
184
|
-
provider="apple"
|
|
185
|
-
onPress={handleAppleSignIn}
|
|
186
|
-
loading={appleLoading}
|
|
187
|
-
/>
|
|
188
|
-
)}
|
|
189
|
-
|
|
190
|
-
<Button onPress={handleNavigateToRegister}>
|
|
191
|
-
Sign Up
|
|
192
|
-
</Button>
|
|
193
|
-
</>
|
|
194
|
-
) : (
|
|
195
|
-
<>
|
|
196
|
-
<RegisterForm />
|
|
197
|
-
|
|
198
|
-
{/* Social login buttons */}
|
|
199
|
-
{providers.includes('google') && (
|
|
200
|
-
<SocialButton
|
|
201
|
-
provider="google"
|
|
202
|
-
onPress={handleGoogleSignIn}
|
|
203
|
-
loading={googleLoading}
|
|
204
|
-
/>
|
|
205
|
-
)}
|
|
206
|
-
|
|
207
|
-
{providers.includes('apple') && (
|
|
208
|
-
<SocialButton
|
|
209
|
-
provider="apple"
|
|
210
|
-
onPress={handleAppleSignIn}
|
|
211
|
-
loading={appleLoading}
|
|
212
|
-
/>
|
|
213
|
-
)}
|
|
214
|
-
|
|
215
|
-
<Button onPress={handleNavigateToLogin}>
|
|
216
|
-
Sign In
|
|
217
|
-
</Button>
|
|
218
|
-
</>
|
|
219
|
-
)}
|
|
220
|
-
</View>
|
|
221
|
-
</BottomSheetModal>
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
```
|
|
53
|
+
### Mode Management
|
|
225
54
|
|
|
226
|
-
|
|
55
|
+
**Purpose**: Tracks current modal mode (login or register).
|
|
227
56
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
57
|
+
**VALUES**:
|
|
58
|
+
- `'login'` - Show login form
|
|
59
|
+
- `'register'` - Show registration form
|
|
60
|
+
|
|
61
|
+
**Rules**:
|
|
62
|
+
- MUST display appropriate form based on mode
|
|
63
|
+
- MUST switch forms when mode changes
|
|
64
|
+
- MUST preserve mode during modal open
|
|
65
|
+
- MUST reset to default on close
|
|
66
|
+
|
|
67
|
+
**Constraints**:
|
|
68
|
+
- Controlled by authModalStore
|
|
69
|
+
- Default mode: `'login'`
|
|
70
|
+
- Switchable via navigation handlers
|
|
71
|
+
- Auto-reset on modal close
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### Provider Detection
|
|
76
|
+
|
|
77
|
+
**Purpose**: Automatically determines which social providers are available.
|
|
78
|
+
|
|
79
|
+
**VALUES**:
|
|
80
|
+
- Type: `SocialAuthProvider[]`
|
|
81
|
+
- Possible: `['google']`, `['apple']`, `['google', 'apple']`, `[]`
|
|
82
|
+
|
|
83
|
+
**Rules**:
|
|
84
|
+
- MUST check provider availability
|
|
85
|
+
- MUST respect platform limitations
|
|
86
|
+
- MUST filter based on configuration
|
|
87
|
+
- MUST update on config changes
|
|
88
|
+
|
|
89
|
+
**Constraints**:
|
|
90
|
+
- Platform-dependent:
|
|
91
|
+
- iOS: Google + Apple (if configured)
|
|
92
|
+
- Android: Google only
|
|
93
|
+
- Web: Google only
|
|
94
|
+
- Configuration-dependent
|
|
95
|
+
- Auto-calculated from config
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Navigation Handlers
|
|
100
|
+
|
|
101
|
+
### handleNavigateToRegister
|
|
102
|
+
|
|
103
|
+
**Purpose**: Switch modal from login to register mode.
|
|
104
|
+
|
|
105
|
+
**Rules**:
|
|
106
|
+
- MUST change mode to `'register'`
|
|
107
|
+
- MUST keep modal open
|
|
108
|
+
- MUST update form display
|
|
109
|
+
|
|
110
|
+
**Constraints**:
|
|
111
|
+
- No modal close/open cycle
|
|
112
|
+
- Smooth form transition
|
|
113
|
+
- Preserves any input data (if applicable)
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### handleNavigateToLogin
|
|
118
|
+
|
|
119
|
+
**Purpose**: Switch modal from register to login mode.
|
|
120
|
+
|
|
121
|
+
**Rules**:
|
|
122
|
+
- MUST change mode to `'login'`
|
|
123
|
+
- MUST keep modal open
|
|
124
|
+
- MUST update form display
|
|
125
|
+
|
|
126
|
+
**Constraints**:
|
|
127
|
+
- No modal close/open cycle
|
|
128
|
+
- Smooth form transition
|
|
129
|
+
- Clears register form data
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### handleDismiss
|
|
134
|
+
|
|
135
|
+
**Purpose**: Handle modal dismiss event (user swipes down or taps backdrop).
|
|
136
|
+
|
|
137
|
+
**Rules**:
|
|
138
|
+
- MUST reset modal state
|
|
139
|
+
- MUST clear mode to default
|
|
140
|
+
- MUST clear any pending callbacks
|
|
141
|
+
- MUST handle cleanup
|
|
142
|
+
|
|
143
|
+
**Constraints**:
|
|
144
|
+
- Called by BottomSheetModal onDismiss
|
|
145
|
+
- Auto-executed on user action
|
|
146
|
+
- Cleanup required
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### handleClose
|
|
151
|
+
|
|
152
|
+
**Purpose**: Programmatically close modal and cleanup.
|
|
153
|
+
|
|
154
|
+
**Rules**:
|
|
155
|
+
- MUST close modal
|
|
156
|
+
- MUST reset modal state
|
|
157
|
+
- MUST clear pending callbacks
|
|
158
|
+
- MUST execute cleanup
|
|
159
|
+
|
|
160
|
+
**Constraints**:
|
|
161
|
+
- Programmatic close
|
|
162
|
+
- Same cleanup as dismiss
|
|
163
|
+
- Safe to call multiple times
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Social Authentication
|
|
168
|
+
|
|
169
|
+
### handleGoogleSignIn
|
|
170
|
+
|
|
171
|
+
**Purpose**: Initiate Google OAuth flow from modal.
|
|
172
|
+
|
|
173
|
+
**Rules**:
|
|
174
|
+
- MUST call Google auth function
|
|
175
|
+
- MUST handle loading state
|
|
176
|
+
- MUST display errors to user
|
|
177
|
+
- MUST auto-close modal on success
|
|
178
|
+
|
|
179
|
+
**MUST NOT**:
|
|
180
|
+
- Call if provider not configured
|
|
181
|
+
- Leave loading state indefinitely
|
|
182
|
+
- Ignore auth results
|
|
183
|
+
|
|
184
|
+
**Constraints**:
|
|
185
|
+
- Uses configured Google client IDs
|
|
186
|
+
- Auto-closes on successful auth
|
|
187
|
+
- Stays open on failure (for retry)
|
|
188
|
+
- Loading state managed automatically
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
### handleAppleSignIn
|
|
193
|
+
|
|
194
|
+
**Purpose**: Initiate Apple Sign-In flow from modal.
|
|
195
|
+
|
|
196
|
+
**Rules**:
|
|
197
|
+
- MUST call Apple auth function
|
|
198
|
+
- MUST handle loading state
|
|
199
|
+
- MUST display errors to user
|
|
200
|
+
- MUST auto-close modal on success
|
|
201
|
+
|
|
202
|
+
**MUST NOT**:
|
|
203
|
+
- Call if provider not available
|
|
204
|
+
- Call on non-iOS platforms
|
|
205
|
+
- Leave loading state indefinitely
|
|
206
|
+
|
|
207
|
+
**Constraints**:
|
|
208
|
+
- iOS only (hidden on other platforms)
|
|
209
|
+
- Requires Apple Developer account
|
|
210
|
+
- Auto-closes on successful auth
|
|
211
|
+
- Stays open on failure (for retry)
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Auto-Close Behavior
|
|
216
|
+
|
|
217
|
+
### Strategy
|
|
279
218
|
|
|
280
|
-
|
|
219
|
+
**Purpose**: Automatically close modal after successful authentication.
|
|
281
220
|
|
|
221
|
+
**Rules**:
|
|
222
|
+
- MUST close modal on successful auth
|
|
223
|
+
- MUST execute pending callback after close
|
|
224
|
+
- MUST not close on auth failure
|
|
225
|
+
- MUST not close if user cancels
|
|
226
|
+
|
|
227
|
+
**MUST NOT**:
|
|
228
|
+
- Stay open after successful auth
|
|
229
|
+
- Close prematurely during auth flow
|
|
230
|
+
- Execute callback before auth complete
|
|
231
|
+
|
|
232
|
+
### Constraints
|
|
233
|
+
|
|
234
|
+
**AUTO-CLOSE TRIGGERS**:
|
|
235
|
+
- Anonymous → Authenticated: Close modal
|
|
236
|
+
- Unauthenticated → Authenticated: Close modal
|
|
237
|
+
- Authenticated → Authenticated (reauth): No close needed
|
|
238
|
+
|
|
239
|
+
**PENDING CALLBACKS**:
|
|
240
|
+
- Stored in authModalStore
|
|
241
|
+
- Executed after successful auth
|
|
242
|
+
- Cleared after execution
|
|
243
|
+
- Can be action (navigate, API call, etc.)
|
|
244
|
+
|
|
245
|
+
**NO-CLOSE SCENARIOS**:
|
|
246
|
+
- Authentication failure
|
|
247
|
+
- User cancellation
|
|
248
|
+
- Network errors
|
|
249
|
+
- Validation errors
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Pending Callbacks
|
|
254
|
+
|
|
255
|
+
### Strategy
|
|
256
|
+
|
|
257
|
+
**Purpose**: Execute callback after successful authentication.
|
|
258
|
+
|
|
259
|
+
**Use Cases**:
|
|
260
|
+
- Retry protected action after auth
|
|
261
|
+
- Navigate to intended destination
|
|
262
|
+
- Trigger post-auth operations
|
|
263
|
+
- Restore user flow
|
|
264
|
+
|
|
265
|
+
**Rules**:
|
|
266
|
+
- MUST store callback before showing modal
|
|
267
|
+
- MUST execute after successful auth
|
|
268
|
+
- MUST clear after execution
|
|
269
|
+
- MUST handle callback errors
|
|
270
|
+
|
|
271
|
+
**MUST NOT**:
|
|
272
|
+
- Execute callback before auth
|
|
273
|
+
- Forget callback after auth
|
|
274
|
+
- Execute multiple times
|
|
275
|
+
- Lose callback context
|
|
276
|
+
|
|
277
|
+
### Constraints
|
|
278
|
+
|
|
279
|
+
**CALLBACK TYPES**:
|
|
280
|
+
- Navigation function
|
|
281
|
+
- Async operation
|
|
282
|
+
- State update
|
|
283
|
+
- Any void-returning function
|
|
284
|
+
|
|
285
|
+
**EXECUTION TIMING**:
|
|
286
|
+
- After successful authentication
|
|
287
|
+
- Before modal close
|
|
288
|
+
- Before UI updates
|
|
289
|
+
- Can be async
|
|
290
|
+
|
|
291
|
+
**ERROR HANDLING**:
|
|
292
|
+
- Catch callback errors
|
|
293
|
+
- Show error to user
|
|
294
|
+
- Don't block auth completion
|
|
295
|
+
- Log errors for debugging
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Configuration
|
|
300
|
+
|
|
301
|
+
### Social Authentication Config
|
|
302
|
+
|
|
303
|
+
**socialConfig** parameter structure:
|
|
304
|
+
|
|
305
|
+
**GOOGLE CONFIG**:
|
|
282
306
|
```typescript
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const handlePress = () => {
|
|
288
|
-
if (!isAuthenticated) {
|
|
289
|
-
// Show login modal
|
|
290
|
-
showAuthModal(undefined, 'login');
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Perform auth-required action
|
|
295
|
-
console.log('Action successful');
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
return (
|
|
299
|
-
<Button onPress={handlePress}>
|
|
300
|
-
Auth Required Action
|
|
301
|
-
</Button>
|
|
302
|
-
);
|
|
307
|
+
google?: {
|
|
308
|
+
iosClientId?: string;
|
|
309
|
+
webClientId?: string;
|
|
310
|
+
androidClientId?: string;
|
|
303
311
|
}
|
|
304
312
|
```
|
|
313
|
+
At least one client ID required
|
|
305
314
|
|
|
306
|
-
|
|
307
|
-
|
|
315
|
+
**APPLE CONFIG**:
|
|
308
316
|
```typescript
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const { isAuthenticated } = useAuth();
|
|
312
|
-
|
|
313
|
-
const handleAddToFavorites = async () => {
|
|
314
|
-
if (!isAuthenticated) {
|
|
315
|
-
// Save callback to run after successful auth
|
|
316
|
-
showAuthModal(async () => {
|
|
317
|
-
await addToFavorites(postId);
|
|
318
|
-
Alert.alert('Success', 'Added to favorites');
|
|
319
|
-
}, 'login');
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// User authenticated, perform action directly
|
|
324
|
-
await addToFavorites(postId);
|
|
325
|
-
Alert.alert('Success', 'Added to favorites');
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
return (
|
|
329
|
-
<Button onPress={handleAddToFavorites}>
|
|
330
|
-
Add to Favorites
|
|
331
|
-
</Button>
|
|
332
|
-
);
|
|
317
|
+
apple?: {
|
|
318
|
+
enabled: boolean;
|
|
333
319
|
}
|
|
334
320
|
```
|
|
335
321
|
|
|
336
|
-
|
|
322
|
+
**Rules**:
|
|
323
|
+
- MUST provide client IDs for Google
|
|
324
|
+
- MUST enable Apple explicitly if needed
|
|
325
|
+
- MUST match Firebase console configuration
|
|
337
326
|
|
|
338
|
-
|
|
327
|
+
**Constraints**:
|
|
328
|
+
- Google: Requires at least one client ID
|
|
329
|
+
- Apple: Only works on iOS
|
|
330
|
+
- Both: Require Firebase setup
|
|
339
331
|
|
|
340
|
-
|
|
341
|
-
- **Anonymous → Authenticated**: Anonymous user registers
|
|
332
|
+
---
|
|
342
333
|
|
|
343
|
-
|
|
344
|
-
// User signs in
|
|
345
|
-
// → useAuth store updates
|
|
346
|
-
// → useAuthBottomSheet detects this
|
|
347
|
-
// → Modal auto-closes
|
|
348
|
-
// → Pending callback executes
|
|
349
|
-
```
|
|
334
|
+
## Loading States
|
|
350
335
|
|
|
351
|
-
|
|
336
|
+
### Strategy
|
|
352
337
|
|
|
353
|
-
|
|
338
|
+
**Purpose**: Proper loading indication during authentication.
|
|
354
339
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
340
|
+
**Rules**:
|
|
341
|
+
- MUST show loading during auth operation
|
|
342
|
+
- MUST disable auth buttons during loading
|
|
343
|
+
- MUST re-enable after completion
|
|
344
|
+
- MUST handle concurrent operations
|
|
345
|
+
|
|
346
|
+
**MUST NOT**:
|
|
347
|
+
- Allow multiple concurrent auth operations
|
|
348
|
+
- Leave loading state indefinitely
|
|
349
|
+
- Allow button press during loading
|
|
350
|
+
|
|
351
|
+
### Constraints
|
|
352
|
+
|
|
353
|
+
**LOADING STATES**:
|
|
354
|
+
- `googleLoading: boolean` - Google auth in progress
|
|
355
|
+
- `appleLoading: boolean` - Apple auth in progress
|
|
356
|
+
|
|
357
|
+
**VISUAL FEEDBACK**:
|
|
358
|
+
- Disable buttons during loading
|
|
359
|
+
- Show spinner/indicator
|
|
360
|
+
- Prevent mode switch during loading
|
|
361
|
+
- Clear errors on new operation
|
|
362
|
+
|
|
363
|
+
---
|
|
367
364
|
|
|
368
365
|
## Error Handling
|
|
369
366
|
|
|
370
|
-
|
|
371
|
-
function AuthBottomSheetWithErrorHandling() {
|
|
372
|
-
const {
|
|
373
|
-
modalRef,
|
|
374
|
-
mode,
|
|
375
|
-
handleGoogleSignIn,
|
|
376
|
-
handleAppleSignIn,
|
|
377
|
-
} = useAuthBottomSheet({
|
|
378
|
-
socialConfig: {
|
|
379
|
-
google: { webClientId: Config.GOOGLE_WEB_CLIENT_ID },
|
|
380
|
-
apple: { enabled: true },
|
|
381
|
-
},
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
const handleGoogleSignInWithErrorHandling = async () => {
|
|
385
|
-
try {
|
|
386
|
-
await handleGoogleSignIn();
|
|
387
|
-
} catch (error) {
|
|
388
|
-
// Additional error handling if needed
|
|
389
|
-
Alert.alert('Error', 'Something went wrong');
|
|
390
|
-
}
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
return (
|
|
394
|
-
<BottomSheetModal ref={modalRef}>
|
|
395
|
-
<Button onPress={handleGoogleSignInWithErrorHandling}>
|
|
396
|
-
Sign in with Google
|
|
397
|
-
</Button>
|
|
398
|
-
</BottomSheetModal>
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
```
|
|
367
|
+
### Strategy
|
|
402
368
|
|
|
403
|
-
|
|
369
|
+
**Purpose**: Graceful error handling in modal context.
|
|
370
|
+
|
|
371
|
+
**Rules**:
|
|
372
|
+
- MUST display errors in modal
|
|
373
|
+
- MUST keep modal open on error
|
|
374
|
+
- MUST allow retry after error
|
|
375
|
+
- MUST clear errors on new operation
|
|
376
|
+
|
|
377
|
+
**MUST NOT**:
|
|
378
|
+
- Close modal on error
|
|
379
|
+
- Show raw error messages
|
|
380
|
+
- Block retry indefinitely
|
|
381
|
+
- Lose user context
|
|
382
|
+
|
|
383
|
+
### Constraints
|
|
384
|
+
|
|
385
|
+
**ERROR DISPLAY**:
|
|
386
|
+
- In-modal error message
|
|
387
|
+
- Clear retry option
|
|
388
|
+
- User-friendly text
|
|
389
|
+
- Localized messages
|
|
390
|
+
|
|
391
|
+
**ERROR RECOVERY**:
|
|
392
|
+
- User can retry same operation
|
|
393
|
+
- Can switch to different provider
|
|
394
|
+
- Can switch to login/register
|
|
395
|
+
- Manual dismiss if desired
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Modal Lifecycle
|
|
400
|
+
|
|
401
|
+
### Strategy
|
|
402
|
+
|
|
403
|
+
**Purpose**: Proper modal lifecycle management.
|
|
404
404
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
405
|
+
**OPENING**:
|
|
406
|
+
1. Trigger: `showAuthModal` called
|
|
407
|
+
2. Mode: Set to 'login' or 'register'
|
|
408
|
+
3. Callback: Stored if provided
|
|
409
|
+
4. Modal: Opens with animation
|
|
410
|
+
|
|
411
|
+
**DURING AUTH**:
|
|
412
|
+
1. User fills form or clicks social button
|
|
413
|
+
2. Loading state shown
|
|
414
|
+
3. Auth operation executed
|
|
415
|
+
4. Success or failure determined
|
|
416
|
+
|
|
417
|
+
**CLOSING**:
|
|
418
|
+
1. Success: Auto-close + callback execution
|
|
419
|
+
2. Failure: Stays open for retry
|
|
420
|
+
3. Dismiss: Cleanup + reset
|
|
421
|
+
4. Cancel: Cleanup + reset
|
|
422
|
+
|
|
423
|
+
**Rules**:
|
|
424
|
+
- MUST follow lifecycle sequence
|
|
425
|
+
- MUST cleanup on every close
|
|
426
|
+
- MUST reset state appropriately
|
|
427
|
+
- MUST not leak memory
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Integration Points
|
|
432
|
+
|
|
433
|
+
### Store Integration
|
|
434
|
+
|
|
435
|
+
**authModalStore** manages:
|
|
436
|
+
- Modal open/close state
|
|
437
|
+
- Current mode (login/register)
|
|
438
|
+
- Pending callback
|
|
439
|
+
- Social auth configuration
|
|
440
|
+
|
|
441
|
+
**Rules**:
|
|
442
|
+
- MUST use store for modal state
|
|
443
|
+
- MUST not duplicate state locally
|
|
444
|
+
- MUST subscribe to store updates
|
|
445
|
+
- MUST trigger store actions
|
|
446
|
+
|
|
447
|
+
---
|
|
409
448
|
|
|
410
449
|
## Related Hooks
|
|
411
450
|
|
|
412
|
-
-
|
|
413
|
-
-
|
|
414
|
-
-
|
|
451
|
+
- **`useAuth`** (`src/presentation/hooks/useAuth.ts`) - Authentication state
|
|
452
|
+
- **`useSocialLogin`** (`src/presentation/hooks/useSocialLogin.md`) - Social authentication
|
|
453
|
+
- **`useAuthRequired`** (`src/presentation/hooks/useAuthRequired.md`) - Auth requirement checks
|
|
454
|
+
|
|
455
|
+
## Related Components
|
|
456
|
+
|
|
457
|
+
- **`AuthBottomSheet`** (`src/presentation/components/AuthBottomSheet.tsx`) - Modal component
|
|
458
|
+
- **`LoginForm`** (`src/presentation/components/LoginForm.md`) - Login form
|
|
459
|
+
- **`RegisterForm`** (`src/presentation/components/LoginForm.md`) - Registration form
|
|
460
|
+
- **`SocialLoginButtons`** (`src/presentation/components/SocialLoginButtons.md`) - Social auth UI
|
|
461
|
+
|
|
462
|
+
## Related Stores
|
|
463
|
+
|
|
464
|
+
- **`authModalStore`** (`src/presentation/stores/authModalStore.ts`) - Modal state management
|