react-native-ensys-camera-x 1.0.7

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 (506) hide show
  1. package/CustomCamera.podspec +20 -0
  2. package/LICENSE +20 -0
  3. package/README.md +833 -0
  4. package/android/build.gradle +135 -0
  5. package/android/consumer-rules.pro +47 -0
  6. package/android/src/main/AndroidManifest.xml +72 -0
  7. package/android/src/main/java/android/print/PdfPrint.java +51 -0
  8. package/android/src/main/java/com/customcamera/AnimatedImageViewManager.kt +199 -0
  9. package/android/src/main/java/com/customcamera/AudioPlayerView.kt +322 -0
  10. package/android/src/main/java/com/customcamera/AudioRecorder.kt +506 -0
  11. package/android/src/main/java/com/customcamera/BarcodeScannerActivity.kt +361 -0
  12. package/android/src/main/java/com/customcamera/BlurBackgroundView.kt +199 -0
  13. package/android/src/main/java/com/customcamera/CacheCleanupManager.kt +386 -0
  14. package/android/src/main/java/com/customcamera/CameraAspectRatioMode.kt +77 -0
  15. package/android/src/main/java/com/customcamera/CameraAsset.kt +211 -0
  16. package/android/src/main/java/com/customcamera/CameraTheme.kt +479 -0
  17. package/android/src/main/java/com/customcamera/CompressionCacheStore.kt +504 -0
  18. package/android/src/main/java/com/customcamera/CompressionFileNameUtils.kt +7 -0
  19. package/android/src/main/java/com/customcamera/CompressionProfile.kt +195 -0
  20. package/android/src/main/java/com/customcamera/CustomCameraActivity.kt +7291 -0
  21. package/android/src/main/java/com/customcamera/CustomCameraFileProvider.kt +9 -0
  22. package/android/src/main/java/com/customcamera/CustomCameraModule.kt +2479 -0
  23. package/android/src/main/java/com/customcamera/CustomCameraPackage.kt +53 -0
  24. package/android/src/main/java/com/customcamera/DisplayUtils.kt +9 -0
  25. package/android/src/main/java/com/customcamera/DocumentPreviewView.kt +846 -0
  26. package/android/src/main/java/com/customcamera/DrawingView.kt +214 -0
  27. package/android/src/main/java/com/customcamera/EmojiPickerData.kt +228 -0
  28. package/android/src/main/java/com/customcamera/FilterStripAdapter.kt +158 -0
  29. package/android/src/main/java/com/customcamera/GifSupport.kt +215 -0
  30. package/android/src/main/java/com/customcamera/GlobalAudioPlayer.kt +320 -0
  31. package/android/src/main/java/com/customcamera/ImageExporter.kt +1394 -0
  32. package/android/src/main/java/com/customcamera/ImageFormatSupport.kt +163 -0
  33. package/android/src/main/java/com/customcamera/Localization.kt +206 -0
  34. package/android/src/main/java/com/customcamera/MediaAdapters.kt +758 -0
  35. package/android/src/main/java/com/customcamera/MediaCacheManager.kt +782 -0
  36. package/android/src/main/java/com/customcamera/MediaExportFormats.kt +201 -0
  37. package/android/src/main/java/com/customcamera/MediaFileIo.kt +310 -0
  38. package/android/src/main/java/com/customcamera/MediaMetadataStore.kt +494 -0
  39. package/android/src/main/java/com/customcamera/MediaPreviewEditor.kt +14865 -0
  40. package/android/src/main/java/com/customcamera/MediaPublisher.kt +423 -0
  41. package/android/src/main/java/com/customcamera/MediaStorageWorkflow.kt +722 -0
  42. package/android/src/main/java/com/customcamera/MediaStoreRepository.kt +378 -0
  43. package/android/src/main/java/com/customcamera/MediaThumbnailView.kt +286 -0
  44. package/android/src/main/java/com/customcamera/MediaUtils.kt +37 -0
  45. package/android/src/main/java/com/customcamera/NativeVideoViewManager.kt +845 -0
  46. package/android/src/main/java/com/customcamera/OfficeDocumentConverter.kt +2791 -0
  47. package/android/src/main/java/com/customcamera/PendingCaptureCrops.kt +88 -0
  48. package/android/src/main/java/com/customcamera/PowerPointPreview.kt +4077 -0
  49. package/android/src/main/java/com/customcamera/RecentPickerStore.kt +74 -0
  50. package/android/src/main/java/com/customcamera/SecureFileEraser.kt +411 -0
  51. package/android/src/main/java/com/customcamera/SecureKeyModule.kt +88 -0
  52. package/android/src/main/java/com/customcamera/SecureMediaDeleter.kt +493 -0
  53. package/android/src/main/java/com/customcamera/StickerPickerData.kt +107 -0
  54. package/android/src/main/java/com/customcamera/SvgDrawable.kt +175 -0
  55. package/android/src/main/java/com/customcamera/SvgIconViewManager.kt +77 -0
  56. package/android/src/main/java/com/customcamera/TextEntryController.kt +553 -0
  57. package/android/src/main/java/com/customcamera/ThumbnailLoader.kt +455 -0
  58. package/android/src/main/java/com/customcamera/UploadService.kt +909 -0
  59. package/android/src/main/java/com/customcamera/VideoEditUtils.kt +210 -0
  60. package/android/src/main/java/com/customcamera/VideoRotationTranscoder.kt +1992 -0
  61. package/android/src/main/java/com/customcamera/gif/AnimatedGifEncoder.kt +473 -0
  62. package/android/src/main/java/com/customcamera/gif/GifDecoder.kt +690 -0
  63. package/android/src/main/java/com/customcamera/gif/GifFramesDrawable.kt +160 -0
  64. package/android/src/main/java/com/customcamera/gif/GifHttp.kt +112 -0
  65. package/android/src/main/java/com/customcamera/gif/GifImageLoader.kt +186 -0
  66. package/android/src/main/java/com/customcamera/gif/GifModels.kt +74 -0
  67. package/android/src/main/java/com/customcamera/gif/GifProvider.kt +49 -0
  68. package/android/src/main/java/com/customcamera/gif/GifProviders.kt +27 -0
  69. package/android/src/main/java/com/customcamera/gif/GifRepository.kt +124 -0
  70. package/android/src/main/java/com/customcamera/gif/GifSafety.kt +33 -0
  71. package/android/src/main/java/com/customcamera/gif/GiphyGifProvider.kt +146 -0
  72. package/android/src/main/java/com/customcamera/gif/LZWEncoder.kt +258 -0
  73. package/android/src/main/java/com/customcamera/gif/NeuQuant.kt +435 -0
  74. package/android/src/main/java/com/customcamera/gif/TenorGifProvider.kt +147 -0
  75. package/android/src/main/res/drawable/bg_brush_selected.xml +5 -0
  76. package/android/src/main/res/drawable/bg_color_swatch.xml +5 -0
  77. package/android/src/main/res/drawable/bg_editor_toolbar.xml +6 -0
  78. package/android/src/main/res/drawable/bg_icon_circle.xml +5 -0
  79. package/android/src/main/res/drawable/bg_icon_circle_light.xml +5 -0
  80. package/android/src/main/res/drawable/bg_mode_tab_active.xml +6 -0
  81. package/android/src/main/res/drawable/bg_pill.xml +6 -0
  82. package/android/src/main/res/drawable/bg_recording_dot.xml +6 -0
  83. package/android/src/main/res/drawable/bg_selection_badge.xml +8 -0
  84. package/android/src/main/res/drawable/bg_send_button.xml +5 -0
  85. package/android/src/main/res/drawable/bg_shutter_inner.xml +5 -0
  86. package/android/src/main/res/drawable/bg_shutter_recording.xml +6 -0
  87. package/android/src/main/res/drawable/bg_shutter_ring.xml +8 -0
  88. package/android/src/main/res/drawable/bg_shutter_video_idle.xml +5 -0
  89. package/android/src/main/res/drawable/bg_thumbnail.xml +9 -0
  90. package/android/src/main/res/drawable/ic_aspect_ratio.xml +17 -0
  91. package/android/src/main/res/drawable/ic_audio.xml +10 -0
  92. package/android/src/main/res/drawable/ic_back.xml +10 -0
  93. package/android/src/main/res/drawable/ic_brush_medium.xml +12 -0
  94. package/android/src/main/res/drawable/ic_brush_thick.xml +12 -0
  95. package/android/src/main/res/drawable/ic_brush_thin.xml +12 -0
  96. package/android/src/main/res/drawable/ic_check.xml +17 -0
  97. package/android/src/main/res/drawable/ic_chevron_down.xml +10 -0
  98. package/android/src/main/res/drawable/ic_chevron_up.xml +13 -0
  99. package/android/src/main/res/drawable/ic_clear_drawing.xml +10 -0
  100. package/android/src/main/res/drawable/ic_close.xml +10 -0
  101. package/android/src/main/res/drawable/ic_cover.xml +9 -0
  102. package/android/src/main/res/drawable/ic_crop.xml +10 -0
  103. package/android/src/main/res/drawable/ic_delete.xml +9 -0
  104. package/android/src/main/res/drawable/ic_document.xml +10 -0
  105. package/android/src/main/res/drawable/ic_done.xml +10 -0
  106. package/android/src/main/res/drawable/ic_download.xml +10 -0
  107. package/android/src/main/res/drawable/ic_emoji.xml +10 -0
  108. package/android/src/main/res/drawable/ic_filter.xml +10 -0
  109. package/android/src/main/res/drawable/ic_flash_auto.xml +7 -0
  110. package/android/src/main/res/drawable/ic_flash_off.xml +23 -0
  111. package/android/src/main/res/drawable/ic_flash_on.xml +16 -0
  112. package/android/src/main/res/drawable/ic_flip.xml +15 -0
  113. package/android/src/main/res/drawable/ic_gallery.xml +10 -0
  114. package/android/src/main/res/drawable/ic_gif.xml +24 -0
  115. package/android/src/main/res/drawable/ic_lock.xml +19 -0
  116. package/android/src/main/res/drawable/ic_lock_open.xml +22 -0
  117. package/android/src/main/res/drawable/ic_marker.xml +10 -0
  118. package/android/src/main/res/drawable/ic_more_vert.xml +18 -0
  119. package/android/src/main/res/drawable/ic_overlay_close.xml +19 -0
  120. package/android/src/main/res/drawable/ic_overlay_resize.xml +18 -0
  121. package/android/src/main/res/drawable/ic_pause.xml +10 -0
  122. package/android/src/main/res/drawable/ic_photo_mode.xml +10 -0
  123. package/android/src/main/res/drawable/ic_play.xml +10 -0
  124. package/android/src/main/res/drawable/ic_redo.xml +10 -0
  125. package/android/src/main/res/drawable/ic_rotate.xml +9 -0
  126. package/android/src/main/res/drawable/ic_send.xml +10 -0
  127. package/android/src/main/res/drawable/ic_share.xml +10 -0
  128. package/android/src/main/res/drawable/ic_stat_upload.xml +10 -0
  129. package/android/src/main/res/drawable/ic_sticker.xml +24 -0
  130. package/android/src/main/res/drawable/ic_text.xml +10 -0
  131. package/android/src/main/res/drawable/ic_text_align_center.xml +11 -0
  132. package/android/src/main/res/drawable/ic_text_align_left.xml +11 -0
  133. package/android/src/main/res/drawable/ic_text_align_right.xml +11 -0
  134. package/android/src/main/res/drawable/ic_text_bg.xml +11 -0
  135. package/android/src/main/res/drawable/ic_trim.xml +23 -0
  136. package/android/src/main/res/drawable/ic_undo.xml +10 -0
  137. package/android/src/main/res/drawable/ic_video_mode.xml +10 -0
  138. package/android/src/main/res/drawable/ic_video_note.xml +13 -0
  139. package/android/src/main/res/drawable/ic_volume_off.xml +9 -0
  140. package/android/src/main/res/drawable/ic_volume_on.xml +9 -0
  141. package/android/src/main/res/drawable/sticker_heart.xml +9 -0
  142. package/android/src/main/res/drawable/sticker_smile.xml +9 -0
  143. package/android/src/main/res/drawable/sticker_star.xml +9 -0
  144. package/android/src/main/res/drawable/sticker_thumbsup.xml +9 -0
  145. package/android/src/main/res/values/colors.xml +34 -0
  146. package/android/src/main/res/values/ids.xml +15 -0
  147. package/android/src/main/res/values/strings.xml +15 -0
  148. package/android/src/main/res/values/styles.xml +20 -0
  149. package/android/src/main/res/xml/file_paths.xml +34 -0
  150. package/ios/CustomCamera.h +5 -0
  151. package/ios/CustomCamera.mm +214 -0
  152. package/lib/module/AudioPlayerContext.js +233 -0
  153. package/lib/module/AudioPlayerContext.js.map +1 -0
  154. package/lib/module/CameraPreview.js +304 -0
  155. package/lib/module/CameraPreview.js.map +1 -0
  156. package/lib/module/NativeAnimatedImageView.js +41 -0
  157. package/lib/module/NativeAnimatedImageView.js.map +1 -0
  158. package/lib/module/NativeAudioPlayerView.js +33 -0
  159. package/lib/module/NativeAudioPlayerView.js.map +1 -0
  160. package/lib/module/NativeBlurView.js +35 -0
  161. package/lib/module/NativeBlurView.js.map +1 -0
  162. package/lib/module/NativeCustomCamera.js +128 -0
  163. package/lib/module/NativeCustomCamera.js.map +1 -0
  164. package/lib/module/NativeCustomCamera.web.js +143 -0
  165. package/lib/module/NativeCustomCamera.web.js.map +1 -0
  166. package/lib/module/NativeCustomVideoView.js +5 -0
  167. package/lib/module/NativeCustomVideoView.js.map +1 -0
  168. package/lib/module/NativeDocumentPreviewView.js +156 -0
  169. package/lib/module/NativeDocumentPreviewView.js.map +1 -0
  170. package/lib/module/NativeMediaThumbnailView.js +110 -0
  171. package/lib/module/NativeMediaThumbnailView.js.map +1 -0
  172. package/lib/module/NativeSvgIcon.js +32 -0
  173. package/lib/module/NativeSvgIcon.js.map +1 -0
  174. package/lib/module/ResponsivePreviewContainer.js +171 -0
  175. package/lib/module/ResponsivePreviewContainer.js.map +1 -0
  176. package/lib/module/accessibility.js +61 -0
  177. package/lib/module/accessibility.js.map +1 -0
  178. package/lib/module/config.js +352 -0
  179. package/lib/module/config.js.map +1 -0
  180. package/lib/module/cpuOptimization.js +296 -0
  181. package/lib/module/cpuOptimization.js.map +1 -0
  182. package/lib/module/db/DatabaseManager.js +191 -0
  183. package/lib/module/db/DatabaseManager.js.map +1 -0
  184. package/lib/module/db/MediaMapper.js +284 -0
  185. package/lib/module/db/MediaMapper.js.map +1 -0
  186. package/lib/module/db/MediaRepository.js +242 -0
  187. package/lib/module/db/MediaRepository.js.map +1 -0
  188. package/lib/module/db/index.js +41 -0
  189. package/lib/module/db/index.js.map +1 -0
  190. package/lib/module/db/migrations.js +180 -0
  191. package/lib/module/db/migrations.js.map +1 -0
  192. package/lib/module/db/react-native-sqlcipher.d.js +2 -0
  193. package/lib/module/db/react-native-sqlcipher.d.js.map +1 -0
  194. package/lib/module/db/secureKey.js +87 -0
  195. package/lib/module/db/secureKey.js.map +1 -0
  196. package/lib/module/db/types.js +57 -0
  197. package/lib/module/db/types.js.map +1 -0
  198. package/lib/module/db/useMediaDatabase.js +123 -0
  199. package/lib/module/db/useMediaDatabase.js.map +1 -0
  200. package/lib/module/defaultIcons.js +2259 -0
  201. package/lib/module/defaultIcons.js.map +1 -0
  202. package/lib/module/deviceCapabilities.js +408 -0
  203. package/lib/module/deviceCapabilities.js.map +1 -0
  204. package/lib/module/errors.js +267 -0
  205. package/lib/module/errors.js.map +1 -0
  206. package/lib/module/iconConfig.js +796 -0
  207. package/lib/module/iconConfig.js.map +1 -0
  208. package/lib/module/icons.js +514 -0
  209. package/lib/module/icons.js.map +1 -0
  210. package/lib/module/index.js +251 -0
  211. package/lib/module/index.js.map +1 -0
  212. package/lib/module/jest-globals.d.js +2 -0
  213. package/lib/module/jest-globals.d.js.map +1 -0
  214. package/lib/module/library/MediaLibrary.js +107 -0
  215. package/lib/module/library/MediaLibrary.js.map +1 -0
  216. package/lib/module/library/MediaLibraryScreen.js +2597 -0
  217. package/lib/module/library/MediaLibraryScreen.js.map +1 -0
  218. package/lib/module/library/components/AudioPreview.js +74 -0
  219. package/lib/module/library/components/AudioPreview.js.map +1 -0
  220. package/lib/module/library/components/DocumentPreview.js +331 -0
  221. package/lib/module/library/components/DocumentPreview.js.map +1 -0
  222. package/lib/module/library/components/ExpandableFab.js +343 -0
  223. package/lib/module/library/components/ExpandableFab.js.map +1 -0
  224. package/lib/module/library/components/FileTiles.js +251 -0
  225. package/lib/module/library/components/FileTiles.js.map +1 -0
  226. package/lib/module/library/components/ImagePreview.js +70 -0
  227. package/lib/module/library/components/ImagePreview.js.map +1 -0
  228. package/lib/module/library/components/MediaMetadataHeader.js +175 -0
  229. package/lib/module/library/components/MediaMetadataHeader.js.map +1 -0
  230. package/lib/module/library/components/RecordAudioScreen.js +816 -0
  231. package/lib/module/library/components/RecordAudioScreen.js.map +1 -0
  232. package/lib/module/library/components/VideoPreview.js +453 -0
  233. package/lib/module/library/components/VideoPreview.js.map +1 -0
  234. package/lib/module/library/components/ViewerCounter.js +55 -0
  235. package/lib/module/library/components/ViewerCounter.js.map +1 -0
  236. package/lib/module/library/compressionEstimate.js +507 -0
  237. package/lib/module/library/compressionEstimate.js.map +1 -0
  238. package/lib/module/library/fileMetadata.js +196 -0
  239. package/lib/module/library/fileMetadata.js.map +1 -0
  240. package/lib/module/library/index.js +42 -0
  241. package/lib/module/library/index.js.map +1 -0
  242. package/lib/module/library/libraryIconRegistry.js +69 -0
  243. package/lib/module/library/libraryIconRegistry.js.map +1 -0
  244. package/lib/module/library/libraryIcons.js +858 -0
  245. package/lib/module/library/libraryIcons.js.map +1 -0
  246. package/lib/module/library/localizedFormat.js +181 -0
  247. package/lib/module/library/localizedFormat.js.map +1 -0
  248. package/lib/module/library/palette.js +225 -0
  249. package/lib/module/library/palette.js.map +1 -0
  250. package/lib/module/library/responsive.js +53 -0
  251. package/lib/module/library/responsive.js.map +1 -0
  252. package/lib/module/locales.js +416 -0
  253. package/lib/module/locales.js.map +1 -0
  254. package/lib/module/localization.js +1064 -0
  255. package/lib/module/localization.js.map +1 -0
  256. package/lib/module/logger.js +20 -0
  257. package/lib/module/logger.js.map +1 -0
  258. package/lib/module/lowMemoryCache.js +206 -0
  259. package/lib/module/lowMemoryCache.js.map +1 -0
  260. package/lib/module/mediaHistory.js +33 -0
  261. package/lib/module/mediaHistory.js.map +1 -0
  262. package/lib/module/mediaStorageService.js +402 -0
  263. package/lib/module/mediaStorageService.js.map +1 -0
  264. package/lib/module/memory.js +79 -0
  265. package/lib/module/memory.js.map +1 -0
  266. package/lib/module/nativeActions.js +307 -0
  267. package/lib/module/nativeActions.js.map +1 -0
  268. package/lib/module/nativeComponentSupport.js +61 -0
  269. package/lib/module/nativeComponentSupport.js.map +1 -0
  270. package/lib/module/networkPerformance.js +24 -0
  271. package/lib/module/networkPerformance.js.map +1 -0
  272. package/lib/module/package.json +1 -0
  273. package/lib/module/performance.js +104 -0
  274. package/lib/module/performance.js.map +1 -0
  275. package/lib/module/performanceMonitor.js +155 -0
  276. package/lib/module/performanceMonitor.js.map +1 -0
  277. package/lib/module/permissions.js +370 -0
  278. package/lib/module/permissions.js.map +1 -0
  279. package/lib/module/rendering.js +40 -0
  280. package/lib/module/rendering.js.map +1 -0
  281. package/lib/module/security.js +18 -0
  282. package/lib/module/security.js.map +1 -0
  283. package/lib/module/state.js +266 -0
  284. package/lib/module/state.js.map +1 -0
  285. package/lib/module/storage.js +400 -0
  286. package/lib/module/storage.js.map +1 -0
  287. package/lib/module/theme.js +390 -0
  288. package/lib/module/theme.js.map +1 -0
  289. package/lib/module/types.js +4 -0
  290. package/lib/module/types.js.map +1 -0
  291. package/lib/module/utils.js +115 -0
  292. package/lib/module/utils.js.map +1 -0
  293. package/lib/module/validation.js +288 -0
  294. package/lib/module/validation.js.map +1 -0
  295. package/lib/typescript/package.json +1 -0
  296. package/lib/typescript/src/AudioPlayerContext.d.ts +27 -0
  297. package/lib/typescript/src/AudioPlayerContext.d.ts.map +1 -0
  298. package/lib/typescript/src/CameraPreview.d.ts +13 -0
  299. package/lib/typescript/src/CameraPreview.d.ts.map +1 -0
  300. package/lib/typescript/src/NativeAnimatedImageView.d.ts +33 -0
  301. package/lib/typescript/src/NativeAnimatedImageView.d.ts.map +1 -0
  302. package/lib/typescript/src/NativeAudioPlayerView.d.ts +12 -0
  303. package/lib/typescript/src/NativeAudioPlayerView.d.ts.map +1 -0
  304. package/lib/typescript/src/NativeBlurView.d.ts +12 -0
  305. package/lib/typescript/src/NativeBlurView.d.ts.map +1 -0
  306. package/lib/typescript/src/NativeCustomCamera.d.ts +167 -0
  307. package/lib/typescript/src/NativeCustomCamera.d.ts.map +1 -0
  308. package/lib/typescript/src/NativeCustomCamera.web.d.ts +47 -0
  309. package/lib/typescript/src/NativeCustomCamera.web.d.ts.map +1 -0
  310. package/lib/typescript/src/NativeCustomVideoView.d.ts +30 -0
  311. package/lib/typescript/src/NativeCustomVideoView.d.ts.map +1 -0
  312. package/lib/typescript/src/NativeDocumentPreviewView.d.ts +48 -0
  313. package/lib/typescript/src/NativeDocumentPreviewView.d.ts.map +1 -0
  314. package/lib/typescript/src/NativeMediaThumbnailView.d.ts +54 -0
  315. package/lib/typescript/src/NativeMediaThumbnailView.d.ts.map +1 -0
  316. package/lib/typescript/src/NativeSvgIcon.d.ts +25 -0
  317. package/lib/typescript/src/NativeSvgIcon.d.ts.map +1 -0
  318. package/lib/typescript/src/ResponsivePreviewContainer.d.ts +92 -0
  319. package/lib/typescript/src/ResponsivePreviewContainer.d.ts.map +1 -0
  320. package/lib/typescript/src/accessibility.d.ts +20 -0
  321. package/lib/typescript/src/accessibility.d.ts.map +1 -0
  322. package/lib/typescript/src/config.d.ts +145 -0
  323. package/lib/typescript/src/config.d.ts.map +1 -0
  324. package/lib/typescript/src/cpuOptimization.d.ts +63 -0
  325. package/lib/typescript/src/cpuOptimization.d.ts.map +1 -0
  326. package/lib/typescript/src/db/DatabaseManager.d.ts +48 -0
  327. package/lib/typescript/src/db/DatabaseManager.d.ts.map +1 -0
  328. package/lib/typescript/src/db/MediaMapper.d.ts +77 -0
  329. package/lib/typescript/src/db/MediaMapper.d.ts.map +1 -0
  330. package/lib/typescript/src/db/MediaRepository.d.ts +66 -0
  331. package/lib/typescript/src/db/MediaRepository.d.ts.map +1 -0
  332. package/lib/typescript/src/db/index.d.ts +23 -0
  333. package/lib/typescript/src/db/index.d.ts.map +1 -0
  334. package/lib/typescript/src/db/migrations.d.ts +31 -0
  335. package/lib/typescript/src/db/migrations.d.ts.map +1 -0
  336. package/lib/typescript/src/db/secureKey.d.ts +10 -0
  337. package/lib/typescript/src/db/secureKey.d.ts.map +1 -0
  338. package/lib/typescript/src/db/types.d.ts +115 -0
  339. package/lib/typescript/src/db/types.d.ts.map +1 -0
  340. package/lib/typescript/src/db/useMediaDatabase.d.ts +41 -0
  341. package/lib/typescript/src/db/useMediaDatabase.d.ts.map +1 -0
  342. package/lib/typescript/src/defaultIcons.d.ts +139 -0
  343. package/lib/typescript/src/defaultIcons.d.ts.map +1 -0
  344. package/lib/typescript/src/deviceCapabilities.d.ts +92 -0
  345. package/lib/typescript/src/deviceCapabilities.d.ts.map +1 -0
  346. package/lib/typescript/src/errors.d.ts +95 -0
  347. package/lib/typescript/src/errors.d.ts.map +1 -0
  348. package/lib/typescript/src/iconConfig.d.ts +176 -0
  349. package/lib/typescript/src/iconConfig.d.ts.map +1 -0
  350. package/lib/typescript/src/icons.d.ts +217 -0
  351. package/lib/typescript/src/icons.d.ts.map +1 -0
  352. package/lib/typescript/src/index.d.ts +104 -0
  353. package/lib/typescript/src/index.d.ts.map +1 -0
  354. package/lib/typescript/src/library/MediaLibrary.d.ts +57 -0
  355. package/lib/typescript/src/library/MediaLibrary.d.ts.map +1 -0
  356. package/lib/typescript/src/library/MediaLibraryScreen.d.ts +51 -0
  357. package/lib/typescript/src/library/MediaLibraryScreen.d.ts.map +1 -0
  358. package/lib/typescript/src/library/components/AudioPreview.d.ts +6 -0
  359. package/lib/typescript/src/library/components/AudioPreview.d.ts.map +1 -0
  360. package/lib/typescript/src/library/components/DocumentPreview.d.ts +10 -0
  361. package/lib/typescript/src/library/components/DocumentPreview.d.ts.map +1 -0
  362. package/lib/typescript/src/library/components/ExpandableFab.d.ts +39 -0
  363. package/lib/typescript/src/library/components/ExpandableFab.d.ts.map +1 -0
  364. package/lib/typescript/src/library/components/FileTiles.d.ts +8 -0
  365. package/lib/typescript/src/library/components/FileTiles.d.ts.map +1 -0
  366. package/lib/typescript/src/library/components/ImagePreview.d.ts +5 -0
  367. package/lib/typescript/src/library/components/ImagePreview.d.ts.map +1 -0
  368. package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts +16 -0
  369. package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts.map +1 -0
  370. package/lib/typescript/src/library/components/RecordAudioScreen.d.ts +8 -0
  371. package/lib/typescript/src/library/components/RecordAudioScreen.d.ts.map +1 -0
  372. package/lib/typescript/src/library/components/VideoPreview.d.ts +20 -0
  373. package/lib/typescript/src/library/components/VideoPreview.d.ts.map +1 -0
  374. package/lib/typescript/src/library/components/ViewerCounter.d.ts +13 -0
  375. package/lib/typescript/src/library/components/ViewerCounter.d.ts.map +1 -0
  376. package/lib/typescript/src/library/compressionEstimate.d.ts +313 -0
  377. package/lib/typescript/src/library/compressionEstimate.d.ts.map +1 -0
  378. package/lib/typescript/src/library/fileMetadata.d.ts +33 -0
  379. package/lib/typescript/src/library/fileMetadata.d.ts.map +1 -0
  380. package/lib/typescript/src/library/index.d.ts +40 -0
  381. package/lib/typescript/src/library/index.d.ts.map +1 -0
  382. package/lib/typescript/src/library/libraryIconRegistry.d.ts +35 -0
  383. package/lib/typescript/src/library/libraryIconRegistry.d.ts.map +1 -0
  384. package/lib/typescript/src/library/libraryIcons.d.ts +85 -0
  385. package/lib/typescript/src/library/libraryIcons.d.ts.map +1 -0
  386. package/lib/typescript/src/library/localizedFormat.d.ts +49 -0
  387. package/lib/typescript/src/library/localizedFormat.d.ts.map +1 -0
  388. package/lib/typescript/src/library/palette.d.ts +104 -0
  389. package/lib/typescript/src/library/palette.d.ts.map +1 -0
  390. package/lib/typescript/src/library/responsive.d.ts +15 -0
  391. package/lib/typescript/src/library/responsive.d.ts.map +1 -0
  392. package/lib/typescript/src/locales.d.ts +103 -0
  393. package/lib/typescript/src/locales.d.ts.map +1 -0
  394. package/lib/typescript/src/localization.d.ts +1051 -0
  395. package/lib/typescript/src/localization.d.ts.map +1 -0
  396. package/lib/typescript/src/logger.d.ts +4 -0
  397. package/lib/typescript/src/logger.d.ts.map +1 -0
  398. package/lib/typescript/src/lowMemoryCache.d.ts +64 -0
  399. package/lib/typescript/src/lowMemoryCache.d.ts.map +1 -0
  400. package/lib/typescript/src/mediaHistory.d.ts +3 -0
  401. package/lib/typescript/src/mediaHistory.d.ts.map +1 -0
  402. package/lib/typescript/src/mediaStorageService.d.ts +155 -0
  403. package/lib/typescript/src/mediaStorageService.d.ts.map +1 -0
  404. package/lib/typescript/src/memory.d.ts +21 -0
  405. package/lib/typescript/src/memory.d.ts.map +1 -0
  406. package/lib/typescript/src/nativeActions.d.ts +174 -0
  407. package/lib/typescript/src/nativeActions.d.ts.map +1 -0
  408. package/lib/typescript/src/nativeComponentSupport.d.ts +30 -0
  409. package/lib/typescript/src/nativeComponentSupport.d.ts.map +1 -0
  410. package/lib/typescript/src/networkPerformance.d.ts +12 -0
  411. package/lib/typescript/src/networkPerformance.d.ts.map +1 -0
  412. package/lib/typescript/src/performance.d.ts +32 -0
  413. package/lib/typescript/src/performance.d.ts.map +1 -0
  414. package/lib/typescript/src/performanceMonitor.d.ts +45 -0
  415. package/lib/typescript/src/performanceMonitor.d.ts.map +1 -0
  416. package/lib/typescript/src/permissions.d.ts +132 -0
  417. package/lib/typescript/src/permissions.d.ts.map +1 -0
  418. package/lib/typescript/src/rendering.d.ts +9 -0
  419. package/lib/typescript/src/rendering.d.ts.map +1 -0
  420. package/lib/typescript/src/security.d.ts +6 -0
  421. package/lib/typescript/src/security.d.ts.map +1 -0
  422. package/lib/typescript/src/state.d.ts +102 -0
  423. package/lib/typescript/src/state.d.ts.map +1 -0
  424. package/lib/typescript/src/storage.d.ts +117 -0
  425. package/lib/typescript/src/storage.d.ts.map +1 -0
  426. package/lib/typescript/src/theme.d.ts +15 -0
  427. package/lib/typescript/src/theme.d.ts.map +1 -0
  428. package/lib/typescript/src/types.d.ts +802 -0
  429. package/lib/typescript/src/types.d.ts.map +1 -0
  430. package/lib/typescript/src/utils.d.ts +50 -0
  431. package/lib/typescript/src/utils.d.ts.map +1 -0
  432. package/lib/typescript/src/validation.d.ts +52 -0
  433. package/lib/typescript/src/validation.d.ts.map +1 -0
  434. package/package.json +204 -0
  435. package/react-native.config.js +17 -0
  436. package/src/AudioPlayerContext.tsx +220 -0
  437. package/src/CameraPreview.tsx +352 -0
  438. package/src/NativeAnimatedImageView.tsx +71 -0
  439. package/src/NativeAudioPlayerView.tsx +39 -0
  440. package/src/NativeBlurView.tsx +40 -0
  441. package/src/NativeCustomCamera.ts +305 -0
  442. package/src/NativeCustomCamera.web.ts +192 -0
  443. package/src/NativeCustomVideoView.ts +30 -0
  444. package/src/NativeDocumentPreviewView.tsx +196 -0
  445. package/src/NativeMediaThumbnailView.tsx +167 -0
  446. package/src/NativeSvgIcon.tsx +46 -0
  447. package/src/ResponsivePreviewContainer.tsx +227 -0
  448. package/src/accessibility.ts +80 -0
  449. package/src/config.ts +406 -0
  450. package/src/cpuOptimization.ts +365 -0
  451. package/src/db/DatabaseManager.ts +212 -0
  452. package/src/db/MediaMapper.ts +377 -0
  453. package/src/db/MediaRepository.ts +313 -0
  454. package/src/db/index.ts +73 -0
  455. package/src/db/migrations.ts +222 -0
  456. package/src/db/react-native-sqlcipher.d.ts +76 -0
  457. package/src/db/secureKey.ts +100 -0
  458. package/src/db/types.ts +123 -0
  459. package/src/db/useMediaDatabase.ts +191 -0
  460. package/src/defaultIcons.tsx +2390 -0
  461. package/src/deviceCapabilities.ts +438 -0
  462. package/src/errors.ts +350 -0
  463. package/src/iconConfig.tsx +962 -0
  464. package/src/icons.tsx +788 -0
  465. package/src/index.tsx +763 -0
  466. package/src/jest-globals.d.ts +9 -0
  467. package/src/library/MediaLibrary.tsx +141 -0
  468. package/src/library/MediaLibraryScreen.tsx +3003 -0
  469. package/src/library/components/AudioPreview.tsx +73 -0
  470. package/src/library/components/DocumentPreview.tsx +361 -0
  471. package/src/library/components/ExpandableFab.tsx +342 -0
  472. package/src/library/components/FileTiles.tsx +252 -0
  473. package/src/library/components/ImagePreview.tsx +72 -0
  474. package/src/library/components/MediaMetadataHeader.tsx +208 -0
  475. package/src/library/components/RecordAudioScreen.tsx +845 -0
  476. package/src/library/components/VideoPreview.tsx +478 -0
  477. package/src/library/components/ViewerCounter.tsx +71 -0
  478. package/src/library/compressionEstimate.ts +662 -0
  479. package/src/library/fileMetadata.ts +212 -0
  480. package/src/library/index.ts +66 -0
  481. package/src/library/libraryIconRegistry.tsx +86 -0
  482. package/src/library/libraryIcons.tsx +928 -0
  483. package/src/library/localizedFormat.ts +207 -0
  484. package/src/library/palette.ts +281 -0
  485. package/src/library/responsive.ts +49 -0
  486. package/src/locales.ts +381 -0
  487. package/src/localization.ts +1947 -0
  488. package/src/logger.ts +20 -0
  489. package/src/lowMemoryCache.ts +218 -0
  490. package/src/mediaHistory.ts +42 -0
  491. package/src/mediaStorageService.ts +546 -0
  492. package/src/memory.ts +102 -0
  493. package/src/nativeActions.ts +422 -0
  494. package/src/nativeComponentSupport.ts +60 -0
  495. package/src/networkPerformance.ts +30 -0
  496. package/src/performance.ts +137 -0
  497. package/src/performanceMonitor.ts +219 -0
  498. package/src/permissions.ts +403 -0
  499. package/src/rendering.ts +47 -0
  500. package/src/security.ts +19 -0
  501. package/src/state.ts +333 -0
  502. package/src/storage.ts +453 -0
  503. package/src/theme.tsx +467 -0
  504. package/src/types.ts +946 -0
  505. package/src/utils.ts +177 -0
  506. package/src/validation.ts +372 -0
