@oxyhq/services 5.15.8 → 5.16.0

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 (148) hide show
  1. package/lib/commonjs/core/OxyServices.js +0 -1
  2. package/lib/commonjs/core/OxyServices.js.map +1 -1
  3. package/lib/commonjs/core/mixins/OxyServices.auth.js +3 -6
  4. package/lib/commonjs/core/mixins/OxyServices.auth.js.map +1 -1
  5. package/lib/commonjs/core/mixins/OxyServices.devices.js +1 -1
  6. package/lib/commonjs/core/mixins/OxyServices.devices.js.map +1 -1
  7. package/lib/commonjs/core/mixins/index.js +11 -12
  8. package/lib/commonjs/core/mixins/index.js.map +1 -1
  9. package/lib/commonjs/crypto/signatureService.js +3 -2
  10. package/lib/commonjs/crypto/signatureService.js.map +1 -1
  11. package/lib/commonjs/i18n/locales/ar-SA.json +1 -9
  12. package/lib/commonjs/i18n/locales/ca-ES.json +1 -9
  13. package/lib/commonjs/i18n/locales/de-DE.json +1 -9
  14. package/lib/commonjs/i18n/locales/en-US.json +3 -21
  15. package/lib/commonjs/i18n/locales/es-ES.json +3 -21
  16. package/lib/commonjs/i18n/locales/fr-FR.json +1 -9
  17. package/lib/commonjs/i18n/locales/it-IT.json +1 -9
  18. package/lib/commonjs/i18n/locales/ja-JP.json +1 -9
  19. package/lib/commonjs/i18n/locales/ko-KR.json +1 -9
  20. package/lib/commonjs/i18n/locales/pt-PT.json +1 -9
  21. package/lib/commonjs/i18n/locales/zh-CN.json +1 -9
  22. package/lib/commonjs/ui/context/OxyContext.js +24 -4
  23. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  24. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +217 -100
  25. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  26. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +2 -319
  27. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  28. package/lib/commonjs/ui/screens/OxyAuthScreen.js +178 -77
  29. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  30. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +0 -1
  31. package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
  32. package/lib/commonjs/ui/screens/SessionManagementScreen.js +43 -29
  33. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  34. package/lib/commonjs/ui/stores/authStore.js +14 -1
  35. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  36. package/lib/module/core/OxyServices.js +0 -1
  37. package/lib/module/core/OxyServices.js.map +1 -1
  38. package/lib/module/core/mixins/OxyServices.auth.js +3 -6
  39. package/lib/module/core/mixins/OxyServices.auth.js.map +1 -1
  40. package/lib/module/core/mixins/OxyServices.devices.js +1 -1
  41. package/lib/module/core/mixins/OxyServices.devices.js.map +1 -1
  42. package/lib/module/core/mixins/index.js +1 -2
  43. package/lib/module/core/mixins/index.js.map +1 -1
  44. package/lib/module/crypto/signatureService.js +3 -2
  45. package/lib/module/crypto/signatureService.js.map +1 -1
  46. package/lib/module/i18n/locales/ar-SA.json +1 -9
  47. package/lib/module/i18n/locales/ca-ES.json +1 -9
  48. package/lib/module/i18n/locales/de-DE.json +1 -9
  49. package/lib/module/i18n/locales/en-US.json +3 -21
  50. package/lib/module/i18n/locales/es-ES.json +3 -21
  51. package/lib/module/i18n/locales/fr-FR.json +1 -9
  52. package/lib/module/i18n/locales/it-IT.json +1 -9
  53. package/lib/module/i18n/locales/ja-JP.json +1 -9
  54. package/lib/module/i18n/locales/ko-KR.json +1 -9
  55. package/lib/module/i18n/locales/pt-PT.json +1 -9
  56. package/lib/module/i18n/locales/zh-CN.json +1 -9
  57. package/lib/module/ui/context/OxyContext.js +24 -4
  58. package/lib/module/ui/context/OxyContext.js.map +1 -1
  59. package/lib/module/ui/context/hooks/useAuthOperations.js +217 -100
  60. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  61. package/lib/module/ui/screens/AccountSettingsScreen.js +2 -319
  62. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  63. package/lib/module/ui/screens/OxyAuthScreen.js +179 -78
  64. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  65. package/lib/module/ui/screens/PrivacySettingsScreen.js +0 -1
  66. package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
  67. package/lib/module/ui/screens/SessionManagementScreen.js +44 -29
  68. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  69. package/lib/module/ui/stores/authStore.js +14 -1
  70. package/lib/module/ui/stores/authStore.js.map +1 -1
  71. package/lib/typescript/core/OxyServices.d.ts +0 -1
  72. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  73. package/lib/typescript/core/mixins/OxyServices.auth.d.ts +3 -4
  74. package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
  75. package/lib/typescript/core/mixins/OxyServices.devices.d.ts +1 -4
  76. package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
  77. package/lib/typescript/core/mixins/index.d.ts +1 -64
  78. package/lib/typescript/core/mixins/index.d.ts.map +1 -1
  79. package/lib/typescript/crypto/signatureService.d.ts +2 -1
  80. package/lib/typescript/crypto/signatureService.d.ts.map +1 -1
  81. package/lib/typescript/models/interfaces.d.ts +1 -1
  82. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  83. package/lib/typescript/types/bip39.d.ts +1 -0
  84. package/lib/typescript/types/buffer.d.ts +1 -0
  85. package/lib/typescript/types/color.d.ts +1 -0
  86. package/lib/typescript/types/elliptic.d.ts +1 -0
  87. package/lib/typescript/types/expo-crypto.d.ts +1 -0
  88. package/lib/typescript/types/expo-secure-store.d.ts +1 -0
  89. package/lib/typescript/ui/context/OxyContext.d.ts +11 -3
  90. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  91. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +13 -5
  92. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  93. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  94. package/lib/typescript/ui/screens/OxyAuthScreen.d.ts +1 -0
  95. package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  96. package/lib/typescript/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
  97. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  98. package/lib/typescript/ui/stores/authStore.d.ts +4 -0
  99. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  100. package/package.json +6 -5
  101. package/src/core/OxyServices.ts +0 -1
  102. package/src/core/mixins/OxyServices.auth.ts +3 -8
  103. package/src/core/mixins/OxyServices.devices.ts +1 -4
  104. package/src/core/mixins/index.ts +2 -5
  105. package/src/crypto/index.ts +1 -0
  106. package/src/crypto/keyManager.ts +1 -0
  107. package/src/crypto/polyfill.ts +1 -0
  108. package/src/crypto/recoveryPhrase.ts +1 -0
  109. package/src/crypto/signatureService.ts +4 -5
  110. package/src/i18n/locales/ar-SA.json +1 -9
  111. package/src/i18n/locales/ca-ES.json +1 -9
  112. package/src/i18n/locales/de-DE.json +1 -9
  113. package/src/i18n/locales/en-US.json +3 -21
  114. package/src/i18n/locales/es-ES.json +3 -21
  115. package/src/i18n/locales/fr-FR.json +1 -9
  116. package/src/i18n/locales/it-IT.json +1 -9
  117. package/src/i18n/locales/ja-JP.json +1 -9
  118. package/src/i18n/locales/ko-KR.json +1 -9
  119. package/src/i18n/locales/pt-PT.json +1 -9
  120. package/src/i18n/locales/zh-CN.json +1 -9
  121. package/src/models/interfaces.ts +1 -1
  122. package/src/types/bip39.d.ts +1 -0
  123. package/src/types/buffer.d.ts +1 -0
  124. package/src/types/color.d.ts +1 -0
  125. package/src/types/elliptic.d.ts +1 -0
  126. package/src/types/expo-crypto.d.ts +1 -0
  127. package/src/types/expo-secure-store.d.ts +1 -0
  128. package/src/ui/context/OxyContext.tsx +35 -3
  129. package/src/ui/context/hooks/useAuthOperations.ts +212 -98
  130. package/src/ui/screens/AccountSettingsScreen.tsx +1 -201
  131. package/src/ui/screens/OxyAuthScreen.tsx +193 -69
  132. package/src/ui/screens/PrivacySettingsScreen.tsx +0 -2
  133. package/src/ui/screens/SessionManagementScreen.tsx +43 -26
  134. package/src/ui/stores/authStore.ts +31 -2
  135. package/lib/commonjs/core/mixins/OxyServices.totp.js +0 -53
  136. package/lib/commonjs/core/mixins/OxyServices.totp.js.map +0 -1
  137. package/lib/commonjs/ui/components/profile/TwoFactorSetupModal.js +0 -467
  138. package/lib/commonjs/ui/components/profile/TwoFactorSetupModal.js.map +0 -1
  139. package/lib/module/core/mixins/OxyServices.totp.js +0 -49
  140. package/lib/module/core/mixins/OxyServices.totp.js.map +0 -1
  141. package/lib/module/ui/components/profile/TwoFactorSetupModal.js +0 -460
  142. package/lib/module/ui/components/profile/TwoFactorSetupModal.js.map +0 -1
  143. package/lib/typescript/core/mixins/OxyServices.totp.d.ts +0 -66
  144. package/lib/typescript/core/mixins/OxyServices.totp.d.ts.map +0 -1
  145. package/lib/typescript/ui/components/profile/TwoFactorSetupModal.d.ts +0 -11
  146. package/lib/typescript/ui/components/profile/TwoFactorSetupModal.d.ts.map +0 -1
  147. package/src/core/mixins/OxyServices.totp.ts +0 -36
  148. package/src/ui/components/profile/TwoFactorSetupModal.tsx +0 -442
