From b3244efcb7d70ccbaa4b061e582305a98188c241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=E1=BA=A3o=20H=C3=A0?= Date: Fri, 13 Dec 2024 14:16:28 +0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20camera=20config,=20re?= =?UTF-8?q?move=20allowedCamera=20props?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nitro/multipleimagepicker/CameraEngine.kt | 38 ++ .../multipleimagepicker/CompressEngine.kt | 43 -- .../nitro/multipleimagepicker/GlideEngine.kt | 121 ++--- .../MultipleImagePickerImp.kt | 10 +- docs/docs/CONFIG.mdx | 39 +- docs/docs/index.md | 1 - example/src/index.tsx | 45 +- ios/HybridMultipleImagePicker+Camera.swift | 14 + ios/HybridMultipleImagePicker+Config.swift | 34 +- .../generated/android/c++/JCameraDevice.hpp | 58 +++ .../c++/JHybridMultipleImagePickerSpec.cpp | 8 + .../generated/android/c++/JNitroConfig.hpp | 16 +- .../android/c++/JPickerCameraConfig.hpp | 58 +++ .../nitro/multipleimagepicker/CameraDevice.kt | 25 + .../nitro/multipleimagepicker/NitroConfig.kt | 4 +- .../multipleimagepicker/PickerCameraConfig.kt | 22 + .../MultipleImagePicker-Swift-Cxx-Bridge.hpp | 15 + ...MultipleImagePicker-Swift-Cxx-Umbrella.hpp | 6 + .../HybridMultipleImagePickerSpecSwift.hpp | 6 + .../generated/ios/swift/CameraDevice.swift | 40 ++ .../generated/ios/swift/NitroConfig.swift | 56 +- .../ios/swift/PickerCameraConfig.swift | 58 +++ .../generated/shared/c++/CameraDevice.hpp | 78 +++ nitrogen/generated/shared/c++/NitroConfig.hpp | 15 +- .../shared/c++/PickerCameraConfig.hpp | 74 +++ src/index.ts | 9 +- src/types/camera.ts | 32 ++ src/types/config.ts | 484 ------------------ src/types/crop.ts | 92 ++++ src/types/index.ts | 5 +- src/types/media.ts | 8 - src/types/picker.ts | 378 ++++++++++++++ src/types/preview.ts | 39 ++ src/types/result.ts | 6 - 34 files changed, 1246 insertions(+), 691 deletions(-) create mode 100644 android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt delete mode 100644 android/src/main/java/com/margelo/nitro/multipleimagepicker/CompressEngine.kt create mode 100644 ios/HybridMultipleImagePicker+Camera.swift create mode 100644 nitrogen/generated/android/c++/JCameraDevice.hpp create mode 100644 nitrogen/generated/android/c++/JPickerCameraConfig.hpp create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraDevice.kt create mode 100644 nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCameraConfig.kt create mode 100644 nitrogen/generated/ios/swift/CameraDevice.swift create mode 100644 nitrogen/generated/ios/swift/PickerCameraConfig.swift create mode 100644 nitrogen/generated/shared/c++/CameraDevice.hpp create mode 100644 nitrogen/generated/shared/c++/PickerCameraConfig.hpp create mode 100644 src/types/camera.ts create mode 100644 src/types/crop.ts delete mode 100644 src/types/media.ts create mode 100644 src/types/picker.ts create mode 100644 src/types/preview.ts diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt new file mode 100644 index 00000000..af41cdb6 --- /dev/null +++ b/android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt @@ -0,0 +1,38 @@ +package com.margelo.nitro.multipleimagepicker + +import android.content.Context +import androidx.fragment.app.Fragment +import com.bumptech.glide.Glide +import com.luck.lib.camerax.SimpleCameraX +import com.luck.picture.lib.interfaces.OnCameraInterceptListener +import java.io.File + +class CameraEngine(private val appContext: Context, val config: PickerCameraConfig) : OnCameraInterceptListener { + override fun openCamera(fragment: Fragment, cameraMode: Int, requestCode: Int) { + val camera = SimpleCameraX.of() + camera.isAutoRotation(true) + camera.setCameraMode(cameraMode) + camera.isDisplayRecordChangeTime(true) + camera.isManualFocusCameraPreview(true) + camera.isZoomCameraPreview(true) + camera.setOutputPathDir(getSandboxCameraOutputPath()) + camera.setRecordVideoMaxSecond(config.videoMaximumDuration?.toInt() ?: 60) + +// camera.setPermissionDeniedListener(getSimpleXPermissionDeniedListener()) +// camera.setPermissionDescriptionListener(getSimpleXPermissionDescriptionListener()) + camera.setImageEngine { context, url, imageView -> + Glide.with(context).load(url).into(imageView) + } + camera.start(fragment.requireActivity(), fragment, requestCode) + } + + private fun getSandboxCameraOutputPath(): String { + val externalFilesDir: File? = appContext.getExternalFilesDir("") + val customFile = File(externalFilesDir?.absolutePath, "Sandbox") + if (!customFile.exists()) { + customFile.mkdirs() + } + return customFile.absolutePath + File.separator + + } +} \ No newline at end of file diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/CompressEngine.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/CompressEngine.kt deleted file mode 100644 index edcf7379..00000000 --- a/android/src/main/java/com/margelo/nitro/multipleimagepicker/CompressEngine.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.margelo.nitro.multipleimagepicker - -import android.content.Context -import android.net.Uri -import com.luck.picture.lib.config.PictureMimeType -import com.luck.picture.lib.engine.CompressFileEngine -import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener -import com.luck.picture.lib.utils.DateUtils -import top.zibin.luban.CompressionPredicate -import top.zibin.luban.Luban -import top.zibin.luban.OnNewCompressListener -import java.io.File - -//TODO: -class CompressEngine : CompressFileEngine { - override fun onStartCompress( - context: Context, - source: ArrayList, - call: OnKeyValueResultCallbackListener - ) { - Luban.with(context).load(source).ignoreBy(100).setRenameListener { filePath -> - val indexOf = filePath.lastIndexOf(".") - val postfix = if (indexOf != -1) filePath.substring(indexOf) else ".jpg" - DateUtils.getCreateFileName("CMP_") + postfix - }.filter(CompressionPredicate { path -> - if (PictureMimeType.isUrlHasImage(path) && !PictureMimeType.isHasHttp(path)) { - return@CompressionPredicate true - } - !PictureMimeType.isUrlHasGif(path) - }).setCompressListener(object : OnNewCompressListener { - override fun onStart() { - } - - override fun onSuccess(source: String, compressFile: File) { - call.onCallback(source, compressFile.absolutePath) - } - - override fun onError(source: String, e: Throwable) { - call.onCallback(source, null) - } - }).launch() - } -} diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/GlideEngine.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/GlideEngine.kt index 31f26ec2..3b4f17cc 100644 --- a/android/src/main/java/com/margelo/nitro/multipleimagepicker/GlideEngine.kt +++ b/android/src/main/java/com/margelo/nitro/multipleimagepicker/GlideEngine.kt @@ -8,105 +8,78 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.luck.picture.lib.engine.ImageEngine import com.luck.picture.lib.utils.ActivityCompatHelper - -/** - * @author:luck - * @date:2019-11-13 17:02 - * @describe:Glide加载引擎 - */ class GlideEngine private constructor() : ImageEngine { - /** - * 加载图片 - * - * @param context 上下文 - * @param url 资源url - * @param imageView 图片承载控件 - */ - override fun loadImage(context: Context, url: String, imageView: ImageView) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return - } - Glide.with(context) + override fun loadImage(context: Context, url: String, imageView: ImageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context) .load(url) .into(imageView) - } - - override fun loadImage( - context: Context, - imageView: ImageView, - url: String, - maxWidth: Int, - maxHeight: Int - ) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return } - Glide.with(context) + + override fun loadImage( + context: Context, + imageView: ImageView, + url: String, + maxWidth: Int, + maxHeight: Int + ) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context) .load(url) .override(maxWidth, maxHeight) .into(imageView) - } - - /** - * 加载相册目录封面 - * - * @param context 上下文 - * @param url 图片路径 - * @param imageView 承载图片ImageView - */ - override fun loadAlbumCover(context: Context, url: String, imageView: ImageView) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return } - Glide.with(context) + + override fun loadAlbumCover(context: Context, url: String, imageView: ImageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context) .asBitmap() .load(url) .override(180, 180) .sizeMultiplier(0.5f) .transform(CenterCrop(), RoundedCorners(8)) .into(imageView) - } - - /** - * 加载图片列表图片 - * - * @param context 上下文 - * @param url 图片路径 - * @param imageView 承载图片ImageView - */ - override fun loadGridImage(context: Context, url: String, imageView: ImageView) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return } - Glide.with(context) + + override fun loadGridImage(context: Context, url: String, imageView: ImageView) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context) .load(url) .override(200, 200) .centerCrop() .placeholder(com.luck.picture.lib.R.drawable.ps_image_placeholder) .into(imageView) - } + } - override fun pauseRequests(context: Context) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return + override fun pauseRequests(context: Context) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context).pauseRequests() } - Glide.with(context).pauseRequests() - } - override fun resumeRequests(context: Context) { - if (!ActivityCompatHelper.assertValidRequest(context)) { - return + override fun resumeRequests(context: Context) { + if (!ActivityCompatHelper.assertValidRequest(context)) { + return + } + Glide.with(context).resumeRequests() } - Glide.with(context).resumeRequests() - } - private object InstanceHolder { - val instance = GlideEngine() - } + private object InstanceHolder { + val instance = GlideEngine() + } - companion object { - fun createGlideEngine(): GlideEngine { - return InstanceHolder.instance + companion object { + fun createGlideEngine(): GlideEngine { + return InstanceHolder.instance + } } - } } \ No newline at end of file diff --git a/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt b/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt index 6b111c3f..d391dc31 100644 --- a/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt +++ b/android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt @@ -96,6 +96,7 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) : .setImageEngine(imageEngine) .setSelectedData(dataList) .setSelectorUIStyle(style) + .apply { if (isCrop) { setCropOption(config.crop) @@ -114,6 +115,13 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) : maxFileSize?.let { setFilterMaxFileSize(it) } + + + isDisplayCamera(config.camera != null) + + config.camera?.let { + setCameraInterceptListener(CameraEngine(appContext, it)) + } } .setImageSpanCount(config.numberOfColumn?.toInt() ?: 3) .setMaxSelectNum(maxSelect) @@ -129,8 +137,6 @@ class MultipleImagePickerImp(reactContext: ReactApplicationContext?) : // isPreview .isPreviewImage(isPreview) .isPreviewVideo(isPreview) - // - .isDisplayCamera(config.allowedCamera ?: true) .isDisplayTimeAxis(true) .setSelectionMode(selectMode) .isOriginalControl(config.isHiddenOriginalButton == false) diff --git a/docs/docs/CONFIG.mdx b/docs/docs/CONFIG.mdx index e9f97502..00cf2bda 100644 --- a/docs/docs/CONFIG.mdx +++ b/docs/docs/CONFIG.mdx @@ -27,15 +27,6 @@ See [**Result**](/result) - **Default**: `[]` - **Required**: No -### `allowedCamera` - -Enable camera functionality. - -- **Type**: boolean -- **Default**: `true` -- **Required**: No -- **Platform**: iOS, Android - ### `allowedLimit` Display additional select more media when permission on `iOS` is limited. @@ -81,6 +72,36 @@ Maximum number of videos allowed. - **Required**: No - **Platform**: iOS, Android +## Camera 📸 + +Configuration camera functionality. + +- **Type**: object +- **Default**: `{}` +- **Required**: No +- **Platform**: iOS, Android + +### `cameraDevice` + +Camera device to be used. + +- **Type**: `string` +- **Default**: `back` +- **Required**: No +- **Platform**: iOS +- **Options**: + - `back`: Back camera + - `front`: Front camera + +### `videoMaximumDuration` + +Maximum video duration in seconds. + +- **Type**: number +- **Default**: 60 +- **Required**: No +- **Platform**: iOS, Android + ## Crop 🪚 Configuration for image cropping functionality. diff --git a/docs/docs/index.md b/docs/docs/index.md index 234bd32d..a6561cc5 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -31,7 +31,6 @@ React Native Multiple Image Picker **(RNMIP)** enables application to pick image | 🎨 | UI Customization (numberOfColumn, spacing, primaryColor ... ) | | 🌚 | Dark Mode, Light Mode | | 🌄 | Choose multiple images/video. | -| 🤐 | Compress image after selected (new) ✨ | | 📦 | Support smart album `(camera roll, selfies, panoramas, favorites, videos...)`. | | 📺 | Display video duration. | | 🎆 | Preview image/video. | diff --git a/example/src/index.tsx b/example/src/index.tsx index ff27b550..00437220 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -83,13 +83,6 @@ export default function App() { const response = await openPicker({ ...options, selectedAssets: images, - crop: { - ratio: [ - { title: 'Instagram', width: 1, height: 1 }, - { title: 'Twitter', width: 16, height: 9 }, - { title: 'Facebook', width: 12, height: 11 }, - ], - }, }) setImages(Array.isArray(response) ? response : [response]) @@ -262,13 +255,39 @@ export default function App() { /> ) : null} - {/* allowedCamera */} + Camera 📸 + + + + setOptions('camera', value ? {} : undefined) + } + /> + - + {/* camera videoMaximumDuration */} + + { + setOptions('camera', { + ...(options.camera ?? { cameraDevice: 'back' }), + videoMaximumDuration: parseNumber(value), + }) + }} + /> + + {IS_IOS ? ( <> diff --git a/ios/HybridMultipleImagePicker+Camera.swift b/ios/HybridMultipleImagePicker+Camera.swift new file mode 100644 index 00000000..32cfc49c --- /dev/null +++ b/ios/HybridMultipleImagePicker+Camera.swift @@ -0,0 +1,14 @@ +// +// HybridMultipleImagePicker+Camera.swift +// Pods +// +// Created by BAO HA on 13/12/24. +// + +import HXPhotoPicker + +extension HybridMultipleImagePicker { +// func setCameraConfig(config: Camera) { +// // +// } +} diff --git a/ios/HybridMultipleImagePicker+Config.swift b/ios/HybridMultipleImagePicker+Config.swift index 757140d9..a47e126b 100644 --- a/ios/HybridMultipleImagePicker+Config.swift +++ b/ios/HybridMultipleImagePicker+Config.swift @@ -35,8 +35,6 @@ extension HybridMultipleImagePicker { photoList.allowSwipeToSelect = options.allowSwipeToSelect ?? true - photoList.allowAddCamera = options.allowedCamera ?? true - photoList.allowAddLimit = options.allowedLimit ?? true // check media type @@ -49,6 +47,9 @@ extension HybridMultipleImagePicker { config.selectOptions = [.video, .photo, .gifPhoto, .livePhoto] } + config.indicatorType = .system + config.photoList.cell.kf_indicatorColor = .black + if let boxStyle = SelectBoxView.Style(rawValue: Int(options.selectBoxStyle.rawValue)) { previewView.selectBox.style = boxStyle photoList.cell.selectBox.style = boxStyle @@ -94,8 +95,6 @@ extension HybridMultipleImagePicker { config.isSelectedOriginal = false -// config.isFetchDeatilsAsset = true - let isPreview = options.isPreview ?? true previewView.bottomView.isShowPreviewList = isPreview @@ -115,16 +114,35 @@ extension HybridMultipleImagePicker { config.editorOptions = [.photo, .gifPhoto, .livePhoto] if let crop = options.crop { - let editor = setCropConfig(crop) - - config.editor = editor - + config.editor = setCropConfig(crop) } else { previewView.bottomView.isHiddenEditButton = true } photoList.finishSelectionAfterTakingPhoto = true + if let cameraOption = options.camera { + photoList.allowAddCamera = true + + var cameraConfig = SystemCameraConfiguration() + + cameraConfig.editExportPreset = .highQuality + cameraConfig.videoQuality = .typeHigh + + switch Int(cameraOption.cameraDevice.rawValue) { + case 0: + cameraConfig.cameraDevice = .front + default: + cameraConfig.cameraDevice = .rear + } + + cameraConfig.videoMaximumDuration = cameraOption.videoMaximumDuration ?? 60 + + photoList.cameraType = .system(cameraConfig) + } else { + photoList.allowAddCamera = false + } + config.photoList = photoList config.previewView = previewView diff --git a/nitrogen/generated/android/c++/JCameraDevice.hpp b/nitrogen/generated/android/c++/JCameraDevice.hpp new file mode 100644 index 00000000..4dd1afb0 --- /dev/null +++ b/nitrogen/generated/android/c++/JCameraDevice.hpp @@ -0,0 +1,58 @@ +/// +/// JCameraDevice.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "CameraDevice.hpp" + +namespace margelo::nitro::multipleimagepicker { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ enum "CameraDevice" and the the Kotlin enum "CameraDevice". + */ + struct JCameraDevice final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/CameraDevice;"; + + public: + /** + * Convert this Java/Kotlin-based enum to the C++ enum CameraDevice. + */ + [[maybe_unused]] + CameraDevice toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldOrdinal = clazz->getField("_ordinal"); + int ordinal = this->getFieldValue(fieldOrdinal); + return static_cast(ordinal); + } + + public: + /** + * Create a Java/Kotlin-based enum with the given C++ enum's value. + */ + [[maybe_unused]] + static jni::alias_ref fromCpp(CameraDevice value) { + static const auto clazz = javaClassStatic(); + static const auto fieldFRONT = clazz->getStaticField("FRONT"); + static const auto fieldBACK = clazz->getStaticField("BACK"); + + switch (value) { + case CameraDevice::FRONT: + return clazz->getStaticFieldValue(fieldFRONT); + case CameraDevice::BACK: + return clazz->getStaticFieldValue(fieldBACK); + default: + std::string stringValue = std::to_string(static_cast(value)); + throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); + } + } + }; + +} // namespace margelo::nitro::multipleimagepicker diff --git a/nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp b/nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp index 6f5ea11a..87c47bd7 100644 --- a/nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp +++ b/nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp @@ -31,6 +31,10 @@ namespace margelo::nitro::multipleimagepicker { enum class Language; } namespace margelo::nitro::multipleimagepicker { enum class Theme; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } +// Forward declaration of `PickerCameraConfig` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { struct PickerCameraConfig; } +// Forward declaration of `CameraDevice` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } // Forward declaration of `NitroCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCropConfig; } // Forward declaration of `CropResult` to properly resolve imports. @@ -67,6 +71,10 @@ namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } #include "JTheme.hpp" #include "Presentation.hpp" #include "JPresentation.hpp" +#include "PickerCameraConfig.hpp" +#include "JPickerCameraConfig.hpp" +#include "CameraDevice.hpp" +#include "JCameraDevice.hpp" #include #include "JFunc_void_std__vector_Result_.hpp" #include "JFunc_void_double.hpp" diff --git a/nitrogen/generated/android/c++/JNitroConfig.hpp b/nitrogen/generated/android/c++/JNitroConfig.hpp index e5e59914..17e1ae2b 100644 --- a/nitrogen/generated/android/c++/JNitroConfig.hpp +++ b/nitrogen/generated/android/c++/JNitroConfig.hpp @@ -10,10 +10,13 @@ #include #include "NitroConfig.hpp" +#include "CameraDevice.hpp" #include "CropRatio.hpp" +#include "JCameraDevice.hpp" #include "JCropRatio.hpp" #include "JLanguage.hpp" #include "JMediaType.hpp" +#include "JPickerCameraConfig.hpp" #include "JPickerCropConfig.hpp" #include "JPresentation.hpp" #include "JResult.hpp" @@ -24,6 +27,7 @@ #include "JTheme.hpp" #include "Language.hpp" #include "MediaType.hpp" +#include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "Presentation.hpp" #include "Result.hpp" @@ -68,8 +72,6 @@ namespace margelo::nitro::multipleimagepicker { jni::local_ref isPreview = this->getFieldValue(fieldIsPreview); static const auto fieldPrimaryColor = clazz->getField("primaryColor"); jni::local_ref primaryColor = this->getFieldValue(fieldPrimaryColor); - static const auto fieldAllowedCamera = clazz->getField("allowedCamera"); - jni::local_ref allowedCamera = this->getFieldValue(fieldAllowedCamera); static const auto fieldAllowSwipeToSelect = clazz->getField("allowSwipeToSelect"); jni::local_ref allowSwipeToSelect = this->getFieldValue(fieldAllowSwipeToSelect); static const auto fieldSpacing = clazz->getField("spacing"); @@ -106,6 +108,8 @@ namespace margelo::nitro::multipleimagepicker { jni::local_ref theme = this->getFieldValue(fieldTheme); static const auto fieldPresentation = clazz->getField("presentation"); jni::local_ref presentation = this->getFieldValue(fieldPresentation); + static const auto fieldCamera = clazz->getField("camera"); + jni::local_ref camera = this->getFieldValue(fieldCamera); return NitroConfig( mediaType->toCpp(), [&]() { @@ -123,7 +127,6 @@ namespace margelo::nitro::multipleimagepicker { numberOfColumn != nullptr ? std::make_optional(numberOfColumn->value()) : std::nullopt, isPreview != nullptr ? std::make_optional(static_cast(isPreview->value())) : std::nullopt, primaryColor != nullptr ? std::make_optional(primaryColor->value()) : std::nullopt, - allowedCamera != nullptr ? std::make_optional(static_cast(allowedCamera->value())) : std::nullopt, allowSwipeToSelect != nullptr ? std::make_optional(static_cast(allowSwipeToSelect->value())) : std::nullopt, spacing != nullptr ? std::make_optional(spacing->value()) : std::nullopt, isHiddenPreviewButton != nullptr ? std::make_optional(static_cast(isHiddenPreviewButton->value())) : std::nullopt, @@ -141,7 +144,8 @@ namespace margelo::nitro::multipleimagepicker { text != nullptr ? std::make_optional(text->toCpp()) : std::nullopt, language->toCpp(), theme->toCpp(), - presentation->toCpp() + presentation->toCpp(), + camera != nullptr ? std::make_optional(camera->toCpp()) : std::nullopt ); } @@ -167,7 +171,6 @@ namespace margelo::nitro::multipleimagepicker { value.numberOfColumn.has_value() ? jni::JDouble::valueOf(value.numberOfColumn.value()) : nullptr, value.isPreview.has_value() ? jni::JBoolean::valueOf(value.isPreview.value()) : nullptr, value.primaryColor.has_value() ? jni::JDouble::valueOf(value.primaryColor.value()) : nullptr, - value.allowedCamera.has_value() ? jni::JBoolean::valueOf(value.allowedCamera.value()) : nullptr, value.allowSwipeToSelect.has_value() ? jni::JBoolean::valueOf(value.allowSwipeToSelect.value()) : nullptr, value.spacing.has_value() ? jni::JDouble::valueOf(value.spacing.value()) : nullptr, value.isHiddenPreviewButton.has_value() ? jni::JBoolean::valueOf(value.isHiddenPreviewButton.value()) : nullptr, @@ -185,7 +188,8 @@ namespace margelo::nitro::multipleimagepicker { value.text.has_value() ? JText::fromCpp(value.text.value()) : nullptr, JLanguage::fromCpp(value.language), JTheme::fromCpp(value.theme), - JPresentation::fromCpp(value.presentation) + JPresentation::fromCpp(value.presentation), + value.camera.has_value() ? JPickerCameraConfig::fromCpp(value.camera.value()) : nullptr ); } }; diff --git a/nitrogen/generated/android/c++/JPickerCameraConfig.hpp b/nitrogen/generated/android/c++/JPickerCameraConfig.hpp new file mode 100644 index 00000000..74168638 --- /dev/null +++ b/nitrogen/generated/android/c++/JPickerCameraConfig.hpp @@ -0,0 +1,58 @@ +/// +/// JPickerCameraConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include "PickerCameraConfig.hpp" + +#include "CameraDevice.hpp" +#include "JCameraDevice.hpp" +#include + +namespace margelo::nitro::multipleimagepicker { + + using namespace facebook; + + /** + * The C++ JNI bridge between the C++ struct "PickerCameraConfig" and the the Kotlin data class "PickerCameraConfig". + */ + struct JPickerCameraConfig final: public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/PickerCameraConfig;"; + + public: + /** + * Convert this Java/Kotlin-based struct to the C++ struct PickerCameraConfig by copying all values to C++. + */ + [[maybe_unused]] + PickerCameraConfig toCpp() const { + static const auto clazz = javaClassStatic(); + static const auto fieldCameraDevice = clazz->getField("cameraDevice"); + jni::local_ref cameraDevice = this->getFieldValue(fieldCameraDevice); + static const auto fieldVideoMaximumDuration = clazz->getField("videoMaximumDuration"); + jni::local_ref videoMaximumDuration = this->getFieldValue(fieldVideoMaximumDuration); + return PickerCameraConfig( + cameraDevice->toCpp(), + videoMaximumDuration != nullptr ? std::make_optional(videoMaximumDuration->value()) : std::nullopt + ); + } + + public: + /** + * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java. + */ + [[maybe_unused]] + static jni::local_ref fromCpp(const PickerCameraConfig& value) { + return newInstance( + JCameraDevice::fromCpp(value.cameraDevice), + value.videoMaximumDuration.has_value() ? jni::JDouble::valueOf(value.videoMaximumDuration.value()) : nullptr + ); + } + }; + +} // namespace margelo::nitro::multipleimagepicker diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraDevice.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraDevice.kt new file mode 100644 index 00000000..cee78441 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraDevice.kt @@ -0,0 +1,25 @@ +/// +/// CameraDevice.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.multipleimagepicker + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip + +/** + * Represents the JavaScript enum/union "CameraDevice". + */ +@DoNotStrip +@Keep +enum class CameraDevice { + FRONT, + BACK; + + @DoNotStrip + @Keep + private val _ordinal = ordinal +} diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroConfig.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroConfig.kt index 5851eb1b..de5cf8d1 100644 --- a/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroConfig.kt +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroConfig.kt @@ -24,7 +24,6 @@ data class NitroConfig( val numberOfColumn: Double?, val isPreview: Boolean?, val primaryColor: Double?, - val allowedCamera: Boolean?, val allowSwipeToSelect: Boolean?, val spacing: Double?, val isHiddenPreviewButton: Boolean?, @@ -42,5 +41,6 @@ data class NitroConfig( val text: Text?, val language: Language, val theme: Theme, - val presentation: Presentation + val presentation: Presentation, + val camera: PickerCameraConfig? ) diff --git a/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCameraConfig.kt b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCameraConfig.kt new file mode 100644 index 00000000..afd67231 --- /dev/null +++ b/nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCameraConfig.kt @@ -0,0 +1,22 @@ +/// +/// PickerCameraConfig.kt +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +package com.margelo.nitro.multipleimagepicker + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.core.* + +/** + * Represents the JavaScript object/struct "PickerCameraConfig". + */ +@DoNotStrip +@Keep +data class PickerCameraConfig( + val cameraDevice: CameraDevice, + val videoMaximumDuration: Double? +) diff --git a/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp b/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp index f6741986..5f6b142c 100644 --- a/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp +++ b/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp @@ -8,6 +8,8 @@ #pragma once // Forward declarations of C++ defined types +// Forward declaration of `CameraDevice` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `CropResult` to properly resolve imports. @@ -16,6 +18,8 @@ namespace margelo::nitro::multipleimagepicker { struct CropResult; } namespace margelo::nitro::multipleimagepicker { class HybridMultipleImagePickerSpec; } // Forward declaration of `MediaPreview` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct MediaPreview; } +// Forward declaration of `PickerCameraConfig` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { struct PickerCameraConfig; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `ResultType` to properly resolve imports. @@ -30,10 +34,12 @@ namespace margelo::nitro::multipleimagepicker { struct Text; } namespace MultipleImagePicker { class HybridMultipleImagePickerSpecCxx; } // Include C++ defined types +#include "CameraDevice.hpp" #include "CropRatio.hpp" #include "CropResult.hpp" #include "HybridMultipleImagePickerSpec.hpp" #include "MediaPreview.hpp" +#include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "Result.hpp" #include "ResultType.hpp" @@ -126,6 +132,15 @@ namespace margelo::nitro::multipleimagepicker::bridge::swift { return std::optional(value); } + // pragma MARK: std::optional + /** + * Specialized version of `std::optional`. + */ + using std__optional_PickerCameraConfig_ = std::optional; + inline std::optional create_std__optional_PickerCameraConfig_(const PickerCameraConfig& value) { + return std::optional(value); + } + // pragma MARK: std::function& /* result */)> /** * Specialized version of `std::function&)>`. diff --git a/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Umbrella.hpp b/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Umbrella.hpp index 01b4aca3..1d15092a 100644 --- a/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Umbrella.hpp +++ b/nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Umbrella.hpp @@ -8,6 +8,8 @@ #pragma once // Forward declarations of C++ defined types +// Forward declaration of `CameraDevice` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `CropResult` to properly resolve imports. @@ -26,6 +28,8 @@ namespace margelo::nitro::multipleimagepicker { struct NitroConfig; } namespace margelo::nitro::multipleimagepicker { struct NitroCropConfig; } // Forward declaration of `NitroPreviewConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } +// Forward declaration of `PickerCameraConfig` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { struct PickerCameraConfig; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `Presentation` to properly resolve imports. @@ -44,6 +48,7 @@ namespace margelo::nitro::multipleimagepicker { struct Text; } namespace margelo::nitro::multipleimagepicker { enum class Theme; } // Include C++ defined types +#include "CameraDevice.hpp" #include "CropRatio.hpp" #include "CropResult.hpp" #include "HybridMultipleImagePickerSpec.hpp" @@ -53,6 +58,7 @@ namespace margelo::nitro::multipleimagepicker { enum class Theme; } #include "NitroConfig.hpp" #include "NitroCropConfig.hpp" #include "NitroPreviewConfig.hpp" +#include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "Presentation.hpp" #include "Result.hpp" diff --git a/nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp b/nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp index df9896f6..37aa344f 100644 --- a/nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp +++ b/nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp @@ -36,6 +36,10 @@ namespace margelo::nitro::multipleimagepicker { enum class Language; } namespace margelo::nitro::multipleimagepicker { enum class Theme; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } +// Forward declaration of `PickerCameraConfig` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { struct PickerCameraConfig; } +// Forward declaration of `CameraDevice` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } // Forward declaration of `NitroCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCropConfig; } // Forward declaration of `CropResult` to properly resolve imports. @@ -60,6 +64,8 @@ namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } #include "Language.hpp" #include "Theme.hpp" #include "Presentation.hpp" +#include "PickerCameraConfig.hpp" +#include "CameraDevice.hpp" #include #include "NitroCropConfig.hpp" #include "CropResult.hpp" diff --git a/nitrogen/generated/ios/swift/CameraDevice.swift b/nitrogen/generated/ios/swift/CameraDevice.swift new file mode 100644 index 00000000..49efc2d7 --- /dev/null +++ b/nitrogen/generated/ios/swift/CameraDevice.swift @@ -0,0 +1,40 @@ +/// +/// CameraDevice.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +/** + * Represents the JS union `CameraDevice`, backed by a C++ enum. + */ +public typealias CameraDevice = margelo.nitro.multipleimagepicker.CameraDevice + +public extension CameraDevice { + /** + * Get a CameraDevice for the given String value, or + * return `nil` if the given value was invalid/unknown. + */ + init?(fromString string: String) { + switch string { + case "front": + self = .front + case "back": + self = .back + default: + return nil + } + } + + /** + * Get the String value this CameraDevice represents. + */ + var stringValue: String { + switch self { + case .front: + return "front" + case .back: + return "back" + } + } +} diff --git a/nitrogen/generated/ios/swift/NitroConfig.swift b/nitrogen/generated/ios/swift/NitroConfig.swift index 59f80ea3..d456df5a 100644 --- a/nitrogen/generated/ios/swift/NitroConfig.swift +++ b/nitrogen/generated/ios/swift/NitroConfig.swift @@ -18,7 +18,7 @@ public extension NitroConfig { /** * Create a new instance of `NitroConfig`. */ - init(mediaType: MediaType, selectedAssets: [Result], selectBoxStyle: SelectBoxStyle, selectMode: SelectMode, numberOfColumn: Double?, isPreview: Bool?, primaryColor: Double?, allowedCamera: Bool?, allowSwipeToSelect: Bool?, spacing: Double?, isHiddenPreviewButton: Bool?, isHiddenOriginalButton: Bool?, isShowPreviewList: Bool?, allowHapticTouchPreview: Bool?, allowedLimit: Bool?, maxVideo: Double?, maxSelect: Double?, maxVideoDuration: Double?, minVideoDuration: Double?, maxFileSize: Double?, backgroundDark: Double?, crop: PickerCropConfig?, text: Text?, language: Language, theme: Theme, presentation: Presentation) { + init(mediaType: MediaType, selectedAssets: [Result], selectBoxStyle: SelectBoxStyle, selectMode: SelectMode, numberOfColumn: Double?, isPreview: Bool?, primaryColor: Double?, allowSwipeToSelect: Bool?, spacing: Double?, isHiddenPreviewButton: Bool?, isHiddenOriginalButton: Bool?, isShowPreviewList: Bool?, allowHapticTouchPreview: Bool?, allowedLimit: Bool?, maxVideo: Double?, maxSelect: Double?, maxVideoDuration: Double?, minVideoDuration: Double?, maxFileSize: Double?, backgroundDark: Double?, crop: PickerCropConfig?, text: Text?, language: Language, theme: Theme, presentation: Presentation, camera: PickerCameraConfig?) { self.init(mediaType, { () -> bridge.std__vector_Result_ in var __vector = bridge.create_std__vector_Result_(selectedAssets.count) for __item in selectedAssets { @@ -43,12 +43,6 @@ public extension NitroConfig { } else { return .init() } - }(), { () -> bridge.std__optional_bool_ in - if let __unwrappedValue = allowedCamera { - return bridge.create_std__optional_bool_(__unwrappedValue) - } else { - return .init() - } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = allowSwipeToSelect { return bridge.create_std__optional_bool_(__unwrappedValue) @@ -139,7 +133,13 @@ public extension NitroConfig { } else { return .init() } - }(), language, theme, presentation) + }(), language, theme, presentation, { () -> bridge.std__optional_PickerCameraConfig_ in + if let __unwrappedValue = camera { + return bridge.create_std__optional_PickerCameraConfig_(__unwrappedValue) + } else { + return .init() + } + }()) } var mediaType: MediaType { @@ -243,23 +243,6 @@ public extension NitroConfig { } } - var allowedCamera: Bool? { - @inline(__always) - get { - return self.__allowedCamera.value - } - @inline(__always) - set { - self.__allowedCamera = { () -> bridge.std__optional_bool_ in - if let __unwrappedValue = newValue { - return bridge.create_std__optional_bool_(__unwrappedValue) - } else { - return .init() - } - }() - } - } - var allowSwipeToSelect: Bool? { @inline(__always) get { @@ -559,4 +542,27 @@ public extension NitroConfig { self.__presentation = newValue } } + + var camera: PickerCameraConfig? { + @inline(__always) + get { + return { () -> PickerCameraConfig? in + if let __unwrapped = self.__camera.value { + return __unwrapped + } else { + return nil + } + }() + } + @inline(__always) + set { + self.__camera = { () -> bridge.std__optional_PickerCameraConfig_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_PickerCameraConfig_(__unwrappedValue) + } else { + return .init() + } + }() + } + } } diff --git a/nitrogen/generated/ios/swift/PickerCameraConfig.swift b/nitrogen/generated/ios/swift/PickerCameraConfig.swift new file mode 100644 index 00000000..889b54f4 --- /dev/null +++ b/nitrogen/generated/ios/swift/PickerCameraConfig.swift @@ -0,0 +1,58 @@ +/// +/// PickerCameraConfig.swift +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +import NitroModules + +/** + * Represents an instance of `PickerCameraConfig`, backed by a C++ struct. + */ +public typealias PickerCameraConfig = margelo.nitro.multipleimagepicker.PickerCameraConfig + +public extension PickerCameraConfig { + private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift + + /** + * Create a new instance of `PickerCameraConfig`. + */ + init(cameraDevice: CameraDevice, videoMaximumDuration: Double?) { + self.init(cameraDevice, { () -> bridge.std__optional_double_ in + if let __unwrappedValue = videoMaximumDuration { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }()) + } + + var cameraDevice: CameraDevice { + @inline(__always) + get { + return self.__cameraDevice + } + @inline(__always) + set { + self.__cameraDevice = newValue + } + } + + var videoMaximumDuration: Double? { + @inline(__always) + get { + return self.__videoMaximumDuration.value + } + @inline(__always) + set { + self.__videoMaximumDuration = { () -> bridge.std__optional_double_ in + if let __unwrappedValue = newValue { + return bridge.create_std__optional_double_(__unwrappedValue) + } else { + return .init() + } + }() + } + } +} diff --git a/nitrogen/generated/shared/c++/CameraDevice.hpp b/nitrogen/generated/shared/c++/CameraDevice.hpp new file mode 100644 index 00000000..73e2d0d5 --- /dev/null +++ b/nitrogen/generated/shared/c++/CameraDevice.hpp @@ -0,0 +1,78 @@ +/// +/// CameraDevice.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +namespace margelo::nitro::multipleimagepicker { + + /** + * An enum which can be represented as a JavaScript union (CameraDevice). + */ + enum class CameraDevice { + FRONT SWIFT_NAME(front) = 0, + BACK SWIFT_NAME(back) = 1, + } CLOSED_ENUM; + +} // namespace margelo::nitro::multipleimagepicker + +namespace margelo::nitro { + + using namespace margelo::nitro::multipleimagepicker; + + // C++ CameraDevice <> JS CameraDevice (union) + template <> + struct JSIConverter { + static inline CameraDevice fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + std::string unionValue = JSIConverter::fromJSI(runtime, arg); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("front"): return CameraDevice::FRONT; + case hashString("back"): return CameraDevice::BACK; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum CameraDevice - invalid value!"); + } + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, CameraDevice arg) { + switch (arg) { + case CameraDevice::FRONT: return JSIConverter::toJSI(runtime, "front"); + case CameraDevice::BACK: return JSIConverter::toJSI(runtime, "back"); + default: [[unlikely]] + throw std::invalid_argument("Cannot convert CameraDevice to JS - invalid value: " + + std::to_string(static_cast(arg)) + "!"); + } + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isString()) { + return false; + } + std::string unionValue = JSIConverter::fromJSI(runtime, value); + switch (hashString(unionValue.c_str(), unionValue.size())) { + case hashString("front"): + case hashString("back"): + return true; + default: + return false; + } + } + }; + +} // namespace margelo::nitro diff --git a/nitrogen/generated/shared/c++/NitroConfig.hpp b/nitrogen/generated/shared/c++/NitroConfig.hpp index a110ad02..acf1534d 100644 --- a/nitrogen/generated/shared/c++/NitroConfig.hpp +++ b/nitrogen/generated/shared/c++/NitroConfig.hpp @@ -36,6 +36,8 @@ namespace margelo::nitro::multipleimagepicker { enum class Language; } namespace margelo::nitro::multipleimagepicker { enum class Theme; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } +// Forward declaration of `PickerCameraConfig` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { struct PickerCameraConfig; } #include "MediaType.hpp" #include @@ -48,6 +50,7 @@ namespace margelo::nitro::multipleimagepicker { enum class Presentation; } #include "Language.hpp" #include "Theme.hpp" #include "Presentation.hpp" +#include "PickerCameraConfig.hpp" namespace margelo::nitro::multipleimagepicker { @@ -63,7 +66,6 @@ namespace margelo::nitro::multipleimagepicker { std::optional numberOfColumn SWIFT_PRIVATE; std::optional isPreview SWIFT_PRIVATE; std::optional primaryColor SWIFT_PRIVATE; - std::optional allowedCamera SWIFT_PRIVATE; std::optional allowSwipeToSelect SWIFT_PRIVATE; std::optional spacing SWIFT_PRIVATE; std::optional isHiddenPreviewButton SWIFT_PRIVATE; @@ -82,9 +84,10 @@ namespace margelo::nitro::multipleimagepicker { Language language SWIFT_PRIVATE; Theme theme SWIFT_PRIVATE; Presentation presentation SWIFT_PRIVATE; + std::optional camera SWIFT_PRIVATE; public: - explicit NitroConfig(MediaType mediaType, std::vector selectedAssets, SelectBoxStyle selectBoxStyle, SelectMode selectMode, std::optional numberOfColumn, std::optional isPreview, std::optional primaryColor, std::optional allowedCamera, std::optional allowSwipeToSelect, std::optional spacing, std::optional isHiddenPreviewButton, std::optional isHiddenOriginalButton, std::optional isShowPreviewList, std::optional allowHapticTouchPreview, std::optional allowedLimit, std::optional maxVideo, std::optional maxSelect, std::optional maxVideoDuration, std::optional minVideoDuration, std::optional maxFileSize, std::optional backgroundDark, std::optional crop, std::optional text, Language language, Theme theme, Presentation presentation): mediaType(mediaType), selectedAssets(selectedAssets), selectBoxStyle(selectBoxStyle), selectMode(selectMode), numberOfColumn(numberOfColumn), isPreview(isPreview), primaryColor(primaryColor), allowedCamera(allowedCamera), allowSwipeToSelect(allowSwipeToSelect), spacing(spacing), isHiddenPreviewButton(isHiddenPreviewButton), isHiddenOriginalButton(isHiddenOriginalButton), isShowPreviewList(isShowPreviewList), allowHapticTouchPreview(allowHapticTouchPreview), allowedLimit(allowedLimit), maxVideo(maxVideo), maxSelect(maxSelect), maxVideoDuration(maxVideoDuration), minVideoDuration(minVideoDuration), maxFileSize(maxFileSize), backgroundDark(backgroundDark), crop(crop), text(text), language(language), theme(theme), presentation(presentation) {} + explicit NitroConfig(MediaType mediaType, std::vector selectedAssets, SelectBoxStyle selectBoxStyle, SelectMode selectMode, std::optional numberOfColumn, std::optional isPreview, std::optional primaryColor, std::optional allowSwipeToSelect, std::optional spacing, std::optional isHiddenPreviewButton, std::optional isHiddenOriginalButton, std::optional isShowPreviewList, std::optional allowHapticTouchPreview, std::optional allowedLimit, std::optional maxVideo, std::optional maxSelect, std::optional maxVideoDuration, std::optional minVideoDuration, std::optional maxFileSize, std::optional backgroundDark, std::optional crop, std::optional text, Language language, Theme theme, Presentation presentation, std::optional camera): mediaType(mediaType), selectedAssets(selectedAssets), selectBoxStyle(selectBoxStyle), selectMode(selectMode), numberOfColumn(numberOfColumn), isPreview(isPreview), primaryColor(primaryColor), allowSwipeToSelect(allowSwipeToSelect), spacing(spacing), isHiddenPreviewButton(isHiddenPreviewButton), isHiddenOriginalButton(isHiddenOriginalButton), isShowPreviewList(isShowPreviewList), allowHapticTouchPreview(allowHapticTouchPreview), allowedLimit(allowedLimit), maxVideo(maxVideo), maxSelect(maxSelect), maxVideoDuration(maxVideoDuration), minVideoDuration(minVideoDuration), maxFileSize(maxFileSize), backgroundDark(backgroundDark), crop(crop), text(text), language(language), theme(theme), presentation(presentation), camera(camera) {} }; } // namespace margelo::nitro::multipleimagepicker @@ -106,7 +109,6 @@ namespace margelo::nitro { JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "numberOfColumn")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isPreview")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "primaryColor")), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "allowedCamera")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "allowSwipeToSelect")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "spacing")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isHiddenPreviewButton")), @@ -124,7 +126,8 @@ namespace margelo::nitro { JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "text")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "language")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "theme")), - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "presentation")) + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "presentation")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "camera")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const NitroConfig& arg) { @@ -136,7 +139,6 @@ namespace margelo::nitro { obj.setProperty(runtime, "numberOfColumn", JSIConverter>::toJSI(runtime, arg.numberOfColumn)); obj.setProperty(runtime, "isPreview", JSIConverter>::toJSI(runtime, arg.isPreview)); obj.setProperty(runtime, "primaryColor", JSIConverter>::toJSI(runtime, arg.primaryColor)); - obj.setProperty(runtime, "allowedCamera", JSIConverter>::toJSI(runtime, arg.allowedCamera)); obj.setProperty(runtime, "allowSwipeToSelect", JSIConverter>::toJSI(runtime, arg.allowSwipeToSelect)); obj.setProperty(runtime, "spacing", JSIConverter>::toJSI(runtime, arg.spacing)); obj.setProperty(runtime, "isHiddenPreviewButton", JSIConverter>::toJSI(runtime, arg.isHiddenPreviewButton)); @@ -155,6 +157,7 @@ namespace margelo::nitro { obj.setProperty(runtime, "language", JSIConverter::toJSI(runtime, arg.language)); obj.setProperty(runtime, "theme", JSIConverter::toJSI(runtime, arg.theme)); obj.setProperty(runtime, "presentation", JSIConverter::toJSI(runtime, arg.presentation)); + obj.setProperty(runtime, "camera", JSIConverter>::toJSI(runtime, arg.camera)); return obj; } static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { @@ -169,7 +172,6 @@ namespace margelo::nitro { if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "numberOfColumn"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isPreview"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "primaryColor"))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "allowedCamera"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "allowSwipeToSelect"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "spacing"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isHiddenPreviewButton"))) return false; @@ -188,6 +190,7 @@ namespace margelo::nitro { if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "language"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "theme"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "presentation"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "camera"))) return false; return true; } }; diff --git a/nitrogen/generated/shared/c++/PickerCameraConfig.hpp b/nitrogen/generated/shared/c++/PickerCameraConfig.hpp new file mode 100644 index 00000000..649b447f --- /dev/null +++ b/nitrogen/generated/shared/c++/PickerCameraConfig.hpp @@ -0,0 +1,74 @@ +/// +/// PickerCameraConfig.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/mrousavy/nitro +/// Copyright © 2024 Marc Rousavy @ Margelo +/// + +#pragma once + +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif +#if __has_include() +#include +#else +#error NitroModules cannot be found! Are you sure you installed NitroModules properly? +#endif + +// Forward declaration of `CameraDevice` to properly resolve imports. +namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } + +#include "CameraDevice.hpp" +#include + +namespace margelo::nitro::multipleimagepicker { + + /** + * A struct which can be represented as a JavaScript object (PickerCameraConfig). + */ + struct PickerCameraConfig { + public: + CameraDevice cameraDevice SWIFT_PRIVATE; + std::optional videoMaximumDuration SWIFT_PRIVATE; + + public: + explicit PickerCameraConfig(CameraDevice cameraDevice, std::optional videoMaximumDuration): cameraDevice(cameraDevice), videoMaximumDuration(videoMaximumDuration) {} + }; + +} // namespace margelo::nitro::multipleimagepicker + +namespace margelo::nitro { + + using namespace margelo::nitro::multipleimagepicker; + + // C++ PickerCameraConfig <> JS PickerCameraConfig (object) + template <> + struct JSIConverter { + static inline PickerCameraConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return PickerCameraConfig( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "cameraDevice")), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "videoMaximumDuration")) + ); + } + static inline jsi::Value toJSI(jsi::Runtime& runtime, const PickerCameraConfig& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, "cameraDevice", JSIConverter::toJSI(runtime, arg.cameraDevice)); + obj.setProperty(runtime, "videoMaximumDuration", JSIConverter>::toJSI(runtime, arg.videoMaximumDuration)); + return obj; + } + static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "cameraDevice"))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "videoMaximumDuration"))) return false; + return true; + } + }; + +} // namespace margelo::nitro diff --git a/src/index.ts b/src/index.ts index 901c0671..30bfbe6d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -76,7 +76,7 @@ export async function openCropper( config.language = 'system' } - Picker.openCrop( + return Picker.openCrop( image, cropConfig, (result: CropResult) => { @@ -107,7 +107,7 @@ export function openPreview( throw new Error('Media is required') } - Picker.openPreview( + return Picker.openPreview( media as MediaPreview[], index, config as NitroPreviewConfig @@ -123,7 +123,6 @@ export const defaultOptions: Config = { maxVideo: DEFAULT_COUNT, primaryColor: '#FB9300', backgroundDark: '#2f2f2f', - allowedCamera: true, allowedLimit: true, numberOfColumn: 3, isPreview: true, @@ -136,6 +135,10 @@ export const defaultOptions: Config = { theme: 'system', isHiddenOriginalButton: false, allowSwipeToSelect: true, + camera: { + cameraDevice: 'front', + videoMaximumDuration: 60, + }, } const LANGUAGES = [ diff --git a/src/types/camera.ts b/src/types/camera.ts new file mode 100644 index 00000000..d2223774 --- /dev/null +++ b/src/types/camera.ts @@ -0,0 +1,32 @@ +import { MediaType } from './config' + +export type CameraDevice = 'front' | 'back' + +export type PickerCameraConfig = { + cameraDevice: CameraDevice + videoMaximumDuration?: number +} + +export interface NitroCameraConfig extends PickerCameraConfig { + mediaType: MediaType +} + +export interface CameraConfig + extends Omit { + /** + * Type of camera + * @typedef {'front' | 'back'} CameraDevice + */ + cameraDevice: CameraDevice + + /** + * Type of media to be displayed + * @typedef {'video' | 'image' | 'all'} MediaType + */ + mediaType: MediaType + + /** + * Maximum duration of video + * @type {number} + */ +} diff --git a/src/types/config.ts b/src/types/config.ts index 83939033..96a81e61 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,6 +1,3 @@ -import { ColorValue } from 'react-native' -import { Result } from './result' - export type Theme = 'light' | 'dark' export type Presentation = 'fullScreenModal' | 'formSheet' @@ -20,487 +17,6 @@ export type Language = | 'fr' | 'ar' -export type SelectBoxStyle = 'number' | 'tick' - -export type SelectMode = 'single' | 'multiple' - export type MediaType = 'video' | 'image' | 'all' export type CropRatio = { title?: string; width: number; height: number } - -/** - * Configuration for image cropping - * @interface PickerCropConfig - */ -export type PickerCropConfig = { - /** Enable circular crop mask */ - circle?: boolean - - ratio: CropRatio[] - - /** - * Default ratio to be selected when opening the crop interface. - * If not specified, the first ratio in the list will be selected. - * - * @platform ios, android - * - * @example - * ```ts - * // Custom ratio without title - * defaultRatio: { width: 4, height: 3 } - */ - defaultRatio?: CropRatio - - /** Enable free style cropping */ - freeStyle?: boolean -} - -/** - * Custom text labels for buttons and headers - * @interface Text - */ -export interface Text { - /** Text for finish/done button */ - finish?: string - /** Text for original button */ - original?: string - /** Text for preview button */ - preview?: string - /** Text for edit button */ - edit?: string -} - -/** - * Main configuration interface for the Nitro image picker - * @interface NitroConfig - */ -export interface NitroConfig { - /** - * Type of media to display in picker - * @type {MediaType} - */ - mediaType: MediaType - - /** - * Array of currently selected assets - * @type {Result[]} - */ - selectedAssets: Result[] - - /** - * Style of the selection box - * @type {SelectBoxStyle} - */ - selectBoxStyle: SelectBoxStyle - - /** - * Selection mode for picker - * @type {SelectMode} - */ - selectMode: SelectMode - - /** - * Number of columns in the grid view - * @type {number} - */ - numberOfColumn?: number - - /** - * Enable preview functionality - * @type {boolean} - */ - isPreview?: boolean - - /** - * Primary color value in number format - * @type {number} - */ - primaryColor?: number - - /** - * Enable camera functionality - * @type {boolean} - */ - allowedCamera?: boolean - - /** - * Enable swipe gesture for selection - * @type {boolean} - */ - allowSwipeToSelect?: boolean - - /** - * Spacing between items in the grid - * @type {number} - */ - spacing?: number - - /** - * Hide the preview button and button mode - * @type {boolean} - */ - isHiddenPreviewButton?: boolean - - /** - * Hide the original button - * @type {boolean} - */ - isHiddenOriginalButton?: boolean - - /** - * Show preview list - * @type {boolean} - * @platform ios - */ - isShowPreviewList?: boolean - - /** - * Enable haptic feedback on preview - * @type {boolean} - * @platform ios - */ - allowHapticTouchPreview?: boolean - - /** - * Enable selection limit - * @type {boolean} - */ - allowedLimit?: boolean - - /** - * Maximum number of videos allowed - * @type {number} - */ - maxVideo?: number - - /** - * Maximum number of items that can be selected - * @type {number} - */ - maxSelect?: number - - /** - * Maximum duration for videos in seconds - * @type {number} - */ - maxVideoDuration?: number - - /** - * Minimum duration for videos in seconds - * @type {number} - */ - minVideoDuration?: number - - /** - * Maximum file size in bytes - * @type {number} - */ - maxFileSize?: number - - /** - * Background color for dark mode in number format - * @type {number} - */ - backgroundDark?: number - - /** - * Configuration options for image cropping functionality. - * - * @type {PickerCropConfig} - * @property {boolean} [circle] - Enable circular crop mask for profile pictures - * - * @example - * ```ts - * // -> Enable basic cropping with default settings - * crop: {} - * - * // -> Enable cropping with circle crop mask - * crop: { - * circle: true, - * } - * ``` - * - * @platform ios, android - */ - crop?: PickerCropConfig - - /** - * Custom text labels for various UI elements in the picker. - * Allows customization of button labels and headers to support localization and branding. - * - * @type {Text} - * @property {string} [finish] - Label for the finish/done button - * @property {string} [original] - Label for the original button - * @property {string} [preview] - Label for the preview button - * @property {string} [edit] - Label for the edit button - * - * @example - * ```ts - * text: { - * finish: 'Complete', - * original: 'Original', - * preview: 'Preview', - * edit: 'Edit' - * } - * ``` - * - * @remarks - * - All properties are optional and will use default values if not specified - * - Useful for localization and customizing the user interface - */ - text?: Text - - /** - * Interface language - * @type {Language} - */ - language: Language - - /** - * Theme mode - * @type {Theme} - */ - theme: Theme - - presentation: Presentation -} - -export interface Config - extends Omit< - NitroConfig, - | 'selectedAssets' - | 'mediaType' - | 'selectMode' - | 'selectBoxStyle' - | 'primaryColor' - | 'presentation' - | 'language' - | 'theme' - | 'backgroundDark' - | 'crop' - > { - /** - * Type of media to be displayed - * @typedef {'video' | 'image' | 'all'} MediaType - */ - mediaType?: MediaType - - /** - * Array of currently selected assets - * @type {Result[]} - */ - selectedAssets?: Result[] - - /** - * Style of selection box in the picker - * @typedef {'number' | 'tick'} SelectBoxStyle - */ - selectBoxStyle?: SelectBoxStyle - - /** - * Mode of selection in the picker - * @typedef {'single' | 'multiple'} SelectMode - */ - selectMode?: SelectMode - - /** - * Primary color for the picker UI elements. - * Accepts various color formats: - * - Hex strings: '#RGB', '#RGBA', '#RRGGBB', '#RRGGBBAA' - * - RGB/RGBA strings: 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 0.5)' - * - Named colors: 'red', 'blue', etc. - * - Numbers for RGB values - * - * @platform ios, android - * @type {ColorValue} - * @example - * ```ts - * primaryColor: '#FF0000' - * primaryColor: 'rgb(255, 0, 0)' - * primaryColor: 'red' - * ``` - */ - primaryColor?: ColorValue - - /** - * Modal presentation style for the picker. - * - 'fullScreenModal': Opens picker in full screen - * - 'formSheet': Opens picker in a form sheet style - * - * @platform ios - * @default 'fullScreenModal' - * @type {Presentation} - * @example - * ```ts - * presentation: 'formSheet' - * ``` - */ - presentation?: Presentation - - /** - * Language options for the picker. - * @description - * - 'system': 🌐 System default - * - 'zh-Hans': 🇨🇳 Simplified Chinese - * - 'zh-Hant': 🇹🇼 Traditional Chinese - * - 'ja': 🇯🇵 Japanese - * - 'ko': 🇰🇷 Korean - * - 'en': 🇬🇧 English - * - 'th': 🇹🇭 Thai - * - 'id': 🇮🇩 Indonesian - * - 'vi': 🇻🇳 Vietnamese (My Country) - * - 'ru': 🇷🇺 Russian - * - 'de': 🇩🇪 German - * - 'fr': 🇫🇷 French - * - 'ar': 🇸🇦 Arabic - */ - language?: Language - - /** - * Theme mode for the picker. - * - 'light': Uses light theme - * - 'dark': Uses dark theme - * - 'system': Uses system default theme - * - * @platform ios, android - * @default 'system' - * @type {'light' | 'dark' | 'system'} - */ - theme?: Theme | 'system' - - /** - * Background color for dark mode UI elements. - * Accepts various color formats: - * - Hex strings: '#RGB', '#RGBA', '#RRGGBB', '#RRGGBBAA' - * - RGB/RGBA strings: 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 0.5)' - * - Named colors: 'red', 'blue', etc. - * - Numbers for RGB values - * - * @platform ios, android - * @type {ColorValue} - * @example - * ```ts - * backgroundDark: '#000000' - * backgroundDark: 'rgb(0, 0, 0)' - * backgroundDark: 'black' - * ``` - */ - backgroundDark?: ColorValue - - /** - * Configuration for image cropping - * @interface PickerCropConfig - */ - crop?: Omit & { - /** - * Array of aspect ratios for image cropping. The ratios will be inserted after the default ratios (Original and Square). - * Android: Maximum: 4 items - * - * @platform ios, Android - * - * @property {Array} ratio - Array of custom aspect ratios - * @property {string} [ratio[].title] - Optional display title for the ratio (e.g., "16:9"). If not provided, will use "width/height" - * @property {number} ratio[].width - Width value for aspect ratio - * @property {number} ratio[].height - Height value for aspect ratio - * - * @example - * ```ts - * ratio: [ - * { title: "Instagram", width: 1, height: 1 }, - * { title: "Twitter", width: 16, height: 9 }, - * { width: 12, height: 11 } - * ] - * ``` - */ - ratio?: CropRatio[] - } -} - -// CROP - -export interface NitroCropConfig extends PickerCropConfig { - /** - * Interface language - * @type {Language} - */ - language: Language - - presentation: Presentation -} - -export interface CropConfig - extends Omit { - /** - * Language options for the picker. - * - * @platform ios - * - * @description - * - 'system': 🌐 System default - * - 'zh-Hans': 🇨🇳 Simplified Chinese - * - 'zh-Hant': 🇹🇼 Traditional Chinese - * - 'ja': 🇯🇵 Japanese - * - 'ko': 🇰🇷 Korean - * - 'en': 🇬🇧 English - * - 'th': 🇹🇭 Thai - * - 'id': 🇮🇩 Indonesian - * - 'vi': 🇻🇳 Vietnamese (My Country) - * - 'ru': 🇷🇺 Russian - * - 'de': 🇩🇪 German - * - 'fr': 🇫🇷 French - * - 'ar': 🇸🇦 Arabic - */ - language?: Language - - /** - * Array of aspect ratios for image cropping. The ratios will be inserted after the default ratios (Original and Square). - * Android: Maximum: 4 items - * - * @platform ios, android - * - * @property {Array} ratio - Array of custom aspect ratios - * @property {string} [ratio[].title] - Optional display title for the ratio (e.g., "16:9"). If not provided, will use "width/height" - * @property {number} ratio[].width - Width value for aspect ratio - * @property {number} ratio[].height - Height value for aspect ratio - * - * @example - * ```ts - * ratio: [ - * { title: "Instagram", width: 1, height: 1 }, - * { title: "Twitter", width: 16, height: 9 }, - * { width: 12, height: 11 } - * ] - * ``` - */ - ratio?: CropRatio[] -} - -// PREVIEW -export type NitroPreviewConfig = { - language: Language -} - -export interface PreviewConfig - extends Omit { - /** - * Language options for the picker. - * - * @platform ios - * - * @description - * - 'system': 🌐 System default - * - 'zh-Hans': 🇨🇳 Simplified Chinese - * - 'zh-Hant': 🇹🇼 Traditional Chinese - * - 'ja': 🇯🇵 Japanese - * - 'ko': 🇰🇷 Korean - * - 'en': 🇬🇧 English - * - 'th': 🇹🇭 Thai - * - 'id': 🇮🇩 Indonesian - * - 'vi': 🇻🇳 Vietnamese (My Country) - * - 'ru': 🇷🇺 Russian - * - 'de': 🇩🇪 German - * - 'fr': 🇫🇷 French - * - 'ar': 🇸🇦 Arabic - */ - language?: Language -} diff --git a/src/types/crop.ts b/src/types/crop.ts new file mode 100644 index 00000000..5670af06 --- /dev/null +++ b/src/types/crop.ts @@ -0,0 +1,92 @@ +import { CropRatio, Language, Presentation } from './config' + +/** + * Configuration for image cropping + * @interface PickerCropConfig + */ +export type PickerCropConfig = { + /** Enable circular crop mask */ + circle?: boolean + + ratio: CropRatio[] + + /** + * Default ratio to be selected when opening the crop interface. + * If not specified, the first ratio in the list will be selected. + * + * @platform ios, android + * + * @example + * ```ts + * // Custom ratio without title + * defaultRatio: { width: 4, height: 3 } + */ + defaultRatio?: CropRatio + + /** Enable free style cropping */ + freeStyle?: boolean +} + +// CROP +export interface NitroCropConfig extends PickerCropConfig { + /** + * Interface language + * @type {Language} + */ + language: Language + + presentation: Presentation +} + +export interface CropConfig + extends Omit { + /** + * Language options for the picker. + * + * @platform ios + * + * @description + * - 'system': 🌐 System default + * - 'zh-Hans': 🇨🇳 Simplified Chinese + * - 'zh-Hant': 🇹🇼 Traditional Chinese + * - 'ja': 🇯🇵 Japanese + * - 'ko': 🇰🇷 Korean + * - 'en': 🇬🇧 English + * - 'th': 🇹🇭 Thai + * - 'id': 🇮🇩 Indonesian + * - 'vi': 🇻🇳 Vietnamese (My Country) + * - 'ru': 🇷🇺 Russian + * - 'de': 🇩🇪 German + * - 'fr': 🇫🇷 French + * - 'ar': 🇸🇦 Arabic + */ + language?: Language + + /** + * Array of aspect ratios for image cropping. The ratios will be inserted after the default ratios (Original and Square). + * Android: Maximum: 4 items + * + * @platform ios, android + * + * @property {Array} ratio - Array of custom aspect ratios + * @property {string} [ratio[].title] - Optional display title for the ratio (e.g., "16:9"). If not provided, will use "width/height" + * @property {number} ratio[].width - Width value for aspect ratio + * @property {number} ratio[].height - Height value for aspect ratio + * + * @example + * ```ts + * ratio: [ + * { title: "Instagram", width: 1, height: 1 }, + * { title: "Twitter", width: 16, height: 9 }, + * { width: 12, height: 11 } + * ] + * ``` + */ + ratio?: CropRatio[] +} + +export interface CropResult { + path: string + width: number + height: number +} diff --git a/src/types/index.ts b/src/types/index.ts index ac22cc34..218313bc 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -2,4 +2,7 @@ // export * from './error' export * from './result' export * from './config' -export * from './media' +export * from './crop' +export * from './preview' +export * from './picker' +export * from './camera' diff --git a/src/types/media.ts b/src/types/media.ts deleted file mode 100644 index f4cd5720..00000000 --- a/src/types/media.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ResultType } from './result' - -export interface MediaPreview { - type: ResultType - path?: string - thumbnail?: string - localIdentifier?: string -} diff --git a/src/types/picker.ts b/src/types/picker.ts new file mode 100644 index 00000000..514d2dae --- /dev/null +++ b/src/types/picker.ts @@ -0,0 +1,378 @@ +import { ColorValue } from 'react-native' +import { CropRatio, Language, MediaType, Presentation, Theme } from './config' +import { Result } from './result' +import { PickerCropConfig } from './crop' +import { PickerCameraConfig } from './camera' + +export type SelectBoxStyle = 'number' | 'tick' + +export type SelectMode = 'single' | 'multiple' + +/** + * Custom text labels for buttons and headers + * @interface Text + */ +export interface Text { + /** Text for finish/done button */ + finish?: string + /** Text for original button */ + original?: string + /** Text for preview button */ + preview?: string + /** Text for edit button */ + edit?: string +} + +/** + * Main configuration interface for the Nitro image picker + * @interface NitroConfig + */ +export interface NitroConfig { + /** + * Type of media to display in picker + * @type {MediaType} + */ + mediaType: MediaType + + /** + * Array of currently selected assets + * @type {Result[]} + */ + selectedAssets: Result[] + + /** + * Style of the selection box + * @type {SelectBoxStyle} + */ + selectBoxStyle: SelectBoxStyle + + /** + * Selection mode for picker + * @type {SelectMode} + */ + selectMode: SelectMode + + /** + * Number of columns in the grid view + * @type {number} + */ + numberOfColumn?: number + + /** + * Enable preview functionality + * @type {boolean} + */ + isPreview?: boolean + + /** + * Primary color value in number format + * @type {number} + */ + primaryColor?: number + /** + * Enable swipe gesture for selection + * @type {boolean} + */ + allowSwipeToSelect?: boolean + + /** + * Spacing between items in the grid + * @type {number} + */ + spacing?: number + + /** + * Hide the preview button and button mode + * @type {boolean} + */ + isHiddenPreviewButton?: boolean + + /** + * Hide the original button + * @type {boolean} + */ + isHiddenOriginalButton?: boolean + + /** + * Show preview list + * @type {boolean} + * @platform ios + */ + isShowPreviewList?: boolean + + /** + * Enable haptic feedback on preview + * @type {boolean} + * @platform ios + */ + allowHapticTouchPreview?: boolean + + /** + * Enable selection limit + * @type {boolean} + */ + allowedLimit?: boolean + + /** + * Maximum number of videos allowed + * @type {number} + */ + maxVideo?: number + + /** + * Maximum number of items that can be selected + * @type {number} + */ + maxSelect?: number + + /** + * Maximum duration for videos in seconds + * @type {number} + */ + maxVideoDuration?: number + + /** + * Minimum duration for videos in seconds + * @type {number} + */ + minVideoDuration?: number + + /** + * Maximum file size in bytes + * @type {number} + */ + maxFileSize?: number + + /** + * Background color for dark mode in number format + * @type {number} + */ + backgroundDark?: number + + /** + * Configuration options for image cropping functionality. + * + * @type {PickerCropConfig} + * @property {boolean} [circle] - Enable circular crop mask for profile pictures + * + * @example + * ```ts + * // -> Enable basic cropping with default settings + * crop: {} + * + * // -> Enable cropping with circle crop mask + * crop: { + * circle: true, + * } + * ``` + * + * @platform ios, android + */ + crop?: PickerCropConfig + + /** + * Custom text labels for various UI elements in the picker. + * Allows customization of button labels and headers to support localization and branding. + * + * @type {Text} + * @property {string} [finish] - Label for the finish/done button + * @property {string} [original] - Label for the original button + * @property {string} [preview] - Label for the preview button + * @property {string} [edit] - Label for the edit button + * + * @example + * ```ts + * text: { + * finish: 'Complete', + * original: 'Original', + * preview: 'Preview', + * edit: 'Edit' + * } + * ``` + * + * @remarks + * - All properties are optional and will use default values if not specified + * - Useful for localization and customizing the user interface + */ + text?: Text + + /** + * Interface language + * @type {Language} + */ + language: Language + + /** + * Theme mode + * @type {Theme} + */ + theme: Theme + + presentation: Presentation + + /** + * Camera configuration + * @type {PickerCameraConfig} + */ + camera?: PickerCameraConfig +} + +export interface Config + extends Omit< + NitroConfig, + | 'selectedAssets' + | 'mediaType' + | 'selectMode' + | 'selectBoxStyle' + | 'primaryColor' + | 'presentation' + | 'language' + | 'theme' + | 'backgroundDark' + | 'crop' + | 'camera' + > { + /** + * Type of media to be displayed + * @typedef {'video' | 'image' | 'all'} MediaType + */ + mediaType?: MediaType + + /** + * Array of currently selected assets + * @type {Result[]} + */ + selectedAssets?: Result[] + + /** + * Style of selection box in the picker + * @typedef {'number' | 'tick'} SelectBoxStyle + */ + selectBoxStyle?: SelectBoxStyle + + /** + * Mode of selection in the picker + * @typedef {'single' | 'multiple'} SelectMode + */ + selectMode?: SelectMode + + /** + * Primary color for the picker UI elements. + * Accepts various color formats: + * - Hex strings: '#RGB', '#RGBA', '#RRGGBB', '#RRGGBBAA' + * - RGB/RGBA strings: 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 0.5)' + * - Named colors: 'red', 'blue', etc. + * - Numbers for RGB values + * + * @platform ios, android + * @type {ColorValue} + * @example + * ```ts + * primaryColor: '#FF0000' + * primaryColor: 'rgb(255, 0, 0)' + * primaryColor: 'red' + * ``` + */ + primaryColor?: ColorValue + + /** + * Modal presentation style for the picker. + * - 'fullScreenModal': Opens picker in full screen + * - 'formSheet': Opens picker in a form sheet style + * + * @platform ios + * @default 'fullScreenModal' + * @type {Presentation} + * @example + * ```ts + * presentation: 'formSheet' + * ``` + */ + presentation?: Presentation + + /** + * Language options for the picker. + * @description + * - 'system': 🌐 System default + * - 'zh-Hans': 🇨🇳 Simplified Chinese + * - 'zh-Hant': 🇹🇼 Traditional Chinese + * - 'ja': 🇯🇵 Japanese + * - 'ko': 🇰🇷 Korean + * - 'en': 🇬🇧 English + * - 'th': 🇹🇭 Thai + * - 'id': 🇮🇩 Indonesian + * - 'vi': 🇻🇳 Vietnamese (My Country) + * - 'ru': 🇷🇺 Russian + * - 'de': 🇩🇪 German + * - 'fr': 🇫🇷 French + * - 'ar': 🇸🇦 Arabic + */ + language?: Language + + /** + * Theme mode for the picker. + * - 'light': Uses light theme + * - 'dark': Uses dark theme + * - 'system': Uses system default theme + * + * @platform ios, android + * @default 'system' + * @type {'light' | 'dark' | 'system'} + */ + theme?: Theme | 'system' + + /** + * Background color for dark mode UI elements. + * Accepts various color formats: + * - Hex strings: '#RGB', '#RGBA', '#RRGGBB', '#RRGGBBAA' + * - RGB/RGBA strings: 'rgb(255, 0, 0)', 'rgba(255, 0, 0, 0.5)' + * - Named colors: 'red', 'blue', etc. + * - Numbers for RGB values + * + * @platform ios, android + * @type {ColorValue} + * @example + * ```ts + * backgroundDark: '#000000' + * backgroundDark: 'rgb(0, 0, 0)' + * backgroundDark: 'black' + * ``` + */ + backgroundDark?: ColorValue + + /** + * Configuration for image cropping + * @interface PickerCropConfig + */ + + crop?: Omit & { + /** + * Array of aspect ratios for image cropping. The ratios will be inserted after the default ratios (Original and Square). + * Android: Maximum: 4 items + * + * @platform ios, Android + * + * @property {Array} ratio - Array of custom aspect ratios + * @property {string} [ratio[].title] - Optional display title for the ratio (e.g., "16:9"). If not provided, will use "width/height" + * @property {number} ratio[].width - Width value for aspect ratio + * @property {number} ratio[].height - Height value for aspect ratio + * + * @example + * ```ts + * ratio: [ + * { title: "Instagram", width: 1, height: 1 }, + * { title: "Twitter", width: 16, height: 9 }, + * { width: 12, height: 11 } + * ] + * ``` + */ + ratio?: CropRatio[] + + /** + * Camera configuration + * @type {CameraConfig} + */ + } + + camera?: PickerCameraConfig +} diff --git a/src/types/preview.ts b/src/types/preview.ts new file mode 100644 index 00000000..e61c994a --- /dev/null +++ b/src/types/preview.ts @@ -0,0 +1,39 @@ +import { Language } from './config' +import { ResultType } from './result' + +// PREVIEW +export type NitroPreviewConfig = { + language: Language +} + +export interface PreviewConfig + extends Omit { + /** + * Language options for the picker. + * + * @platform ios + * + * @description + * - 'system': 🌐 System default + * - 'zh-Hans': 🇨🇳 Simplified Chinese + * - 'zh-Hant': 🇹🇼 Traditional Chinese + * - 'ja': 🇯🇵 Japanese + * - 'ko': 🇰🇷 Korean + * - 'en': 🇬🇧 English + * - 'th': 🇹🇭 Thai + * - 'id': 🇮🇩 Indonesian + * - 'vi': 🇻🇳 Vietnamese (My Country) + * - 'ru': 🇷🇺 Russian + * - 'de': 🇩🇪 German + * - 'fr': 🇫🇷 French + * - 'ar': 🇸🇦 Arabic + */ + language?: Language +} + +export interface MediaPreview { + type: ResultType + path?: string + thumbnail?: string + localIdentifier?: string +} diff --git a/src/types/result.ts b/src/types/result.ts index 9d60f693..59e875f0 100644 --- a/src/types/result.ts +++ b/src/types/result.ts @@ -17,9 +17,3 @@ export interface Result { thumbnail?: string crop?: boolean } - -export interface CropResult { - path: string - width: number - height: number -}