@umituz/react-native-settings 5.4.17 → 5.4.19

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 (46) hide show
  1. package/dist/core/base/BaseService.d.ts +86 -0
  2. package/dist/core/index.d.ts +27 -0
  3. package/dist/core/patterns/Modal/ModalConfig.d.ts +197 -0
  4. package/dist/core/patterns/Modal/useModalState.d.ts +53 -0
  5. package/dist/core/patterns/Screen/ScreenConfig.d.ts +273 -0
  6. package/dist/core/patterns/Screen/useScreenData.d.ts +62 -0
  7. package/dist/core/utils/logger.d.ts +76 -0
  8. package/dist/core/utils/validators.d.ts +114 -0
  9. package/dist/domains/ai-consent/index.d.ts +37 -0
  10. package/dist/domains/ai-consent/presentation/components/AIConsentModal.d.ts +26 -0
  11. package/dist/domains/ai-consent/presentation/components/AIConsentSetting.d.ts +28 -0
  12. package/dist/domains/ai-consent/presentation/hooks/useAIConsent.d.ts +27 -0
  13. package/dist/domains/ai-consent/presentation/screens/AIConsentScreen.d.ts +37 -0
  14. package/dist/domains/disclaimer/index.d.ts +0 -2
  15. package/dist/domains/disclaimer/presentation/components/DisclaimerSetting.d.ts +1 -2
  16. package/dist/domains/disclaimer/presentation/screens/DisclaimerScreen.d.ts +11 -20
  17. package/dist/domains/feedback/index.d.ts +2 -1
  18. package/dist/domains/feedback/presentation/components/SupportSection.d.ts +1 -1
  19. package/dist/domains/feedback/presentation/screens/FeedbackScreen.d.ts +21 -0
  20. package/dist/domains/gamification/types/index.d.ts +1 -0
  21. package/dist/domains/gamification/utils/calculations.d.ts +3 -0
  22. package/dist/domains/localization/index.d.ts +1 -1
  23. package/dist/domains/localization/infrastructure/config/i18n.d.ts +1 -1
  24. package/dist/domains/notifications/infrastructure/services/NotificationService.d.ts +5 -2
  25. package/dist/domains/notifications/quietHours/infrastructure/hooks/useQuietHoursActions.d.ts +4 -4
  26. package/dist/domains/rating/application/services/RatingService.d.ts +50 -21
  27. package/dist/domains/rating/index.d.ts +2 -2
  28. package/dist/domains/rating/presentation/hooks/useAppRating.d.ts +1 -1
  29. package/dist/domains/rating/presentation/screens/RatingPromptScreen.d.ts +22 -0
  30. package/dist/index.d.ts +4 -0
  31. package/dist/infrastructure/services/SettingsService.d.ts +5 -2
  32. package/dist/presentation/components/GenericModal.d.ts +35 -0
  33. package/dist/presentation/components/GenericScreen.d.ts +41 -0
  34. package/dist/presentation/components/index.d.ts +17 -0
  35. package/dist/presentation/navigation/hooks/useSettingsNavigation.d.ts +21 -15
  36. package/dist/presentation/navigation/types.d.ts +8 -0
  37. package/dist/presentation/navigation/utils/navigationHelpers.d.ts +1 -1
  38. package/package.json +1 -1
  39. package/src/domains/ai-consent/index.ts +53 -0
  40. package/src/domains/ai-consent/presentation/components/AIConsentModal.tsx +64 -0
  41. package/src/domains/ai-consent/presentation/components/AIConsentSetting.tsx +106 -0
  42. package/src/domains/ai-consent/presentation/hooks/useAIConsent.ts +125 -0
  43. package/src/domains/ai-consent/presentation/screens/AIConsentScreen.tsx +414 -0
  44. package/src/index.ts +3 -0
  45. package/src/presentation/navigation/hooks/useSettingsScreens.ts +9 -1
  46. package/src/presentation/navigation/types.ts +2 -0