@@ -1,442 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import {
3
- View,
4
- Text,
5
- TextInput,
6
- TouchableOpacity,
7
- StyleSheet,
8
- Modal,
9
- Platform,
10
- ScrollView,
11
- ActivityIndicator,
12
- } from 'react-native';
13
- import { Ionicons } from '@expo/vector-icons';
14
- import QRCode from 'react-native-qrcode-svg';
15
- import { useThemeStyles } from '../../hooks/useThemeStyles';
16
- import { useColorScheme } from '../../hooks/use-color-scheme';
17
- import { useI18n } from '../../hooks/useI18n';
18
- import { fontFamilies } from '../../styles/fonts';
19
- import { useOxy } from '../../context/OxyContext';
20
- import { useAuthStore } from '../../stores/authStore';
21
- import { toast } from '../../../lib/sonner';
22
-
23
- interface TwoFactorSetupModalProps {
24
- visible: boolean;
25
- onClose: () => void;
26
- isEnabled: boolean;
27
- theme?: 'light' | 'dark';
28
- onSave?: () => void;
29
- }
30
-
31
- export const TwoFactorSetupModal: React.FC<TwoFactorSetupModalProps> = ({
32
- visible,
33
- onClose,
34
- isEnabled,
35
- theme = 'light',
36
- onSave,
37
- }) => {
38
- const { t } = useI18n();
39
- const colorScheme = useColorScheme();
40
- const themeStyles = useThemeStyles(theme || 'light', colorScheme);
41
- const colors = themeStyles.colors;
42
- const { oxyServices, activeSessionId } = useOxy();
43
- const updateUser = useAuthStore((state) => state.updateUser);
44
-
45
- const [totpSetupUrl, setTotpSetupUrl] = useState<string | null>(null);
46
- const [totpCode, setTotpCode] = useState('');
47
- const [isBusy, setIsBusy] = useState(false);
48
- const [showRecoveryCodes, setShowRecoveryCodes] = useState(false);
49
- const [recoveryCodes, setRecoveryCodes] = useState<string[] | null>(null);
50
- const [recoveryKey, setRecoveryKey] = useState<string | null>(null);
51
-
52
- useEffect(() => {
53
- if (visible && !isEnabled) {
54
- setTotpSetupUrl(null);
55
- setTotpCode('');
56
- setShowRecoveryCodes(false);
57
- setRecoveryCodes(null);
58
- setRecoveryKey(null);
59
- }
60
- }, [visible, isEnabled]);
61
-
62
- const handleGenerateQR = async () => {
63
- if (!activeSessionId || !oxyServices) {
64
- toast.error(t('editProfile.toasts.noActiveSession') || 'No active session');
65
- return;
66
- }
67
-
68
- setIsBusy(true);
69
- try {
70
- const { otpauthUrl } = await oxyServices.startTotpEnrollment(activeSessionId);
71
- setTotpSetupUrl(otpauthUrl);
72
- } catch (e: any) {
73
- toast.error(e?.message || (t('editProfile.toasts.totpStartFailed') || 'Failed to start TOTP enrollment'));
74
- } finally {
75
- setIsBusy(false);
76
- }
77
- };
78
-
79
- const handleVerify = async () => {
80
- if (!activeSessionId || !oxyServices) {
81
- toast.error(t('editProfile.toasts.noActiveSession') || 'No active session');
82
- return;
83
- }
84
-
85
- if (totpCode.length !== 6) {
86
- toast.error(t('editProfile.toasts.invalidCode') || 'Please enter a 6-digit code');
87
- return;
88
- }
89
-
90
- setIsBusy(true);
91
- try {
92
- const result = await oxyServices.verifyTotpEnrollment(activeSessionId, totpCode);
93
- await updateUser({ privacySettings: { twoFactorEnabled: true } }, oxyServices);
94
-
95
- if (result?.backupCodes || result?.recoveryKey) {
96
- setRecoveryCodes(result.backupCodes || null);
97
- setRecoveryKey(result.recoveryKey || null);
98
- setShowRecoveryCodes(true);
99
- } else {
100
- toast.success(t('editProfile.toasts.twoFactorEnabled') || 'Two‑Factor Authentication enabled');
101
- onSave?.();
102
- onClose();
103
- }
104
- } catch (e: any) {
105
- toast.error(e?.message || (t('editProfile.toasts.invalidCode') || 'Invalid code'));
106
- } finally {
107
- setIsBusy(false);
108
- }
109
- };
110
-
111
- const handleDisable = async () => {
112
- if (!activeSessionId || !oxyServices) {
113
- toast.error(t('editProfile.toasts.noActiveSession') || 'No active session');
114
- return;
115
- }
116
-
117
- if (totpCode.length !== 6) {
118
- toast.error(t('editProfile.toasts.invalidCode') || 'Please enter a 6-digit code');
119
- return;
120
- }
121
-
122
- setIsBusy(true);
123
- try {
124
- // Verify code before disabling
125
- await oxyServices.verifyTotpEnrollment(activeSessionId, totpCode);
126
- await updateUser({ privacySettings: { twoFactorEnabled: false } }, oxyServices);
127
- toast.success(t('editProfile.toasts.twoFactorDisabled') || 'Two‑Factor Authentication disabled');
128
- onSave?.();
129
- onClose();
130
- } catch (e: any) {
131
- toast.error(e?.message || (t('editProfile.toasts.invalidCode') || 'Invalid code'));
132
- } finally {
133
- setIsBusy(false);
134
- }
135
- };
136
-
137
- return (
138
- <Modal
139
- visible={visible}
140
- animationType="slide"
141
- transparent={true}
142
- onRequestClose={onClose}
143
- >
144
- <View style={styles.modalOverlay}>
145
- <View style={[styles.modalContent, { backgroundColor: colors.background }]}>
146
- <View style={styles.modalHeader}>
147
- <TouchableOpacity onPress={onClose} style={styles.closeButton}>
148
- <Ionicons name="close" size={24} color={colors.text} />
149
- </TouchableOpacity>
150
- <Text style={[styles.modalTitle, { color: colors.text }]}>
151
- {t('editProfile.items.twoFactor.title') || 'Two‑Factor Authentication'}
152
- </Text>
153
- <View style={{ width: 40 }} />
154
- </View>
155
-
156
- <ScrollView style={styles.modalBody}>
157
- {showRecoveryCodes ? (
158
- <View style={styles.recoverySection}>
159
- <Text style={[styles.sectionTitle, { color: colors.text }]}>
160
- {t('editProfile.items.twoFactor.saveCodes') || 'Save These Codes'}
161
- </Text>
162
- <Text style={[styles.description, { color: colors.secondaryText }]}>
163
- {t('editProfile.items.twoFactor.recoveryDescription') || 'Backup codes and your Recovery Key are shown only once. Store them securely.'}
164
- </Text>
165
-
166
- {recoveryCodes && recoveryCodes.length > 0 && (
167
- <View style={styles.recoveryCodesContainer}>
168
- <Text style={[styles.recoveryLabel, { color: colors.text }]}>Backup Codes</Text>
169
- <View style={[styles.codesBox, { backgroundColor: colors.card, borderColor: colors.border }]}>
170
- {recoveryCodes.map((code, idx) => (
171
- <Text key={idx} style={[styles.codeText, { color: colors.text }]}>
172
- {code}
173
- </Text>
174
- ))}
175
- </View>
176
- </View>
177
- )}
178
-
179
- {recoveryKey && (
180
- <View style={styles.recoveryCodesContainer}>
181
- <Text style={[styles.recoveryLabel, { color: colors.text }]}>Recovery Key</Text>
182
- <View style={[styles.codesBox, { backgroundColor: colors.card, borderColor: colors.border }]}>
183
- <Text style={[styles.codeText, { color: colors.text }]}>
184
- {recoveryKey}
185
- </Text>
186
- </View>
187
- </View>
188
- )}
189
-
190
- <TouchableOpacity
191
- style={[styles.primaryButton, { backgroundColor: colors.tint }]}
192
- onPress={() => {
193
- setShowRecoveryCodes(false);
194
- onSave?.();
195
- onClose();
196
- }}
197
- >
198
- <Text style={styles.primaryButtonText}>
199
- {t('editProfile.items.twoFactor.saved') || 'I saved them'}
200
- </Text>
201
- </TouchableOpacity>
202
- </View>
203
- ) : isEnabled ? (
204
- <View style={styles.disableSection}>
205
- <Text style={[styles.description, { color: colors.secondaryText }]}>
206
- {t('editProfile.items.twoFactor.disableDescription') || 'Two‑Factor Authentication is currently enabled. To disable, enter a code from your authenticator app.'}
207
- </Text>
208
- <View style={styles.inputGroup}>
209
- <Text style={[styles.label, { color: colors.text }]}>
210
- {t('editProfile.items.twoFactor.enterCode') || 'Enter 6‑digit code'}
211
- </Text>
212
- <TextInput
213
- style={[
214
- styles.input,
215
- {
216
- backgroundColor: colors.card,
217
- color: colors.text,
218
- borderColor: colors.border,
219
- },
220
- ]}
221
- value={totpCode}
222
- onChangeText={setTotpCode}
223
- placeholder="123456"
224
- placeholderTextColor={colors.secondaryText}
225
- keyboardType="number-pad"
226
- maxLength={6}
227
- selectionColor={colors.tint}
228
- />
229
- </View>
230
- <TouchableOpacity
231
- style={[styles.primaryButton, { backgroundColor: '#FF3B30' }]}
232
- disabled={isBusy || totpCode.length !== 6}
233
- onPress={handleDisable}
234
- >
235
- {isBusy ? (
236
- <ActivityIndicator size="small" color="#fff" />
237
- ) : (
238
- <Text style={styles.primaryButtonText}>
239
- {t('editProfile.items.twoFactor.disable') || 'Disable'}
240
- </Text>
241
- )}
242
- </TouchableOpacity>
243
- </View>
244
- ) : (
245
- <View style={styles.enableSection}>
246
- <Text style={[styles.description, { color: colors.secondaryText }]}>
247
- {t('editProfile.items.twoFactor.description') || 'Protect your account with a 6‑digit code from an authenticator app. Scan the QR code then enter the code to enable.'}
248
- </Text>
249
-
250
- {!totpSetupUrl ? (
251
- <TouchableOpacity
252
- style={[styles.primaryButton, { backgroundColor: colors.tint }]}
253
- disabled={isBusy}
254
- onPress={handleGenerateQR}
255
- >
256
- {isBusy ? (
257
- <ActivityIndicator size="small" color="#fff" />
258
- ) : (
259
- <>
260
- <Ionicons name="shield-checkmark" size={18} color="#fff" />
261
- <Text style={styles.primaryButtonText}>
262
- {t('editProfile.items.twoFactor.generateQR') || 'Generate QR Code'}
263
- </Text>
264
- </>
265
- )}
266
- </TouchableOpacity>
267
- ) : (
268
- <>
269
- <View style={[styles.qrContainer, { backgroundColor: '#fff' }]}>
270
- <QRCode value={totpSetupUrl} size={180} />
271
- </View>
272
- <View style={styles.inputGroup}>
273
- <Text style={[styles.label, { color: colors.text }]}>
274
- {t('editProfile.items.twoFactor.enterCode') || 'Enter 6‑digit code'}
275
- </Text>
276
- <TextInput
277
- style={[
278
- styles.input,
279
- {
280
- backgroundColor: colors.card,
281
- color: colors.text,
282
- borderColor: colors.border,
283
- },
284
- ]}
285
- value={totpCode}
286
- onChangeText={setTotpCode}
287
- placeholder="123456"
288
- placeholderTextColor={colors.secondaryText}
289
- keyboardType="number-pad"
290
- maxLength={6}
291
- selectionColor={colors.tint}
292
- />
293
- </View>
294
- <TouchableOpacity
295
- style={[styles.primaryButton, { backgroundColor: colors.tint }]}
296
- disabled={isBusy || totpCode.length !== 6}
297
- onPress={handleVerify}
298
- >
299
- {isBusy ? (
300
- <ActivityIndicator size="small" color="#fff" />
301
- ) : (
302
- <>
303
- <Ionicons name="checkmark-circle" size={18} color="#fff" />
304
- <Text style={styles.primaryButtonText}>
305
- {t('editProfile.items.twoFactor.verify') || 'Verify & Enable'}
306
- </Text>
307
- </>
308
- )}
309
- </TouchableOpacity>
310
- </>
311
- )}
312
- </View>
313
- )}
314
- </ScrollView>
315
- </View>
316
- </View>
317
- </Modal>
318
- );
319
- };
320
-
321
- const styles = StyleSheet.create({
322
- modalOverlay: {
323
- flex: 1,
324
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
325
- justifyContent: 'flex-end',
326
- },
327
- modalContent: {
328
- borderTopLeftRadius: 20,
329
- borderTopRightRadius: 20,
330
- paddingTop: Platform.OS === 'ios' ? 20 : 16,
331
- maxHeight: '80%',
332
- },
333
- modalHeader: {
334
- flexDirection: 'row',
335
- alignItems: 'center',
336
- justifyContent: 'space-between',
337
- paddingHorizontal: 16,
338
- paddingBottom: 16,
339
- borderBottomWidth: StyleSheet.hairlineWidth,
340
- borderBottomColor: '#E5E5EA',
341
- },
342
- closeButton: {
343
- width: 40,
344
- height: 40,
345
- alignItems: 'center',
346
- justifyContent: 'center',
347
- },
348
- modalTitle: {
349
- fontSize: 18,
350
- fontWeight: '600',
351
- fontFamily: fontFamilies.phuduSemiBold,
352
- flex: 1,
353
- textAlign: 'center',
354
- },
355
- modalBody: {
356
- padding: 16,
357
- },
358
- enableSection: {
359
- gap: 24,
360
- alignItems: 'center',
361
- },
362
- disableSection: {
363
- gap: 24,
364
- },
365
- recoverySection: {
366
- gap: 24,
367
- },
368
- sectionTitle: {
369
- fontSize: 20,
370
- fontWeight: '700',
371
- fontFamily: fontFamilies.phuduBold,
372
- },
373
- description: {
374
- fontSize: 14,
375
- lineHeight: 20,
376
- },
377
- qrContainer: {
378
- padding: 16,
379
- borderRadius: 16,
380
- alignItems: 'center',
381
- justifyContent: 'center',
382
- },
383
- inputGroup: {
384
- width: '100%',
385
- gap: 8,
386
- },
387
- label: {
388
- fontSize: 14,
389
- fontWeight: '600',
390
- fontFamily: fontFamilies.phuduSemiBold,
391
- },
392
- input: {
393
- borderWidth: StyleSheet.hairlineWidth,
394
- borderRadius: 12,
395
- padding: 16,
396
- fontSize: 16,
397
- minHeight: 52,
398
- textAlign: 'center',
399
- },
400
- primaryButton: {
401
- flexDirection: 'row',
402
- alignItems: 'center',
403
- justifyContent: 'center',
404
- gap: 8,
405
- paddingVertical: 12,
406
- paddingHorizontal: 16,
407
- borderRadius: 12,
408
- width: '100%',
409
- },
410
- primaryButtonText: {
411
- color: '#fff',
412
- fontSize: 16,
413
- fontWeight: '600',
414
- fontFamily: fontFamilies.phuduSemiBold,
415
- },
416
- recoveryCodesContainer: {
417
- gap: 8,
418
- },
419
- recoveryLabel: {
420
- fontSize: 16,
421
- fontWeight: '600',
422
- fontFamily: fontFamilies.phuduSemiBold,
423
- },
424
- codesBox: {
425
- padding: 16,
426
- borderRadius: 12,
427
- borderWidth: StyleSheet.hairlineWidth,
428
- gap: 8,
429
- },
430
- codeText: {
431
- fontSize: 14,
432
- fontFamily: Platform.OS === 'web' ? 'monospace' as any : 'monospace',
433
- },
434
- });
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-