Repository: baronha/react-native-multiple-image-picker Branch: main Commit: defc08c12fe7 Files: 239 Total size: 528.8 KB Directory structure: gitextract_k5e7rspq/ ├── .circleci/ │ └── config.yml ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── docs.yml ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── MultipleImagePicker.podspec ├── README.md ├── android/ │ ├── CMakeLists.txt │ ├── build.gradle │ ├── gradle.properties │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── cpp/ │ │ └── cpp-adapter.cpp │ ├── java/ │ │ └── com/ │ │ └── margelo/ │ │ └── nitro/ │ │ └── multipleimagepicker/ │ │ ├── CameraEngine.kt │ │ ├── Constant.kt │ │ ├── CropEngine.kt │ │ ├── ExoPlayerEngine.kt │ │ ├── GlideEngine.kt │ │ ├── ImageLoaderUtils.kt │ │ ├── LoadingDialog.kt │ │ ├── MultipleImagePicker.kt │ │ ├── MultipleImagePickerImp.kt │ │ ├── MultipleImagePickerPackage.java │ │ ├── PictureSelectorEngineImp.kt │ │ └── VideoThumbnailEngine.kt │ └── res/ │ ├── anim/ │ │ └── anim_modal_in.xml │ ├── drawable/ │ │ ├── checkbox_selector.xml │ │ ├── complete_button.xml │ │ ├── ic_checkmark.xml │ │ ├── ic_down.xml │ │ ├── num_oval.xml │ │ ├── picture_not_selected.xml │ │ ├── picture_selector.xml │ │ ├── preview_gallery_item.xml │ │ └── preview_gallery_white_bg.xml │ ├── layout/ │ │ └── loading_dialog.xml │ └── values/ │ ├── colors.xml │ └── styles.xml ├── babel.config.js ├── docs/ │ ├── .gitignore │ ├── docs/ │ │ ├── CAMERA.mdx │ │ ├── CONFIG.mdx │ │ ├── CROP.mdx │ │ ├── GETTING_STARTED.mdx │ │ ├── PREVIEW.mdx │ │ ├── RESULT.mdx │ │ ├── SHOWCASE/ │ │ │ ├── index.mdx │ │ │ ├── showcase.css │ │ │ └── showcase.json │ │ ├── USAGE.mdx │ │ └── index.md │ ├── docusaurus.config.ts │ ├── package.json │ ├── patches/ │ │ └── @gorhom+docusaurus-preset+1.0.2.patch │ ├── sidebars.ts │ ├── src/ │ │ └── css/ │ │ └── custom.css │ ├── static/ │ │ └── .nojekyll │ └── tsconfig.json ├── example/ │ ├── .gitignore │ ├── App.tsx │ ├── Gemfile │ ├── README.md │ ├── app.json │ ├── babel.config.js │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src/ │ │ ├── assets/ │ │ │ └── index.ts │ │ ├── common/ │ │ │ └── const.ts │ │ ├── components/ │ │ │ ├── BottomSheet.tsx │ │ │ ├── Button.tsx │ │ │ ├── CheckBox.tsx │ │ │ ├── CodeTag.tsx │ │ │ ├── Container.tsx │ │ │ ├── CounterView.tsx │ │ │ ├── Divider.tsx │ │ │ ├── Input.tsx │ │ │ ├── Row.tsx │ │ │ ├── SectionView.tsx │ │ │ ├── SegmentControl.tsx │ │ │ ├── Text.tsx │ │ │ ├── View.tsx │ │ │ └── index.tsx │ │ ├── hook/ │ │ │ ├── context.ts │ │ │ ├── index.ts │ │ │ └── useTheme.ts │ │ ├── index.tsx │ │ └── theme/ │ │ ├── color.ts │ │ └── size.ts │ └── tsconfig.json ├── ios/ │ ├── Assets.swift │ ├── Assets.xcassets/ │ │ ├── Contents.json │ │ └── close.imageset/ │ │ └── Contents.json │ ├── ErrorCode.swift │ ├── HybridMultipleImagePicker+Camera.swift │ ├── HybridMultipleImagePicker+Config.swift │ ├── HybridMultipleImagePicker+Crop.swift │ ├── HybridMultipleImagePicker+Preview.swift │ ├── HybridMultipleImagePicker+Result.swift │ ├── HybridMultipleImagePicker.swift │ ├── MultipleImagePickerOnLoad.mm │ ├── PHAsset+Thumbnail.swift │ ├── PhotoCancelItem.swift │ ├── TopViewController.swift │ ├── UIColor+Hex.swift │ ├── UIColor+React.swift │ ├── UIImage.swift │ ├── URL+Mime.swift │ └── Utils.swift ├── nitro.json ├── nitrogen/ │ └── generated/ │ ├── .gitattributes │ ├── android/ │ │ ├── MultipleImagePicker+autolinking.cmake │ │ ├── MultipleImagePicker+autolinking.gradle │ │ ├── MultipleImagePickerOnLoad.cpp │ │ ├── MultipleImagePickerOnLoad.hpp │ │ ├── c++/ │ │ │ ├── JCameraDevice.hpp │ │ │ ├── JCameraResult.hpp │ │ │ ├── JCropRatio.hpp │ │ │ ├── JCropResult.hpp │ │ │ ├── JFunc_void_CameraResult.hpp │ │ │ ├── JFunc_void_CropResult.hpp │ │ │ ├── JFunc_void_double.hpp │ │ │ ├── JFunc_void_std__vector_PickerResult_.hpp │ │ │ ├── JHybridMultipleImagePickerSpec.cpp │ │ │ ├── JHybridMultipleImagePickerSpec.hpp │ │ │ ├── JLanguage.hpp │ │ │ ├── JMediaPreview.hpp │ │ │ ├── JMediaType.hpp │ │ │ ├── JNitroCameraConfig.hpp │ │ │ ├── JNitroConfig.hpp │ │ │ ├── JNitroCropConfig.hpp │ │ │ ├── JNitroPreviewConfig.hpp │ │ │ ├── JPickerCameraConfig.hpp │ │ │ ├── JPickerCropConfig.hpp │ │ │ ├── JPickerResult.hpp │ │ │ ├── JPresentation.hpp │ │ │ ├── JResultType.hpp │ │ │ ├── JSelectBoxStyle.hpp │ │ │ ├── JSelectMode.hpp │ │ │ ├── JText.hpp │ │ │ └── JTheme.hpp │ │ └── kotlin/ │ │ └── com/ │ │ └── margelo/ │ │ └── nitro/ │ │ └── multipleimagepicker/ │ │ ├── CameraDevice.kt │ │ ├── CameraResult.kt │ │ ├── CropRatio.kt │ │ ├── CropResult.kt │ │ ├── Func_void_CameraResult.kt │ │ ├── Func_void_CropResult.kt │ │ ├── Func_void_double.kt │ │ ├── Func_void_std__vector_PickerResult_.kt │ │ ├── HybridMultipleImagePickerSpec.kt │ │ ├── Language.kt │ │ ├── MediaPreview.kt │ │ ├── MediaType.kt │ │ ├── MultipleImagePickerOnLoad.kt │ │ ├── NitroCameraConfig.kt │ │ ├── NitroConfig.kt │ │ ├── NitroCropConfig.kt │ │ ├── NitroPreviewConfig.kt │ │ ├── PickerCameraConfig.kt │ │ ├── PickerCropConfig.kt │ │ ├── PickerResult.kt │ │ ├── Presentation.kt │ │ ├── ResultType.kt │ │ ├── SelectBoxStyle.kt │ │ ├── SelectMode.kt │ │ ├── Text.kt │ │ └── Theme.kt │ ├── ios/ │ │ ├── MultipleImagePicker+autolinking.rb │ │ ├── MultipleImagePicker-Swift-Cxx-Bridge.cpp │ │ ├── MultipleImagePicker-Swift-Cxx-Bridge.hpp │ │ ├── MultipleImagePicker-Swift-Cxx-Umbrella.hpp │ │ ├── MultipleImagePickerAutolinking.mm │ │ ├── MultipleImagePickerAutolinking.swift │ │ ├── c++/ │ │ │ ├── HybridMultipleImagePickerSpecSwift.cpp │ │ │ └── HybridMultipleImagePickerSpecSwift.hpp │ │ └── swift/ │ │ ├── CameraDevice.swift │ │ ├── CameraResult.swift │ │ ├── CropRatio.swift │ │ ├── CropResult.swift │ │ ├── Func_void_CameraResult.swift │ │ ├── Func_void_CropResult.swift │ │ ├── Func_void_double.swift │ │ ├── Func_void_std__vector_PickerResult_.swift │ │ ├── HybridMultipleImagePickerSpec.swift │ │ ├── HybridMultipleImagePickerSpec_cxx.swift │ │ ├── Language.swift │ │ ├── MediaPreview.swift │ │ ├── MediaType.swift │ │ ├── NitroCameraConfig.swift │ │ ├── NitroConfig.swift │ │ ├── NitroCropConfig.swift │ │ ├── NitroPreviewConfig.swift │ │ ├── PickerCameraConfig.swift │ │ ├── PickerCropConfig.swift │ │ ├── PickerResult.swift │ │ ├── Presentation.swift │ │ ├── ResultType.swift │ │ ├── SelectBoxStyle.swift │ │ ├── SelectMode.swift │ │ ├── Text.swift │ │ └── Theme.swift │ └── shared/ │ └── c++/ │ ├── CameraDevice.hpp │ ├── CameraResult.hpp │ ├── CropRatio.hpp │ ├── CropResult.hpp │ ├── HybridMultipleImagePickerSpec.cpp │ ├── HybridMultipleImagePickerSpec.hpp │ ├── Language.hpp │ ├── MediaPreview.hpp │ ├── MediaType.hpp │ ├── NitroCameraConfig.hpp │ ├── NitroConfig.hpp │ ├── NitroCropConfig.hpp │ ├── NitroPreviewConfig.hpp │ ├── PickerCameraConfig.hpp │ ├── PickerCropConfig.hpp │ ├── PickerResult.hpp │ ├── Presentation.hpp │ ├── ResultType.hpp │ ├── SelectBoxStyle.hpp │ ├── SelectMode.hpp │ ├── Text.hpp │ └── Theme.hpp ├── package.json ├── react-native.config.js ├── scripts/ │ └── bootstrap.js ├── src/ │ ├── index.ts │ ├── specs/ │ │ └── MultipleImagePicker.nitro.ts │ └── types/ │ ├── camera.ts │ ├── config.ts │ ├── crop.ts │ ├── error.ts │ ├── index.ts │ ├── picker.ts │ ├── preview.ts │ └── result.ts ├── tsconfig.build.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 executors: default: docker: - image: circleci/node:10 working_directory: ~/project commands: attach_project: steps: - attach_workspace: at: ~/project jobs: install-dependencies: executor: default steps: - checkout - attach_project - restore_cache: keys: - dependencies-{{ checksum "package.json" }} - dependencies- - restore_cache: keys: - dependencies-example-{{ checksum "example/package.json" }} - dependencies-example- - run: name: Install dependencies command: | yarn install --cwd example --frozen-lockfile yarn install --frozen-lockfile - save_cache: key: dependencies-{{ checksum "package.json" }} paths: node_modules - save_cache: key: dependencies-example-{{ checksum "example/package.json" }} paths: example/node_modules - persist_to_workspace: root: . paths: . lint: executor: default steps: - attach_project - run: name: Lint files command: | yarn lint typescript: executor: default steps: - attach_project - run: name: Typecheck files command: | yarn typescript unit-tests: executor: default steps: - attach_project - run: name: Run unit tests command: | yarn test --coverage - store_artifacts: path: coverage destination: coverage build-package: executor: default steps: - attach_project - run: name: Build package command: | yarn prepare workflows: build-and-test: jobs: - install-dependencies - lint: requires: - install-dependencies - typescript: requires: - install-dependencies - unit-tests: requires: - install-dependencies - build-package: requires: - install-dependencies ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: baronha patreon: baronha open_collective: # Replace with a single Open Collective username ko_fi: baoha tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/workflows/docs.yml ================================================ name: Deploy to GitHub Pages on: push: branches: - main paths: - 'docs/**' jobs: build: name: Build Docusaurus runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 18 cache: yarn - name: Install dependencies working-directory: docs run: yarn install --frozen-lockfile - name: Build docs working-directory: docs run: yarn build - name: Upload Build Artifact uses: actions/upload-pages-artifact@v3 with: path: docs/build deploy: name: Deploy to GitHub Pages needs: build # Grant GITHUB_TOKEN the permissions required to make a Pages deployment permissions: pages: write # to deploy to Pages id-token: write # to verify the deployment originates from an appropriate source # Deploy to the github-pages environment environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ================================================ FILE: .gitignore ================================================ # OSX # .DS_Store # XDE .expo/ # VSCode .vscode/ jsconfig.json # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate project.xcworkspace # Android/IJ # .classpath .cxx .gradle .idea .project .settings local.properties android.iml # Cocoapods # example/ios/Pods # Ruby example/vendor/ # node.js # node_modules/ npm-debug.log yarn-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ android/app/libs android/keystores/debug.keystore # Yarn .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/sdks !.yarn/versions # Expo .expo/ # Turborepo .turbo/ # generated by bob lib/ ================================================ FILE: .npmignore ================================================ example/ files/ node_modules/ npm-debug.log package-lock.json ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. ## Development workflow To get started with the project, run `yarn` in the root directory to install the required dependencies for each package: ```sh yarn ``` While developing, you can run the [example app](/example/) to test your changes. To start the packager: ```sh yarn example start ``` To run the example app on Android: ```sh yarn example android ``` To run the example app on iOS: ```sh yarn example ios ``` Make sure your code passes TypeScript and ESLint. Run the following to verify: ```sh yarn typescript yarn lint ``` To fix formatting errors, run the following: ```sh yarn lint --fix ``` Remember to add tests for your change if possible. Run the unit tests by: ```sh yarn test ``` To edit the Objective-C files, open `example/ios/MultipleImagePickerExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-multiple-image-picker`. To edit the Kotlin files, open `example/android` in Android studio and find the source files at `reactnativemultipleimagepicker` under `Android`. ### Commit message convention We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages: - `fix`: bug fixes, e.g. fix crash due to deprecated method. - `feat`: new features, e.g. add new method to the module. - `refactor`: code refactor, e.g. migrate from class components to hooks. - `docs`: changes into documentation, e.g. add usage example for the module.. - `test`: adding or updating tests, e.g. add integration tests using detox. - `chore`: tooling changes, e.g. change CI config. Our pre-commit hooks verify that your commit message matches this format when committing. ### Linting and tests [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/) We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. Our pre-commit hooks verify that the linter and tests pass when committing. ### Scripts The `package.json` file contains various scripts for common tasks: - `yarn bootstrap`: setup project by installing all dependencies and pods. - `yarn typescript`: type-check files with TypeScript. - `yarn lint`: lint files with ESLint. - `yarn test`: run unit tests with Jest. - `yarn example start`: start the Metro server for the example app. - `yarn example android`: run the example app on Android. - `yarn example ios`: run the example app on iOS. ### Sending a pull request > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github). When you're sending a pull request: - Prefer small pull requests focused on one change. - Verify that linters and tests are passing. - Review the documentation to make sure it looks good. - Follow the pull request template when opening a pull request. - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue. ## Code of Conduct ### Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ### Our Standards Examples of behavior that contributes to a positive environment for our community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience - Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: - The use of sexualized language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email address, without their explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ### Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ### Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ### Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ### Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: #### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. #### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. #### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. #### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ### Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 Baron Ha. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MultipleImagePicker.podspec ================================================ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) Pod::Spec.new do |s| s.name = "MultipleImagePicker" s.version = package["version"] s.summary = package["description"] s.homepage = package["homepage"] s.license = package["license"] s.authors = package["author"] s.platforms = { :ios => min_ios_version_supported } s.source = { :git => "https://github.com/baronha/react-native-multiple-image-picker.git", :tag => "#{s.version}" } s.source_files = [ # Implementation (Swift) "ios/**/*.{swift}", # Autolinking/Registration (Objective-C++) "ios/**/*.{m,mm}", # Implementation (C++ objects) "cpp/**/*.{hpp,cpp}", ] s.resource_bundles = { "MultipleImagePicker" => ["ios/Assets.xcassets"] } s.dependency "HXPhotoPicker/Picker", "4.2.4" s.dependency "HXPhotoPicker/Camera/Lite", "4.2.4" s.dependency "HXPhotoPicker/Editor", "4.2.4" s.pod_target_xcconfig = { # C++ compiler flags, mainly for folly. "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES FOLLY_MOBILE" } if ENV["USE_FRAMEWORKS"] s.dependency "React-Core" add_dependency(s, "React-jsinspector", :framework_name => "jsinspector_modern") add_dependency(s, "React-rendererconsistency", :framework_name => "React_rendererconsistency") add_dependency(s, "React-jsinspectortracing", :framework_name => 'jsinspector_moderntracing') add_dependency(s, "React-jsinspectorcdp", :framework_name => 'jsinspector_moderncdp') end load 'nitrogen/generated/ios/MultipleImagePicker+autolinking.rb' add_nitrogen_files(s) s.dependency 'React-jsi' s.dependency 'React-callinvoker' install_modules_dependencies(s) end ================================================ FILE: README.md ================================================ ![Logo][Logo]

