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,163 @@
|
|
|
1
|
+
package com.customcamera
|
|
2
|
+
|
|
3
|
+
import android.os.Build
|
|
4
|
+
import java.util.Locale
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Single source of truth for "which still-image container is this, and what can this device
|
|
8
|
+
* do with it".
|
|
9
|
+
*
|
|
10
|
+
* Before this existed, four tables answered overlapping halves of the same question and drifted
|
|
11
|
+
* apart: [MediaCacheManager.MediaFormat], [MediaPublisher]'s publish-time MIME mapping,
|
|
12
|
+
* [MediaPreviewEditor]'s save-to-gallery extension, and [ThumbnailLoader]'s alpha-capable set.
|
|
13
|
+
* A format added to one but not the others is exactly how HEIF/AVIF ended up being cached as
|
|
14
|
+
* `.jpg`, published as `image/jpeg`, and decoded into an alpha-less config. Those call sites now
|
|
15
|
+
* all read from here, so a format is supported everywhere or nowhere.
|
|
16
|
+
*
|
|
17
|
+
* Detection deliberately uses BOTH signals the platform gives us — the declared MIME type first,
|
|
18
|
+
* the file extension second — because MediaStore rows written by other apps routinely carry one
|
|
19
|
+
* without the other. [GifSupport] keeps its own GIF-specific entry point (animation detection has
|
|
20
|
+
* no analogue for these formats) but follows the same precedence, so the two never disagree.
|
|
21
|
+
*/
|
|
22
|
+
object ImageFormatSupport {
|
|
23
|
+
/**
|
|
24
|
+
* A still-image container this library understands end to end: it can be discovered, decoded
|
|
25
|
+
* to a thumbnail, cached, previewed, edited and published without ever being renamed to
|
|
26
|
+
* something it is not.
|
|
27
|
+
*
|
|
28
|
+
* [minSdk] is the API level whose *platform decoders* gained the format. Below it the file is
|
|
29
|
+
* still a first-class asset — it is listed, selected, cached and sent byte-for-byte — only its
|
|
30
|
+
* pixels cannot be rendered locally, which is what [isDecodable] exists to tell callers.
|
|
31
|
+
*/
|
|
32
|
+
enum class Format(
|
|
33
|
+
val extension: String,
|
|
34
|
+
val mimeType: String,
|
|
35
|
+
val alternateMimeTypes: Set<String> = emptySet(),
|
|
36
|
+
val alternateExtensions: Set<String> = emptySet(),
|
|
37
|
+
val mayHaveAlpha: Boolean = false,
|
|
38
|
+
val minSdk: Int = Build.VERSION_CODES.BASE
|
|
39
|
+
) {
|
|
40
|
+
JPEG("jpg", "image/jpeg", alternateExtensions = setOf("jpeg")),
|
|
41
|
+
PNG("png", "image/png", mayHaveAlpha = true),
|
|
42
|
+
WEBP("webp", "image/webp", mayHaveAlpha = true),
|
|
43
|
+
GIF("gif", "image/gif", mayHaveAlpha = true),
|
|
44
|
+
BMP("bmp", "image/bmp"),
|
|
45
|
+
PDF("pdf", "application/pdf"),
|
|
46
|
+
|
|
47
|
+
// HEIF and HEIC are the same underlying container, but they are kept as separate entries
|
|
48
|
+
// rather than aliases so each keeps its OWN name. Collapsing them would rename every
|
|
49
|
+
// `image/heic` file (what every iPhone produces) to `.heif` on its way into the cache —
|
|
50
|
+
// the exact class of "the name no longer describes the bytes" bug this registry exists to
|
|
51
|
+
// prevent. They share decodability and alpha capability because the container is the same.
|
|
52
|
+
HEIF(
|
|
53
|
+
"heif",
|
|
54
|
+
"image/heif",
|
|
55
|
+
alternateMimeTypes = setOf("image/heif-sequence"),
|
|
56
|
+
alternateExtensions = setOf("hif"),
|
|
57
|
+
mayHaveAlpha = true,
|
|
58
|
+
minSdk = Build.VERSION_CODES.P
|
|
59
|
+
),
|
|
60
|
+
HEIC(
|
|
61
|
+
"heic",
|
|
62
|
+
"image/heic",
|
|
63
|
+
alternateMimeTypes = setOf("image/heic-sequence"),
|
|
64
|
+
mayHaveAlpha = true,
|
|
65
|
+
minSdk = Build.VERSION_CODES.P
|
|
66
|
+
),
|
|
67
|
+
|
|
68
|
+
// AVIF decoding is platform-provided from Android 12 (API 31). `image/avif` is the
|
|
69
|
+
// registered type; `.avifs` is the animated-sequence extension and shares the container.
|
|
70
|
+
AVIF(
|
|
71
|
+
"avif",
|
|
72
|
+
"image/avif",
|
|
73
|
+
alternateExtensions = setOf("avifs"),
|
|
74
|
+
mayHaveAlpha = true,
|
|
75
|
+
minSdk = Build.VERSION_CODES.S
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/** Every MIME spelling that identifies this container. */
|
|
79
|
+
val mimeTypes: Set<String> get() = alternateMimeTypes + mimeType
|
|
80
|
+
|
|
81
|
+
/** Every file extension that identifies this container, without the leading dot. */
|
|
82
|
+
val extensions: Set<String> get() = alternateExtensions + extension
|
|
83
|
+
|
|
84
|
+
/** The extension with its leading dot, for building file names. */
|
|
85
|
+
val dottedExtension: String get() = ".$extension"
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Whether THIS device can turn the bytes into pixels. False only for HEIF below API 28 and
|
|
89
|
+
* AVIF below API 31 — see [Format.minSdk]. Callers use this to fall back to a placeholder
|
|
90
|
+
* instead of showing a black or empty tile.
|
|
91
|
+
*/
|
|
92
|
+
val isDecodable: Boolean get() = Build.VERSION.SDK_INT >= minSdk
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private val BY_MIME: Map<String, Format> =
|
|
96
|
+
Format.entries.flatMap { format -> format.mimeTypes.map { it to format } }.toMap()
|
|
97
|
+
|
|
98
|
+
private val BY_EXTENSION: Map<String, Format> =
|
|
99
|
+
Format.entries.flatMap { format -> format.extensions.map { it to format } }.toMap()
|
|
100
|
+
|
|
101
|
+
/** The format [mimeType] names, or null if it is absent or not a container we handle. */
|
|
102
|
+
fun fromMimeType(mimeType: String?): Format? =
|
|
103
|
+
mimeType?.lowercase(Locale.US)?.substringBefore(';')?.trim()?.let { BY_MIME[it] }
|
|
104
|
+
|
|
105
|
+
/** The format the extension of [name] (a file name, path or URI) names, or null. */
|
|
106
|
+
fun fromFileName(name: String?): Format? = extensionOf(name)?.let { BY_EXTENSION[it] }
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Resolve the format of an asset from its declared MIME type first, then its file name /
|
|
110
|
+
* cache path / URI path.
|
|
111
|
+
*
|
|
112
|
+
* A declared, recognised `image/` type is authoritative: an asset that says it is
|
|
113
|
+
* `image/jpeg` is not reclassified because something in its path ends in `.png`. Only an
|
|
114
|
+
* absent or unrecognised type falls through to the extension — which is what rescues the
|
|
115
|
+
* many MediaStore rows and SAF documents that arrive with no MIME type at all.
|
|
116
|
+
*
|
|
117
|
+
* (Written `image/` rather than with a trailing wildcard on purpose: Kotlin block comments
|
|
118
|
+
* NEST, so a literal slash-star inside a KDoc opens a comment that is never closed and
|
|
119
|
+
* silently swallows the rest of the file. GifSupport's KDoc avoids it the same way.)
|
|
120
|
+
*/
|
|
121
|
+
fun of(asset: CameraAsset): Format? {
|
|
122
|
+
fromMimeType(asset.mimeType)?.let { return it }
|
|
123
|
+
// An unrecognised but declared image type (e.g. image/x-adobe-dng) is a real image we
|
|
124
|
+
// simply do not special-case; do NOT let a misleading path extension override it.
|
|
125
|
+
if (asset.mimeType?.lowercase(Locale.US)?.startsWith("image/") == true) return null
|
|
126
|
+
return fromFileName(asset.fileName ?: asset.cachePath ?: asset.uri.path)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* True when [mimeType] denotes any still image, including containers this registry does not
|
|
131
|
+
* enumerate. Used to widen MediaStore discovery: a row whose MEDIA_TYPE is wrong but whose
|
|
132
|
+
* MIME type says `image/…` is still an image the user expects to see.
|
|
133
|
+
*/
|
|
134
|
+
fun isImageMimeType(mimeType: String?): Boolean =
|
|
135
|
+
mimeType?.lowercase(Locale.US)?.startsWith("image/") == true
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* True when this asset's container can carry per-pixel transparency, and so must not be
|
|
139
|
+
* decoded into RGB_565 (which would replace transparency with solid black).
|
|
140
|
+
*
|
|
141
|
+
* An unrecognised container answers false: RGB_565 is only ever an optimisation for known
|
|
142
|
+
* opaque formats, and JPEG — every camera capture and every extracted cover frame — is the
|
|
143
|
+
* overwhelmingly common case.
|
|
144
|
+
*/
|
|
145
|
+
fun mayHaveAlpha(asset: CameraAsset): Boolean = of(asset)?.mayHaveAlpha == true
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Whether this device's platform decoders can render [asset]'s pixels. Unknown/unlisted
|
|
149
|
+
* containers answer true — BitmapFactory supports more than this registry enumerates, and
|
|
150
|
+
* refusing to try would regress formats that work today.
|
|
151
|
+
*/
|
|
152
|
+
fun isDecodable(asset: CameraAsset): Boolean = of(asset)?.isDecodable ?: true
|
|
153
|
+
|
|
154
|
+
/** The lower-cased extension of [name] without its dot, or null when it has none. */
|
|
155
|
+
private fun extensionOf(name: String?): String? {
|
|
156
|
+
if (name.isNullOrEmpty()) return null
|
|
157
|
+
// Strip any query/fragment so `…/file.avif?token=…` still resolves.
|
|
158
|
+
val path = name.substringBefore('?').substringBefore('#')
|
|
159
|
+
val segment = path.substringAfterLast('/', path)
|
|
160
|
+
val extension = segment.substringAfterLast('.', "")
|
|
161
|
+
return extension.lowercase(Locale.US).takeIf { it.isNotEmpty() }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
package com.customcamera
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.widget.TextView
|
|
7
|
+
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|
8
|
+
import org.json.JSONObject
|
|
9
|
+
import java.util.Locale
|
|
10
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Every user-facing string, the text direction, and the active language for the
|
|
14
|
+
* native camera screens.
|
|
15
|
+
*
|
|
16
|
+
* The host app owns all of it. React Native pushes a flat key -> string map plus
|
|
17
|
+
* the active locale through `CustomCameraModule.setLocalization`; this object
|
|
18
|
+
* persists them so an Activity launched cold is already translated, and
|
|
19
|
+
* broadcasts [ACTION_LOCALIZATION_CHANGED] so screens that are already open
|
|
20
|
+
* re-render without a restart.
|
|
21
|
+
*
|
|
22
|
+
* The plugin never picks a language itself and ships no per-language resources:
|
|
23
|
+
* a missing key falls back to the English default passed at the call site.
|
|
24
|
+
*/
|
|
25
|
+
object Localization {
|
|
26
|
+
const val ACTION_LOCALIZATION_CHANGED = "com.customcamera.LOCALIZATION_CHANGED"
|
|
27
|
+
|
|
28
|
+
private const val PREFS_NAME = "CameraLocalization"
|
|
29
|
+
private const val KEY_TRANSLATIONS = "translations"
|
|
30
|
+
private const val KEY_IS_RTL = "isRtl"
|
|
31
|
+
private const val KEY_LOCALE = "locale"
|
|
32
|
+
|
|
33
|
+
private val translations = ConcurrentHashMap<String, String>()
|
|
34
|
+
|
|
35
|
+
var isRtl: Boolean = false
|
|
36
|
+
private set
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The host app's active language as a BCP-47 tag ("fr", "pt-BR", "zh-Hans",
|
|
40
|
+
* "ar"), or empty when the host has not told us. Empty means "use the
|
|
41
|
+
* device locale", which is the best guess available.
|
|
42
|
+
*/
|
|
43
|
+
var localeTag: String = ""
|
|
44
|
+
private set
|
|
45
|
+
|
|
46
|
+
@Volatile
|
|
47
|
+
private var resolvedLocale: Locale = Locale.getDefault()
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The locale to format user-facing dates, file sizes and durations with, so
|
|
51
|
+
* that a Japanese UI does not show English month names and a French UI gets
|
|
52
|
+
* a comma decimal separator.
|
|
53
|
+
*
|
|
54
|
+
* Never use this to normalise machine-readable text (MIME types, file
|
|
55
|
+
* extensions, cache keys) — those must stay [Locale.US] or the Turkish
|
|
56
|
+
* dotless-i turns "IMAGE/JPEG" into something that no longer matches.
|
|
57
|
+
*/
|
|
58
|
+
val locale: Locale
|
|
59
|
+
get() = resolvedLocale
|
|
60
|
+
|
|
61
|
+
fun init(context: Context) {
|
|
62
|
+
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
63
|
+
val jsonString = prefs.getString(KEY_TRANSLATIONS, "{}") ?: "{}"
|
|
64
|
+
isRtl = prefs.getBoolean(KEY_IS_RTL, false)
|
|
65
|
+
applyLocaleTag(prefs.getString(KEY_LOCALE, "") ?: "")
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
val jsonObject = JSONObject(jsonString)
|
|
69
|
+
translations.clear()
|
|
70
|
+
val keys = jsonObject.keys()
|
|
71
|
+
while (keys.hasNext()) {
|
|
72
|
+
val key = keys.next()
|
|
73
|
+
translations[key] = jsonObject.getString(key)
|
|
74
|
+
}
|
|
75
|
+
} catch (e: Exception) {
|
|
76
|
+
// Ignore parsing errors, fall back to defaults
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
fun setTranslations(
|
|
81
|
+
context: Context,
|
|
82
|
+
map: Map<String, String>,
|
|
83
|
+
rtl: Boolean,
|
|
84
|
+
localeTag: String = "",
|
|
85
|
+
) {
|
|
86
|
+
translations.clear()
|
|
87
|
+
translations.putAll(map)
|
|
88
|
+
isRtl = rtl
|
|
89
|
+
applyLocaleTag(localeTag)
|
|
90
|
+
|
|
91
|
+
val jsonObject = JSONObject()
|
|
92
|
+
for ((key, value) in map) {
|
|
93
|
+
jsonObject.put(key, value)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
97
|
+
.edit()
|
|
98
|
+
.putString(KEY_TRANSLATIONS, jsonObject.toString())
|
|
99
|
+
.putBoolean(KEY_IS_RTL, rtl)
|
|
100
|
+
.putString(KEY_LOCALE, this.localeTag)
|
|
101
|
+
.apply()
|
|
102
|
+
|
|
103
|
+
// Invalidate caches dependent on localization
|
|
104
|
+
EmojiPickerData.invalidateCache()
|
|
105
|
+
StickerPickerData.invalidateCache()
|
|
106
|
+
|
|
107
|
+
LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(ACTION_LOCALIZATION_CHANGED))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fun getString(key: String, default: String, vararg args: Any): String {
|
|
111
|
+
var text = translations[key] ?: default
|
|
112
|
+
args.forEachIndexed { index, arg ->
|
|
113
|
+
text = text.replace("{$index}", arg.toString())
|
|
114
|
+
}
|
|
115
|
+
return text
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* [String.format] in the host app's language, for anything the user reads.
|
|
120
|
+
*
|
|
121
|
+
* Use instead of a bare `String.format` or a hardcoded [Locale.US]: it is
|
|
122
|
+
* what makes "1.5 MB" render as "1,5 MB" in French and switches digits in
|
|
123
|
+
* locales that use their own numerals.
|
|
124
|
+
*/
|
|
125
|
+
fun format(format: String, vararg args: Any?): String =
|
|
126
|
+
String.format(locale, format, *args)
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* A measurement and its unit, both localized: the number picks up the host
|
|
130
|
+
* locale's digits and decimal separator, the unit comes from [unitKey] so a
|
|
131
|
+
* language that does not abbreviate "MB" as "MB" can override it.
|
|
132
|
+
*
|
|
133
|
+
* @param numberFormat a [String.format] spec for the number alone, e.g. `"%.1f"`.
|
|
134
|
+
*/
|
|
135
|
+
fun formatUnit(unitKey: String, default: String, numberFormat: String, value: Double): String =
|
|
136
|
+
getString(unitKey, default, format(numberFormat, value))
|
|
137
|
+
|
|
138
|
+
/** [formatUnit] for a whole number, e.g. a raw byte count. */
|
|
139
|
+
fun formatUnit(unitKey: String, default: String, value: Long): String =
|
|
140
|
+
getString(unitKey, default, format("%d", value))
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A [SimpleDateFormat] over the active language, using the host-overridable
|
|
144
|
+
* `dateFormatPattern` key. Month and weekday names follow [locale], so the
|
|
145
|
+
* pattern only needs overriding to change field order.
|
|
146
|
+
*/
|
|
147
|
+
fun dateFormatter(): java.text.SimpleDateFormat =
|
|
148
|
+
java.text.SimpleDateFormat(
|
|
149
|
+
getString("dateFormatPattern", "MMM dd, yyyy"),
|
|
150
|
+
locale,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
/** [View.LAYOUT_DIRECTION_RTL] or [View.LAYOUT_DIRECTION_LTR] for the active language. */
|
|
154
|
+
val layoutDirection: Int
|
|
155
|
+
get() = if (isRtl) View.LAYOUT_DIRECTION_RTL else View.LAYOUT_DIRECTION_LTR
|
|
156
|
+
|
|
157
|
+
/** Mirrors a view subtree to match the active language's direction. */
|
|
158
|
+
fun applyLayoutDirection(view: View?) {
|
|
159
|
+
view?.layoutDirection = layoutDirection
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Mirrors a dialog to match the active language's direction.
|
|
164
|
+
*
|
|
165
|
+
* A dialog lives in its OWN window, and that window's decor view has no
|
|
166
|
+
* parent to inherit from — Android resolves its direction from
|
|
167
|
+
* `Locale.getDefault()`, i.e. the DEVICE language. So the direction set on
|
|
168
|
+
* the activity's root view does not reach it: an Arabic dialog on an
|
|
169
|
+
* English device would lay its title, message and buttons out
|
|
170
|
+
* left-to-right while the screen behind it is mirrored.
|
|
171
|
+
*
|
|
172
|
+
* Call this AFTER `show()` — the decor view does not exist before that.
|
|
173
|
+
*/
|
|
174
|
+
fun applyDialogDirection(dialog: android.app.Dialog?) {
|
|
175
|
+
applyLayoutDirection(dialog?.window?.decorView)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Aligns text to the reading direction and lets the paragraph itself be
|
|
180
|
+
* mirrored, which matters for labels that mix Arabic with Latin file names.
|
|
181
|
+
*/
|
|
182
|
+
fun applyTextDirection(view: TextView?) {
|
|
183
|
+
val target = view ?: return
|
|
184
|
+
target.textDirection =
|
|
185
|
+
if (isRtl) View.TEXT_DIRECTION_RTL else View.TEXT_DIRECTION_LTR
|
|
186
|
+
target.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private fun applyLocaleTag(tag: String) {
|
|
190
|
+
val trimmed = tag.trim()
|
|
191
|
+
localeTag = trimmed
|
|
192
|
+
resolvedLocale =
|
|
193
|
+
if (trimmed.isEmpty()) {
|
|
194
|
+
Locale.getDefault()
|
|
195
|
+
} else {
|
|
196
|
+
try {
|
|
197
|
+
// Accepts "fr", "pt-BR" and "zh-Hans"; underscores are the
|
|
198
|
+
// one spelling forLanguageTag rejects, so normalise them.
|
|
199
|
+
val parsed = Locale.forLanguageTag(trimmed.replace('_', '-'))
|
|
200
|
+
if (parsed.language.isEmpty()) Locale.getDefault() else parsed
|
|
201
|
+
} catch (e: Exception) {
|
|
202
|
+
Locale.getDefault()
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|