create-gufran-expo-app 2.0.0 → 2.0.2

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 (266) hide show
  1. package/lib/createApp.js +7 -2
  2. package/package.json +1 -1
  3. package/template/App.tsx +118 -0
  4. package/template/ReactotronConfig.js +5 -0
  5. package/template/android/app/build.gradle +184 -0
  6. package/template/android/app/debug.keystore +0 -0
  7. package/template/android/app/google-services.json +29 -0
  8. package/template/android/app/proguard-rules.pro +14 -0
  9. package/template/android/app/src/debug/AndroidManifest.xml +7 -0
  10. package/template/android/app/src/debugOptimized/AndroidManifest.xml +7 -0
  11. package/template/android/app/src/main/AndroidManifest.xml +28 -0
  12. package/template/android/app/src/main/assets/fonts/Outfit-Bold.ttf +0 -0
  13. package/template/android/app/src/main/assets/fonts/Outfit-Light.ttf +0 -0
  14. package/template/android/app/src/main/assets/fonts/Outfit-Medium.ttf +0 -0
  15. package/template/android/app/src/main/assets/fonts/Outfit-Regular.ttf +0 -0
  16. package/template/android/app/src/main/assets/fonts/Outfit-SemiBold.ttf +0 -0
  17. package/template/android/app/src/main/java/com/club/yakka/MainActivity.kt +61 -0
  18. package/template/android/app/src/main/java/com/club/yakka/MainApplication.kt +60 -0
  19. package/template/android/app/src/main/res/drawable/ic_launcher_background.xml +6 -0
  20. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  21. package/template/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png +0 -0
  22. package/template/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png +0 -0
  23. package/template/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png +0 -0
  24. package/template/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png +0 -0
  25. package/template/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png +0 -0
  26. package/template/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  27. package/template/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  28. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  29. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp +0 -0
  30. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  31. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  32. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp +0 -0
  33. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  34. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  35. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp +0 -0
  36. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  37. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  38. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp +0 -0
  39. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  40. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  41. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp +0 -0
  42. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  43. package/template/android/app/src/main/res/values/colors.xml +6 -0
  44. package/template/android/app/src/main/res/values/strings.xml +5 -0
  45. package/template/android/app/src/main/res/values/styles.xml +14 -0
  46. package/template/android/app/src/main/res/values-night/colors.xml +1 -0
  47. package/template/android/build.gradle +33 -0
  48. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  49. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  50. package/template/android/gradle.properties +65 -0
  51. package/template/android/gradlew +251 -0
  52. package/template/android/gradlew.bat +94 -0
  53. package/template/android/settings.gradle +39 -0
  54. package/template/app.json +69 -0
  55. package/template/assets/adaptive-icon.png +0 -0
  56. package/template/assets/adaptive-icon1.png +0 -0
  57. package/template/assets/app_icon.png +0 -0
  58. package/template/assets/favicon.png +0 -0
  59. package/template/assets/icon.png +0 -0
  60. package/template/assets/splash-icon.png +0 -0
  61. package/template/babel-plugin-disable-font-scaling.js +41 -0
  62. package/template/babel.config.js +28 -0
  63. package/template/firebase.json +5 -0
  64. package/template/index.ts +24 -0
  65. package/template/ios/.xcode.env +11 -0
  66. package/template/ios/ClubYakka/AppDelegate.swift +74 -0
  67. package/template/ios/ClubYakka/ClubYakka-Bridging-Header.h +3 -0
  68. package/template/ios/ClubYakka/ClubYakka.entitlements +8 -0
  69. package/template/ios/ClubYakka/GoogleService-Info.plist +30 -0
  70. package/template/ios/ClubYakka/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png +0 -0
  71. package/template/ios/ClubYakka/Images.xcassets/AppIcon.appiconset/Contents.json +14 -0
  72. package/template/ios/ClubYakka/Images.xcassets/Contents.json +6 -0
  73. package/template/ios/ClubYakka/Images.xcassets/SplashScreenBackground.colorset/Contents.json +20 -0
  74. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +23 -0
  75. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image.png +0 -0
  76. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image@2x.png +0 -0
  77. package/template/ios/ClubYakka/Images.xcassets/SplashScreenLegacy.imageset/image@3x.png +0 -0
  78. package/template/ios/ClubYakka/Info.plist +101 -0
  79. package/template/ios/ClubYakka/PrivacyInfo.xcprivacy +50 -0
  80. package/template/ios/ClubYakka/SplashScreen.storyboard +48 -0
  81. package/template/ios/ClubYakka/Supporting/Expo.plist +12 -0
  82. package/template/ios/ClubYakka.xcodeproj/project.pbxproj +669 -0
  83. package/template/ios/ClubYakka.xcodeproj/xcshareddata/xcschemes/ClubYakka.xcscheme +88 -0
  84. package/template/ios/ClubYakka.xcworkspace/contents.xcworkspacedata +10 -0
  85. package/template/ios/ClubYakka.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +5 -0
  86. package/template/ios/Podfile +84 -0
  87. package/template/ios/Podfile.lock +2698 -0
  88. package/template/ios/Podfile.properties.json +8 -0
  89. package/template/metro.config.js +17 -0
  90. package/template/package.json +70 -0
  91. package/template/patches/react-native-background-upload+6.6.0.patch +704 -0
  92. package/template/react-native.config.js +7 -0
  93. package/template/src/assets/fonts/Outfit-Bold.ttf +0 -0
  94. package/template/src/assets/fonts/Outfit-Light.ttf +0 -0
  95. package/template/src/assets/fonts/Outfit-Medium.ttf +0 -0
  96. package/template/src/assets/fonts/Outfit-Regular.ttf +0 -0
  97. package/template/src/assets/fonts/Outfit-SemiBold.ttf +0 -0
  98. package/template/src/assets/icons/BG.svg +33 -0
  99. package/template/src/assets/icons/Ic_Users.svg +6 -0
  100. package/template/src/assets/icons/arrow-left-white.svg +4 -0
  101. package/template/src/assets/icons/arrow-left.svg +4 -0
  102. package/template/src/assets/icons/bell.svg +4 -0
  103. package/template/src/assets/icons/bottomSheetIcone.svg +3 -0
  104. package/template/src/assets/icons/call.svg +4 -0
  105. package/template/src/assets/icons/camera.svg +0 -0
  106. package/template/src/assets/icons/chatAppleGreenBG.svg +22 -0
  107. package/template/src/assets/icons/check.svg +4 -0
  108. package/template/src/assets/icons/check_Radio.svg +4 -0
  109. package/template/src/assets/icons/chevron-right.svg +3 -0
  110. package/template/src/assets/icons/clubDefauldImage.png +0 -0
  111. package/template/src/assets/icons/curvBackgroundView.svg +3 -0
  112. package/template/src/assets/icons/defaultClub.png +0 -0
  113. package/template/src/assets/icons/email.svg +3 -0
  114. package/template/src/assets/icons/emptyUser.svg +5 -0
  115. package/template/src/assets/icons/eye-Hide.svg +8 -0
  116. package/template/src/assets/icons/eye.svg +4 -0
  117. package/template/src/assets/icons/gallery.svg +4 -0
  118. package/template/src/assets/icons/home.svg +4 -0
  119. package/template/src/assets/icons/ic_Calendar.svg +14 -0
  120. package/template/src/assets/icons/ic_Calendar_blue.svg +12 -0
  121. package/template/src/assets/icons/ic_Calendar_white.svg +12 -0
  122. package/template/src/assets/icons/ic_Chat.svg +14 -0
  123. package/template/src/assets/icons/ic_ChatAppleGreen.svg +21 -0
  124. package/template/src/assets/icons/ic_ChatAppleWhite.svg +21 -0
  125. package/template/src/assets/icons/ic_Download.svg +6 -0
  126. package/template/src/assets/icons/ic_Events.svg +6 -0
  127. package/template/src/assets/icons/ic_HeadCoachIcon.svg +3 -0
  128. package/template/src/assets/icons/ic_Membership.svg +10 -0
  129. package/template/src/assets/icons/ic_Notification.svg +6 -0
  130. package/template/src/assets/icons/ic_Raffles.svg +14 -0
  131. package/template/src/assets/icons/ic_Referral_Members.svg +12 -0
  132. package/template/src/assets/icons/ic_Shop.svg +13 -0
  133. package/template/src/assets/icons/ic_Teams.svg +8 -0
  134. package/template/src/assets/icons/ic_Volunteer.svg +9 -0
  135. package/template/src/assets/icons/ic_add.svg +3 -0
  136. package/template/src/assets/icons/ic_addCircle.svg +5 -0
  137. package/template/src/assets/icons/ic_chatSend.svg +4 -0
  138. package/template/src/assets/icons/ic_chat_blue_bg.svg +22 -0
  139. package/template/src/assets/icons/ic_clock_blue.svg +4 -0
  140. package/template/src/assets/icons/ic_delete.svg +8 -0
  141. package/template/src/assets/icons/ic_more.svg +5 -0
  142. package/template/src/assets/icons/ic_mute.svg +10 -0
  143. package/template/src/assets/icons/ic_pdf.svg +3 -0
  144. package/template/src/assets/icons/ic_pending_AppleGreen.svg +11 -0
  145. package/template/src/assets/icons/ic_right_appleGreen.svg +11 -0
  146. package/template/src/assets/icons/ic_unread_chat_blue_bg.svg +23 -0
  147. package/template/src/assets/icons/ic_volunteer_Member.svg +8 -0
  148. package/template/src/assets/icons/index.ts +144 -0
  149. package/template/src/assets/icons/location-blue.svg +4 -0
  150. package/template/src/assets/icons/location-white.svg +4 -0
  151. package/template/src/assets/icons/location.svg +4 -0
  152. package/template/src/assets/icons/lock.svg +5 -0
  153. package/template/src/assets/icons/log-out.svg +5 -0
  154. package/template/src/assets/icons/login_logo.svg +9 -0
  155. package/template/src/assets/icons/mail.svg +4 -0
  156. package/template/src/assets/icons/or_saprater.svg +5 -0
  157. package/template/src/assets/icons/password.svg +4 -0
  158. package/template/src/assets/icons/profile-appleGreen.svg +6 -0
  159. package/template/src/assets/icons/search.svg +3 -0
  160. package/template/src/assets/icons/settings.svg +4 -0
  161. package/template/src/assets/icons/success.svg +4 -0
  162. package/template/src/assets/icons/unCheck_Radio.svg +3 -0
  163. package/template/src/assets/icons/uncheck.svg +3 -0
  164. package/template/src/assets/icons/upload_Image.svg +6 -0
  165. package/template/src/assets/icons/upload_Image_Member.svg +6 -0
  166. package/template/src/assets/icons/user.svg +4 -0
  167. package/template/src/assets/icons/wifi.svg +1 -0
  168. package/template/src/assets/images/Splash.png +0 -0
  169. package/template/src/assets/images/SplashLogo.png +0 -0
  170. package/template/src/assets/images/background.png +0 -0
  171. package/template/src/assets/images/clubDefauldImage.png +0 -0
  172. package/template/src/assets/images/index.tsx +9 -0
  173. package/template/src/assets/index.ts +1 -0
  174. package/template/src/components/common/AddMemberModal.tsx +543 -0
  175. package/template/src/components/common/AppLoader.tsx +91 -0
  176. package/template/src/components/common/Button.tsx +173 -0
  177. package/template/src/components/common/ClubCard.tsx +248 -0
  178. package/template/src/components/common/Icon.tsx +93 -0
  179. package/template/src/components/common/IconAlt.tsx +65 -0
  180. package/template/src/components/common/IconButton.tsx +92 -0
  181. package/template/src/components/common/ImagePicker.tsx +451 -0
  182. package/template/src/components/common/LoadingSpinner.tsx +30 -0
  183. package/template/src/components/common/OTPInput.tsx +128 -0
  184. package/template/src/components/common/ReminderCalendar.tsx +129 -0
  185. package/template/src/components/common/ReminderCardItem.tsx +91 -0
  186. package/template/src/components/common/SafeAreaWrapper.tsx +27 -0
  187. package/template/src/components/common/SetReminderModal.tsx +308 -0
  188. package/template/src/components/common/SlowInternet.js +57 -0
  189. package/template/src/components/common/TeamCard.tsx +297 -0
  190. package/template/src/components/common/TextInput.tsx +227 -0
  191. package/template/src/components/common/ToastConfig.tsx +103 -0
  192. package/template/src/components/common/ToastManager.ts +86 -0
  193. package/template/src/components/common/UploadProgressModal.tsx +284 -0
  194. package/template/src/components/common/WrapperContainer.tsx +39 -0
  195. package/template/src/components/common/index.ts +19 -0
  196. package/template/src/constants/Constants.tsx +7 -0
  197. package/template/src/constants/Fonts.tsx +30 -0
  198. package/template/src/constants/index.ts +45 -0
  199. package/template/src/constants/strings.ts +211 -0
  200. package/template/src/constants/theme.ts +72 -0
  201. package/template/src/contexts/AuthContext.tsx +268 -0
  202. package/template/src/contexts/index.ts +2 -0
  203. package/template/src/hooks/index.ts +3 -0
  204. package/template/src/hooks/useImageUpload.ts +199 -0
  205. package/template/src/index.ts +8 -0
  206. package/template/src/navigation/AuthStack.tsx +67 -0
  207. package/template/src/navigation/MainStack.tsx +183 -0
  208. package/template/src/navigation/MiddleStack.tsx +35 -0
  209. package/template/src/navigation/RootNavigator.tsx +101 -0
  210. package/template/src/navigation/index.ts +5 -0
  211. package/template/src/navigation/navigationRef.ts +5 -0
  212. package/template/src/providers/QueryProvider.tsx +30 -0
  213. package/template/src/screens/DetailsScreen.tsx +271 -0
  214. package/template/src/screens/HomeScreen.tsx +736 -0
  215. package/template/src/screens/ProfileScreen.tsx +202 -0
  216. package/template/src/screens/SettingsScreen.tsx +253 -0
  217. package/template/src/screens/SportHubScreen.tsx +280 -0
  218. package/template/src/screens/auth/AddMamber.tsx +428 -0
  219. package/template/src/screens/auth/ForgotPasswordScreen.tsx +176 -0
  220. package/template/src/screens/auth/LoginScreen.tsx +286 -0
  221. package/template/src/screens/auth/OTPVerifyScreen.tsx +359 -0
  222. package/template/src/screens/auth/RegisterScreen.tsx +430 -0
  223. package/template/src/screens/auth/SuccessScreen.tsx +201 -0
  224. package/template/src/screens/auth/WalcomeScreen.tsx +274 -0
  225. package/template/src/screens/auth/index.ts +8 -0
  226. package/template/src/screens/chat/ChatScreen.tsx +1819 -0
  227. package/template/src/screens/chat/ChatThreadsScreen.tsx +360 -0
  228. package/template/src/screens/chat/ReportMessageScreen.tsx +238 -0
  229. package/template/src/screens/clubs/Announcements.tsx +426 -0
  230. package/template/src/screens/clubs/BuyRaffleTicketsScreen.tsx +568 -0
  231. package/template/src/screens/clubs/ClubDeteils.tsx +497 -0
  232. package/template/src/screens/clubs/JoinClub.tsx +841 -0
  233. package/template/src/screens/events/EventScreen.tsx +460 -0
  234. package/template/src/screens/index.ts +42 -0
  235. package/template/src/screens/raffles/MyReferralMembersScreen.tsx +758 -0
  236. package/template/src/screens/raffles/RaffleDetailsScreen.tsx +762 -0
  237. package/template/src/screens/raffles/RafflesScreen.tsx +495 -0
  238. package/template/src/screens/raffles/SetRaffleReminderScreen.tsx +390 -0
  239. package/template/src/screens/teams/JoinTeamScreen.tsx +464 -0
  240. package/template/src/screens/teams/MyTeamDetailsScreen.tsx +979 -0
  241. package/template/src/screens/teams/MyTeamScreen.tsx +568 -0
  242. package/template/src/screens/teams/PendingRequestsScreen.tsx +426 -0
  243. package/template/src/screens/volunteerOpportunities/SetReminderScreen.tsx +631 -0
  244. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesDetailsScreen.tsx +1049 -0
  245. package/template/src/screens/volunteerOpportunities/VolunteerOpportunitiesScreen.tsx +608 -0
  246. package/template/src/services/api.ts +167 -0
  247. package/template/src/services/authService.ts +422 -0
  248. package/template/src/services/index.ts +5 -0
  249. package/template/src/services/mainServices.ts +1963 -0
  250. package/template/src/stores/authStore.ts +159 -0
  251. package/template/src/stores/index.ts +2 -0
  252. package/template/src/types/index.ts +85 -0
  253. package/template/src/types/navigation.ts +206 -0
  254. package/template/src/utils/AzureUploaderService.ts +371 -0
  255. package/template/src/utils/ClubSearchManager.ts +222 -0
  256. package/template/src/utils/NotificationManager.ts +503 -0
  257. package/template/src/utils/UploadDebugUtil.ts +107 -0
  258. package/template/src/utils/imagePicker.ts +321 -0
  259. package/template/src/utils/index.ts +111 -0
  260. package/template/src/utils/permissions.ts +277 -0
  261. package/template/src/utils/scaling.ts +14 -0
  262. package/template/src/utils/storage.ts +247 -0
  263. package/template/src/utils/usePermissions.ts +275 -0
  264. package/template/src/utils/validation.ts +340 -0
  265. package/template/tsconfig.json +50 -0
  266. package/template/types/svg.d.ts +6 -0
