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,553 @@
|
|
|
1
|
+
package com.customcamera
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.graphics.Rect
|
|
5
|
+
import android.graphics.Typeface
|
|
6
|
+
import android.graphics.drawable.GradientDrawable
|
|
7
|
+
import android.text.Layout
|
|
8
|
+
import android.util.TypedValue
|
|
9
|
+
import android.view.Gravity
|
|
10
|
+
import android.view.KeyEvent
|
|
11
|
+
import android.view.View
|
|
12
|
+
import android.view.ViewGroup
|
|
13
|
+
import android.view.ViewTreeObserver
|
|
14
|
+
import android.view.inputmethod.EditorInfo
|
|
15
|
+
import android.view.inputmethod.InputMethodManager
|
|
16
|
+
import android.widget.EditText
|
|
17
|
+
import android.widget.FrameLayout
|
|
18
|
+
import android.widget.HorizontalScrollView
|
|
19
|
+
import android.widget.ImageView
|
|
20
|
+
import android.widget.LinearLayout
|
|
21
|
+
import android.widget.TextView
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Immutable description of one text overlay's styling. Stamped onto the overlay
|
|
25
|
+
* frame view (via R.id.tag_text_overlay_spec) when the text is applied, so the
|
|
26
|
+
* overlay can be re-opened for editing with its exact style restored, and so
|
|
27
|
+
* per-asset overlay state can be captured/restored across carousel navigation.
|
|
28
|
+
*/
|
|
29
|
+
data class TextOverlaySpec(
|
|
30
|
+
val text: String,
|
|
31
|
+
val color: Int,
|
|
32
|
+
val fontIndex: Int,
|
|
33
|
+
val backgroundMode: Int,
|
|
34
|
+
val alignment: Int,
|
|
35
|
+
val textSizeSp: Float = TextEntryController.DEFAULT_TEXT_SIZE_SP
|
|
36
|
+
) {
|
|
37
|
+
companion object {
|
|
38
|
+
const val DEFAULT_TEXT_SIZE_SP = 30f
|
|
39
|
+
const val BG_NONE = 0
|
|
40
|
+
const val BG_SOLID = 1
|
|
41
|
+
const val BG_TRANSLUCENT = 2
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class TextEntryController(
|
|
47
|
+
private val activity: CustomCameraActivity,
|
|
48
|
+
private val host: FrameLayout,
|
|
49
|
+
private val statusBarHeight: () -> Int,
|
|
50
|
+
private val navigationBarHeight: () -> Int,
|
|
51
|
+
private val leftInset: () -> Int,
|
|
52
|
+
private val rightInset: () -> Int,
|
|
53
|
+
private val onDone: (TextOverlaySpec) -> Unit,
|
|
54
|
+
private val onDeleteExisting: () -> Unit,
|
|
55
|
+
private val onDismissed: () -> Unit
|
|
56
|
+
) {
|
|
57
|
+
companion object {
|
|
58
|
+
const val DEFAULT_TEXT_SIZE_SP = 30f
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The live entry field and the confirmed overlay must wrap at the SAME width, or
|
|
62
|
+
* the background pill re-sizes when the user taps Done. Single source of truth so
|
|
63
|
+
* both the live [EditText] and the confirmed library TextView cap wrapping identically.
|
|
64
|
+
*/
|
|
65
|
+
const val TEXT_MAX_WIDTH_FRACTION = 0.86f
|
|
66
|
+
|
|
67
|
+
/** Background-pill geometry shared by the live field and the confirmed overlay. */
|
|
68
|
+
const val PILL_PADDING_H_DP = 12
|
|
69
|
+
const val PILL_PADDING_V_DP = 6
|
|
70
|
+
const val PILL_CORNER_DP = 8
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Pins every text-measurement parameter that diverges between an editable
|
|
74
|
+
* [EditText] (the live preview) and a static TextView (the confirmed overlay), so
|
|
75
|
+
* the confirmed pill wraps and measures byte-identically to what the user saw while
|
|
76
|
+
* editing. The key offender is [Layout.BREAK_STRATEGY_SIMPLE]: an EditText defaults
|
|
77
|
+
* to it while a TextView defaults to [Layout.BREAK_STRATEGY_HIGH_QUALITY], so the
|
|
78
|
+
* same text breaks into different lines and the background pill visibly shrinks on
|
|
79
|
+
* Done. Applied to BOTH views (an EditText is a TextView) so neither can drift from
|
|
80
|
+
* theme defaults. Safe on this module's minSdk 24 (break/hyphenation APIs are 23+).
|
|
81
|
+
*/
|
|
82
|
+
fun pinTextMetrics(view: TextView, screenWidthPx: Int) {
|
|
83
|
+
view.maxWidth = (screenWidthPx * TEXT_MAX_WIDTH_FRACTION).toInt()
|
|
84
|
+
view.maxLines = 8
|
|
85
|
+
view.setHorizontallyScrolling(false)
|
|
86
|
+
view.includeFontPadding = true
|
|
87
|
+
view.letterSpacing = 0f
|
|
88
|
+
view.setLineSpacing(0f, 1f)
|
|
89
|
+
view.breakStrategy = Layout.BREAK_STRATEGY_SIMPLE
|
|
90
|
+
view.hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE
|
|
91
|
+
view.minWidth = 0
|
|
92
|
+
view.minHeight = 0
|
|
93
|
+
view.minimumWidth = 0
|
|
94
|
+
view.minimumHeight = 0
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Two font weights toggled by the "Aa" control - system typefaces only,
|
|
99
|
+
* so no font files ship with the plugin.
|
|
100
|
+
*
|
|
101
|
+
* Index 0 = Bold, index 1 = Normal. A single tap flips between them.
|
|
102
|
+
* The chosen index is persisted in [TextOverlaySpec.fontIndex].
|
|
103
|
+
*/
|
|
104
|
+
val FONTS: List<Typeface> = listOf(
|
|
105
|
+
Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD),
|
|
106
|
+
Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
/** Swatch palette - identical to the palette the old text dialog offered. */
|
|
110
|
+
fun palette(theme: CameraTheme): List<Int> = listOf(
|
|
111
|
+
theme.colors.primaryContrast,
|
|
112
|
+
theme.colors.background,
|
|
113
|
+
Color.RED,
|
|
114
|
+
Color.BLUE,
|
|
115
|
+
Color.GREEN,
|
|
116
|
+
Color.YELLOW,
|
|
117
|
+
Color.parseColor("#FFC0CB"),
|
|
118
|
+
Color.parseColor("#00FF00"),
|
|
119
|
+
Color.parseColor("#008080")
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private val theme = activity.theme
|
|
124
|
+
|
|
125
|
+
var isShowing = false
|
|
126
|
+
private set
|
|
127
|
+
|
|
128
|
+
// Style state for the session — WhatsApp remembers the last-used style between
|
|
129
|
+
// text entries, so these persist across show()/hide() cycles.
|
|
130
|
+
private var color: Int = theme.colors.primaryContrast
|
|
131
|
+
private var fontIndex = 0
|
|
132
|
+
private var backgroundMode = TextOverlaySpec.BG_NONE
|
|
133
|
+
private var alignment = Gravity.CENTER_HORIZONTAL
|
|
134
|
+
private var textSizeSp = DEFAULT_TEXT_SIZE_SP
|
|
135
|
+
|
|
136
|
+
private var editingExisting = false
|
|
137
|
+
|
|
138
|
+
private var root: FrameLayout? = null
|
|
139
|
+
private var input: EditText? = null
|
|
140
|
+
private var swatchRow: View? = null
|
|
141
|
+
private var alignButton: ImageView? = null
|
|
142
|
+
private var keyboardListener: ViewTreeObserver.OnGlobalLayoutListener? = null
|
|
143
|
+
|
|
144
|
+
/** Opens the entry mode. [existing] pre-fills text + style for re-editing. */
|
|
145
|
+
fun show(existing: TextOverlaySpec? = null) {
|
|
146
|
+
if (isShowing) return
|
|
147
|
+
isShowing = true
|
|
148
|
+
editingExisting = existing != null
|
|
149
|
+
existing?.let {
|
|
150
|
+
color = it.color
|
|
151
|
+
fontIndex = it.fontIndex.coerceIn(FONTS.indices)
|
|
152
|
+
backgroundMode = it.backgroundMode
|
|
153
|
+
alignment = it.alignment
|
|
154
|
+
textSizeSp = it.textSizeSp
|
|
155
|
+
}
|
|
156
|
+
buildUi(existing?.text.orEmpty())
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fun hide() {
|
|
160
|
+
if (!isShowing) return
|
|
161
|
+
isShowing = false
|
|
162
|
+
keyboardListener?.let {
|
|
163
|
+
host.viewTreeObserver.takeIf { vto -> vto.isAlive }?.removeOnGlobalLayoutListener(it)
|
|
164
|
+
}
|
|
165
|
+
keyboardListener = null
|
|
166
|
+
input?.let { hideKeyboard(it) }
|
|
167
|
+
root?.let { host.removeView(it) }
|
|
168
|
+
root = null
|
|
169
|
+
input = null
|
|
170
|
+
swatchRow = null
|
|
171
|
+
alignButton = null
|
|
172
|
+
onDismissed()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private fun currentSpec(): TextOverlaySpec = TextOverlaySpec(
|
|
176
|
+
text = input?.text?.toString()?.trim().orEmpty(),
|
|
177
|
+
color = color,
|
|
178
|
+
fontIndex = fontIndex,
|
|
179
|
+
backgroundMode = backgroundMode,
|
|
180
|
+
alignment = alignment,
|
|
181
|
+
textSizeSp = textSizeSp
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
private fun confirm() {
|
|
185
|
+
val spec = currentSpec()
|
|
186
|
+
if (spec.text.isEmpty()) {
|
|
187
|
+
// Empty on Done: adding nothing = cancel; emptying an existing overlay = delete.
|
|
188
|
+
if (editingExisting) onDeleteExisting()
|
|
189
|
+
hide()
|
|
190
|
+
return
|
|
191
|
+
}
|
|
192
|
+
// Apply BEFORE hide(): the host clears its "which overlay is being edited"
|
|
193
|
+
// state when onDismissed fires, so onDone must run while it is still set.
|
|
194
|
+
onDone(spec)
|
|
195
|
+
hide()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private fun buildUi(initialText: String) {
|
|
199
|
+
val screenWidth = activity.resources.displayMetrics.widthPixels
|
|
200
|
+
|
|
201
|
+
val container = FrameLayout(activity).apply {
|
|
202
|
+
setBackgroundColor(theme.componentColor("editor", "textEntryScrim", 0xB3000000.toInt()))
|
|
203
|
+
isClickable = true
|
|
204
|
+
isFocusable = true
|
|
205
|
+
elevation = dp(32).toFloat()
|
|
206
|
+
// Tapping the scrim (outside the text) confirms, like WhatsApp.
|
|
207
|
+
setOnClickListener { confirm() }
|
|
208
|
+
}
|
|
209
|
+
root = container
|
|
210
|
+
|
|
211
|
+
// ── Center: the live-styled text field ──────────────────────────────────
|
|
212
|
+
val field = EditText(activity).apply {
|
|
213
|
+
background = null
|
|
214
|
+
setText(initialText)
|
|
215
|
+
setSelection(initialText.length)
|
|
216
|
+
hint = Localization.getString("typeTextHint", "Type text")
|
|
217
|
+
setHintTextColor(theme.componentColor("editor", "hintText", 0x88FFFFFF.toInt()))
|
|
218
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSp)
|
|
219
|
+
imeOptions = EditorInfo.IME_ACTION_DONE
|
|
220
|
+
// Multiline while still surfacing a Done action on the IME.
|
|
221
|
+
setRawInputType(
|
|
222
|
+
EditorInfo.TYPE_CLASS_TEXT or
|
|
223
|
+
EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE or
|
|
224
|
+
EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
|
|
225
|
+
)
|
|
226
|
+
setHorizontallyScrolling(false)
|
|
227
|
+
maxLines = 8
|
|
228
|
+
setOnEditorActionListener { _, actionId, _ ->
|
|
229
|
+
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
|
230
|
+
confirm()
|
|
231
|
+
true
|
|
232
|
+
} else false
|
|
233
|
+
}
|
|
234
|
+
// Consume taps so the scrim's confirm click doesn't fire while typing.
|
|
235
|
+
setOnClickListener { }
|
|
236
|
+
// System Back (after the IME dismisses) closes the entry mode without
|
|
237
|
+
// applying — key events are delivered to the focused view, i.e. this field.
|
|
238
|
+
setOnKeyListener { _, keyCode, event ->
|
|
239
|
+
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
|
240
|
+
hide()
|
|
241
|
+
true
|
|
242
|
+
} else false
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
input = field
|
|
246
|
+
// Cap wrapping and pin every text-measurement metric so the live pill is the EXACT
|
|
247
|
+
// size the confirmed overlay will be. The confirmed overlay (PhotoEditor
|
|
248
|
+
// addText/editText) is a static TextView; MediaPreviewEditor runs the same
|
|
249
|
+
// pinTextMetrics on it, so both break lines identically and the background never
|
|
250
|
+
// shrinks when the user taps Done.
|
|
251
|
+
pinTextMetrics(field, screenWidth)
|
|
252
|
+
applyLiveStyle()
|
|
253
|
+
container.addView(
|
|
254
|
+
field,
|
|
255
|
+
FrameLayout.LayoutParams(
|
|
256
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
257
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
258
|
+
Gravity.CENTER
|
|
259
|
+
).apply {
|
|
260
|
+
// Keep the field visually centered in the region above the keyboard.
|
|
261
|
+
bottomMargin = dp(64)
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
// ── Top action row: Cancel | spacer | Aa · align · bg · Done ────────────
|
|
266
|
+
val actionIconSize = if (screenWidth < dp(360)) dp(34) else dp(40)
|
|
267
|
+
val actionRow = LinearLayout(activity).apply {
|
|
268
|
+
orientation = LinearLayout.HORIZONTAL
|
|
269
|
+
gravity = Gravity.CENTER_VERTICAL
|
|
270
|
+
setPadding(dp(8), dp(6), dp(8), dp(6))
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
val cancelBtn = actionIcon(R.drawable.ic_close, actionIconSize) { hide() }
|
|
274
|
+
cancelBtn.bindDescription("textCancel", "Cancel text")
|
|
275
|
+
actionRow.addView(cancelBtn, actionParams(actionIconSize))
|
|
276
|
+
actionRow.addView(View(activity), LinearLayout.LayoutParams(0, 1, 1f))
|
|
277
|
+
|
|
278
|
+
val fontBtn = TextView(activity).apply {
|
|
279
|
+
text = Localization.getString("textFontSample", "Aa")
|
|
280
|
+
gravity = Gravity.CENTER
|
|
281
|
+
includeFontPadding = false
|
|
282
|
+
setTextColor(theme.colors.primaryContrast)
|
|
283
|
+
setTextSize(TypedValue.COMPLEX_UNIT_PX, actionIconSize * 0.48f)
|
|
284
|
+
typeface = FONTS[fontIndex]
|
|
285
|
+
bindDescription("textFont", "Change font")
|
|
286
|
+
setOnClickListener {
|
|
287
|
+
fontIndex = if (fontIndex == 0) 1 else 0
|
|
288
|
+
typeface = FONTS[fontIndex]
|
|
289
|
+
applyLiveStyle()
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
actionRow.addView(fontBtn, actionParams(actionIconSize))
|
|
293
|
+
|
|
294
|
+
val alignBtn = actionIcon(alignBuiltinIconRes(), actionIconSize) {
|
|
295
|
+
alignment = when (alignment) {
|
|
296
|
+
Gravity.START -> Gravity.CENTER_HORIZONTAL
|
|
297
|
+
Gravity.CENTER_HORIZONTAL -> Gravity.END
|
|
298
|
+
else -> Gravity.START
|
|
299
|
+
}
|
|
300
|
+
alignButton?.let { applyAlignIcon(it) }
|
|
301
|
+
applyLiveStyle()
|
|
302
|
+
}
|
|
303
|
+
alignBtn.bindDescription("textAlignment", "Change text alignment")
|
|
304
|
+
alignButton = alignBtn
|
|
305
|
+
actionRow.addView(alignBtn, actionParams(actionIconSize))
|
|
306
|
+
|
|
307
|
+
val bgBtn = actionIcon(R.drawable.ic_text_bg, actionIconSize) {
|
|
308
|
+
backgroundMode = (backgroundMode + 1) % 3
|
|
309
|
+
applyLiveStyle()
|
|
310
|
+
}
|
|
311
|
+
bgBtn.bindDescription("textBackground", "Change text background")
|
|
312
|
+
actionRow.addView(bgBtn, actionParams(actionIconSize))
|
|
313
|
+
|
|
314
|
+
val doneBtn = actionIcon(R.drawable.ic_done, actionIconSize) { confirm() }
|
|
315
|
+
doneBtn.bindDescription("textDone", "Apply text")
|
|
316
|
+
actionRow.addView(doneBtn, actionParams(actionIconSize))
|
|
317
|
+
|
|
318
|
+
container.addView(
|
|
319
|
+
actionRow,
|
|
320
|
+
FrameLayout.LayoutParams(
|
|
321
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
322
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
323
|
+
Gravity.TOP
|
|
324
|
+
).apply {
|
|
325
|
+
topMargin = statusBarHeight() + dp(8)
|
|
326
|
+
marginStart = leftInset() + dp(8)
|
|
327
|
+
marginEnd = rightInset() + dp(8)
|
|
328
|
+
}
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
// ── Bottom: color swatches, repositioned above the keyboard ─────────────
|
|
332
|
+
val swatchSize = if (screenWidth < dp(360)) dp(30) else dp(34)
|
|
333
|
+
val swatches = LinearLayout(activity).apply {
|
|
334
|
+
orientation = LinearLayout.HORIZONTAL
|
|
335
|
+
gravity = Gravity.CENTER
|
|
336
|
+
setPadding(dp(8), dp(6), dp(8), dp(6))
|
|
337
|
+
}
|
|
338
|
+
val colors = palette(theme)
|
|
339
|
+
val selectedColor = color
|
|
340
|
+
val swatchViews = colors.map { c ->
|
|
341
|
+
View(activity).apply {
|
|
342
|
+
background = GradientDrawable().apply {
|
|
343
|
+
shape = GradientDrawable.OVAL
|
|
344
|
+
setColor(c)
|
|
345
|
+
setStroke(
|
|
346
|
+
if (c == selectedColor) dp(3) else dp(1),
|
|
347
|
+
if (c == selectedColor) theme.colors.primaryContrast
|
|
348
|
+
else theme.componentColor("editor", "swatchBorder", 0x55FFFFFF)
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
swatchViews.forEachIndexed { index, swatch ->
|
|
354
|
+
swatches.addView(swatch, LinearLayout.LayoutParams(swatchSize, swatchSize).apply {
|
|
355
|
+
setMargins(dp(6), dp(6), dp(6), dp(6))
|
|
356
|
+
})
|
|
357
|
+
swatch.setOnClickListener {
|
|
358
|
+
color = colors[index]
|
|
359
|
+
swatchViews.forEachIndexed { i, v ->
|
|
360
|
+
(v.background as GradientDrawable).setStroke(
|
|
361
|
+
if (i == index) dp(3) else dp(1),
|
|
362
|
+
if (i == index) theme.colors.primaryContrast
|
|
363
|
+
else theme.componentColor("editor", "swatchBorder", 0x55FFFFFF)
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
applyLiveStyle()
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
val swatchScroll = HorizontalScrollView(activity).apply {
|
|
370
|
+
isHorizontalScrollBarEnabled = false
|
|
371
|
+
addView(swatches)
|
|
372
|
+
}
|
|
373
|
+
swatchRow = swatchScroll
|
|
374
|
+
container.addView(
|
|
375
|
+
swatchScroll,
|
|
376
|
+
FrameLayout.LayoutParams(
|
|
377
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
378
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
379
|
+
Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
|
380
|
+
).apply {
|
|
381
|
+
bottomMargin = navigationBarHeight() + dp(12)
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
// System Back closes the entry mode without applying.
|
|
386
|
+
container.isFocusableInTouchMode = true
|
|
387
|
+
container.setOnKeyListener { _, keyCode, event ->
|
|
388
|
+
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
|
|
389
|
+
hide()
|
|
390
|
+
true
|
|
391
|
+
} else false
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
host.addView(
|
|
395
|
+
container,
|
|
396
|
+
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
trackKeyboard(container)
|
|
400
|
+
|
|
401
|
+
field.requestFocus()
|
|
402
|
+
field.post {
|
|
403
|
+
(activity.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? InputMethodManager)
|
|
404
|
+
?.showSoftInput(field, InputMethodManager.SHOW_IMPLICIT)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Restyles the live EditText from the current style state so the preview always
|
|
410
|
+
* matches the final overlay exactly (same color/typeface/gravity/background the
|
|
411
|
+
* TextStyleBuilder applies at Done).
|
|
412
|
+
*/
|
|
413
|
+
private fun applyLiveStyle() {
|
|
414
|
+
val field = input ?: return
|
|
415
|
+
field.typeface = FONTS[fontIndex]
|
|
416
|
+
field.gravity = alignment or Gravity.CENTER_VERTICAL
|
|
417
|
+
field.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSp)
|
|
418
|
+
when (backgroundMode) {
|
|
419
|
+
TextOverlaySpec.BG_SOLID -> {
|
|
420
|
+
field.setTextColor(contrastOn(color))
|
|
421
|
+
field.background = backgroundPill(color, translucent = false)
|
|
422
|
+
field.setPadding(dp(PILL_PADDING_H_DP), dp(PILL_PADDING_V_DP), dp(PILL_PADDING_H_DP), dp(PILL_PADDING_V_DP))
|
|
423
|
+
}
|
|
424
|
+
TextOverlaySpec.BG_TRANSLUCENT -> {
|
|
425
|
+
field.setTextColor(theme.colors.primaryContrast)
|
|
426
|
+
field.background = backgroundPill(color, translucent = true)
|
|
427
|
+
field.setPadding(dp(PILL_PADDING_H_DP), dp(PILL_PADDING_V_DP), dp(PILL_PADDING_H_DP), dp(PILL_PADDING_V_DP))
|
|
428
|
+
}
|
|
429
|
+
else -> {
|
|
430
|
+
field.setTextColor(color)
|
|
431
|
+
field.background = null
|
|
432
|
+
field.setPadding(0, 0, 0, 0)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Tracks the soft keyboard height via the visible display frame (the activity
|
|
439
|
+
* runs fullscreen without adjustResize, so IME window insets never reach the
|
|
440
|
+
* layout) and keeps the swatch row pinned just above the keyboard.
|
|
441
|
+
*/
|
|
442
|
+
private fun trackKeyboard(container: View) {
|
|
443
|
+
val listener = ViewTreeObserver.OnGlobalLayoutListener {
|
|
444
|
+
val visible = Rect()
|
|
445
|
+
container.getWindowVisibleDisplayFrame(visible)
|
|
446
|
+
val keyboardHeight = (container.rootView.height - visible.bottom).coerceAtLeast(0)
|
|
447
|
+
val row = swatchRow ?: return@OnGlobalLayoutListener
|
|
448
|
+
val lp = row.layoutParams as? FrameLayout.LayoutParams ?: return@OnGlobalLayoutListener
|
|
449
|
+
val target = if (keyboardHeight > dp(80)) {
|
|
450
|
+
keyboardHeight + dp(8)
|
|
451
|
+
} else {
|
|
452
|
+
navigationBarHeight() + dp(12)
|
|
453
|
+
}
|
|
454
|
+
if (lp.bottomMargin != target) {
|
|
455
|
+
lp.bottomMargin = target
|
|
456
|
+
row.layoutParams = lp
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
container.viewTreeObserver.addOnGlobalLayoutListener(listener)
|
|
460
|
+
keyboardListener = listener
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ── Small helpers (local mirrors of MediaPreviewEditor's private utilities) ──
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Built-in drawable id → white-label icon name, so this screen's icons honour
|
|
467
|
+
* the same per-icon `resourceName` / `tintColor` config as the rest of the
|
|
468
|
+
* editor. Mirrors `MediaPreviewEditor.iconNames` for the drawables used here.
|
|
469
|
+
*/
|
|
470
|
+
private val iconNames: Map<Int, String> = mapOf(
|
|
471
|
+
R.drawable.ic_close to "close",
|
|
472
|
+
R.drawable.ic_text_bg to "text_bg",
|
|
473
|
+
R.drawable.ic_text_align_left to "text_align_left",
|
|
474
|
+
R.drawable.ic_text_align_center to "text_align_center",
|
|
475
|
+
R.drawable.ic_text_align_right to "text_align_right",
|
|
476
|
+
R.drawable.ic_done to "done"
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Sets [builtinRes] through the white-label config (host SVG → host
|
|
481
|
+
* `resourceName` → built-in) and tints it: a configured per-icon / global
|
|
482
|
+
* tint wins; a host-provided SVG keeps its OWN colours (a solid filter would
|
|
483
|
+
* flatten it); a plain glyph falls back to the dark-editor contrast colour so
|
|
484
|
+
* it stays visible. Mirrors `MediaPreviewEditor`'s resolution for this screen.
|
|
485
|
+
*/
|
|
486
|
+
private fun ImageView.setThemedIcon(builtinRes: Int) {
|
|
487
|
+
val name = iconNames[builtinRes]
|
|
488
|
+
val drawable = theme.config.iconDrawable(activity, name ?: "", builtinRes)
|
|
489
|
+
setImageDrawable(drawable)
|
|
490
|
+
val tint =
|
|
491
|
+
if (name != null) {
|
|
492
|
+
theme.config.iconTintFor(name, drawable, theme.colors.primaryContrast)
|
|
493
|
+
} else {
|
|
494
|
+
theme.colors.primaryContrast
|
|
495
|
+
}
|
|
496
|
+
tint?.let { setColorFilter(it) } ?: clearColorFilter()
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
private fun alignBuiltinIconRes(): Int = when (alignment) {
|
|
500
|
+
Gravity.START -> R.drawable.ic_text_align_left
|
|
501
|
+
Gravity.END -> R.drawable.ic_text_align_right
|
|
502
|
+
else -> R.drawable.ic_text_align_center
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Repaint the alignment button for the current alignment. Each of the three
|
|
507
|
+
* alignments is its own configurable icon, so the tint is re-resolved along
|
|
508
|
+
* with the drawable rather than only on first build.
|
|
509
|
+
*/
|
|
510
|
+
private fun applyAlignIcon(view: ImageView) {
|
|
511
|
+
view.setThemedIcon(alignBuiltinIconRes())
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
private fun actionIcon(drawableRes: Int, size: Int, onClick: () -> Unit): ImageView =
|
|
515
|
+
ImageView(activity).apply {
|
|
516
|
+
setThemedIcon(drawableRes)
|
|
517
|
+
scaleType = ImageView.ScaleType.CENTER
|
|
518
|
+
setPadding(dp(4), dp(4), dp(4), dp(4))
|
|
519
|
+
setOnClickListener { onClick() }
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
private fun actionParams(size: Int): LinearLayout.LayoutParams =
|
|
523
|
+
LinearLayout.LayoutParams(size + dp(8), size + dp(8)).apply {
|
|
524
|
+
setMargins(dp(4), 0, dp(4), 0)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
private fun View.bindDescription(key: String, default: String) {
|
|
528
|
+
contentDescription = Localization.getString(key, default)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private fun backgroundPill(base: Int, translucent: Boolean): GradientDrawable =
|
|
532
|
+
GradientDrawable().apply {
|
|
533
|
+
cornerRadius = dp(PILL_CORNER_DP).toFloat()
|
|
534
|
+
setColor(if (translucent) (base and 0x00FFFFFF) or 0x66000000 else base)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/** Black or white, whichever contrasts against [background] (WhatsApp behaviour). */
|
|
538
|
+
private fun contrastOn(background: Int): Int {
|
|
539
|
+
val r = Color.red(background)
|
|
540
|
+
val g = Color.green(background)
|
|
541
|
+
val b = Color.blue(background)
|
|
542
|
+
val luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255.0
|
|
543
|
+
return if (luminance > 0.6) Color.BLACK else Color.WHITE
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private fun hideKeyboard(view: View) {
|
|
547
|
+
(activity.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? InputMethodManager)
|
|
548
|
+
?.hideSoftInputFromWindow(view.windowToken, 0)
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private fun dp(value: Int): Int =
|
|
552
|
+
(value * activity.resources.displayMetrics.density).toInt()
|
|
553
|
+
}
|