[![iOS][iOS]][iOS-URL] [![Android][Android]][Android-URL] [![Swift][Swift]][Swift-URL] [![Kotlin][Kotlin]][Kotlin-URL] [![React-Native][React-Native]][React-Native-URL] ## Overview 🎇 https://github.com/user-attachments/assets/79580bc7-237c-46b7-b92e-1479cc6d9079 React Native Multiple Image Picker **(RNMIP)** enables application to pick images and videos from multiple smart album in iOS/Android. React Native Multiple Image Picker is based on two libraries available, [HXPhotoPicker](https://github.com/SilenceLove/HXPhotoPicker) and [PictureSelector](https://github.com/LuckSiege/PictureSelector) ## Documentation 📚 ## Features 🔥 | 🤩 | ![Logo][Logo] | | --- | ------------------------------------------------------------------------------------- | | 🍕 | [**Crop**](/docs/docs/CROP.mdx) single/multiple image. | | 🎑 | [**Preview**](/docs/docs/PREVIEW.mdx) image/video. | | 📸 | [**Camera**](/docs/docs/CAMERA.mdx) module for capturing photos and recording videos. | | 🐳 | Keep the previous selection. | | 0️⃣ | Selected order index. | | 🎨 | UI Customization (numberOfColumn, spacing, primaryColor ... ) | | 🌚 | Dark Mode, Light Mode | | 🌄 | Choose multiple images/video. | | 📦 | Support smart album `(camera roll, selfies, panoramas, favorites, videos...)`. | | 📺 | Display video duration. | | ⛅️ | Support iCloud Photo Library. | | 🌪 | Scrolling performance. ☕️ | ## Requirements Because RNMIP uses Nitro Module, it complies with Nitro Modules' requirements. View Nitro Modules' requirements [here](https://nitro.margelo.com/docs/minimum-requirements) - `Xcode 16+` - `iOS 13+` - `react-native 0.75+` - `compileSdkVersion 34+` ## Installation See more [**Installation**](https://nitrogenzlab.github.io/react-native-multiple-image-picker/getting-started) ## Usage Here is a simple usage of the Multiple Image Picker.
See more [**Config**](https://nitrogenzlab.github.io/react-native-multiple-image-picker/config) ```typescript import { openPicker, Config } from '@baronha/react-native-multiple-image-picker' const config: Config = { maxSelect: 10, maxVideo: 10, primaryColor: '#FB9300', backgroundDark: '#2f2f2f', numberOfColumn: 4, mediaType: 'all', selectBoxStyle: 'number', selectMode: 'multiple', language: 'vi', // 🇻🇳 Vietnamese theme: 'dark', isHiddenOriginalButton: false, primaryColor: '#F6B35D', } const onPicker = async () => { try { const response = await openPicker(config) setImages(response) } catch (e) { // catch error for multiple image picker } } ``` ## To Do - [x] Crop Image in iOS. - [x] Preview Controller for `iOS`. - [x] Handle Permission when limited on `iOS`. - [x] Migrating Library to the New Architecture. - [x] Multiple Crop Image. - [x] Multiple Preview Image. - [x] Dynamic Theme. - [x] Dynamic Language - [x] Open Crop Controller. - [x] Open Preview Controller. - [x] Open Camera Controller. ## Sponsor & Support ☕️ [![BuyMeACoffee][BuyMeACoffee]][BuyMeACoffee-URL] [![Kofi][Kofi]][Kofi-URL] [BuyMeACoffee]: https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black [BuyMeACoffee-URL]: https://buymeacoffee.com/baronha [Kofi]: https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white [Kofi-URL]: https://ko-fi.com/baoha To keep this library maintained and up-to-date please consider [sponsoring it on GitHub](https://github.com/sponsors/baronha). Or if you are looking for a private support or help in customizing the experience, then reach out to me on Twitter [@\_baronha](https://twitter.com/_baronha).
Besides, I also built a product using HXPhotoPicker here, Hope you support:
## Built With ❤️ [![NitroModules](https://img.shields.io/badge/Nitro_Modules-0052CC?style=for-the-badge)](https://nitro.margelo.com/docs/nitro-modules)
[![HXPhotoPicker](https://img.shields.io/badge/HXPhotoPicker-F05138?style=for-the-badge)](https://github.com/SilenceLove/HXPhotoPicker)
[![PictureSelector](https://img.shields.io/badge/Picture_Selector-b07219?style=for-the-badge)](https://github.com/LuckSiege/PictureSelector) ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=baronha/react-native-multiple-image-picker&type=Date)](https://star-history.com/#bytebase/star-history&Date) ## Showcase ✨ List of used applications with `@baronha/react-native-multiple-image-picker` Contributions are welcome! If you have an application that uses `@baronha/react-native-multiple-image-picker`, please open a [pull request](/docs/docs/SHOWCASE/showcase.json) to add it to the list. See all [**Showcase**](https://nitrogenzlab.github.io/react-native-multiple-image-picker/showcase) ## Performance We're trying to improve performance. If you have a better solution, please open a [issue](https://github.com/NitrogenZLab/react-native-multiple-image-picker/issues) or [pull request](https://github.com/NitrogenZLab/react-native-multiple-image-picker/pulls). Best regards! ## License MIT
[TLPhotoPicker](https://github.com/tilltue/TLPhotoPicker/blob/master/LICENSE)
[PictureSelector](https://github.com/LuckSiege/PictureSelector/blob/master/LICENSE) [iOS]: https://img.shields.io/badge/iOS-000000?style=for-the-badge&logo=ios&logoColor=white [iOS-URL]: https://www.apple.com/ios [Android]: https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white [Android-URL]: https://www.android.com/ [React-Native]: https://img.shields.io/badge/React_Native-20232A?style=for-the-badge&logo=react&logoColor=61DAFB [React-Native-URL]: https://reactnative.dev/ [React-Native]: https://img.shields.io/badge/React_Native-20232A?style=for-the-badge&logo=react&logoColor=61DAFB [React-Native-URL]: https://reactnative.dev/ [Swift]: https://img.shields.io/badge/Swift-FA7343?style=for-the-badge&logo=swift&logoColor=white [Swift-URL]: https://developer.apple.com/swift/ [Kotlin]: https://img.shields.io/badge/Kotlin-0095D5?&style=for-the-badge&logo=kotlin&logoColor=white [Kotlin-URL]: https://kotlinlang.org/ [Logo]: https://img.shields.io/badge/React_Native_Multiple_Image_Picker-DF78C3?style=for-the-badge ================================================ FILE: android/CMakeLists.txt ================================================ project(MultipleImagePicker) cmake_minimum_required(VERSION 3.9.0) set (PACKAGE_NAME MultipleImagePicker) set (CMAKE_VERBOSE_MAKEFILE ON) set (CMAKE_CXX_STANDARD 20) # Define C++ library and add all sources add_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp ) # Add Nitrogen specs :) include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/MultipleImagePicker+autolinking.cmake) # Set up local includes include_directories( "src/main/cpp" "../cpp" ) find_library(LOG_LIB log) # Link all libraries together target_link_libraries( ${PACKAGE_NAME} ${LOG_LIB} android # <-- Android core ) ================================================ FILE: android/build.gradle ================================================ buildscript { repositories { google() mavenCentral() } dependencies { classpath "com.android.tools.build:gradle:7.2.1" } } def reactNativeArchitectures() { def value = rootProject.getProperties().get("reactNativeArchitectures") return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } def isNewArchitectureEnabled() { return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" } apply plugin: "com.android.library" apply plugin: 'org.jetbrains.kotlin.android' apply from: '../nitrogen/generated/android/MultipleImagePicker+autolinking.gradle' if (isNewArchitectureEnabled()) { apply plugin: "com.facebook.react" } def getExtOrDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["MultipleImagePicker_" + name] } def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["MultipleImagePicker_" + name]).toInteger() } android { namespace "com.margelo.nitro.multipleimagepicker" ndkVersion getExtOrDefault("ndkVersion") compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") defaultConfig { minSdkVersion getExtOrIntegerDefault("minSdkVersion") targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" arguments "-DANDROID_STL=c++_shared" abiFilters(*reactNativeArchitectures()) } } } externalNativeBuild { cmake { path "CMakeLists.txt" } } packagingOptions { excludes = ["META-INF", "META-INF/**", "**/libc++_shared.so", "**/libfbjni.so", "**/libjsi.so", "**/libfolly_json.so", "**/libfolly_runtime.so", "**/libglog.so", "**/libhermes.so", "**/libhermes-executor-debug.so", "**/libhermes_executor.so", "**/libreactnative.so", "**/libreactnativejni.so", "**/libturbomodulejsijni.so", "**/libreact_nativemodule_core.so", "**/libjscexecutor.so"] } buildFeatures { buildConfig true prefab true } buildTypes { release { minifyEnabled false } } lintOptions { disable "GradleCompatible" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } sourceSets { main { if (isNewArchitectureEnabled()) { java.srcDirs += [ // React Codegen files "${project.buildDir}/generated/source/codegen/java"] } } } } repositories { mavenCentral() google() } dependencies { // For < 0.71, this will be from the local maven repo // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin //noinspection GradleDynamicVersion // Add a dependency on NitroModules implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' // PictureSelector basic (Necessary) implementation 'io.github.lucksiege:pictureselector:v3.11.2' // image compress library (Not necessary) implementation 'io.github.lucksiege:compress:v3.11.2' // uCrop library (Not necessary) implementation 'io.github.lucksiege:ucrop:v3.11.2' // simple camerax library (Not necessary) implementation 'io.github.lucksiege:camerax:v3.11.2' // exoplayer implementation "com.google.android.exoplayer:exoplayer:2.19.1" implementation "com.facebook.react:react-native:+" // Add a dependency on NitroModules implementation project(":react-native-nitro-modules") } if (isNewArchitectureEnabled()) { react { jsRootDir = file("../src/") libraryName = "MultipleImagePicker" codegenJavaPackageName = "com.margelo.nitro.multipleimagepicker" } } ================================================ FILE: android/gradle.properties ================================================ MultipleImagePicker_kotlinVersion=1.9.24 MultipleImagePicker_minSdkVersion=23 MultipleImagePicker_targetSdkVersion=34 MultipleImagePicker_compileSdkVersion=34 MultipleImagePicker_ndkVersion=26.1.10909125 ================================================ FILE: android/src/main/AndroidManifest.xml ================================================ ================================================ FILE: android/src/main/cpp/cpp-adapter.cpp ================================================ #include #include "MultipleImagePickerOnLoad.hpp" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return margelo::nitro::multipleimagepicker::initialize(vm); } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/CameraEngine.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.content.Context import android.graphics.Color import androidx.fragment.app.Fragment import com.bumptech.glide.Glide import com.facebook.react.bridge.ColorPropConverter 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: NitroCameraConfig, ) : OnCameraInterceptListener { override fun openCamera(fragment: Fragment, cameraMode: Int, requestCode: Int) { val camera = SimpleCameraX.of() camera.setImageEngine { context, url, imageView -> Glide.with(context).load(url).into(imageView) } camera.isAutoRotation(true) camera.setCameraMode(cameraMode) camera.isDisplayRecordChangeTime(true) camera.isManualFocusCameraPreview(true) camera.isZoomCameraPreview(true) camera.setRecordVideoMaxSecond(config.videoMaximumDuration?.toInt() ?: 60) camera.setCameraAroundState(config.cameraDevice == CameraDevice.FRONT) camera.setOutputPathDir(getSandboxCameraOutputPath()) config.color?.let { val primaryColor = ColorPropConverter.getColor(it, appContext) ?: Color.BLACK camera.setCaptureLoadingColor(primaryColor) } 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 } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/Constant.kt ================================================ package com.margelo.nitro.multipleimagepicker object Constant { const val TOOLBAR_TEXT_SIZE = 12 } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/CropEngine.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.content.Context import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri import android.widget.ImageView import androidx.fragment.app.Fragment import com.bumptech.glide.Glide import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition import com.luck.picture.lib.config.PictureMimeType import com.luck.picture.lib.engine.CropFileEngine import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnMediaEditInterceptListener import com.luck.picture.lib.utils.DateUtils import com.margelo.nitro.multipleimagepicker.ImageLoaderUtils.assertValidRequest import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop.Options import com.yalantis.ucrop.UCropImageEngine import java.io.File class CropImageEngine : UCropImageEngine { override fun loadImage(context: Context, url: String, imageView: ImageView) { if (!assertValidRequest(context)) { return } Glide.with(context).load(url).override(180, 180).into(imageView) } override fun loadImage( context: Context, url: Uri, maxWidth: Int, maxHeight: Int, call: UCropImageEngine.OnCallbackListener ) { Glide.with(context).asBitmap().load(url).override(maxWidth, maxHeight) .into(object : CustomTarget() { override fun onResourceReady( resource: Bitmap, transition: Transition? ) { call.onCall(resource) } override fun onLoadCleared(placeholder: Drawable?) { call.onCall(null) } }) } } class CropEngine(cropOption: Options) : CropFileEngine { private val options: Options = cropOption override fun onStartCrop( fragment: Fragment, srcUri: Uri?, destinationUri: Uri?, dataSource: ArrayList?, requestCode: Int ) { val uCrop = UCrop.of(srcUri!!, destinationUri!!, dataSource) uCrop.withOptions(options) uCrop.setImageEngine(CropImageEngine()) uCrop.start(fragment.requireActivity(), fragment, requestCode) } } class MediaEditInterceptListener( private val outputCropPath: String, private val options: Options, ) : OnMediaEditInterceptListener { override fun onStartMediaEdit( fragment: Fragment, currentLocalMedia: LocalMedia, requestCode: Int ) { val currentEditPath = currentLocalMedia.availablePath val inputUri = if (PictureMimeType.isContent(currentEditPath)) Uri.parse(currentEditPath) else Uri.fromFile(File(currentEditPath)) val destinationUri = Uri.fromFile( File(outputCropPath, DateUtils.getCreateFileName("CROP_") + ".jpeg") ) val uCrop = UCrop.of(inputUri, destinationUri) uCrop.withOptions(options) // set engine uCrop.setImageEngine(CropImageEngine()) // start edit uCrop.startEdit(fragment.requireActivity(), fragment, requestCode) } } fun getSandboxPath(context: Context): String { val externalFilesDir: File? = context.getExternalFilesDir("") val customFile = File(externalFilesDir?.absolutePath, "Sandbox") if (!customFile.exists()) { customFile.mkdirs() } return customFile.absolutePath + File.separator } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/ExoPlayerEngine.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.content.Context import android.net.Uri import android.view.View import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.PlaybackException import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.ui.StyledPlayerView import com.luck.picture.lib.config.PictureMimeType import com.luck.picture.lib.config.SelectorProviders import com.luck.picture.lib.engine.VideoPlayerEngine import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnPlayerListener import java.io.File import java.util.concurrent.CopyOnWriteArrayList class ExoPlayerEngine : VideoPlayerEngine { private val listeners = CopyOnWriteArrayList() override fun onCreateVideoPlayer(context: Context): View { val exoPlayer = StyledPlayerView(context) exoPlayer.useController = true return exoPlayer } override fun onStarPlayer(exoPlayer: StyledPlayerView, media: LocalMedia) { val player = exoPlayer.player if (player != null) { val mediaItem: MediaItem val path = media.availablePath mediaItem = if (PictureMimeType.isContent(path)) { MediaItem.fromUri(Uri.parse(path)) } else if (PictureMimeType.isHasHttp(path)) { MediaItem.fromUri(path) } else { MediaItem.fromUri(Uri.fromFile(File(path))) } val config = SelectorProviders.getInstance().selectorConfig player.repeatMode = if (config.isLoopAutoPlay) Player.REPEAT_MODE_ALL else Player.REPEAT_MODE_OFF player.setMediaItem(mediaItem) player.prepare() player.play() } } override fun onResume(exoPlayer: StyledPlayerView) { val player = exoPlayer.player player?.play() } override fun onPause(exoPlayer: StyledPlayerView) { val player = exoPlayer.player player?.pause() } override fun isPlaying(exoPlayer: StyledPlayerView): Boolean { val player = exoPlayer.player return player != null && player.isPlaying } override fun addPlayListener(playerListener: OnPlayerListener) { if (!listeners.contains(playerListener)) { listeners.add(playerListener) } } override fun removePlayListener(playerListener: OnPlayerListener) { listeners.remove(playerListener) } override fun onPlayerAttachedToWindow(exoPlayer: StyledPlayerView) { val player: Player = ExoPlayer.Builder(exoPlayer.context).build() exoPlayer.player = player player.addListener(mPlayerListener) } override fun onPlayerDetachedFromWindow(exoPlayer: StyledPlayerView) { val player = exoPlayer.player if (player != null) { player.removeListener(mPlayerListener) player.release() exoPlayer.player = null } } override fun destroy(exoPlayer: StyledPlayerView) { val player = exoPlayer.player if (player != null) { player.removeListener(mPlayerListener) player.release() } } private val mPlayerListener: Player.Listener = object : Player.Listener { override fun onPlayerError(error: PlaybackException) { for (i in listeners.indices) { val playerListener = listeners[i] playerListener.onPlayerError() } } override fun onPlaybackStateChanged(playbackState: Int) { if (playbackState == Player.STATE_READY) { for (i in listeners.indices) { val playerListener = listeners[i] playerListener.onPlayerReady() } } else if (playbackState == Player.STATE_BUFFERING) { for (i in listeners.indices) { val playerListener = listeners[i] playerListener.onPlayerLoading() } } else if (playbackState == Player.STATE_ENDED) { for (i in listeners.indices) { val playerListener = listeners[i] playerListener.onPlayerEnd() } } } } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/GlideEngine.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.content.Context import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.luck.picture.lib.engine.ImageEngine import com.luck.picture.lib.utils.ActivityCompatHelper class GlideEngine private constructor() : ImageEngine { 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) .load(url) .override(maxWidth, maxHeight) .into(imageView) } 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) } 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 } Glide.with(context).pauseRequests() } override fun resumeRequests(context: Context) { if (!ActivityCompatHelper.assertValidRequest(context)) { return } Glide.with(context).resumeRequests() } private object InstanceHolder { val instance = GlideEngine() } companion object { fun createGlideEngine(): GlideEngine { return InstanceHolder.instance } } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/ImageLoaderUtils.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.app.Activity import android.content.Context import android.content.ContextWrapper object ImageLoaderUtils { fun assertValidRequest(context: Context?): Boolean { if (context is Activity) { return !isDestroy(context) } else if (context is ContextWrapper) { if (context.baseContext is Activity) { val activity = context.baseContext as Activity return !isDestroy(activity) } } return true } private fun isDestroy(activity: Activity?): Boolean { return if (activity == null) { true } else activity.isFinishing || activity.isDestroyed } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/LoadingDialog.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.app.Dialog import android.content.Context import android.os.Bundle import android.view.Gravity import android.view.ViewGroup class LoadingDialog(context: Context?) : Dialog(context!!, R.style.Picture_Theme_AlertDialog) { init { setCancelable(true) setCanceledOnTouchOutside(false) } override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.loading_dialog) setDialogSize() } private fun setDialogSize() { val params = window!!.attributes params.width = ViewGroup.LayoutParams.WRAP_CONTENT params.height = ViewGroup.LayoutParams.WRAP_CONTENT params.gravity = Gravity.CENTER window!!.setWindowAnimations(R.style.PictureThemeDialogWindowStyle) window!!.attributes = params } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePicker.kt ================================================ package com.margelo.nitro.multipleimagepicker import com.margelo.nitro.NitroModules class MultipleImagePicker : HybridMultipleImagePickerSpec() { override val memorySize: Long get() = 5 private val pickerModule = MultipleImagePickerImp(NitroModules.applicationContext) override fun openPicker( config: NitroConfig, resolved: (result: Array) -> Unit, rejected: (reject: Double) -> Unit ) { pickerModule.openPicker(config, resolved, rejected) } override fun openCrop( image: String, config: NitroCropConfig, resolved: (result: CropResult) -> Unit, rejected: (reject: Double) -> Unit ) { pickerModule.openCrop(image, config, resolved, rejected) } override fun openPreview( media: Array, index: Double, config: NitroPreviewConfig, onLongPress: (index: Double) -> Unit ) { pickerModule.openPreview(media, index.toInt(), config, onLongPress) } override fun openCamera( config: NitroCameraConfig, resolved: (result: CameraResult) -> Unit, rejected: (reject: Double) -> Unit ) { pickerModule.openCamera(config, resolved, rejected) } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerImp.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.app.Activity import android.content.Context import android.content.Intent import android.graphics.Color import android.net.Uri import androidx.core.content.ContextCompat import com.facebook.react.bridge.BaseActivityEventListener import com.facebook.react.bridge.ColorPropConverter import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.luck.picture.lib.app.IApp import com.luck.picture.lib.app.PictureAppMaster import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.PictureMimeType import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.config.SelectModeConfig import com.luck.picture.lib.engine.PictureSelectorEngine import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnCustomLoadingListener import com.luck.picture.lib.interfaces.OnExternalPreviewEventListener import com.luck.picture.lib.interfaces.OnMediaEditInterceptListener import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.luck.picture.lib.language.LanguageConfig import com.luck.picture.lib.style.BottomNavBarStyle import com.luck.picture.lib.style.PictureSelectorStyle import com.luck.picture.lib.style.PictureWindowAnimationStyle import com.luck.picture.lib.style.SelectMainStyle import com.luck.picture.lib.style.TitleBarStyle import com.luck.picture.lib.utils.DateUtils import com.luck.picture.lib.utils.DensityUtil import com.luck.picture.lib.utils.MediaUtils import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop.Options import com.yalantis.ucrop.UCrop.REQUEST_CROP import com.yalantis.ucrop.model.AspectRatio import java.io.File import java.net.HttpURLConnection import java.net.URL class MultipleImagePickerImp(reactContext: ReactApplicationContext?) : ReactContextBaseJavaModule(reactContext), IApp { override fun getName(): String { return "MultipleImagePicker" } companion object { const val TAG = "MultipleImagePicker" } private var style = PictureSelectorStyle() private lateinit var config: NitroConfig private var cropOption = Options() private var dataList = mutableListOf() @ReactMethod fun openPicker( options: NitroConfig, resolved: (result: Array) -> Unit, rejected: (reject: Double) -> Unit ) { PictureAppMaster.getInstance().app = this val activity = reactApplicationContext.currentActivity ?: throw IllegalStateException("No current Activity available") val imageEngine = GlideEngine.createGlideEngine() // set global config config = options setStyle() // set style for UI handleSelectedAssets(config) val chooseMode = getChooseMode(config.mediaType) val maxSelect = config.maxSelect?.toInt() ?: 20 val maxVideo = config.maxVideo?.toInt() ?: 20 val isPreview = config.isPreview ?: true val maxFileSize = config.maxFileSize?.toLong() val maxDuration = config.maxVideoDuration?.toInt() val minDuration = config.minVideoDuration?.toInt() val allowSwipeToSelect = config.allowSwipeToSelect ?: false val isMultiple = config.selectMode == SelectMode.MULTIPLE val selectMode = if (isMultiple) SelectModeConfig.MULTIPLE else SelectModeConfig.SINGLE val isCrop = config.crop != null PictureSelector.create(activity) .openGallery(chooseMode) .setImageEngine(imageEngine) .setSelectedData(dataList) .setSelectorUIStyle(style) .apply { if (isCrop) { setCropOption(config.crop) // Disabled force crop engine for multiple if (!isMultiple) setCropEngine(CropEngine(cropOption)) else setEditMediaInterceptListener(setEditMediaEvent()) } maxDuration?.let { setFilterVideoMaxSecond(it) } minDuration?.let { setFilterVideoMinSecond(it) } maxFileSize?.let { setFilterMaxFileSize(it) } isDisplayCamera(config.camera != null) config.camera?.let { val cameraConfig = NitroCameraConfig( mediaType = MediaType.ALL, presentation = Presentation.FULLSCREENMODAL, language = Language.SYSTEM, crop = null, isSaveSystemAlbum = false, color = config.primaryColor, cameraDevice = it.cameraDevice, videoMaximumDuration = it.videoMaximumDuration ) setCameraInterceptListener(CameraEngine(appContext, cameraConfig)) } } .setVideoThumbnailListener(VideoThumbnailEngine(getVideoThumbnailDir())) .setImageSpanCount(config.numberOfColumn?.toInt() ?: 3) .setMaxSelectNum(maxSelect) .isDirectReturnSingle(true) .isSelectZoomAnim(true) .isPageStrategy(true, 50) .isWithSelectVideoImage(true) .setMaxVideoSelectNum(if (maxVideo != 20) maxVideo else maxSelect) .isMaxSelectEnabledMask(true) .isAutoVideoPlay(true) .isFastSlidingSelect(allowSwipeToSelect) .isPageSyncAlbumCount(true) // isPreview .isPreviewImage(isPreview) .isPreviewVideo(isPreview) .isDisplayTimeAxis(true) .setSelectionMode(selectMode) .isOriginalControl(config.isHiddenOriginalButton == false) .setLanguage(getLanguage(config.language)) .isPreviewFullScreenMode(true) .forResult(object : OnResultCallbackListener { override fun onResult(localMedia: ArrayList?) { var data: Array = arrayOf() if (localMedia?.size == 0 || localMedia == null) { resolved(arrayOf()) return } // set dataList dataList = localMedia.filterNotNull().toMutableList() localMedia.forEach { item -> if (item != null) { val media = getResult(item) data += media // Add the media to the data array } } resolved(data) } override fun onCancel() { // } }) } @ReactMethod fun openCrop( image: String, options: NitroCropConfig, resolved: (result: CropResult) -> Unit, rejected: (reject: Double) -> Unit ) { cropOption = Options() setCropOption( PickerCropConfig( circle = options.circle, ratio = options.ratio, defaultRatio = options.defaultRatio, freeStyle = options.freeStyle ) ) try { val uri = when { // image network image.startsWith("http://") || image.startsWith("https://") -> { // Handle remote URL val url = URL(image) val connection = url.openConnection() as HttpURLConnection connection.doInput = true connection.connect() val inputStream = connection.inputStream // Create a temp file to store the image val file = File(appContext.cacheDir, "CROP_") file.outputStream().use { output -> inputStream.copyTo(output) } Uri.fromFile(file) } else -> Uri.parse(image) } val destinationUri = Uri.fromFile( File(getSandboxPath(appContext), DateUtils.getCreateFileName("CROP_") + ".jpeg") ) val uCrop = UCrop.of(uri, destinationUri).withOptions(cropOption) // set engine uCrop.setImageEngine(CropImageEngine()) // start edit val cropActivityEventListener = object : BaseActivityEventListener() { override fun onActivityResult( activity: Activity, requestCode: Int, resultCode: Int, data: Intent? ) { if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CROP) { val resultUri = UCrop.getOutput(data!!) val width = UCrop.getOutputImageWidth(data).toDouble() val height = UCrop.getOutputImageHeight(data).toDouble() resultUri?.let { val result = CropResult( path = it.toString(), width, height, ) resolved(result) } } else if (resultCode == UCrop.RESULT_ERROR) { val cropError = UCrop.getError(data!!) rejected(0.0) } // Remove listener after getting result reactApplicationContext.removeActivityEventListener(this) } } // Add listener before starting UCrop reactApplicationContext.addActivityEventListener(cropActivityEventListener) reactApplicationContext.currentActivity?.let { uCrop.start(it, REQUEST_CROP) } } catch (e: Exception) { rejected(0.0) } } @ReactMethod fun openPreview( media: Array, index: Int, config: NitroPreviewConfig, onLongPress: (index: Double) -> Unit ) { val imageEngine = GlideEngine.createGlideEngine() val assets: ArrayList = arrayListOf() val previewStyle = PictureSelectorStyle() val titleBarStyle = TitleBarStyle() previewStyle.windowAnimationStyle.setActivityEnterAnimation(R.anim.anim_modal_in) previewStyle.windowAnimationStyle.setActivityExitAnimation(com.luck.picture.lib.R.anim.ps_anim_modal_out) previewStyle.selectMainStyle.previewBackgroundColor = Color.BLACK titleBarStyle.previewTitleBackgroundColor = Color.BLACK previewStyle.titleBarStyle = titleBarStyle media.withIndex().forEach { (index, mediaItem) -> var asset: LocalMedia? = null mediaItem.path?.let { path -> // network asset if (path.startsWith("https://") || path.startsWith("http://")) { val localMedia = LocalMedia.create() localMedia.path = path localMedia.mimeType = if (mediaItem.type == ResultType.VIDEO) "video/mp4" else MediaUtils.getMimeTypeFromMediaHttpUrl( path ) ?: "image/jpg" asset = localMedia } else { asset = LocalMedia.generateLocalMedia(appContext, path) } } asset?.let { it.setPosition(index) assets.add(it) } } val activity = reactApplicationContext.currentActivity ?: throw IllegalStateException("No current Activity available") PictureSelector .create(activity) .openPreview() .setImageEngine(imageEngine) .setLanguage(getLanguage(config.language)) .setSelectorUIStyle(previewStyle) .isPreviewFullScreenMode(true) .isAutoVideoPlay(config.videoAutoPlay == true) .setVideoPlayerEngine(ExoPlayerEngine()) .isVideoPauseResumePlay(true) .setCustomLoadingListener(getCustomLoadingListener()) .setExternalPreviewEventListener(object : OnExternalPreviewEventListener { override fun onPreviewDelete(position: Int) { // } override fun onLongPressDownload(context: Context, media: LocalMedia): Boolean { onLongPress(media.position.toDouble()) return true } }) .startFragmentPreview(index, false, assets) } private fun getCustomLoadingListener(): OnCustomLoadingListener { return OnCustomLoadingListener { context -> LoadingDialog(context) } } @ReactMethod fun openCamera( config: NitroCameraConfig, resolved: (result: CameraResult) -> Unit, rejected: (reject: Double) -> Unit ) { val activity = reactApplicationContext.currentActivity ?: throw IllegalStateException("No current Activity available") val chooseMode = getChooseMode(config.mediaType) PictureSelector .create(activity) .openCamera(chooseMode) .setLanguage(getLanguage(config.language)) .setCameraInterceptListener(CameraEngine(appContext, config)) .isQuickCapture(true) .isOriginalControl(true) .setVideoThumbnailListener(VideoThumbnailEngine(getVideoThumbnailDir())) .apply { if (config.crop != null) { setCropEngine(CropEngine(cropOption)) } } .forResult(object : OnResultCallbackListener { override fun onResult(results: java.util.ArrayList?) { results?.first()?.let { val result = getResult(it) resolved( CameraResult( path = result.path, type = result.type, width = result.width, height = result.height, duration = result.duration, thumbnail = result.thumbnail, fileName = result.fileName ) ) } } override fun onCancel() { // rejected(0.0) } }) } private fun getChooseMode(mediaType: MediaType): Int { return when (mediaType) { MediaType.VIDEO -> SelectMimeType.ofVideo() MediaType.IMAGE -> SelectMimeType.ofImage() else -> SelectMimeType.ofAll() } } private fun getVideoThumbnailDir(): String { val externalFilesDir: File? = appContext.getExternalFilesDir("") val customFile = File(externalFilesDir?.absolutePath, "Thumbnail") if (!customFile.exists()) { customFile.mkdirs() } return customFile.absolutePath + File.separator } private fun getLanguage(language: Language): Int { return when (language) { Language.VI -> LanguageConfig.VIETNAM // -> 🇻🇳 My country. Yeahhh Language.EN -> LanguageConfig.ENGLISH Language.ZH_HANS -> LanguageConfig.CHINESE Language.ZH_HANT -> LanguageConfig.TRADITIONAL_CHINESE Language.DE -> LanguageConfig.GERMANY Language.KO -> LanguageConfig.KOREA Language.FR -> LanguageConfig.FRANCE Language.JA -> LanguageConfig.JAPAN Language.AR -> LanguageConfig.AR Language.RU -> LanguageConfig.RU else -> LanguageConfig.SYSTEM_LANGUAGE } } private fun setCropOption(config: PickerCropConfig?) { cropOption.setShowCropFrame(true) cropOption.setShowCropGrid(true) cropOption.setCircleDimmedLayer(config?.circle ?: false) cropOption.setCropOutputPathDir(getSandboxPath(appContext)) cropOption.isCropDragSmoothToCenter(true) cropOption.isForbidSkipMultipleCrop(true) cropOption.setMaxScaleMultiplier(100f) cropOption.setToolbarWidgetColor(Color.BLACK) cropOption.setStatusBarColor(Color.WHITE) cropOption.isDarkStatusBarBlack(true) cropOption.isDragCropImages(true) cropOption.setFreeStyleCropEnabled(config?.freeStyle ?: true) cropOption.setSkipCropMimeType(*getNotSupportCrop()) val ratioCount = config?.ratio?.size ?: 0 if (config?.defaultRatio != null || ratioCount > 0) { var ratioList = arrayOf(AspectRatio("Original", 0f, 0f)) if (ratioCount > 0) { config?.ratio?.take(4)?.toTypedArray()?.forEach { item -> ratioList += AspectRatio( item.title, item.width.toFloat(), item.height.toFloat() ) } } // Add default Aspects ratioList += arrayOf( AspectRatio(null, 1f, 1f), AspectRatio(null, 16f, 9f), AspectRatio(null, 4f, 3f), AspectRatio(null, 3f, 2f) ) config?.defaultRatio?.let { val defaultRatio = AspectRatio(it.title, it.width.toFloat(), it.height.toFloat()) ratioList = arrayOf(defaultRatio) + ratioList } cropOption.apply { setAspectRatioOptions( 0, *ratioList.take(5).toTypedArray() ) } } } private fun getNotSupportCrop(): Array { return arrayOf(PictureMimeType.ofGIF(), PictureMimeType.ofWEBP()) } private fun setEditMediaEvent(): OnMediaEditInterceptListener { return MediaEditInterceptListener(getSandboxPath(appContext), cropOption) } private fun setStyle() { val primaryColor = ColorPropConverter.getColor(config.primaryColor, appContext) val isNumber = config.selectMode == SelectMode.MULTIPLE && config.selectBoxStyle == SelectBoxStyle.NUMBER val selectType = if (isNumber) R.drawable.picture_selector else R.drawable.checkbox_selector val isDark = config.theme == Theme.DARK val backgroundDark = ColorPropConverter.getColor(config.backgroundDark, appContext) ?: ContextCompat.getColor( appContext, com.luck.picture.lib.R.color.ps_color_33 ) val foreground = if (isDark) Color.WHITE else Color.BLACK val background = if (isDark) backgroundDark else Color.WHITE val titleBar = TitleBarStyle() val bottomBar = BottomNavBarStyle() val mainStyle = SelectMainStyle() val iconBack = if (isDark) com.luck.picture.lib.R.drawable.ps_ic_back else com.luck.picture.lib.R.drawable.ps_ic_black_back cropOption.setLogoColor(primaryColor ?: Color.BLACK) // TITLE BAR titleBar.titleBackgroundColor = background titleBar.isAlbumTitleRelativeLeft = true titleBar.titleAlbumBackgroundResource = com.luck.picture.lib.R.drawable.ps_album_bg titleBar.titleDrawableRightResource = com.luck.picture.lib.R.drawable.ps_ic_grey_arrow titleBar.previewTitleLeftBackResource = iconBack titleBar.titleLeftBackResource = iconBack titleBar.isHideCancelButton = true // BOTTOM BAR bottomBar.bottomPreviewNormalTextColor = foreground bottomBar.bottomPreviewSelectTextColor = foreground bottomBar.bottomNarBarBackgroundColor = background bottomBar.bottomEditorTextColor = foreground bottomBar.bottomOriginalTextColor = foreground bottomBar.bottomPreviewNarBarBackgroundColor = background mainStyle.mainListBackgroundColor = foreground mainStyle.selectNormalTextColor = foreground mainStyle.isDarkStatusBarBlack = !isDark mainStyle.statusBarColor = background mainStyle.mainListBackgroundColor = background mainStyle.adapterPreviewGalleryItemSize = DensityUtil.dip2px(appContext, 52f); mainStyle.adapterPreviewGalleryBackgroundResource = if (isDark) com.luck.picture.lib.R.drawable.ps_preview_gallery_bg else R.drawable.preview_gallery_white_bg mainStyle.adapterPreviewGalleryFrameResource = R.drawable.preview_gallery_item mainStyle.previewBackgroundColor = background bottomBar.isCompleteCountTips = false bottomBar.bottomOriginalTextSize = Constant.TOOLBAR_TEXT_SIZE bottomBar.bottomSelectNumTextSize = Constant.TOOLBAR_TEXT_SIZE // bottomBar.bottomPreviewNormalTextSize = Constant.TOOLBAR_TEXT_SIZE // bottomBar.bottomEditorTextSize = Constant.TOOLBAR_TEXT_SIZE // MAIN STYLE mainStyle.isCompleteSelectRelativeTop = false mainStyle.isPreviewDisplaySelectGallery = true mainStyle.isAdapterItemIncludeEdge = true mainStyle.isPreviewSelectRelativeBottom = false // mainStyle.previewSelectTextSize = Constant.TOOLBAR_TEXT_SIZE mainStyle.selectTextColor = primaryColor ?: Color.BLACK // mainStyle.selectTextSize = Constant.TOOLBAR_TEXT_SIZE mainStyle.selectBackground = selectType mainStyle.isSelectNumberStyle = isNumber mainStyle.previewSelectBackground = selectType mainStyle.isPreviewSelectNumberStyle = isNumber if (config.camera != null) { // hide title camera mainStyle.adapterCameraText = " " } // custom toolbar text config.text.let { text -> text?.finish.let { mainStyle.selectText = it mainStyle.selectNormalText = it mainStyle.selectText = it } text?.preview.let { mainStyle.previewSelectText = it } text?.original.let { bottomBar.bottomOriginalText = it } text?.edit.let { bottomBar.bottomEditorText = it } } // SET STYLE style.titleBarStyle = titleBar style.bottomBarStyle = bottomBar style.selectMainStyle = mainStyle // ANIMATION SLIDE FROM BOTTOM val animationStyle = PictureWindowAnimationStyle() animationStyle.setActivityEnterAnimation(com.luck.picture.lib.R.anim.ps_anim_up_in) animationStyle.setActivityExitAnimation(com.luck.picture.lib.R.anim.ps_anim_down_out) style.windowAnimationStyle = animationStyle } private fun handleSelectedAssets(config: NitroConfig) { val assets = config.selectedAssets val assetIds = assets.map { it.localIdentifier }.toSet() dataList = dataList.filter { media -> assetIds.contains(media.id.toString()) }.toMutableList() } private fun getResult(item: LocalMedia): PickerResult { val type: ResultType = if (item.mimeType.startsWith("video/")) ResultType.VIDEO else ResultType.IMAGE var path = item.path var width: Double = item.width.toDouble() var height: Double = item.height.toDouble() val thumbnail = item.videoThumbnailPath?.let { if (!it.startsWith("file://")) "file://$it" else it } if (item.isCut) { path = "file://${item.cutPath}" width = item.cropImageWidth.toDouble() height = item.cropImageHeight.toDouble() } if (!path.startsWith("file://") && !path.startsWith("content://") && type == ResultType.IMAGE) path = "file://$path" val media = PickerResult( localIdentifier = item.id.toString(), width, height, mime = item.mimeType, size = item.size.toDouble(), bucketId = item.bucketId.toDouble(), realPath = item.realPath, parentFolderName = item.parentFolderName, creationDate = item.dateAddedTime.toDouble(), crop = item.isCut, path, type, fileName = item.fileName, thumbnail = thumbnail, duration = item.duration.toDouble() ) return media } override fun getAppContext(): Context { return reactApplicationContext } override fun getPictureSelectorEngine(): PictureSelectorEngine { return PictureSelectorEngineImp() } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/MultipleImagePickerPackage.java ================================================ package com.margelo.nitro.multipleimagepicker; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.TurboReactPackage; import java.util.HashMap; public class MultipleImagePickerPackage extends TurboReactPackage { @Nullable @Override public NativeModule getModule(@NonNull String name, @NonNull ReactApplicationContext reactContext) { return null; } @Override public ReactModuleInfoProvider getReactModuleInfoProvider() { return HashMap::new; } static { System.loadLibrary("MultipleImagePicker"); } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/PictureSelectorEngineImp.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.util.Log import com.luck.picture.lib.basic.IBridgeLoaderFactory import com.luck.picture.lib.engine.* import com.luck.picture.lib.engine.CompressEngine import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnInjectLayoutResourceListener import com.luck.picture.lib.interfaces.OnResultCallbackListener class PictureSelectorEngineImp : PictureSelectorEngine { /** * 重新创建[ImageEngine]引擎 * * @return */ override fun createImageLoaderEngine(): ImageEngine { return GlideEngine.createGlideEngine() } /** * 重新创建[CompressEngine]引擎 * * @return */ override fun createCompressEngine(): CompressEngine? { // TODO 这种情况是内存极度不足的情况下,比如开启开发者选项中的不保留活动或后台进程限制,导致CompressEngine被回收 return null } /** * 重新创建[CompressEngine]引擎 * * @return */ override fun createCompressFileEngine(): CompressFileEngine? { // TODO 这种情况是内存极度不足的情况下,比如开启开发者选项中的不保留活动或后台进程限制,导致CompressFileEngine被回收 return null } /** * 重新创建[ExtendLoaderEngine]引擎 * * @return */ override fun createLoaderDataEngine(): ExtendLoaderEngine? { return null } override fun createVideoPlayerEngine(): VideoPlayerEngine<*>? { return null } override fun onCreateLoader(): IBridgeLoaderFactory? { return null } /** * 重新创建[SandboxFileEngine]引擎 * * @return */ override fun createSandboxFileEngine(): SandboxFileEngine? { return null } override fun createUriToFileTransformEngine(): UriToFileTransformEngine? { return null } override fun createLayoutResourceListener(): OnInjectLayoutResourceListener? { return null } override fun getResultCallbackListener(): OnResultCallbackListener { return object : OnResultCallbackListener { override fun onResult(result: ArrayList) { Log.i(TAG, "onResult:" + result.size) } override fun onCancel() { Log.i(TAG, "PictureSelector onCancel") } } } companion object { private val TAG = PictureSelectorEngineImp::class.java.simpleName } } ================================================ FILE: android/src/main/java/com/margelo/nitro/multipleimagepicker/VideoThumbnailEngine.kt ================================================ package com.margelo.nitro.multipleimagepicker import android.content.Context import android.graphics.Bitmap import android.graphics.drawable.Drawable import com.bumptech.glide.Glide import com.bumptech.glide.request.target.CustomTarget import com.bumptech.glide.request.transition.Transition import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener import com.luck.picture.lib.interfaces.OnVideoThumbnailEventListener import com.luck.picture.lib.utils.PictureFileUtils import java.io.ByteArrayOutputStream import java.io.File import java.io.FileOutputStream import java.io.IOException class VideoThumbnailEngine(private val targetPath: String) : OnVideoThumbnailEventListener { override fun onVideoThumbnail( context: Context, videoPath: String, call: OnKeyValueResultCallbackListener ) { Glide.with(context).asBitmap().sizeMultiplier(0.6f).load(videoPath) .into(object : CustomTarget() { override fun onResourceReady( resource: Bitmap, transition: Transition? ) { val stream = ByteArrayOutputStream() resource.compress(Bitmap.CompressFormat.JPEG, 60, stream) var fos: FileOutputStream? = null var result: String? = null try { val targetFile = File(targetPath, "thumbnails_" + System.currentTimeMillis() + ".jpg") fos = FileOutputStream(targetFile) fos.write(stream.toByteArray()) fos.flush() result = targetFile.absolutePath } catch (e: IOException) { e.printStackTrace() } finally { PictureFileUtils.close(fos) PictureFileUtils.close(stream) } call.onCallback(videoPath, result) } override fun onLoadCleared(placeholder: Drawable?) { call.onCallback(videoPath, "") } }) } } ================================================ FILE: android/src/main/res/anim/anim_modal_in.xml ================================================ ================================================ FILE: android/src/main/res/drawable/checkbox_selector.xml ================================================ ================================================ FILE: android/src/main/res/drawable/complete_button.xml ================================================ ================================================ FILE: android/src/main/res/drawable/ic_checkmark.xml ================================================ ================================================ FILE: android/src/main/res/drawable/ic_down.xml ================================================ ================================================ FILE: android/src/main/res/drawable/num_oval.xml ================================================ ================================================ FILE: android/src/main/res/drawable/picture_not_selected.xml ================================================ ================================================ FILE: android/src/main/res/drawable/picture_selector.xml ================================================ ================================================ FILE: android/src/main/res/drawable/preview_gallery_item.xml ================================================ ================================================ FILE: android/src/main/res/drawable/preview_gallery_white_bg.xml ================================================ ================================================ FILE: android/src/main/res/layout/loading_dialog.xml ================================================ ================================================ FILE: android/src/main/res/values/colors.xml ================================================ #393a3e #000000 #f6f6f6 #fafafa #B6B6B6 #f94c51 #43c117 #53575e #00000000 #FFFFFF #E0DBDBDB #7D7DFF #9b9b9b #E0FF6100 #FF0000 #FB9300 #333333 #0D333333 ================================================ FILE: android/src/main/res/values/styles.xml ================================================ ================================================ FILE: babel.config.js ================================================ module.exports = { presets: ['module:metro-react-native-babel-preset'], }; ================================================ FILE: docs/.gitignore ================================================ # Dependencies /node_modules # Production /build # Generated files .docusaurus .cache-loader # Misc .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* ================================================ FILE: docs/docs/CAMERA.mdx ================================================ --- id: camera title: Camera 📸 sidebar_label: Camera 📸 slug: /camera --- import ReactPlayer from 'react-player' The camera module provides a simple interface for capturing photos and recording videos with customizable options. ## Usage ```typescript import { openCamera } from '@baronha/react-native-multiple-image-picker' const open = async () => { try { const response = await openCamera({ mediaType: 'all', cameraDevice: 'back' }) console.log(response) } catch (e) { console.log(e) } } ``` ## Configuration Options ### `mediaType` Specifies the type of media that can be captured. ```typescript mediaType?: 'video' | 'image' | 'all' ``` **Default:** `'all'` ### `cameraDevice` Selects which camera to use for capture. ```typescript cameraDevice?: 'front' | 'back' ``` **Default:** `'back'` ### `videoMaximumDuration` Sets the maximum duration for video recording in seconds. ```typescript videoMaximumDuration?: number ``` **Default:** No limit ### `presentation` Controls how the camera view is presented (iOS only). ```typescript presentation?: 'fullScreenModal' | 'formSheet' ``` **Default:** `'fullScreenModal'` ### `language` Sets the interface language. ```typescript language?: Language ``` **Supported values:** - 🌐 `'system'`: System default - 🇨🇳 `'zh-Hans'`: Simplified Chinese - 🇹🇼 `'zh-Hant'`: Traditional Chinese - 🇯🇵 `'ja'`: Japanese - 🇰🇷 `'ko'`: Korean - 🇬🇧 `'en'`: English - 🇹🇭 `'th'`: Thai - 🇮🇩 `'id'`: Indonesian - 🇻🇳 `'vi'`: Vietnamese - 🇷🇺 `'ru'`: Russian - 🇩🇪 `'de'`: German - 🇫🇷 `'fr'`: French - 🇸🇦 `'ar'`: Arabic **Default:** `'system'` ### `crop` Enables and configures image cropping after capture. See details in [Crop Configuration](/config/#crop-) ### `color` - **Type**: [**ColorValue**](https://reactnative.dev/docs/colors) - **Default**: 🟦 `#2979ff` - **Required**: No - **Platform**: iOS, Android ## Result Type The camera function returns a `CameraResult` object: ```typescript interface CameraResult { /** * Path to the captured media file * - iOS: Starts with 'file://' * - Android: Can start with 'file://' or 'content://' */ path: string /** * Type of captured media * - 'video': For video recordings * - 'image': For photos */ type: 'video' | 'image' /** * Width of the media in pixels * For cropped images, this represents the final cropped width */ width: number /** * Height of the media in pixels * For cropped images, this represents the final cropped height */ height: number /** * Duration of the video in seconds * Only available when type is 'video' * @platform ios, android */ duration: number /** * Path to the video thumbnail image * Only available when type is 'video' * Format: 'file://path/to/thumbnail.jpg' * @platform ios, android */ thumbnail?: string /** * Original filename of the captured media * Example: 'IMG_1234.JPG' or 'VID_5678.MP4' */ fileName: string } ``` ### Example Response #### Photo Capture ```typescript { path: 'file:///var/mobile/Containers/.../IMG_0123.JPG', type: 'image', width: 3024, height: 4032, fileName: 'IMG_0123.JPG' } ``` #### Video Recording ```typescript { path: 'file:///var/mobile/Containers/.../VID_0124.MP4', type: 'video', width: 1920, height: 1080, duration: 15.6, thumbnail: 'file:///var/mobile/Containers/.../VID_0124_thumb.JPG', fileName: 'VID_0124.MP4' } ``` ### Notes - The `path` format may vary between iOS and Android. Always use the provided path as-is. - Video thumbnails are automatically generated and provided in the `thumbnail` property. - For cropped images, the `width` and `height` reflect the dimensions after cropping. - The `duration` property is only available for video recordings and is measured in seconds. - All file paths are provided with the appropriate prefix (`file://` or `content://`). ## Examples ### Photo Capture ```typescript const result = await openCamera({ mediaType: 'image', cameraDevice: 'back' }) ``` ### Video Recording ```typescript const result = await openCamera({ mediaType: 'video', videoMaximumDuration: 30, cameraDevice: 'front' }) ``` ### With Cropping ```typescript const result = await openCamera({ mediaType: 'image', crop: { circle: true, ratio: [ { title: "Square", width: 1, height: 1 }, { title: "Portrait", width: 3, height: 4 } ] } }) ``` ### Custom UI ```typescript const result = await openCamera({ color: '#FF6B6B', language: 'en', presentation: 'fullScreenModal' }) ``` ## Platform Specific Notes ### iOS - Supports `presentation` option for modal style - Full support for all UI customization options ### Android - Maximum 4 custom crop ratios - Some UI elements may appear differently ## Required Permissions ### iOS Add to `Info.plist`: ```xml NSCameraUsageDescription Camera access is required to take photos and videos NSMicrophoneUsageDescription Microphone access is required to record videos ``` ### Android Add to `AndroidManifest.xml`: ```xml ``` ================================================ FILE: docs/docs/CONFIG.mdx ================================================ --- id: config title: Configuration sidebar_label: Configuration slug: /config --- # Configuration ### `selectMode` Mode of selection in the picker. - **Type**: string - **Default**: `multiple` - **Required**: No - **Options**: - `single`: Single selection mode - `multiple`: Multiple selection mode ### `selectedAssets` Keep previous selection in Multiple Image Picker
See [**Result**](/result) - **Type**: Result[] - **Default**: `[]` - **Required**: No ### `allowedLimit` Display additional select more media when permission on `iOS` is limited. - **Type**: boolean - **Default**: `true` - **Required**: No - **Platform**: iOS ### `allowSwipeToSelect` Allow swiping to select items. - **Type**: boolean - **Default**: `true` - **Required**: No - **Platform**: iOS, Android ### `isHiddenOriginalButton` Hide the original button. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS, Android ### `maxSelect` Maximum number of items that can be selected. - **Type**: number - **Default**: `20` - **Required**: No - **Platform**: iOS, Android ### `maxVideo` Maximum number of videos allowed. - **Type**: number - **Default**: `20` - **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. - **Type**: object - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android ### `circle` Enable circular crop mask. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS, Android ### `ratio` Aspect ratios for cropping. Android: Maximum: 4 items - **Type**: `array` - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android - **Properties**: - `title`: string - Display title for the ratio (e.g., "Square", "16:9") - `width`: number - Width value for the aspect ratio - `height`: number - Height value for the aspect ratio ### `defaultRatio` Default ratio to be selected when opening the crop interface. - **Type**: `object` - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android - **Properties**: - `title`: string - Display title for the ratio (e.g., "Square", "16:9") - `width`: number - Width value for the aspect ratio - `height`: number - Height value for the aspect ratio ### `freeStyle` Enable free style cropping. - **Type**: `boolean` - **Default**: `false` - **Required**: No - **Platform**: iOS, Android --- ## UI Customize 🌈 ### `theme` Theme mode for the picker. - **Type**: string - **Default**: `system` - **Required**: No - **Platform**: iOS, Android - **Options**: - `light`: Light theme - `dark`: Dark theme - `system`: System default theme ### `primaryColor` Primary color for the picker UI elements. - **Type**: [**ColorValue**](https://reactnative.dev/docs/colors) - **Default**: 🟦 `#2979ff` - **Required**: No - **Platform**: iOS, Android ### `backgroundDark` Background color for dark mode UI elements. - **Type**: [**ColorValue**](https://reactnative.dev/docs/colors) - **Default**: ⚫️ `#1A1A1A` - **Required**: No - **Platform**: iOS, Android ### `selectBoxStyle` Style of selection box in the picker. - **Type**: string - **Default**: `number` - **Required**: No - **Options**: - `number`: Show numbers in selection box - `tick`: Show checkmark in selection box ### `spacing` Spacing between items in the grid. - **Type**: number - **Default**: `2` - **Required**: No - **Platform**: iOS, Android ### `numberOfColumn` Number of columns in the grid view. - **Type**: number - **Default**: `4` - **Required**: No - **Platform**: iOS, Android ### `presentation` Modal presentation style for the picker. - **Type**: string - **Default**: `fullScreenModal` - **Required**: No - **Platform**: iOS - **Options**: - `fullScreenModal`: Full screen presentation - `formSheet`: Form sheet presentation --- ## Filter data 🎞️ ### `mediaType` Type of media to be displayed in the picker. - **Type**: string - **Default**: `all` - **Required**: No - **Options**: - `video`: Only show videos - `image`: Only show images - `all`: Show both videos and images ### `maxVideoDuration` Maximum duration for videos in seconds. - **Type**: number - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android ### `minVideoDuration` Minimum duration for videos in seconds. - **Type**: number - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android ### `maxFileSize` Maximum file size in bytes. - **Type**: number - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android --- ## Preview 🌠 ### `isPreview` Enable preview functionality. - **Type**: boolean - **Default**: `true` - **Required**: No - **Platform**: iOS, Android ### `isShowPreviewList` Show preview list. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS ### `isHiddenPreviewButton` Hide the preview button and button mode. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS, Android ### `allowHapticTouchPreview` Enable haptic feedback on preview. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS --- ## Localization 🌐 ### `text` Custom text labels for buttons and headers. - **Type**: object - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android - **Properties**: - `finish`: string - Text for finish/done button - `original`: string - Text for original button - `preview`: string - Text for preview button - `edit`: string - Text for edit button ### `language` Interface language for the picker. - **Type**: string - **Default**: `system` - **Required**: No - **Options**: - `system`: 🌐 System default - `zh-Hans`: 🇨🇳 Simplified Chinese - `zh-Hant`: 🇹🇼 Traditional Chinese - `ja`: 🇯🇵 Japanese - `ko`: 🇰🇷 Korean - `en`: 🇬🇧 English - `vi`: 🇻🇳 Vietnamese - `ru`: 🇷🇺 Russian - `de`: 🇩🇪 German - `fr`: 🇫🇷 French - `ar`: 🇸🇦 Arabic **iOS Only**: - `id`: 🇮🇩 Indonesian - `th`: 🇹🇭 Thai ================================================ FILE: docs/docs/CROP.mdx ================================================ --- id: crop title: Crop 🍕 sidebar_label: Crop 🍕 slug: /crop --- ## Usage ```typescript import { openCropper } from '@baronha/react-native-multiple-image-picker' const cropConfig: CropConfig = { // ... } const open = async () => { try { const response = await openCropper('file://path/to/image.jpg', cropConfig) setImages(response) } catch (e) { // catch error for multiple image picker } } ``` ## CropConfig ### `circle` Enable circular crop mask. - **Type**: boolean - **Default**: `false` - **Required**: No - **Platform**: iOS, Android ### `ratio` Aspect ratios for cropping. Android: Maximum: 4 items - **Type**: `array` - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android - **Properties**: - `title`: string - Display title for the ratio (e.g., "Square", "16:9") - `width`: number - Width value for the aspect ratio - `height`: number - Height value for the aspect ratio ### `defaultRatio` Default ratio to be selected when opening the crop interface. - **Type**: `object` - **Default**: `undefined` - **Required**: No - **Platform**: iOS, Android - **Properties**: - `title`: string - Display title for the ratio (e.g., "Square", "16:9") - `width`: number - Width value for the aspect ratio - `height`: number - Height value for the aspect ratio ### `freeStyle` Enable free style cropping. - **Type**: `boolean` - **Default**: `false` - **Required**: No - **Platform**: iOS, Android ### `language` - **Type**: `string` - **Default**: `false` - **Required**: No - **Platform**: iOS See [**Language**](/config/#language) ## Result ### `path` - **Type**: `string` ### `width` - **Type**: `number` ### `height` - **Type**: `number` ================================================ FILE: docs/docs/GETTING_STARTED.mdx ================================================ --- id: getting-started title: Getting Started sidebar_label: Getting Started sidebar_id: getting-started slug: /getting-started --- import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' import useBaseUrl from '@docusaurus/useBaseUrl' ## Requirements Because RNMIP uses Nitro Module, it complies with Nitro Modules' requirements.
View Nitro Modules' requirements [here](https://nitro.margelo.com/docs/minimum-requirements) - `iOS` 13+ - `react-native` 0.75+ - `Xcode` 16+ - `react-native` 0.75+ - `compileSdkVersion` 34+ ## Installing Install [@baronha/react-native-multiple-image-picker](https://www.npmjs.com/package/@baronha/react-native-multiple-image-picker) through npm: > This package requires `react-native-nitro-modules` to be installed first. > See [react-native-nitro-modules](https://github.com/mrousavy/nitro) for more information. ```bash yarn add @baronha/react-native-multiple-image-picker yarn add -D react-native-nitro-modules cd ios && pod install ``` ```bash npx expo install @baronha/react-native-multiple-image-picker npx expo install react-native-nitro-modules -- --dev npx expo prebuild ``` ## Updating manifests ### Info.plist Open your project's `Info.plist` and add the following lines inside the outermost `` tag: ```xml NSPhotoLibraryAddUsageDescription $(PRODUCT_NAME) needs photo library permissions NSPhotoLibraryUsageDescription $(PRODUCT_NAME) needs photo library permissions NSCameraUsageDescription $(PRODUCT_NAME) needs to access your Camera NSMicrophoneUsageDescription $(PRODUCT_NAME) needs to access your microphone so that you can record audio. ``` ### Managed Expo Config your Expo app (`app.json`, `app.config.json` or `app.config.js`): ```json { "name": "my app", "ios": { // ... "infoPlist": { "NSPhotoLibraryAddUsageDescription": "$(PRODUCT_NAME) needs photo library permissions", "NSPhotoLibraryUsageDescription": "$(PRODUCT_NAME) needs photo library permissions", // if you allow camera, you need to add this "NSCameraUsageDescription": "$(PRODUCT_NAME) needs to access your Camera", "NSMicrophoneUsageDescription": "$(PRODUCT_NAME) needs to access your microphone so that you can record audio" } // ... } } ``` Finally, compile the mods: ```bash npx expo prebuild ``` To apply the changes, build a new binary with EAS: ```bash eas build ```
#### 🎉 Hooray! You're ready to learn about [Usage](/usage)! --- ================================================ FILE: docs/docs/PREVIEW.mdx ================================================ --- id: preview title: Preview 🎑 sidebar_label: Preview 🎑 slug: /preview --- import ReactPlayer from 'react-player' ## Overview Preview is a simple image viewer that supports both local and remote media. It allows you to preview images and videos seamlessly. ## Usage ```typescript import { openPreview, PreviewConfig, } from '@baronha/react-native-multiple-image-picker' const previewConfig: PreviewConfig = { language: 'system', } const media: MediaPreview[] = [ // remote image { path: 'https://images.unsplash.com/photo-1733235015085-fc29c17c4a16?w=500', type: 'image', }, // local video { path: 'file://Documents/video-sample/mp4', thumbnail: 'https://images.unsplash.com/photo-1733889886752-f4599c954608?q=80&w=2574&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', type: 'video', }, // remote video { path: 'https://cdn.pixabay.com/video/2024/02/09/199958-911694865_large.mp4', type: 'video', }, ] // call to preview openPreview(media, 2, previewConfig) ``` ## `MediaPreview[]` `MediaPreview[]` is an array of media objects that you want to preview. Each object in the array should have the following properties:
**NOTE**: You can also use [`Result[]`](/result) from openPicker's return result - `path`: A string representing the URL or file path of the media. - `type`: A string indicating the type of media, either `image` or `video`. - `thumbnail` (optional): A string representing the URL of the thumbnail image for videos. - `localIdentifier` (optional): A string representing the local identifier for media from device gallery. ## `index` default: `0` The `index` parameter in the `openPreview` function specifies the initial media item to display. It is a zero-based index, meaning that `0` will display the first item in the `MediaPreview` array. ## `previewConfig` ### [`language`](/config/#language) see [`language`](/config/#language) ### `onLongPress` `onLongPress` is a callback function that is called when a long press is detected on the media item. It is a function that takes an index as an argument and returns void. ```typescript onLongPress: (index: number) => void ``` ## Additional Information - Ensure that the media paths are accessible and correctly formatted. - The `openPreview` function is part of the `@baronha/react-native-multiple-image-picker` package, which should be installed and properly configured in your project. For more detailed information, refer to the [official documentation](https://github.com/baronha/react-native-multiple-image-picker). ================================================ FILE: docs/docs/RESULT.mdx ================================================ --- id: result title: Result sidebar_label: Result slug: /result --- The result object returned for each selected media item. ### `path` - **Type**: string - **Description**: Local file path of the media ### `fileName` - **Type**: string - **Description**: Name of the media file ### `localIdentifier` - **Type**: string - **Description**: Unique identifier for the media asset ### `width` - **Type**: number - **Description**: Width of the media in pixels ### `height` - **Type**: number - **Description**: Height of the media in pixels ### `mime` - **Type**: string - **Description**: MIME type of the media file ### `size` - **Type**: number - **Description**: File size in bytes ### `bucketId` - **Type**: number - **Description**: ID of the bucket containing the media - **Platform**: Android ### `realPath` - **Type**: string - **Description**: Actual file path in the device storage - **Platform**: Android ### `parentFolderName` - **Type**: string - **Description**: Name of the parent folder - **Platform**: Android ### `creationDate` - **Type**: number - **Description**: Creation timestamp of the media ### `type` - **Type**: string - **Options**: `image` | `video` - **Description**: Type of the media file ### `duration` - **Type**: number - **Description**: Duration in seconds (for video files) ### `thumbnail` - **Type**: string - **Description**: Thumbnail path for video files ### `crop` - **Type**: boolean - **Description**: Indicates if the media has been cropped ================================================ FILE: docs/docs/SHOWCASE/index.mdx ================================================ --- id: showcase title: Showcase ✨ sidebar_label: Showcase ✨ slug: /showcase --- import style from './showcase.css' import data from './showcase.json' List of used applications with `@baronha/react-native-multiple-image-picker` > Contributions are welcome! If you have an application that uses `@baronha/react-native-multiple-image-picker`
> please open a [**Pull Request**](https://github.com/baronha/react-native-multiple-image-picker/tree/master/docs/docs/SHOWCASE/showcase.json) to add it to the list.
{data.map((item, index) => { return ( {item.title} {item.title}

{item?.tagline}

) })}
================================================ FILE: docs/docs/SHOWCASE/showcase.css ================================================ .showcaseContainer { display: flex; /* justify-content: space-between; */ flex-wrap: wrap; gap: 20px; } .showcaseItem { flex: 1; color: inherit; text-decoration: none; } .showcaseItem a:hover { color: red; text-decoration: none !important; } .showcaseItem b { font-size: 1rem; } .showcaseItem .showcaseTagline { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; margin: 0; } .showcaseBanner { width: 100%; aspect-ratio: 16/9; object-fit: cover; } @media (max-width: 768px) { .showcaseItem { flex: 100%; margin-right: 0; } } @media (min-width: 992px) { /* lg */ .showcaseItem { max-width: 33.333%; } } @media (min-width: 1200px) { /* xl */ .showcaseItem { max-width: 33.333%; } } @media (min-width: 1400px) { /* xxl */ .showcaseItem { max-width: 33.333%; } } @media (max-width: 480px) { .showcaseItem { flex: 100%; } } ================================================ FILE: docs/docs/SHOWCASE/showcase.json ================================================ [ { "banner": "https://github.com/user-attachments/assets/84ec6432-1557-4649-965c-6100d9c4c12d", "title": "✨ Binsoo - Photo Filters & Editor", "link": "https://apps.apple.com/vn/app/binsoo-photo-filters-editor/id6502683720", "tagline": "Endless aesthetics and effects" }, { "banner": "https://github.com/user-attachments/assets/72a7787a-4a41-40e3-b6bb-a5c7b0eafc83", "title": "Pupi", "link": "https://apps.apple.com/vn/app/pupi-h%E1%BB%8Dc-vui-ti%E1%BA%BFn-b%E1%BB%99/id1638474798", "tagline": "Học vui & tiến b‪ộ" }, { "banner": "https://github.com/user-attachments/assets/dd92d243-7fb0-40ff-9b78-7b4fd2a54092", "title": "Pety", "link": "https://apps.apple.com/vn/app/pety/id1506375124", "tagline": "New Lifestyle for Pet Lovers" } ] ================================================ FILE: docs/docs/USAGE.mdx ================================================ --- id: usage title: Usage sidebar_label: Usage slug: /usage --- Here is a simple usage of the Multiple Image Picker.
See more [**Config**](/config) ```typescript import { openPicker, Config } from '@baronha/react-native-multiple-image-picker' const config: Config = { maxSelect: 10, maxVideo: 10, primaryColor: '#FB9300', backgroundDark: '#2f2f2f', numberOfColumn: 4, mediaType: 'all', selectBoxStyle: 'number', selectMode: 'multiple', language: 'vi', // 🇻🇳 Vietnamese theme: 'dark', isHiddenOriginalButton: false, primaryColor: '#F6B35D', } const onPicker = async () => { try { const response = await openPicker(config) setImages(response) } catch (e) { // catch error for multiple image picker } } ``` ================================================ FILE: docs/docs/index.md ================================================ --- id: index title: Multiple Image Picker | BAO HA hide_title: true sidebar_label: Multiple Image Picker description: 🏞 react-native-multiple-image-picker enables applications to pick images and videos from multiple smart albums in iOS/Android image: img/banner.png slug: / --- import ReactPlayer from 'react-player' ![Logo][Logo] [![iOS][iOS]][iOS-URL] [![Android][Android]][Android-URL] [![Swift][Swift]][Swift-URL] [![Kotlin][Kotlin]][Kotlin-URL] [![React-Native][React-Native]][React-Native-URL] ## Overview 🎇 React Native Multiple Image Picker **(RNMIP)** enables application to pick images and videos from multiple smart album in iOS/Android. React Native Multiple Image Picker is based on two libraries available, [HXPhotoPicker](https://github.com/SilenceLove/HXPhotoPicker) and [PictureSelector](https://github.com/LuckSiege/PictureSelector) ## Features 🔥 | 🤩 | ![Logo][Logo] | | --- | ------------------------------------------------------------------------------ | | 🍕 | [**Crop**](/crop) single/multiple image. | | 🎑 | [**Preview**](/preview) image/video. | | 📸 | [**Camera**](/camera) module for capturing photos and recording videos. | | 🐳 | Keep the previous selection. | | 0️⃣ | Selected order index. | | 🎨 | UI Customization (numberOfColumn, spacing, primaryColor ... ) | | 🌚 | Dark Mode, Light Mode | | 🌄 | Choose multiple images/video. | | 📦 | Support smart album `(camera roll, selfies, panoramas, favorites, videos...)`. | | 📺 | Display video duration. | | ⛅️ | Support iCloud Photo Library. | | 🌪 | Scrolling performance. ☕️ | ## Sponsor & Support ☕️ To keep this library maintained and up-to-date please consider [sponsoring it on GitHub](https://github.com/sponsors/baronha). Or if you are looking for a private support or help in customizing the experience, then reach out to me on Twitter [@\_baronha](https://twitter.com/_baronha). ## Built With ❤️ [![NitroModules](https://img.shields.io/badge/Nitro_Modules-0052CC?style=for-the-badge)](https://nitro.margelo.com/docs/nitro-modules) [![HXPhotoPicker](https://img.shields.io/badge/HXPhotoPicker-F05138?style=for-the-badge)](https://github.com/SilenceLove/HXPhotoPicker) [![PictureSelector](https://img.shields.io/badge/Picture_Selector-b07219?style=for-the-badge)](https://github.com/LuckSiege/PictureSelector) [iOS]: https://img.shields.io/badge/iOS-000000?style=for-the-badge&logo=ios&logoColor=white [iOS-URL]: https://www.apple.com/ios [Android]: https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white [Android-URL]: https://www.android.com/ [React-Native]: https://img.shields.io/badge/React_Native-20232A?style=for-the-badge&logo=react&logoColor=61DAFB [React-Native-URL]: https://reactnative.dev/ [React-Native]: https://img.shields.io/badge/React_Native-20232A?style=for-the-badge&logo=react&logoColor=61DAFB [React-Native-URL]: https://reactnative.dev/ [Swift]: https://img.shields.io/badge/Swift-FA7343?style=for-the-badge&logo=swift&logoColor=white [Swift-URL]: https://developer.apple.com/swift/ [Kotlin]: https://img.shields.io/badge/Kotlin-0095D5?&style=for-the-badge&logo=kotlin&logoColor=white [Kotlin-URL]: https://kotlinlang.org/ [Logo]: https://img.shields.io/badge/React_Native_Multiple_Image_Picker-DF78C3?style=for-the-badge ================================================ FILE: docs/docusaurus.config.ts ================================================ import { themes as prismThemes } from 'prism-react-renderer' import type { Config } from '@docusaurus/types' import type * as Preset from '@docusaurus/preset-classic' // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) const config: Config = { title: 'React Native Multiple Image Picker', tagline: 'High-performance React Native Multiple Image Picker library.', favicon: 'img/favicon.ico', // Set the production url of your site here url: 'https://nitrogenzlab.github.io', // Set the // pathname under which your site is served // For GitHub pages deployment, it is often '//' baseUrl: '/react-native-multiple-image-picker', // GitHub pages deployment config. // If you aren't using GitHub pages, you don't need these. organizationName: 'baronha', // Usually your GitHub org/user name. projectName: 'react-native-multiple-image-picker', // Usually your repo name. trailingSlash: false, onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'warn', // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you // may want to replace "en" with "zh-Hans". i18n: { defaultLocale: 'en', locales: ['en', 'vi'], path: 'i18n', localeConfigs: { en: { label: 'English', direction: 'ltr', htmlLang: 'en-US', calendar: 'gregory', path: 'en', }, }, }, presets: [ [ '@gorhom/docusaurus-preset', { docs: { sidebarPath: './sidebars.ts', routeBasePath: '/', editUrl: 'https://github.com/NitrogenZLab/react-native-multiple-image-picker/tree/main/docs/docs', lastVersion: 'current', versions: { current: { label: 'v2.0', }, }, }, theme: { customCss: './src/css/custom.css', }, } satisfies Preset.Options, ], ], themeConfig: { // Replace with your project's social card image: 'img/banner.png', colorMode: { defaultMode: 'dark', disableSwitch: false, respectPrefersColorScheme: true, }, navbar: { title: 'RNMIP', logo: { alt: 'RNMIP Logo', src: 'img/RNMIP.png', }, items: [ { type: 'docSidebar', sidebarId: 'multiple-image-picker', position: 'left', label: 'Guides', }, { href: 'https://github.com/NitrogenZLab/react-native-multiple-image-picker/tree/main/example', label: 'Example', position: 'left', }, { href: '/showcase', label: 'Showcase', position: 'left', }, { href: 'https://github.com/NitrogenZLab/react-native-multiple-image-picker', label: 'GitHub', position: 'right', }, { href: 'https://apps.apple.com/vn/app/binsoo-photo-filters-editor/id6502683720', label: '✨ Binsoo - Photo Editor', position: 'right', }, ], }, footer: { style: 'dark', links: [ { title: 'Guides', items: [ { label: 'Getting Started', to: '/getting-started', }, { label: 'Config', to: '/config', }, { label: 'Result', to: '/result', }, { label: '☕️ Buy me a coffee', href: 'https://github.com/sponsors/baronha', }, ], }, { title: 'Community', items: [ { label: 'X', href: 'https://x.com/_baronha', }, { label: 'Threads', href: 'https://www.threads.net/@___donquijote', }, ], }, { title: 'More', items: [ { label: 'Github', href: 'https://github.com/baronha', }, { label: 'Binsoo - Photo Editor', href: 'https://apps.apple.com/vn/app/binsoo-photo-filters-editor/id6502683720', }, ], }, ], copyright: `Copyright © ${new Date().getFullYear()} Bảo Hà (baronha)`, }, prism: { theme: prismThemes.github, darkTheme: prismThemes.dracula, }, } satisfies Preset.ThemeConfig, } export default config ================================================ FILE: docs/package.json ================================================ { "name": "docs", "version": "2.2.6", "private": true, "scripts": { "docusaurus": "docusaurus", "start": "docusaurus start", "build": "docusaurus build", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "clear": "docusaurus clear", "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "tsc", "postinstall": "patch-package" }, "dependencies": { "@docusaurus/core": "3.5.2", "@docusaurus/plugin-google-gtag": "^3.5.2", "@docusaurus/preset-classic": "3.5.2", "@gorhom/docusaurus-preset": "*", "@gorhom/docusaurus-theme": "*", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-player": "^2.16.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.5.2", "@docusaurus/tsconfig": "3.5.2", "@docusaurus/types": "3.5.2", "patch-package": "^8.0.0", "typescript": "~5.6.2" }, "browserslist": { "production": [ ">0.5%", "not dead", "not op_mini all" ], "development": [ "last 3 chrome version", "last 3 firefox version", "last 5 safari version" ] }, "engines": { "node": ">=18.0" } } ================================================ FILE: docs/patches/@gorhom+docusaurus-preset+1.0.2.patch ================================================ diff --git a/node_modules/@gorhom/docusaurus-preset/lib/index.js b/node_modules/@gorhom/docusaurus-preset/lib/index.js index 66e815e..7ab6b15 100644 --- a/node_modules/@gorhom/docusaurus-preset/lib/index.js +++ b/node_modules/@gorhom/docusaurus-preset/lib/index.js @@ -23,21 +23,21 @@ export default function preset(context, opts = {}) { theme: prismThemes.github, darkTheme: prismThemes.dracula, }; - // overrides footer - themeConfig.footer = { - ...(themeConfig.footer ?? {}), - copyright: `Open Source by Mo Gorhom.`, - links: [ - { - label: "Github", - href: "https://github.com/gorhom", - }, - { - label: "X (Twitter)", - href: "https://twitter.com/gorhom", - }, - ] - }; + // overrides footer + themeConfig.footer = { + + copyright: `Open Source by Bao Ha.`, + links: [ + { + label: "Github", + href: "https://github.com/baronha", + }, + { + label: "X (Twitter)", + href: "https://twitter.com/_baronha", + }, + ], + } const themes = []; themes.push(makePluginConfig("@gorhom/docusaurus-theme", theme)); if (algolia) { ================================================ FILE: docs/sidebars.ts ================================================ import type { SidebarsConfig } from '@docusaurus/plugin-content-docs' // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) /** * Creating a sidebar enables you to: - create an ordered group of docs - render a sidebar for each doc of that group - provide next/previous navigation The sidebars can be generated from the filesystem, or explicitly defined here. Create as many sidebars as you want. */ const sidebars: SidebarsConfig = { 'multiple-image-picker': [ { type: 'category', label: 'RNMIP', link: { type: 'doc', id: 'index', }, items: ['getting-started', 'usage', 'config', 'result'], }, 'crop', 'preview', 'camera', ], } export default sidebars ================================================ FILE: docs/src/css/custom.css ================================================ ================================================ FILE: docs/static/.nojekyll ================================================ ================================================ FILE: docs/tsconfig.json ================================================ { // This file is not used in compilation. It is here just for a nice editor experience. "extends": "@docusaurus/tsconfig", "compilerOptions": { "baseUrl": "." }, "exclude": [".docusaurus", "build"] } ================================================ FILE: example/.gitignore ================================================ # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files # dependencies node_modules/ # Expo .expo/ dist/ web-build/ # Native *.orig.* *.jks *.p8 *.p12 *.key *.mobileprovision # Metro .metro-health-check* # debug npm-debug.* yarn-debug.* yarn-error.* # macOS .DS_Store *.pem # local env files .env*.local # typescript *.tsbuildinfo /ios /android ================================================ FILE: example/App.tsx ================================================ import { LogBox, UIManager } from 'react-native' import App from './src' LogBox.ignoreAllLogs() UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true) export default App ================================================ FILE: example/Gemfile ================================================ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version ruby ">= 3.0.0" # Exclude problematic versions of cocoapods and activesupport that causes build failures. gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' ================================================ FILE: example/README.md ================================================ # Example This website is built using [Expo](https://docs.expo.dev/) https://github.com/user-attachments/assets/79580bc7-237c-46b7-b92e-1479cc6d9079 ### Installation ``` $ yarn $ yarn prebuild --clean ``` ### Step 2 ``` $ NNN Enjoy Bro 🐧 ``` ================================================ FILE: example/app.json ================================================ { "expo": { "name": "MultipleImagePickerExample", "slug": "MultipleImagePickerExample", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "automatic", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "ios": { "supportsTablet": true, "infoPlist": { "NSCameraUsageDescription": "We needs to access your camera so that you can upload your photo: (avatar, etc.)", "NSPhotoLibraryAddUsageDescription": "We needs photo library permissions to allow you to upload profile images.", "NSPhotoLibraryUsageDescription": "We needs photo library permissions to allow you to upload profile images.", "NSMicrophoneUsageDescription": "We needs to access your microphone so that you can take your photo: (avatar, etc.)" }, "bundleIdentifier": "com.baoha.imagepicker" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, "package": "com.baoha.imagepicker" }, "plugins": [ [ "expo-build-properties", { "ios": { "deploymentTarget": "15.6", "useFrameworks": "static" }, "android": { "compileSdkVersion": 34, "targetSdkVersion": 34, "buildToolsVersion": "34.0.0" } } ] ] } } ================================================ FILE: example/babel.config.js ================================================ const path = require('path') module.exports = function (api) { api.cache(true) return { presets: ['babel-preset-expo'], plugins: [ [ 'module-resolver', { extensions: ['.tsx', '.ts', '.js', '.json'], alias: { // For development, we want to alias the library to the source '@baronha/react-native-multiple-image-picker': path.join( __dirname, '..', 'src', 'index.ts' ), }, }, ], ], } } ================================================ FILE: example/metro.config.js ================================================ // Learn more https://docs.expo.io/guides/customizing-metro const { getDefaultConfig } = require('expo/metro-config') const path = require('path') const config = getDefaultConfig(__dirname) // npm v7+ will install ../node_modules/react-native because of peerDependencies. // To prevent the incompatible react-native bewtween ./node_modules/react-native and ../node_modules/react-native, // excludes the one from the parent folder when bundling. config.resolver.blockList = [ ...Array.from(config.resolver.blockList ?? []), new RegExp(path.resolve('..', 'node_modules', 'react-native')), ] config.resolver.nodeModulesPaths = [ path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../node_modules'), ] config.watchFolders = [path.resolve(__dirname, '..')] config.transformer.getTransformOptions = async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }) module.exports = config ================================================ FILE: example/package.json ================================================ { "name": "multipleimagepickerexample", "version": "2.2.3", "main": "expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", "pod": "cd ios && bundle exec pod update", "pod-new-arch": "cd ios && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install", "prebuild": "expo prebuild", "gradle": "cd android && ./gradlew clean && ./gradlew build" }, "dependencies": { "@react-native-segmented-control/segmented-control": "2.5.7", "expo": "^54.0.27", "expo-build-properties": "~1.0.10", "expo-status-bar": "~3.0.9", "expo-system-ui": "~6.0.9", "immer": "^10.1.1", "react": "19.1.0", "react-native": "0.81.5", "use-immer": "^0.10.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@react-native/babel-preset": "0.75.2", "@react-native/metro-config": "0.75.2", "@react-native/typescript-config": "0.75.2", "@types/react": "~19.1.10", "react-native-builder-bob": "^0.30.0", "react-native-nitro-modules": "^0.25.2", "typescript": "~5.9.2" }, "private": true } ================================================ FILE: example/react-native.config.js ================================================ const path = require('path') const pkg = require('../package.json') module.exports = { project: { ios: { automaticPodsInstallation: true, }, }, dependencies: { [pkg.name]: { root: path.join(__dirname, '..'), }, }, } ================================================ FILE: example/src/assets/index.ts ================================================ const images = { logo: require('./logo.png'), plusSign: require('./plus-sign.png'), check: require('./check.png'), } export default images ================================================ FILE: example/src/common/const.ts ================================================ import { Platform } from 'react-native' export const IS_IOS = Platform.OS === 'ios' export const IS_ANDROID = Platform.OS === 'android' export const LOCALIZED_LANGUAGES = [ { key: 'system', label: 'System 🌐', }, { key: 'vi', label: 'Tiếng Việt 🇻🇳', }, { key: 'zh-Hans', label: '简体中文 🇨🇳', }, { key: 'zh-Hant', label: '繁體中文 🇹🇼', }, { key: 'ja', label: '日本語 🇯🇵', }, { key: 'ko', label: '한국어 🇰🇷', }, { key: 'en', label: 'English 🇺🇸', }, { key: 'ru', label: 'Русский 🇷🇺', }, { key: 'de', label: 'Deutsch 🇩🇪', }, { key: 'fr', label: 'Français 🇫🇷', }, { key: 'ar', label: 'العربية 🇸🇦', }, ...(IS_IOS ? [ { key: 'th', label: 'ไทย 🇹🇭', }, { key: 'id', label: 'Bahasa Indonesia 🇮🇩', }, ] : []), ] ================================================ FILE: example/src/components/BottomSheet.tsx ================================================ import React from 'react' import { View } from 'react-native' export function BottomSheet() { return ( ) } ================================================ FILE: example/src/components/Button.tsx ================================================ import React from 'react' import { StyleSheet, TouchableOpacity, TouchableOpacityProps, } from 'react-native' import useTheme from '../hook/useTheme' import { Text } from './Text' interface Props extends TouchableOpacityProps { children: React.ReactNode | string type?: 'full' | 'outline' } export function Button({ children, style: containerStyle, onPress, type = 'full', }: Props) { const { foreground, background } = useTheme() const isFull = type === 'full' return ( {typeof children === 'string' ? ( {children} ) : ( children )} ) } const style = StyleSheet.create({ button: { padding: 12, alignItems: 'center', borderWidth: 1.5, }, text: { fontFamily: 'Avenir', fontWeight: 'bold', }, }) ================================================ FILE: example/src/components/CheckBox.tsx ================================================ import React from 'react' import { Image, StyleSheet, TouchableOpacity, TouchableOpacityProps, } from 'react-native' import images from '../assets' import useTheme from '../hook/useTheme' interface CheckBoxProps extends TouchableOpacityProps { checked?: boolean onChecked?: (checked: boolean) => void } export function CheckBox({ checked = false, onChecked, ...props }: CheckBoxProps) { const { foreground, background_2 } = useTheme() return ( onChecked?.(!checked)} {...props} style={[ style.container, props.style, { backgroundColor: checked ? foreground : background_2, borderColor: foreground + '64', }, ]} > {checked && ( )} ) } const style = StyleSheet.create({ container: { width: 24, height: 24, alignItems: 'center', justifyContent: 'center', borderRadius: 4, }, check: { width: 16, height: 16, }, }) ================================================ FILE: example/src/components/CodeTag.tsx ================================================ import React from 'react' import { View } from './View' import { StyleSheet, TextProps, ViewProps } from 'react-native' import { Text } from './Text' interface CodeTagProps extends ViewProps { children: string textProps?: TextProps } export function CodeTag({ children, textProps, ...props }: CodeTagProps) { return ( {children} ) } const style = StyleSheet.create({ text: { // fontFamily: 'monospace', fontWeight: 600, fontSize: 16, }, container: { padding: 8, paddingVertical: 6, borderRadius: 4, alignSelf: 'baseline', }, }) ================================================ FILE: example/src/components/Container.tsx ================================================ import React from 'react' import { StyleSheet, ViewProps } from 'react-native' import useTheme from '../hook/useTheme' import { View } from './View' interface Props extends ViewProps { level?: 0 | 1 | 2 | 3 } export function Container({ children, style: containerStyle, level = 0, }: Props) { const theme = useTheme() const backgroundColor = !level ? theme.background : theme[`background_${level}` as keyof typeof theme] return ( {children} ) } const style = StyleSheet.create({ container: { flex: 1, }, }) ================================================ FILE: example/src/components/CounterView.tsx ================================================ import React from 'react' import { View } from './View' import { Row, RowProps } from './Row' import { StyleSheet, TouchableOpacity } from 'react-native' import { Text } from './Text' import useTheme from '../hook/useTheme' interface CounterViewProps extends RowProps { value?: number onChange: (value: number) => void range?: { min?: number max?: number } } export function CounterView({ value = 0, onChange, range, ...props }: CounterViewProps) { const { background_2 } = useTheme() return ( { const min = range?.min ?? 0 onChange(value - 1 < min ? min : value - 1) }} > {value} { const max = range?.max if (max) onChange(value + 1 > max ? max : value + 1) else onChange(value + 1) }} > + ) } const style = StyleSheet.create({ counterView: { // height: 32, paddingHorizontal: 12, borderRadius: 4, alignItems: 'center', justifyContent: 'center', }, button: { borderRadius: 4, height: 32, width: 32, alignItems: 'center', justifyContent: 'center', }, buttonText: { fontSize: 16, fontWeight: 'bold', fontFamily: 'Avenir', }, }) ================================================ FILE: example/src/components/Divider.tsx ================================================ import React from 'react' import { StyleSheet } from 'react-native' import useTheme from '../hook/useTheme' import { View } from './View' export default function Divider() { const { foreground } = useTheme() return } const style = StyleSheet.create({ container: { height: 1, width: '100%', opacity: 0.2, }, }) ================================================ FILE: example/src/components/Input.tsx ================================================ import React from 'react' import { StyleSheet, TextInput, TextInputProps } from 'react-native' import useTheme from '../hook/useTheme' interface InputProps extends TextInputProps {} export function Input({ ...props }: InputProps) { const { background_2, foreground } = useTheme() return ( ) } const style = StyleSheet.create({ input: { paddingHorizontal: 12, paddingVertical: 12, borderRadius: 8, fontSize: 16, }, }) ================================================ FILE: example/src/components/Row.tsx ================================================ import React from 'react' import { StyleSheet, ViewStyle } from 'react-native' import { View, ViewProps } from './View' export interface RowProps extends ViewProps { alignItems?: ViewStyle['alignItems'] gap?: number } export function Row({ children, gap, alignItems = 'center', ...props }: RowProps) { return ( {children} ) } const style = StyleSheet.create({ container: { flexDirection: 'row', }, }) ================================================ FILE: example/src/components/SectionView.tsx ================================================ import React from 'react' import { Row } from './Row' import { CodeTag } from './CodeTag' import { View } from './View' import { Text } from './Text' import { StyleSheet, Switch } from 'react-native' import { useAppContext } from '../hook/context' import { Config } from '@baronha/react-native-multiple-image-picker' import { SegmentControl } from './SegmentControl' type key = keyof Config interface SectionViewProps { title: key description: string optionKey?: key children?: React.ReactNode defaultValue?: boolean segmentControl?: string[] } export default function SectionView({ title, description, optionKey, children, defaultValue = false, segmentControl, }: SectionViewProps) { const { options, setOptions } = useAppContext() return ( {title} {description} {children || (optionKey ? ( !segmentControl ? ( setOptions(optionKey, valueChange) } /> ) : null ) : null)} {segmentControl && optionKey ? ( setOptions(optionKey, valueChange)} /> ) : null} ) } const style = StyleSheet.create({ section: { rowGap: 12, columnGap: 24, }, sectionTitle: { gap: 8, }, des: { fontSize: 12, // marginBottom: 12, }, }) ================================================ FILE: example/src/components/SegmentControl.tsx ================================================ import React from 'react' import SegmentedControl, { SegmentedControlProps, } from '@react-native-segmented-control/segmented-control' export function SegmentControl({ ...props }: SegmentedControlProps) { return } ================================================ FILE: example/src/components/Text.tsx ================================================ import React from 'react' import { Text as RNText, TextProps } from 'react-native' import useTheme from '../hook/useTheme' export function Text({ children, style: containerStyle }: TextProps) { const { foreground } = useTheme() return ( {children} ) } ================================================ FILE: example/src/components/View.tsx ================================================ import React from 'react' import { View as RNView, ViewProps as RNViewProps } from 'react-native' import useTheme from '../hook/useTheme' export interface ViewProps extends RNViewProps { level?: 0 | 1 | 2 | 3 flex?: number } export function View({ children, style: containerStyle, level = 0, flex, }: ViewProps) { const theme = useTheme() const backgroundColor = !level ? theme.background : theme[`background_${level}` as keyof typeof theme] return ( {children} ) } ================================================ FILE: example/src/components/index.tsx ================================================ export * from './Container' export * from './Button' export * from './SegmentControl' export * from './Text' export * from './View' export * from './CodeTag' export * from './Row' export * from './Divider' export * from './CheckBox' export * from './SectionView' export * from './Input' export * from './CounterView' ================================================ FILE: example/src/hook/context.ts ================================================ import { createContext, useContext } from 'react' import { Config, defaultOptions, } from '@baronha/react-native-multiple-image-picker' export const AppContext = createContext<{ options: Config setOptions: (key: keyof Config, value: Config[keyof Config]) => void }>({ options: defaultOptions, setOptions: () => {}, }) export const useAppContext = () => useContext(AppContext) ================================================ FILE: example/src/hook/index.ts ================================================ export * from './useTheme' ================================================ FILE: example/src/hook/useTheme.ts ================================================ import { useColorScheme } from 'react-native' import * as color from '../theme/color' export default function useTheme() { const colorScheme = useColorScheme() as keyof typeof color return color[colorScheme] } ================================================ FILE: example/src/index.tsx ================================================ import React, { useCallback, useMemo, useState } from 'react' import { ActionSheetIOS, Alert, Appearance, ColorSchemeName, Image, KeyboardAvoidingView, LayoutAnimation, Platform, SafeAreaView, ScrollView, Switch, TouchableOpacity, useColorScheme, } from 'react-native' import { StyleSheet } from 'react-native' import { openPicker, PickerResult, defaultOptions, Config, openCropper, openPreview, openCamera, } from '@baronha/react-native-multiple-image-picker' import { useImmer } from 'use-immer' import { StatusBar } from 'expo-status-bar' import { Button, CodeTag, Container, CounterView, Input, Row, SegmentControl, Text, View, } from './components' import useTheme from './hook/useTheme' import assets from './assets' import { WIDTH } from './theme/size' import { IS_IOS, LOCALIZED_LANGUAGES } from './common/const' import { AppContext } from './hook/context' import SectionView from './components/SectionView' const layoutEffect = () => { LayoutAnimation.configureNext({ duration: 350, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, }, }) } const parseNumber = (value: string): number | undefined => { const parsed = Number(value) return value === '' || Number.isNaN(parsed) ? undefined : parsed } export default function App() { const { background, foreground } = useTheme() const [images, setImages] = useState([]) const [options, changeOptions] = useImmer(defaultOptions) const colorScheme = useColorScheme() const setOptions = (key: keyof Config, value: Config[keyof Config]) => { changeOptions((draft) => { draft[key] = value as any }) } console.log('images: ', images) const onPressImage = useCallback( (_: PickerResult, index: number) => { openPreview(images, index, { onLongPress: () => { if (Platform.OS === 'ios') { ActionSheetIOS.showActionSheetWithOptions( { options: ['Download', 'Cancel'], cancelButtonIndex: 1, userInterfaceStyle: colorScheme ?? 'light', }, (buttonIndex) => { if (buttonIndex === 0) { // Download } else if (buttonIndex === 1) { // Cancel } } ) } else { Alert.alert('Options', '', [ { text: 'Cancel', style: 'cancel', onPress: () => { console.log('Cancel') }, }, { text: 'Download', onPress: () => { console.log('Download') }, }, ]) } }, }) }, [images, colorScheme] ) const onPicker = async () => { try { const response = await openPicker({ ...options, selectedAssets: images.filter((item) => item.localIdentifier), }) setImages(Array.isArray(response) ? response : [response]) layoutEffect() } catch (e) { console.log('e: ', e) } } const onCamera = async () => { try { const response = await openCamera() setImages((prev) => { return [response as PickerResult, ...prev] }) layoutEffect() } catch (e) { console.log('e: ', e) } } const onCrop = async () => { try { const response = await openCropper(images[0].path, { ratio: [ { title: 'Instagram', width: 1, height: 1 }, { title: 'Twitter', width: 16, height: 9 }, { title: 'Facebook', width: 12, height: 11 }, ], }) setImages((prev) => { const data = [...prev] data[0].path = response.path data[0].width = response.width data[0].height = response.height return data }) layoutEffect() } catch (e) { console.log('e: ', e) } } const onRemovePhoto = useCallback( (_: PickerResult, index: number) => { const data = [...images].filter((__, idx) => idx !== index) setImages(data) }, [images, setImages] ) const onChangeTheme = (value: string) => { Appearance.setColorScheme(value as ColorSchemeName) } const renderImage = useMemo(() => { return ( {images.map((image, index) => ( onPressImage(image, index)} style={style.image} > onRemovePhoto(image, index)} > ))} ) }, [images, onPressImage, onRemovePhoto]) return ( {Platform.OS === 'android' && ( )} Multiple Image Picker BY BAOHA {images.length > 0 ? ( <> {renderImage} ) : ( )} Config {/* mediaType */} setOptions('mediaType', value)} /> {/* theme */} {/* selectMode */} setOptions('selectMode', value)} /> {/* selectBoxStyle */} {/* presentation */} {IS_IOS ? ( ) : null} Camera 📸 setOptions('camera', value ? {} : undefined) } /> {/* camera videoMaximumDuration */} { setOptions('camera', { ...(options.camera ?? { cameraDevice: 'back' }), videoMaximumDuration: parseNumber(value), }) }} /> {IS_IOS ? ( <> {/* allowedLimit */} ) : null} {/* allowSwipeToSelect */} {/* isHiddenOriginalButton */} {/* maxSelect */} setOptions('maxSelect', value)} /> {/* maxVideo */} setOptions('maxVideo', value)} /> {/* numberOfColumn */} setOptions('numberOfColumn', value)} /> {/* spacing */} setOptions('spacing', value)} /> {/* Filter data 🎞️ */} Filter data 🎞️ {/* maxVideoDuration */} { setOptions('maxVideoDuration', parseNumber(value)) }} /> {/* minVideoDuration */} { setOptions('minVideoDuration', parseNumber(value)) }} /> {/* maxFileSize */} { setOptions('maxFileSize', parseNumber(value)) }} /> Crop 🌠 setOptions('crop', value ? true : undefined) } /> setOptions( 'crop', value ? { circle: true } : { circle: false } ) } /> {/* Preview */} Preview 🌠 {/* isPreview */} {/* isShowPreviewList */} {/* isHiddenPreviewButton */} {/* allowHapticTouchPreview */} {IS_IOS ? ( ) : null} Localization 🌐 {( [ 'finish', 'preview', 'original', 'edit', ] as (keyof Config['text'])[] ).map((key) => ( { const object = { ...options.text, [key]: value, } Object.entries(object).forEach(([textKey, textValue]) => { if (textValue === '' || !textValue) delete object[textKey as keyof Config['text']] }) setOptions( 'text', Object.entries(object).length > 0 ? object : undefined ) }} /> ))} {LOCALIZED_LANGUAGES.map(({ key, label }) => { const onPress = () => { setOptions('language', key) } const active = options.language === key return ( {label} ) })} ) } const numberOfColumn = 3 const style = StyleSheet.create({ titleView: { padding: 16, flexDirection: 'row', gap: 12, }, mip: { // flex: 1, }, textView: { alignItems: 'flex-start', flex: 1, height: 48, gap: 4, }, title: { fontWeight: 900, fontSize: 20, fontFamily: 'Avenir', textTransform: 'uppercase', paddingTop: 12, marginBottom: -12, }, buttonOpen: { margin: 16, }, scrollView: { gap: 12, paddingTop: 12, paddingBottom: 24, }, content: { flexDirection: 'column', gap: 32, padding: 16, }, logo: { aspectRatio: 1, objectFit: 'cover', height: 48, width: 48, }, buttonPlus: { alignItems: 'center', justifyContent: 'center', padding: 48, marginHorizontal: 16, // backgroundColor: '#D4D4D432', borderStyle: 'dashed', borderWidth: 2, borderColor: '#D4D4D492', borderRadius: 8, }, plusSign: { width: 16, height: 16, }, section: { rowGap: 12, columnGap: 24, }, sectionTitle: { gap: 8, }, des: { fontSize: 12, }, keyboardAvoidingView: { flex: 1, }, language: { flexWrap: 'wrap', rowGap: 12, columnGap: 12, }, languageItem: { paddingHorizontal: 12, paddingVertical: 8, borderRadius: 6, borderWidth: 1, }, bottom: { padding: 16, paddingHorizontal: 24, }, openPicker: { flex: 1, }, imageContainer: { flexDirection: 'row', flexWrap: 'wrap', gap: 6, paddingHorizontal: 6, }, image: { width: (WIDTH - 24) / numberOfColumn, height: (WIDTH - 24) / numberOfColumn, }, removeButton: { position: 'absolute', top: 6, right: 6, backgroundColor: 'rgba(0, 0, 0, 0.9)', borderRadius: 100, padding: 6, }, trash: { width: 16, height: 16, transform: [{ rotate: '45deg' }], }, }) ================================================ FILE: example/src/theme/color.ts ================================================ export const light = { background: '#ffffff', foreground: '#000000', primary: '#000000', // background level background_1: '#f0f0f0', background_2: '#f3f3f3', background_3: '#f5f5f5', } export const dark = { background: '#000000', foreground: '#ffffff', primary: '#ffffff', // background level background_1: '#101010', background_2: '#202020', background_3: '#303030', } export const colors = { ...light, divider: '#D4D4D499', } ================================================ FILE: example/src/theme/size.ts ================================================ import { Dimensions } from 'react-native' export const { width: WIDTH, height: HEIGHT } = Dimensions.get('window') export const HALF_HEIGHT = HEIGHT / 2 export const HALF_WIDTH = WIDTH / 2 ================================================ FILE: example/tsconfig.json ================================================ { "compilerOptions": { "outDir": "./lib" }, "extends": "../tsconfig" } ================================================ FILE: ios/Assets.swift ================================================ // // Assets.swift // Pods // // Created by BAO HA on 4/12/24. // import UIKit class Assets { class func bundle() -> Bundle { let podBundle = Bundle(for: Assets.self) if let url = podBundle.url(forResource: "MultipleImagePicker", withExtension: "bundle") { let bundle = Bundle(url: url) return bundle ?? podBundle } return podBundle } } extension UIImage { static var close = UIImage(name: "close") convenience init(name: String) { self.init(named: name, in: Assets.bundle(), compatibleWith: nil)! } } ================================================ FILE: ios/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: ios/Assets.xcassets/close.imageset/Contents.json ================================================ { "images" : [ { "filename" : "close.png", "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "author" : "xcode", "version" : 1 } } ================================================ FILE: ios/ErrorCode.swift ================================================ // // ErrorCode.swift // Pods // // Created by BAO HA on 3/12/24. // // enum ErrorCode: Int, Error { // // } ================================================ FILE: ios/HybridMultipleImagePicker+Camera.swift ================================================ // // HybridMultipleImagePicker+Camera.swift // Pods // // Created by BAO HA on 13/12/24. // import AVFoundation import HXPhotoPicker import Photos extension HybridMultipleImagePicker { func openCamera(config: NitroCameraConfig, resolved: @escaping ((CameraResult) -> Void), rejected: @escaping ((Double) -> Void)) throws { var captureType: CameraController.CaptureType = .all // check media type switch config.mediaType { case .image: captureType = .photo case .video: captureType = .video default: break } // config var cameraConfig = CameraConfiguration() cameraConfig.videoMaximumDuration = config.videoMaximumDuration ?? 60 cameraConfig.modalPresentationStyle = self.setPresentation(config.presentation) cameraConfig.editor.modalPresentationStyle = .fullScreen if let crop = config.crop { let editor = PickerCropConfig(circle: crop.circle, ratio: crop.ratio, defaultRatio: crop.defaultRatio, freeStyle: crop.freeStyle) cameraConfig.editor = setCropConfig(editor) } else { cameraConfig.allowsEditing = false } cameraConfig.languageType = setLocale(language: config.language) cameraConfig.isSaveSystemAlbum = config.isSaveSystemAlbum ?? false cameraConfig.sessionPreset = .hd4K3840x2160 cameraConfig.aspectRatio = .fullScreen if let color = config.color, let focusColor = getReactColor(Int(color)) { cameraConfig.focusColor = focusColor } switch Int(config.cameraDevice?.rawValue ?? 1) { case 0: cameraConfig.position = .front default: cameraConfig.position = .back } func getCameraResult(_ result: CameraController.Result, _ asset: PHAsset?) { if let asset { Task { let photoAsset = PhotoAsset(asset) let urlResult = try await photoAsset.urlResult() let path = urlResult.url.absoluteString let phAsset = photoAsset.phAsset let thumbnail = phAsset?.getVideoAssetThumbnail(from: path, in: 1) resolved(CameraResult(path: path, type: photoAsset.mediaType == .photo ? ResultType.image : ResultType.video, width: photoAsset.imageSize.width, height: photoAsset.imageSize.height, duration: photoAsset.videoDuration, thumbnail: thumbnail, fileName: phAsset?.fileName)) } } else { switch result { case .image(let uiImage): let fileName = "IMG_\(Int(Date().timeIntervalSince1970)).jpg" let filePath = uiImage.getPath(fileName: fileName, quality: 1.0) if let filePath { resolved(CameraResult(path: filePath, type: ResultType.image, width: uiImage.size.width, height: uiImage.size.height, duration: nil, thumbnail: nil, fileName: fileName)) } else { rejected(1) } case .video(let url): let asset = AVAsset(url: url) let thumbnail = getVideoThumbnail(from: url.absoluteString, in: 1) var result = CameraResult(path: "file://\(url.absoluteString)", type: ResultType.video, width: nil, height: nil, duration: asset.duration.seconds, thumbnail: thumbnail, fileName: url.lastPathComponent) if let track = asset.tracks(withMediaType: AVMediaType.video).first { let trackSize = track.naturalSize.applying(track.preferredTransform) let size = CGSize(width: abs(trackSize.width), height: abs(trackSize.height)) result.width = Double(size.width) result.height = Double(size.height) } resolved(result) } } } DispatchQueue.main.async { Photo.capture(cameraConfig, type: captureType) { result, asset, _ in getCameraResult(result, asset) } } } func setCameraConfig(_ options: PickerCameraConfig) -> SystemCameraConfiguration { var config = SystemCameraConfiguration() config.editExportPreset = .highQuality config.videoQuality = .typeHigh switch Int(options.cameraDevice?.rawValue ?? 1) { case 0: config.cameraDevice = .front default: config.cameraDevice = .rear } config.videoMaximumDuration = options.videoMaximumDuration ?? 60 return config } } ================================================ FILE: ios/HybridMultipleImagePicker+Config.swift ================================================ // // HybridMultipleImagePicker+Config.swift // react-native-multiple-image-picker // // Created by BAO HA on 15/10/2024. // import HXPhotoPicker import UIKit // Swift enum // @objc enum MediaType: SelectBoxView.Style extension HybridMultipleImagePicker { func setConfig(_ options: NitroConfig) { config = PickerConfiguration.default var photoList = config.photoList var previewView = config.previewView if let spacing = options.spacing { photoList.spacing = spacing } if let rowNumber = options.numberOfColumn { photoList.rowNumber = Int(rowNumber) } if let isHiddenPreviewButton = options.isHiddenPreviewButton { previewView.bottomView.isHiddenPreviewButton = isHiddenPreviewButton photoList.bottomView.isHiddenOriginalButton = isHiddenPreviewButton } if let isHiddenOriginalButton = options.isHiddenOriginalButton { previewView.bottomView.isHiddenOriginalButton = isHiddenOriginalButton photoList.bottomView.isHiddenOriginalButton = isHiddenOriginalButton } photoList.allowHapticTouchPreview = options.allowHapticTouchPreview ?? true photoList.allowSwipeToSelect = options.allowSwipeToSelect ?? true photoList.allowAddLimit = options.allowedLimit ?? true // check media type switch options.mediaType { case .image: config.selectOptions = [.photo, .livePhoto, .gifPhoto] case .video: config.selectOptions = .video default: 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 } photoList.isShowFilterItem = false photoList.sort = .desc photoList.isShowAssetNumber = false previewView.disableFinishButtonWhenNotSelected = false if let selectMode = PickerSelectMode(rawValue: Int(options.selectMode.rawValue)) { config.selectMode = selectMode } if let maxFileSize = options.maxFileSize { config.maximumSelectedPhotoFileSize = Int(maxFileSize) config.maximumSelectedVideoFileSize = Int(maxFileSize) } // Setting for video if options.mediaType == .all || options.mediaType == .video { if let maxVideo = options.maxVideo { config.maximumSelectedVideoCount = Int(maxVideo) } if let maxVideoDuration = options.maxVideoDuration { config.maximumSelectedVideoDuration = Int(maxVideoDuration) } if let minVideoDuration = options.minVideoDuration { config.minimumSelectedVideoDuration = Int(minVideoDuration) } } if let maxSelect = options.maxSelect { config.maximumSelectedCount = Int(maxSelect) } config.allowSyncICloudWhenSelectPhoto = true config.allowCustomTransitionAnimation = true config.isSelectedOriginal = false let isPreview = options.isPreview ?? true previewView.bottomView.isShowPreviewList = isPreview photoList.bottomView.isHiddenPreviewButton = !isPreview photoList.allowHapticTouchPreview = isPreview photoList.bottomView.previewListTickColor = .clear photoList.bottomView.isShowSelectedView = isPreview if isPreview { config.videoSelectionTapAction = .preview config.photoSelectionTapAction = .preview } else { config.videoSelectionTapAction = .quickSelect config.photoSelectionTapAction = .quickSelect } config.editorOptions = [.photo, .gifPhoto, .livePhoto] if let crop = options.crop { config.editor = setCropConfig(crop) } else { previewView.bottomView.isHiddenEditButton = true } photoList.finishSelectionAfterTakingPhoto = true if let cameraOption = options.camera { photoList.allowAddCamera = true photoList.cameraType = .system(setCameraConfig(cameraOption)) } else { photoList.allowAddCamera = false } config.photoList = photoList config.previewView = previewView setLanguage(options) setTheme(options) config.modalPresentationStyle = setPresentation(options.presentation) } private func setTheme(_ options: NitroConfig) { let isDark = options.theme == Theme.dark // custom background dark if let background = options.backgroundDark, let backgroundDark = getReactColor(Int(background)), isDark { config.photoList.backgroundDarkColor = backgroundDark config.photoList.backgroundColor = backgroundDark } // LIGHT THEME if !isDark { let background = UIColor.white let barStyle = UIBarStyle.default config.statusBarStyle = .darkContent config.appearanceStyle = .normal config.photoList.bottomView.barStyle = barStyle config.navigationBarStyle = barStyle config.previewView.bottomView.barStyle = barStyle config.previewView.backgroundColor = background config.previewView.bottomView.backgroundColor = background config.photoList.leftNavigationItems = [PhotoCancelItem.self] config.photoList.backgroundColor = .white config.photoList.emptyView.titleColor = .black config.photoList.emptyView.subTitleColor = .darkGray config.photoList.titleView.backgroundColor = UIColor.black.withAlphaComponent(0.5) config.albumList.backgroundColor = .white config.albumList.cellBackgroundColor = .white config.albumList.albumNameColor = .black config.albumList.photoCountColor = .black config.albumList.cellSelectedColor = "#e1e1e1".hx.color config.albumList.separatorLineColor = "#e1e1e1".hx.color } if let primaryColor = options.primaryColor, let color = getReactColor(Int(primaryColor)) { config.setThemeColor(color) } config.navigationTitleColor = .white config.photoList.titleView.arrow.arrowColor = .white config.photoList.cell.customSelectableCellClass = nil } func setPresentation(_ presentation: Presentation?) -> UIModalPresentationStyle { if let presentation { switch Int(presentation.rawValue) { case 1: return .formSheet default: return .fullScreen } } return .fullScreen } private func setLanguage(_ options: NitroConfig) { if let text = options.text { if let finish = text.finish { config.textManager.picker.photoList.bottomView.finishTitle = .custom(finish) config.textManager.picker.preview.bottomView.finishTitle = .custom(finish) config.textManager.editor.crop.maskListFinishTitle = .custom(finish) } if let original = text.original { config.textManager.picker.photoList.bottomView.originalTitle = .custom(original) config.textManager.picker.preview.bottomView.originalTitle = .custom(original) } if let preview = text.preview { config.textManager.picker.photoList.bottomView.previewTitle = .custom(preview) } if let edit = text.edit { config.textManager.picker.preview.bottomView.editTitle = .custom(edit) } } config.languageType = setLocale(language: options.language) } func setLocale(language: Language) -> LanguageType { switch language { case .vi: return .vietnamese // -> 🇻🇳 My country. Yeahhh case .zhHans: return .simplifiedChinese case .zhHant: return .traditionalChinese case .ja: return .japanese case .ko: return .korean case .en: return .english case .th: return .thai case .id: return .indonesia case .ru: return .russian case .de: return .german case .fr: return .french case .ar: return .arabic default: return .system } } } ================================================ FILE: ios/HybridMultipleImagePicker+Crop.swift ================================================ // // HybridMultipleImagePicker+Crop.swift // Pods // // Created by BAO HA on 9/12/24. // import HXPhotoPicker extension HybridMultipleImagePicker { func openCrop(image: String, config: NitroCropConfig, resolved: @escaping ((CropResult) -> Void), rejected: @escaping ((Double) -> Void)) throws { let asset: EditorAsset if image.hasPrefix("http://") || image.hasPrefix("https://") || image.hasPrefix("file://") { guard let url = URL(string: image), let data = try? Data(contentsOf: url) else { rejected(0) return } asset = .init(type: .imageData(data)) } else { asset = .init(type: .photoAsset(.init(localIdentifier: image))) } let cropOption = PickerCropConfig(circle: config.circle, ratio: config.ratio, defaultRatio: config.defaultRatio, freeStyle: config.freeStyle) var editConfig = setCropConfig(cropOption) editConfig.languageType = setLocale(language: config.language) DispatchQueue.main.async { Photo.edit(asset: asset, config: editConfig) { result, _ in if let path = result.result?.url.absoluteString, let size = result.result?.image?.size { let result = CropResult(path: path, width: size.width, height: size.height) resolved(result) } } } } func setCropConfig(_ cropConfig: PickerCropConfig) -> EditorConfiguration { var config = EditorConfiguration() if let defaultRatio = cropConfig.defaultRatio { config.cropSize.aspectRatio = .init(width: defaultRatio.width, height: defaultRatio.height) } config.photo.defaultSelectedToolOption = .cropSize config.isFixedCropSizeState = true config.cropSize.defaultSeletedIndex = 0 let freeStyle = cropConfig.freeStyle ?? true config.cropSize.isFixedRatio = !freeStyle config.isWhetherFinishButtonDisabledInUneditedState = true config.cropSize.isRoundCrop = cropConfig.circle ?? false config.cropSize.isResetToOriginal = true config.toolsView = .init(toolOptions: [.init(imageType: PickerConfiguration.default.editor.imageResource.editor.tools.cropSize, type: .cropSize)]) config.photo.defaultSelectedToolOption = .cropSize if config.cropSize.isRoundCrop { config.cropSize.aspectRatios = [] } else { var aspectRatios: [EditorRatioToolConfig] = PickerConfiguration.default.editor.cropSize.aspectRatios let ratio = cropConfig.ratio // custom ratio if ratio.count > 0 { ratio.forEach { ratio in let width = Int(ratio.width) let height = Int(ratio.height) aspectRatios.insert(.init(title: .custom(ratio.title ?? "\(width)/\(height)"), ratio: .init(width: width, height: height)), at: 3) } } config.cropSize.aspectRatios = freeStyle ? aspectRatios : aspectRatios.filter { // check freeStyle crop if $0.ratio == .zero { return false } return true } } return config } } ================================================ FILE: ios/HybridMultipleImagePicker+Preview.swift ================================================ // // HybridMultipleImagePicker+Preview.swift // Pods // // Created by BAO HA on 11/12/24. // import HXPhotoPicker extension HybridMultipleImagePicker { func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig, onLongPress: @escaping ((Double) -> Void)) throws { var previewConfig = HXPhotoPicker.PhotoBrowser.Configuration() previewConfig.showDelete = false var assets: [PhotoAsset] = [] previewConfig.tintColor = .white previewConfig.videoPlayType = config.videoAutoPlay == true ? .auto : .normal previewConfig.livePhotoPlayType = .auto previewConfig.languageType = setLocale(language: config.language) media.forEach { mediaItem in var asset: PhotoAsset? if let localIdentifier = mediaItem.localIdentifier { asset = .init(localIdentifier: localIdentifier) // auto play gif if let filePath = mediaItem.path, let url = URL(string: filePath), isGifFile(url) == true { asset = .init(.init(imageURL: url)) } } else if let path = mediaItem.path, let url = URL(string: path) { let thumbnail = URL(string: mediaItem.thumbnail ?? "") ?? url if mediaItem.type == .image { // network asset if path.hasPrefix("https://") || path.hasPrefix("http://") { asset = PhotoAsset(NetworkImageAsset( thumbnailURL: thumbnail, originalURL: url, thumbnailLoadMode: .alwaysThumbnail, originalLoadMode: .alwaysThumbnail )) } else { asset = .init(.init(imageURL: url)) } } else { asset = .init(networkVideoAsset: .init(videoURL: url, coverImageURL: thumbnail)) } } if let asset { assets.append(asset) } } if Int(index) > assets.count - 1 { return } DispatchQueue.main.async { HXPhotoPicker.PhotoBrowser.show( assets, pageIndex: Int(index), config: previewConfig, longPressHandler: { index, _, _ in onLongPress(Double(index)) } ) } } } ================================================ FILE: ios/HybridMultipleImagePicker+Result.swift ================================================ // // HybridMultipleImagePicker+Result.swift // Pods // // Created by BAO HA on 24/10/24. // import HXPhotoPicker extension HybridMultipleImagePicker { func getResult(_ asset: PhotoAsset) async throws -> PickerResult { let urlResult = try await asset.urlResult() let url = urlResult.url let creationDate = Int(asset.phAsset?.creationDate?.timeIntervalSince1970 ?? 0) let mime = url.getMimeType() let phAsset = asset.phAsset let type: ResultType = .init(fromString: asset.mediaType == .video ? "video" : "image")! let thumbnail = asset.phAsset?.getVideoAssetThumbnail(from: url.absoluteString, in: 1) return PickerResult(localIdentifier: phAsset!.localIdentifier, width: asset.imageSize.width, height: asset.imageSize.height, mime: mime, size: Double(asset.fileSize), bucketId: nil, realPath: nil, parentFolderName: nil, creationDate: creationDate > 0 ? Double(creationDate) : nil, crop: false, path: "file://\(url.absoluteString)", type: type, duration: asset.videoDuration, thumbnail: thumbnail, fileName: phAsset?.fileName) } } ================================================ FILE: ios/HybridMultipleImagePicker.swift ================================================ // // HybridMultipleImagePicker.swift // // Created by Marc Rousavy on 18.07.24. // import Foundation import HXPhotoPicker import NitroModules import Photos class HybridMultipleImagePicker: HybridMultipleImagePickerSpec { var selectedAssets: [PhotoAsset] = .init() var config: PickerConfiguration = .init() func openPicker(config: NitroConfig, resolved: @escaping (([PickerResult]) -> Void), rejected: @escaping ((Double) -> Void)) throws { setConfig(config) // get selected photo selectedAssets = selectedAssets.filter { asset in config.selectedAssets.contains { $0.localIdentifier == asset.phAsset?.localIdentifier } } DispatchQueue.main.async { Photo.picker( self.config, selectedAssets: self.selectedAssets ) { pickerResult, controller in controller.autoDismiss = false // check crop for single if let asset = pickerResult.photoAssets.first, config.selectMode == .single, config.crop != nil, asset.mediaType == .photo, asset.editedResult?.url == nil { // open crop Photo.edit(asset: .init(type: .photoAsset(asset)), config: self.config.editor, sender: controller) { editedResult, _ in if let photoAsset = pickerResult.photoAssets.first, let result = editedResult.result { photoAsset.editedResult = .some(result) Task { let resultData = try await self.getResult(photoAsset) DispatchQueue.main.async { resolved([resultData]) controller.dismiss(true) } } } } return } // show alert view let alert = UIAlertController(title: nil, message: "Loading...", preferredStyle: .alert) alert.showLoading() controller.present(alert, animated: true) let group = DispatchGroup() var data: [PickerResult] = [] self.selectedAssets = pickerResult.photoAssets Task { for response in pickerResult.photoAssets { group.enter() let resultData = try await self.getResult(response) data.append(resultData) group.leave() } DispatchQueue.main.async { alert.dismiss(animated: true) { controller.dismiss(true) resolved(data) } } } } cancel: { cancel in cancel.autoDismiss = true } } } } extension UIAlertController { func showLoading() { let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) loadingIndicator.hidesWhenStopped = true loadingIndicator.style = UIActivityIndicatorView.Style.medium if #available(iOS 13.0, *) { loadingIndicator.color = .secondaryLabel } else { loadingIndicator.color = .black } loadingIndicator.startAnimating() view.addSubview(loadingIndicator) } } ================================================ FILE: ios/MultipleImagePickerOnLoad.mm ================================================ // // MultipleImagePickerOnLoad.mm // MultipleImagePicker // // Created by Marc Rousavy on 22.07.24. // #import #import #import "React/RCTBridgeModule.h" @interface MultipleImagePickerOnLoad : NSObject @end @implementation MultipleImagePickerOnLoad using namespace margelo::nitro; + (void)load { // TODO: Register all Swift Hybrid Objects here // TODO: Register all C++ Hybrid Objects here } @end ================================================ FILE: ios/PHAsset+Thumbnail.swift ================================================ // // PHAsset+Thumbnail.swift // Pods // // Created by BAO HA on 24/10/24. // import Photos extension PHAsset { func getVideoAssetThumbnail(from moviePath: String, in seconds: Double) -> String? { if mediaType == .video { if let path = getVideoThumbnail(from: moviePath, in: seconds) { return "file://\(path)" } } return nil } var fileName: String { if let resources = PHAssetResource.assetResources(for: self).first { return resources.originalFilename } return "" } } func getVideoThumbnail(from moviePath: String, in seconds: Double) -> String? { let filepath = moviePath.replacingOccurrences(of: "file://", with: "") let vidURL = URL(fileURLWithPath: filepath) let asset = AVURLAsset(url: vidURL, options: nil) let generator = AVAssetImageGenerator(asset: asset) generator.appliesPreferredTrackTransform = true let time = CMTime(seconds: seconds, preferredTimescale: 600) var thumbnail: UIImage? do { let imgRef = try generator.copyCGImage(at: time, actualTime: nil) thumbnail = UIImage(cgImage: imgRef) } catch { print("Error create thumbnail: \(error)") return nil } if let thumbnail { return thumbnail.getPath(fileName: nil, quality: 0.8) } return nil } ================================================ FILE: ios/PhotoCancelItem.swift ================================================ // // PhotoCancelItem.swift // Pods // // Created by BAO HA on 4/12/24. // import HXPhotoPicker import UIKit extension UIView: HXPickerCompatible { var size: CGSize { get { frame.size } set { var rect = frame rect.size = newValue frame = rect } } } public class PhotoCancelItem: UIView, PhotoNavigationItem { public weak var itemDelegate: PhotoNavigationItemDelegate? public var itemType: PhotoNavigationItemType { .cancel } let config: PickerConfiguration public required init(config: PickerConfiguration) { self.config = config super.init(frame: .zero) initView() } var button: UIButton! func initView() { button = UIButton(type: .custom) button.setImage(UIImage.close, for: .normal) button.addTarget(self, action: #selector(didCancelClick), for: .touchUpInside) addSubview(button) if let btnSize = button.currentImage?.size { button.size = btnSize size = btnSize } } @objc func didCancelClick() { print("close ne") itemDelegate?.photoControllerDidCancel() } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } ================================================ FILE: ios/TopViewController.swift ================================================ // // TopViewController.swift // Pods // // Created by BAO HA on 11/12/24. // import UIKit func getTopViewController() -> UIViewController? { var controller = UIApplication.shared.keyWindow?.rootViewController while let presentedViewController = controller?.presentedViewController { controller = presentedViewController } return controller } ================================================ FILE: ios/UIColor+Hex.swift ================================================ // // UIColor+Hex.swift // react-native-multiple-image-picker // // Created by BAO HA on 15/10/2024. // import UIKit extension UIColor { convenience init(hex: String, alpha: CGFloat = 1.0) { var cString: String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() var rgbValue: UInt32 = 10066329 // color #999999 if string has wrong format if cString.hasPrefix("#") { cString.remove(at: cString.startIndex) } if (cString.count) == 6 { Scanner(string: cString).scanHexInt32(&rgbValue) } self.init( red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, blue: CGFloat(rgbValue & 0x0000FF) / 255.0, alpha: alpha ) } } ================================================ FILE: ios/UIColor+React.swift ================================================ // // UIColor+React.swift // Pods // // Created by BAO HA on 16/10/24. // import React import UIKit func getReactColor(_ color: Int?) -> UIColor? { RCTConvert.uiColor(color) } ================================================ FILE: ios/UIImage.swift ================================================ // // UIImage.swift // Pods // // Created by BAO HA on 16/12/24. // extension UIImage { func getPath(fileName name: String? = nil, quality: CGFloat = 1.0) -> String? { let tempDirectoryURL = FileManager.default.temporaryDirectory let data = self.jpegData(compressionQuality: 0.9) let fileName = name ?? "IMG_\(Int(Date().timeIntervalSince1970)).jpg" let fileURL = tempDirectoryURL.appendingPathComponent(fileName) if let imageData = self.jpegData(compressionQuality: quality) { do { try imageData.write(to: fileURL) return fileURL.absoluteString } catch { return nil } } return nil } } ================================================ FILE: ios/URL+Mime.swift ================================================ // // URL+Mime.swift // Pods // // Created by BAO HA on 23/10/24. // import Foundation import MobileCoreServices import UniformTypeIdentifiers extension URL { func getMimeType() -> String { let pathExtension = self.pathExtension.lowercased() if #available(iOS 14.0, *) { // Sử dụng UniformTypeIdentifiers (UTType) cho iOS 14+ if let utType = UTType(filenameExtension: pathExtension) { return utType.preferredMIMEType ?? "application/octet-stream" } } else { // Sử dụng MobileCoreServices (kUTType) cho iOS 13 trở xuống if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(), let mimeType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() { return mimeType as String } } // Trả về MIME type mặc định nếu không tìm thấy return "application/octet-stream" } } ================================================ FILE: ios/Utils.swift ================================================ // // Utils.swift // Pods // // Created by BAO HA on 11/12/24. // import MobileCoreServices import UniformTypeIdentifiers func isImage(_ urlString: String) -> Bool { guard let url = URL(string: urlString), let pathExtension = url.pathExtension as CFString?, let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil)? .takeRetainedValue() else { return false } return UTTypeConformsTo(uti, kUTTypeImage) } func isGifFile(_ url: URL) -> Bool { // Kiểm tra phần mở rộng if url.pathExtension.lowercased() == "gif" { return true } // Kiểm tra UTI let fileExtension = url.pathExtension as CFString guard let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, nil)?.takeRetainedValue() else { return false } return UTTypeConformsTo(uti, kUTTypeGIF) } ================================================ FILE: nitro.json ================================================ { "$schema": "https://nitro.margelo.com/nitro.schema.json", "cxxNamespace": ["multipleimagepicker"], "ios": { "iosModuleName": "MultipleImagePicker" }, "android": { "androidNamespace": ["multipleimagepicker"], "androidCxxLibName": "MultipleImagePicker" }, "autolinking": { "MultipleImagePicker": { "swift": "HybridMultipleImagePicker", "kotlin": "MultipleImagePicker" } }, "ignorePaths": ["node_modules"] } ================================================ FILE: nitrogen/generated/.gitattributes ================================================ * linguist-generated ================================================ FILE: nitrogen/generated/android/MultipleImagePicker+autolinking.cmake ================================================ # # MultipleImagePicker+autolinking.cmake # This file was generated by nitrogen. DO NOT MODIFY THIS FILE. # https://github.com/mrousavy/nitro # Copyright © 2025 Marc Rousavy @ Margelo # # This is a CMake file that adds all files generated by Nitrogen # to the current CMake project. # # To use it, add this to your CMakeLists.txt: # ```cmake # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/MultipleImagePicker+autolinking.cmake) # ``` # Add all headers that were generated by Nitrogen include_directories( "../nitrogen/generated/shared/c++" "../nitrogen/generated/android/c++" "../nitrogen/generated/android/" ) # Add all .cpp sources that were generated by Nitrogen target_sources( # CMake project name (Android C++ library name) MultipleImagePicker PRIVATE # Autolinking Setup ../nitrogen/generated/android/MultipleImagePickerOnLoad.cpp # Shared Nitrogen C++ sources ../nitrogen/generated/shared/c++/HybridMultipleImagePickerSpec.cpp # Android-specific Nitrogen C++ sources ../nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp ) # Define a flag to check if we are building properly add_definitions(-DBUILDING_MULTIPLEIMAGEPICKER_WITH_GENERATED_CMAKE_PROJECT) # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake # Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake target_compile_definitions( MultipleImagePicker PRIVATE -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -DFOLLY_MOBILE=1 -DFOLLY_HAVE_RECVMMSG=1 -DFOLLY_HAVE_PTHREAD=1 # Once we target android-23 above, we can comment # the following line. NDK uses GNU style stderror_r() after API 23. -DFOLLY_HAVE_XSI_STRERROR_R=1 ) # Add all libraries required by the generated specs find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++ find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule) find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library # Link all libraries together target_link_libraries( MultipleImagePicker fbjni::fbjni # <-- Facebook C++ JNI helpers ReactAndroid::jsi # <-- RN: JSI react-native-nitro-modules::NitroModules # <-- NitroModules Core :) ) # Link react-native (different prefab between RN 0.75 and RN 0.76) if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) target_link_libraries( MultipleImagePicker ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab ) else() target_link_libraries( MultipleImagePicker ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core ) endif() ================================================ FILE: nitrogen/generated/android/MultipleImagePicker+autolinking.gradle ================================================ /// /// MultipleImagePicker+autolinking.gradle /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /// This is a Gradle file that adds all files generated by Nitrogen /// to the current Gradle project. /// /// To use it, add this to your build.gradle: /// ```gradle /// apply from: '../nitrogen/generated/android/MultipleImagePicker+autolinking.gradle' /// ``` logger.warn("[NitroModules] 🔥 MultipleImagePicker is boosted by nitro!") android { sourceSets { main { java.srcDirs += [ // Nitrogen files "${project.projectDir}/../nitrogen/generated/android/kotlin" ] } } } ================================================ FILE: nitrogen/generated/android/MultipleImagePickerOnLoad.cpp ================================================ /// /// MultipleImagePickerOnLoad.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #ifndef BUILDING_MULTIPLEIMAGEPICKER_WITH_GENERATED_CMAKE_PROJECT #error MultipleImagePickerOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this? #endif #include "MultipleImagePickerOnLoad.hpp" #include #include #include #include "JHybridMultipleImagePickerSpec.hpp" #include "JFunc_void_std__vector_PickerResult_.hpp" #include "JFunc_void_double.hpp" #include "JFunc_void_CropResult.hpp" #include "JFunc_void_CameraResult.hpp" #include #include namespace margelo::nitro::multipleimagepicker { int initialize(JavaVM* vm) { using namespace margelo::nitro; using namespace margelo::nitro::multipleimagepicker; using namespace facebook; return facebook::jni::initialize(vm, [] { // Register native JNI methods margelo::nitro::multipleimagepicker::JHybridMultipleImagePickerSpec::registerNatives(); margelo::nitro::multipleimagepicker::JFunc_void_std__vector_PickerResult__cxx::registerNatives(); margelo::nitro::multipleimagepicker::JFunc_void_double_cxx::registerNatives(); margelo::nitro::multipleimagepicker::JFunc_void_CropResult_cxx::registerNatives(); margelo::nitro::multipleimagepicker::JFunc_void_CameraResult_cxx::registerNatives(); // Register Nitro Hybrid Objects HybridObjectRegistry::registerHybridObjectConstructor( "MultipleImagePicker", []() -> std::shared_ptr { static DefaultConstructableObject object("com/margelo/nitro/multipleimagepicker/MultipleImagePicker"); auto instance = object.create(); auto globalRef = jni::make_global(instance); return JNISharedPtr::make_shared_from_jni(globalRef); } ); }); } } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/MultipleImagePickerOnLoad.hpp ================================================ /// /// MultipleImagePickerOnLoad.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #include #include namespace margelo::nitro::multipleimagepicker { /** * Initializes the native (C++) part of MultipleImagePicker, and autolinks all Hybrid Objects. * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`). * Example: * ```cpp (cpp-adapter.cpp) * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { * return margelo::nitro::multipleimagepicker::initialize(vm); * } * ``` */ int initialize(JavaVM* vm); } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JCameraDevice.hpp ================================================ /// /// JCameraDevice.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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]] [[nodiscard]] 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 ================================================ FILE: nitrogen/generated/android/c++/JCameraResult.hpp ================================================ /// /// JCameraResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "CameraResult.hpp" #include "JResultType.hpp" #include "ResultType.hpp" #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "CameraResult" and the the Kotlin data class "CameraResult". */ struct JCameraResult final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/CameraResult;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct CameraResult by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] CameraResult toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldPath = clazz->getField("path"); jni::local_ref path = this->getFieldValue(fieldPath); static const auto fieldType = clazz->getField("type"); jni::local_ref type = this->getFieldValue(fieldType); static const auto fieldWidth = clazz->getField("width"); jni::local_ref width = this->getFieldValue(fieldWidth); static const auto fieldHeight = clazz->getField("height"); jni::local_ref height = this->getFieldValue(fieldHeight); static const auto fieldDuration = clazz->getField("duration"); jni::local_ref duration = this->getFieldValue(fieldDuration); static const auto fieldThumbnail = clazz->getField("thumbnail"); jni::local_ref thumbnail = this->getFieldValue(fieldThumbnail); static const auto fieldFileName = clazz->getField("fileName"); jni::local_ref fileName = this->getFieldValue(fieldFileName); return CameraResult( path->toStdString(), type->toCpp(), width != nullptr ? std::make_optional(width->value()) : std::nullopt, height != nullptr ? std::make_optional(height->value()) : std::nullopt, duration != nullptr ? std::make_optional(duration->value()) : std::nullopt, thumbnail != nullptr ? std::make_optional(thumbnail->toStdString()) : std::nullopt, fileName != nullptr ? std::make_optional(fileName->toStdString()) : 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 CameraResult& value) { return newInstance( jni::make_jstring(value.path), JResultType::fromCpp(value.type), value.width.has_value() ? jni::JDouble::valueOf(value.width.value()) : nullptr, value.height.has_value() ? jni::JDouble::valueOf(value.height.value()) : nullptr, value.duration.has_value() ? jni::JDouble::valueOf(value.duration.value()) : nullptr, value.thumbnail.has_value() ? jni::make_jstring(value.thumbnail.value()) : nullptr, value.fileName.has_value() ? jni::make_jstring(value.fileName.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JCropRatio.hpp ================================================ /// /// JCropRatio.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "CropRatio.hpp" #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "CropRatio" and the the Kotlin data class "CropRatio". */ struct JCropRatio final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/CropRatio;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct CropRatio by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] CropRatio toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldTitle = clazz->getField("title"); jni::local_ref title = this->getFieldValue(fieldTitle); static const auto fieldWidth = clazz->getField("width"); double width = this->getFieldValue(fieldWidth); static const auto fieldHeight = clazz->getField("height"); double height = this->getFieldValue(fieldHeight); return CropRatio( title != nullptr ? std::make_optional(title->toStdString()) : std::nullopt, width, height ); } 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 CropRatio& value) { return newInstance( value.title.has_value() ? jni::make_jstring(value.title.value()) : nullptr, value.width, value.height ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JCropResult.hpp ================================================ /// /// JCropResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "CropResult.hpp" #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "CropResult" and the the Kotlin data class "CropResult". */ struct JCropResult final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/CropResult;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct CropResult by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] CropResult toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldPath = clazz->getField("path"); jni::local_ref path = this->getFieldValue(fieldPath); static const auto fieldWidth = clazz->getField("width"); double width = this->getFieldValue(fieldWidth); static const auto fieldHeight = clazz->getField("height"); double height = this->getFieldValue(fieldHeight); return CropResult( path->toStdString(), width, height ); } 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 CropResult& value) { return newInstance( jni::make_jstring(value.path), value.width, value.height ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JFunc_void_CameraResult.hpp ================================================ /// /// JFunc_void_CameraResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include #include #include "CameraResult.hpp" #include "JCameraResult.hpp" #include #include "ResultType.hpp" #include "JResultType.hpp" #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * Represents the Java/Kotlin callback `(result: CameraResult) -> Unit`. * This can be passed around between C++ and Java/Kotlin. */ struct JFunc_void_CameraResult: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_CameraResult;"; public: /** * Invokes the function this `JFunc_void_CameraResult` instance holds through JNI. */ void invoke(const CameraResult& result) const { static const auto method = javaClassStatic()->getMethod /* result */)>("invoke"); method(self(), JCameraResult::fromCpp(result)); } }; /** * An implementation of Func_void_CameraResult that is backed by a C++ implementation (using `std::function<...>`) */ struct JFunc_void_CameraResult_cxx final: public jni::HybridClass { public: static jni::local_ref fromCpp(const std::function& func) { return JFunc_void_CameraResult_cxx::newObjectCxxArgs(func); } public: /** * Invokes the C++ `std::function<...>` this `JFunc_void_CameraResult_cxx` instance holds. */ void invoke_cxx(jni::alias_ref result) { _func(result->toCpp()); } public: [[nodiscard]] inline const std::function& getFunction() const { return _func; } public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_CameraResult_cxx;"; static void registerNatives() { registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_CameraResult_cxx::invoke_cxx)}); } private: explicit JFunc_void_CameraResult_cxx(const std::function& func): _func(func) { } private: friend HybridBase; std::function _func; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JFunc_void_CropResult.hpp ================================================ /// /// JFunc_void_CropResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include #include #include "CropResult.hpp" #include "JCropResult.hpp" #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * Represents the Java/Kotlin callback `(result: CropResult) -> Unit`. * This can be passed around between C++ and Java/Kotlin. */ struct JFunc_void_CropResult: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_CropResult;"; public: /** * Invokes the function this `JFunc_void_CropResult` instance holds through JNI. */ void invoke(const CropResult& result) const { static const auto method = javaClassStatic()->getMethod /* result */)>("invoke"); method(self(), JCropResult::fromCpp(result)); } }; /** * An implementation of Func_void_CropResult that is backed by a C++ implementation (using `std::function<...>`) */ struct JFunc_void_CropResult_cxx final: public jni::HybridClass { public: static jni::local_ref fromCpp(const std::function& func) { return JFunc_void_CropResult_cxx::newObjectCxxArgs(func); } public: /** * Invokes the C++ `std::function<...>` this `JFunc_void_CropResult_cxx` instance holds. */ void invoke_cxx(jni::alias_ref result) { _func(result->toCpp()); } public: [[nodiscard]] inline const std::function& getFunction() const { return _func; } public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_CropResult_cxx;"; static void registerNatives() { registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_CropResult_cxx::invoke_cxx)}); } private: explicit JFunc_void_CropResult_cxx(const std::function& func): _func(func) { } private: friend HybridBase; std::function _func; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JFunc_void_double.hpp ================================================ /// /// JFunc_void_double.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * Represents the Java/Kotlin callback `(index: Double) -> Unit`. * This can be passed around between C++ and Java/Kotlin. */ struct JFunc_void_double: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_double;"; public: /** * Invokes the function this `JFunc_void_double` instance holds through JNI. */ void invoke(double index) const { static const auto method = javaClassStatic()->getMethod("invoke"); method(self(), index); } }; /** * An implementation of Func_void_double that is backed by a C++ implementation (using `std::function<...>`) */ struct JFunc_void_double_cxx final: public jni::HybridClass { public: static jni::local_ref fromCpp(const std::function& func) { return JFunc_void_double_cxx::newObjectCxxArgs(func); } public: /** * Invokes the C++ `std::function<...>` this `JFunc_void_double_cxx` instance holds. */ void invoke_cxx(double index) { _func(index); } public: [[nodiscard]] inline const std::function& getFunction() const { return _func; } public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_double_cxx;"; static void registerNatives() { registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_double_cxx::invoke_cxx)}); } private: explicit JFunc_void_double_cxx(const std::function& func): _func(func) { } private: friend HybridBase; std::function _func; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JFunc_void_std__vector_PickerResult_.hpp ================================================ /// /// JFunc_void_std__vector_PickerResult_.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include #include #include #include "PickerResult.hpp" #include "JPickerResult.hpp" #include #include #include "ResultType.hpp" #include "JResultType.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * Represents the Java/Kotlin callback `(result: Array) -> Unit`. * This can be passed around between C++ and Java/Kotlin. */ struct JFunc_void_std__vector_PickerResult_: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_std__vector_PickerResult_;"; public: /** * Invokes the function this `JFunc_void_std__vector_PickerResult_` instance holds through JNI. */ void invoke(const std::vector& result) const { static const auto method = javaClassStatic()->getMethod> /* result */)>("invoke"); method(self(), [&]() { size_t __size = result.size(); jni::local_ref> __array = jni::JArrayClass::newArray(__size); for (size_t __i = 0; __i < __size; __i++) { const auto& __element = result[__i]; __array->setElement(__i, *JPickerResult::fromCpp(__element)); } return __array; }()); } }; /** * An implementation of Func_void_std__vector_PickerResult_ that is backed by a C++ implementation (using `std::function<...>`) */ struct JFunc_void_std__vector_PickerResult__cxx final: public jni::HybridClass { public: static jni::local_ref fromCpp(const std::function& /* result */)>& func) { return JFunc_void_std__vector_PickerResult__cxx::newObjectCxxArgs(func); } public: /** * Invokes the C++ `std::function<...>` this `JFunc_void_std__vector_PickerResult__cxx` instance holds. */ void invoke_cxx(jni::alias_ref> result) { _func([&]() { size_t __size = result->size(); std::vector __vector; __vector.reserve(__size); for (size_t __i = 0; __i < __size; __i++) { auto __element = result->getElement(__i); __vector.push_back(__element->toCpp()); } return __vector; }()); } public: [[nodiscard]] inline const std::function& /* result */)>& getFunction() const { return _func; } public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Func_void_std__vector_PickerResult__cxx;"; static void registerNatives() { registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_std__vector_PickerResult__cxx::invoke_cxx)}); } private: explicit JFunc_void_std__vector_PickerResult__cxx(const std::function& /* result */)>& func): _func(func) { } private: friend HybridBase; std::function& /* result */)> _func; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.cpp ================================================ /// /// JHybridMultipleImagePickerSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #include "JHybridMultipleImagePickerSpec.hpp" // Forward declaration of `NitroConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroConfig; } // Forward declaration of `MediaType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class MediaType; } // Forward declaration of `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } // Forward declaration of `SelectBoxStyle` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectBoxStyle; } // Forward declaration of `SelectMode` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectMode; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `Text` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct Text; } // Forward declaration of `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `Theme` to properly resolve imports. 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. namespace margelo::nitro::multipleimagepicker { struct CropResult; } // Forward declaration of `MediaPreview` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct MediaPreview; } // Forward declaration of `NitroPreviewConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } // Forward declaration of `NitroCameraConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCameraConfig; } // Forward declaration of `CameraResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CameraResult; } #include "NitroConfig.hpp" #include "JNitroConfig.hpp" #include "MediaType.hpp" #include "JMediaType.hpp" #include #include "PickerResult.hpp" #include "JPickerResult.hpp" #include #include #include "ResultType.hpp" #include "JResultType.hpp" #include "SelectBoxStyle.hpp" #include "JSelectBoxStyle.hpp" #include "SelectMode.hpp" #include "JSelectMode.hpp" #include "PickerCropConfig.hpp" #include "JPickerCropConfig.hpp" #include "CropRatio.hpp" #include "JCropRatio.hpp" #include "Text.hpp" #include "JText.hpp" #include "Language.hpp" #include "JLanguage.hpp" #include "Theme.hpp" #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_PickerResult_.hpp" #include "JFunc_void_double.hpp" #include "NitroCropConfig.hpp" #include "JNitroCropConfig.hpp" #include "CropResult.hpp" #include "JFunc_void_CropResult.hpp" #include "JCropResult.hpp" #include "MediaPreview.hpp" #include "JMediaPreview.hpp" #include "NitroPreviewConfig.hpp" #include "JNitroPreviewConfig.hpp" #include "NitroCameraConfig.hpp" #include "JNitroCameraConfig.hpp" #include "CameraResult.hpp" #include "JFunc_void_CameraResult.hpp" #include "JCameraResult.hpp" namespace margelo::nitro::multipleimagepicker { jni::local_ref JHybridMultipleImagePickerSpec::initHybrid(jni::alias_ref jThis) { return makeCxxInstance(jThis); } void JHybridMultipleImagePickerSpec::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", JHybridMultipleImagePickerSpec::initHybrid), }); } size_t JHybridMultipleImagePickerSpec::getExternalMemorySize() noexcept { static const auto method = javaClassStatic()->getMethod("getMemorySize"); return method(_javaPart); } // Properties // Methods void JHybridMultipleImagePickerSpec::openPicker(const NitroConfig& config, const std::function& /* result */)>& resolved, const std::function& rejected) { static const auto method = javaClassStatic()->getMethod /* config */, jni::alias_ref /* resolved */, jni::alias_ref /* rejected */)>("openPicker_cxx"); method(_javaPart, JNitroConfig::fromCpp(config), JFunc_void_std__vector_PickerResult__cxx::fromCpp(resolved), JFunc_void_double_cxx::fromCpp(rejected)); } void JHybridMultipleImagePickerSpec::openCrop(const std::string& image, const NitroCropConfig& config, const std::function& resolved, const std::function& rejected) { static const auto method = javaClassStatic()->getMethod /* image */, jni::alias_ref /* config */, jni::alias_ref /* resolved */, jni::alias_ref /* rejected */)>("openCrop_cxx"); method(_javaPart, jni::make_jstring(image), JNitroCropConfig::fromCpp(config), JFunc_void_CropResult_cxx::fromCpp(resolved), JFunc_void_double_cxx::fromCpp(rejected)); } void JHybridMultipleImagePickerSpec::openPreview(const std::vector& media, double index, const NitroPreviewConfig& config, const std::function& onLongPress) { static const auto method = javaClassStatic()->getMethod> /* media */, double /* index */, jni::alias_ref /* config */, jni::alias_ref /* onLongPress */)>("openPreview_cxx"); method(_javaPart, [&]() { size_t __size = media.size(); jni::local_ref> __array = jni::JArrayClass::newArray(__size); for (size_t __i = 0; __i < __size; __i++) { const auto& __element = media[__i]; __array->setElement(__i, *JMediaPreview::fromCpp(__element)); } return __array; }(), index, JNitroPreviewConfig::fromCpp(config), JFunc_void_double_cxx::fromCpp(onLongPress)); } void JHybridMultipleImagePickerSpec::openCamera(const NitroCameraConfig& config, const std::function& resolved, const std::function& rejected) { static const auto method = javaClassStatic()->getMethod /* config */, jni::alias_ref /* resolved */, jni::alias_ref /* rejected */)>("openCamera_cxx"); method(_javaPart, JNitroCameraConfig::fromCpp(config), JFunc_void_CameraResult_cxx::fromCpp(resolved), JFunc_void_double_cxx::fromCpp(rejected)); } } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JHybridMultipleImagePickerSpec.hpp ================================================ /// /// HybridMultipleImagePickerSpec.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include #include "HybridMultipleImagePickerSpec.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; class JHybridMultipleImagePickerSpec: public jni::HybridClass, public virtual HybridMultipleImagePickerSpec { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/HybridMultipleImagePickerSpec;"; static jni::local_ref initHybrid(jni::alias_ref jThis); static void registerNatives(); protected: // C++ constructor (called from Java via `initHybrid()`) explicit JHybridMultipleImagePickerSpec(jni::alias_ref jThis) : HybridObject(HybridMultipleImagePickerSpec::TAG), _javaPart(jni::make_global(jThis)) {} public: ~JHybridMultipleImagePickerSpec() override { // Hermes GC can destroy JS objects on a non-JNI Thread. jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); } public: size_t getExternalMemorySize() noexcept override; public: inline const jni::global_ref& getJavaPart() const noexcept { return _javaPart; } public: // Properties public: // Methods void openPicker(const NitroConfig& config, const std::function& /* result */)>& resolved, const std::function& rejected) override; void openCrop(const std::string& image, const NitroCropConfig& config, const std::function& resolved, const std::function& rejected) override; void openPreview(const std::vector& media, double index, const NitroPreviewConfig& config, const std::function& onLongPress) override; void openCamera(const NitroCameraConfig& config, const std::function& resolved, const std::function& rejected) override; private: friend HybridBase; using HybridBase::HybridBase; jni::global_ref _javaPart; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JLanguage.hpp ================================================ /// /// JLanguage.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "Language.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "Language" and the the Kotlin enum "Language". */ struct JLanguage final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Language;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum Language. */ [[maybe_unused]] [[nodiscard]] Language 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(Language value) { static const auto clazz = javaClassStatic(); static const auto fieldSYSTEM = clazz->getStaticField("SYSTEM"); static const auto fieldZH_HANS = clazz->getStaticField("ZH_HANS"); static const auto fieldZH_HANT = clazz->getStaticField("ZH_HANT"); static const auto fieldJA = clazz->getStaticField("JA"); static const auto fieldKO = clazz->getStaticField("KO"); static const auto fieldEN = clazz->getStaticField("EN"); static const auto fieldTH = clazz->getStaticField("TH"); static const auto fieldID = clazz->getStaticField("ID"); static const auto fieldVI = clazz->getStaticField("VI"); static const auto fieldRU = clazz->getStaticField("RU"); static const auto fieldDE = clazz->getStaticField("DE"); static const auto fieldFR = clazz->getStaticField("FR"); static const auto fieldAR = clazz->getStaticField("AR"); switch (value) { case Language::SYSTEM: return clazz->getStaticFieldValue(fieldSYSTEM); case Language::ZH_HANS: return clazz->getStaticFieldValue(fieldZH_HANS); case Language::ZH_HANT: return clazz->getStaticFieldValue(fieldZH_HANT); case Language::JA: return clazz->getStaticFieldValue(fieldJA); case Language::KO: return clazz->getStaticFieldValue(fieldKO); case Language::EN: return clazz->getStaticFieldValue(fieldEN); case Language::TH: return clazz->getStaticFieldValue(fieldTH); case Language::ID: return clazz->getStaticFieldValue(fieldID); case Language::VI: return clazz->getStaticFieldValue(fieldVI); case Language::RU: return clazz->getStaticFieldValue(fieldRU); case Language::DE: return clazz->getStaticFieldValue(fieldDE); case Language::FR: return clazz->getStaticFieldValue(fieldFR); case Language::AR: return clazz->getStaticFieldValue(fieldAR); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JMediaPreview.hpp ================================================ /// /// JMediaPreview.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "MediaPreview.hpp" #include "JResultType.hpp" #include "ResultType.hpp" #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "MediaPreview" and the the Kotlin data class "MediaPreview". */ struct JMediaPreview final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/MediaPreview;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct MediaPreview by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] MediaPreview toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldType = clazz->getField("type"); jni::local_ref type = this->getFieldValue(fieldType); static const auto fieldPath = clazz->getField("path"); jni::local_ref path = this->getFieldValue(fieldPath); static const auto fieldThumbnail = clazz->getField("thumbnail"); jni::local_ref thumbnail = this->getFieldValue(fieldThumbnail); static const auto fieldLocalIdentifier = clazz->getField("localIdentifier"); jni::local_ref localIdentifier = this->getFieldValue(fieldLocalIdentifier); return MediaPreview( type->toCpp(), path != nullptr ? std::make_optional(path->toStdString()) : std::nullopt, thumbnail != nullptr ? std::make_optional(thumbnail->toStdString()) : std::nullopt, localIdentifier != nullptr ? std::make_optional(localIdentifier->toStdString()) : 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 MediaPreview& value) { return newInstance( JResultType::fromCpp(value.type), value.path.has_value() ? jni::make_jstring(value.path.value()) : nullptr, value.thumbnail.has_value() ? jni::make_jstring(value.thumbnail.value()) : nullptr, value.localIdentifier.has_value() ? jni::make_jstring(value.localIdentifier.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JMediaType.hpp ================================================ /// /// JMediaType.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "MediaType.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "MediaType" and the the Kotlin enum "MediaType". */ struct JMediaType final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/MediaType;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum MediaType. */ [[maybe_unused]] [[nodiscard]] MediaType 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(MediaType value) { static const auto clazz = javaClassStatic(); static const auto fieldVIDEO = clazz->getStaticField("VIDEO"); static const auto fieldIMAGE = clazz->getStaticField("IMAGE"); static const auto fieldALL = clazz->getStaticField("ALL"); switch (value) { case MediaType::VIDEO: return clazz->getStaticFieldValue(fieldVIDEO); case MediaType::IMAGE: return clazz->getStaticFieldValue(fieldIMAGE); case MediaType::ALL: return clazz->getStaticFieldValue(fieldALL); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JNitroCameraConfig.hpp ================================================ /// /// JNitroCameraConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "NitroCameraConfig.hpp" #include "CameraDevice.hpp" #include "CropRatio.hpp" #include "JCameraDevice.hpp" #include "JCropRatio.hpp" #include "JLanguage.hpp" #include "JMediaType.hpp" #include "JPickerCropConfig.hpp" #include "JPresentation.hpp" #include "Language.hpp" #include "MediaType.hpp" #include "PickerCropConfig.hpp" #include "Presentation.hpp" #include #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "NitroCameraConfig" and the the Kotlin data class "NitroCameraConfig". */ struct JNitroCameraConfig final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/NitroCameraConfig;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct NitroCameraConfig by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] NitroCameraConfig toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldMediaType = clazz->getField("mediaType"); jni::local_ref mediaType = this->getFieldValue(fieldMediaType); static const auto fieldPresentation = clazz->getField("presentation"); jni::local_ref presentation = this->getFieldValue(fieldPresentation); static const auto fieldLanguage = clazz->getField("language"); jni::local_ref language = this->getFieldValue(fieldLanguage); static const auto fieldCrop = clazz->getField("crop"); jni::local_ref crop = this->getFieldValue(fieldCrop); static const auto fieldIsSaveSystemAlbum = clazz->getField("isSaveSystemAlbum"); jni::local_ref isSaveSystemAlbum = this->getFieldValue(fieldIsSaveSystemAlbum); static const auto fieldColor = clazz->getField("color"); jni::local_ref color = this->getFieldValue(fieldColor); 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 NitroCameraConfig( mediaType->toCpp(), presentation->toCpp(), language->toCpp(), crop != nullptr ? std::make_optional(crop->toCpp()) : std::nullopt, isSaveSystemAlbum != nullptr ? std::make_optional(static_cast(isSaveSystemAlbum->value())) : std::nullopt, color != nullptr ? std::make_optional(color->value()) : std::nullopt, cameraDevice != nullptr ? std::make_optional(cameraDevice->toCpp()) : std::nullopt, 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 NitroCameraConfig& value) { return newInstance( JMediaType::fromCpp(value.mediaType), JPresentation::fromCpp(value.presentation), JLanguage::fromCpp(value.language), value.crop.has_value() ? JPickerCropConfig::fromCpp(value.crop.value()) : nullptr, value.isSaveSystemAlbum.has_value() ? jni::JBoolean::valueOf(value.isSaveSystemAlbum.value()) : nullptr, value.color.has_value() ? jni::JDouble::valueOf(value.color.value()) : nullptr, value.cameraDevice.has_value() ? JCameraDevice::fromCpp(value.cameraDevice.value()) : nullptr, value.videoMaximumDuration.has_value() ? jni::JDouble::valueOf(value.videoMaximumDuration.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JNitroConfig.hpp ================================================ /// /// JNitroConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #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 "JPickerResult.hpp" #include "JPresentation.hpp" #include "JResultType.hpp" #include "JSelectBoxStyle.hpp" #include "JSelectMode.hpp" #include "JText.hpp" #include "JTheme.hpp" #include "Language.hpp" #include "MediaType.hpp" #include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "PickerResult.hpp" #include "Presentation.hpp" #include "ResultType.hpp" #include "SelectBoxStyle.hpp" #include "SelectMode.hpp" #include "Text.hpp" #include "Theme.hpp" #include #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "NitroConfig" and the the Kotlin data class "NitroConfig". */ struct JNitroConfig final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/NitroConfig;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct NitroConfig by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] NitroConfig toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldMediaType = clazz->getField("mediaType"); jni::local_ref mediaType = this->getFieldValue(fieldMediaType); static const auto fieldSelectedAssets = clazz->getField>("selectedAssets"); jni::local_ref> selectedAssets = this->getFieldValue(fieldSelectedAssets); static const auto fieldSelectBoxStyle = clazz->getField("selectBoxStyle"); jni::local_ref selectBoxStyle = this->getFieldValue(fieldSelectBoxStyle); static const auto fieldSelectMode = clazz->getField("selectMode"); jni::local_ref selectMode = this->getFieldValue(fieldSelectMode); static const auto fieldNumberOfColumn = clazz->getField("numberOfColumn"); jni::local_ref numberOfColumn = this->getFieldValue(fieldNumberOfColumn); static const auto fieldIsPreview = clazz->getField("isPreview"); jni::local_ref isPreview = this->getFieldValue(fieldIsPreview); static const auto fieldPrimaryColor = clazz->getField("primaryColor"); jni::local_ref primaryColor = this->getFieldValue(fieldPrimaryColor); static const auto fieldAllowSwipeToSelect = clazz->getField("allowSwipeToSelect"); jni::local_ref allowSwipeToSelect = this->getFieldValue(fieldAllowSwipeToSelect); static const auto fieldSpacing = clazz->getField("spacing"); jni::local_ref spacing = this->getFieldValue(fieldSpacing); static const auto fieldIsHiddenPreviewButton = clazz->getField("isHiddenPreviewButton"); jni::local_ref isHiddenPreviewButton = this->getFieldValue(fieldIsHiddenPreviewButton); static const auto fieldIsHiddenOriginalButton = clazz->getField("isHiddenOriginalButton"); jni::local_ref isHiddenOriginalButton = this->getFieldValue(fieldIsHiddenOriginalButton); static const auto fieldIsShowPreviewList = clazz->getField("isShowPreviewList"); jni::local_ref isShowPreviewList = this->getFieldValue(fieldIsShowPreviewList); static const auto fieldAllowHapticTouchPreview = clazz->getField("allowHapticTouchPreview"); jni::local_ref allowHapticTouchPreview = this->getFieldValue(fieldAllowHapticTouchPreview); static const auto fieldAllowedLimit = clazz->getField("allowedLimit"); jni::local_ref allowedLimit = this->getFieldValue(fieldAllowedLimit); static const auto fieldMaxVideo = clazz->getField("maxVideo"); jni::local_ref maxVideo = this->getFieldValue(fieldMaxVideo); static const auto fieldMaxSelect = clazz->getField("maxSelect"); jni::local_ref maxSelect = this->getFieldValue(fieldMaxSelect); static const auto fieldMaxVideoDuration = clazz->getField("maxVideoDuration"); jni::local_ref maxVideoDuration = this->getFieldValue(fieldMaxVideoDuration); static const auto fieldMinVideoDuration = clazz->getField("minVideoDuration"); jni::local_ref minVideoDuration = this->getFieldValue(fieldMinVideoDuration); static const auto fieldMaxFileSize = clazz->getField("maxFileSize"); jni::local_ref maxFileSize = this->getFieldValue(fieldMaxFileSize); static const auto fieldBackgroundDark = clazz->getField("backgroundDark"); jni::local_ref backgroundDark = this->getFieldValue(fieldBackgroundDark); static const auto fieldCrop = clazz->getField("crop"); jni::local_ref crop = this->getFieldValue(fieldCrop); static const auto fieldText = clazz->getField("text"); jni::local_ref text = this->getFieldValue(fieldText); static const auto fieldLanguage = clazz->getField("language"); jni::local_ref language = this->getFieldValue(fieldLanguage); static const auto fieldTheme = clazz->getField("theme"); 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(), [&]() { size_t __size = selectedAssets->size(); std::vector __vector; __vector.reserve(__size); for (size_t __i = 0; __i < __size; __i++) { auto __element = selectedAssets->getElement(__i); __vector.push_back(__element->toCpp()); } return __vector; }(), selectBoxStyle->toCpp(), selectMode->toCpp(), 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, 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, isHiddenOriginalButton != nullptr ? std::make_optional(static_cast(isHiddenOriginalButton->value())) : std::nullopt, isShowPreviewList != nullptr ? std::make_optional(static_cast(isShowPreviewList->value())) : std::nullopt, allowHapticTouchPreview != nullptr ? std::make_optional(static_cast(allowHapticTouchPreview->value())) : std::nullopt, allowedLimit != nullptr ? std::make_optional(static_cast(allowedLimit->value())) : std::nullopt, maxVideo != nullptr ? std::make_optional(maxVideo->value()) : std::nullopt, maxSelect != nullptr ? std::make_optional(maxSelect->value()) : std::nullopt, maxVideoDuration != nullptr ? std::make_optional(maxVideoDuration->value()) : std::nullopt, minVideoDuration != nullptr ? std::make_optional(minVideoDuration->value()) : std::nullopt, maxFileSize != nullptr ? std::make_optional(maxFileSize->value()) : std::nullopt, backgroundDark != nullptr ? std::make_optional(backgroundDark->value()) : std::nullopt, crop != nullptr ? std::make_optional(crop->toCpp()) : std::nullopt, text != nullptr ? std::make_optional(text->toCpp()) : std::nullopt, language->toCpp(), theme->toCpp(), presentation->toCpp(), camera != nullptr ? std::make_optional(camera->toCpp()) : 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 NitroConfig& value) { return newInstance( JMediaType::fromCpp(value.mediaType), [&]() { size_t __size = value.selectedAssets.size(); jni::local_ref> __array = jni::JArrayClass::newArray(__size); for (size_t __i = 0; __i < __size; __i++) { const auto& __element = value.selectedAssets[__i]; __array->setElement(__i, *JPickerResult::fromCpp(__element)); } return __array; }(), JSelectBoxStyle::fromCpp(value.selectBoxStyle), JSelectMode::fromCpp(value.selectMode), 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.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, value.isHiddenOriginalButton.has_value() ? jni::JBoolean::valueOf(value.isHiddenOriginalButton.value()) : nullptr, value.isShowPreviewList.has_value() ? jni::JBoolean::valueOf(value.isShowPreviewList.value()) : nullptr, value.allowHapticTouchPreview.has_value() ? jni::JBoolean::valueOf(value.allowHapticTouchPreview.value()) : nullptr, value.allowedLimit.has_value() ? jni::JBoolean::valueOf(value.allowedLimit.value()) : nullptr, value.maxVideo.has_value() ? jni::JDouble::valueOf(value.maxVideo.value()) : nullptr, value.maxSelect.has_value() ? jni::JDouble::valueOf(value.maxSelect.value()) : nullptr, value.maxVideoDuration.has_value() ? jni::JDouble::valueOf(value.maxVideoDuration.value()) : nullptr, value.minVideoDuration.has_value() ? jni::JDouble::valueOf(value.minVideoDuration.value()) : nullptr, value.maxFileSize.has_value() ? jni::JDouble::valueOf(value.maxFileSize.value()) : nullptr, value.backgroundDark.has_value() ? jni::JDouble::valueOf(value.backgroundDark.value()) : nullptr, value.crop.has_value() ? JPickerCropConfig::fromCpp(value.crop.value()) : nullptr, value.text.has_value() ? JText::fromCpp(value.text.value()) : nullptr, JLanguage::fromCpp(value.language), JTheme::fromCpp(value.theme), JPresentation::fromCpp(value.presentation), value.camera.has_value() ? JPickerCameraConfig::fromCpp(value.camera.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JNitroCropConfig.hpp ================================================ /// /// JNitroCropConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "NitroCropConfig.hpp" #include "CropRatio.hpp" #include "JCropRatio.hpp" #include "JLanguage.hpp" #include "JPresentation.hpp" #include "Language.hpp" #include "Presentation.hpp" #include #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "NitroCropConfig" and the the Kotlin data class "NitroCropConfig". */ struct JNitroCropConfig final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/NitroCropConfig;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct NitroCropConfig by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] NitroCropConfig toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldLanguage = clazz->getField("language"); jni::local_ref language = this->getFieldValue(fieldLanguage); static const auto fieldPresentation = clazz->getField("presentation"); jni::local_ref presentation = this->getFieldValue(fieldPresentation); static const auto fieldCircle = clazz->getField("circle"); jni::local_ref circle = this->getFieldValue(fieldCircle); static const auto fieldRatio = clazz->getField>("ratio"); jni::local_ref> ratio = this->getFieldValue(fieldRatio); static const auto fieldDefaultRatio = clazz->getField("defaultRatio"); jni::local_ref defaultRatio = this->getFieldValue(fieldDefaultRatio); static const auto fieldFreeStyle = clazz->getField("freeStyle"); jni::local_ref freeStyle = this->getFieldValue(fieldFreeStyle); return NitroCropConfig( language->toCpp(), presentation->toCpp(), circle != nullptr ? std::make_optional(static_cast(circle->value())) : std::nullopt, [&]() { size_t __size = ratio->size(); std::vector __vector; __vector.reserve(__size); for (size_t __i = 0; __i < __size; __i++) { auto __element = ratio->getElement(__i); __vector.push_back(__element->toCpp()); } return __vector; }(), defaultRatio != nullptr ? std::make_optional(defaultRatio->toCpp()) : std::nullopt, freeStyle != nullptr ? std::make_optional(static_cast(freeStyle->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 NitroCropConfig& value) { return newInstance( JLanguage::fromCpp(value.language), JPresentation::fromCpp(value.presentation), value.circle.has_value() ? jni::JBoolean::valueOf(value.circle.value()) : nullptr, [&]() { size_t __size = value.ratio.size(); jni::local_ref> __array = jni::JArrayClass::newArray(__size); for (size_t __i = 0; __i < __size; __i++) { const auto& __element = value.ratio[__i]; __array->setElement(__i, *JCropRatio::fromCpp(__element)); } return __array; }(), value.defaultRatio.has_value() ? JCropRatio::fromCpp(value.defaultRatio.value()) : nullptr, value.freeStyle.has_value() ? jni::JBoolean::valueOf(value.freeStyle.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JNitroPreviewConfig.hpp ================================================ /// /// JNitroPreviewConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "NitroPreviewConfig.hpp" #include "JLanguage.hpp" #include "Language.hpp" #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "NitroPreviewConfig" and the the Kotlin data class "NitroPreviewConfig". */ struct JNitroPreviewConfig final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/NitroPreviewConfig;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct NitroPreviewConfig by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] NitroPreviewConfig toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldLanguage = clazz->getField("language"); jni::local_ref language = this->getFieldValue(fieldLanguage); static const auto fieldVideoAutoPlay = clazz->getField("videoAutoPlay"); jni::local_ref videoAutoPlay = this->getFieldValue(fieldVideoAutoPlay); return NitroPreviewConfig( language->toCpp(), videoAutoPlay != nullptr ? std::make_optional(static_cast(videoAutoPlay->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 NitroPreviewConfig& value) { return newInstance( JLanguage::fromCpp(value.language), value.videoAutoPlay.has_value() ? jni::JBoolean::valueOf(value.videoAutoPlay.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JPickerCameraConfig.hpp ================================================ /// /// JPickerCameraConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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]] [[nodiscard]] 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 != nullptr ? std::make_optional(cameraDevice->toCpp()) : std::nullopt, 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( value.cameraDevice.has_value() ? JCameraDevice::fromCpp(value.cameraDevice.value()) : nullptr, value.videoMaximumDuration.has_value() ? jni::JDouble::valueOf(value.videoMaximumDuration.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JPickerCropConfig.hpp ================================================ /// /// JPickerCropConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "PickerCropConfig.hpp" #include "CropRatio.hpp" #include "JCropRatio.hpp" #include #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "PickerCropConfig" and the the Kotlin data class "PickerCropConfig". */ struct JPickerCropConfig final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/PickerCropConfig;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct PickerCropConfig by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] PickerCropConfig toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldCircle = clazz->getField("circle"); jni::local_ref circle = this->getFieldValue(fieldCircle); static const auto fieldRatio = clazz->getField>("ratio"); jni::local_ref> ratio = this->getFieldValue(fieldRatio); static const auto fieldDefaultRatio = clazz->getField("defaultRatio"); jni::local_ref defaultRatio = this->getFieldValue(fieldDefaultRatio); static const auto fieldFreeStyle = clazz->getField("freeStyle"); jni::local_ref freeStyle = this->getFieldValue(fieldFreeStyle); return PickerCropConfig( circle != nullptr ? std::make_optional(static_cast(circle->value())) : std::nullopt, [&]() { size_t __size = ratio->size(); std::vector __vector; __vector.reserve(__size); for (size_t __i = 0; __i < __size; __i++) { auto __element = ratio->getElement(__i); __vector.push_back(__element->toCpp()); } return __vector; }(), defaultRatio != nullptr ? std::make_optional(defaultRatio->toCpp()) : std::nullopt, freeStyle != nullptr ? std::make_optional(static_cast(freeStyle->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 PickerCropConfig& value) { return newInstance( value.circle.has_value() ? jni::JBoolean::valueOf(value.circle.value()) : nullptr, [&]() { size_t __size = value.ratio.size(); jni::local_ref> __array = jni::JArrayClass::newArray(__size); for (size_t __i = 0; __i < __size; __i++) { const auto& __element = value.ratio[__i]; __array->setElement(__i, *JCropRatio::fromCpp(__element)); } return __array; }(), value.defaultRatio.has_value() ? JCropRatio::fromCpp(value.defaultRatio.value()) : nullptr, value.freeStyle.has_value() ? jni::JBoolean::valueOf(value.freeStyle.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JPickerResult.hpp ================================================ /// /// JPickerResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "PickerResult.hpp" #include "JResultType.hpp" #include "ResultType.hpp" #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "PickerResult" and the the Kotlin data class "PickerResult". */ struct JPickerResult final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/PickerResult;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct PickerResult by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] PickerResult toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldLocalIdentifier = clazz->getField("localIdentifier"); jni::local_ref localIdentifier = this->getFieldValue(fieldLocalIdentifier); static const auto fieldWidth = clazz->getField("width"); double width = this->getFieldValue(fieldWidth); static const auto fieldHeight = clazz->getField("height"); double height = this->getFieldValue(fieldHeight); static const auto fieldMime = clazz->getField("mime"); jni::local_ref mime = this->getFieldValue(fieldMime); static const auto fieldSize = clazz->getField("size"); double size = this->getFieldValue(fieldSize); static const auto fieldBucketId = clazz->getField("bucketId"); jni::local_ref bucketId = this->getFieldValue(fieldBucketId); static const auto fieldRealPath = clazz->getField("realPath"); jni::local_ref realPath = this->getFieldValue(fieldRealPath); static const auto fieldParentFolderName = clazz->getField("parentFolderName"); jni::local_ref parentFolderName = this->getFieldValue(fieldParentFolderName); static const auto fieldCreationDate = clazz->getField("creationDate"); jni::local_ref creationDate = this->getFieldValue(fieldCreationDate); static const auto fieldCrop = clazz->getField("crop"); jni::local_ref crop = this->getFieldValue(fieldCrop); static const auto fieldPath = clazz->getField("path"); jni::local_ref path = this->getFieldValue(fieldPath); static const auto fieldType = clazz->getField("type"); jni::local_ref type = this->getFieldValue(fieldType); static const auto fieldDuration = clazz->getField("duration"); jni::local_ref duration = this->getFieldValue(fieldDuration); static const auto fieldThumbnail = clazz->getField("thumbnail"); jni::local_ref thumbnail = this->getFieldValue(fieldThumbnail); static const auto fieldFileName = clazz->getField("fileName"); jni::local_ref fileName = this->getFieldValue(fieldFileName); return PickerResult( localIdentifier->toStdString(), width, height, mime->toStdString(), size, bucketId != nullptr ? std::make_optional(bucketId->value()) : std::nullopt, realPath != nullptr ? std::make_optional(realPath->toStdString()) : std::nullopt, parentFolderName != nullptr ? std::make_optional(parentFolderName->toStdString()) : std::nullopt, creationDate != nullptr ? std::make_optional(creationDate->value()) : std::nullopt, crop != nullptr ? std::make_optional(static_cast(crop->value())) : std::nullopt, path->toStdString(), type->toCpp(), duration != nullptr ? std::make_optional(duration->value()) : std::nullopt, thumbnail != nullptr ? std::make_optional(thumbnail->toStdString()) : std::nullopt, fileName != nullptr ? std::make_optional(fileName->toStdString()) : 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 PickerResult& value) { return newInstance( jni::make_jstring(value.localIdentifier), value.width, value.height, jni::make_jstring(value.mime), value.size, value.bucketId.has_value() ? jni::JDouble::valueOf(value.bucketId.value()) : nullptr, value.realPath.has_value() ? jni::make_jstring(value.realPath.value()) : nullptr, value.parentFolderName.has_value() ? jni::make_jstring(value.parentFolderName.value()) : nullptr, value.creationDate.has_value() ? jni::JDouble::valueOf(value.creationDate.value()) : nullptr, value.crop.has_value() ? jni::JBoolean::valueOf(value.crop.value()) : nullptr, jni::make_jstring(value.path), JResultType::fromCpp(value.type), value.duration.has_value() ? jni::JDouble::valueOf(value.duration.value()) : nullptr, value.thumbnail.has_value() ? jni::make_jstring(value.thumbnail.value()) : nullptr, value.fileName.has_value() ? jni::make_jstring(value.fileName.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JPresentation.hpp ================================================ /// /// JPresentation.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "Presentation.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "Presentation" and the the Kotlin enum "Presentation". */ struct JPresentation final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Presentation;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum Presentation. */ [[maybe_unused]] [[nodiscard]] Presentation 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(Presentation value) { static const auto clazz = javaClassStatic(); static const auto fieldFULLSCREENMODAL = clazz->getStaticField("FULLSCREENMODAL"); static const auto fieldFORMSHEET = clazz->getStaticField("FORMSHEET"); switch (value) { case Presentation::FULLSCREENMODAL: return clazz->getStaticFieldValue(fieldFULLSCREENMODAL); case Presentation::FORMSHEET: return clazz->getStaticFieldValue(fieldFORMSHEET); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JResultType.hpp ================================================ /// /// JResultType.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "ResultType.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "ResultType" and the the Kotlin enum "ResultType". */ struct JResultType final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/ResultType;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum ResultType. */ [[maybe_unused]] [[nodiscard]] ResultType 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(ResultType value) { static const auto clazz = javaClassStatic(); static const auto fieldVIDEO = clazz->getStaticField("VIDEO"); static const auto fieldIMAGE = clazz->getStaticField("IMAGE"); switch (value) { case ResultType::VIDEO: return clazz->getStaticFieldValue(fieldVIDEO); case ResultType::IMAGE: return clazz->getStaticFieldValue(fieldIMAGE); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JSelectBoxStyle.hpp ================================================ /// /// JSelectBoxStyle.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "SelectBoxStyle.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "SelectBoxStyle" and the the Kotlin enum "SelectBoxStyle". */ struct JSelectBoxStyle final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/SelectBoxStyle;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum SelectBoxStyle. */ [[maybe_unused]] [[nodiscard]] SelectBoxStyle 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(SelectBoxStyle value) { static const auto clazz = javaClassStatic(); static const auto fieldNUMBER = clazz->getStaticField("NUMBER"); static const auto fieldTICK = clazz->getStaticField("TICK"); switch (value) { case SelectBoxStyle::NUMBER: return clazz->getStaticFieldValue(fieldNUMBER); case SelectBoxStyle::TICK: return clazz->getStaticFieldValue(fieldTICK); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JSelectMode.hpp ================================================ /// /// JSelectMode.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "SelectMode.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "SelectMode" and the the Kotlin enum "SelectMode". */ struct JSelectMode final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/SelectMode;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum SelectMode. */ [[maybe_unused]] [[nodiscard]] SelectMode 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(SelectMode value) { static const auto clazz = javaClassStatic(); static const auto fieldSINGLE = clazz->getStaticField("SINGLE"); static const auto fieldMULTIPLE = clazz->getStaticField("MULTIPLE"); switch (value) { case SelectMode::SINGLE: return clazz->getStaticFieldValue(fieldSINGLE); case SelectMode::MULTIPLE: return clazz->getStaticFieldValue(fieldMULTIPLE); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JText.hpp ================================================ /// /// JText.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "Text.hpp" #include #include namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ struct "Text" and the the Kotlin data class "Text". */ struct JText final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Text;"; public: /** * Convert this Java/Kotlin-based struct to the C++ struct Text by copying all values to C++. */ [[maybe_unused]] [[nodiscard]] Text toCpp() const { static const auto clazz = javaClassStatic(); static const auto fieldFinish = clazz->getField("finish"); jni::local_ref finish = this->getFieldValue(fieldFinish); static const auto fieldOriginal = clazz->getField("original"); jni::local_ref original = this->getFieldValue(fieldOriginal); static const auto fieldPreview = clazz->getField("preview"); jni::local_ref preview = this->getFieldValue(fieldPreview); static const auto fieldEdit = clazz->getField("edit"); jni::local_ref edit = this->getFieldValue(fieldEdit); return Text( finish != nullptr ? std::make_optional(finish->toStdString()) : std::nullopt, original != nullptr ? std::make_optional(original->toStdString()) : std::nullopt, preview != nullptr ? std::make_optional(preview->toStdString()) : std::nullopt, edit != nullptr ? std::make_optional(edit->toStdString()) : 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 Text& value) { return newInstance( value.finish.has_value() ? jni::make_jstring(value.finish.value()) : nullptr, value.original.has_value() ? jni::make_jstring(value.original.value()) : nullptr, value.preview.has_value() ? jni::make_jstring(value.preview.value()) : nullptr, value.edit.has_value() ? jni::make_jstring(value.edit.value()) : nullptr ); } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/c++/JTheme.hpp ================================================ /// /// JTheme.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include #include "Theme.hpp" namespace margelo::nitro::multipleimagepicker { using namespace facebook; /** * The C++ JNI bridge between the C++ enum "Theme" and the the Kotlin enum "Theme". */ struct JTheme final: public jni::JavaClass { public: static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/multipleimagepicker/Theme;"; public: /** * Convert this Java/Kotlin-based enum to the C++ enum Theme. */ [[maybe_unused]] [[nodiscard]] Theme 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(Theme value) { static const auto clazz = javaClassStatic(); static const auto fieldLIGHT = clazz->getStaticField("LIGHT"); static const auto fieldDARK = clazz->getStaticField("DARK"); switch (value) { case Theme::LIGHT: return clazz->getStaticFieldValue(fieldLIGHT); case Theme::DARK: return clazz->getStaticFieldValue(fieldDARK); default: std::string stringValue = std::to_string(static_cast(value)); throw std::invalid_argument("Invalid enum value (" + stringValue + "!"); } } }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraDevice.kt ================================================ /// /// CameraDevice.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CameraResult.kt ================================================ /// /// CameraResult.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "CameraResult". */ @DoNotStrip @Keep data class CameraResult @DoNotStrip @Keep constructor( val path: String, val type: ResultType, val width: Double?, val height: Double?, val duration: Double?, val thumbnail: String?, val fileName: String? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CropRatio.kt ================================================ /// /// CropRatio.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "CropRatio". */ @DoNotStrip @Keep data class CropRatio @DoNotStrip @Keep constructor( val title: String?, val width: Double, val height: Double ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/CropResult.kt ================================================ /// /// CropResult.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "CropResult". */ @DoNotStrip @Keep data class CropResult @DoNotStrip @Keep constructor( val path: String, val width: Double, val height: Double ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Func_void_CameraResult.kt ================================================ /// /// Func_void_CameraResult.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.* import dalvik.annotation.optimization.FastNative /** * Represents the JavaScript callback `(result: struct) => void`. * This can be either implemented in C++ (in which case it might be a callback coming from JS), * or in Kotlin/Java (in which case it is a native callback). */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType") fun interface Func_void_CameraResult: (CameraResult) -> Unit { /** * Call the given JS callback. * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. */ @DoNotStrip @Keep override fun invoke(result: CameraResult): Unit } /** * Represents the JavaScript callback `(result: struct) => void`. * This is implemented in C++, via a `std::function<...>`. * The callback might be coming from JS. */ @DoNotStrip @Keep @Suppress( "KotlinJniMissingFunction", "unused", "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", ) class Func_void_CameraResult_cxx: Func_void_CameraResult { @DoNotStrip @Keep private val mHybridData: HybridData @DoNotStrip @Keep private constructor(hybridData: HybridData) { mHybridData = hybridData } @DoNotStrip @Keep override fun invoke(result: CameraResult): Unit = invoke_cxx(result) @FastNative private external fun invoke_cxx(result: CameraResult): Unit } /** * Represents the JavaScript callback `(result: struct) => void`. * This is implemented in Java/Kotlin, via a `(CameraResult) -> Unit`. * The callback is always coming from native. */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType", "unused") class Func_void_CameraResult_java(private val function: (CameraResult) -> Unit): Func_void_CameraResult { @DoNotStrip @Keep override fun invoke(result: CameraResult): Unit { return this.function(result) } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Func_void_CropResult.kt ================================================ /// /// Func_void_CropResult.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.* import dalvik.annotation.optimization.FastNative /** * Represents the JavaScript callback `(result: struct) => void`. * This can be either implemented in C++ (in which case it might be a callback coming from JS), * or in Kotlin/Java (in which case it is a native callback). */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType") fun interface Func_void_CropResult: (CropResult) -> Unit { /** * Call the given JS callback. * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. */ @DoNotStrip @Keep override fun invoke(result: CropResult): Unit } /** * Represents the JavaScript callback `(result: struct) => void`. * This is implemented in C++, via a `std::function<...>`. * The callback might be coming from JS. */ @DoNotStrip @Keep @Suppress( "KotlinJniMissingFunction", "unused", "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", ) class Func_void_CropResult_cxx: Func_void_CropResult { @DoNotStrip @Keep private val mHybridData: HybridData @DoNotStrip @Keep private constructor(hybridData: HybridData) { mHybridData = hybridData } @DoNotStrip @Keep override fun invoke(result: CropResult): Unit = invoke_cxx(result) @FastNative private external fun invoke_cxx(result: CropResult): Unit } /** * Represents the JavaScript callback `(result: struct) => void`. * This is implemented in Java/Kotlin, via a `(CropResult) -> Unit`. * The callback is always coming from native. */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType", "unused") class Func_void_CropResult_java(private val function: (CropResult) -> Unit): Func_void_CropResult { @DoNotStrip @Keep override fun invoke(result: CropResult): Unit { return this.function(result) } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Func_void_double.kt ================================================ /// /// Func_void_double.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.* import dalvik.annotation.optimization.FastNative /** * Represents the JavaScript callback `(index: number) => void`. * This can be either implemented in C++ (in which case it might be a callback coming from JS), * or in Kotlin/Java (in which case it is a native callback). */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType") fun interface Func_void_double: (Double) -> Unit { /** * Call the given JS callback. * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. */ @DoNotStrip @Keep override fun invoke(index: Double): Unit } /** * Represents the JavaScript callback `(index: number) => void`. * This is implemented in C++, via a `std::function<...>`. * The callback might be coming from JS. */ @DoNotStrip @Keep @Suppress( "KotlinJniMissingFunction", "unused", "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", ) class Func_void_double_cxx: Func_void_double { @DoNotStrip @Keep private val mHybridData: HybridData @DoNotStrip @Keep private constructor(hybridData: HybridData) { mHybridData = hybridData } @DoNotStrip @Keep override fun invoke(index: Double): Unit = invoke_cxx(index) @FastNative private external fun invoke_cxx(index: Double): Unit } /** * Represents the JavaScript callback `(index: number) => void`. * This is implemented in Java/Kotlin, via a `(Double) -> Unit`. * The callback is always coming from native. */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType", "unused") class Func_void_double_java(private val function: (Double) -> Unit): Func_void_double { @DoNotStrip @Keep override fun invoke(index: Double): Unit { return this.function(index) } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Func_void_std__vector_PickerResult_.kt ================================================ /// /// Func_void_std__vector_PickerResult_.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.* import dalvik.annotation.optimization.FastNative /** * Represents the JavaScript callback `(result: array) => void`. * This can be either implemented in C++ (in which case it might be a callback coming from JS), * or in Kotlin/Java (in which case it is a native callback). */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType") fun interface Func_void_std__vector_PickerResult_: (Array) -> Unit { /** * Call the given JS callback. * @throws Throwable if the JS function itself throws an error, or if the JS function/runtime has already been deleted. */ @DoNotStrip @Keep override fun invoke(result: Array): Unit } /** * Represents the JavaScript callback `(result: array) => void`. * This is implemented in C++, via a `std::function<...>`. * The callback might be coming from JS. */ @DoNotStrip @Keep @Suppress( "KotlinJniMissingFunction", "unused", "RedundantSuppression", "RedundantUnitReturnType", "FunctionName", "ConvertSecondaryConstructorToPrimary", "ClassName", "LocalVariableName", ) class Func_void_std__vector_PickerResult__cxx: Func_void_std__vector_PickerResult_ { @DoNotStrip @Keep private val mHybridData: HybridData @DoNotStrip @Keep private constructor(hybridData: HybridData) { mHybridData = hybridData } @DoNotStrip @Keep override fun invoke(result: Array): Unit = invoke_cxx(result) @FastNative private external fun invoke_cxx(result: Array): Unit } /** * Represents the JavaScript callback `(result: array) => void`. * This is implemented in Java/Kotlin, via a `(Array) -> Unit`. * The callback is always coming from native. */ @DoNotStrip @Keep @Suppress("ClassName", "RedundantUnitReturnType", "unused") class Func_void_std__vector_PickerResult__java(private val function: (Array) -> Unit): Func_void_std__vector_PickerResult_ { @DoNotStrip @Keep override fun invoke(result: Array): Unit { return this.function(result) } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/HybridMultipleImagePickerSpec.kt ================================================ /// /// HybridMultipleImagePickerSpec.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import com.margelo.nitro.core.* /** * A Kotlin class representing the MultipleImagePicker HybridObject. * Implement this abstract class to create Kotlin-based instances of MultipleImagePicker. */ @DoNotStrip @Keep @Suppress( "KotlinJniMissingFunction", "unused", "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" ) abstract class HybridMultipleImagePickerSpec: HybridObject() { @DoNotStrip private var mHybridData: HybridData = initHybrid() init { super.updateNative(mHybridData) } override fun updateNative(hybridData: HybridData) { mHybridData = hybridData super.updateNative(hybridData) } // Properties // Methods abstract fun openPicker(config: NitroConfig, resolved: (result: Array) -> Unit, rejected: (reject: Double) -> Unit): Unit @DoNotStrip @Keep private fun openPicker_cxx(config: NitroConfig, resolved: Func_void_std__vector_PickerResult_, rejected: Func_void_double): Unit { val __result = openPicker(config, resolved, rejected) return __result } abstract fun openCrop(image: String, config: NitroCropConfig, resolved: (result: CropResult) -> Unit, rejected: (reject: Double) -> Unit): Unit @DoNotStrip @Keep private fun openCrop_cxx(image: String, config: NitroCropConfig, resolved: Func_void_CropResult, rejected: Func_void_double): Unit { val __result = openCrop(image, config, resolved, rejected) return __result } abstract fun openPreview(media: Array, index: Double, config: NitroPreviewConfig, onLongPress: (index: Double) -> Unit): Unit @DoNotStrip @Keep private fun openPreview_cxx(media: Array, index: Double, config: NitroPreviewConfig, onLongPress: Func_void_double): Unit { val __result = openPreview(media, index, config, onLongPress) return __result } abstract fun openCamera(config: NitroCameraConfig, resolved: (result: CameraResult) -> Unit, rejected: (reject: Double) -> Unit): Unit @DoNotStrip @Keep private fun openCamera_cxx(config: NitroCameraConfig, resolved: Func_void_CameraResult, rejected: Func_void_double): Unit { val __result = openCamera(config, resolved, rejected) return __result } private external fun initHybrid(): HybridData companion object { private const val TAG = "HybridMultipleImagePickerSpec" } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Language.kt ================================================ /// /// Language.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "Language". */ @DoNotStrip @Keep enum class Language { SYSTEM, ZH_HANS, ZH_HANT, JA, KO, EN, TH, ID, VI, RU, DE, FR, AR; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/MediaPreview.kt ================================================ /// /// MediaPreview.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "MediaPreview". */ @DoNotStrip @Keep data class MediaPreview @DoNotStrip @Keep constructor( val type: ResultType, val path: String?, val thumbnail: String?, val localIdentifier: String? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/MediaType.kt ================================================ /// /// MediaType.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "MediaType". */ @DoNotStrip @Keep enum class MediaType { VIDEO, IMAGE, ALL; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/MultipleImagePickerOnLoad.kt ================================================ /// /// MultipleImagePickerOnLoad.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import android.util.Log internal class MultipleImagePickerOnLoad { companion object { private const val TAG = "MultipleImagePickerOnLoad" private var didLoad = false /** * Initializes the native part of "MultipleImagePicker". * This method is idempotent and can be called more than once. */ @JvmStatic fun initializeNative() { if (didLoad) return try { Log.i(TAG, "Loading MultipleImagePicker C++ library...") System.loadLibrary("MultipleImagePicker") Log.i(TAG, "Successfully loaded MultipleImagePicker C++ library!") didLoad = true } catch (e: Error) { Log.e(TAG, "Failed to load MultipleImagePicker C++ library! Is it properly installed and linked? " + "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e) throw e } } } } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroCameraConfig.kt ================================================ /// /// NitroCameraConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "NitroCameraConfig". */ @DoNotStrip @Keep data class NitroCameraConfig @DoNotStrip @Keep constructor( val mediaType: MediaType, val presentation: Presentation, val language: Language, val crop: PickerCropConfig?, val isSaveSystemAlbum: Boolean?, val color: Double?, val cameraDevice: CameraDevice?, val videoMaximumDuration: Double? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroConfig.kt ================================================ /// /// NitroConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "NitroConfig". */ @DoNotStrip @Keep data class NitroConfig @DoNotStrip @Keep constructor( val mediaType: MediaType, val selectedAssets: Array, val selectBoxStyle: SelectBoxStyle, val selectMode: SelectMode, val numberOfColumn: Double?, val isPreview: Boolean?, val primaryColor: Double?, val allowSwipeToSelect: Boolean?, val spacing: Double?, val isHiddenPreviewButton: Boolean?, val isHiddenOriginalButton: Boolean?, val isShowPreviewList: Boolean?, val allowHapticTouchPreview: Boolean?, val allowedLimit: Boolean?, val maxVideo: Double?, val maxSelect: Double?, val maxVideoDuration: Double?, val minVideoDuration: Double?, val maxFileSize: Double?, val backgroundDark: Double?, val crop: PickerCropConfig?, val text: Text?, val language: Language, val theme: Theme, val presentation: Presentation, val camera: PickerCameraConfig? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroCropConfig.kt ================================================ /// /// NitroCropConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "NitroCropConfig". */ @DoNotStrip @Keep data class NitroCropConfig @DoNotStrip @Keep constructor( val language: Language, val presentation: Presentation, val circle: Boolean?, val ratio: Array, val defaultRatio: CropRatio?, val freeStyle: Boolean? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/NitroPreviewConfig.kt ================================================ /// /// NitroPreviewConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "NitroPreviewConfig". */ @DoNotStrip @Keep data class NitroPreviewConfig @DoNotStrip @Keep constructor( val language: Language, val videoAutoPlay: Boolean? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCameraConfig.kt ================================================ /// /// PickerCameraConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 @DoNotStrip @Keep constructor( val cameraDevice: CameraDevice?, val videoMaximumDuration: Double? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerCropConfig.kt ================================================ /// /// PickerCropConfig.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "PickerCropConfig". */ @DoNotStrip @Keep data class PickerCropConfig @DoNotStrip @Keep constructor( val circle: Boolean?, val ratio: Array, val defaultRatio: CropRatio?, val freeStyle: Boolean? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/PickerResult.kt ================================================ /// /// PickerResult.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "PickerResult". */ @DoNotStrip @Keep data class PickerResult @DoNotStrip @Keep constructor( val localIdentifier: String, val width: Double, val height: Double, val mime: String, val size: Double, val bucketId: Double?, val realPath: String?, val parentFolderName: String?, val creationDate: Double?, val crop: Boolean?, val path: String, val type: ResultType, val duration: Double?, val thumbnail: String?, val fileName: String? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Presentation.kt ================================================ /// /// Presentation.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "Presentation". */ @DoNotStrip @Keep enum class Presentation { FULLSCREENMODAL, FORMSHEET; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/ResultType.kt ================================================ /// /// ResultType.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "ResultType". */ @DoNotStrip @Keep enum class ResultType { VIDEO, IMAGE; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/SelectBoxStyle.kt ================================================ /// /// SelectBoxStyle.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "SelectBoxStyle". */ @DoNotStrip @Keep enum class SelectBoxStyle { NUMBER, TICK; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/SelectMode.kt ================================================ /// /// SelectMode.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "SelectMode". */ @DoNotStrip @Keep enum class SelectMode { SINGLE, MULTIPLE; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Text.kt ================================================ /// /// Text.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 "Text". */ @DoNotStrip @Keep data class Text @DoNotStrip @Keep constructor( val finish: String?, val original: String?, val preview: String?, val edit: String? ) { /* main constructor */ } ================================================ FILE: nitrogen/generated/android/kotlin/com/margelo/nitro/multipleimagepicker/Theme.kt ================================================ /// /// Theme.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// package com.margelo.nitro.multipleimagepicker import androidx.annotation.Keep import com.facebook.proguard.annotations.DoNotStrip /** * Represents the JavaScript enum/union "Theme". */ @DoNotStrip @Keep enum class Theme { LIGHT, DARK; @DoNotStrip @Keep private val _ordinal = ordinal } ================================================ FILE: nitrogen/generated/ios/MultipleImagePicker+autolinking.rb ================================================ # # MultipleImagePicker+autolinking.rb # This file was generated by nitrogen. DO NOT MODIFY THIS FILE. # https://github.com/mrousavy/nitro # Copyright © 2025 Marc Rousavy @ Margelo # # This is a Ruby script that adds all files generated by Nitrogen # to the given podspec. # # To use it, add this to your .podspec: # ```ruby # Pod::Spec.new do |spec| # # ... # # # Add all files generated by Nitrogen # load 'nitrogen/generated/ios/MultipleImagePicker+autolinking.rb' # add_nitrogen_files(spec) # end # ``` def add_nitrogen_files(spec) Pod::UI.puts "[NitroModules] 🔥 MultipleImagePicker is boosted by nitro!" spec.dependency "NitroModules" current_source_files = Array(spec.attributes_hash['source_files']) spec.source_files = current_source_files + [ # Generated cross-platform specs "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}", # Generated bridges for the cross-platform specs "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}", ] current_public_header_files = Array(spec.attributes_hash['public_header_files']) spec.public_header_files = current_public_header_files + [ # Generated specs "nitrogen/generated/shared/**/*.{h,hpp}", # Swift to C++ bridging helpers "nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp" ] current_private_header_files = Array(spec.attributes_hash['private_header_files']) spec.private_header_files = current_private_header_files + [ # iOS specific specs "nitrogen/generated/ios/c++/**/*.{h,hpp}", # Views are framework-specific and should be private "nitrogen/generated/shared/**/views/**/*" ] current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {} spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({ # Use C++ 20 "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", # Enables C++ <-> Swift interop (by default it's only C) "SWIFT_OBJC_INTEROP_MODE" => "objcxx", # Enables stricter modular headers "DEFINES_MODULE" => "YES", }) end ================================================ FILE: nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.cpp ================================================ /// /// MultipleImagePicker-Swift-Cxx-Bridge.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #include "MultipleImagePicker-Swift-Cxx-Bridge.hpp" // Include C++ implementation defined types #include "HybridMultipleImagePickerSpecSwift.hpp" #include "MultipleImagePicker-Swift-Cxx-Umbrella.hpp" namespace margelo::nitro::multipleimagepicker::bridge::swift { // pragma MARK: std::function& /* result */)> Func_void_std__vector_PickerResult_ create_Func_void_std__vector_PickerResult_(void* _Nonnull swiftClosureWrapper) { auto swiftClosure = MultipleImagePicker::Func_void_std__vector_PickerResult_::fromUnsafe(swiftClosureWrapper); return [swiftClosure = std::move(swiftClosure)](const std::vector& result) mutable -> void { swiftClosure.call(result); }; } // pragma MARK: std::function Func_void_double create_Func_void_double(void* _Nonnull swiftClosureWrapper) { auto swiftClosure = MultipleImagePicker::Func_void_double::fromUnsafe(swiftClosureWrapper); return [swiftClosure = std::move(swiftClosure)](double reject) mutable -> void { swiftClosure.call(reject); }; } // pragma MARK: std::function Func_void_CropResult create_Func_void_CropResult(void* _Nonnull swiftClosureWrapper) { auto swiftClosure = MultipleImagePicker::Func_void_CropResult::fromUnsafe(swiftClosureWrapper); return [swiftClosure = std::move(swiftClosure)](const CropResult& result) mutable -> void { swiftClosure.call(result); }; } // pragma MARK: std::function Func_void_CameraResult create_Func_void_CameraResult(void* _Nonnull swiftClosureWrapper) { auto swiftClosure = MultipleImagePicker::Func_void_CameraResult::fromUnsafe(swiftClosureWrapper); return [swiftClosure = std::move(swiftClosure)](const CameraResult& result) mutable -> void { swiftClosure.call(result); }; } // pragma MARK: std::shared_ptr std::shared_ptr create_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(void* _Nonnull swiftUnsafePointer) { MultipleImagePicker::HybridMultipleImagePickerSpec_cxx swiftPart = MultipleImagePicker::HybridMultipleImagePickerSpec_cxx::fromUnsafe(swiftUnsafePointer); return std::make_shared(swiftPart); } void* _Nonnull get_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ cppType) { std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType); #ifdef NITRO_DEBUG if (swiftWrapper == nullptr) [[unlikely]] { throw std::runtime_error("Class \"HybridMultipleImagePickerSpec\" is not implemented in Swift!"); } #endif MultipleImagePicker::HybridMultipleImagePickerSpec_cxx& swiftPart = swiftWrapper->getSwiftPart(); return swiftPart.toUnsafe(); } } // namespace margelo::nitro::multipleimagepicker::bridge::swift ================================================ FILE: nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Bridge.hpp ================================================ /// /// MultipleImagePicker-Swift-Cxx-Bridge.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #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 `CameraResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CameraResult; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `CropResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropResult; } // Forward declaration of `HybridMultipleImagePickerSpec` to properly resolve imports. 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 `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } // Forward declaration of `Text` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct Text; } // Forward declarations of Swift defined types // Forward declaration of `HybridMultipleImagePickerSpec_cxx` to properly resolve imports. namespace MultipleImagePicker { class HybridMultipleImagePickerSpec_cxx; } // Include C++ defined types #include "CameraDevice.hpp" #include "CameraResult.hpp" #include "CropRatio.hpp" #include "CropResult.hpp" #include "HybridMultipleImagePickerSpec.hpp" #include "MediaPreview.hpp" #include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "PickerResult.hpp" #include "ResultType.hpp" #include "Text.hpp" #include #include #include #include #include #include #include /** * Contains specialized versions of C++ templated types so they can be accessed from Swift, * as well as helper functions to interact with those C++ types from Swift. */ namespace margelo::nitro::multipleimagepicker::bridge::swift { // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_double_ = std::optional; inline std::optional create_std__optional_double_(const double& value) { return std::optional(value); } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_std__string_ = std::optional; inline std::optional create_std__optional_std__string_(const std::string& value) { return std::optional(value); } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_bool_ = std::optional; inline std::optional create_std__optional_bool_(const bool& value) { return std::optional(value); } // pragma MARK: std::vector /** * Specialized version of `std::vector`. */ using std__vector_PickerResult_ = std::vector; inline std::vector create_std__vector_PickerResult_(size_t size) { std::vector vector; vector.reserve(size); return vector; } // pragma MARK: std::vector /** * Specialized version of `std::vector`. */ using std__vector_CropRatio_ = std::vector; inline std::vector create_std__vector_CropRatio_(size_t size) { std::vector vector; vector.reserve(size); return vector; } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_CropRatio_ = std::optional; inline std::optional create_std__optional_CropRatio_(const CropRatio& value) { return std::optional(value); } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_PickerCropConfig_ = std::optional; inline std::optional create_std__optional_PickerCropConfig_(const PickerCropConfig& value) { return std::optional(value); } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_Text_ = std::optional; inline std::optional create_std__optional_Text_(const Text& value) { return std::optional(value); } // pragma MARK: std::optional /** * Specialized version of `std::optional`. */ using std__optional_CameraDevice_ = std::optional; inline std::optional create_std__optional_CameraDevice_(const CameraDevice& value) { 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&)>`. */ using Func_void_std__vector_PickerResult_ = std::function& /* result */)>; /** * Wrapper class for a `std::function& / * result * /)>`, this can be used from Swift. */ class Func_void_std__vector_PickerResult__Wrapper final { public: explicit Func_void_std__vector_PickerResult__Wrapper(std::function& /* result */)>&& func): _function(std::make_shared& /* result */)>>(std::move(func))) {} inline void call(std::vector result) const { _function->operator()(result); } private: std::shared_ptr& /* result */)>> _function; }; Func_void_std__vector_PickerResult_ create_Func_void_std__vector_PickerResult_(void* _Nonnull swiftClosureWrapper); inline Func_void_std__vector_PickerResult__Wrapper wrap_Func_void_std__vector_PickerResult_(Func_void_std__vector_PickerResult_ value) { return Func_void_std__vector_PickerResult__Wrapper(std::move(value)); } // pragma MARK: std::function /** * Specialized version of `std::function`. */ using Func_void_double = std::function; /** * Wrapper class for a `std::function`, this can be used from Swift. */ class Func_void_double_Wrapper final { public: explicit Func_void_double_Wrapper(std::function&& func): _function(std::make_shared>(std::move(func))) {} inline void call(double reject) const { _function->operator()(reject); } private: std::shared_ptr> _function; }; Func_void_double create_Func_void_double(void* _Nonnull swiftClosureWrapper); inline Func_void_double_Wrapper wrap_Func_void_double(Func_void_double value) { return Func_void_double_Wrapper(std::move(value)); } // pragma MARK: std::function /** * Specialized version of `std::function`. */ using Func_void_CropResult = std::function; /** * Wrapper class for a `std::function`, this can be used from Swift. */ class Func_void_CropResult_Wrapper final { public: explicit Func_void_CropResult_Wrapper(std::function&& func): _function(std::make_shared>(std::move(func))) {} inline void call(CropResult result) const { _function->operator()(result); } private: std::shared_ptr> _function; }; Func_void_CropResult create_Func_void_CropResult(void* _Nonnull swiftClosureWrapper); inline Func_void_CropResult_Wrapper wrap_Func_void_CropResult(Func_void_CropResult value) { return Func_void_CropResult_Wrapper(std::move(value)); } // pragma MARK: std::vector /** * Specialized version of `std::vector`. */ using std__vector_MediaPreview_ = std::vector; inline std::vector create_std__vector_MediaPreview_(size_t size) { std::vector vector; vector.reserve(size); return vector; } // pragma MARK: std::function /** * Specialized version of `std::function`. */ using Func_void_CameraResult = std::function; /** * Wrapper class for a `std::function`, this can be used from Swift. */ class Func_void_CameraResult_Wrapper final { public: explicit Func_void_CameraResult_Wrapper(std::function&& func): _function(std::make_shared>(std::move(func))) {} inline void call(CameraResult result) const { _function->operator()(result); } private: std::shared_ptr> _function; }; Func_void_CameraResult create_Func_void_CameraResult(void* _Nonnull swiftClosureWrapper); inline Func_void_CameraResult_Wrapper wrap_Func_void_CameraResult(Func_void_CameraResult value) { return Func_void_CameraResult_Wrapper(std::move(value)); } // pragma MARK: std::shared_ptr /** * Specialized version of `std::shared_ptr`. */ using std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ = std::shared_ptr; std::shared_ptr create_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(void* _Nonnull swiftUnsafePointer); void* _Nonnull get_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ cppType); // pragma MARK: std::weak_ptr using std__weak_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ = std::weak_ptr; inline std__weak_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ weakify_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(const std::shared_ptr& strong) { return strong; } // pragma MARK: Result using Result_void_ = Result; inline Result_void_ create_Result_void_() { return Result::withValue(); } inline Result_void_ create_Result_void_(const std::exception_ptr& error) { return Result::withError(error); } } // namespace margelo::nitro::multipleimagepicker::bridge::swift ================================================ FILE: nitrogen/generated/ios/MultipleImagePicker-Swift-Cxx-Umbrella.hpp ================================================ /// /// MultipleImagePicker-Swift-Cxx-Umbrella.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #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 `CameraResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CameraResult; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `CropResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropResult; } // Forward declaration of `HybridMultipleImagePickerSpec` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { class HybridMultipleImagePickerSpec; } // Forward declaration of `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `MediaPreview` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct MediaPreview; } // Forward declaration of `MediaType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class MediaType; } // Forward declaration of `NitroCameraConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCameraConfig; } // Forward declaration of `NitroConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroConfig; } // Forward declaration of `NitroCropConfig` to properly resolve imports. 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 `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } // Forward declaration of `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } // Forward declaration of `SelectBoxStyle` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectBoxStyle; } // Forward declaration of `SelectMode` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectMode; } // Forward declaration of `Text` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct Text; } // Forward declaration of `Theme` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Theme; } // Include C++ defined types #include "CameraDevice.hpp" #include "CameraResult.hpp" #include "CropRatio.hpp" #include "CropResult.hpp" #include "HybridMultipleImagePickerSpec.hpp" #include "Language.hpp" #include "MediaPreview.hpp" #include "MediaType.hpp" #include "NitroCameraConfig.hpp" #include "NitroConfig.hpp" #include "NitroCropConfig.hpp" #include "NitroPreviewConfig.hpp" #include "PickerCameraConfig.hpp" #include "PickerCropConfig.hpp" #include "PickerResult.hpp" #include "Presentation.hpp" #include "ResultType.hpp" #include "SelectBoxStyle.hpp" #include "SelectMode.hpp" #include "Text.hpp" #include "Theme.hpp" #include #include #include #include #include #include #include // C++ helpers for Swift #include "MultipleImagePicker-Swift-Cxx-Bridge.hpp" // Common C++ types used in Swift #include #include #include // Forward declarations of Swift defined types // Forward declaration of `HybridMultipleImagePickerSpec_cxx` to properly resolve imports. namespace MultipleImagePicker { class HybridMultipleImagePickerSpec_cxx; } // Include Swift defined types #if __has_include("MultipleImagePicker-Swift.h") // This header is generated by Xcode/Swift on every app build. // If it cannot be found, make sure the Swift module's name (= podspec name) is actually "MultipleImagePicker". #include "MultipleImagePicker-Swift.h" // Same as above, but used when building with frameworks (`use_frameworks`) #elif __has_include() #include #else #error MultipleImagePicker's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually "MultipleImagePicker", and try building the app first. #endif ================================================ FILE: nitrogen/generated/ios/MultipleImagePickerAutolinking.mm ================================================ /// /// MultipleImagePickerAutolinking.mm /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #import #import #import "MultipleImagePicker-Swift-Cxx-Umbrella.hpp" #import #include "HybridMultipleImagePickerSpecSwift.hpp" @interface MultipleImagePickerAutolinking : NSObject @end @implementation MultipleImagePickerAutolinking + (void) load { using namespace margelo::nitro; using namespace margelo::nitro::multipleimagepicker; HybridObjectRegistry::registerHybridObjectConstructor( "MultipleImagePicker", []() -> std::shared_ptr { std::shared_ptr hybridObject = MultipleImagePicker::MultipleImagePickerAutolinking::createMultipleImagePicker(); return hybridObject; } ); } @end ================================================ FILE: nitrogen/generated/ios/MultipleImagePickerAutolinking.swift ================================================ /// /// MultipleImagePickerAutolinking.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// public final class MultipleImagePickerAutolinking { public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Creates an instance of a Swift class that implements `HybridMultipleImagePickerSpec`, * and wraps it in a Swift class that can directly interop with C++ (`HybridMultipleImagePickerSpec_cxx`) * * This is generated by Nitrogen and will initialize the class specified * in the `"autolinking"` property of `nitro.json` (in this case, `HybridMultipleImagePicker`). */ public static func createMultipleImagePicker() -> bridge.std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ { let hybridObject = HybridMultipleImagePicker() return { () -> bridge.std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ in let __cxxWrapped = hybridObject.getCxxWrapper() return __cxxWrapped.getCxxPart() }() } } ================================================ FILE: nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.cpp ================================================ /// /// HybridMultipleImagePickerSpecSwift.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #include "HybridMultipleImagePickerSpecSwift.hpp" namespace margelo::nitro::multipleimagepicker { } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/ios/c++/HybridMultipleImagePickerSpecSwift.hpp ================================================ /// /// HybridMultipleImagePickerSpecSwift.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #include "HybridMultipleImagePickerSpec.hpp" // Forward declaration of `HybridMultipleImagePickerSpec_cxx` to properly resolve imports. namespace MultipleImagePicker { class HybridMultipleImagePickerSpec_cxx; } // Forward declaration of `NitroConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroConfig; } // Forward declaration of `MediaType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class MediaType; } // Forward declaration of `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } // Forward declaration of `SelectBoxStyle` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectBoxStyle; } // Forward declaration of `SelectMode` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectMode; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } // Forward declaration of `Text` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct Text; } // Forward declaration of `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `Theme` to properly resolve imports. 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. namespace margelo::nitro::multipleimagepicker { struct CropResult; } // Forward declaration of `MediaPreview` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct MediaPreview; } // Forward declaration of `NitroPreviewConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } // Forward declaration of `NitroCameraConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCameraConfig; } // Forward declaration of `CameraResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CameraResult; } #include "NitroConfig.hpp" #include "MediaType.hpp" #include #include "PickerResult.hpp" #include #include #include "ResultType.hpp" #include "SelectBoxStyle.hpp" #include "SelectMode.hpp" #include "PickerCropConfig.hpp" #include "CropRatio.hpp" #include "Text.hpp" #include "Language.hpp" #include "Theme.hpp" #include "Presentation.hpp" #include "PickerCameraConfig.hpp" #include "CameraDevice.hpp" #include #include "NitroCropConfig.hpp" #include "CropResult.hpp" #include "MediaPreview.hpp" #include "NitroPreviewConfig.hpp" #include "NitroCameraConfig.hpp" #include "CameraResult.hpp" #include "MultipleImagePicker-Swift-Cxx-Umbrella.hpp" namespace margelo::nitro::multipleimagepicker { /** * The C++ part of HybridMultipleImagePickerSpec_cxx.swift. * * HybridMultipleImagePickerSpecSwift (C++) accesses HybridMultipleImagePickerSpec_cxx (Swift), and might * contain some additional bridging code for C++ <> Swift interop. * * Since this obviously introduces an overhead, I hope at some point in * the future, HybridMultipleImagePickerSpec_cxx can directly inherit from the C++ class HybridMultipleImagePickerSpec * to simplify the whole structure and memory management. */ class HybridMultipleImagePickerSpecSwift: public virtual HybridMultipleImagePickerSpec { public: // Constructor from a Swift instance explicit HybridMultipleImagePickerSpecSwift(const MultipleImagePicker::HybridMultipleImagePickerSpec_cxx& swiftPart): HybridObject(HybridMultipleImagePickerSpec::TAG), _swiftPart(swiftPart) { } public: // Get the Swift part inline MultipleImagePicker::HybridMultipleImagePickerSpec_cxx& getSwiftPart() noexcept { return _swiftPart; } public: // Get memory pressure inline size_t getExternalMemorySize() noexcept override { return _swiftPart.getMemorySize(); } public: // Properties public: // Methods inline void openPicker(const NitroConfig& config, const std::function& /* result */)>& resolved, const std::function& rejected) override { auto __result = _swiftPart.openPicker(config, resolved, rejected); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } } inline void openCrop(const std::string& image, const NitroCropConfig& config, const std::function& resolved, const std::function& rejected) override { auto __result = _swiftPart.openCrop(image, config, resolved, rejected); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } } inline void openPreview(const std::vector& media, double index, const NitroPreviewConfig& config, const std::function& onLongPress) override { auto __result = _swiftPart.openPreview(media, std::forward(index), config, onLongPress); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } } inline void openCamera(const NitroCameraConfig& config, const std::function& resolved, const std::function& rejected) override { auto __result = _swiftPart.openCamera(config, resolved, rejected); if (__result.hasError()) [[unlikely]] { std::rethrow_exception(__result.error()); } } private: MultipleImagePicker::HybridMultipleImagePickerSpec_cxx _swiftPart; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/ios/swift/CameraDevice.swift ================================================ /// /// CameraDevice.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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" } } } ================================================ FILE: nitrogen/generated/ios/swift/CameraResult.swift ================================================ /// /// CameraResult.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `CameraResult`, backed by a C++ struct. */ public typealias CameraResult = margelo.nitro.multipleimagepicker.CameraResult public extension CameraResult { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `CameraResult`. */ init(path: String, type: ResultType, width: Double?, height: Double?, duration: Double?, thumbnail: String?, fileName: String?) { self.init(std.string(path), type, { () -> bridge.std__optional_double_ in if let __unwrappedValue = width { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = height { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = duration { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = thumbnail { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = fileName { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }()) } var path: String { @inline(__always) get { return String(self.__path) } @inline(__always) set { self.__path = std.string(newValue) } } var type: ResultType { @inline(__always) get { return self.__type } @inline(__always) set { self.__type = newValue } } var width: Double? { @inline(__always) get { return self.__width.value } @inline(__always) set { self.__width = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var height: Double? { @inline(__always) get { return self.__height.value } @inline(__always) set { self.__height = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var duration: Double? { @inline(__always) get { return self.__duration.value } @inline(__always) set { self.__duration = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var thumbnail: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__thumbnail.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__thumbnail = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var fileName: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__fileName.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__fileName = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/CropRatio.swift ================================================ /// /// CropRatio.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `CropRatio`, backed by a C++ struct. */ public typealias CropRatio = margelo.nitro.multipleimagepicker.CropRatio public extension CropRatio { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `CropRatio`. */ init(title: String?, width: Double, height: Double) { self.init({ () -> bridge.std__optional_std__string_ in if let __unwrappedValue = title { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), width, height) } var title: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__title.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__title = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var width: Double { @inline(__always) get { return self.__width } @inline(__always) set { self.__width = newValue } } var height: Double { @inline(__always) get { return self.__height } @inline(__always) set { self.__height = newValue } } } ================================================ FILE: nitrogen/generated/ios/swift/CropResult.swift ================================================ /// /// CropResult.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `CropResult`, backed by a C++ struct. */ public typealias CropResult = margelo.nitro.multipleimagepicker.CropResult public extension CropResult { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `CropResult`. */ init(path: String, width: Double, height: Double) { self.init(std.string(path), width, height) } var path: String { @inline(__always) get { return String(self.__path) } @inline(__always) set { self.__path = std.string(newValue) } } var width: Double { @inline(__always) get { return self.__width } @inline(__always) set { self.__width = newValue } } var height: Double { @inline(__always) get { return self.__height } @inline(__always) set { self.__height = newValue } } } ================================================ FILE: nitrogen/generated/ios/swift/Func_void_CameraResult.swift ================================================ /// /// Func_void_CameraResult.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Wraps a Swift `(_ result: CameraResult) -> Void` as a class. * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. */ public final class Func_void_CameraResult { public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift private let closure: (_ result: CameraResult) -> Void public init(_ closure: @escaping (_ result: CameraResult) -> Void) { self.closure = closure } @inline(__always) public func call(result: CameraResult) -> Void { self.closure(result) } /** * Casts this instance to a retained unsafe raw pointer. * This acquires one additional strong reference on the object! */ @inline(__always) public func toUnsafe() -> UnsafeMutableRawPointer { return Unmanaged.passRetained(self).toOpaque() } /** * Casts an unsafe pointer to a `Func_void_CameraResult`. * The pointer has to be a retained opaque `Unmanaged`. * This removes one strong reference from the object! */ @inline(__always) public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_CameraResult { return Unmanaged.fromOpaque(pointer).takeRetainedValue() } } ================================================ FILE: nitrogen/generated/ios/swift/Func_void_CropResult.swift ================================================ /// /// Func_void_CropResult.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Wraps a Swift `(_ result: CropResult) -> Void` as a class. * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. */ public final class Func_void_CropResult { public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift private let closure: (_ result: CropResult) -> Void public init(_ closure: @escaping (_ result: CropResult) -> Void) { self.closure = closure } @inline(__always) public func call(result: CropResult) -> Void { self.closure(result) } /** * Casts this instance to a retained unsafe raw pointer. * This acquires one additional strong reference on the object! */ @inline(__always) public func toUnsafe() -> UnsafeMutableRawPointer { return Unmanaged.passRetained(self).toOpaque() } /** * Casts an unsafe pointer to a `Func_void_CropResult`. * The pointer has to be a retained opaque `Unmanaged`. * This removes one strong reference from the object! */ @inline(__always) public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_CropResult { return Unmanaged.fromOpaque(pointer).takeRetainedValue() } } ================================================ FILE: nitrogen/generated/ios/swift/Func_void_double.swift ================================================ /// /// Func_void_double.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Wraps a Swift `(_ index: Double) -> Void` as a class. * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. */ public final class Func_void_double { public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift private let closure: (_ index: Double) -> Void public init(_ closure: @escaping (_ index: Double) -> Void) { self.closure = closure } @inline(__always) public func call(index: Double) -> Void { self.closure(index) } /** * Casts this instance to a retained unsafe raw pointer. * This acquires one additional strong reference on the object! */ @inline(__always) public func toUnsafe() -> UnsafeMutableRawPointer { return Unmanaged.passRetained(self).toOpaque() } /** * Casts an unsafe pointer to a `Func_void_double`. * The pointer has to be a retained opaque `Unmanaged`. * This removes one strong reference from the object! */ @inline(__always) public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_double { return Unmanaged.fromOpaque(pointer).takeRetainedValue() } } ================================================ FILE: nitrogen/generated/ios/swift/Func_void_std__vector_PickerResult_.swift ================================================ /// /// Func_void_std__vector_PickerResult_.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Wraps a Swift `(_ result: [PickerResult]) -> Void` as a class. * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`. */ public final class Func_void_std__vector_PickerResult_ { public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift private let closure: (_ result: [PickerResult]) -> Void public init(_ closure: @escaping (_ result: [PickerResult]) -> Void) { self.closure = closure } @inline(__always) public func call(result: bridge.std__vector_PickerResult_) -> Void { self.closure(result.map({ __item in __item })) } /** * Casts this instance to a retained unsafe raw pointer. * This acquires one additional strong reference on the object! */ @inline(__always) public func toUnsafe() -> UnsafeMutableRawPointer { return Unmanaged.passRetained(self).toOpaque() } /** * Casts an unsafe pointer to a `Func_void_std__vector_PickerResult_`. * The pointer has to be a retained opaque `Unmanaged`. * This removes one strong reference from the object! */ @inline(__always) public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__vector_PickerResult_ { return Unmanaged.fromOpaque(pointer).takeRetainedValue() } } ================================================ FILE: nitrogen/generated/ios/swift/HybridMultipleImagePickerSpec.swift ================================================ /// /// HybridMultipleImagePickerSpec.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import Foundation import NitroModules /// See ``HybridMultipleImagePickerSpec`` public protocol HybridMultipleImagePickerSpec_protocol: HybridObject { // Properties // Methods func openPicker(config: NitroConfig, resolved: @escaping (_ result: [PickerResult]) -> Void, rejected: @escaping (_ reject: Double) -> Void) throws -> Void func openCrop(image: String, config: NitroCropConfig, resolved: @escaping (_ result: CropResult) -> Void, rejected: @escaping (_ reject: Double) -> Void) throws -> Void func openPreview(media: [MediaPreview], index: Double, config: NitroPreviewConfig, onLongPress: @escaping (_ index: Double) -> Void) throws -> Void func openCamera(config: NitroCameraConfig, resolved: @escaping (_ result: CameraResult) -> Void, rejected: @escaping (_ reject: Double) -> Void) throws -> Void } /// See ``HybridMultipleImagePickerSpec`` public class HybridMultipleImagePickerSpec_base { private weak var cxxWrapper: HybridMultipleImagePickerSpec_cxx? = nil public func getCxxWrapper() -> HybridMultipleImagePickerSpec_cxx { #if DEBUG guard self is HybridMultipleImagePickerSpec else { fatalError("`self` is not a `HybridMultipleImagePickerSpec`! Did you accidentally inherit from `HybridMultipleImagePickerSpec_base` instead of `HybridMultipleImagePickerSpec`?") } #endif if let cxxWrapper = self.cxxWrapper { return cxxWrapper } else { let cxxWrapper = HybridMultipleImagePickerSpec_cxx(self as! HybridMultipleImagePickerSpec) self.cxxWrapper = cxxWrapper return cxxWrapper } } } /** * A Swift base-protocol representing the MultipleImagePicker HybridObject. * Implement this protocol to create Swift-based instances of MultipleImagePicker. * ```swift * class HybridMultipleImagePicker : HybridMultipleImagePickerSpec { * // ... * } * ``` */ public typealias HybridMultipleImagePickerSpec = HybridMultipleImagePickerSpec_protocol & HybridMultipleImagePickerSpec_base ================================================ FILE: nitrogen/generated/ios/swift/HybridMultipleImagePickerSpec_cxx.swift ================================================ /// /// HybridMultipleImagePickerSpec_cxx.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import Foundation import NitroModules /** * A class implementation that bridges HybridMultipleImagePickerSpec over to C++. * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined. * * Also, some Swift types need to be bridged with special handling: * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330) * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++ */ public class HybridMultipleImagePickerSpec_cxx { /** * The Swift <> C++ bridge's namespace (`margelo::nitro::multipleimagepicker::bridge::swift`) * from `MultipleImagePicker-Swift-Cxx-Bridge.hpp`. * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift. */ public typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Holds an instance of the `HybridMultipleImagePickerSpec` Swift protocol. */ private var __implementation: any HybridMultipleImagePickerSpec /** * Holds a weak pointer to the C++ class that wraps the Swift class. */ private var __cxxPart: bridge.std__weak_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ /** * Create a new `HybridMultipleImagePickerSpec_cxx` that wraps the given `HybridMultipleImagePickerSpec`. * All properties and methods bridge to C++ types. */ public init(_ implementation: any HybridMultipleImagePickerSpec) { self.__implementation = implementation self.__cxxPart = .init() /* no base class */ } /** * Get the actual `HybridMultipleImagePickerSpec` instance this class wraps. */ @inline(__always) public func getHybridMultipleImagePickerSpec() -> any HybridMultipleImagePickerSpec { return __implementation } /** * Casts this instance to a retained unsafe raw pointer. * This acquires one additional strong reference on the object! */ public func toUnsafe() -> UnsafeMutableRawPointer { return Unmanaged.passRetained(self).toOpaque() } /** * Casts an unsafe pointer to a `HybridMultipleImagePickerSpec_cxx`. * The pointer has to be a retained opaque `Unmanaged`. * This removes one strong reference from the object! */ public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridMultipleImagePickerSpec_cxx { return Unmanaged.fromOpaque(pointer).takeRetainedValue() } /** * Gets (or creates) the C++ part of this Hybrid Object. * The C++ part is a `std::shared_ptr`. */ public func getCxxPart() -> bridge.std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_ { let cachedCxxPart = self.__cxxPart.lock() if cachedCxxPart.__convertToBool() { return cachedCxxPart } else { let newCxxPart = bridge.create_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(self.toUnsafe()) __cxxPart = bridge.weakify_std__shared_ptr_margelo__nitro__multipleimagepicker__HybridMultipleImagePickerSpec_(newCxxPart) return newCxxPart } } /** * Get the memory size of the Swift class (plus size of any other allocations) * so the JS VM can properly track it and garbage-collect the JS object if needed. */ @inline(__always) public var memorySize: Int { return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize } // Properties // Methods @inline(__always) public final func openPicker(config: NitroConfig, resolved: bridge.Func_void_std__vector_PickerResult_, rejected: bridge.Func_void_double) -> bridge.Result_void_ { do { try self.__implementation.openPicker(config: config, resolved: { () -> ([PickerResult]) -> Void in let __wrappedFunction = bridge.wrap_Func_void_std__vector_PickerResult_(resolved) return { (__result: [PickerResult]) -> Void in __wrappedFunction.call({ () -> bridge.std__vector_PickerResult_ in var __vector = bridge.create_std__vector_PickerResult_(__result.count) for __item in __result { __vector.push_back(__item) } return __vector }()) } }(), rejected: { () -> (Double) -> Void in let __wrappedFunction = bridge.wrap_Func_void_double(rejected) return { (__reject: Double) -> Void in __wrappedFunction.call(__reject) } }()) return bridge.create_Result_void_() } catch (let __error) { let __exceptionPtr = __error.toCpp() return bridge.create_Result_void_(__exceptionPtr) } } @inline(__always) public final func openCrop(image: std.string, config: NitroCropConfig, resolved: bridge.Func_void_CropResult, rejected: bridge.Func_void_double) -> bridge.Result_void_ { do { try self.__implementation.openCrop(image: String(image), config: config, resolved: { () -> (CropResult) -> Void in let __wrappedFunction = bridge.wrap_Func_void_CropResult(resolved) return { (__result: CropResult) -> Void in __wrappedFunction.call(__result) } }(), rejected: { () -> (Double) -> Void in let __wrappedFunction = bridge.wrap_Func_void_double(rejected) return { (__reject: Double) -> Void in __wrappedFunction.call(__reject) } }()) return bridge.create_Result_void_() } catch (let __error) { let __exceptionPtr = __error.toCpp() return bridge.create_Result_void_(__exceptionPtr) } } @inline(__always) public final func openPreview(media: bridge.std__vector_MediaPreview_, index: Double, config: NitroPreviewConfig, onLongPress: bridge.Func_void_double) -> bridge.Result_void_ { do { try self.__implementation.openPreview(media: media.map({ __item in __item }), index: index, config: config, onLongPress: { () -> (Double) -> Void in let __wrappedFunction = bridge.wrap_Func_void_double(onLongPress) return { (__index: Double) -> Void in __wrappedFunction.call(__index) } }()) return bridge.create_Result_void_() } catch (let __error) { let __exceptionPtr = __error.toCpp() return bridge.create_Result_void_(__exceptionPtr) } } @inline(__always) public final func openCamera(config: NitroCameraConfig, resolved: bridge.Func_void_CameraResult, rejected: bridge.Func_void_double) -> bridge.Result_void_ { do { try self.__implementation.openCamera(config: config, resolved: { () -> (CameraResult) -> Void in let __wrappedFunction = bridge.wrap_Func_void_CameraResult(resolved) return { (__result: CameraResult) -> Void in __wrappedFunction.call(__result) } }(), rejected: { () -> (Double) -> Void in let __wrappedFunction = bridge.wrap_Func_void_double(rejected) return { (__reject: Double) -> Void in __wrappedFunction.call(__reject) } }()) return bridge.create_Result_void_() } catch (let __error) { let __exceptionPtr = __error.toCpp() return bridge.create_Result_void_(__exceptionPtr) } } } ================================================ FILE: nitrogen/generated/ios/swift/Language.swift ================================================ /// /// Language.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `Language`, backed by a C++ enum. */ public typealias Language = margelo.nitro.multipleimagepicker.Language public extension Language { /** * Get a Language for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "system": self = .system case "zh-Hans": self = .zhHans case "zh-Hant": self = .zhHant case "ja": self = .ja case "ko": self = .ko case "en": self = .en case "th": self = .th case "id": self = .id case "vi": self = .vi case "ru": self = .ru case "de": self = .de case "fr": self = .fr case "ar": self = .ar default: return nil } } /** * Get the String value this Language represents. */ var stringValue: String { switch self { case .system: return "system" case .zhHans: return "zh-Hans" case .zhHant: return "zh-Hant" case .ja: return "ja" case .ko: return "ko" case .en: return "en" case .th: return "th" case .id: return "id" case .vi: return "vi" case .ru: return "ru" case .de: return "de" case .fr: return "fr" case .ar: return "ar" } } } ================================================ FILE: nitrogen/generated/ios/swift/MediaPreview.swift ================================================ /// /// MediaPreview.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `MediaPreview`, backed by a C++ struct. */ public typealias MediaPreview = margelo.nitro.multipleimagepicker.MediaPreview public extension MediaPreview { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `MediaPreview`. */ init(type: ResultType, path: String?, thumbnail: String?, localIdentifier: String?) { self.init(type, { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = path { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = thumbnail { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = localIdentifier { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }()) } var type: ResultType { @inline(__always) get { return self.__type } @inline(__always) set { self.__type = newValue } } var path: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__path.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__path = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var thumbnail: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__thumbnail.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__thumbnail = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var localIdentifier: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__localIdentifier.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__localIdentifier = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/MediaType.swift ================================================ /// /// MediaType.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `MediaType`, backed by a C++ enum. */ public typealias MediaType = margelo.nitro.multipleimagepicker.MediaType public extension MediaType { /** * Get a MediaType for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "video": self = .video case "image": self = .image case "all": self = .all default: return nil } } /** * Get the String value this MediaType represents. */ var stringValue: String { switch self { case .video: return "video" case .image: return "image" case .all: return "all" } } } ================================================ FILE: nitrogen/generated/ios/swift/NitroCameraConfig.swift ================================================ /// /// NitroCameraConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `NitroCameraConfig`, backed by a C++ struct. */ public typealias NitroCameraConfig = margelo.nitro.multipleimagepicker.NitroCameraConfig public extension NitroCameraConfig { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `NitroCameraConfig`. */ init(mediaType: MediaType, presentation: Presentation, language: Language, crop: PickerCropConfig?, isSaveSystemAlbum: Bool?, color: Double?, cameraDevice: CameraDevice?, videoMaximumDuration: Double?) { self.init(mediaType, presentation, language, { () -> bridge.std__optional_PickerCropConfig_ in if let __unwrappedValue = crop { return bridge.create_std__optional_PickerCropConfig_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = isSaveSystemAlbum { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = color { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_CameraDevice_ in if let __unwrappedValue = cameraDevice { return bridge.create_std__optional_CameraDevice_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = videoMaximumDuration { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }()) } var mediaType: MediaType { @inline(__always) get { return self.__mediaType } @inline(__always) set { self.__mediaType = newValue } } var presentation: Presentation { @inline(__always) get { return self.__presentation } @inline(__always) set { self.__presentation = newValue } } var language: Language { @inline(__always) get { return self.__language } @inline(__always) set { self.__language = newValue } } var crop: PickerCropConfig? { @inline(__always) get { return { () -> PickerCropConfig? in if let __unwrapped = self.__crop.value { return __unwrapped } else { return nil } }() } @inline(__always) set { self.__crop = { () -> bridge.std__optional_PickerCropConfig_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_PickerCropConfig_(__unwrappedValue) } else { return .init() } }() } } var isSaveSystemAlbum: Bool? { @inline(__always) get { return self.__isSaveSystemAlbum.value } @inline(__always) set { self.__isSaveSystemAlbum = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var color: Double? { @inline(__always) get { return self.__color.value } @inline(__always) set { self.__color = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var cameraDevice: CameraDevice? { @inline(__always) get { return self.__cameraDevice.value } @inline(__always) set { self.__cameraDevice = { () -> bridge.std__optional_CameraDevice_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_CameraDevice_(__unwrappedValue) } else { return .init() } }() } } 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() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/NitroConfig.swift ================================================ /// /// NitroConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `NitroConfig`, backed by a C++ struct. */ public typealias NitroConfig = margelo.nitro.multipleimagepicker.NitroConfig public extension NitroConfig { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `NitroConfig`. */ init(mediaType: MediaType, selectedAssets: [PickerResult], 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_PickerResult_ in var __vector = bridge.create_std__vector_PickerResult_(selectedAssets.count) for __item in selectedAssets { __vector.push_back(__item) } return __vector }(), selectBoxStyle, selectMode, { () -> bridge.std__optional_double_ in if let __unwrappedValue = numberOfColumn { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = isPreview { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = primaryColor { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = allowSwipeToSelect { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = spacing { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = isHiddenPreviewButton { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = isHiddenOriginalButton { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = isShowPreviewList { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = allowHapticTouchPreview { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = allowedLimit { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = maxVideo { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = maxSelect { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = maxVideoDuration { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = minVideoDuration { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = maxFileSize { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = backgroundDark { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_PickerCropConfig_ in if let __unwrappedValue = crop { return bridge.create_std__optional_PickerCropConfig_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_Text_ in if let __unwrappedValue = text { return bridge.create_std__optional_Text_(__unwrappedValue) } else { return .init() } }(), 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 { @inline(__always) get { return self.__mediaType } @inline(__always) set { self.__mediaType = newValue } } var selectedAssets: [PickerResult] { @inline(__always) get { return self.__selectedAssets.map({ __item in __item }) } @inline(__always) set { self.__selectedAssets = { () -> bridge.std__vector_PickerResult_ in var __vector = bridge.create_std__vector_PickerResult_(newValue.count) for __item in newValue { __vector.push_back(__item) } return __vector }() } } var selectBoxStyle: SelectBoxStyle { @inline(__always) get { return self.__selectBoxStyle } @inline(__always) set { self.__selectBoxStyle = newValue } } var selectMode: SelectMode { @inline(__always) get { return self.__selectMode } @inline(__always) set { self.__selectMode = newValue } } var numberOfColumn: Double? { @inline(__always) get { return self.__numberOfColumn.value } @inline(__always) set { self.__numberOfColumn = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var isPreview: Bool? { @inline(__always) get { return self.__isPreview.value } @inline(__always) set { self.__isPreview = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var primaryColor: Double? { @inline(__always) get { return self.__primaryColor.value } @inline(__always) set { self.__primaryColor = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var allowSwipeToSelect: Bool? { @inline(__always) get { return self.__allowSwipeToSelect.value } @inline(__always) set { self.__allowSwipeToSelect = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var spacing: Double? { @inline(__always) get { return self.__spacing.value } @inline(__always) set { self.__spacing = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var isHiddenPreviewButton: Bool? { @inline(__always) get { return self.__isHiddenPreviewButton.value } @inline(__always) set { self.__isHiddenPreviewButton = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var isHiddenOriginalButton: Bool? { @inline(__always) get { return self.__isHiddenOriginalButton.value } @inline(__always) set { self.__isHiddenOriginalButton = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var isShowPreviewList: Bool? { @inline(__always) get { return self.__isShowPreviewList.value } @inline(__always) set { self.__isShowPreviewList = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var allowHapticTouchPreview: Bool? { @inline(__always) get { return self.__allowHapticTouchPreview.value } @inline(__always) set { self.__allowHapticTouchPreview = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var allowedLimit: Bool? { @inline(__always) get { return self.__allowedLimit.value } @inline(__always) set { self.__allowedLimit = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var maxVideo: Double? { @inline(__always) get { return self.__maxVideo.value } @inline(__always) set { self.__maxVideo = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var maxSelect: Double? { @inline(__always) get { return self.__maxSelect.value } @inline(__always) set { self.__maxSelect = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var maxVideoDuration: Double? { @inline(__always) get { return self.__maxVideoDuration.value } @inline(__always) set { self.__maxVideoDuration = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var minVideoDuration: Double? { @inline(__always) get { return self.__minVideoDuration.value } @inline(__always) set { self.__minVideoDuration = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var maxFileSize: Double? { @inline(__always) get { return self.__maxFileSize.value } @inline(__always) set { self.__maxFileSize = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var backgroundDark: Double? { @inline(__always) get { return self.__backgroundDark.value } @inline(__always) set { self.__backgroundDark = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var crop: PickerCropConfig? { @inline(__always) get { return { () -> PickerCropConfig? in if let __unwrapped = self.__crop.value { return __unwrapped } else { return nil } }() } @inline(__always) set { self.__crop = { () -> bridge.std__optional_PickerCropConfig_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_PickerCropConfig_(__unwrappedValue) } else { return .init() } }() } } var text: Text? { @inline(__always) get { return { () -> Text? in if let __unwrapped = self.__text.value { return __unwrapped } else { return nil } }() } @inline(__always) set { self.__text = { () -> bridge.std__optional_Text_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_Text_(__unwrappedValue) } else { return .init() } }() } } var language: Language { @inline(__always) get { return self.__language } @inline(__always) set { self.__language = newValue } } var theme: Theme { @inline(__always) get { return self.__theme } @inline(__always) set { self.__theme = newValue } } var presentation: Presentation { @inline(__always) get { return self.__presentation } @inline(__always) set { 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() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/NitroCropConfig.swift ================================================ /// /// NitroCropConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `NitroCropConfig`, backed by a C++ struct. */ public typealias NitroCropConfig = margelo.nitro.multipleimagepicker.NitroCropConfig public extension NitroCropConfig { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `NitroCropConfig`. */ init(language: Language, presentation: Presentation, circle: Bool?, ratio: [CropRatio], defaultRatio: CropRatio?, freeStyle: Bool?) { self.init(language, presentation, { () -> bridge.std__optional_bool_ in if let __unwrappedValue = circle { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__vector_CropRatio_ in var __vector = bridge.create_std__vector_CropRatio_(ratio.count) for __item in ratio { __vector.push_back(__item) } return __vector }(), { () -> bridge.std__optional_CropRatio_ in if let __unwrappedValue = defaultRatio { return bridge.create_std__optional_CropRatio_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = freeStyle { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }()) } var language: Language { @inline(__always) get { return self.__language } @inline(__always) set { self.__language = newValue } } var presentation: Presentation { @inline(__always) get { return self.__presentation } @inline(__always) set { self.__presentation = newValue } } var circle: Bool? { @inline(__always) get { return self.__circle.value } @inline(__always) set { self.__circle = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var ratio: [CropRatio] { @inline(__always) get { return self.__ratio.map({ __item in __item }) } @inline(__always) set { self.__ratio = { () -> bridge.std__vector_CropRatio_ in var __vector = bridge.create_std__vector_CropRatio_(newValue.count) for __item in newValue { __vector.push_back(__item) } return __vector }() } } var defaultRatio: CropRatio? { @inline(__always) get { return { () -> CropRatio? in if let __unwrapped = self.__defaultRatio.value { return __unwrapped } else { return nil } }() } @inline(__always) set { self.__defaultRatio = { () -> bridge.std__optional_CropRatio_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_CropRatio_(__unwrappedValue) } else { return .init() } }() } } var freeStyle: Bool? { @inline(__always) get { return self.__freeStyle.value } @inline(__always) set { self.__freeStyle = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/NitroPreviewConfig.swift ================================================ /// /// NitroPreviewConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `NitroPreviewConfig`, backed by a C++ struct. */ public typealias NitroPreviewConfig = margelo.nitro.multipleimagepicker.NitroPreviewConfig public extension NitroPreviewConfig { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `NitroPreviewConfig`. */ init(language: Language, videoAutoPlay: Bool?) { self.init(language, { () -> bridge.std__optional_bool_ in if let __unwrappedValue = videoAutoPlay { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }()) } var language: Language { @inline(__always) get { return self.__language } @inline(__always) set { self.__language = newValue } } var videoAutoPlay: Bool? { @inline(__always) get { return self.__videoAutoPlay.value } @inline(__always) set { self.__videoAutoPlay = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/PickerCameraConfig.swift ================================================ /// /// PickerCameraConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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({ () -> bridge.std__optional_CameraDevice_ in if let __unwrappedValue = cameraDevice { return bridge.create_std__optional_CameraDevice_(__unwrappedValue) } else { return .init() } }(), { () -> 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.value } @inline(__always) set { self.__cameraDevice = { () -> bridge.std__optional_CameraDevice_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_CameraDevice_(__unwrappedValue) } else { return .init() } }() } } 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() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/PickerCropConfig.swift ================================================ /// /// PickerCropConfig.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `PickerCropConfig`, backed by a C++ struct. */ public typealias PickerCropConfig = margelo.nitro.multipleimagepicker.PickerCropConfig public extension PickerCropConfig { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `PickerCropConfig`. */ init(circle: Bool?, ratio: [CropRatio], defaultRatio: CropRatio?, freeStyle: Bool?) { self.init({ () -> bridge.std__optional_bool_ in if let __unwrappedValue = circle { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__vector_CropRatio_ in var __vector = bridge.create_std__vector_CropRatio_(ratio.count) for __item in ratio { __vector.push_back(__item) } return __vector }(), { () -> bridge.std__optional_CropRatio_ in if let __unwrappedValue = defaultRatio { return bridge.create_std__optional_CropRatio_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = freeStyle { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }()) } var circle: Bool? { @inline(__always) get { return self.__circle.value } @inline(__always) set { self.__circle = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var ratio: [CropRatio] { @inline(__always) get { return self.__ratio.map({ __item in __item }) } @inline(__always) set { self.__ratio = { () -> bridge.std__vector_CropRatio_ in var __vector = bridge.create_std__vector_CropRatio_(newValue.count) for __item in newValue { __vector.push_back(__item) } return __vector }() } } var defaultRatio: CropRatio? { @inline(__always) get { return { () -> CropRatio? in if let __unwrapped = self.__defaultRatio.value { return __unwrapped } else { return nil } }() } @inline(__always) set { self.__defaultRatio = { () -> bridge.std__optional_CropRatio_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_CropRatio_(__unwrappedValue) } else { return .init() } }() } } var freeStyle: Bool? { @inline(__always) get { return self.__freeStyle.value } @inline(__always) set { self.__freeStyle = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/PickerResult.swift ================================================ /// /// PickerResult.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `PickerResult`, backed by a C++ struct. */ public typealias PickerResult = margelo.nitro.multipleimagepicker.PickerResult public extension PickerResult { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `PickerResult`. */ init(localIdentifier: String, width: Double, height: Double, mime: String, size: Double, bucketId: Double?, realPath: String?, parentFolderName: String?, creationDate: Double?, crop: Bool?, path: String, type: ResultType, duration: Double?, thumbnail: String?, fileName: String?) { self.init(std.string(localIdentifier), width, height, std.string(mime), size, { () -> bridge.std__optional_double_ in if let __unwrappedValue = bucketId { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = realPath { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = parentFolderName { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_double_ in if let __unwrappedValue = creationDate { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_bool_ in if let __unwrappedValue = crop { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }(), std.string(path), type, { () -> bridge.std__optional_double_ in if let __unwrappedValue = duration { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = thumbnail { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = fileName { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }()) } var localIdentifier: String { @inline(__always) get { return String(self.__localIdentifier) } @inline(__always) set { self.__localIdentifier = std.string(newValue) } } var width: Double { @inline(__always) get { return self.__width } @inline(__always) set { self.__width = newValue } } var height: Double { @inline(__always) get { return self.__height } @inline(__always) set { self.__height = newValue } } var mime: String { @inline(__always) get { return String(self.__mime) } @inline(__always) set { self.__mime = std.string(newValue) } } var size: Double { @inline(__always) get { return self.__size } @inline(__always) set { self.__size = newValue } } var bucketId: Double? { @inline(__always) get { return self.__bucketId.value } @inline(__always) set { self.__bucketId = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var realPath: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__realPath.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__realPath = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var parentFolderName: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__parentFolderName.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__parentFolderName = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var creationDate: Double? { @inline(__always) get { return self.__creationDate.value } @inline(__always) set { self.__creationDate = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var crop: Bool? { @inline(__always) get { return self.__crop.value } @inline(__always) set { self.__crop = { () -> bridge.std__optional_bool_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_bool_(__unwrappedValue) } else { return .init() } }() } } var path: String { @inline(__always) get { return String(self.__path) } @inline(__always) set { self.__path = std.string(newValue) } } var type: ResultType { @inline(__always) get { return self.__type } @inline(__always) set { self.__type = newValue } } var duration: Double? { @inline(__always) get { return self.__duration.value } @inline(__always) set { self.__duration = { () -> bridge.std__optional_double_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_double_(__unwrappedValue) } else { return .init() } }() } } var thumbnail: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__thumbnail.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__thumbnail = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var fileName: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__fileName.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__fileName = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/Presentation.swift ================================================ /// /// Presentation.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `Presentation`, backed by a C++ enum. */ public typealias Presentation = margelo.nitro.multipleimagepicker.Presentation public extension Presentation { /** * Get a Presentation for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "fullScreenModal": self = .fullscreenmodal case "formSheet": self = .formsheet default: return nil } } /** * Get the String value this Presentation represents. */ var stringValue: String { switch self { case .fullscreenmodal: return "fullScreenModal" case .formsheet: return "formSheet" } } } ================================================ FILE: nitrogen/generated/ios/swift/ResultType.swift ================================================ /// /// ResultType.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `ResultType`, backed by a C++ enum. */ public typealias ResultType = margelo.nitro.multipleimagepicker.ResultType public extension ResultType { /** * Get a ResultType for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "video": self = .video case "image": self = .image default: return nil } } /** * Get the String value this ResultType represents. */ var stringValue: String { switch self { case .video: return "video" case .image: return "image" } } } ================================================ FILE: nitrogen/generated/ios/swift/SelectBoxStyle.swift ================================================ /// /// SelectBoxStyle.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `SelectBoxStyle`, backed by a C++ enum. */ public typealias SelectBoxStyle = margelo.nitro.multipleimagepicker.SelectBoxStyle public extension SelectBoxStyle { /** * Get a SelectBoxStyle for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "number": self = .number case "tick": self = .tick default: return nil } } /** * Get the String value this SelectBoxStyle represents. */ var stringValue: String { switch self { case .number: return "number" case .tick: return "tick" } } } ================================================ FILE: nitrogen/generated/ios/swift/SelectMode.swift ================================================ /// /// SelectMode.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `SelectMode`, backed by a C++ enum. */ public typealias SelectMode = margelo.nitro.multipleimagepicker.SelectMode public extension SelectMode { /** * Get a SelectMode for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "single": self = .single case "multiple": self = .multiple default: return nil } } /** * Get the String value this SelectMode represents. */ var stringValue: String { switch self { case .single: return "single" case .multiple: return "multiple" } } } ================================================ FILE: nitrogen/generated/ios/swift/Text.swift ================================================ /// /// Text.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// import NitroModules /** * Represents an instance of `Text`, backed by a C++ struct. */ public typealias Text = margelo.nitro.multipleimagepicker.Text public extension Text { private typealias bridge = margelo.nitro.multipleimagepicker.bridge.swift /** * Create a new instance of `Text`. */ init(finish: String?, original: String?, preview: String?, edit: String?) { self.init({ () -> bridge.std__optional_std__string_ in if let __unwrappedValue = finish { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = original { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = preview { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }(), { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = edit { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }()) } var finish: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__finish.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__finish = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var original: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__original.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__original = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var preview: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__preview.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__preview = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } var edit: String? { @inline(__always) get { return { () -> String? in if let __unwrapped = self.__edit.value { return String(__unwrapped) } else { return nil } }() } @inline(__always) set { self.__edit = { () -> bridge.std__optional_std__string_ in if let __unwrappedValue = newValue { return bridge.create_std__optional_std__string_(std.string(__unwrappedValue)) } else { return .init() } }() } } } ================================================ FILE: nitrogen/generated/ios/swift/Theme.swift ================================================ /// /// Theme.swift /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// /** * Represents the JS union `Theme`, backed by a C++ enum. */ public typealias Theme = margelo.nitro.multipleimagepicker.Theme public extension Theme { /** * Get a Theme for the given String value, or * return `nil` if the given value was invalid/unknown. */ init?(fromString string: String) { switch string { case "light": self = .light case "dark": self = .dark default: return nil } } /** * Get the String value this Theme represents. */ var stringValue: String { switch self { case .light: return "light" case .dark: return "dark" } } } ================================================ FILE: nitrogen/generated/shared/c++/CameraDevice.hpp ================================================ /// /// CameraDevice.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 final { 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 ================================================ FILE: nitrogen/generated/shared/c++/CameraResult.hpp ================================================ /// /// CameraResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } #include #include "ResultType.hpp" #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (CameraResult). */ struct CameraResult { public: std::string path SWIFT_PRIVATE; ResultType type SWIFT_PRIVATE; std::optional width SWIFT_PRIVATE; std::optional height SWIFT_PRIVATE; std::optional duration SWIFT_PRIVATE; std::optional thumbnail SWIFT_PRIVATE; std::optional fileName SWIFT_PRIVATE; public: CameraResult() = default; explicit CameraResult(std::string path, ResultType type, std::optional width, std::optional height, std::optional duration, std::optional thumbnail, std::optional fileName): path(path), type(type), width(width), height(height), duration(duration), thumbnail(thumbnail), fileName(fileName) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ CameraResult <> JS CameraResult (object) template <> struct JSIConverter final { static inline CameraResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return CameraResult( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "path")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "type")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "width")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "height")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "duration")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "thumbnail")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "fileName")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const CameraResult& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "path", JSIConverter::toJSI(runtime, arg.path)); obj.setProperty(runtime, "type", JSIConverter::toJSI(runtime, arg.type)); obj.setProperty(runtime, "width", JSIConverter>::toJSI(runtime, arg.width)); obj.setProperty(runtime, "height", JSIConverter>::toJSI(runtime, arg.height)); obj.setProperty(runtime, "duration", JSIConverter>::toJSI(runtime, arg.duration)); obj.setProperty(runtime, "thumbnail", JSIConverter>::toJSI(runtime, arg.thumbnail)); obj.setProperty(runtime, "fileName", JSIConverter>::toJSI(runtime, arg.fileName)); 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, "path"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "type"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "duration"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "thumbnail"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "fileName"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/CropRatio.hpp ================================================ /// /// CropRatio.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 #include #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (CropRatio). */ struct CropRatio { public: std::optional title SWIFT_PRIVATE; double width SWIFT_PRIVATE; double height SWIFT_PRIVATE; public: CropRatio() = default; explicit CropRatio(std::optional title, double width, double height): title(title), width(width), height(height) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ CropRatio <> JS CropRatio (object) template <> struct JSIConverter final { static inline CropRatio fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return CropRatio( JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "title")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const CropRatio& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "title", JSIConverter>::toJSI(runtime, arg.title)); obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); 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, "title"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/CropResult.hpp ================================================ /// /// CropResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (CropResult). */ struct CropResult { public: std::string path SWIFT_PRIVATE; double width SWIFT_PRIVATE; double height SWIFT_PRIVATE; public: CropResult() = default; explicit CropResult(std::string path, double width, double height): path(path), width(width), height(height) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ CropResult <> JS CropResult (object) template <> struct JSIConverter final { static inline CropResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return CropResult( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "path")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const CropResult& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "path", JSIConverter::toJSI(runtime, arg.path)); obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); 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, "path"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/HybridMultipleImagePickerSpec.cpp ================================================ /// /// HybridMultipleImagePickerSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #include "HybridMultipleImagePickerSpec.hpp" namespace margelo::nitro::multipleimagepicker { void HybridMultipleImagePickerSpec::loadHybridMethods() { // load base methods/properties HybridObject::loadHybridMethods(); // load custom methods/properties registerHybrids(this, [](Prototype& prototype) { prototype.registerHybridMethod("openPicker", &HybridMultipleImagePickerSpec::openPicker); prototype.registerHybridMethod("openCrop", &HybridMultipleImagePickerSpec::openCrop); prototype.registerHybridMethod("openPreview", &HybridMultipleImagePickerSpec::openPreview); prototype.registerHybridMethod("openCamera", &HybridMultipleImagePickerSpec::openCamera); }); } } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/shared/c++/HybridMultipleImagePickerSpec.hpp ================================================ /// /// HybridMultipleImagePickerSpec.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 Marc Rousavy @ Margelo /// #pragma once #if __has_include() #include #else #error NitroModules cannot be found! Are you sure you installed NitroModules properly? #endif // Forward declaration of `NitroConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroConfig; } // Forward declaration of `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `NitroCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCropConfig; } // Forward declaration of `CropResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropResult; } // Forward declaration of `MediaPreview` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct MediaPreview; } // Forward declaration of `NitroPreviewConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroPreviewConfig; } // Forward declaration of `NitroCameraConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct NitroCameraConfig; } // Forward declaration of `CameraResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CameraResult; } #include "NitroConfig.hpp" #include #include #include "PickerResult.hpp" #include #include "NitroCropConfig.hpp" #include "CropResult.hpp" #include "MediaPreview.hpp" #include "NitroPreviewConfig.hpp" #include "NitroCameraConfig.hpp" #include "CameraResult.hpp" namespace margelo::nitro::multipleimagepicker { using namespace margelo::nitro; /** * An abstract base class for `MultipleImagePicker` * Inherit this class to create instances of `HybridMultipleImagePickerSpec` in C++. * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. * @example * ```cpp * class HybridMultipleImagePicker: public HybridMultipleImagePickerSpec { * public: * HybridMultipleImagePicker(...): HybridObject(TAG) { ... } * // ... * }; * ``` */ class HybridMultipleImagePickerSpec: public virtual HybridObject { public: // Constructor explicit HybridMultipleImagePickerSpec(): HybridObject(TAG) { } // Destructor ~HybridMultipleImagePickerSpec() override = default; public: // Properties public: // Methods virtual void openPicker(const NitroConfig& config, const std::function& /* result */)>& resolved, const std::function& rejected) = 0; virtual void openCrop(const std::string& image, const NitroCropConfig& config, const std::function& resolved, const std::function& rejected) = 0; virtual void openPreview(const std::vector& media, double index, const NitroPreviewConfig& config, const std::function& onLongPress) = 0; virtual void openCamera(const NitroCameraConfig& config, const std::function& resolved, const std::function& rejected) = 0; protected: // Hybrid Setup void loadHybridMethods() override; protected: // Tag for logging static constexpr auto TAG = "MultipleImagePicker"; }; } // namespace margelo::nitro::multipleimagepicker ================================================ FILE: nitrogen/generated/shared/c++/Language.hpp ================================================ /// /// Language.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (Language). */ enum class Language { SYSTEM SWIFT_NAME(system) = 0, ZH_HANS SWIFT_NAME(zhHans) = 1, ZH_HANT SWIFT_NAME(zhHant) = 2, JA SWIFT_NAME(ja) = 3, KO SWIFT_NAME(ko) = 4, EN SWIFT_NAME(en) = 5, TH SWIFT_NAME(th) = 6, ID SWIFT_NAME(id) = 7, VI SWIFT_NAME(vi) = 8, RU SWIFT_NAME(ru) = 9, DE SWIFT_NAME(de) = 10, FR SWIFT_NAME(fr) = 11, AR SWIFT_NAME(ar) = 12, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ Language <> JS Language (union) template <> struct JSIConverter final { static inline Language fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("system"): return Language::SYSTEM; case hashString("zh-Hans"): return Language::ZH_HANS; case hashString("zh-Hant"): return Language::ZH_HANT; case hashString("ja"): return Language::JA; case hashString("ko"): return Language::KO; case hashString("en"): return Language::EN; case hashString("th"): return Language::TH; case hashString("id"): return Language::ID; case hashString("vi"): return Language::VI; case hashString("ru"): return Language::RU; case hashString("de"): return Language::DE; case hashString("fr"): return Language::FR; case hashString("ar"): return Language::AR; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum Language - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, Language arg) { switch (arg) { case Language::SYSTEM: return JSIConverter::toJSI(runtime, "system"); case Language::ZH_HANS: return JSIConverter::toJSI(runtime, "zh-Hans"); case Language::ZH_HANT: return JSIConverter::toJSI(runtime, "zh-Hant"); case Language::JA: return JSIConverter::toJSI(runtime, "ja"); case Language::KO: return JSIConverter::toJSI(runtime, "ko"); case Language::EN: return JSIConverter::toJSI(runtime, "en"); case Language::TH: return JSIConverter::toJSI(runtime, "th"); case Language::ID: return JSIConverter::toJSI(runtime, "id"); case Language::VI: return JSIConverter::toJSI(runtime, "vi"); case Language::RU: return JSIConverter::toJSI(runtime, "ru"); case Language::DE: return JSIConverter::toJSI(runtime, "de"); case Language::FR: return JSIConverter::toJSI(runtime, "fr"); case Language::AR: return JSIConverter::toJSI(runtime, "ar"); default: [[unlikely]] throw std::invalid_argument("Cannot convert Language 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("system"): case hashString("zh-Hans"): case hashString("zh-Hant"): case hashString("ja"): case hashString("ko"): case hashString("en"): case hashString("th"): case hashString("id"): case hashString("vi"): case hashString("ru"): case hashString("de"): case hashString("fr"): case hashString("ar"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/MediaPreview.hpp ================================================ /// /// MediaPreview.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } #include "ResultType.hpp" #include #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (MediaPreview). */ struct MediaPreview { public: ResultType type SWIFT_PRIVATE; std::optional path SWIFT_PRIVATE; std::optional thumbnail SWIFT_PRIVATE; std::optional localIdentifier SWIFT_PRIVATE; public: MediaPreview() = default; explicit MediaPreview(ResultType type, std::optional path, std::optional thumbnail, std::optional localIdentifier): type(type), path(path), thumbnail(thumbnail), localIdentifier(localIdentifier) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ MediaPreview <> JS MediaPreview (object) template <> struct JSIConverter final { static inline MediaPreview fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return MediaPreview( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "type")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "path")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "thumbnail")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "localIdentifier")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const MediaPreview& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "type", JSIConverter::toJSI(runtime, arg.type)); obj.setProperty(runtime, "path", JSIConverter>::toJSI(runtime, arg.path)); obj.setProperty(runtime, "thumbnail", JSIConverter>::toJSI(runtime, arg.thumbnail)); obj.setProperty(runtime, "localIdentifier", JSIConverter>::toJSI(runtime, arg.localIdentifier)); 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, "type"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "path"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "thumbnail"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "localIdentifier"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/MediaType.hpp ================================================ /// /// MediaType.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (MediaType). */ enum class MediaType { VIDEO SWIFT_NAME(video) = 0, IMAGE SWIFT_NAME(image) = 1, ALL SWIFT_NAME(all) = 2, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ MediaType <> JS MediaType (union) template <> struct JSIConverter final { static inline MediaType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("video"): return MediaType::VIDEO; case hashString("image"): return MediaType::IMAGE; case hashString("all"): return MediaType::ALL; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum MediaType - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, MediaType arg) { switch (arg) { case MediaType::VIDEO: return JSIConverter::toJSI(runtime, "video"); case MediaType::IMAGE: return JSIConverter::toJSI(runtime, "image"); case MediaType::ALL: return JSIConverter::toJSI(runtime, "all"); default: [[unlikely]] throw std::invalid_argument("Cannot convert MediaType 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("video"): case hashString("image"): case hashString("all"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/NitroCameraConfig.hpp ================================================ /// /// NitroCameraConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `MediaType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class MediaType; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } // Forward declaration of `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `CameraDevice` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class CameraDevice; } #include "MediaType.hpp" #include "Presentation.hpp" #include "Language.hpp" #include #include "PickerCropConfig.hpp" #include "CameraDevice.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (NitroCameraConfig). */ struct NitroCameraConfig { public: MediaType mediaType SWIFT_PRIVATE; Presentation presentation SWIFT_PRIVATE; Language language SWIFT_PRIVATE; std::optional crop SWIFT_PRIVATE; std::optional isSaveSystemAlbum SWIFT_PRIVATE; std::optional color SWIFT_PRIVATE; std::optional cameraDevice SWIFT_PRIVATE; std::optional videoMaximumDuration SWIFT_PRIVATE; public: NitroCameraConfig() = default; explicit NitroCameraConfig(MediaType mediaType, Presentation presentation, Language language, std::optional crop, std::optional isSaveSystemAlbum, std::optional color, std::optional cameraDevice, std::optional videoMaximumDuration): mediaType(mediaType), presentation(presentation), language(language), crop(crop), isSaveSystemAlbum(isSaveSystemAlbum), color(color), cameraDevice(cameraDevice), videoMaximumDuration(videoMaximumDuration) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ NitroCameraConfig <> JS NitroCameraConfig (object) template <> struct JSIConverter final { static inline NitroCameraConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return NitroCameraConfig( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "mediaType")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "presentation")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "language")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "crop")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isSaveSystemAlbum")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "color")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "cameraDevice")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "videoMaximumDuration")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const NitroCameraConfig& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "mediaType", JSIConverter::toJSI(runtime, arg.mediaType)); obj.setProperty(runtime, "presentation", JSIConverter::toJSI(runtime, arg.presentation)); obj.setProperty(runtime, "language", JSIConverter::toJSI(runtime, arg.language)); obj.setProperty(runtime, "crop", JSIConverter>::toJSI(runtime, arg.crop)); obj.setProperty(runtime, "isSaveSystemAlbum", JSIConverter>::toJSI(runtime, arg.isSaveSystemAlbum)); obj.setProperty(runtime, "color", JSIConverter>::toJSI(runtime, arg.color)); 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, "mediaType"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "presentation"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "language"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "crop"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isSaveSystemAlbum"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "color"))) return false; 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 ================================================ FILE: nitrogen/generated/shared/c++/NitroConfig.hpp ================================================ /// /// NitroConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `MediaType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class MediaType; } // Forward declaration of `PickerResult` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerResult; } // Forward declaration of `SelectBoxStyle` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectBoxStyle; } // Forward declaration of `SelectMode` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class SelectMode; } // Forward declaration of `PickerCropConfig` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct PickerCropConfig; } // Forward declaration of `Text` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct Text; } // Forward declaration of `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `Theme` to properly resolve imports. 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 #include "PickerResult.hpp" #include "SelectBoxStyle.hpp" #include "SelectMode.hpp" #include #include "PickerCropConfig.hpp" #include "Text.hpp" #include "Language.hpp" #include "Theme.hpp" #include "Presentation.hpp" #include "PickerCameraConfig.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (NitroConfig). */ struct NitroConfig { public: MediaType mediaType SWIFT_PRIVATE; std::vector selectedAssets SWIFT_PRIVATE; SelectBoxStyle selectBoxStyle SWIFT_PRIVATE; SelectMode selectMode SWIFT_PRIVATE; std::optional numberOfColumn SWIFT_PRIVATE; std::optional isPreview SWIFT_PRIVATE; std::optional primaryColor SWIFT_PRIVATE; std::optional allowSwipeToSelect SWIFT_PRIVATE; std::optional spacing SWIFT_PRIVATE; std::optional isHiddenPreviewButton SWIFT_PRIVATE; std::optional isHiddenOriginalButton SWIFT_PRIVATE; std::optional isShowPreviewList SWIFT_PRIVATE; std::optional allowHapticTouchPreview SWIFT_PRIVATE; std::optional allowedLimit SWIFT_PRIVATE; std::optional maxVideo SWIFT_PRIVATE; std::optional maxSelect SWIFT_PRIVATE; std::optional maxVideoDuration SWIFT_PRIVATE; std::optional minVideoDuration SWIFT_PRIVATE; std::optional maxFileSize SWIFT_PRIVATE; std::optional backgroundDark SWIFT_PRIVATE; std::optional crop SWIFT_PRIVATE; std::optional text SWIFT_PRIVATE; Language language SWIFT_PRIVATE; Theme theme SWIFT_PRIVATE; Presentation presentation SWIFT_PRIVATE; std::optional camera SWIFT_PRIVATE; public: NitroConfig() = default; 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 namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ NitroConfig <> JS NitroConfig (object) template <> struct JSIConverter final { static inline NitroConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return NitroConfig( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "mediaType")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "selectedAssets")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "selectBoxStyle")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "selectMode")), 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, "allowSwipeToSelect")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "spacing")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isHiddenPreviewButton")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isHiddenOriginalButton")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "isShowPreviewList")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "allowHapticTouchPreview")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "allowedLimit")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxVideo")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxSelect")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxVideoDuration")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "minVideoDuration")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "maxFileSize")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "backgroundDark")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "crop")), 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, "camera")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const NitroConfig& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "mediaType", JSIConverter::toJSI(runtime, arg.mediaType)); obj.setProperty(runtime, "selectedAssets", JSIConverter>::toJSI(runtime, arg.selectedAssets)); obj.setProperty(runtime, "selectBoxStyle", JSIConverter::toJSI(runtime, arg.selectBoxStyle)); obj.setProperty(runtime, "selectMode", JSIConverter::toJSI(runtime, arg.selectMode)); 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, "allowSwipeToSelect", JSIConverter>::toJSI(runtime, arg.allowSwipeToSelect)); obj.setProperty(runtime, "spacing", JSIConverter>::toJSI(runtime, arg.spacing)); obj.setProperty(runtime, "isHiddenPreviewButton", JSIConverter>::toJSI(runtime, arg.isHiddenPreviewButton)); obj.setProperty(runtime, "isHiddenOriginalButton", JSIConverter>::toJSI(runtime, arg.isHiddenOriginalButton)); obj.setProperty(runtime, "isShowPreviewList", JSIConverter>::toJSI(runtime, arg.isShowPreviewList)); obj.setProperty(runtime, "allowHapticTouchPreview", JSIConverter>::toJSI(runtime, arg.allowHapticTouchPreview)); obj.setProperty(runtime, "allowedLimit", JSIConverter>::toJSI(runtime, arg.allowedLimit)); obj.setProperty(runtime, "maxVideo", JSIConverter>::toJSI(runtime, arg.maxVideo)); obj.setProperty(runtime, "maxSelect", JSIConverter>::toJSI(runtime, arg.maxSelect)); obj.setProperty(runtime, "maxVideoDuration", JSIConverter>::toJSI(runtime, arg.maxVideoDuration)); obj.setProperty(runtime, "minVideoDuration", JSIConverter>::toJSI(runtime, arg.minVideoDuration)); obj.setProperty(runtime, "maxFileSize", JSIConverter>::toJSI(runtime, arg.maxFileSize)); obj.setProperty(runtime, "backgroundDark", JSIConverter>::toJSI(runtime, arg.backgroundDark)); obj.setProperty(runtime, "crop", JSIConverter>::toJSI(runtime, arg.crop)); obj.setProperty(runtime, "text", JSIConverter>::toJSI(runtime, arg.text)); 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) { if (!value.isObject()) { return false; } jsi::Object obj = value.getObject(runtime); if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "mediaType"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "selectedAssets"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "selectBoxStyle"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "selectMode"))) return false; 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, "allowSwipeToSelect"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "spacing"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isHiddenPreviewButton"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isHiddenOriginalButton"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "isShowPreviewList"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "allowHapticTouchPreview"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "allowedLimit"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxVideo"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxSelect"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxVideoDuration"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "minVideoDuration"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "maxFileSize"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "backgroundDark"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "crop"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "text"))) return false; 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; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/NitroCropConfig.hpp ================================================ /// /// NitroCropConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } // Forward declaration of `Presentation` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Presentation; } // Forward declaration of `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } #include "Language.hpp" #include "Presentation.hpp" #include #include #include "CropRatio.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (NitroCropConfig). */ struct NitroCropConfig { public: Language language SWIFT_PRIVATE; Presentation presentation SWIFT_PRIVATE; std::optional circle SWIFT_PRIVATE; std::vector ratio SWIFT_PRIVATE; std::optional defaultRatio SWIFT_PRIVATE; std::optional freeStyle SWIFT_PRIVATE; public: NitroCropConfig() = default; explicit NitroCropConfig(Language language, Presentation presentation, std::optional circle, std::vector ratio, std::optional defaultRatio, std::optional freeStyle): language(language), presentation(presentation), circle(circle), ratio(ratio), defaultRatio(defaultRatio), freeStyle(freeStyle) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ NitroCropConfig <> JS NitroCropConfig (object) template <> struct JSIConverter final { static inline NitroCropConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return NitroCropConfig( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "language")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "presentation")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "circle")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "ratio")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "defaultRatio")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "freeStyle")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const NitroCropConfig& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "language", JSIConverter::toJSI(runtime, arg.language)); obj.setProperty(runtime, "presentation", JSIConverter::toJSI(runtime, arg.presentation)); obj.setProperty(runtime, "circle", JSIConverter>::toJSI(runtime, arg.circle)); obj.setProperty(runtime, "ratio", JSIConverter>::toJSI(runtime, arg.ratio)); obj.setProperty(runtime, "defaultRatio", JSIConverter>::toJSI(runtime, arg.defaultRatio)); obj.setProperty(runtime, "freeStyle", JSIConverter>::toJSI(runtime, arg.freeStyle)); 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, "language"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "presentation"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "circle"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "ratio"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "defaultRatio"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "freeStyle"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/NitroPreviewConfig.hpp ================================================ /// /// NitroPreviewConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `Language` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class Language; } #include "Language.hpp" #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (NitroPreviewConfig). */ struct NitroPreviewConfig { public: Language language SWIFT_PRIVATE; std::optional videoAutoPlay SWIFT_PRIVATE; public: NitroPreviewConfig() = default; explicit NitroPreviewConfig(Language language, std::optional videoAutoPlay): language(language), videoAutoPlay(videoAutoPlay) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ NitroPreviewConfig <> JS NitroPreviewConfig (object) template <> struct JSIConverter final { static inline NitroPreviewConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return NitroPreviewConfig( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "language")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "videoAutoPlay")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const NitroPreviewConfig& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "language", JSIConverter::toJSI(runtime, arg.language)); obj.setProperty(runtime, "videoAutoPlay", JSIConverter>::toJSI(runtime, arg.videoAutoPlay)); 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, "language"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "videoAutoPlay"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/PickerCameraConfig.hpp ================================================ /// /// PickerCameraConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 #include "CameraDevice.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (PickerCameraConfig). */ struct PickerCameraConfig { public: std::optional cameraDevice SWIFT_PRIVATE; std::optional videoMaximumDuration SWIFT_PRIVATE; public: PickerCameraConfig() = default; explicit PickerCameraConfig(std::optional 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 final { 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 ================================================ FILE: nitrogen/generated/shared/c++/PickerCropConfig.hpp ================================================ /// /// PickerCropConfig.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `CropRatio` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { struct CropRatio; } #include #include #include "CropRatio.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (PickerCropConfig). */ struct PickerCropConfig { public: std::optional circle SWIFT_PRIVATE; std::vector ratio SWIFT_PRIVATE; std::optional defaultRatio SWIFT_PRIVATE; std::optional freeStyle SWIFT_PRIVATE; public: PickerCropConfig() = default; explicit PickerCropConfig(std::optional circle, std::vector ratio, std::optional defaultRatio, std::optional freeStyle): circle(circle), ratio(ratio), defaultRatio(defaultRatio), freeStyle(freeStyle) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ PickerCropConfig <> JS PickerCropConfig (object) template <> struct JSIConverter final { static inline PickerCropConfig fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return PickerCropConfig( JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "circle")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "ratio")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "defaultRatio")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "freeStyle")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const PickerCropConfig& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "circle", JSIConverter>::toJSI(runtime, arg.circle)); obj.setProperty(runtime, "ratio", JSIConverter>::toJSI(runtime, arg.ratio)); obj.setProperty(runtime, "defaultRatio", JSIConverter>::toJSI(runtime, arg.defaultRatio)); obj.setProperty(runtime, "freeStyle", JSIConverter>::toJSI(runtime, arg.freeStyle)); 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, "circle"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "ratio"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "defaultRatio"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "freeStyle"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/PickerResult.hpp ================================================ /// /// PickerResult.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 `ResultType` to properly resolve imports. namespace margelo::nitro::multipleimagepicker { enum class ResultType; } #include #include #include "ResultType.hpp" namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (PickerResult). */ struct PickerResult { public: std::string localIdentifier SWIFT_PRIVATE; double width SWIFT_PRIVATE; double height SWIFT_PRIVATE; std::string mime SWIFT_PRIVATE; double size SWIFT_PRIVATE; std::optional bucketId SWIFT_PRIVATE; std::optional realPath SWIFT_PRIVATE; std::optional parentFolderName SWIFT_PRIVATE; std::optional creationDate SWIFT_PRIVATE; std::optional crop SWIFT_PRIVATE; std::string path SWIFT_PRIVATE; ResultType type SWIFT_PRIVATE; std::optional duration SWIFT_PRIVATE; std::optional thumbnail SWIFT_PRIVATE; std::optional fileName SWIFT_PRIVATE; public: PickerResult() = default; explicit PickerResult(std::string localIdentifier, double width, double height, std::string mime, double size, std::optional bucketId, std::optional realPath, std::optional parentFolderName, std::optional creationDate, std::optional crop, std::string path, ResultType type, std::optional duration, std::optional thumbnail, std::optional fileName): localIdentifier(localIdentifier), width(width), height(height), mime(mime), size(size), bucketId(bucketId), realPath(realPath), parentFolderName(parentFolderName), creationDate(creationDate), crop(crop), path(path), type(type), duration(duration), thumbnail(thumbnail), fileName(fileName) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ PickerResult <> JS PickerResult (object) template <> struct JSIConverter final { static inline PickerResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return PickerResult( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "localIdentifier")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "width")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "height")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "mime")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "size")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "bucketId")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "realPath")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "parentFolderName")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "creationDate")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "crop")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "path")), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, "type")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "duration")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "thumbnail")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "fileName")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const PickerResult& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "localIdentifier", JSIConverter::toJSI(runtime, arg.localIdentifier)); obj.setProperty(runtime, "width", JSIConverter::toJSI(runtime, arg.width)); obj.setProperty(runtime, "height", JSIConverter::toJSI(runtime, arg.height)); obj.setProperty(runtime, "mime", JSIConverter::toJSI(runtime, arg.mime)); obj.setProperty(runtime, "size", JSIConverter::toJSI(runtime, arg.size)); obj.setProperty(runtime, "bucketId", JSIConverter>::toJSI(runtime, arg.bucketId)); obj.setProperty(runtime, "realPath", JSIConverter>::toJSI(runtime, arg.realPath)); obj.setProperty(runtime, "parentFolderName", JSIConverter>::toJSI(runtime, arg.parentFolderName)); obj.setProperty(runtime, "creationDate", JSIConverter>::toJSI(runtime, arg.creationDate)); obj.setProperty(runtime, "crop", JSIConverter>::toJSI(runtime, arg.crop)); obj.setProperty(runtime, "path", JSIConverter::toJSI(runtime, arg.path)); obj.setProperty(runtime, "type", JSIConverter::toJSI(runtime, arg.type)); obj.setProperty(runtime, "duration", JSIConverter>::toJSI(runtime, arg.duration)); obj.setProperty(runtime, "thumbnail", JSIConverter>::toJSI(runtime, arg.thumbnail)); obj.setProperty(runtime, "fileName", JSIConverter>::toJSI(runtime, arg.fileName)); 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, "localIdentifier"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "width"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "height"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "mime"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "size"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "bucketId"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "realPath"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "parentFolderName"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "creationDate"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "crop"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "path"))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, "type"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "duration"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "thumbnail"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "fileName"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/Presentation.hpp ================================================ /// /// Presentation.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (Presentation). */ enum class Presentation { FULLSCREENMODAL SWIFT_NAME(fullscreenmodal) = 0, FORMSHEET SWIFT_NAME(formsheet) = 1, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ Presentation <> JS Presentation (union) template <> struct JSIConverter final { static inline Presentation fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("fullScreenModal"): return Presentation::FULLSCREENMODAL; case hashString("formSheet"): return Presentation::FORMSHEET; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum Presentation - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, Presentation arg) { switch (arg) { case Presentation::FULLSCREENMODAL: return JSIConverter::toJSI(runtime, "fullScreenModal"); case Presentation::FORMSHEET: return JSIConverter::toJSI(runtime, "formSheet"); default: [[unlikely]] throw std::invalid_argument("Cannot convert Presentation 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("fullScreenModal"): case hashString("formSheet"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/ResultType.hpp ================================================ /// /// ResultType.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (ResultType). */ enum class ResultType { VIDEO SWIFT_NAME(video) = 0, IMAGE SWIFT_NAME(image) = 1, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ ResultType <> JS ResultType (union) template <> struct JSIConverter final { static inline ResultType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("video"): return ResultType::VIDEO; case hashString("image"): return ResultType::IMAGE; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum ResultType - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, ResultType arg) { switch (arg) { case ResultType::VIDEO: return JSIConverter::toJSI(runtime, "video"); case ResultType::IMAGE: return JSIConverter::toJSI(runtime, "image"); default: [[unlikely]] throw std::invalid_argument("Cannot convert ResultType 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("video"): case hashString("image"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/SelectBoxStyle.hpp ================================================ /// /// SelectBoxStyle.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (SelectBoxStyle). */ enum class SelectBoxStyle { NUMBER SWIFT_NAME(number) = 0, TICK SWIFT_NAME(tick) = 1, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ SelectBoxStyle <> JS SelectBoxStyle (union) template <> struct JSIConverter final { static inline SelectBoxStyle fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("number"): return SelectBoxStyle::NUMBER; case hashString("tick"): return SelectBoxStyle::TICK; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum SelectBoxStyle - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, SelectBoxStyle arg) { switch (arg) { case SelectBoxStyle::NUMBER: return JSIConverter::toJSI(runtime, "number"); case SelectBoxStyle::TICK: return JSIConverter::toJSI(runtime, "tick"); default: [[unlikely]] throw std::invalid_argument("Cannot convert SelectBoxStyle 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("number"): case hashString("tick"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/SelectMode.hpp ================================================ /// /// SelectMode.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (SelectMode). */ enum class SelectMode { SINGLE SWIFT_NAME(single) = 0, MULTIPLE SWIFT_NAME(multiple) = 1, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ SelectMode <> JS SelectMode (union) template <> struct JSIConverter final { static inline SelectMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("single"): return SelectMode::SINGLE; case hashString("multiple"): return SelectMode::MULTIPLE; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum SelectMode - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, SelectMode arg) { switch (arg) { case SelectMode::SINGLE: return JSIConverter::toJSI(runtime, "single"); case SelectMode::MULTIPLE: return JSIConverter::toJSI(runtime, "multiple"); default: [[unlikely]] throw std::invalid_argument("Cannot convert SelectMode 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("single"): case hashString("multiple"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/Text.hpp ================================================ /// /// Text.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 #include #include namespace margelo::nitro::multipleimagepicker { /** * A struct which can be represented as a JavaScript object (Text). */ struct Text { public: std::optional finish SWIFT_PRIVATE; std::optional original SWIFT_PRIVATE; std::optional preview SWIFT_PRIVATE; std::optional edit SWIFT_PRIVATE; public: Text() = default; explicit Text(std::optional finish, std::optional original, std::optional preview, std::optional edit): finish(finish), original(original), preview(preview), edit(edit) {} }; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ Text <> JS Text (object) template <> struct JSIConverter final { static inline Text fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); return Text( JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "finish")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "original")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "preview")), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "edit")) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const Text& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, "finish", JSIConverter>::toJSI(runtime, arg.finish)); obj.setProperty(runtime, "original", JSIConverter>::toJSI(runtime, arg.original)); obj.setProperty(runtime, "preview", JSIConverter>::toJSI(runtime, arg.preview)); obj.setProperty(runtime, "edit", JSIConverter>::toJSI(runtime, arg.edit)); 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, "finish"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "original"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "preview"))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "edit"))) return false; return true; } }; } // namespace margelo::nitro ================================================ FILE: nitrogen/generated/shared/c++/Theme.hpp ================================================ /// /// Theme.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/mrousavy/nitro /// Copyright © 2025 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 (Theme). */ enum class Theme { LIGHT SWIFT_NAME(light) = 0, DARK SWIFT_NAME(dark) = 1, } CLOSED_ENUM; } // namespace margelo::nitro::multipleimagepicker namespace margelo::nitro { using namespace margelo::nitro::multipleimagepicker; // C++ Theme <> JS Theme (union) template <> struct JSIConverter final { static inline Theme fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { std::string unionValue = JSIConverter::fromJSI(runtime, arg); switch (hashString(unionValue.c_str(), unionValue.size())) { case hashString("light"): return Theme::LIGHT; case hashString("dark"): return Theme::DARK; default: [[unlikely]] throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum Theme - invalid value!"); } } static inline jsi::Value toJSI(jsi::Runtime& runtime, Theme arg) { switch (arg) { case Theme::LIGHT: return JSIConverter::toJSI(runtime, "light"); case Theme::DARK: return JSIConverter::toJSI(runtime, "dark"); default: [[unlikely]] throw std::invalid_argument("Cannot convert Theme 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("light"): case hashString("dark"): return true; default: return false; } } }; } // namespace margelo::nitro ================================================ FILE: package.json ================================================ { "name": "@baronha/react-native-multiple-image-picker", "version": "2.2.5", "description": "� react-native-multiple-image-picker enables applications to pick images and videos from multiple smart albums in iOS/Android �", "main": "./lib/commonjs/index.js", "module": "./lib/module/index.js", "types": "./lib/typescript/index.d.ts", "react-native": "src/index", "source": "src/index", "files": [ "src", "nitrogen", "react-native.config.js", "lib", "android/build.gradle", "android/gradle.properties", "android/CMakeLists.txt", "android/src", "ios/**/*.h", "ios/**/*.m", "ios/**/*.mm", "ios/**/*.cpp", "ios/**/*.swift", "ios/Assets.xcassets", "app.plugin.js", "*.podspec", "README.md" ], "scripts": { "typecheck": "tsc --project tsconfig.build.json --noEmit", "clean": "rm -rf android/build node_modules/**/android/build lib", "lint": "eslint \"**/*.{js,ts,tsx}\" --fix", "lint-ci": "eslint \"**/*.{js,ts,tsx}\" -f @jamesacarr/github-actions", "typescript": "tsc --noEmit false", "specs": "bun run --filter=\"**\" typescript && bun nitro-codegen --logLevel=\"debug\"", "nitro": "yarn nitro-codegen", "example": "yarn --cwd MultipleImagePickerExample", "pod": "cd MultipleImagePickerExample && pod-install --quiet", "bootstrap": "yarn example && yarn && yarn pod", "prepare": "bob build" }, "keywords": [ "react-native", "ios", "android" ], "repository": { "type": "git", "url": "git+https://github.com/NitrogenZLab/react-native-multiple-image-picker.git" }, "author": "Bảo Hà. (https://github.com/baronha)", "license": "MIT", "bugs": { "url": "https://github.com/NitrogenZLab/react-native-multiple-image-picker/issues" }, "homepage": "https://github.com/NitrogenZLab/react-native-multiple-image-picker#readme", "publishConfig": { "registry": "https://registry.npmjs.org/" }, "devDependencies": { "@react-native/eslint-config": "^0.75.2", "@types/jest": "^29.5.12", "@types/react": "^18.3.4", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", "nitro-codegen": "0.25.2", "prettier": "^3.3.3", "react": "^18.3.1", "react-native": "^0.75.2", "react-native-builder-bob": "^0.30.0", "react-native-nitro-modules": "0.25.2", "typescript": "^5.5.4" }, "peerDependencies": { "react": "*", "react-native": "*" }, "eslintConfig": { "root": true, "extends": [ "@react-native", "prettier" ], "plugins": [ "prettier" ], "rules": { "prettier/prettier": [ "warn", { "quoteProps": "consistent", "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "useTabs": false } ] } }, "eslintIgnore": [ "node_modules/", "lib/" ], "prettier": { "quoteProps": "consistent", "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "useTabs": false, "semi": false }, "react-native-builder-bob": { "source": "src", "output": "lib", "targets": [ "commonjs", "module", [ "typescript", { "project": "tsconfig.build.json" } ] ] }, "packageManager": "yarn@1.22.22" } ================================================ FILE: react-native.config.js ================================================ // https://github.com/react-native-community/cli/blob/main/docs/dependencies.md module.exports = { dependency: { platforms: { /** * @type {import('@react-native-community/cli-types').IOSDependencyParams} */ ios: {}, /** * @type {import('@react-native-community/cli-types').AndroidDependencyParams} */ android: {}, }, }, } ================================================ FILE: scripts/bootstrap.js ================================================ const path = require('path'); const child_process = require('child_process'); const root = path.resolve(__dirname, '..'); const args = process.argv.slice(2); const options = { cwd: process.cwd(), env: process.env, stdio: 'inherit', encoding: 'utf-8', }; let result; if (process.cwd() !== root || args.length) { // We're not in the root of the project, or additional arguments were passed // In this case, forward the command to `yarn` result = child_process.spawnSync('yarn', args, options); } else { // If `yarn` is run without arguments, perform bootstrap result = child_process.spawnSync('yarn', ['bootstrap'], options); } process.exitCode = result.status; ================================================ FILE: src/index.ts ================================================ export * from './specs/MultipleImagePicker.nitro' export * from './types' import { NitroModules } from 'react-native-nitro-modules' import { type MultipleImagePicker } from './specs/MultipleImagePicker.nitro' import { processColor, Appearance } from 'react-native' import { PickerResult, Config, NitroConfig, CropResult, CropConfig, NitroCropConfig, PreviewConfig, NitroPreviewConfig, MediaPreview, CameraConfig, NitroCameraConfig, CameraResult, Language, } from './types' import { CropReject, CameraError } from './types/error' const Picker = NitroModules.createHybridObject( 'MultipleImagePicker' ) type IPromisePicker = T['selectMode'] extends 'single' ? PickerResult : PickerResult[] export async function openPicker( conf: T ): Promise> { return new Promise((resolved, rejected) => { const config = { ...defaultOptions, ...conf } as NitroConfig config.primaryColor = processColor(config.primaryColor) as any config.backgroundDark = processColor(config.backgroundDark) as any if ((config as Config)?.theme === 'system') { const theme = Appearance.getColorScheme() ?? 'light' config.theme = theme } config.language = validateLanguage(config.language) if (typeof config.crop === 'boolean') { config.crop = config.crop ? { ratio: [] } : undefined } if (config.crop) config.crop.ratio = config.crop?.ratio ?? [] return Picker.openPicker( config, (result: PickerResult[]) => { resolved(result as IPromisePicker) }, (reject: number) => { rejected(reject) } ) }) } export async function openCropper( image: string, config?: CropConfig ): Promise { return new Promise( (resolved, rejected: (reason: (typeof CropReject)[0]) => void) => { const cropConfig = { presentation: 'fullScreenModal', language: 'system', ratio: [], ...config, } as NitroCropConfig cropConfig.language = validateLanguage(cropConfig.language) return Picker.openCrop( image, cropConfig, (result: CropResult) => { resolved(result) }, (error: number) => { rejected(CropReject?.[error as 0 | 1] ?? CropReject[0]) } ) } ) } export function openPreview( media: MediaPreview[] | PickerResult[], index: number = 0, conf?: PreviewConfig ): void { const config: PreviewConfig = { language: conf?.language ?? 'system', videoAutoPlay: true, ...conf, } if (config?.language && !LANGUAGES.includes(config.language)) { config.language = 'system' } if (media.length === 0) { throw new Error('Media is required') } return Picker.openPreview( media as MediaPreview[], index, config as NitroPreviewConfig, config?.onLongPress ?? (() => {}) ) } export async function openCamera(config?: CameraConfig): Promise { return new Promise((resolved, rejected) => { const cameraConfig = { cameraDevice: 'back', presentation: 'fullScreenModal', language: 'system', mediaType: 'all', allowLocation: true, isSaveSystemAlbum: false, ...config, } as NitroCameraConfig cameraConfig.color = processColor(cameraConfig.color ?? primaryColor) as any cameraConfig.language = validateLanguage(cameraConfig.language) if (typeof cameraConfig.crop === 'boolean') { cameraConfig.crop = cameraConfig.crop ? { ratio: [] } : undefined } if (cameraConfig.crop && !cameraConfig.crop?.ratio) cameraConfig.crop.ratio = [] return Picker.openCamera( cameraConfig, (result: CameraResult) => { resolved(result) }, (error: CameraError) => { rejected(error) } ) }) } const DEFAULT_COUNT = 20 const validateLanguage = (language?: Language): Language => { if (!language || !LANGUAGES.includes(language)) { return 'system' } return language } const primaryColor = '#2979ff' export const defaultOptions: Config = { maxSelect: DEFAULT_COUNT, maxVideo: DEFAULT_COUNT, primaryColor, backgroundDark: '#2f2f2f', allowedLimit: true, numberOfColumn: 3, isPreview: true, mediaType: 'all', selectedAssets: [], selectBoxStyle: 'number', selectMode: 'multiple', presentation: 'fullScreenModal', language: 'system', theme: 'system', isHiddenOriginalButton: false, allowSwipeToSelect: true, camera: { cameraDevice: 'back', videoMaximumDuration: 60, }, } const LANGUAGES = [ 'system', 'zh-Hans', 'zh-Hant', 'ja', 'ko', 'en', 'th', 'id', 'vi', 'ru', 'de', 'fr', 'ar', ] as const ================================================ FILE: src/specs/MultipleImagePicker.nitro.ts ================================================ import { type HybridObject } from 'react-native-nitro-modules' import { CameraResult, CropResult, MediaPreview, NitroCameraConfig, NitroConfig, NitroCropConfig, NitroPreviewConfig, PickerResult, } from '../types' export interface MultipleImagePicker extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> { openPicker( config: NitroConfig, resolved: (result: PickerResult[]) => void, rejected: (reject: number) => void ): void openCrop( image: string, config: NitroCropConfig, resolved: (result: CropResult) => void, rejected: (reject: number) => void ): void openPreview( media: MediaPreview[], index: number, config: NitroPreviewConfig, onLongPress: (index: number) => void ): void openCamera( config: NitroCameraConfig, resolved: (result: CameraResult) => void, rejected: (reject: number) => void ): void } ================================================ FILE: src/types/camera.ts ================================================ import { ColorValue } from 'react-native' import { Language, MediaType, Presentation } from './config' import { PickerCropConfig, CropRatio } from './crop' import { BaseResult } from './result' export type CameraDevice = 'front' | 'back' export type PickerCameraConfig = { /** * Type of camera * @typedef {'front' | 'back'} CameraDevice */ cameraDevice?: CameraDevice /** * Maximum duration of video * @type {number} */ videoMaximumDuration?: number } export interface NitroCameraConfig extends PickerCameraConfig { mediaType: MediaType presentation: Presentation language: Language crop?: PickerCropConfig /** * Save image to system album * @type {boolean} */ isSaveSystemAlbum?: boolean color?: number } export interface CameraConfig extends Omit< NitroCameraConfig, 'mediaType' | 'language' | 'presentation' | 'crop' | 'color' > { /** * Type of media to be displayed * @typedef {'video' | 'image' | 'all'} MediaType */ mediaType?: MediaType /** * 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 crop?: | boolean | (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} */ }) /** * 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' * ``` */ color?: ColorValue } export interface CameraResult extends BaseResult { // } ================================================ FILE: src/types/config.ts ================================================ export type Theme = 'light' | 'dark' export type Presentation = 'fullScreenModal' | 'formSheet' export type Language = | 'system' | 'zh-Hans' | 'zh-Hant' | 'ja' | 'ko' | 'en' | 'th' | 'id' | 'vi' | 'ru' | 'de' | 'fr' | 'ar' export type MediaType = 'video' | 'image' | 'all' ================================================ FILE: src/types/crop.ts ================================================ import { Language, Presentation } from './config' 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 } // 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 } ================================================ FILE: src/types/error.ts ================================================ export enum MultipleImagePickerError { CANCELLED = 0, } export enum CameraError { INVALID_OUTPUT_FILE = 1, } export const CropReject = { 0: { code: 0, message: 'Invalid Image', }, 1: { code: 1, message: 'User Cancelled', }, } ================================================ FILE: src/types/index.ts ================================================ export * from './result' export * from './config' export * from './crop' export * from './preview' export * from './picker' export * from './camera' ================================================ FILE: src/types/picker.ts ================================================ import { ColorValue } from 'react-native' import { Language, MediaType, Presentation, Theme } from './config' import { PickerCropConfig, CropRatio } from './crop' import { PickerCameraConfig } from './camera' import { PickerResult } from './result' 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: PickerResult[] /** * 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 } // CONFIG TYPE 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?: PickerResult[] /** * 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?: | boolean | (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 } ================================================ FILE: src/types/preview.ts ================================================ import { Language } from './config' import { ResultType } from './result' // PREVIEW export type NitroPreviewConfig = { language: Language /** * Auto play video when open preview. * * @platform iOS, Android */ videoAutoPlay?: boolean } 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 onLongPress?: (index: number) => void } export interface MediaPreview { type: ResultType path?: string thumbnail?: string localIdentifier?: string } ================================================ FILE: src/types/result.ts ================================================ /** * Represents the type of media content * @example * const type: ResultType = 'image' * const type: ResultType = 'video' */ export type ResultType = 'image' | 'video' /** * Base interface containing common properties for media results. * Used as a foundation for more specific result types. * * @example * const baseResult: BaseResult = { * path: '/path/to/media/file.jpg', * type: 'image', * width: 1920, * height: 1080, * fileName: 'file.jpg' * } */ export interface BaseResult { /** * File path of the media asset * Can be relative or absolute depending on context */ path: string /** * Type of media content * Used to determine how the asset should be handled */ type: ResultType /** * Width of the media in pixels * Optional in base result as it may not be immediately available */ width?: number /** * Height of the media in pixels * Optional in base result as it may not be immediately available */ height?: number /** * Duration of the media in seconds * Only applicable for video content * @example 120.5 // 2 minutes and 30 seconds */ duration?: number /** * Path to a thumbnail image representation * Useful for previews and grid displays * Can be a local path or URL depending on implementation */ thumbnail?: string /** * Original filename of the media asset * Includes the file extension * @example "IMG_20240301_123456.jpg" */ fileName?: string } /** * Extended result interface with complete metadata and file information. * Used for fully processed media assets where all properties are known. * * @extends BaseResult * * @example * const result: Result = { * path: '/path/to/media/file.jpg', * type: 'image', * width: 1920, * height: 1080, * fileName: 'file.jpg', * localIdentifier: 'unique-id-123', * mime: 'image/jpeg', * size: 1024000, * creationDate: 1709312436000 * } */ export interface PickerResult extends BaseResult { /** * Unique identifier for the media asset * Used for local database tracking and reference * Format may vary depending on platform/implementation */ localIdentifier: string /** * Width of the media in pixels * Required in Result interface as it should be known after processing */ width: number /** * Height of the media in pixels * Required in Result interface as it should be known after processing */ height: number /** * MIME type of the media file * @example "image/jpeg", "video/mp4" */ mime: string /** * File size in bytes * @example 1024000 // 1MB */ size: number /** * Optional identifier for storage bucket * Used when assets are stored in cloud storage systems * @platform android */ bucketId?: number /** * Actual file path on the system * May differ from the `path` property in cases where * the file is stored in a different location than referenced * @platform android */ realPath?: string /** * Name of the containing folder * Useful for organization and grouping * @platform android */ parentFolderName?: string /** * Unix timestamp in milliseconds of when the media was created * @example 1709312436000 // March 1, 2024 12:34:56 PM */ creationDate?: number /** * Indicates if the media has been cropped from its original dimensions * Used to track image modifications */ crop?: boolean } ================================================ FILE: tsconfig.build.json ================================================ { "extends": "./tsconfig", "exclude": ["example", "docs"] } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "baseUrl": ".", "outDir": "./lib", "paths": { "@baronha/react-native-multiple-image-picker": ["src"] }, "allowUnreachableCode": false, "allowUnusedLabels": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "jsx": "react", "lib": ["esnext"], "module": "esnext", "moduleResolution": "node", "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "noImplicitUseStrict": false, "noStrictGenericChecks": false, "noUnusedLocals": true, "noUnusedParameters": true, "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "esnext" } }