@@ -0,0 +1,414 @@
1
+ /**
2
+ * AI Consent Screen
3
+ *
4
+ * Full screen for displaying AI technology disclosure and consent.
5
+ * Required by Apple App Store Guidelines 5.1.1(i) & 5.1.2(i)
6
+ *
7
+ * Features:
8
+ * - Lists all AI providers and their purposes
9
+ * - Explains data sharing practices
10
+ * - Provides privacy policy links
11
+ * - Accept/Decline buttons
12
+ * - Scrollable content
13
+ */
14
+
15
+ import React, { memo } from 'react';
16
+ import {
17
+ View,
18
+ StyleSheet,
19
+ ScrollView,
20
+ TouchableOpacity,
21
+ } from 'react-native';
22
+ import {
23
+ ScreenLayout,
24
+ } from '@umituz/react-native-design-system/layouts';
25
+ import {
26
+ AtomicText,
27
+ AtomicButton,
28
+ AtomicSpinner,
29
+ } from '@umituz/react-native-design-system/atoms';
30
+ import {
31
+ NavigationHeader,
32
+ useAppNavigation,
33
+ } from '@umituz/react-native-design-system/molecules';
34
+ import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
35
+
36
+ export interface AIProvider {
37
+ name: string;
38
+ purpose: string;
39
+ privacyUrl: string;
40
+ }
41
+
42
+ export interface AIConsentScreenParams {
43
+ providers?: AIProvider[];
44
+ customMessage?: string;
45
+ onAccept?: () => void;
46
+ onDecline?: () => void;
47
+ [key: string]: unknown;
48
+ }
49
+
50
+ export interface AIConsentScreenProps {
51
+ route?: {
52
+ params?: AIConsentScreenParams;
53
+ };
54
+ providers?: AIProvider[];
55
+ customMessage?: string;
56
+ onAccept?: () => void;
57
+ onDecline?: () => void;
58
+ standalone?: boolean;
59
+ }
60
+
61
+ const DEFAULT_PROVIDERS: AIProvider[] = [
62
+ {
63
+ name: 'Pruna AI',
64
+ purpose: 'Image generation & editing',
65
+ privacyUrl: 'https://pruna.ai/privacy',
66
+ },
67
+ {
68
+ name: 'FAL AI',
69
+ purpose: 'Video generation infrastructure',
70
+ privacyUrl: 'https://fal.ai/privacy',
71
+ },
72
+ {
73
+ name: 'Groq AI',
74
+ purpose: 'Text processing & prompts',
75
+ privacyUrl: 'https://groq.com/privacy',
76
+ },
77
+ ];
78
+
79
+ export const AIConsentScreen: React.FC<AIConsentScreenProps> = memo(({
80
+ route,
81
+ providers = DEFAULT_PROVIDERS,
82
+ customMessage,
83
+ onAccept,
84
+ onDecline,
85
+ standalone = false,
86
+ }) => {
87
+ const navigation = useAppNavigation();
88
+ const tokens = useAppDesignTokens();
89
+ const [loading, setLoading] = React.useState(false);
90
+
91
+ // Get params from route or use props
92
+ const params = route?.params || {};
93
+ const finalProviders = params.providers || providers;
94
+ const finalMessage = params.customMessage || customMessage;
95
+ const finalOnAccept = params.onAccept || onAccept;
96
+ const finalOnDecline = params.onDecline || onDecline;
97
+
98
+ const handleAccept = async () => {
99
+ if (finalOnAccept) {
100
+ setLoading(true);
101
+ try {
102
+ await finalOnAccept();
103
+ } catch (error) {
104
+ console.error('[AIConsentScreen] Accept error:', error);
105
+ } finally {
106
+ setLoading(false);
107
+ }
108
+ }
109
+
110
+ if (!standalone) {
111
+ navigation.goBack();
112
+ }
113
+ };
114
+
115
+ const handleDecline = () => {
116
+ if (finalOnDecline) {
117
+ finalOnDecline();
118
+ }
119
+
120
+ if (!standalone) {
121
+ navigation.goBack();
122
+ }
123
+ };
124
+
125
+ const handleLinkPress = (url: string) => {
126
+ // TODO: Implement Linking.openURL
127
+ console.log('[AIConsentScreen] Open URL:', url);
128
+ };
129
+
130
+ return (
131
+ <ScreenLayout
132
+ scrollable={true}
133
+ edges={['top', 'bottom', 'left', 'right']}
134
+ hideScrollIndicator={false}
135
+ >
136
+ {!standalone && (
137
+ <NavigationHeader
138
+ title="AI Technology Disclosure"
139
+ onBackPress={() => navigation.goBack()}
140
+ />
141
+ )}
142
+
143
+ <ScrollView
144
+ style={styles.scrollView}
145
+ contentContainerStyle={styles.scrollContent}
146
+ showsVerticalScrollIndicator={false}
147
+ >
148
+ {finalMessage && (
149
+ <AtomicText style={styles.introText}>
150
+ {finalMessage}
151
+ </AtomicText>
152
+ )}
153
+
154
+ <AtomicText style={styles.introText}>
155
+ Vivoim uses multiple AI services to generate content. Before using
156
+ our AI features, please review how your data is processed.
157
+ </AtomicText>
158
+
159
+ <View style={styles.section}>
160
+ <AtomicText style={styles.sectionTitle}>
161
+ 🤖 AI Services We Use
162
+ </AtomicText>
163
+ <View style={styles.providerList}>
164
+ {finalProviders.map((provider, index) => (
165
+ <View key={index} style={styles.providerItem}>
166
+ <View style={styles.providerHeader}>
167
+ <AtomicText style={styles.providerName}>
168
+ {provider.name}
169
+ </AtomicText>
170
+ <TouchableOpacity
171
+ onPress={() => handleLinkPress(provider.privacyUrl)}
172
+ >
173
+ <AtomicText style={styles.privacyLink}>
174
+ Privacy Policy
175
+ </AtomicText>
176
+ </TouchableOpacity>
177
+ </View>
178
+ <AtomicText style={styles.providerPurpose}>
179
+ {provider.purpose}
180
+ </AtomicText>
181
+ </View>
182
+ ))}
183
+ </View>
184
+ </View>
185
+
186
+ <View style={styles.section}>
187
+ <AtomicText style={styles.sectionTitle}>
188
+ 📸 What We Send to AI Services
189
+ </AtomicText>
190
+ <AtomicText style={styles.bullet}>
191
+ • Photos you select from your gallery
192
+ </AtomicText>
193
+ <AtomicText style={styles.bullet}>
194
+ • Text prompts you enter
195
+ </AtomicText>
196
+ <AtomicText style={styles.bullet}>
197
+ • Generation instructions and settings
198
+ </AtomicText>
199
+ <AtomicText style={styles.note}>
200
+ Note: Your photos are processed to generate content and are NOT
201
+ stored permanently by us or AI providers after processing
202
+ completes.
203
+ </AtomicText>
204
+ </View>
205
+
206
+ <View style={styles.section}>
207
+ <AtomicText style={styles.sectionTitle}>
208
+ 🔒 Data Privacy
209
+ </AtomicText>
210
+ <AtomicText style={styles.bullet}>
211
+ • Original photos are deleted after processing
212
+ </AtomicText>
213
+ <AtomicText style={styles.bullet}>
214
+ • Generated content is stored in your account only
215
+ </AtomicText>
216
+ <AtomicText style={styles.bullet}>
217
+ • You can delete any content at any time
218
+ </AtomicText>
219
+ <AtomicText style={styles.bullet}>
220
+ • Face data is used for generation only
221
+ </AtomicText>
222
+ <AtomicText style={styles.bullet}>
223
+ • No biometric authentication or tracking
224
+ </AtomicText>
225
+ </View>
226
+
227
+ <View style={styles.section}>
228
+ <AtomicText style={styles.sectionTitle}>
229
+ 📄 Legal Documents
230
+ </AtomicText>
231
+ <TouchableOpacity
232
+ style={styles.linkButton}
233
+ onPress={() => handleLinkPress('https://umituz.com/projects/ai-technology/vivoim/privacy')}
234
+ >
235
+ <AtomicText style={styles.linkText}>
236
+ Privacy Policy →
237
+ </AtomicText>
238
+ </TouchableOpacity>
239
+ <TouchableOpacity
240
+ style={styles.linkButton}
241
+ onPress={() => handleLinkPress('https://umituz.com/projects/ai-technology/vivoim/terms')}
242
+ >
243
+ <AtomicText style={styles.linkText}>
244
+ Terms of Use →
245
+ </AtomicText>
246
+ </TouchableOpacity>
247
+ </View>
248
+
249
+ <View style={styles.declarationSection}>
250
+ <View style={styles.checkbox}>
251
+ <View style={styles.checkboxInner}>
252
+ <AtomicText style={styles.checkmark}>✓</AtomicText>
253
+ </View>
254
+ </View>
255
+ <AtomicText style={styles.declarationText}>
256
+ I have read and agree to the Privacy Policy and Terms of Use. I
257
+ understand that my photos will be processed by third-party AI
258
+ services to generate content.
259
+ </AtomicText>
260
+ </View>
261
+ </ScrollView>
262
+
263
+ <View style={styles.footer}>
264
+ <AtomicButton
265
+ variant="secondary"
266
+ onPress={handleDecline}
267
+ style={styles.declineButton}
268
+ fullWidth
269
+ >
270
+ Decline
271
+ </AtomicButton>
272
+ <AtomicButton
273
+ variant="primary"
274
+ onPress={handleAccept}
275
+ disabled={loading}
276
+ style={styles.acceptButton}
277
+ fullWidth
278
+ >
279
+ {loading ? (
280
+ <AtomicSpinner size="sm" color="background" />
281
+ ) : (
282
+ 'I Accept'
283
+ )}
284
+ </AtomicButton>
285
+ </View>
286
+ </ScreenLayout>
287
+ );
288
+ });
289
+
290
+ AIConsentScreen.displayName = 'AIConsentScreen';
291
+
292
+ const styles = StyleSheet.create({
293
+ scrollView: {
294
+ flex: 1,
295
+ },
296
+ scrollContent: {
297
+ paddingBottom: 100,
298
+ },
299
+ introText: {
300
+ fontSize: 15,
301
+ lineHeight: 22,
302
+ marginBottom: 24,
303
+ color: '#374151',
304
+ },
305
+ section: {
306
+ marginBottom: 24,
307
+ padding: 16,
308
+ backgroundColor: '#F9FAFB',
309
+ borderRadius: 12,
310
+ },
311
+ sectionTitle: {
312
+ fontSize: 17,
313
+ fontWeight: '600',
314
+ color: '#111827',
315
+ marginBottom: 12,
316
+ },
317
+ providerList: {
318
+ gap: 12,
319
+ },
320
+ providerItem: {
321
+ backgroundColor: '#FFFFFF',
322
+ padding: 12,
323
+ borderRadius: 8,
324
+ borderWidth: 1,
325
+ borderColor: '#E5E7EB',
326
+ },
327
+ providerHeader: {
328
+ flexDirection: 'row',
329
+ justifyContent: 'space-between',
330
+ alignItems: 'center',
331
+ marginBottom: 4,
332
+ },
333
+ providerName: {
334
+ fontSize: 15,
335
+ fontWeight: '600',
336
+ color: '#111827',
337
+ },
338
+ privacyLink: {
339
+ fontSize: 13,
340
+ color: '#3B82F6',
341
+ },
342
+ providerPurpose: {
343
+ fontSize: 14,
344
+ color: '#6B7280',
345
+ },
346
+ bullet: {
347
+ fontSize: 15,
348
+ color: '#374151',
349
+ lineHeight: 22,
350
+ marginLeft: 8,
351
+ },
352
+ note: {
353
+ fontSize: 13,
354
+ color: '#6B7280',
355
+ fontStyle: 'italic',
356
+ marginLeft: 8,
357
+ marginTop: 4,
358
+ },
359
+ linkButton: {
360
+ paddingVertical: 8,
361
+ marginTop: 8,
362
+ },
363
+ linkText: {
364
+ fontSize: 15,
365
+ color: '#3B82F6',
366
+ fontWeight: '500',
367
+ },
368
+ declarationSection: {
369
+ flexDirection: 'row',
370
+ alignItems: 'flex-start',
371
+ marginTop: 8,
372
+ padding: 12,
373
+ backgroundColor: '#EFF6FF',
374
+ borderRadius: 8,
375
+ },
376
+ checkbox: {
377
+ width: 24,
378
+ height: 24,
379
+ marginRight: 12,
380
+ marginTop: 2,
381
+ },
382
+ checkboxInner: {
383
+ width: 24,
384
+ height: 24,
385
+ borderRadius: 4,
386
+ backgroundColor: '#3B82F6',
387
+ alignItems: 'center',
388
+ justifyContent: 'center',
389
+ },
390
+ checkmark: {
391
+ color: '#FFFFFF',
392
+ fontSize: 16,
393
+ fontWeight: '700',
394
+ },
395
+ declarationText: {
396
+ flex: 1,
397
+ fontSize: 14,
398
+ color: '#1E3A8A',
399
+ lineHeight: 20,
400
+ },
401
+ footer: {
402
+ flexDirection: 'row',
403
+ padding: 16,
404
+ borderTopWidth: 1,
405
+ borderTopColor: '#E5E7EB',
406
+ gap: 12,
407
+ },
408
+ declineButton: {
409
+ flex: 1,
410
+ },
411
+ acceptButton: {
412
+ flex: 1,
413
+ },
414
+ });
package/src/index.ts CHANGED
@@ -141,6 +141,9 @@ export * from "./domains/gamification";
141
141
  // Localization Domain - i18n, language selection, translations
