@umituz/react-native-auth 3.4.30 → 3.4.31

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.
@@ -0,0 +1,411 @@
1
+ # Social Login Hooks
2
+
3
+ Google ve Apple ile social authentication işlemleri için hooks.
4
+
5
+ ## Hooks
6
+
7
+ - **[`useSocialLogin`](#usesociallogin)** - Genel social login yönetimi
8
+ - **[`useGoogleAuth`](#usegoogleauth)** - Google ile giriş (OAuth flow)
9
+ - **[`useAppleAuth`](#useappleauth)** - Apple ile giriş
10
+
11
+ ---
12
+
13
+ ## useSocialLogin
14
+
15
+ Genel social login işlevselliği sağlar. `@umituz/react-native-firebase` paketinin `useSocialAuth` hook'unu wrap'ler.
16
+
17
+ ### Kullanım
18
+
19
+ ```typescript
20
+ import { useSocialLogin } from '@umituz/react-native-auth';
21
+
22
+ function LoginScreen() {
23
+ const {
24
+ signInWithGoogle,
25
+ signInWithApple,
26
+ googleLoading,
27
+ appleLoading,
28
+ googleConfigured,
29
+ appleAvailable,
30
+ } = useSocialLogin({
31
+ google: {
32
+ webClientId: 'your-web-client-id.apps.googleusercontent.com',
33
+ iosClientId: 'your-ios-client-id.apps.googleusercontent.com',
34
+ },
35
+ apple: { enabled: true },
36
+ });
37
+
38
+ return (
39
+ <View>
40
+ <Button
41
+ onPress={signInWithGoogle}
42
+ disabled={googleLoading || !googleConfigured}
43
+ >
44
+ {googleLoading ? 'Giriş yapılıyor...' : 'Google ile Giriş'}
45
+ </Button>
46
+
47
+ <Button
48
+ onPress={signInWithApple}
49
+ disabled={appleLoading || !appleAvailable}
50
+ >
51
+ {appleLoading ? 'Giriş yapılıyor...' : 'Apple ile Giriş'}
52
+ </Button>
53
+ </View>
54
+ );
55
+ }
56
+ ```
57
+
58
+ ### API
59
+
60
+ #### Parameters
61
+
62
+ | Param | Tip | Açıklama |
63
+ |-------|------|----------|
64
+ | `config` | `UseSocialLoginConfig` | Social auth konfigürasyonu |
65
+
66
+ #### UseSocialLoginConfig
67
+
68
+ ```typescript
69
+ interface UseSocialLoginConfig {
70
+ google?: {
71
+ iosClientId?: string;
72
+ webClientId?: string;
73
+ androidClientId?: string;
74
+ };
75
+ apple?: {
76
+ enabled: boolean;
77
+ };
78
+ }
79
+ ```
80
+
81
+ #### Return Value
82
+
83
+ | Prop | Tip | Açıklama |
84
+ |------|-----|----------|
85
+ | `signInWithGoogle` | `() => Promise<SocialAuthResult>` | Google ile giriş (Not: `useGoogleAuth` kullanın) |
86
+ | `signInWithApple` | `() => Promise<SocialAuthResult>` | Apple ile giriş |
87
+ | `googleLoading` | `boolean` | Google giriş loading durumu |
88
+ | `appleLoading` | `boolean` | Apple giriş loading durumu |
89
+ | `googleConfigured` | `boolean` | Google yapılandırılmış mı |
90
+ | `appleAvailable` | `boolean` | Apple mevcut mu (sadece iOS) |
91
+
92
+ **Not:** `signInWithGoogle` için tam OAuth flow'u `useGoogleAuth` hook'unu kullanın.
93
+
94
+ ---
95
+
96
+ ## useGoogleAuth
97
+
98
+ Google OAuth flow'unu `expo-auth-session` kullanarak yönetir ve Firebase authentication ile entegre eder.
99
+
100
+ ### Kullanım
101
+
102
+ ```typescript
103
+ import { useGoogleAuth } from '@umituz/react-native-auth';
104
+
105
+ function LoginScreen() {
106
+ const { signInWithGoogle, googleLoading, googleConfigured } = useGoogleAuth({
107
+ iosClientId: 'your-ios-client-id.apps.googleusercontent.com',
108
+ webClientId: 'your-web-client-id.apps.googleusercontent.com',
109
+ androidClientId: 'your-android-client-id.apps.googleusercontent.com',
110
+ });
111
+
112
+ const handleGoogleSignIn = async () => {
113
+ const result = await signInWithGoogle();
114
+
115
+ if (result.success) {
116
+ console.log('Google ile giriş başarılı');
117
+ } else {
118
+ Alert.alert('Hata', result.error || 'Giriş başarısız');
119
+ }
120
+ };
121
+
122
+ return (
123
+ <Button
124
+ onPress={handleGoogleSignIn}
125
+ disabled={googleLoading || !googleConfigured}
126
+ >
127
+ {googleLoading ? 'Giriş yapılıyor...' : 'Google ile Giriş'}
128
+ </Button>
129
+ );
130
+ }
131
+ ```
132
+
133
+ ### API
134
+
135
+ #### Parameters
136
+
137
+ | Param | Tip | Required | Açıklama |
138
+ |-------|------|----------|----------|
139
+ | `iosClientId` | `string` | No* | iOS için Google Client ID |
140
+ | `webClientId` | `string` | No* | Web için Google Client ID |
141
+ | `androidClientId` | `string` | No* | Android için Google Client ID |
142
+
143
+ *En az biri sağlanmalıdır.
144
+
145
+ #### Return Value
146
+
147
+ | Prop | Tip | Açıklama |
148
+ |------|-----|----------|
149
+ | `signInWithGoogle` | `() => Promise<SocialAuthResult>` | Google ile giriş fonksiyonu |
150
+ | `googleLoading` | `boolean` | Loading durumu |
151
+ | `googleConfigured` | `boolean` | Yapılandırılmış mı |
152
+
153
+ ### Örnekler
154
+
155
+ #### Google ile Giriş Ekranı
156
+
157
+ ```typescript
158
+ function SocialLoginScreen() {
159
+ const { signInWithGoogle, googleLoading } = useGoogleAuth({
160
+ iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
161
+ webClientId: Config.GOOGLE_WEB_CLIENT_ID,
162
+ });
163
+
164
+ const { signInWithApple, appleLoading, appleAvailable } = useAppleAuth();
165
+
166
+ return (
167
+ <View style={styles.container}>
168
+ <Text style={styles.title}>Giriş Yap</Text>
169
+
170
+ <TouchableOpacity
171
+ style={styles.googleButton}
172
+ onPress={signInWithGoogle}
173
+ disabled={googleLoading}
174
+ >
175
+ {googleLoading ? (
176
+ <ActivityIndicator />
177
+ ) : (
178
+ <>
179
+ <GoogleIcon />
180
+ <Text>Google ile devam et</Text>
181
+ </>
182
+ )}
183
+ </TouchableOpacity>
184
+
185
+ {Platform.OS === 'ios' && appleAvailable && (
186
+ <TouchableOpacity
187
+ style={styles.appleButton}
188
+ onPress={signInWithApple}
189
+ disabled={appleLoading}
190
+ >
191
+ {appleLoading ? (
192
+ <ActivityIndicator />
193
+ ) : (
194
+ <>
195
+ <AppleIcon />
196
+ <Text>Apple ile devam et</Text>
197
+ </>
198
+ )}
199
+ </TouchableOpacity>
200
+ )}
201
+ </View>
202
+ );
203
+ }
204
+ ```
205
+
206
+ #### Hata Yönetimi
207
+
208
+ ```typescript
209
+ function LoginWithErrorHandling() {
210
+ const { signInWithGoogle, googleLoading } = useGoogleAuth({
211
+ webClientId: Config.GOOGLE_WEB_CLIENT_ID,
212
+ });
213
+
214
+ const handleGoogleSignIn = async () => {
215
+ try {
216
+ const result = await signInWithGoogle();
217
+
218
+ if (result.success) {
219
+ // Başarılı giriş
220
+ navigation.navigate('Home');
221
+ } else {
222
+ // Hata durumunda
223
+ if (result.error?.includes('cancelled')) {
224
+ // Kullanıcı iptal etti
225
+ return;
226
+ }
227
+
228
+ Alert.alert(
229
+ 'Giriş Hatası',
230
+ result.error || 'Google ile giriş yapılamadı'
231
+ );
232
+ }
233
+ } catch (error) {
234
+ Alert.alert(
235
+ 'Beklenmeyen Hata',
236
+ 'Bir hata oluştu. Lütfen daha sonra tekrar deneyin.'
237
+ );
238
+ }
239
+ };
240
+
241
+ return <Button onPress={handleGoogleSignIn} />;
242
+ }
243
+ ```
244
+
245
+ ---
246
+
247
+ ## useAppleAuth
248
+
249
+ Apple Sign-In işlevselliği sağlar. Sadece iOS'ta mevcuttur.
250
+
251
+ ### Kullanım
252
+
253
+ ```typescript
254
+ import { useAppleAuth } from '@umituz/react-native-auth';
255
+ import { Platform } from 'react-native';
256
+
257
+ function LoginScreen() {
258
+ const { signInWithApple, appleLoading, appleAvailable } = useAppleAuth();
259
+
260
+ if (Platform.OS !== 'ios' || !appleAvailable) {
261
+ return null; // Apple sadece iOS'ta çalışır
262
+ }
263
+
264
+ return (
265
+ <TouchableOpacity
266
+ onPress={signInWithApple}
267
+ disabled={appleLoading}
268
+ style={styles.appleButton}
269
+ >
270
+ {appleLoading ? (
271
+ <ActivityIndicator />
272
+ ) : (
273
+ <>
274
+ <AppleIcon />
275
+ <Text>Apple ile Giriş</Text>
276
+ </>
277
+ )}
278
+ </TouchableOpacity>
279
+ );
280
+ }
281
+ ```
282
+
283
+ ### API
284
+
285
+ #### Return Value
286
+
287
+ | Prop | Tip | Açıklama |
288
+ |------|-----|----------|
289
+ | `signInWithApple` | `() => Promise<SocialAuthResult>` | Apple ile giriş fonksiyonu |
290
+ | `appleLoading` | `boolean` | Loading durumu |
291
+ | `appleAvailable` | `boolean` | Apple Sign-In mevcut mu (iOS only) |
292
+
293
+ ### Örnekler
294
+
295
+ #### Platform-Specific Apple Button
296
+
297
+ ```typescript
298
+ function SocialLoginButtons() {
299
+ const { signInWithApple, appleLoading, appleAvailable } = useAppleAuth();
300
+ const { signInWithGoogle, googleLoading } = useGoogleAuth({
301
+ webClientId: Config.GOOGLE_WEB_CLIENT_ID,
302
+ });
303
+
304
+ return (
305
+ <View>
306
+ {/* Google - tüm platformlar */}
307
+ <SocialButton
308
+ provider="google"
309
+ onPress={signInWithGoogle}
310
+ loading={googleLoading}
311
+ />
312
+
313
+ {/* Apple - sadece iOS */}
314
+ {Platform.OS === 'ios' && appleAvailable && (
315
+ <SocialButton
316
+ provider="apple"
317
+ onPress={signInWithApple}
318
+ loading={appleLoading}
319
+ />
320
+ )}
321
+ </View>
322
+ );
323
+ }
324
+ ```
325
+
326
+ #### Apple ile Giriş ve Hata Yönetimi
327
+
328
+ ```typescript
329
+ function AppleLoginButton() {
330
+ const { signInWithApple, appleLoading, appleAvailable } = useAppleAuth();
331
+
332
+ const handleAppleSignIn = async () => {
333
+ const result = await signInWithApple();
334
+
335
+ if (result.success) {
336
+ console.log('Apple ile giriş başarılı');
337
+ // Kullanıcıyı ana ekrana yönlendir
338
+ } else {
339
+ // Hata yönetimi
340
+ if (result.error?.includes('cancelled')) {
341
+ console.log('Kullanıcı iptal etti');
342
+ } else {
343
+ Alert.alert('Hata', result.error || 'Apple ile giriş yapılamadı');
344
+ }
345
+ }
346
+ };
347
+
348
+ if (!appleAvailable) {
349
+ return null;
350
+ }
351
+
352
+ return (
353
+ <TouchableOpacity onPress={handleAppleSignIn} disabled={appleLoading}>
354
+ <Text>Apple ile Giriş</Text>
355
+ </TouchableOpacity>
356
+ );
357
+ }
358
+ ```
359
+
360
+ ## SocialAuthResult
361
+
362
+ Tüm social login fonksiyonları aynı result tipini döner:
363
+
364
+ ```typescript
365
+ interface SocialAuthResult {
366
+ success: boolean;
367
+ error?: string;
368
+ user?: AuthUser;
369
+ }
370
+ ```
371
+
372
+ ## Konfigürasyon
373
+
374
+ ### Google Client ID Almak
375
+
376
+ 1. [Google Cloud Console](https://console.cloud.google.com/)'a gidin
377
+ 2. Yeni bir proje oluşturun veya mevcut projeyi seçin
378
+ 3. "APIs & Services" > "Credentials" sayfasına gidin
379
+ 4. "OAuth 2.0 Client IDs" oluşturun:
380
+ - **iOS**: iOS uygulamanız için
381
+ - **Android**: Android uygulamanız için
382
+ - **Web**: Expo/web için
383
+
384
+ ### Apple Sign-In Konfigürasyonu
385
+
386
+ 1. [Apple Developer](https://developer.apple.com/)'da gidin
387
+ 2. "Certificates, Identifiers & Profiles" > "Identifiers"
388
+ 3. App ID'nizi seçin ve "Sign In with Apple"ı enable edin
389
+ 4. Firebase Console'da Apple Sign-In'i enable edin
390
+
391
+ ## Önemli Notlar
392
+
393
+ ### Google
394
+ - `expo-web-browser` kurulumu gerekir
395
+ - `WebBrowser.maybeCompleteAuthSession()` app root'ta çağrılmalı
396
+ - En az bir client ID sağlanmalıdır
397
+
398
+ ### Apple
399
+ - Sadece iOS'ta mevcuttur
400
+ - `expo-apple-authentication` kurulumu gerekir
401
+ - Apple Developer hesabı gerekir
402
+ - Test için cihaz gereklidir (simulator'de çalışmayabilir)
403
+
404
+ ## İlgili Hook'lar
405
+
406
+ - [`useAuth`](./useAuth.md) - Ana auth state yönetimi
407
+ - [`useSocialLogin`](#usesociallogin) - Genel social login yönetimi
408
+
409
+ ## İlgili Component'ler
410
+
411
+ - [`SocialLoginButtons`](../components/SocialLoginButtons.md) - Social login button component'i
@@ -0,0 +1,230 @@
1
+ # useUserProfile
2
+
3
+ Hook for fetching user profile data for display in settings or profile screens.
4
+
5
+ ## Features
6
+
7
+ - Returns profile data based on auth state
8
+ - Generates anonymous names for anonymous users
9
+ - Memoized for performance
10
+ - Type-safe profile data
11
+
12
+ ## Usage
13
+
14
+ ```typescript
15
+ import { useUserProfile } from '@umituz/react-native-auth';
16
+
17
+ function ProfileHeader() {
18
+ const profile = useUserProfile({
19
+ accountRoute: '/account',
20
+ anonymousDisplayName: 'Guest User',
21
+ });
22
+
23
+ if (!profile) {
24
+ return <LoadingSpinner />;
25
+ }
26
+
27
+ return (
28
+ <View>
29
+ <Avatar source={{ uri: profile.avatarUrl }} />
30
+ <Text>{profile.displayName}</Text>
31
+ {profile.isAnonymous && <Text>Guest</Text>}
32
+ </View>
33
+ );
34
+ }
35
+ ```
36
+
37
+ ## API
38
+
39
+ ### Parameters
40
+
41
+ | Param | Type | Default | Description |
42
+ |-------|------|---------|-------------|
43
+ | `anonymousDisplayName` | `string` | `undefined` | Default name for anonymous users |
44
+ | `accountRoute` | `string` | `undefined` | Account settings route |
45
+ | `anonymousNameConfig` | `AnonymousNameConfig` | `undefined` | Anonymous name generation config |
46
+
47
+ ### Return Value
48
+
49
+ `UserProfileData | undefined` - `undefined` if no user, otherwise:
50
+
51
+ | Prop | Type | Description |
52
+ |------|------|-------------|
53
+ | `displayName` | `string` | User's display name |
54
+ | `userId` | `string` | User ID |
55
+ | `isAnonymous` | `boolean` | Is anonymous user |
56
+ | `avatarUrl` | `string \| undefined` | Profile photo URL |
57
+ | `accountSettingsRoute` | `string \| undefined` | Account settings route |
58
+
59
+ ## Examples
60
+
61
+ ### Simple Profile Header
62
+
63
+ ```typescript
64
+ function ProfileHeader() {
65
+ const profile = useUserProfile();
66
+
67
+ if (!profile) return null;
68
+
69
+ return (
70
+ <View style={styles.header}>
71
+ {profile.avatarUrl ? (
72
+ <Image source={{ uri: profile.avatarUrl }} style={styles.avatar} />
73
+ ) : (
74
+ <View style={styles.placeholderAvatar}>
75
+ <Text>{profile.displayName?.[0]}</Text>
76
+ </View>
77
+ )}
78
+ <View>
79
+ <Text style={styles.name}>{profile.displayName}</Text>
80
+ {profile.isAnonymous && (
81
+ <Badge style={styles.badge}>Guest</Badge>
82
+ )}
83
+ </View>
84
+ </View>
85
+ );
86
+ }
87
+ ```
88
+
89
+ ### Profile Settings Link
90
+
91
+ ```typescript
92
+ function SettingsLink() {
93
+ const profile = useUserProfile({
94
+ accountRoute: '/settings/account',
95
+ });
96
+
97
+ if (!profile || profile.isAnonymous) {
98
+ return null; // Don't show for anonymous users
99
+ }
100
+
101
+ return (
102
+ <TouchableOpacity
103
+ onPress={() => navigation.navigate(profile.accountSettingsRoute)}
104
+ >
105
+ <Text>Account Settings</Text>
106
+ </TouchableOpacity>
107
+ );
108
+ }
109
+ ```
110
+
111
+ ### Anonymous User with Custom Name
112
+
113
+ ```typescript
114
+ function UserProfileCard() {
115
+ const profile = useUserProfile({
116
+ anonymousDisplayName: 'Guest User',
117
+ anonymousNameConfig: {
118
+ prefix: 'User',
119
+ adjectiveCount: 1,
120
+ nounCount: 1,
121
+ },
122
+ });
123
+
124
+ if (!profile) return <Skeleton />;
125
+
126
+ return (
127
+ <Card>
128
+ <Card.Title>{profile.displayName}</Card.Title>
129
+ {profile.isAnonymous && (
130
+ <Card.Description>
131
+ <Link href="/register">Create an account</Link> for more features
132
+ </Card.Description>
133
+ )}
134
+ </Card>
135
+ );
136
+ }
137
+ ```
138
+
139
+ ### Navigation Integration
140
+
141
+ ```typescript
142
+ function ProfileTab() {
143
+ const profile = useUserProfile({
144
+ accountRoute: 'Account',
145
+ });
146
+
147
+ const navigation = useNavigation();
148
+
149
+ const handleProfilePress = () => {
150
+ if (profile?.isAnonymous) {
151
+ navigation.navigate('Register');
152
+ } else if (profile?.accountSettingsRoute) {
153
+ navigation.navigate(profile.accountSettingsRoute);
154
+ }
155
+ };
156
+
157
+ return (
158
+ <TouchableOpacity onPress={handleProfilePress}>
159
+ <Text>{profile?.displayName || 'Profile'}</Text>
160
+ </TouchableOpacity>
161
+ );
162
+ }
163
+ ```
164
+
165
+ ### Conditional Content Based on Auth
166
+
167
+ ```typescript
168
+ function WelcomeBanner() {
169
+ const profile = useUserProfile();
170
+
171
+ if (!profile) return <LoadingBanner />;
172
+
173
+ if (profile.isAnonymous) {
174
+ return (
175
+ <Banner>
176
+ <Text>Welcome, {profile.displayName}!</Text>
177
+ <Button onPress={() => navigation.navigate('Register')}>
178
+ Create Account
179
+ </Button>
180
+ </Banner>
181
+ );
182
+ }
183
+
184
+ return (
185
+ <Banner>
186
+ <Text>Welcome, {profile.displayName}!</Text>
187
+ <Text>Complete your profile to get the most out of the app.</Text>
188
+ </Banner>
189
+ );
190
+ }
191
+ ```
192
+
193
+ ## Anonymous Name Generation
194
+
195
+ Anonymous users automatically get random names generated:
196
+
197
+ ```typescript
198
+ import { generateAnonymousName } from '@umituz/react-native-auth';
199
+
200
+ // Default: "User_Witty_Badger_1234"
201
+ const name1 = generateAnonymousName('user-123');
202
+
203
+ // Custom config
204
+ const name2 = generateAnonymousName('user-123', {
205
+ prefix: 'Guest',
206
+ adjectiveCount: 1,
207
+ nounCount: 1,
208
+ });
209
+ // "Guest_Clever_Fox_1234"
210
+
211
+ // ID only
212
+ const name3 = generateAnonymousName('user-123', {
213
+ prefix: '',
214
+ adjectiveCount: 0,
215
+ nounCount: 0,
216
+ });
217
+ // "user-123"
218
+ ```
219
+
220
+ ## Performance Notes
221
+
222
+ - Hook uses `useMemo` for performance
223
+ - Only recalculates when dependencies change
224
+ - Automatically updates on user sign-in/sign-out
225
+
226
+ ## Related Hooks
227
+
228
+ - [`useAuth`](./useAuth.md) - Main auth state management
229
+ - [`useProfileUpdate`](./useProfileUpdate.md) - Profile updates
230
+ - [`useProfileEdit`](./useProfileEdit.md) - Profile editing form