@@ -0,0 +1,14 @@
1
+ import { Dimensions } from "react-native";
2
+
3
+ export const { width, height } = Dimensions.get("screen");
4
+
5
+ // Guideline sizes are based on standard ~5" screen mobile device
6
+ const guidelineBaseWidth = 350;
7
+ const guidelineBaseHeight = 680;
8
+
9
+ const scale = (size: number) => (width / guidelineBaseWidth) * size;
10
+ const verticalScale = (size: number) => (height / guidelineBaseHeight) * size;
11
+ const moderateScale = (size: number, factor = 0.5) =>
12
+ size + (scale(size) - size) * factor;
13
+
14
+ export { moderateScale, scale, verticalScale };
@@ -0,0 +1,247 @@
1
+ import { MMKV } from 'react-native-mmkv';
2
+
3
+ // Create MMKV instances for different data types
4
+ const storage = new MMKV({
5
+ id: 'club-yakka-storage',
6
+ encryptionKey: 'club-yakka-encryption-key', // In production, use a secure key
7
+ });
8
+
9
+ const authStorage = new MMKV({
10
+ id: 'club-yakka-auth',
11
+ encryptionKey: 'club-yakka-auth-key', // In production, use a secure key
12
+ });
13
+
14
+ // Generic storage interface
15
+ interface StorageInterface {
16
+ setItem: (key: string, value: string) => void;
17
+ getItem: (key: string) => string | undefined;
18
+ removeItem: (key: string) => void;
19
+ getAllKeys: () => string[];
20
+ clear: () => void;
21
+ setObject: <T>(key: string, value: T) => void;
22
+ getObject: <T>(key: string) => T | undefined;
23
+ setBoolean: (key: string, value: boolean) => void;
24
+ getBoolean: (key: string) => boolean | undefined;
25
+ setNumber: (key: string, value: number) => void;
26
+ getNumber: (key: string) => number | undefined;
27
+ }
28
+
29
+ // Create storage utilities
30
+ const createStorageUtil = (mmkvInstance: MMKV): StorageInterface => ({
31
+ setItem: (key: string, value: string) => {
32
+ mmkvInstance.set(key, value);
33
+ },
34
+
35
+ getItem: (key: string) => {
36
+ return mmkvInstance.getString(key);
37
+ },
38
+
39
+ removeItem: (key: string) => {
40
+ mmkvInstance.delete(key);
41
+ },
42
+
43
+ getAllKeys: () => {
44
+ return mmkvInstance.getAllKeys();
45
+ },
46
+
47
+ clear: () => {
48
+ mmkvInstance.clearAll();
49
+ },
50
+
51
+ setObject: <T>(key: string, value: T) => {
52
+ try {
53
+ mmkvInstance.set(key, JSON.stringify(value));
54
+ } catch (error) {
55
+ console.error(`Error storing object for key ${key}:`, error);
56
+ }
57
+ },
58
+
59
+ getObject: <T>(key: string): T | undefined => {
60
+ try {
61
+ const value = mmkvInstance.getString(key);
62
+ return value ? JSON.parse(value) : undefined;
63
+ } catch (error) {
64
+ console.error(`Error parsing object for key ${key}:`, error);
65
+ return undefined;
66
+ }
67
+ },
68
+
69
+ setBoolean: (key: string, value: boolean) => {
70
+ mmkvInstance.set(key, value);
71
+ },
72
+
73
+ getBoolean: (key: string) => {
74
+ return mmkvInstance.getBoolean(key);
75
+ },
76
+
77
+ setNumber: (key: string, value: number) => {
78
+ mmkvInstance.set(key, value);
79
+ },
80
+
81
+ getNumber: (key: string) => {
82
+ return mmkvInstance.getNumber(key);
83
+ },
84
+ });
85
+
86
+ // Export storage instances
87
+ export const generalStorage = createStorageUtil(storage);
88
+ export const secureStorage = createStorageUtil(authStorage);
89
+
90
+ // Specific storage functions for common use cases
91
+ export const StorageService = {
92
+ // Authentication related storage
93
+ auth: {
94
+ setToken: (token: string) => secureStorage.setItem('user_token', token),
95
+ getToken: () => secureStorage.getItem('user_token'),
96
+ removeToken: () => secureStorage.removeItem('user_token'),
97
+
98
+ setAccessToken: (token: string) => {secureStorage.setItem('access_token', token);},
99
+ getAccessToken: () => {
100
+ const token = secureStorage.getItem('access_token')
101
+ return token;
102
+ },
103
+ removeAccessToken: () => secureStorage.removeItem('access_token'),
104
+ setAuthorizationToken: (token: string) => {
105
+ secureStorage.setItem('authorization_token', token);
106
+ },
107
+ getAuthorizationToken: () => {
108
+ const token = secureStorage.getItem('authorization_token');
109
+ return token;
110
+ },
111
+ removeAuthorizationToken: () => secureStorage.removeItem('authorization_token'),
112
+
113
+ setUser: (user: any) => secureStorage.setObject('user_data', user),
114
+ getUser: () => secureStorage.getObject('user_data'),
115
+ removeUser: () => secureStorage.removeItem('user_data'),
116
+
117
+ setTokens: (accessToken: string, authorizationToken: string) => {
118
+ secureStorage.setItem('access_token', accessToken);
119
+ secureStorage.setItem('authorization_token', authorizationToken);
120
+ },
121
+
122
+ getTokens: () => {
123
+ const accessToken = secureStorage.getItem('access_token');
124
+ const authorizationToken = secureStorage.getItem('authorization_token');
125
+
126
+ return {
127
+ accessToken,
128
+ authorizationToken,
129
+ };
130
+ },
131
+
132
+ clearAuthData: () => {
133
+ console.log("🧹 STORAGE - clearAuthData() called");
134
+ secureStorage.removeItem('user_token');
135
+ secureStorage.removeItem('access_token');
136
+ secureStorage.removeItem('authorization_token');
137
+ secureStorage.removeItem('user_data');
138
+ },
139
+ },
140
+
141
+ // App preferences
142
+ preferences: {
143
+ setTheme: (theme: 'light' | 'dark') => generalStorage.setItem('theme_preference', theme),
144
+ getTheme: () => generalStorage.getItem('theme_preference') as 'light' | 'dark' | undefined,
145
+
146
+ setLanguage: (language: string) => generalStorage.setItem('language_preference', language),
147
+ getLanguage: () => generalStorage.getItem('language_preference'),
148
+
149
+ setNotificationsEnabled: (enabled: boolean) => generalStorage.setBoolean('notifications_enabled', enabled),
150
+ getNotificationsEnabled: () => generalStorage.getBoolean('notifications_enabled') ?? true,
151
+
152
+ setBiometricEnabled: (enabled: boolean) => generalStorage.setBoolean('biometric_enabled', enabled),
153
+ getBiometricEnabled: () => generalStorage.getBoolean('biometric_enabled') ?? false,
154
+
155
+ // Welcome screen tracking
156
+ setWelcomeScreenShown: (shown: boolean) => generalStorage.setBoolean('welcome_screen_shown', shown),
157
+ getWelcomeScreenShown: () => generalStorage.getBoolean('welcome_screen_shown') ?? false,
158
+ },
159
+
160
+ // App data cache
161
+ cache: {
162
+ set: <T>(key: string, data: T, ttl?: number) => {
163
+ const cacheData = {
164
+ data,
165
+ timestamp: Date.now(),
166
+ ttl: ttl || 0,
167
+ };
168
+ generalStorage.setObject(`cache_${key}`, cacheData);
169
+ },
170
+
171
+ get: <T>(key: string): T | undefined => {
172
+ const cacheData = generalStorage.getObject<{
173
+ data: T;
174
+ timestamp: number;
175
+ ttl: number;
176
+ }>(`cache_${key}`);
177
+
178
+ if (!cacheData) return undefined;
179
+
180
+ // Check if cache has expired
181
+ if (cacheData.ttl > 0 && Date.now() - cacheData.timestamp > cacheData.ttl) {
182
+ generalStorage.removeItem(`cache_${key}`);
183
+ return undefined;
184
+ }
185
+
186
+ return cacheData.data;
187
+ },
188
+
189
+ remove: (key: string) => generalStorage.removeItem(`cache_${key}`),
190
+
191
+ clear: () => {
192
+ const keys = generalStorage.getAllKeys();
193
+ keys.forEach(key => {
194
+ if (key.startsWith('cache_')) {
195
+ generalStorage.removeItem(key);
196
+ }
197
+ });
198
+ },
199
+ },
200
+
201
+ // Development utilities
202
+ dev: {
203
+ logAllKeys: () => {
204
+ console.log('General Storage Keys:', generalStorage.getAllKeys());
205
+ console.log('Secure Storage Keys:', secureStorage.getAllKeys());
206
+ },
207
+
208
+ clearAll: () => {
209
+ generalStorage.clear();
210
+ secureStorage.clear();
211
+ console.log('All storage cleared');
212
+ },
213
+ },
214
+ };
215
+
216
+ // Hook for reactive storage updates (optional)
217
+ export class StorageListener {
218
+ private listeners: Map<string, ((value: any) => void)[]> = new Map();
219
+
220
+ subscribe<T>(key: string, callback: (value: T) => void): () => void {
221
+ if (!this.listeners.has(key)) {
222
+ this.listeners.set(key, []);
223
+ }
224
+
225
+ this.listeners.get(key)!.push(callback);
226
+
227
+ // Return unsubscribe function
228
+ return () => {
229
+ const callbacks = this.listeners.get(key);
230
+ if (callbacks) {
231
+ const index = callbacks.indexOf(callback);
232
+ if (index > -1) {
233
+ callbacks.splice(index, 1);
234
+ }
235
+ }
236
+ };
237
+ }
238
+
239
+ notify(key: string, value: any) {
240
+ const callbacks = this.listeners.get(key);
241
+ if (callbacks) {
242
+ callbacks.forEach(callback => callback(value));
243
+ }
244
+ }
245
+ }
246
+
247
+ export const storageListener = new StorageListener();
@@ -0,0 +1,275 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import {
3
+ PermissionType,
4
+ PermissionResult,
5
+ PermissionRequestResult,
6
+ requestPermission,
7
+ getPermissionStatus,
8
+ requestMultiplePermissions,
9
+ getMultiplePermissionStatuses,
10
+ PermissionGroups,
11
+ requestPermissionGroup,
12
+ isPermissionGroupGranted,
13
+ } from './permissions';
14
+
15
+ /**
16
+ * Hook for managing a single permission
17
+ */
18
+ export const usePermission = (permission: PermissionType) => {
19
+ const [status, setStatus] = useState<PermissionResult | null>(null);
20
+ const [isLoading, setIsLoading] = useState(true);
21
+
22
+ const checkStatus = useCallback(async () => {
23
+ try {
24
+ setIsLoading(true);
25
+ const result = await getPermissionStatus(permission);
26
+ setStatus(result);
27
+ } catch (error) {
28
+ console.error(`Error checking permission ${permission}:`, error);
29
+ setStatus({
30
+ status: 'denied',
31
+ canAskAgain: false,
32
+ });
33
+ } finally {
34
+ setIsLoading(false);
35
+ }
36
+ }, [permission]);
37
+
38
+ const request = useCallback(async (): Promise<PermissionRequestResult> => {
39
+ try {
40
+ setIsLoading(true);
41
+ const result = await requestPermission(permission);
42
+ setStatus({
43
+ status: result.status,
44
+ canAskAgain: result.canAskAgain,
45
+ expires: result.expires,
46
+ });
47
+ return result;
48
+ } catch (error) {
49
+ console.error(`Error requesting permission ${permission}:`, error);
50
+ const errorResult: PermissionRequestResult = {
51
+ granted: false,
52
+ status: 'denied',
53
+ canAskAgain: false,
54
+ };
55
+ setStatus({
56
+ status: 'denied',
57
+ canAskAgain: false,
58
+ });
59
+ return errorResult;
60
+ } finally {
61
+ setIsLoading(false);
62
+ }
63
+ }, [permission]);
64
+
65
+ useEffect(() => {
66
+ checkStatus();
67
+ }, [checkStatus]);
68
+
69
+ return {
70
+ status,
71
+ isLoading,
72
+ isGranted: status?.status === 'granted',
73
+ canAskAgain: status?.canAskAgain ?? false,
74
+ request,
75
+ refresh: checkStatus,
76
+ };
77
+ };
78
+
79
+ /**
80
+ * Hook for managing multiple permissions
81
+ */
82
+ export const usePermissions = (permissions: PermissionType[]) => {
83
+ const [statuses, setStatuses] = useState<Record<PermissionType, PermissionResult> | null>(null);
84
+ const [isLoading, setIsLoading] = useState(true);
85
+
86
+ const checkStatuses = useCallback(async () => {
87
+ try {
88
+ setIsLoading(true);
89
+ const results = await getMultiplePermissionStatuses(permissions);
90
+ setStatuses(results);
91
+ } catch (error) {
92
+ console.error('Error checking permissions:', error);
93
+ const errorResults: Record<PermissionType, PermissionResult> = {} as any;
94
+ permissions.forEach(permission => {
95
+ errorResults[permission] = {
96
+ status: 'denied',
97
+ canAskAgain: false,
98
+ };
99
+ });
100
+ setStatuses(errorResults);
101
+ } finally {
102
+ setIsLoading(false);
103
+ }
104
+ }, [permissions]);
105
+
106
+ const request = useCallback(async (): Promise<Record<PermissionType, PermissionRequestResult>> => {
107
+ try {
108
+ setIsLoading(true);
109
+ const results = await requestMultiplePermissions(permissions);
110
+ const statusResults: Record<PermissionType, PermissionResult> = {} as any;
111
+
112
+ permissions.forEach(permission => {
113
+ const result = results[permission];
114
+ statusResults[permission] = {
115
+ status: result.status,
116
+ canAskAgain: result.canAskAgain,
117
+ expires: result.expires,
118
+ };
119
+ });
120
+
121
+ setStatuses(statusResults);
122
+ return results;
123
+ } catch (error) {
124
+ console.error('Error requesting permissions:', error);
125
+ const errorResults: Record<PermissionType, PermissionRequestResult> = {} as any;
126
+ const errorStatuses: Record<PermissionType, PermissionResult> = {} as any;
127
+
128
+ permissions.forEach(permission => {
129
+ errorResults[permission] = {
130
+ granted: false,
131
+ status: 'denied',
132
+ canAskAgain: false,
133
+ };
134
+ errorStatuses[permission] = {
135
+ status: 'denied',
136
+ canAskAgain: false,
137
+ };
138
+ });
139
+
140
+ setStatuses(errorStatuses);
141
+ return errorResults;
142
+ } finally {
143
+ setIsLoading(false);
144
+ }
145
+ }, [permissions]);
146
+
147
+ useEffect(() => {
148
+ checkStatuses();
149
+ }, [checkStatuses]);
150
+
151
+ const isGranted = useCallback((permission: PermissionType): boolean => {
152
+ return statuses?.[permission]?.status === 'granted' ?? false;
153
+ }, [statuses]);
154
+
155
+ const canAskAgain = useCallback((permission: PermissionType): boolean => {
156
+ return statuses?.[permission]?.canAskAgain ?? false;
157
+ }, [statuses]);
158
+
159
+ const allGranted = useCallback((): boolean => {
160
+ if (!statuses) return false;
161
+ return permissions.every(permission => statuses[permission]?.status === 'granted');
162
+ }, [statuses, permissions]);
163
+
164
+ const anyGranted = useCallback((): boolean => {
165
+ if (!statuses) return false;
166
+ return permissions.some(permission => statuses[permission]?.status === 'granted');
167
+ }, [statuses, permissions]);
168
+
169
+ return {
170
+ statuses,
171
+ isLoading,
172
+ isGranted,
173
+ canAskAgain,
174
+ allGranted,
175
+ anyGranted,
176
+ request,
177
+ refresh: checkStatuses,
178
+ };
179
+ };
180
+
181
+ /**
182
+ * Hook for managing permission groups
183
+ */
184
+ export const usePermissionGroup = (group: keyof typeof PermissionGroups) => {
185
+ const permissions = PermissionGroups[group];
186
+ const permissionHook = usePermissions(permissions);
187
+
188
+ const requestGroup = useCallback(async (): Promise<Record<PermissionType, PermissionRequestResult>> => {
189
+ try {
190
+ permissionHook.isLoading = true;
191
+ const results = await requestPermissionGroup(group);
192
+ const statusResults: Record<PermissionType, PermissionResult> = {} as any;
193
+
194
+ permissions.forEach(permission => {
195
+ const result = results[permission];
196
+ statusResults[permission] = {
197
+ status: result.status,
198
+ canAskAgain: result.canAskAgain,
199
+ expires: result.expires,
200
+ };
201
+ });
202
+
203
+ permissionHook.setStatuses?.(statusResults);
204
+ return results;
205
+ } catch (error) {
206
+ console.error(`Error requesting permission group ${group}:`, error);
207
+ const errorResults: Record<PermissionType, PermissionRequestResult> = {} as any;
208
+ const errorStatuses: Record<PermissionType, PermissionResult> = {} as any;
209
+
210
+ permissions.forEach(permission => {
211
+ errorResults[permission] = {
212
+ granted: false,
213
+ status: 'denied',
214
+ canAskAgain: false,
215
+ };
216
+ errorStatuses[permission] = {
217
+ status: 'denied',
218
+ canAskAgain: false,
219
+ };
220
+ });
221
+
222
+ permissionHook.setStatuses?.(errorStatuses);
223
+ return errorResults;
224
+ } finally {
225
+ permissionHook.isLoading = false;
226
+ }
227
+ }, [group, permissions, permissionHook]);
228
+
229
+ const isGroupGranted = useCallback(async (): Promise<boolean> => {
230
+ return isPermissionGroupGranted(group);
231
+ }, [group]);
232
+
233
+ return {
234
+ ...permissionHook,
235
+ requestGroup,
236
+ isGroupGranted,
237
+ groupName: group,
238
+ permissions,
239
+ };
240
+ };
241
+
242
+ /**
243
+ * Hook for camera permissions specifically
244
+ */
245
+ export const useCameraPermissions = () => {
246
+ return usePermissionGroup('camera');
247
+ };
248
+
249
+ /**
250
+ * Hook for location permissions specifically
251
+ */
252
+ export const useLocationPermissions = () => {
253
+ return usePermissionGroup('location');
254
+ };
255
+
256
+ /**
257
+ * Hook for media permissions (camera, camera roll, audio recording)
258
+ */
259
+ export const useMediaPermissions = () => {
260
+ return usePermissionGroup('media');
261
+ };
262
+
263
+ /**
264
+ * Hook for contacts permissions specifically
265
+ */
266
+ export const useContactsPermissions = () => {
267
+ return usePermissionGroup('contacts');
268
+ };
269
+
270
+ /**
271
+ * Hook for calendar permissions specifically
272
+ */
273
+ export const useCalendarPermissions = () => {
274
+ return usePermissionGroup('calendar');
275
+ };