@@ -0,0 +1,365 @@
1
+ /// <reference lib="dom" />
2
+
3
+ /**
4
+ * CPU optimization utilities for low-end devices
5
+ */
6
+
7
+ import { devWarn } from './logger';
8
+
9
+ /**
10
+ * Debounce function optimized for low-end devices
11
+ * Longer default delay to reduce CPU load
12
+ */
13
+ export function debounceForLowEnd<T extends (...args: unknown[]) => unknown>(
14
+ func: T,
15
+ wait: number = 500 // Longer debounce for low-end
16
+ ): (...args: Parameters<T>) => void {
17
+ let timeout: ReturnType<typeof setTimeout> | null = null;
18
+
19
+ return function (...args: Parameters<T>): void {
20
+ if (timeout) {
21
+ clearTimeout(timeout);
22
+ }
23
+
24
+ timeout = setTimeout(() => {
25
+ // Use requestIdleCallback if available for better CPU management
26
+ const nativeGlobal = global as unknown as {
27
+ requestIdleCallback?: (
28
+ cb: () => void,
29
+ opts?: { timeout?: number }
30
+ ) => void;
31
+ };
32
+
33
+ if (typeof nativeGlobal.requestIdleCallback === 'function') {
34
+ nativeGlobal.requestIdleCallback!(() => func(...args), {
35
+ timeout: 1000,
36
+ });
37
+ } else {
38
+ func(...args);
39
+ }
40
+ }, wait);
41
+ };
42
+ }
43
+
44
+ /**
45
+ * Throttle function optimized for low-end devices
46
+ * Longer limit to reduce CPU load
47
+ */
48
+ export function throttleForLowEnd<T extends (...args: unknown[]) => unknown>(
49
+ func: T,
50
+ limit: number = 1000 // Longer throttle for low-end
51
+ ): (...args: Parameters<T>) => void {
52
+ let lastFunc: ReturnType<typeof setTimeout> | null = null;
53
+ let lastRan = 0;
54
+
55
+ return function (...args: Parameters<T>): void {
56
+ if (!lastRan) {
57
+ func(...args);
58
+ lastRan = Date.now();
59
+ } else {
60
+ if (lastFunc) {
61
+ clearTimeout(lastFunc);
62
+ }
63
+
64
+ lastFunc = setTimeout(
65
+ () => {
66
+ if (Date.now() - lastRan >= limit) {
67
+ func(...args);
68
+ lastRan = Date.now();
69
+ }
70
+ },
71
+ limit - (Date.now() - lastRan)
72
+ );
73
+ }
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Run operation in background with priority control
79
+ * Uses requestIdleCallback when available
80
+ */
81
+ export async function runInBackgroundWithPriority(
82
+ operation: () => Promise<void>,
83
+ priority: 'low' | 'normal' | 'high' = 'low'
84
+ ): Promise<void> {
85
+ if (priority === 'low') {
86
+ await Promise.resolve();
87
+ }
88
+
89
+ await operation();
90
+ }
91
+
92
+ /**
93
+ * Create lazy initializer that defers execution
94
+ * Uses requestIdleCallback when available
95
+ */
96
+ export function createLazyInitializer<T>(
97
+ initializer: () => T
98
+ ): () => T | Promise<T> {
99
+ let value: T | null = null;
100
+ let initialized = false;
101
+ let initializing = false;
102
+ let callbacks: Array<(value: T | PromiseLike<T>) => void> = [];
103
+
104
+ const initialize = () => {
105
+ if (initializing) return;
106
+ initializing = true;
107
+
108
+ const nativeGlobal = global as unknown as {
109
+ requestIdleCallback?: (
110
+ cb: () => void,
111
+ opts?: { timeout?: number }
112
+ ) => void;
113
+ };
114
+
115
+ if (typeof nativeGlobal.requestIdleCallback === 'function') {
116
+ nativeGlobal.requestIdleCallback!(
117
+ () => {
118
+ try {
119
+ value = initializer();
120
+ initialized = true;
121
+ callbacks.forEach((cb) => cb(value!));
122
+ callbacks = [];
123
+ } catch {
124
+ // Silently fail lazy initialization
125
+ }
126
+ initializing = false;
127
+ },
128
+ { timeout: 1000 }
129
+ );
130
+
131
+ // Fallback if idle callback doesn't fire
132
+ setTimeout(() => {
133
+ if (!initialized && !initializing) {
134
+ try {
135
+ value = initializer();
136
+ initialized = true;
137
+ callbacks.forEach((cb) => cb(value!));
138
+ callbacks = [];
139
+ } catch {
140
+ // Silently fail
141
+ }
142
+ }
143
+ }, 1000);
144
+ } else {
145
+ try {
146
+ value = initializer();
147
+ initialized = true;
148
+ callbacks.forEach((cb) => cb(value!));
149
+ callbacks = [];
150
+ } catch {
151
+ // Silently fail
152
+ }
153
+ }
154
+ };
155
+
156
+ return () => {
157
+ if (!initialized) {
158
+ if (!initializing) {
159
+ initialize();
160
+ }
161
+
162
+ return new Promise<T>((resolve) => {
163
+ callbacks.push(resolve);
164
+ });
165
+ }
166
+
167
+ return value!;
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Process operations in chunks to avoid blocking UI
173
+ */
174
+ export async function processInChunks<T>(
175
+ operations: (() => Promise<T>)[]
176
+ ): Promise<T[]> {
177
+ const results: T[] = [];
178
+
179
+ for (const operation of operations) {
180
+ await Promise.resolve();
181
+
182
+ try {
183
+ const result = await operation();
184
+ results.push(result);
185
+ } catch (error) {
186
+ throw error;
187
+ }
188
+ }
189
+
190
+ return results;
191
+ }
192
+
193
+ /**
194
+ * CPU-efficient delay that yields to main thread
195
+ */
196
+ export function efficientDelay(ms: number): Promise<void> {
197
+ return new Promise((resolve) => {
198
+ if (ms <= 0) {
199
+ resolve();
200
+ return;
201
+ }
202
+
203
+ const start = performance.now();
204
+ while (performance.now() - start < ms) {
205
+ // Busy-wait briefly to provide a real delay without depending on timers
206
+ }
207
+
208
+ resolve();
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Check if current thread is busy
214
+ */
215
+ export function isMainThreadBusy(): boolean {
216
+ // Simple heuristic for busyness
217
+ const start = performance.now();
218
+ let computation = 0;
219
+
220
+ // Small computation to check responsiveness
221
+ for (let i = 0; i < 1000; i += 1) {
222
+ computation += i;
223
+ }
224
+
225
+ const duration = performance.now() - start;
226
+ if (computation === 0) {
227
+ return false;
228
+ }
229
+
230
+ // If simple computation takes too long, thread is busy
231
+ return duration > 5; // More than 5ms indicates busyness
232
+ }
233
+
234
+ /**
235
+ * Wait for main thread to be available
236
+ */
237
+ export async function waitForMainThreadAvailable(
238
+ maxWait: number = 1000,
239
+ checkInterval: number = 50
240
+ ): Promise<void> {
241
+ const startTime = Date.now();
242
+
243
+ while (Date.now() - startTime < maxWait) {
244
+ if (!isMainThreadBusy()) {
245
+ return;
246
+ }
247
+
248
+ await efficientDelay(checkInterval);
249
+ }
250
+
251
+ // Timeout reached
252
+ devWarn('Main thread remained busy for too long');
253
+ }
254
+
255
+ /**
256
+ * CPU-efficient animation frame handler
257
+ */
258
+ export function requestEfficientAnimationFrame(
259
+ callback: FrameRequestCallback
260
+ ): number {
261
+ if (isMainThreadBusy()) {
262
+ // If main thread is busy, use setTimeout instead
263
+ const handle = setTimeout(() => {
264
+ const time = performance.now();
265
+ callback(time);
266
+ }, 16); // ~60fps
267
+ return handle as unknown as number;
268
+ }
269
+
270
+ return requestAnimationFrame(callback);
271
+ }
272
+
273
+ /**
274
+ * Cancel efficient animation frame
275
+ */
276
+ export function cancelEfficientAnimationFrame(handle: number): void {
277
+ try {
278
+ cancelAnimationFrame(handle);
279
+ } catch {
280
+ // If it was a setTimeout, clear it
281
+ clearTimeout(handle as unknown as ReturnType<typeof setTimeout>);
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Get CPU optimization level based on device specs
287
+ */
288
+ export function getCpuOptimizationLevel(
289
+ ram: 'low' | 'medium' | 'high',
290
+ processor: 'weak' | 'medium' | 'strong'
291
+ ): 'aggressive' | 'moderate' | 'none' {
292
+ if (ram === 'low' || processor === 'weak') {
293
+ return 'aggressive';
294
+ }
295
+
296
+ if (ram === 'medium' || processor === 'medium') {
297
+ return 'moderate';
298
+ }
299
+
300
+ return 'none';
301
+ }
302
+
303
+ /**
304
+ * Check if device supports requestIdleCallback
305
+ */
306
+ export function supportsIdleCallback(): boolean {
307
+ const nativeGlobal = global as unknown as { requestIdleCallback?: unknown };
308
+ return typeof nativeGlobal.requestIdleCallback === 'function';
309
+ }
310
+
311
+ /**
312
+ * Polyfill for requestIdleCallback
313
+ */
314
+ export function requestIdleCallbackPolyfill(
315
+ callback: (deadline: IdleDeadline) => void,
316
+ options?: { timeout: number }
317
+ ): number {
318
+ if (supportsIdleCallback()) {
319
+ const nativeGlobal = global as unknown as {
320
+ requestIdleCallback?: (
321
+ cb: (deadline: IdleDeadline) => void,
322
+ opts?: { timeout?: number }
323
+ ) => number;
324
+ };
325
+
326
+ const idleCallback = nativeGlobal.requestIdleCallback;
327
+ if (typeof idleCallback === 'function') {
328
+ return idleCallback(callback, options);
329
+ }
330
+ }
331
+
332
+ // Polyfill using setTimeout
333
+ const timeout = options?.timeout || 5000;
334
+ const start = Date.now();
335
+
336
+ const handle = setTimeout(() => {
337
+ callback({
338
+ didTimeout: false,
339
+ timeRemaining: () => Math.max(0, timeout - (Date.now() - start)),
340
+ });
341
+ }, 16); // Next animation frame
342
+
343
+ return handle as unknown as number;
344
+ }
345
+
346
+ /**
347
+ * Cancel polyfilled idle callback
348
+ */
349
+ export function cancelIdleCallbackPolyfill(handle: number): void {
350
+ const nativeGlobal = global as unknown as {
351
+ cancelIdleCallback?: (handle: number) => void;
352
+ };
353
+
354
+ if (
355
+ supportsIdleCallback() &&
356
+ typeof nativeGlobal.cancelIdleCallback === 'function'
357
+ ) {
358
+ const idleCancelCallback = nativeGlobal.cancelIdleCallback;
359
+ if (typeof idleCancelCallback === 'function') {
360
+ idleCancelCallback(handle);
361
+ }
362
+ } else {
363
+ clearTimeout(handle as unknown as ReturnType<typeof setTimeout>);
364
+ }
365
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * DatabaseManager — the single, centralized owner of the encrypted SQLCipher
3
+ * connection.
4
+ *
5
+ * Responsibilities:
6
+ * - Lazily open the encrypted database exactly once (idempotent `init`).
7
+ * - Provision the encryption key via the Keystore-backed `secureKey` helper.
8
+ * - Run schema migrations on open.
9
+ * - Expose small, safe primitives (`exec`, `query`, `transaction`) that the
10
+ * repository layer builds on — nothing above this file touches the raw driver.
11
+ *
12
+ * The `react-native-sqlcipher` native driver is imported lazily so the bundle
13
+ * still loads on platforms where it is absent (e.g. web); callers get a clear
14
+ * error instead of a hard crash at import time.
15
+ */
16
+ import { Platform } from 'react-native';
17
+ import type {
18
+ SQLiteDatabase,
19
+ SQLiteStatic,
20
+ ResultSet,
21
+ } from 'react-native-sqlcipher';
22
+ import { getDatabaseKey } from './secureKey';
23
+ import { runMigrations, type MigrationExecutor } from './migrations';
24
+
25
+ const DATABASE_NAME = 'media_secure.db';
26
+ const DATABASE_LOCATION = 'default';
27
+
28
+ /** A single parameterized statement for {@link DatabaseManager.batch}. */
29
+ export interface BatchStatement {
30
+ sql: string;
31
+ params?: any[];
32
+ }
33
+
34
+ /** Loads the native SQLCipher module lazily. Returns null when unavailable. */
35
+ function loadDriver(): SQLiteStatic | null {
36
+ try {
37
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
38
+ const mod = require('react-native-sqlcipher');
39
+ return (mod?.default ?? mod) as SQLiteStatic;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
44
+
45
+ export class DatabaseManager {
46
+ private db: SQLiteDatabase | null = null;
47
+ private initPromise: Promise<SQLiteDatabase> | null = null;
48
+
49
+ /** True once the encrypted database is open and migrated. */
50
+ get isReady(): boolean {
51
+ return this.db !== null;
52
+ }
53
+
54
+ /**
55
+ * Opens (once) the encrypted database and applies migrations. Concurrent
56
+ * callers share a single in-flight open, so `init` is safe to call from
57
+ * multiple screens/hooks simultaneously.
58
+ */
59
+ async init(): Promise<SQLiteDatabase> {
60
+ if (this.db) return this.db;
61
+ if (this.initPromise) return this.initPromise;
62
+
63
+ this.initPromise = this.open()
64
+ .then((db) => {
65
+ this.db = db;
66
+ return db;
67
+ })
68
+ .catch((error) => {
69
+ // Reset so a later attempt can retry from scratch.
70
+ this.initPromise = null;
71
+ throw error;
72
+ });
73
+
74
+ return this.initPromise;
75
+ }
76
+
77
+ private async open(): Promise<SQLiteDatabase> {
78
+ const SQLite = loadDriver();
79
+ if (!SQLite) {
80
+ throw new Error(
81
+ `[DatabaseManager] 'react-native-sqlcipher' is not available on ` +
82
+ `platform '${Platform.OS}'. Install the package and rebuild the ` +
83
+ `native app to enable the encrypted media database.`
84
+ );
85
+ }
86
+
87
+ SQLite.enablePromise(true);
88
+
89
+ const key = await getDatabaseKey();
90
+ const db = await SQLite.openDatabase({
91
+ name: DATABASE_NAME,
92
+ key,
93
+ location: DATABASE_LOCATION,
94
+ });
95
+
96
+ // Pragmas: WAL for concurrent read/write throughput, FK enforcement on.
97
+ await db.executeSql('PRAGMA foreign_keys = ON;');
98
+ try {
99
+ await db.executeSql('PRAGMA journal_mode = WAL;');
100
+ } catch {
101
+ // WAL is an optimization; ignore if the platform rejects it.
102
+ }
103
+
104
+ await runMigrations(this.createMigrationExecutor(db));
105
+
106
+ return db;
107
+ }
108
+
109
+ /** Ensures the DB is open and returns the live connection. */
110
+ private async requireDb(): Promise<SQLiteDatabase> {
111
+ return this.db ?? (await this.init());
112
+ }
113
+
114
+ /**
115
+ * Executes a write/DDL statement. Returns the raw result set for callers that
116
+ * need `insertId` / `rowsAffected`.
117
+ */
118
+ async exec(sql: string, params: any[] = []): Promise<ResultSet> {
119
+ const db = await this.requireDb();
120
+ const [result] = await db.executeSql(sql, params);
121
+ return result;
122
+ }
123
+
124
+ /** Executes a SELECT and returns the rows as an array of `T`. */
125
+ async query<T = any>(sql: string, params: any[] = []): Promise<T[]> {
126
+ const db = await this.requireDb();
127
+ const [result] = await db.executeSql(sql, params);
128
+ const rows: T[] = [];
129
+ for (let i = 0; i < result.rows.length; i++) {
130
+ rows.push(result.rows.item(i) as T);
131
+ }
132
+ return rows;
133
+ }
134
+
135
+ /** Convenience: SELECT returning the first scalar column of the first row. */
136
+ async queryScalar<T = number>(
137
+ sql: string,
138
+ params: any[] = []
139
+ ): Promise<T | null> {
140
+ const rows = await this.query<Record<string, T>>(sql, params);
141
+ if (rows.length === 0) return null;
142
+ const first = rows[0]!;
143
+ const firstKey = Object.keys(first)[0];
144
+ return firstKey === undefined ? null : first[firstKey]!;
145
+ }
146
+
147
+ /**
148
+ * Runs a set of statements atomically in a single transaction.
149
+ *
150
+ * The `react-native-sqlcipher` driver requires every `executeSql` to be queued
151
+ * *synchronously* inside the transaction scope, so this takes a pre-built list
152
+ * of statements rather than an async callback — guaranteeing all-or-nothing
153
+ * semantics (used by `insertMany` and the migration runner).
154
+ */
155
+ async batch(statements: BatchStatement[]): Promise<void> {
156
+ if (statements.length === 0) return;
157
+ const db = await this.requireDb();
158
+ await db.transaction((tx) => {
159
+ for (const { sql, params } of statements) {
160
+ tx.executeSql(sql, params ?? []);
161
+ }
162
+ });
163
+ }
164
+
165
+ /** Adapts this manager to the migration executor contract. */
166
+ private createMigrationExecutor(db: SQLiteDatabase): MigrationExecutor {
167
+ return {
168
+ getVersion: async () => {
169
+ const [result] = await db.executeSql('PRAGMA user_version;');
170
+ const row = result.rows.item(0);
171
+ return Number(row?.user_version ?? 0);
172
+ },
173
+ runBatch: async (statements: string[]) => {
174
+ await db.transaction((tx) => {
175
+ for (const sql of statements) {
176
+ tx.executeSql(sql, []);
177
+ }
178
+ });
179
+ },
180
+ };
181
+ }
182
+
183
+ /** Closes the connection (e.g. on teardown). Safe to call when not open. */
184
+ async close(): Promise<void> {
185
+ const db = this.db;
186
+ this.db = null;
187
+ this.initPromise = null;
188
+ if (db) {
189
+ try {
190
+ await db.close();
191
+ } catch (error) {
192
+ console.warn('[DatabaseManager] close failed', error);
193
+ }
194
+ }
195
+ }
196
+ }
197
+
198
+ // Process-wide singleton — every consumer shares one encrypted connection.
199
+ let managerInstance: DatabaseManager | null = null;
200
+
201
+ /** Returns the shared `DatabaseManager` singleton. */
202
+ export function getDatabaseManager(): DatabaseManager {
203
+ if (!managerInstance) {
204
+ managerInstance = new DatabaseManager();
205
+ }
206
+ return managerInstance;
207
+ }
208
+
209
+ /** Opens + migrates the encrypted database. Call once at app startup. */
210
+ export async function initializeMediaDatabase(): Promise<void> {
211
+ await getDatabaseManager().init();
212
+ }