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,124 @@
1
+ package com.customcamera.gif
2
+
3
+ import android.os.Handler
4
+ import android.os.Looper
5
+ import java.util.concurrent.ExecutorService
6
+ import java.util.concurrent.Executors
7
+ import java.util.concurrent.atomic.AtomicLong
8
+
9
+ /**
10
+ * Background-thread orchestrator between the GIF picker UI and a [GifProvider].
11
+ *
12
+ * The UI never touches a [GifProvider] directly: it calls the repository, which runs the blocking
13
+ * provider call on a worker thread and delivers the typed [GifResult] back on the main thread. A
14
+ * single generation counter implements "latest wins" — when the user starts a new search (or
15
+ * clears it back to trending) any still-in-flight list request is dropped so a slow earlier
16
+ * response can never overwrite the newer list. Pagination ([loadMore]) deliberately does NOT bump
17
+ * the generation, so it continues the current list, but it is dropped if the list changed while it
18
+ * was loading.
19
+ *
20
+ * Categories are cached after the first success (they change rarely) and replayed synchronously.
21
+ *
22
+ * The owner (the picker) must call [shutdown] when it closes to release the worker threads.
23
+ */
24
+ class GifRepository(private val provider: GifProvider) {
25
+
26
+ private val executor: ExecutorService = Executors.newFixedThreadPool(2) { r ->
27
+ Thread(r, "gif-repo").apply { isDaemon = true }
28
+ }
29
+ private val main = Handler(Looper.getMainLooper())
30
+
31
+ /** Bumped by [refreshList]; a delivered result is discarded when this no longer matches. */
32
+ private val listGeneration = AtomicLong(0)
33
+
34
+ @Volatile private var cachedCategories: List<GifCategory>? = null
35
+ @Volatile private var shutdown = false
36
+
37
+ val attributionLabel: String? get() = provider.attributionLabel
38
+
39
+ fun isConfigured(): Boolean = provider.isConfigured()
40
+
41
+ /**
42
+ * Load the first page of a list. [query] null/blank ⇒ trending; otherwise search results.
43
+ * Supersedes any earlier in-flight list request. [onResult] runs on the main thread.
44
+ */
45
+ fun refreshList(query: String?, limit: Int, onResult: (GifResult<GifPage>) -> Unit) {
46
+ val generation = listGeneration.incrementAndGet()
47
+ if (!query.isNullOrBlank() && GifSafety.isBlockedQuery(query)) {
48
+ main.post { onResult(GifResult.Success(GifPage(emptyList(), null))) }
49
+ return
50
+ }
51
+ submitList(query, limit, cursor = null, generation = generation, onResult = onResult)
52
+ }
53
+
54
+ /**
55
+ * Load the next page of the CURRENT list (continuation of the last [refreshList]). The result is
56
+ * dropped if the user changed the list meanwhile. [cursor] comes from [GifPage.nextCursor].
57
+ */
58
+ fun loadMore(query: String?, limit: Int, cursor: String, onResult: (GifResult<GifPage>) -> Unit) {
59
+ val generation = listGeneration.get()
60
+ submitList(query, limit, cursor = cursor, generation = generation, onResult = onResult)
61
+ }
62
+
63
+ private fun submitList(
64
+ query: String?,
65
+ limit: Int,
66
+ cursor: String?,
67
+ generation: Long,
68
+ onResult: (GifResult<GifPage>) -> Unit
69
+ ) {
70
+ if (shutdown) return
71
+ execute {
72
+ val result = if (query.isNullOrBlank()) {
73
+ provider.trending(limit, cursor)
74
+ } else {
75
+ provider.search(query, limit, cursor)
76
+ }
77
+ val safeResult = when (result) {
78
+ is GifResult.Success -> GifResult.Success(GifSafety.filterPage(result.value))
79
+ is GifResult.Failure -> result
80
+ }
81
+ deliver(onResult, safeResult) { listGeneration.get() == generation }
82
+ }
83
+ }
84
+
85
+ /** Load browsable categories, served from cache after the first success. Main-thread callback. */
86
+ fun loadCategories(onResult: (GifResult<List<GifCategory>>) -> Unit) {
87
+ cachedCategories?.let { cached ->
88
+ main.post { onResult(GifResult.Success(cached)) }
89
+ return
90
+ }
91
+ if (shutdown) return
92
+ execute {
93
+ val result = provider.categories()
94
+ if (result is GifResult.Success) cachedCategories = result.value
95
+ deliver(onResult, result) { true }
96
+ }
97
+ }
98
+
99
+ private fun <T> deliver(
100
+ onResult: (GifResult<T>) -> Unit,
101
+ result: GifResult<T>,
102
+ isStillCurrent: () -> Boolean
103
+ ) {
104
+ main.post {
105
+ if (!shutdown && isStillCurrent()) onResult(result)
106
+ }
107
+ }
108
+
109
+ private fun execute(block: () -> Unit) {
110
+ try {
111
+ executor.execute {
112
+ if (!shutdown) block()
113
+ }
114
+ } catch (e: Exception) {
115
+ // Executor rejected (already shut down) — nothing to deliver.
116
+ }
117
+ }
118
+
119
+ /** Stop delivering results and release worker threads. Safe to call more than once. */
120
+ fun shutdown() {
121
+ shutdown = true
122
+ executor.shutdownNow()
123
+ }
124
+ }
@@ -0,0 +1,33 @@
1
+ package com.customcamera.gif
2
+
3
+ /** Shared client-side guard for queries and provider-returned GIF descriptions. */
4
+ internal object GifSafety {
5
+
6
+ private val blockedTerms = setOf(
7
+ "kiss", "kissing", "makeout", "nude", "nudes", "naked", "nsfw", "porn", "porno",
8
+ "xxx", "sex", "sexual", "erotic", "hentai", "fetish", "topless", "uncensored",
9
+ "orgasm", "masturbat", "blowjob", "handjob", "intercourse", "vagina", "penis",
10
+ "dick", "pussy", "boob", "breast", "tits", "anal", "bdsm", "cum", "semen"
11
+ )
12
+
13
+ fun isBlockedQuery(query: String): Boolean = containsBlockedTerm(query)
14
+
15
+ fun filterPage(page: GifPage): GifPage = page.copy(
16
+ items = page.items.filterNot { item ->
17
+ containsBlockedTerm(item.description) ||
18
+ containsBlockedTerm(item.previewUrl) ||
19
+ containsBlockedTerm(item.contentUrl)
20
+ }
21
+ )
22
+
23
+ private fun containsBlockedTerm(value: String): Boolean {
24
+ val normalized = value.lowercase()
25
+ return blockedTerms.any { term ->
26
+ if (term.length < 4) {
27
+ Regex("\\b${Regex.escape(term)}\\b").containsMatchIn(normalized)
28
+ } else {
29
+ normalized.contains(term)
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,146 @@
1
+ package com.customcamera.gif
2
+
3
+ import java.net.URLEncoder
4
+ import org.json.JSONObject
5
+
6
+ /**
7
+ * [GifProvider] backed by the GIPHY HTTP API (v1).
8
+ *
9
+ * All calls block on [GifHttp] and fold every failure into a typed [GifResult.Failure]; nothing
10
+ * throws. GIPHY paginates by integer offset, so the opaque [GifPage.nextCursor] carried across
11
+ * pages is simply the next offset rendered as a string.
12
+ *
13
+ * @param apiKey GIPHY API key; when null/blank the provider reports [isConfigured] == false and
14
+ * every call short-circuits with [GifError.NO_API_KEY].
15
+ */
16
+ class GiphyGifProvider(private val apiKey: String?) : GifProvider {
17
+
18
+ override val id: String = "giphy"
19
+
20
+ override val attributionLabel: String? = "Powered by GIPHY"
21
+
22
+ override fun isConfigured(): Boolean = !apiKey.isNullOrBlank()
23
+
24
+ override fun trending(limit: Int, cursor: String?): GifResult<GifPage> {
25
+ val key = apiKey
26
+ if (key.isNullOrBlank()) return GifResult.Failure(GifError.NO_API_KEY)
27
+ val offset = cursor?.toIntOrNull() ?: 0
28
+ val url = "$BASE/gifs/trending?api_key=${enc(key)}&limit=$limit&offset=$offset" +
29
+ "&rating=g&bundle=messaging_non_clips"
30
+ return when (val res = GifHttp.getJson(url)) {
31
+ is GifResult.Failure -> res
32
+ is GifResult.Success -> parsePage(res.value, limit, offset)
33
+ }
34
+ }
35
+
36
+ override fun search(query: String, limit: Int, cursor: String?): GifResult<GifPage> {
37
+ val key = apiKey
38
+ if (key.isNullOrBlank()) return GifResult.Failure(GifError.NO_API_KEY)
39
+ val offset = cursor?.toIntOrNull() ?: 0
40
+ val url = "$BASE/gifs/search?api_key=${enc(key)}&q=${enc(query)}&limit=$limit&offset=$offset" +
41
+ "&rating=g&lang=en&bundle=messaging_non_clips"
42
+ return when (val res = GifHttp.getJson(url)) {
43
+ is GifResult.Failure -> res
44
+ is GifResult.Success -> parsePage(res.value, limit, offset)
45
+ }
46
+ }
47
+
48
+ override fun categories(): GifResult<List<GifCategory>> {
49
+ val key = apiKey
50
+ if (key.isNullOrBlank()) return GifResult.Failure(GifError.NO_API_KEY)
51
+ val url = "$BASE/gifs/categories?api_key=${enc(key)}"
52
+ val json = when (val res = GifHttp.getJson(url)) {
53
+ is GifResult.Failure -> return GifResult.Success(emptyList())
54
+ is GifResult.Success -> res.value
55
+ }
56
+ // Categories are optional: any parse failure degrades to an empty list, never a hard error.
57
+ val list = runCatching { parseCategories(json) }.getOrDefault(emptyList())
58
+ return GifResult.Success(list)
59
+ }
60
+
61
+ /** Parse a GIPHY list response ({ data, pagination, meta }) into a [GifPage]. */
62
+ private fun parsePage(json: JSONObject, limit: Int, offset: Int): GifResult<GifPage> {
63
+ // GIPHY echoes its own status inside meta; a >= 400 status can accompany an HTTP 200 body.
64
+ val status = json.optJSONObject("meta")?.optInt("status", 200) ?: 200
65
+ if (status >= 400) {
66
+ return GifResult.Failure(
67
+ when {
68
+ status == 429 -> GifError.RATE_LIMITED
69
+ status in 500..599 -> GifError.SERVER
70
+ else -> GifError.PARSE
71
+ }
72
+ )
73
+ }
74
+ val data = json.optJSONArray("data") ?: return GifResult.Failure(GifError.PARSE)
75
+ val items = ArrayList<GifItem>(data.length())
76
+ for (i in 0 until data.length()) {
77
+ val obj = data.optJSONObject(i) ?: continue
78
+ val images = obj.optJSONObject("images")
79
+ val preview = rendition(images, "fixed_width_downsampled", "fixed_width", "preview_gif") ?: continue
80
+ val content = rendition(images, "downsized", "original", "fixed_width") ?: continue
81
+ val (pUrl, pW, pH) = preview
82
+ val (cUrl, cW, cH) = content
83
+ items.add(
84
+ GifItem(
85
+ id = obj.optString("id"),
86
+ description = obj.optString("title"),
87
+ previewUrl = pUrl,
88
+ previewWidth = pW,
89
+ previewHeight = pH,
90
+ contentUrl = cUrl,
91
+ contentWidth = cW,
92
+ contentHeight = cH
93
+ )
94
+ )
95
+ }
96
+ val pagination = json.optJSONObject("pagination")
97
+ val count = pagination?.optInt("count", data.length()) ?: data.length()
98
+ // A missing total_count is treated as unbounded so pagination relies on the count < limit rule.
99
+ val totalCount = pagination?.optInt("total_count", Int.MAX_VALUE) ?: Int.MAX_VALUE
100
+ val nextOffset = offset + count
101
+ val nextCursor = when {
102
+ count < limit -> null
103
+ nextOffset >= totalCount -> null
104
+ else -> nextOffset.toString()
105
+ }
106
+ return GifResult.Success(GifPage(items, nextCursor))
107
+ }
108
+
109
+ /** Parse the optional GIPHY categories response; the caller downgrades any throw to empty. */
110
+ private fun parseCategories(json: JSONObject): List<GifCategory> {
111
+ val data = json.optJSONArray("data") ?: return emptyList()
112
+ val out = ArrayList<GifCategory>(data.length())
113
+ for (i in 0 until data.length()) {
114
+ val obj = data.optJSONObject(i) ?: continue
115
+ val name = obj.optString("name")
116
+ if (name.isBlank()) continue
117
+ val images = obj.optJSONObject("gif")?.optJSONObject("images")
118
+ val imageUrl = rendition(images, "fixed_width", "downsized", "original", "preview_gif")?.first
119
+ out.add(GifCategory(name = name, searchTerm = name, imageUrl = imageUrl))
120
+ }
121
+ return out
122
+ }
123
+
124
+ /**
125
+ * Pick the first present rendition among [names] and return its (url, width, height), or null
126
+ * when none has a usable (non-blank) url. GIPHY encodes width/height as strings.
127
+ */
128
+ private fun rendition(images: JSONObject?, vararg names: String): Triple<String, Int, Int>? {
129
+ if (images == null) return null
130
+ for (name in names) {
131
+ val r = images.optJSONObject(name) ?: continue
132
+ val url = r.optString("url")
133
+ if (url.isBlank()) continue
134
+ val w = r.optString("width").toIntOrNull() ?: 0
135
+ val h = r.optString("height").toIntOrNull() ?: 0
136
+ return Triple(url, w, h)
137
+ }
138
+ return null
139
+ }
140
+
141
+ private fun enc(value: String): String = URLEncoder.encode(value, "UTF-8")
142
+
143
+ companion object {
144
+ private const val BASE = "https://api.giphy.com/v1"
145
+ }
146
+ }
@@ -0,0 +1,258 @@
1
+ package com.customcamera.gif
2
+
3
+ import java.io.IOException
4
+ import java.io.OutputStream
5
+
6
+ /**
7
+ * GIF-variant LZW compressor.
8
+ *
9
+ * Faithful Kotlin port of the LZWEncoder used by Kevin Weiner's [AnimatedGifEncoder], which is
10
+ * itself adapted (K Weiner 12/00) from Jef Poskanzer's Acme.JPM.Encoders GIF encoder by way of
11
+ * J. M. G. Elliott, ultimately derived from the public-domain `GIFCOMPR.C` / `compress` lineage
12
+ * (David Rowley's GIF modifications). This is a syntax-only translation; the emitted bitstream is
13
+ * intended to be byte-for-byte identical to the canonical Java implementation.
14
+ *
15
+ * @param width image width in pixels
16
+ * @param height image height in pixels
17
+ * @param pixels palette-indexed pixels, one byte per pixel, row-major
18
+ * @param colorDepth number of bits per pixel used to seed the initial code size
19
+ */
20
+ class LZWEncoder(width: Int, height: Int, pixels: ByteArray, colorDepth: Int) {
21
+
22
+ private val imgW: Int = width
23
+ private val imgH: Int = height
24
+ private val pixAry: ByteArray = pixels
25
+ private val initCodeSize: Int = maxOf(2, colorDepth)
26
+ private var remaining: Int = 0
27
+ private var curPixel: Int = 0
28
+
29
+ // GIFCOMPR.C - GIF Image compression routines
30
+ //
31
+ // Lempel-Ziv compression based on 'compress'. GIF modifications by
32
+ // David Rowley (mgardi@watdcsu.waterloo.edu)
33
+
34
+ private val bits = 12
35
+ private val hsize = 5003 // 80% occupancy
36
+
37
+ // GIF Image compression - modified 'compress'
38
+ // Based on: compress.c - File compression ala IEEE Computer, June 1984.
39
+ // By Authors: Spencer W. Thomas, Jim McKie, Steve Davies, Ken Turkowski,
40
+ // James A. Woods, Joe Orost.
41
+
42
+ private var nBits = 0 // number of bits/code
43
+ private val maxbits = bits // user settable max # bits/code
44
+ private var maxcode = 0 // maximum code, given nBits
45
+ private val maxmaxcode = 1 shl bits // should NEVER generate this code
46
+
47
+ private val htab = IntArray(hsize)
48
+ private val codetab = IntArray(hsize)
49
+
50
+ private var freeEnt = 0 // first unused entry
51
+
52
+ // Block compression parameters -- after all codes are used up, and the
53
+ // compression rate changes, start over.
54
+ private var clearFlg = false
55
+
56
+ private var gInitBits = 0
57
+ private var clearCode = 0
58
+ private var eofCode = 0
59
+
60
+ // Output accumulator.
61
+ private var curAccum = 0
62
+ private var curBits = 0
63
+
64
+ private val masks = intArrayOf(
65
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F,
66
+ 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
67
+ )
68
+
69
+ // Number of characters so far in this 'packet'.
70
+ private var aCount = 0
71
+
72
+ // Storage for the packet accumulator.
73
+ private val accum = ByteArray(256)
74
+
75
+ companion object {
76
+ private const val EOF = -1
77
+ }
78
+
79
+ /**
80
+ * Adds a character to the end of the current packet, flushing to [outs] at 254 characters.
81
+ */
82
+ private fun charOut(c: Byte, outs: OutputStream) {
83
+ accum[aCount++] = c
84
+ if (aCount >= 254) flushChar(outs)
85
+ }
86
+
87
+ /**
88
+ * Table clear for block compress.
89
+ */
90
+ private fun clBlock(outs: OutputStream) {
91
+ clHash(hsize)
92
+ freeEnt = clearCode + 2
93
+ clearFlg = true
94
+ output(clearCode, outs)
95
+ }
96
+
97
+ /**
98
+ * Resets the hash table.
99
+ */
100
+ private fun clHash(hsize: Int) {
101
+ for (i in 0 until hsize) htab[i] = -1
102
+ }
103
+
104
+ /**
105
+ * Core compressor. See the GIFCOMPR lineage above. Uses open addressing double hashing (Knuth
106
+ * algorithm D with G. Knott's relatively-prime secondary probe) plus block compression with an
107
+ * adaptive reset when the table fills.
108
+ */
109
+ private fun compress(initBits: Int, outs: OutputStream) {
110
+ var fcode = 0
111
+ var i = 0
112
+ var c = 0
113
+ var disp = 0
114
+
115
+ // Set up the globals: gInitBits - initial number of bits.
116
+ gInitBits = initBits
117
+
118
+ // Set up the necessary values.
119
+ clearFlg = false
120
+ nBits = gInitBits
121
+ maxcode = MAXCODE(nBits)
122
+
123
+ clearCode = 1 shl (initBits - 1)
124
+ eofCode = clearCode + 1
125
+ freeEnt = clearCode + 2
126
+
127
+ aCount = 0 // clear packet
128
+
129
+ var ent = nextPixel()
130
+
131
+ var hshift = 0
132
+ fcode = hsize
133
+ while (fcode < 65536) {
134
+ hshift++
135
+ fcode *= 2
136
+ }
137
+ hshift = 8 - hshift // set hash code range bound
138
+
139
+ val hsizeReg = hsize
140
+ clHash(hsizeReg) // clear hash table
141
+
142
+ output(clearCode, outs)
143
+
144
+ outerLoop@ while (true) {
145
+ c = nextPixel()
146
+ if (c == EOF) break
147
+ fcode = (c shl maxbits) + ent
148
+ i = (c shl hshift) xor ent // xor hashing
149
+
150
+ if (htab[i] == fcode) {
151
+ ent = codetab[i]
152
+ continue
153
+ } else if (htab[i] >= 0) { // non-empty slot
154
+ disp = hsizeReg - i // secondary hash (after G. Knott)
155
+ if (i == 0) disp = 1
156
+ do {
157
+ i -= disp
158
+ if (i < 0) i += hsizeReg
159
+ if (htab[i] == fcode) {
160
+ ent = codetab[i]
161
+ continue@outerLoop
162
+ }
163
+ } while (htab[i] >= 0)
164
+ }
165
+ output(ent, outs)
166
+ ent = c
167
+ if (freeEnt < maxmaxcode) {
168
+ codetab[i] = freeEnt++ // code -> hashtable
169
+ htab[i] = fcode
170
+ } else {
171
+ clBlock(outs)
172
+ }
173
+ }
174
+ // Put out the final code.
175
+ output(ent, outs)
176
+ output(eofCode, outs)
177
+ }
178
+
179
+ /**
180
+ * Compresses and writes the pixel data to [os], framed by the initial code-size byte and the
181
+ * trailing block terminator. This is the public entry point used by [AnimatedGifEncoder].
182
+ */
183
+ @Throws(IOException::class)
184
+ fun encode(os: OutputStream) {
185
+ os.write(initCodeSize) // write "initial code size" byte
186
+ remaining = imgW * imgH // reset navigation variables
187
+ curPixel = 0
188
+ compress(initCodeSize + 1, os) // compress and write the pixel data
189
+ os.write(0) // write block terminator
190
+ }
191
+
192
+ /**
193
+ * Flushes the packet to [outs] and resets the accumulator.
194
+ */
195
+ private fun flushChar(outs: OutputStream) {
196
+ if (aCount > 0) {
197
+ outs.write(aCount)
198
+ outs.write(accum, 0, aCount)
199
+ aCount = 0
200
+ }
201
+ }
202
+
203
+ /** Largest code representable in [nBits] bits. */
204
+ private fun MAXCODE(nBits: Int): Int = (1 shl nBits) - 1
205
+
206
+ /**
207
+ * Returns the next pixel from the image, or [EOF] when exhausted.
208
+ */
209
+ private fun nextPixel(): Int {
210
+ if (remaining == 0) return EOF
211
+ remaining--
212
+ val pix = pixAry[curPixel++]
213
+ return pix.toInt() and 0xff
214
+ }
215
+ /**
216
+ * Outputs the given [code], packing it into the bit accumulator and emitting full bytes. When
217
+ * [code] equals [eofCode] the remaining buffered bits are flushed.
218
+ */
219
+ private fun output(code: Int, outs: OutputStream) {
220
+ curAccum = curAccum and masks[curBits]
221
+
222
+ if (curBits > 0) {
223
+ curAccum = curAccum or (code shl curBits)
224
+ } else {
225
+ curAccum = code
226
+ }
227
+
228
+ curBits += nBits
229
+
230
+ while (curBits >= 8) {
231
+ charOut((curAccum and 0xff).toByte(), outs)
232
+ curAccum = curAccum shr 8
233
+ curBits -= 8
234
+ }
235
+
236
+ // If the next entry is going to be too big for the code size, increase it if possible.
237
+ if (freeEnt > maxcode || clearFlg) {
238
+ if (clearFlg) {
239
+ nBits = gInitBits
240
+ maxcode = MAXCODE(nBits)
241
+ clearFlg = false
242
+ } else {
243
+ nBits++
244
+ maxcode = if (nBits == maxbits) maxmaxcode else MAXCODE(nBits)
245
+ }
246
+ }
247
+
248
+ if (code == eofCode) {
249
+ // At EOF, write the rest of the buffer.
250
+ while (curBits > 0) {
251
+ charOut((curAccum and 0xff).toByte(), outs)
252
+ curAccum = curAccum shr 8
253
+ curBits -= 8
254
+ }
255
+ flushChar(outs)
256
+ }
257
+ }
258
+ }