142
142
  export * from "./domains/localization";
143
143
 
144
+ // AI Consent Domain - AI technology disclosure and consent
145
+ export * from "./domains/ai-consent";
146
+
144
147
  // =============================================================================
145
148
  // PRESENTATION LAYER - Config Creator Utilities
146
149
  // =============================================================================
@@ -6,6 +6,7 @@ import { SettingsScreen } from "../../screens/SettingsScreen";
6
6
  import { DisclaimerScreen } from "../../../domains/disclaimer/presentation/screens/DisclaimerScreen";
7
7
  import { FeedbackScreen } from "../../../domains/feedback/presentation/screens/FeedbackScreen";
8
8
  import { RatingPromptScreen } from "../../../domains/rating/presentation/screens/RatingPromptScreen";
9
+ import { AIConsentScreen } from "../../../domains/ai-consent/presentation/screens/AIConsentScreen";
9
10
 
10
11
  // AccountScreen is an optional peer — lazy require so the package works without @umituz/react-native-auth
11
12
  // Returns null if @umituz/react-native-auth is not installed
@@ -198,6 +199,12 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
198
199
  options: { headerShown: false },
199
200
  };
200
201
 
202
+ const aiConsentScreen = {
203
+ name: "AIConsent" as const,
204
+ component: AIConsentScreen,
205
+ options: { headerShown: false },
206
+ };
207
+
201
208
  return combineScreens(
202
209
  baseScreens,
203
210
  faqScreen,
@@ -209,7 +216,8 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
209
216
  featureRequestScreen,
210
217
  disclaimerScreen,
211
218
  feedbackScreen,
212
- ratingPromptScreen
219
+ ratingPromptScreen,
220
+ aiConsentScreen
213
221
  );
214
222
  }, [
215
223
  translations,
@@ -9,6 +9,7 @@ import type { FAQCategory } from "../../domains/faqs";
9
9
  import type { DisclaimerScreenParams } from "../../domains/disclaimer/presentation/screens/DisclaimerScreen";
10
10
  import type { FeedbackScreenParams } from "../../domains/feedback/presentation/screens/FeedbackScreen";
11
11
  import type { RatingPromptScreenParams } from "../../domains/rating/presentation/screens/RatingPromptScreen";
12
+ import type { AIConsentScreenParams } from "../../domains/ai-consent/presentation/screens/AIConsentScreen";
12
13
 
13
14
  /**
14
15
  * App Info passed from main app (APP_INFO constant)
@@ -54,6 +55,7 @@ export type SettingsStackParamList = {
54
55
  Disclaimer: DisclaimerScreenParams;
55
56
  Feedback: FeedbackScreenParams;
56
57
  RatingPrompt: RatingPromptScreenParams;
58
+ AIConsent: AIConsentScreenParams;
57
59
  PasswordPrompt: {
58
60
  onComplete: (password: string | null) => void;
59
61
  title?: string;