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.
- package/CustomCamera.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +833 -0
- package/android/build.gradle +135 -0
- package/android/consumer-rules.pro +47 -0
- package/android/src/main/AndroidManifest.xml +72 -0
- package/android/src/main/java/android/print/PdfPrint.java +51 -0
- package/android/src/main/java/com/customcamera/AnimatedImageViewManager.kt +199 -0
- package/android/src/main/java/com/customcamera/AudioPlayerView.kt +322 -0
- package/android/src/main/java/com/customcamera/AudioRecorder.kt +506 -0
- package/android/src/main/java/com/customcamera/BarcodeScannerActivity.kt +361 -0
- package/android/src/main/java/com/customcamera/BlurBackgroundView.kt +199 -0
- package/android/src/main/java/com/customcamera/CacheCleanupManager.kt +386 -0
- package/android/src/main/java/com/customcamera/CameraAspectRatioMode.kt +77 -0
- package/android/src/main/java/com/customcamera/CameraAsset.kt +211 -0
- package/android/src/main/java/com/customcamera/CameraTheme.kt +479 -0
- package/android/src/main/java/com/customcamera/CompressionCacheStore.kt +504 -0
- package/android/src/main/java/com/customcamera/CompressionFileNameUtils.kt +7 -0
- package/android/src/main/java/com/customcamera/CompressionProfile.kt +195 -0
- package/android/src/main/java/com/customcamera/CustomCameraActivity.kt +7291 -0
- package/android/src/main/java/com/customcamera/CustomCameraFileProvider.kt +9 -0
- package/android/src/main/java/com/customcamera/CustomCameraModule.kt +2479 -0
- package/android/src/main/java/com/customcamera/CustomCameraPackage.kt +53 -0
- package/android/src/main/java/com/customcamera/DisplayUtils.kt +9 -0
- package/android/src/main/java/com/customcamera/DocumentPreviewView.kt +846 -0
- package/android/src/main/java/com/customcamera/DrawingView.kt +214 -0
- package/android/src/main/java/com/customcamera/EmojiPickerData.kt +228 -0
- package/android/src/main/java/com/customcamera/FilterStripAdapter.kt +158 -0
- package/android/src/main/java/com/customcamera/GifSupport.kt +215 -0
- package/android/src/main/java/com/customcamera/GlobalAudioPlayer.kt +320 -0
- package/android/src/main/java/com/customcamera/ImageExporter.kt +1394 -0
- package/android/src/main/java/com/customcamera/ImageFormatSupport.kt +163 -0
- package/android/src/main/java/com/customcamera/Localization.kt +206 -0
- package/android/src/main/java/com/customcamera/MediaAdapters.kt +758 -0
- package/android/src/main/java/com/customcamera/MediaCacheManager.kt +782 -0
- package/android/src/main/java/com/customcamera/MediaExportFormats.kt +201 -0
- package/android/src/main/java/com/customcamera/MediaFileIo.kt +310 -0
- package/android/src/main/java/com/customcamera/MediaMetadataStore.kt +494 -0
- package/android/src/main/java/com/customcamera/MediaPreviewEditor.kt +14865 -0
- package/android/src/main/java/com/customcamera/MediaPublisher.kt +423 -0
- package/android/src/main/java/com/customcamera/MediaStorageWorkflow.kt +722 -0
- package/android/src/main/java/com/customcamera/MediaStoreRepository.kt +378 -0
- package/android/src/main/java/com/customcamera/MediaThumbnailView.kt +286 -0
- package/android/src/main/java/com/customcamera/MediaUtils.kt +37 -0
- package/android/src/main/java/com/customcamera/NativeVideoViewManager.kt +845 -0
- package/android/src/main/java/com/customcamera/OfficeDocumentConverter.kt +2791 -0
- package/android/src/main/java/com/customcamera/PendingCaptureCrops.kt +88 -0
- package/android/src/main/java/com/customcamera/PowerPointPreview.kt +4077 -0
- package/android/src/main/java/com/customcamera/RecentPickerStore.kt +74 -0
- package/android/src/main/java/com/customcamera/SecureFileEraser.kt +411 -0
- package/android/src/main/java/com/customcamera/SecureKeyModule.kt +88 -0
- package/android/src/main/java/com/customcamera/SecureMediaDeleter.kt +493 -0
- package/android/src/main/java/com/customcamera/StickerPickerData.kt +107 -0
- package/android/src/main/java/com/customcamera/SvgDrawable.kt +175 -0
- package/android/src/main/java/com/customcamera/SvgIconViewManager.kt +77 -0
- package/android/src/main/java/com/customcamera/TextEntryController.kt +553 -0
- package/android/src/main/java/com/customcamera/ThumbnailLoader.kt +455 -0
- package/android/src/main/java/com/customcamera/UploadService.kt +909 -0
- package/android/src/main/java/com/customcamera/VideoEditUtils.kt +210 -0
- package/android/src/main/java/com/customcamera/VideoRotationTranscoder.kt +1992 -0
- package/android/src/main/java/com/customcamera/gif/AnimatedGifEncoder.kt +473 -0
- package/android/src/main/java/com/customcamera/gif/GifDecoder.kt +690 -0
- package/android/src/main/java/com/customcamera/gif/GifFramesDrawable.kt +160 -0
- package/android/src/main/java/com/customcamera/gif/GifHttp.kt +112 -0
- package/android/src/main/java/com/customcamera/gif/GifImageLoader.kt +186 -0
- package/android/src/main/java/com/customcamera/gif/GifModels.kt +74 -0
- package/android/src/main/java/com/customcamera/gif/GifProvider.kt +49 -0
- package/android/src/main/java/com/customcamera/gif/GifProviders.kt +27 -0
- package/android/src/main/java/com/customcamera/gif/GifRepository.kt +124 -0
- package/android/src/main/java/com/customcamera/gif/GifSafety.kt +33 -0
- package/android/src/main/java/com/customcamera/gif/GiphyGifProvider.kt +146 -0
- package/android/src/main/java/com/customcamera/gif/LZWEncoder.kt +258 -0
- package/android/src/main/java/com/customcamera/gif/NeuQuant.kt +435 -0
- package/android/src/main/java/com/customcamera/gif/TenorGifProvider.kt +147 -0
- package/android/src/main/res/drawable/bg_brush_selected.xml +5 -0
- package/android/src/main/res/drawable/bg_color_swatch.xml +5 -0
- package/android/src/main/res/drawable/bg_editor_toolbar.xml +6 -0
- package/android/src/main/res/drawable/bg_icon_circle.xml +5 -0
- package/android/src/main/res/drawable/bg_icon_circle_light.xml +5 -0
- package/android/src/main/res/drawable/bg_mode_tab_active.xml +6 -0
- package/android/src/main/res/drawable/bg_pill.xml +6 -0
- package/android/src/main/res/drawable/bg_recording_dot.xml +6 -0
- package/android/src/main/res/drawable/bg_selection_badge.xml +8 -0
- package/android/src/main/res/drawable/bg_send_button.xml +5 -0
- package/android/src/main/res/drawable/bg_shutter_inner.xml +5 -0
- package/android/src/main/res/drawable/bg_shutter_recording.xml +6 -0
- package/android/src/main/res/drawable/bg_shutter_ring.xml +8 -0
- package/android/src/main/res/drawable/bg_shutter_video_idle.xml +5 -0
- package/android/src/main/res/drawable/bg_thumbnail.xml +9 -0
- package/android/src/main/res/drawable/ic_aspect_ratio.xml +17 -0
- package/android/src/main/res/drawable/ic_audio.xml +10 -0
- package/android/src/main/res/drawable/ic_back.xml +10 -0
- package/android/src/main/res/drawable/ic_brush_medium.xml +12 -0
- package/android/src/main/res/drawable/ic_brush_thick.xml +12 -0
- package/android/src/main/res/drawable/ic_brush_thin.xml +12 -0
- package/android/src/main/res/drawable/ic_check.xml +17 -0
- package/android/src/main/res/drawable/ic_chevron_down.xml +10 -0
- package/android/src/main/res/drawable/ic_chevron_up.xml +13 -0
- package/android/src/main/res/drawable/ic_clear_drawing.xml +10 -0
- package/android/src/main/res/drawable/ic_close.xml +10 -0
- package/android/src/main/res/drawable/ic_cover.xml +9 -0
- package/android/src/main/res/drawable/ic_crop.xml +10 -0
- package/android/src/main/res/drawable/ic_delete.xml +9 -0
- package/android/src/main/res/drawable/ic_document.xml +10 -0
- package/android/src/main/res/drawable/ic_done.xml +10 -0
- package/android/src/main/res/drawable/ic_download.xml +10 -0
- package/android/src/main/res/drawable/ic_emoji.xml +10 -0
- package/android/src/main/res/drawable/ic_filter.xml +10 -0
- package/android/src/main/res/drawable/ic_flash_auto.xml +7 -0
- package/android/src/main/res/drawable/ic_flash_off.xml +23 -0
- package/android/src/main/res/drawable/ic_flash_on.xml +16 -0
- package/android/src/main/res/drawable/ic_flip.xml +15 -0
- package/android/src/main/res/drawable/ic_gallery.xml +10 -0
- package/android/src/main/res/drawable/ic_gif.xml +24 -0
- package/android/src/main/res/drawable/ic_lock.xml +19 -0
- package/android/src/main/res/drawable/ic_lock_open.xml +22 -0
- package/android/src/main/res/drawable/ic_marker.xml +10 -0
- package/android/src/main/res/drawable/ic_more_vert.xml +18 -0
- package/android/src/main/res/drawable/ic_overlay_close.xml +19 -0
- package/android/src/main/res/drawable/ic_overlay_resize.xml +18 -0
- package/android/src/main/res/drawable/ic_pause.xml +10 -0
- package/android/src/main/res/drawable/ic_photo_mode.xml +10 -0
- package/android/src/main/res/drawable/ic_play.xml +10 -0
- package/android/src/main/res/drawable/ic_redo.xml +10 -0
- package/android/src/main/res/drawable/ic_rotate.xml +9 -0
- package/android/src/main/res/drawable/ic_send.xml +10 -0
- package/android/src/main/res/drawable/ic_share.xml +10 -0
- package/android/src/main/res/drawable/ic_stat_upload.xml +10 -0
- package/android/src/main/res/drawable/ic_sticker.xml +24 -0
- package/android/src/main/res/drawable/ic_text.xml +10 -0
- package/android/src/main/res/drawable/ic_text_align_center.xml +11 -0
- package/android/src/main/res/drawable/ic_text_align_left.xml +11 -0
- package/android/src/main/res/drawable/ic_text_align_right.xml +11 -0
- package/android/src/main/res/drawable/ic_text_bg.xml +11 -0
- package/android/src/main/res/drawable/ic_trim.xml +23 -0
- package/android/src/main/res/drawable/ic_undo.xml +10 -0
- package/android/src/main/res/drawable/ic_video_mode.xml +10 -0
- package/android/src/main/res/drawable/ic_video_note.xml +13 -0
- package/android/src/main/res/drawable/ic_volume_off.xml +9 -0
- package/android/src/main/res/drawable/ic_volume_on.xml +9 -0
- package/android/src/main/res/drawable/sticker_heart.xml +9 -0
- package/android/src/main/res/drawable/sticker_smile.xml +9 -0
- package/android/src/main/res/drawable/sticker_star.xml +9 -0
- package/android/src/main/res/drawable/sticker_thumbsup.xml +9 -0
- package/android/src/main/res/values/colors.xml +34 -0
- package/android/src/main/res/values/ids.xml +15 -0
- package/android/src/main/res/values/strings.xml +15 -0
- package/android/src/main/res/values/styles.xml +20 -0
- package/android/src/main/res/xml/file_paths.xml +34 -0
- package/ios/CustomCamera.h +5 -0
- package/ios/CustomCamera.mm +214 -0
- package/lib/module/AudioPlayerContext.js +233 -0
- package/lib/module/AudioPlayerContext.js.map +1 -0
- package/lib/module/CameraPreview.js +304 -0
- package/lib/module/CameraPreview.js.map +1 -0
- package/lib/module/NativeAnimatedImageView.js +41 -0
- package/lib/module/NativeAnimatedImageView.js.map +1 -0
- package/lib/module/NativeAudioPlayerView.js +33 -0
- package/lib/module/NativeAudioPlayerView.js.map +1 -0
- package/lib/module/NativeBlurView.js +35 -0
- package/lib/module/NativeBlurView.js.map +1 -0
- package/lib/module/NativeCustomCamera.js +128 -0
- package/lib/module/NativeCustomCamera.js.map +1 -0
- package/lib/module/NativeCustomCamera.web.js +143 -0
- package/lib/module/NativeCustomCamera.web.js.map +1 -0
- package/lib/module/NativeCustomVideoView.js +5 -0
- package/lib/module/NativeCustomVideoView.js.map +1 -0
- package/lib/module/NativeDocumentPreviewView.js +156 -0
- package/lib/module/NativeDocumentPreviewView.js.map +1 -0
- package/lib/module/NativeMediaThumbnailView.js +110 -0
- package/lib/module/NativeMediaThumbnailView.js.map +1 -0
- package/lib/module/NativeSvgIcon.js +32 -0
- package/lib/module/NativeSvgIcon.js.map +1 -0
- package/lib/module/ResponsivePreviewContainer.js +171 -0
- package/lib/module/ResponsivePreviewContainer.js.map +1 -0
- package/lib/module/accessibility.js +61 -0
- package/lib/module/accessibility.js.map +1 -0
- package/lib/module/config.js +352 -0
- package/lib/module/config.js.map +1 -0
- package/lib/module/cpuOptimization.js +296 -0
- package/lib/module/cpuOptimization.js.map +1 -0
- package/lib/module/db/DatabaseManager.js +191 -0
- package/lib/module/db/DatabaseManager.js.map +1 -0
- package/lib/module/db/MediaMapper.js +284 -0
- package/lib/module/db/MediaMapper.js.map +1 -0
- package/lib/module/db/MediaRepository.js +242 -0
- package/lib/module/db/MediaRepository.js.map +1 -0
- package/lib/module/db/index.js +41 -0
- package/lib/module/db/index.js.map +1 -0
- package/lib/module/db/migrations.js +180 -0
- package/lib/module/db/migrations.js.map +1 -0
- package/lib/module/db/react-native-sqlcipher.d.js +2 -0
- package/lib/module/db/react-native-sqlcipher.d.js.map +1 -0
- package/lib/module/db/secureKey.js +87 -0
- package/lib/module/db/secureKey.js.map +1 -0
- package/lib/module/db/types.js +57 -0
- package/lib/module/db/types.js.map +1 -0
- package/lib/module/db/useMediaDatabase.js +123 -0
- package/lib/module/db/useMediaDatabase.js.map +1 -0
- package/lib/module/defaultIcons.js +2259 -0
- package/lib/module/defaultIcons.js.map +1 -0
- package/lib/module/deviceCapabilities.js +408 -0
- package/lib/module/deviceCapabilities.js.map +1 -0
- package/lib/module/errors.js +267 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/iconConfig.js +796 -0
- package/lib/module/iconConfig.js.map +1 -0
- package/lib/module/icons.js +514 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +251 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/jest-globals.d.js +2 -0
- package/lib/module/jest-globals.d.js.map +1 -0
- package/lib/module/library/MediaLibrary.js +107 -0
- package/lib/module/library/MediaLibrary.js.map +1 -0
- package/lib/module/library/MediaLibraryScreen.js +2597 -0
- package/lib/module/library/MediaLibraryScreen.js.map +1 -0
- package/lib/module/library/components/AudioPreview.js +74 -0
- package/lib/module/library/components/AudioPreview.js.map +1 -0
- package/lib/module/library/components/DocumentPreview.js +331 -0
- package/lib/module/library/components/DocumentPreview.js.map +1 -0
- package/lib/module/library/components/ExpandableFab.js +343 -0
- package/lib/module/library/components/ExpandableFab.js.map +1 -0
- package/lib/module/library/components/FileTiles.js +251 -0
- package/lib/module/library/components/FileTiles.js.map +1 -0
- package/lib/module/library/components/ImagePreview.js +70 -0
- package/lib/module/library/components/ImagePreview.js.map +1 -0
- package/lib/module/library/components/MediaMetadataHeader.js +175 -0
- package/lib/module/library/components/MediaMetadataHeader.js.map +1 -0
- package/lib/module/library/components/RecordAudioScreen.js +816 -0
- package/lib/module/library/components/RecordAudioScreen.js.map +1 -0
- package/lib/module/library/components/VideoPreview.js +453 -0
- package/lib/module/library/components/VideoPreview.js.map +1 -0
- package/lib/module/library/components/ViewerCounter.js +55 -0
- package/lib/module/library/components/ViewerCounter.js.map +1 -0
- package/lib/module/library/compressionEstimate.js +507 -0
- package/lib/module/library/compressionEstimate.js.map +1 -0
- package/lib/module/library/fileMetadata.js +196 -0
- package/lib/module/library/fileMetadata.js.map +1 -0
- package/lib/module/library/index.js +42 -0
- package/lib/module/library/index.js.map +1 -0
- package/lib/module/library/libraryIconRegistry.js +69 -0
- package/lib/module/library/libraryIconRegistry.js.map +1 -0
- package/lib/module/library/libraryIcons.js +858 -0
- package/lib/module/library/libraryIcons.js.map +1 -0
- package/lib/module/library/localizedFormat.js +181 -0
- package/lib/module/library/localizedFormat.js.map +1 -0
- package/lib/module/library/palette.js +225 -0
- package/lib/module/library/palette.js.map +1 -0
- package/lib/module/library/responsive.js +53 -0
- package/lib/module/library/responsive.js.map +1 -0
- package/lib/module/locales.js +416 -0
- package/lib/module/locales.js.map +1 -0
- package/lib/module/localization.js +1064 -0
- package/lib/module/localization.js.map +1 -0
- package/lib/module/logger.js +20 -0
- package/lib/module/logger.js.map +1 -0
- package/lib/module/lowMemoryCache.js +206 -0
- package/lib/module/lowMemoryCache.js.map +1 -0
- package/lib/module/mediaHistory.js +33 -0
- package/lib/module/mediaHistory.js.map +1 -0
- package/lib/module/mediaStorageService.js +402 -0
- package/lib/module/mediaStorageService.js.map +1 -0
- package/lib/module/memory.js +79 -0
- package/lib/module/memory.js.map +1 -0
- package/lib/module/nativeActions.js +307 -0
- package/lib/module/nativeActions.js.map +1 -0
- package/lib/module/nativeComponentSupport.js +61 -0
- package/lib/module/nativeComponentSupport.js.map +1 -0
- package/lib/module/networkPerformance.js +24 -0
- package/lib/module/networkPerformance.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/performance.js +104 -0
- package/lib/module/performance.js.map +1 -0
- package/lib/module/performanceMonitor.js +155 -0
- package/lib/module/performanceMonitor.js.map +1 -0
- package/lib/module/permissions.js +370 -0
- package/lib/module/permissions.js.map +1 -0
- package/lib/module/rendering.js +40 -0
- package/lib/module/rendering.js.map +1 -0
- package/lib/module/security.js +18 -0
- package/lib/module/security.js.map +1 -0
- package/lib/module/state.js +266 -0
- package/lib/module/state.js.map +1 -0
- package/lib/module/storage.js +400 -0
- package/lib/module/storage.js.map +1 -0
- package/lib/module/theme.js +390 -0
- package/lib/module/theme.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils.js +115 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/module/validation.js +288 -0
- package/lib/module/validation.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioPlayerContext.d.ts +27 -0
- package/lib/typescript/src/AudioPlayerContext.d.ts.map +1 -0
- package/lib/typescript/src/CameraPreview.d.ts +13 -0
- package/lib/typescript/src/CameraPreview.d.ts.map +1 -0
- package/lib/typescript/src/NativeAnimatedImageView.d.ts +33 -0
- package/lib/typescript/src/NativeAnimatedImageView.d.ts.map +1 -0
- package/lib/typescript/src/NativeAudioPlayerView.d.ts +12 -0
- package/lib/typescript/src/NativeAudioPlayerView.d.ts.map +1 -0
- package/lib/typescript/src/NativeBlurView.d.ts +12 -0
- package/lib/typescript/src/NativeBlurView.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomCamera.d.ts +167 -0
- package/lib/typescript/src/NativeCustomCamera.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomCamera.web.d.ts +47 -0
- package/lib/typescript/src/NativeCustomCamera.web.d.ts.map +1 -0
- package/lib/typescript/src/NativeCustomVideoView.d.ts +30 -0
- package/lib/typescript/src/NativeCustomVideoView.d.ts.map +1 -0
- package/lib/typescript/src/NativeDocumentPreviewView.d.ts +48 -0
- package/lib/typescript/src/NativeDocumentPreviewView.d.ts.map +1 -0
- package/lib/typescript/src/NativeMediaThumbnailView.d.ts +54 -0
- package/lib/typescript/src/NativeMediaThumbnailView.d.ts.map +1 -0
- package/lib/typescript/src/NativeSvgIcon.d.ts +25 -0
- package/lib/typescript/src/NativeSvgIcon.d.ts.map +1 -0
- package/lib/typescript/src/ResponsivePreviewContainer.d.ts +92 -0
- package/lib/typescript/src/ResponsivePreviewContainer.d.ts.map +1 -0
- package/lib/typescript/src/accessibility.d.ts +20 -0
- package/lib/typescript/src/accessibility.d.ts.map +1 -0
- package/lib/typescript/src/config.d.ts +145 -0
- package/lib/typescript/src/config.d.ts.map +1 -0
- package/lib/typescript/src/cpuOptimization.d.ts +63 -0
- package/lib/typescript/src/cpuOptimization.d.ts.map +1 -0
- package/lib/typescript/src/db/DatabaseManager.d.ts +48 -0
- package/lib/typescript/src/db/DatabaseManager.d.ts.map +1 -0
- package/lib/typescript/src/db/MediaMapper.d.ts +77 -0
- package/lib/typescript/src/db/MediaMapper.d.ts.map +1 -0
- package/lib/typescript/src/db/MediaRepository.d.ts +66 -0
- package/lib/typescript/src/db/MediaRepository.d.ts.map +1 -0
- package/lib/typescript/src/db/index.d.ts +23 -0
- package/lib/typescript/src/db/index.d.ts.map +1 -0
- package/lib/typescript/src/db/migrations.d.ts +31 -0
- package/lib/typescript/src/db/migrations.d.ts.map +1 -0
- package/lib/typescript/src/db/secureKey.d.ts +10 -0
- package/lib/typescript/src/db/secureKey.d.ts.map +1 -0
- package/lib/typescript/src/db/types.d.ts +115 -0
- package/lib/typescript/src/db/types.d.ts.map +1 -0
- package/lib/typescript/src/db/useMediaDatabase.d.ts +41 -0
- package/lib/typescript/src/db/useMediaDatabase.d.ts.map +1 -0
- package/lib/typescript/src/defaultIcons.d.ts +139 -0
- package/lib/typescript/src/defaultIcons.d.ts.map +1 -0
- package/lib/typescript/src/deviceCapabilities.d.ts +92 -0
- package/lib/typescript/src/deviceCapabilities.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +95 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/iconConfig.d.ts +176 -0
- package/lib/typescript/src/iconConfig.d.ts.map +1 -0
- package/lib/typescript/src/icons.d.ts +217 -0
- package/lib/typescript/src/icons.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +104 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/library/MediaLibrary.d.ts +57 -0
- package/lib/typescript/src/library/MediaLibrary.d.ts.map +1 -0
- package/lib/typescript/src/library/MediaLibraryScreen.d.ts +51 -0
- package/lib/typescript/src/library/MediaLibraryScreen.d.ts.map +1 -0
- package/lib/typescript/src/library/components/AudioPreview.d.ts +6 -0
- package/lib/typescript/src/library/components/AudioPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/DocumentPreview.d.ts +10 -0
- package/lib/typescript/src/library/components/DocumentPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ExpandableFab.d.ts +39 -0
- package/lib/typescript/src/library/components/ExpandableFab.d.ts.map +1 -0
- package/lib/typescript/src/library/components/FileTiles.d.ts +8 -0
- package/lib/typescript/src/library/components/FileTiles.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ImagePreview.d.ts +5 -0
- package/lib/typescript/src/library/components/ImagePreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts +16 -0
- package/lib/typescript/src/library/components/MediaMetadataHeader.d.ts.map +1 -0
- package/lib/typescript/src/library/components/RecordAudioScreen.d.ts +8 -0
- package/lib/typescript/src/library/components/RecordAudioScreen.d.ts.map +1 -0
- package/lib/typescript/src/library/components/VideoPreview.d.ts +20 -0
- package/lib/typescript/src/library/components/VideoPreview.d.ts.map +1 -0
- package/lib/typescript/src/library/components/ViewerCounter.d.ts +13 -0
- package/lib/typescript/src/library/components/ViewerCounter.d.ts.map +1 -0
- package/lib/typescript/src/library/compressionEstimate.d.ts +313 -0
- package/lib/typescript/src/library/compressionEstimate.d.ts.map +1 -0
- package/lib/typescript/src/library/fileMetadata.d.ts +33 -0
- package/lib/typescript/src/library/fileMetadata.d.ts.map +1 -0
- package/lib/typescript/src/library/index.d.ts +40 -0
- package/lib/typescript/src/library/index.d.ts.map +1 -0
- package/lib/typescript/src/library/libraryIconRegistry.d.ts +35 -0
- package/lib/typescript/src/library/libraryIconRegistry.d.ts.map +1 -0
- package/lib/typescript/src/library/libraryIcons.d.ts +85 -0
- package/lib/typescript/src/library/libraryIcons.d.ts.map +1 -0
- package/lib/typescript/src/library/localizedFormat.d.ts +49 -0
- package/lib/typescript/src/library/localizedFormat.d.ts.map +1 -0
- package/lib/typescript/src/library/palette.d.ts +104 -0
- package/lib/typescript/src/library/palette.d.ts.map +1 -0
- package/lib/typescript/src/library/responsive.d.ts +15 -0
- package/lib/typescript/src/library/responsive.d.ts.map +1 -0
- package/lib/typescript/src/locales.d.ts +103 -0
- package/lib/typescript/src/locales.d.ts.map +1 -0
- package/lib/typescript/src/localization.d.ts +1051 -0
- package/lib/typescript/src/localization.d.ts.map +1 -0
- package/lib/typescript/src/logger.d.ts +4 -0
- package/lib/typescript/src/logger.d.ts.map +1 -0
- package/lib/typescript/src/lowMemoryCache.d.ts +64 -0
- package/lib/typescript/src/lowMemoryCache.d.ts.map +1 -0
- package/lib/typescript/src/mediaHistory.d.ts +3 -0
- package/lib/typescript/src/mediaHistory.d.ts.map +1 -0
- package/lib/typescript/src/mediaStorageService.d.ts +155 -0
- package/lib/typescript/src/mediaStorageService.d.ts.map +1 -0
- package/lib/typescript/src/memory.d.ts +21 -0
- package/lib/typescript/src/memory.d.ts.map +1 -0
- package/lib/typescript/src/nativeActions.d.ts +174 -0
- package/lib/typescript/src/nativeActions.d.ts.map +1 -0
- package/lib/typescript/src/nativeComponentSupport.d.ts +30 -0
- package/lib/typescript/src/nativeComponentSupport.d.ts.map +1 -0
- package/lib/typescript/src/networkPerformance.d.ts +12 -0
- package/lib/typescript/src/networkPerformance.d.ts.map +1 -0
- package/lib/typescript/src/performance.d.ts +32 -0
- package/lib/typescript/src/performance.d.ts.map +1 -0
- package/lib/typescript/src/performanceMonitor.d.ts +45 -0
- package/lib/typescript/src/performanceMonitor.d.ts.map +1 -0
- package/lib/typescript/src/permissions.d.ts +132 -0
- package/lib/typescript/src/permissions.d.ts.map +1 -0
- package/lib/typescript/src/rendering.d.ts +9 -0
- package/lib/typescript/src/rendering.d.ts.map +1 -0
- package/lib/typescript/src/security.d.ts +6 -0
- package/lib/typescript/src/security.d.ts.map +1 -0
- package/lib/typescript/src/state.d.ts +102 -0
- package/lib/typescript/src/state.d.ts.map +1 -0
- package/lib/typescript/src/storage.d.ts +117 -0
- package/lib/typescript/src/storage.d.ts.map +1 -0
- package/lib/typescript/src/theme.d.ts +15 -0
- package/lib/typescript/src/theme.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +802 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils.d.ts +50 -0
- package/lib/typescript/src/utils.d.ts.map +1 -0
- package/lib/typescript/src/validation.d.ts +52 -0
- package/lib/typescript/src/validation.d.ts.map +1 -0
- package/package.json +204 -0
- package/react-native.config.js +17 -0
- package/src/AudioPlayerContext.tsx +220 -0
- package/src/CameraPreview.tsx +352 -0
- package/src/NativeAnimatedImageView.tsx +71 -0
- package/src/NativeAudioPlayerView.tsx +39 -0
- package/src/NativeBlurView.tsx +40 -0
- package/src/NativeCustomCamera.ts +305 -0
- package/src/NativeCustomCamera.web.ts +192 -0
- package/src/NativeCustomVideoView.ts +30 -0
- package/src/NativeDocumentPreviewView.tsx +196 -0
- package/src/NativeMediaThumbnailView.tsx +167 -0
- package/src/NativeSvgIcon.tsx +46 -0
- package/src/ResponsivePreviewContainer.tsx +227 -0
- package/src/accessibility.ts +80 -0
- package/src/config.ts +406 -0
- package/src/cpuOptimization.ts +365 -0
- package/src/db/DatabaseManager.ts +212 -0
- package/src/db/MediaMapper.ts +377 -0
- package/src/db/MediaRepository.ts +313 -0
- package/src/db/index.ts +73 -0
- package/src/db/migrations.ts +222 -0
- package/src/db/react-native-sqlcipher.d.ts +76 -0
- package/src/db/secureKey.ts +100 -0
- package/src/db/types.ts +123 -0
- package/src/db/useMediaDatabase.ts +191 -0
- package/src/defaultIcons.tsx +2390 -0
- package/src/deviceCapabilities.ts +438 -0
- package/src/errors.ts +350 -0
- package/src/iconConfig.tsx +962 -0
- package/src/icons.tsx +788 -0
- package/src/index.tsx +763 -0
- package/src/jest-globals.d.ts +9 -0
- package/src/library/MediaLibrary.tsx +141 -0
- package/src/library/MediaLibraryScreen.tsx +3003 -0
- package/src/library/components/AudioPreview.tsx +73 -0
- package/src/library/components/DocumentPreview.tsx +361 -0
- package/src/library/components/ExpandableFab.tsx +342 -0
- package/src/library/components/FileTiles.tsx +252 -0
- package/src/library/components/ImagePreview.tsx +72 -0
- package/src/library/components/MediaMetadataHeader.tsx +208 -0
- package/src/library/components/RecordAudioScreen.tsx +845 -0
- package/src/library/components/VideoPreview.tsx +478 -0
- package/src/library/components/ViewerCounter.tsx +71 -0
- package/src/library/compressionEstimate.ts +662 -0
- package/src/library/fileMetadata.ts +212 -0
- package/src/library/index.ts +66 -0
- package/src/library/libraryIconRegistry.tsx +86 -0
- package/src/library/libraryIcons.tsx +928 -0
- package/src/library/localizedFormat.ts +207 -0
- package/src/library/palette.ts +281 -0
- package/src/library/responsive.ts +49 -0
- package/src/locales.ts +381 -0
- package/src/localization.ts +1947 -0
- package/src/logger.ts +20 -0
- package/src/lowMemoryCache.ts +218 -0
- package/src/mediaHistory.ts +42 -0
- package/src/mediaStorageService.ts +546 -0
- package/src/memory.ts +102 -0
- package/src/nativeActions.ts +422 -0
- package/src/nativeComponentSupport.ts +60 -0
- package/src/networkPerformance.ts +30 -0
- package/src/performance.ts +137 -0
- package/src/performanceMonitor.ts +219 -0
- package/src/permissions.ts +403 -0
- package/src/rendering.ts +47 -0
- package/src/security.ts +19 -0
- package/src/state.ts +333 -0
- package/src/storage.ts +453 -0
- package/src/theme.tsx +467 -0
- package/src/types.ts +946 -0
- package/src/utils.ts +177 -0
- package/src/validation.ts +372 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
package com.customcamera
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.BroadcastReceiver
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.content.IntentFilter
|
|
8
|
+
import android.content.pm.PackageManager
|
|
9
|
+
import android.graphics.Color
|
|
10
|
+
import android.graphics.drawable.GradientDrawable
|
|
11
|
+
import android.os.Bundle
|
|
12
|
+
import android.util.Log
|
|
13
|
+
import android.util.TypedValue
|
|
14
|
+
import android.view.Gravity
|
|
15
|
+
import android.view.View
|
|
16
|
+
import android.view.ViewGroup
|
|
17
|
+
import android.widget.FrameLayout
|
|
18
|
+
import android.widget.ImageButton
|
|
19
|
+
import android.widget.TextView
|
|
20
|
+
import androidx.activity.ComponentActivity
|
|
21
|
+
import androidx.annotation.OptIn
|
|
22
|
+
import androidx.camera.core.Camera
|
|
23
|
+
import androidx.camera.core.CameraSelector
|
|
24
|
+
import androidx.camera.core.ExperimentalGetImage
|
|
25
|
+
import androidx.camera.core.ImageAnalysis
|
|
26
|
+
import androidx.camera.core.ImageProxy
|
|
27
|
+
import androidx.camera.core.Preview
|
|
28
|
+
import androidx.camera.lifecycle.ProcessCameraProvider
|
|
29
|
+
import androidx.camera.view.PreviewView
|
|
30
|
+
import androidx.core.content.ContextCompat
|
|
31
|
+
import androidx.core.view.WindowCompat
|
|
32
|
+
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|
33
|
+
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
|
|
34
|
+
import com.google.mlkit.vision.barcode.BarcodeScanning
|
|
35
|
+
import com.google.mlkit.vision.barcode.common.Barcode
|
|
36
|
+
import com.google.mlkit.vision.common.InputImage
|
|
37
|
+
import java.util.concurrent.ExecutorService
|
|
38
|
+
import java.util.concurrent.Executors
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Full-screen barcode / QR scanner.
|
|
42
|
+
*
|
|
43
|
+
* Self-contained CameraX ([Preview] + [ImageAnalysis]) + ML Kit pipeline, intentionally kept
|
|
44
|
+
* separate from the 3274-line [CustomCameraActivity] so the capture screen is untouched. Returns
|
|
45
|
+
* the first decoded value via [EXTRA_RESULT_VALUE] (and its human-readable format via
|
|
46
|
+
* [EXTRA_RESULT_FORMAT]) using the standard Activity result contract; the owning
|
|
47
|
+
* [CustomCameraModule.scanQRCode] resolves its promise from onActivityResult.
|
|
48
|
+
*/
|
|
49
|
+
class BarcodeScannerActivity : ComponentActivity() {
|
|
50
|
+
|
|
51
|
+
private lateinit var previewView: PreviewView
|
|
52
|
+
// Rendered as a MONOCHROME bolt glyph (⚡ + U+FE0E text-presentation selector) in a TextView —
|
|
53
|
+
// not a color emoji — so setTextColor(WHITE) tints it white like the rest of the UI. The on/off
|
|
54
|
+
// state is shown via alpha in toggleTorch().
|
|
55
|
+
private lateinit var torchButton: TextView
|
|
56
|
+
private lateinit var cameraExecutor: ExecutorService
|
|
57
|
+
|
|
58
|
+
private var camera: Camera? = null
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Latches once the first barcode is delivered so a burst of successful frames can never call
|
|
62
|
+
* setResult()/finish() twice (which would leak a second result and, upstream, double-resolve
|
|
63
|
+
* the JS promise). Written and read only on the main thread (ML Kit success callbacks post
|
|
64
|
+
* there), but kept @Volatile as defensive documentation of the invariant.
|
|
65
|
+
*/
|
|
66
|
+
@Volatile
|
|
67
|
+
private var resultDelivered = false
|
|
68
|
+
private var torchOn = false
|
|
69
|
+
|
|
70
|
+
private val scanner by lazy {
|
|
71
|
+
BarcodeScanning.getClient(
|
|
72
|
+
BarcodeScannerOptions.Builder()
|
|
73
|
+
.setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
|
|
74
|
+
.build()
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private val localizers = mutableListOf<() -> Unit>()
|
|
79
|
+
|
|
80
|
+
private fun TextView.bindText(key: String, default: String, vararg args: Any) {
|
|
81
|
+
val updater = { this.text = Localization.getString(key, default, *args) }
|
|
82
|
+
updater()
|
|
83
|
+
localizers.add(updater)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private fun View.bindContentDescription(key: String, default: String, vararg args: Any) {
|
|
87
|
+
val updater = { this.contentDescription = Localization.getString(key, default, *args) }
|
|
88
|
+
updater()
|
|
89
|
+
localizers.add(updater)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private val localizationReceiver = object : BroadcastReceiver() {
|
|
93
|
+
override fun onReceive(context: Context?, intent: Intent?) {
|
|
94
|
+
window.decorView.rootView.layoutDirection = if (Localization.isRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR
|
|
95
|
+
localizers.forEach { it.invoke() }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
100
|
+
super.onCreate(savedInstanceState)
|
|
101
|
+
|
|
102
|
+
window.decorView.rootView.layoutDirection = if (Localization.isRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR
|
|
103
|
+
cameraExecutor = Executors.newSingleThreadExecutor()
|
|
104
|
+
setContentView(buildUi())
|
|
105
|
+
|
|
106
|
+
// Match the system bars to the scanner's own backdrop (dark by default, but host-overridable
|
|
107
|
+
// via components.barcodeScanner.background): transparent bars with a light/dark icon appearance
|
|
108
|
+
// picked from the resolved backdrop so the status/nav icons stay legible over it.
|
|
109
|
+
val scannerBackground = CameraTheme.get(this).componentColor("barcodeScanner", "background", Color.BLACK)
|
|
110
|
+
window.statusBarColor = Color.TRANSPARENT
|
|
111
|
+
window.navigationBarColor = Color.TRANSPARENT
|
|
112
|
+
val lightBars = !isColorDark(scannerBackground)
|
|
113
|
+
WindowCompat.getInsetsController(window, window.decorView).apply {
|
|
114
|
+
isAppearanceLightStatusBars = lightBars
|
|
115
|
+
isAppearanceLightNavigationBars = lightBars
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
LocalBroadcastManager.getInstance(this).registerReceiver(
|
|
119
|
+
localizationReceiver, IntentFilter(Localization.ACTION_LOCALIZATION_CHANGED)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if (hasCameraPermission()) {
|
|
123
|
+
startCamera()
|
|
124
|
+
} else {
|
|
125
|
+
requestPermissions(arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── UI ────────────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
private fun buildUi(): View {
|
|
132
|
+
val theme = CameraTheme.get(this)
|
|
133
|
+
val root = FrameLayout(this).apply {
|
|
134
|
+
layoutParams = ViewGroup.LayoutParams(MATCH, MATCH)
|
|
135
|
+
setBackgroundColor(theme.componentColor("barcodeScanner", "background", Color.BLACK))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
previewView = PreviewView(this).apply {
|
|
139
|
+
layoutParams = FrameLayout.LayoutParams(MATCH, MATCH)
|
|
140
|
+
}
|
|
141
|
+
root.addView(previewView)
|
|
142
|
+
|
|
143
|
+
// Minimal centered scan frame (transparent fill, rounded border).
|
|
144
|
+
val frameSize = dp(250)
|
|
145
|
+
val scanFrame = View(this).apply {
|
|
146
|
+
layoutParams = FrameLayout.LayoutParams(frameSize, frameSize, Gravity.CENTER)
|
|
147
|
+
background = GradientDrawable().apply {
|
|
148
|
+
setColor(Color.TRANSPARENT)
|
|
149
|
+
setStroke(dp(3), theme.componentColor("barcodeScanner", "frameBorder", Color.WHITE))
|
|
150
|
+
cornerRadius = dp(16).toFloat()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
root.addView(scanFrame)
|
|
154
|
+
|
|
155
|
+
val hint = TextView(this).apply {
|
|
156
|
+
layoutParams = FrameLayout.LayoutParams(WRAP, WRAP, Gravity.CENTER_HORIZONTAL).apply {
|
|
157
|
+
topMargin = dp(140)
|
|
158
|
+
}
|
|
159
|
+
bindText("pointCameraAtBarcode", "Point the camera at a QR code or barcode")
|
|
160
|
+
setTextColor(theme.componentColor("barcodeScanner", "hintText", Color.WHITE))
|
|
161
|
+
textSize = 14f
|
|
162
|
+
}
|
|
163
|
+
root.addView(hint)
|
|
164
|
+
|
|
165
|
+
val closeButton = ImageButton(this).apply {
|
|
166
|
+
layoutParams = FrameLayout.LayoutParams(dp(48), dp(48), Gravity.TOP or Gravity.START).apply {
|
|
167
|
+
topMargin = dp(40)
|
|
168
|
+
marginStart = dp(16)
|
|
169
|
+
}
|
|
170
|
+
setImageDrawable(theme.config.iconDrawable(this@BarcodeScannerActivity, "close", R.drawable.ic_close))
|
|
171
|
+
theme.config.iconTint("close")?.let { setColorFilter(it) }
|
|
172
|
+
background = circleBackground()
|
|
173
|
+
setPadding(dp(10), dp(10), dp(10), dp(10))
|
|
174
|
+
bindContentDescription("closeScanner", "Close scanner")
|
|
175
|
+
setOnClickListener { cancel() }
|
|
176
|
+
}
|
|
177
|
+
root.addView(closeButton)
|
|
178
|
+
|
|
179
|
+
torchButton = TextView(this).apply {
|
|
180
|
+
layoutParams = FrameLayout.LayoutParams(dp(48), dp(48), Gravity.TOP or Gravity.END).apply {
|
|
181
|
+
topMargin = dp(40)
|
|
182
|
+
marginEnd = dp(16)
|
|
183
|
+
}
|
|
184
|
+
text = "⚡︎"
|
|
185
|
+
gravity = Gravity.CENTER
|
|
186
|
+
includeFontPadding = false
|
|
187
|
+
setTextColor(theme.componentColor("barcodeScanner", "torchGlyph", Color.WHITE))
|
|
188
|
+
setTextSize(TypedValue.COMPLEX_UNIT_PX, dp(22).toFloat())
|
|
189
|
+
// Dimmed until the torch is switched on (see toggleTorch).
|
|
190
|
+
alpha = 0.4f
|
|
191
|
+
background = circleBackground()
|
|
192
|
+
bindContentDescription("toggleFlashlight", "Toggle flashlight")
|
|
193
|
+
setOnClickListener { toggleTorch() }
|
|
194
|
+
}
|
|
195
|
+
root.addView(torchButton)
|
|
196
|
+
|
|
197
|
+
return root
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private fun circleBackground(): GradientDrawable = GradientDrawable().apply {
|
|
201
|
+
shape = GradientDrawable.OVAL
|
|
202
|
+
setColor(
|
|
203
|
+
CameraTheme.get(this@BarcodeScannerActivity)
|
|
204
|
+
.componentColor("barcodeScanner", "buttonBackground", 0x66000000)
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private fun toggleTorch() {
|
|
209
|
+
val control = camera?.cameraControl ?: return
|
|
210
|
+
if (camera?.cameraInfo?.hasFlashUnit() != true) return
|
|
211
|
+
torchOn = !torchOn
|
|
212
|
+
control.enableTorch(torchOn)
|
|
213
|
+
// Bright when on, dimmed when off — the 🔦 glyph itself is unchanged.
|
|
214
|
+
torchButton.alpha = if (torchOn) 1f else 0.4f
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ── Camera + analysis ───────────────────────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
private fun startCamera() {
|
|
220
|
+
val providerFuture = ProcessCameraProvider.getInstance(this)
|
|
221
|
+
providerFuture.addListener(
|
|
222
|
+
{
|
|
223
|
+
// Not lifecycle-scoped: can fire after the user backed out. Binding a destroyed owner
|
|
224
|
+
// throws, so bail if we're already tearing down.
|
|
225
|
+
if (isFinishing || isDestroyed) return@addListener
|
|
226
|
+
try {
|
|
227
|
+
bindCamera(providerFuture.get())
|
|
228
|
+
} catch (e: Exception) {
|
|
229
|
+
Log.e(TAG, "Failed to start barcode scanner camera", e)
|
|
230
|
+
cancel()
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
ContextCompat.getMainExecutor(this)
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private fun bindCamera(provider: ProcessCameraProvider) {
|
|
238
|
+
val preview = Preview.Builder().build().also {
|
|
239
|
+
it.setSurfaceProvider(previewView.surfaceProvider)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
val analysis = ImageAnalysis.Builder()
|
|
243
|
+
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
|
244
|
+
.build()
|
|
245
|
+
.also { it.setAnalyzer(cameraExecutor) { proxy -> analyze(proxy) } }
|
|
246
|
+
|
|
247
|
+
// hasCamera() can throw CameraInfoUnavailableException, so probe it safely (mirrors
|
|
248
|
+
// CustomCameraActivity.hasCameraSafe) and prefer the back camera for scanning.
|
|
249
|
+
val hasBack = runCatching { provider.hasCamera(CameraSelector.DEFAULT_BACK_CAMERA) }.getOrDefault(false)
|
|
250
|
+
val selector =
|
|
251
|
+
if (hasBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA
|
|
252
|
+
|
|
253
|
+
provider.unbindAll()
|
|
254
|
+
camera = provider.bindToLifecycle(this, selector, preview, analysis)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@OptIn(ExperimentalGetImage::class)
|
|
258
|
+
private fun analyze(imageProxy: ImageProxy) {
|
|
259
|
+
if (resultDelivered) {
|
|
260
|
+
imageProxy.close()
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
val mediaImage = imageProxy.image
|
|
264
|
+
if (mediaImage == null) {
|
|
265
|
+
imageProxy.close()
|
|
266
|
+
return
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
val input = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
|
|
270
|
+
scanner.process(input)
|
|
271
|
+
.addOnSuccessListener { barcodes ->
|
|
272
|
+
val hit = barcodes.firstOrNull { !it.rawValue.isNullOrEmpty() }
|
|
273
|
+
if (hit != null && !resultDelivered) {
|
|
274
|
+
resultDelivered = true
|
|
275
|
+
deliverResult(hit.rawValue!!, formatName(hit.format))
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
.addOnFailureListener { e -> Log.w(TAG, "Barcode analysis failed", e) }
|
|
279
|
+
// MUST always close the proxy, or STRATEGY_KEEP_ONLY_LATEST stops delivering frames
|
|
280
|
+
// and scanning silently freezes.
|
|
281
|
+
.addOnCompleteListener { imageProxy.close() }
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
private fun deliverResult(value: String, format: String) {
|
|
285
|
+
runOnUiThread {
|
|
286
|
+
setResult(
|
|
287
|
+
RESULT_OK,
|
|
288
|
+
Intent()
|
|
289
|
+
.putExtra(EXTRA_RESULT_VALUE, value)
|
|
290
|
+
.putExtra(EXTRA_RESULT_FORMAT, format)
|
|
291
|
+
)
|
|
292
|
+
finish()
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private fun cancel() {
|
|
297
|
+
setResult(RESULT_CANCELED)
|
|
298
|
+
finish()
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ── Permissions ─────────────────────────────────────────────────────────────
|
|
302
|
+
|
|
303
|
+
private fun hasCameraPermission(): Boolean =
|
|
304
|
+
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ==
|
|
305
|
+
PackageManager.PERMISSION_GRANTED
|
|
306
|
+
|
|
307
|
+
override fun onRequestPermissionsResult(
|
|
308
|
+
requestCode: Int,
|
|
309
|
+
permissions: Array<String>,
|
|
310
|
+
grantResults: IntArray
|
|
311
|
+
) {
|
|
312
|
+
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
313
|
+
if (requestCode != PERMISSION_REQUEST) return
|
|
314
|
+
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
315
|
+
startCamera()
|
|
316
|
+
} else {
|
|
317
|
+
cancel()
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
override fun onDestroy() {
|
|
322
|
+
super.onDestroy()
|
|
323
|
+
LocalBroadcastManager.getInstance(this).unregisterReceiver(localizationReceiver)
|
|
324
|
+
if (::cameraExecutor.isInitialized) cameraExecutor.shutdown()
|
|
325
|
+
scanner.close()
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
329
|
+
|
|
330
|
+
private fun dp(value: Int): Int = (value * resources.displayMetrics.density).toInt()
|
|
331
|
+
|
|
332
|
+
private fun formatName(format: Int): String = when (format) {
|
|
333
|
+
Barcode.FORMAT_QR_CODE -> "QR_CODE"
|
|
334
|
+
Barcode.FORMAT_AZTEC -> "AZTEC"
|
|
335
|
+
Barcode.FORMAT_DATA_MATRIX -> "DATA_MATRIX"
|
|
336
|
+
Barcode.FORMAT_PDF417 -> "PDF417"
|
|
337
|
+
Barcode.FORMAT_EAN_13 -> "EAN_13"
|
|
338
|
+
Barcode.FORMAT_EAN_8 -> "EAN_8"
|
|
339
|
+
Barcode.FORMAT_UPC_A -> "UPC_A"
|
|
340
|
+
Barcode.FORMAT_UPC_E -> "UPC_E"
|
|
341
|
+
Barcode.FORMAT_CODE_128 -> "CODE_128"
|
|
342
|
+
Barcode.FORMAT_CODE_39 -> "CODE_39"
|
|
343
|
+
Barcode.FORMAT_CODE_93 -> "CODE_93"
|
|
344
|
+
Barcode.FORMAT_CODABAR -> "CODABAR"
|
|
345
|
+
Barcode.FORMAT_ITF -> "ITF"
|
|
346
|
+
else -> "UNKNOWN"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
companion object {
|
|
350
|
+
private const val TAG = "BarcodeScanner"
|
|
351
|
+
private const val PERMISSION_REQUEST = 9301
|
|
352
|
+
private val MATCH = ViewGroup.LayoutParams.MATCH_PARENT
|
|
353
|
+
private val WRAP = ViewGroup.LayoutParams.WRAP_CONTENT
|
|
354
|
+
|
|
355
|
+
const val EXTRA_RESULT_VALUE = "com.customcamera.extra.SCAN_VALUE"
|
|
356
|
+
const val EXTRA_RESULT_FORMAT = "com.customcamera.extra.SCAN_FORMAT"
|
|
357
|
+
|
|
358
|
+
fun createIntent(context: Context): Intent =
|
|
359
|
+
Intent(context, BarcodeScannerActivity::class.java)
|
|
360
|
+
}
|
|
361
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
package com.customcamera
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
import android.graphics.Canvas
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.widget.FrameLayout
|
|
7
|
+
import android.widget.ImageView
|
|
8
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
9
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
10
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
11
|
+
import kotlin.math.max
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* ViewManager for a native, dependency-free "frosted glass" backdrop used behind the
|
|
15
|
+
* expandable FAB menu.
|
|
16
|
+
*
|
|
17
|
+
* How it works (the "snapshot + downscale blur" strategy):
|
|
18
|
+
* 1. When [BlurBackgroundView.setActive] flips true, it takes a ONE-OFF snapshot of the
|
|
19
|
+
* Activity's content view (the media library sitting behind the menu) by drawing it into
|
|
20
|
+
* a heavily down-scaled [Bitmap]. Down-scaling is itself most of the blur and makes the
|
|
21
|
+
* subsequent work tiny.
|
|
22
|
+
* 2. A fast, pure-Kotlin separable box blur (no RenderScript, no RenderEffect, no library)
|
|
23
|
+
* softens the small bitmap. Because the bitmap is a fraction of screen size, this is cheap
|
|
24
|
+
* enough to stay smooth on low-end devices, and it works on every supported API level
|
|
25
|
+
* (min SDK 24) — unlike RenderEffect, which is API 31+.
|
|
26
|
+
* 3. The blurred bitmap is shown in a full-bleed [ImageView] and stretched back up. The
|
|
27
|
+
* surrounding React view fades it in/out, so the existing menu animation is preserved.
|
|
28
|
+
*
|
|
29
|
+
* Only the BACKGROUND is captured/blurred: the view hides ITSELF for the draw, and the menu
|
|
30
|
+
* items are still transparent at the instant the menu begins to open, so neither the blur
|
|
31
|
+
* layer nor the menu rows ever appear inside the blurred snapshot. The snapshot is static
|
|
32
|
+
* while the menu is open (the library underneath is not interactive then), so a single capture
|
|
33
|
+
* is both correct and efficient — no per-frame re-blurring.
|
|
34
|
+
*/
|
|
35
|
+
class BlurBackgroundViewManager : SimpleViewManager<BlurBackgroundView>() {
|
|
36
|
+
override fun getName() = "CustomBlurBackground"
|
|
37
|
+
|
|
38
|
+
override fun createViewInstance(reactContext: ThemedReactContext): BlurBackgroundView =
|
|
39
|
+
BlurBackgroundView(reactContext)
|
|
40
|
+
|
|
41
|
+
@ReactProp(name = "active", defaultBoolean = false)
|
|
42
|
+
fun setActive(view: BlurBackgroundView, active: Boolean) {
|
|
43
|
+
view.setActive(active)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@ReactProp(name = "blurRadius", defaultInt = 4)
|
|
47
|
+
fun setBlurRadius(view: BlurBackgroundView, radius: Int) {
|
|
48
|
+
view.blurRadius = radius.coerceIn(1, 25)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ReactProp(name = "downsampleFactor", defaultInt = 6)
|
|
52
|
+
fun setDownsampleFactor(view: BlurBackgroundView, factor: Int) {
|
|
53
|
+
view.downsampleFactor = factor.coerceIn(1, 16)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class BlurBackgroundView(private val reactContext: ThemedReactContext) : FrameLayout(reactContext) {
|
|
58
|
+
private val imageView = ImageView(reactContext).apply {
|
|
59
|
+
scaleType = ImageView.ScaleType.FIT_XY
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Down-sample divisor for the snapshot — higher = softer + cheaper. */
|
|
63
|
+
var downsampleFactor = 6
|
|
64
|
+
/** Box-blur radius applied to the down-sampled snapshot. */
|
|
65
|
+
var blurRadius = 4
|
|
66
|
+
|
|
67
|
+
private var active = false
|
|
68
|
+
|
|
69
|
+
init {
|
|
70
|
+
addView(
|
|
71
|
+
imageView,
|
|
72
|
+
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun setActive(next: Boolean) {
|
|
77
|
+
if (next == active) return
|
|
78
|
+
active = next
|
|
79
|
+
if (active) {
|
|
80
|
+
// Defer to the next frame so the view is measured/laid out and the background
|
|
81
|
+
// content behind it is fully drawn before we snapshot it.
|
|
82
|
+
post { if (active) captureAndBlur() }
|
|
83
|
+
} else {
|
|
84
|
+
imageView.setImageBitmap(null)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
89
|
+
super.onSizeChanged(w, h, oldw, oldh)
|
|
90
|
+
// Keep the frosted backdrop correct after a rotation / resize while it is showing.
|
|
91
|
+
if (active && w > 0 && h > 0) post { if (active) captureAndBlur() }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private fun captureAndBlur() {
|
|
95
|
+
val source: View =
|
|
96
|
+
reactContext.currentActivity?.findViewById(android.R.id.content) ?: rootView ?: return
|
|
97
|
+
val srcW = source.width
|
|
98
|
+
val srcH = source.height
|
|
99
|
+
if (srcW <= 0 || srcH <= 0) return
|
|
100
|
+
|
|
101
|
+
val factor = max(1, downsampleFactor)
|
|
102
|
+
val bmpW = max(1, srcW / factor)
|
|
103
|
+
val bmpH = max(1, srcH / factor)
|
|
104
|
+
|
|
105
|
+
val bitmap =
|
|
106
|
+
try {
|
|
107
|
+
Bitmap.createBitmap(bmpW, bmpH, Bitmap.Config.ARGB_8888)
|
|
108
|
+
} catch (e: OutOfMemoryError) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
val canvas = Canvas(bitmap)
|
|
112
|
+
val scale = 1f / factor
|
|
113
|
+
canvas.scale(scale, scale)
|
|
114
|
+
|
|
115
|
+
// Exclude our own (currently transparent) blur layer from the snapshot so we never
|
|
116
|
+
// capture a previous frame of the blur, then restore visibility immediately after.
|
|
117
|
+
val prevVisibility = visibility
|
|
118
|
+
visibility = View.INVISIBLE
|
|
119
|
+
try {
|
|
120
|
+
source.draw(canvas)
|
|
121
|
+
} catch (e: Exception) {
|
|
122
|
+
visibility = prevVisibility
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
visibility = prevVisibility
|
|
126
|
+
|
|
127
|
+
boxBlur(bitmap, blurRadius)
|
|
128
|
+
imageView.setImageBitmap(bitmap)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* In-place separable box blur (two axes, run twice for a smoother, Gaussian-like falloff).
|
|
133
|
+
* Operates on the raw ARGB pixel array of a small, down-sampled bitmap, so it is O(pixels)
|
|
134
|
+
* and stays fast on low-end hardware. Alpha is preserved; only RGB channels are averaged.
|
|
135
|
+
*/
|
|
136
|
+
private fun boxBlur(bitmap: Bitmap, radius: Int) {
|
|
137
|
+
if (radius < 1) return
|
|
138
|
+
val w = bitmap.width
|
|
139
|
+
val h = bitmap.height
|
|
140
|
+
if (w <= 0 || h <= 0) return
|
|
141
|
+
|
|
142
|
+
val pixels = IntArray(w * h)
|
|
143
|
+
bitmap.getPixels(pixels, 0, w, 0, 0, w, h)
|
|
144
|
+
|
|
145
|
+
// Two iterations approximate a Gaussian blur well enough for a frosted backdrop.
|
|
146
|
+
repeat(2) {
|
|
147
|
+
blurAxis(pixels, w, h, radius, horizontal = true)
|
|
148
|
+
blurAxis(pixels, w, h, radius, horizontal = false)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
bitmap.setPixels(pixels, 0, w, 0, 0, w, h)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private fun blurAxis(pixels: IntArray, w: Int, h: Int, radius: Int, horizontal: Boolean) {
|
|
155
|
+
val lineCount = if (horizontal) h else w
|
|
156
|
+
val lineLength = if (horizontal) w else h
|
|
157
|
+
if (lineLength <= 1) return
|
|
158
|
+
val window = radius * 2 + 1
|
|
159
|
+
val scratch = IntArray(lineLength)
|
|
160
|
+
|
|
161
|
+
for (line in 0 until lineCount) {
|
|
162
|
+
// Prime the sliding window over the first `radius+1` samples (clamped at the edge).
|
|
163
|
+
var sumR = 0
|
|
164
|
+
var sumG = 0
|
|
165
|
+
var sumB = 0
|
|
166
|
+
for (i in -radius..radius) {
|
|
167
|
+
val idx = indexOf(line, i.coerceIn(0, lineLength - 1), w, horizontal)
|
|
168
|
+
val c = pixels[idx]
|
|
169
|
+
sumR += (c ushr 16) and 0xFF
|
|
170
|
+
sumG += (c ushr 8) and 0xFF
|
|
171
|
+
sumB += c and 0xFF
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (pos in 0 until lineLength) {
|
|
175
|
+
scratch[pos] = (0xFF shl 24) or
|
|
176
|
+
((sumR / window) shl 16) or
|
|
177
|
+
((sumG / window) shl 8) or
|
|
178
|
+
(sumB / window)
|
|
179
|
+
|
|
180
|
+
// Slide the window forward: drop the trailing sample, add the leading one.
|
|
181
|
+
val trailing = (pos - radius).coerceIn(0, lineLength - 1)
|
|
182
|
+
val leading = (pos + radius + 1).coerceIn(0, lineLength - 1)
|
|
183
|
+
val cOut = pixels[indexOf(line, trailing, w, horizontal)]
|
|
184
|
+
val cIn = pixels[indexOf(line, leading, w, horizontal)]
|
|
185
|
+
sumR += ((cIn ushr 16) and 0xFF) - ((cOut ushr 16) and 0xFF)
|
|
186
|
+
sumG += ((cIn ushr 8) and 0xFF) - ((cOut ushr 8) and 0xFF)
|
|
187
|
+
sumB += (cIn and 0xFF) - (cOut and 0xFF)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Write the blurred line back into the shared buffer.
|
|
191
|
+
for (pos in 0 until lineLength) {
|
|
192
|
+
pixels[indexOf(line, pos, w, horizontal)] = scratch[pos]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private fun indexOf(line: Int, pos: Int, w: Int, horizontal: Boolean): Int =
|
|
198
|
+
if (horizontal) line * w + pos else pos * w + line
|
|
199
|
+
}
|