├── .watchmanconfig
├── example
├── .watchmanconfig
├── jest.config.js
├── .bundle
│ └── config
├── .eslintrc.js
├── app.json
├── .prettierrc.js
├── android
│ ├── app
│ │ ├── debug.keystore
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── values
│ │ │ │ │ │ ├── strings.xml
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ └── drawable
│ │ │ │ │ │ └── rn_edit_text_material.xml
│ │ │ │ ├── java
│ │ │ │ │ └── com
│ │ │ │ │ │ └── nitroinappbrowserexample
│ │ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ │ └── MainApplication.kt
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── debug
│ │ │ │ └── AndroidManifest.xml
│ │ ├── proguard-rules.pro
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── settings.gradle
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradlew.bat
│ └── gradlew
├── ios
│ ├── NitroInAppBrowserExample
│ │ ├── Images.xcassets
│ │ │ ├── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── PrivacyInfo.xcprivacy
│ │ ├── AppDelegate.swift
│ │ ├── Info.plist
│ │ └── LaunchScreen.storyboard
│ ├── NitroInAppBrowserExample.xcworkspace
│ │ └── contents.xcworkspacedata
│ ├── .xcode.env
│ ├── Podfile
│ └── NitroInAppBrowserExample.xcodeproj
│ │ └── xcshareddata
│ │ └── xcschemes
│ │ └── NitroInAppBrowserExample.xcscheme
├── index.js
├── tsconfig.json
├── react-native.config.js
├── metro.config.js
├── babel.config.js
├── Gemfile
├── App.tsx
├── package.json
├── .gitignore
├── Gemfile.lock
└── README.md
├── nitrogen
└── generated
│ ├── .gitattributes
│ ├── ios
│ ├── c++
│ │ ├── HybridNitroInAppBrowserSpecSwift.cpp
│ │ └── HybridNitroInAppBrowserSpecSwift.hpp
│ ├── NitroInAppBrowserAutolinking.mm
│ ├── NitroInAppBrowserAutolinking.swift
│ ├── swift
│ │ ├── NitroInAppBrowserDismissButtonLabel.swift
│ │ ├── NitroInAppBrowserPresentationStyle.swift
│ │ ├── Func_void.swift
│ │ ├── Func_void_std__exception_ptr.swift
│ │ ├── HybridNitroInAppBrowserSpec.swift
│ │ ├── NitroInAppBrowserOptions.swift
│ │ └── HybridNitroInAppBrowserSpec_cxx.swift
│ ├── NitroInAppBrowser+autolinking.rb
│ ├── NitroInAppBrowser-Swift-Cxx-Bridge.cpp
│ ├── NitroInAppBrowser-Swift-Cxx-Umbrella.hpp
│ └── NitroInAppBrowser-Swift-Cxx-Bridge.hpp
│ ├── android
│ ├── kotlin
│ │ └── com
│ │ │ └── margelo
│ │ │ └── nitro
│ │ │ └── nitroinappbrowser
│ │ │ ├── NitroInAppBrowserDismissButtonLabel.kt
│ │ │ ├── NitroInAppBrowserPresentationStyle.kt
│ │ │ ├── NitroInAppBrowserOptions.kt
│ │ │ ├── NitroInAppBrowserOnLoad.kt
│ │ │ └── HybridNitroInAppBrowserSpec.kt
│ ├── NitroInAppBrowser+autolinking.gradle
│ ├── NitroInAppBrowserOnLoad.hpp
│ ├── NitroInAppBrowserOnLoad.cpp
│ ├── c++
│ │ ├── JHybridNitroInAppBrowserSpec.hpp
│ │ ├── JNitroInAppBrowserDismissButtonLabel.hpp
│ │ ├── JNitroInAppBrowserPresentationStyle.hpp
│ │ ├── JNitroInAppBrowserOptions.hpp
│ │ └── JHybridNitroInAppBrowserSpec.cpp
│ └── NitroInAppBrowser+autolinking.cmake
│ └── shared
│ └── c++
│ ├── HybridNitroInAppBrowserSpec.cpp
│ ├── HybridNitroInAppBrowserSpec.hpp
│ ├── NitroInAppBrowserDismissButtonLabel.hpp
│ ├── NitroInAppBrowserPresentationStyle.hpp
│ └── NitroInAppBrowserOptions.hpp
├── babel.config.js
├── android
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── cpp
│ │ └── cpp-adapter.cpp
│ │ └── java
│ │ └── com
│ │ └── nitroinappbrowser
│ │ ├── HybridNitroInAppBrowser.kt
│ │ ├── NitroInAppBrowserPackage.java
│ │ └── NitroInAppBrowserImpl.kt
├── gradle.properties
├── CMakeLists.txt
└── build.gradle
├── ios
├── Bridge.h
├── HybridNitroInAppBrowser.swift
├── BrowserConfiguration.swift
├── SafariBrowserPresenter.swift
└── NitroBrowserColor.swift
├── src
├── specs
│ └── nitro-in-app-browser.nitro.ts
├── types.ts
└── index.ts
├── nitro.json
├── post-script.js
├── tsconfig.json
├── .gitignore
├── LICENSE
├── .github
├── dependabot.yml
└── workflows
│ ├── release.yml
│ ├── android-build.yml
│ └── ios-build.yml
├── NitroInAppBrowser.podspec
├── release.config.js
├── README.md
├── CHANGELOG.md
└── package.json
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/nitrogen/generated/.gitattributes:
--------------------------------------------------------------------------------
1 | ** linguist-generated=true
2 |
--------------------------------------------------------------------------------
/example/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | };
4 |
--------------------------------------------------------------------------------
/example/.bundle/config:
--------------------------------------------------------------------------------
1 | BUNDLE_PATH: "vendor/bundle"
2 | BUNDLE_FORCE_RUBY_PLATFORM: 1
3 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:@react-native/babel-preset'],
3 | }
4 |
--------------------------------------------------------------------------------
/example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: '@react-native',
4 | };
5 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "NitroInAppBrowserExample",
3 | "displayName": "NitroInAppBrowserExample"
4 | }
5 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/example/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | arrowParens: 'avoid',
3 | singleQuote: true,
4 | trailingComma: 'all',
5 | };
6 |
--------------------------------------------------------------------------------
/ios/Bridge.h:
--------------------------------------------------------------------------------
1 | //
2 | // Bridge.h
3 | // nitro-in-app-browser
4 | //
5 | // Created by Patrick Kabwe on 5/16/2025
6 | //
7 |
8 | #pragma once
9 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NitroInAppBrowserExample
3 |
4 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/patrickkabwe/react-native-nitro-in-app-browser/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/cpp/cpp-adapter.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "NitroInAppBrowserOnLoad.hpp"
3 |
4 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
5 | return margelo::nitro::nitroinappbrowser::initialize(vm);
6 | }
7 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | NitroInAppBrowser_kotlinVersion=2.0.21
2 | NitroInAppBrowser_minSdkVersion=23
3 | NitroInAppBrowser_targetSdkVersion=34
4 | NitroInAppBrowser_compileSdkVersion=34
5 | NitroInAppBrowser_ndkVersion=27.1.12297006
6 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import {AppRegistry} from 'react-native';
6 | import App from './App';
7 | import {name as appName} from './app.json';
8 |
9 | AppRegistry.registerComponent(appName, () => App);
10 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@react-native/typescript-config/tsconfig.json",
3 | "compilerOptions": {
4 | "strict": true,
5 | "baseUrl": ".",
6 | "paths": {
7 | "react-native-nitro-in-app-browser": ["../src"]
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/specs/nitro-in-app-browser.nitro.ts:
--------------------------------------------------------------------------------
1 | import { type HybridObject } from 'react-native-nitro-modules';
2 | import type { NitroInAppBrowserOptions } from '../types';
3 | export interface NitroInAppBrowser
4 | extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
5 | open(url: string, options?: NitroInAppBrowserOptions): Promise
6 | close(): Promise
7 | }
8 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement { includeBuild("../../node_modules/@react-native/gradle-plugin") }
2 | plugins { id("com.facebook.react.settings") }
3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
4 | rootProject.name = 'NitroInAppBrowserExample'
5 | include ':app'
6 | includeBuild('../../node_modules/@react-native/gradle-plugin')
7 |
--------------------------------------------------------------------------------
/example/react-native.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const pkg = require('../package.json')
3 |
4 | /**
5 | * @type {import('@react-native-community/cli-types').Config}
6 | */
7 | module.exports = {
8 | project: {
9 | ios: {
10 | automaticPodsInstallation: true,
11 | },
12 | },
13 | dependencies: {
14 | [pkg.name]: {
15 | root: path.join(__dirname, '..'),
16 | },
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export type NitroInAppBrowserDismissButtonLabel = 'cancel' | 'done' | 'close'
2 |
3 | export type NitroInAppBrowserPresentationStyle = 'pageSheet' | 'formSheet' | 'fullScreen'
4 |
5 | export interface NitroInAppBrowserOptions {
6 | dismissButtonLabel?: NitroInAppBrowserDismissButtonLabel
7 | presentationStyle?: NitroInAppBrowserPresentationStyle
8 | barColor?: string
9 | controlColor?: string
10 | }
11 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/c++/HybridNitroInAppBrowserSpecSwift.cpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpecSwift.cpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #include "HybridNitroInAppBrowserSpecSwift.hpp"
9 |
10 | namespace margelo::nitro::nitroinappbrowser {
11 | } // namespace margelo::nitro::nitroinappbrowser
12 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
2 | const path = require('path');
3 | const root = path.resolve(__dirname, '..');
4 |
5 | /**
6 | * Metro configuration
7 | * https://facebook.github.io/metro/docs/configuration
8 | *
9 | * @type {import('metro-config').MetroConfig}
10 | */
11 | const config = {
12 | watchFolders: [root],
13 | };
14 |
15 | module.exports = mergeConfig(getDefaultConfig(__dirname), config);
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const pak = require('../package.json');
3 |
4 | module.exports = api => {
5 | api.cache(true);
6 | return {
7 | presets: ['module:@react-native/babel-preset'],
8 | plugins: [
9 | [
10 | 'module-resolver',
11 | {
12 | extensions: ['.js', '.ts', '.json', '.jsx', '.tsx'],
13 | alias: {
14 | [pak.name]: path.join(__dirname, '../', pak.source),
15 | },
16 | },
17 | ],
18 | ],
19 | };
20 | };
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
4 | ruby ">= 2.6.10"
5 |
6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures.
7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
9 | gem 'xcodeproj', '< 1.28.0'
10 | gem 'concurrent-ruby', '< 1.3.6'
11 |
12 | # Ruby 3.4.0 has removed some libraries from the standard library.
13 | gem 'bigdecimal'
14 | gem 'logger'
15 | gem 'benchmark'
16 | gem 'mutex_m'
17 |
--------------------------------------------------------------------------------
/nitro.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://nitro.margelo.com/nitro.schema.json",
3 | "cxxNamespace": [
4 | "nitroinappbrowser"
5 | ],
6 | "ios": {
7 | "iosModuleName": "NitroInAppBrowser"
8 | },
9 | "android": {
10 | "androidNamespace": [
11 | "nitroinappbrowser"
12 | ],
13 | "androidCxxLibName": "NitroInAppBrowser"
14 | },
15 | "autolinking": {
16 | "NitroInAppBrowser": {
17 | "swift": "HybridNitroInAppBrowser",
18 | "kotlin": "HybridNitroInAppBrowser"
19 | }
20 | },
21 | "ignorePaths": [
22 | "**/node_modules"
23 | ]
24 | }
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext {
3 | buildToolsVersion = "36.0.0"
4 | minSdkVersion = 24
5 | compileSdkVersion = 36
6 | targetSdkVersion = 36
7 | ndkVersion = "27.1.12297006"
8 | kotlinVersion = "2.1.20"
9 | }
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle")
16 | classpath("com.facebook.react:react-native-gradle-plugin")
17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
18 | }
19 | }
20 |
21 | apply plugin: "com.facebook.react.rootproject"
22 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroinappbrowser/NitroInAppBrowserDismissButtonLabel.kt:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserDismissButtonLabel.kt
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | package com.margelo.nitro.nitroinappbrowser
9 |
10 | import androidx.annotation.Keep
11 | import com.facebook.proguard.annotations.DoNotStrip
12 |
13 | /**
14 | * Represents the JavaScript enum/union "NitroInAppBrowserDismissButtonLabel".
15 | */
16 | @DoNotStrip
17 | @Keep
18 | enum class NitroInAppBrowserDismissButtonLabel(@DoNotStrip @Keep val value: Int) {
19 | CANCEL(0),
20 | DONE(1),
21 | CLOSE(2);
22 | }
23 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroinappbrowser/NitroInAppBrowserPresentationStyle.kt:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserPresentationStyle.kt
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | package com.margelo.nitro.nitroinappbrowser
9 |
10 | import androidx.annotation.Keep
11 | import com.facebook.proguard.annotations.DoNotStrip
12 |
13 | /**
14 | * Represents the JavaScript enum/union "NitroInAppBrowserPresentationStyle".
15 | */
16 | @DoNotStrip
17 | @Keep
18 | enum class NitroInAppBrowserPresentationStyle(@DoNotStrip @Keep val value: Int) {
19 | PAGESHEET(0),
20 | FORMSHEET(1),
21 | FULLSCREEN(2);
22 | }
23 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { NitroModules } from 'react-native-nitro-modules'
2 | import type { NitroInAppBrowser as NitroInAppBrowserSpec } from './specs/nitro-in-app-browser.nitro'
3 | import type { NitroInAppBrowserOptions, NitroInAppBrowserPresentationStyle } from "./types"
4 | export * from "./types"
5 |
6 | const NitroInAppBrowserModule =
7 | NitroModules.createHybridObject('NitroInAppBrowser')
8 |
9 | const NitroInAppBrowser = {
10 | open: (url: string, options?: Omit & {
11 | presentationStyle?: NitroInAppBrowserPresentationStyle
12 | }) =>
13 | NitroInAppBrowserModule.open(url, options),
14 | close: () => NitroInAppBrowserModule.close(),
15 | }
16 |
17 | export default NitroInAppBrowser
--------------------------------------------------------------------------------
/android/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(NitroInAppBrowser)
2 | cmake_minimum_required(VERSION 3.9.0)
3 |
4 | set (PACKAGE_NAME NitroInAppBrowser)
5 | set (CMAKE_VERBOSE_MAKEFILE ON)
6 | set (CMAKE_CXX_STANDARD 20)
7 |
8 | # Define C++ library and add all sources
9 | add_library(${PACKAGE_NAME} SHARED
10 | src/main/cpp/cpp-adapter.cpp
11 | )
12 |
13 | # Add Nitrogen specs :)
14 | include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroInAppBrowser+autolinking.cmake)
15 |
16 | # Set up local includes
17 | include_directories(
18 | "src/main/cpp"
19 | "../cpp"
20 | )
21 |
22 | find_library(LOG_LIB log)
23 |
24 | # Link all libraries together
25 | target_link_libraries(
26 | ${PACKAGE_NAME}
27 | ${LOG_LIB}
28 | android # <-- Android core
29 | )
30 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/NitroInAppBrowser+autolinking.gradle:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowser+autolinking.gradle
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | /// This is a Gradle file that adds all files generated by Nitrogen
9 | /// to the current Gradle project.
10 | ///
11 | /// To use it, add this to your build.gradle:
12 | /// ```gradle
13 | /// apply from: '../nitrogen/generated/android/NitroInAppBrowser+autolinking.gradle'
14 | /// ```
15 |
16 | logger.warn("[NitroModules] 🔥 NitroInAppBrowser is boosted by nitro!")
17 |
18 | android {
19 | sourceSets {
20 | main {
21 | java.srcDirs += [
22 | // Nitrogen files
23 | "${project.projectDir}/../nitrogen/generated/android/kotlin"
24 | ]
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/nitrogen/generated/shared/c++/HybridNitroInAppBrowserSpec.cpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec.cpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #include "HybridNitroInAppBrowserSpec.hpp"
9 |
10 | namespace margelo::nitro::nitroinappbrowser {
11 |
12 | void HybridNitroInAppBrowserSpec::loadHybridMethods() {
13 | // load base methods/properties
14 | HybridObject::loadHybridMethods();
15 | // load custom methods/properties
16 | registerHybrids(this, [](Prototype& prototype) {
17 | prototype.registerHybridMethod("open", &HybridNitroInAppBrowserSpec::open);
18 | prototype.registerHybridMethod("close", &HybridNitroInAppBrowserSpec::close);
19 | });
20 | }
21 |
22 | } // namespace margelo::nitro::nitroinappbrowser
23 |
--------------------------------------------------------------------------------
/post-script.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file This script is auto-generated by create-nitro-module and should not be edited.
3 | *
4 | * @description This script applies a workaround for Android by modifying the 'OnLoad.cpp' file.
5 | * It reads the file content and removes the 'margelo/nitro/' string from it. This enables support for custom package names.
6 | *
7 | * @module create-nitro-module
8 | */
9 | const path = require('node:path')
10 | const { writeFile, readFile } = require('node:fs/promises')
11 |
12 | const androidWorkaround = async () => {
13 | const androidOnLoadFile = path.join(
14 | process.cwd(),
15 | 'nitrogen/generated/android',
16 | 'NitroInAppBrowserOnLoad.cpp'
17 | )
18 |
19 |
20 | const str = await readFile(androidOnLoadFile, { encoding: 'utf8' })
21 | await writeFile(androidOnLoadFile, str.replace(/margelo\/nitro\//g, ''))
22 | }
23 | androidWorkaround()
--------------------------------------------------------------------------------
/nitrogen/generated/android/NitroInAppBrowserOnLoad.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOnLoad.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #include
9 | #include
10 |
11 | namespace margelo::nitro::nitroinappbrowser {
12 |
13 | /**
14 | * Initializes the native (C++) part of NitroInAppBrowser, and autolinks all Hybrid Objects.
15 | * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`).
16 | * Example:
17 | * ```cpp (cpp-adapter.cpp)
18 | * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
19 | * return margelo::nitro::nitroinappbrowser::initialize(vm);
20 | * }
21 | * ```
22 | */
23 | int initialize(JavaVM* vm);
24 |
25 | } // namespace margelo::nitro::nitroinappbrowser
26 |
--------------------------------------------------------------------------------
/android/src/main/java/com/nitroinappbrowser/HybridNitroInAppBrowser.kt:
--------------------------------------------------------------------------------
1 | package com.nitroinappbrowser
2 |
3 | import com.margelo.nitro.NitroModules
4 | import com.margelo.nitro.core.Promise
5 | import com.margelo.nitro.nitroinappbrowser.HybridNitroInAppBrowserSpec
6 | import com.margelo.nitro.nitroinappbrowser.NitroInAppBrowserOptions
7 | import kotlinx.coroutines.MainScope
8 |
9 | class HybridNitroInAppBrowser: HybridNitroInAppBrowserSpec() {
10 | private val inAppBrowser = NitroInAppBrowserImpl(NitroModules.applicationContext)
11 | private val scope = MainScope()
12 |
13 | override fun open(url: String, options: NitroInAppBrowserOptions?): Promise {
14 | return Promise.async(scope) {
15 | inAppBrowser.open(url, options)
16 | }
17 | }
18 |
19 | override fun close(): Promise {
20 | return Promise.async(scope) {
21 | inAppBrowser.close()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/nitroinappbrowserexample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.nitroinappbrowserexample
2 |
3 | import com.facebook.react.ReactActivity
4 | import com.facebook.react.ReactActivityDelegate
5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6 | import com.facebook.react.defaults.DefaultReactActivityDelegate
7 |
8 | class MainActivity : ReactActivity() {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | override fun getMainComponentName(): String = "NitroInAppBrowserExample"
15 |
16 | /**
17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
19 | */
20 | override fun createReactActivityDelegate(): ReactActivityDelegate =
21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
22 | }
23 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroinappbrowser/NitroInAppBrowserOptions.kt:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOptions.kt
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | package com.margelo.nitro.nitroinappbrowser
9 |
10 | import androidx.annotation.Keep
11 | import com.facebook.proguard.annotations.DoNotStrip
12 | import com.margelo.nitro.core.*
13 |
14 |
15 | /**
16 | * Represents the JavaScript object/struct "NitroInAppBrowserOptions".
17 | */
18 | @DoNotStrip
19 | @Keep
20 | data class NitroInAppBrowserOptions
21 | @DoNotStrip
22 | @Keep
23 | constructor(
24 | @DoNotStrip
25 | @Keep
26 | val dismissButtonLabel: NitroInAppBrowserDismissButtonLabel?,
27 | @DoNotStrip
28 | @Keep
29 | val presentationStyle: NitroInAppBrowserPresentationStyle?,
30 | @DoNotStrip
31 | @Keep
32 | val barColor: String?,
33 | @DoNotStrip
34 | @Keep
35 | val controlColor: String?
36 | ) {
37 | /* main constructor */
38 | }
39 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowserAutolinking.mm:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserAutolinking.mm
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #import
9 | #import
10 | #import "NitroInAppBrowser-Swift-Cxx-Umbrella.hpp"
11 | #import
12 |
13 | #include "HybridNitroInAppBrowserSpecSwift.hpp"
14 |
15 | @interface NitroInAppBrowserAutolinking : NSObject
16 | @end
17 |
18 | @implementation NitroInAppBrowserAutolinking
19 |
20 | + (void) load {
21 | using namespace margelo::nitro;
22 | using namespace margelo::nitro::nitroinappbrowser;
23 |
24 | HybridObjectRegistry::registerHybridObjectConstructor(
25 | "NitroInAppBrowser",
26 | []() -> std::shared_ptr {
27 | std::shared_ptr hybridObject = NitroInAppBrowser::NitroInAppBrowserAutolinking::createNitroInAppBrowser();
28 | return hybridObject;
29 | }
30 | );
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "allowUnreachableCode": false,
5 | "allowUnusedLabels": false,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "jsx": "react",
9 | "lib": ["esnext"],
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "noEmit": false,
13 | "noFallthroughCasesInSwitch": true,
14 | "noImplicitReturns": true,
15 | "noImplicitUseStrict": false,
16 | "noStrictGenericChecks": false,
17 | "noUncheckedIndexedAccess": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "resolveJsonModule": true,
21 | "skipLibCheck": true,
22 | "strict": true,
23 | "target": "esnext",
24 | "verbatimModuleSyntax": true
25 | },
26 | "exclude": [
27 | "**/node_modules",
28 | "**/lib",
29 | "**/.eslintrc.js",
30 | "**/.prettierrc.js",
31 | "**/jest.config.js",
32 | "**/babel.config.js",
33 | "**/metro.config.js",
34 | "**/tsconfig.json"
35 | ],
36 | "include": ["src/**/*", "nitrogen/**/*.json"]
37 | }
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # XDE
6 | .expo/
7 |
8 | # VSCode
9 | .vscode/
10 | jsconfig.json
11 |
12 | # Xcode
13 | #
14 | build/
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 | *.xccheckout
25 | *.moved-aside
26 | DerivedData
27 | *.hmap
28 | *.ipa
29 | *.xcuserstate
30 | project.xcworkspace
31 |
32 | # Android/IJ
33 | #
34 | .classpath
35 | .cxx
36 | .gradle
37 | .idea
38 | .project
39 | .settings
40 | local.properties
41 | android.iml
42 |
43 | # Cocoapods
44 | #
45 | example/ios/Pods
46 |
47 | # Ruby
48 | example/vendor/
49 |
50 | # node.js
51 | #
52 | node_modules/
53 | npm-debug.log
54 | yarn-debug.log
55 | yarn-error.log
56 |
57 | # BUCK
58 | buck-out/
59 | \.buckd/
60 | android/app/libs
61 | android/keystores/debug.keystore
62 |
63 | # Yarn
64 | .yarn/*
65 | !.yarn/patches
66 | !.yarn/plugins
67 | !.yarn/releases
68 | !.yarn/sdks
69 | !.yarn/versions
70 | .kotlin
71 |
72 | # Expo
73 | .expo/
74 |
75 | # generated by bob
76 | lib/
77 | tsconfig.tsbuildinfo
--------------------------------------------------------------------------------
/android/src/main/java/com/nitroinappbrowser/NitroInAppBrowserPackage.java:
--------------------------------------------------------------------------------
1 | package com.nitroinappbrowser;
2 |
3 | import android.util.Log;
4 | import androidx.annotation.Nullable;
5 | import androidx.annotation.NonNull;
6 |
7 | import com.facebook.react.bridge.NativeModule;
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.module.model.ReactModuleInfoProvider;
10 | import com.facebook.react.TurboReactPackage;
11 | import com.margelo.nitro.core.HybridObject;
12 | import com.margelo.nitro.nitroinappbrowser.NitroInAppBrowserOnLoad;
13 |
14 | import java.util.HashMap;
15 | import java.util.function.Supplier;
16 |
17 | public class NitroInAppBrowserPackage extends TurboReactPackage {
18 | @Nullable
19 | @Override
20 | public NativeModule getModule(@NonNull String name, @NonNull ReactApplicationContext reactContext) {
21 | return null;
22 | }
23 |
24 | @NonNull
25 | @Override
26 | public ReactModuleInfoProvider getReactModuleInfoProvider() {
27 | return HashMap::new;
28 | }
29 |
30 | static {
31 | NitroInAppBrowserOnLoad.initializeNative();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Patrick Kabwe
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowserAutolinking.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserAutolinking.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | public final class NitroInAppBrowserAutolinking {
9 | public typealias bridge = margelo.nitro.nitroinappbrowser.bridge.swift
10 |
11 | /**
12 | * Creates an instance of a Swift class that implements `HybridNitroInAppBrowserSpec`,
13 | * and wraps it in a Swift class that can directly interop with C++ (`HybridNitroInAppBrowserSpec_cxx`)
14 | *
15 | * This is generated by Nitrogen and will initialize the class specified
16 | * in the `"autolinking"` property of `nitro.json` (in this case, `HybridNitroInAppBrowser`).
17 | */
18 | public static func createNitroInAppBrowser() -> bridge.std__shared_ptr_HybridNitroInAppBrowserSpec_ {
19 | let hybridObject = HybridNitroInAppBrowser()
20 | return { () -> bridge.std__shared_ptr_HybridNitroInAppBrowserSpec_ in
21 | let __cxxWrapped = hybridObject.getCxxWrapper()
22 | return __cxxWrapped.getCxxPart()
23 | }()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryFileTimestamp
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | C617.1
13 |
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryUserDefaults
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | CA92.1
21 |
22 |
23 |
24 | NSPrivacyAccessedAPIType
25 | NSPrivacyAccessedAPICategorySystemBootTime
26 | NSPrivacyAccessedAPITypeReasons
27 |
28 | 35F9.1
29 |
30 |
31 |
32 | NSPrivacyCollectedDataTypes
33 |
34 | NSPrivacyTracking
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Resolve react_native_pods.rb with node to allow for hoisting
2 | require Pod::Executable.execute_command('node', ['-p',
3 | 'require.resolve(
4 | "react-native/scripts/react_native_pods.rb",
5 | {paths: [process.argv[1]]},
6 | )', __dir__]).strip
7 |
8 | platform :ios, min_ios_version_supported
9 | prepare_react_native_project!
10 |
11 | linkage = ENV['USE_FRAMEWORKS']
12 | if linkage != nil
13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
14 | use_frameworks! :linkage => linkage.to_sym
15 | end
16 |
17 | target 'NitroInAppBrowserExample' do
18 | config = use_native_modules!
19 |
20 | use_react_native!(
21 | :path => config[:reactNativePath],
22 | # An absolute path to your application root.
23 | :app_path => "#{Pod::Config.instance.installation_root}/.."
24 | )
25 |
26 | post_install do |installer|
27 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
28 | react_native_post_install(
29 | installer,
30 | config[:reactNativePath],
31 | :mac_catalyst_enabled => false,
32 | # :ccache_enabled => true
33 | )
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | enable-beta-ecosystems: true
3 | updates:
4 | - package-ecosystem: 'github-actions'
5 | directory: '/'
6 | schedule:
7 | interval: 'daily'
8 | labels:
9 | - 'dependencies'
10 |
11 | - package-ecosystem: 'gradle'
12 | directories:
13 | - '/android/'
14 | - '/example/android/'
15 | schedule:
16 | interval: 'daily'
17 | labels:
18 | - 'nitro-core'
19 | - 'nitrogen'
20 | - 'dependencies'
21 | - 'kotlin'
22 |
23 | - package-ecosystem: 'bundler'
24 | directory: '/example/'
25 | schedule:
26 | interval: 'daily'
27 | labels:
28 | - 'dependencies'
29 | - 'ruby'
30 |
31 | - package-ecosystem: 'npm'
32 | directories:
33 | - '/example/'
34 | - '/'
35 | schedule:
36 | interval: 'daily'
37 | labels:
38 | - 'nitro-core'
39 | - 'dependencies'
40 | - 'typescript'
41 | - 'nitrogen'
42 |
43 | groups:
44 | react-native-cli:
45 | patterns:
46 | - '@react-native-community/cli*'
47 | babel:
48 | patterns:
49 | - '@babel/*'
50 | react-native:
51 | patterns:
52 | - '@react-native/*'
53 |
--------------------------------------------------------------------------------
/NitroInAppBrowser.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "NitroInAppBrowser"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.homepage = package["homepage"]
10 | s.license = package["license"]
11 | s.authors = package["author"]
12 |
13 | s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
14 | s.source = { :git => "https://github.com/patrickkabwe/react-native-nitro-in-app-browser.git", :tag => "#{s.version}" }
15 |
16 | s.source_files = [
17 | # Implementation (Swift)
18 | "ios/**/*.{swift}",
19 | # Autolinking/Registration (Objective-C++)
20 | "ios/**/*.{m,mm}",
21 | # Implementation (C++ objects)
22 | "cpp/**/*.{hpp,cpp}",
23 | ]
24 |
25 | s.pod_target_xcconfig = {
26 | # C++ compiler flags, mainly for folly.
27 | "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
28 | }
29 |
30 | load 'nitrogen/generated/ios/NitroInAppBrowser+autolinking.rb'
31 | add_nitrogen_files(s)
32 |
33 | s.dependency 'React-jsi'
34 | s.dependency 'React-callinvoker'
35 | install_modules_dependencies(s)
36 | end
37 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroinappbrowser/NitroInAppBrowserOnLoad.kt:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOnLoad.kt
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | package com.margelo.nitro.nitroinappbrowser
9 |
10 | import android.util.Log
11 |
12 | internal class NitroInAppBrowserOnLoad {
13 | companion object {
14 | private const val TAG = "NitroInAppBrowserOnLoad"
15 | private var didLoad = false
16 | /**
17 | * Initializes the native part of "NitroInAppBrowser".
18 | * This method is idempotent and can be called more than once.
19 | */
20 | @JvmStatic
21 | fun initializeNative() {
22 | if (didLoad) return
23 | try {
24 | Log.i(TAG, "Loading NitroInAppBrowser C++ library...")
25 | System.loadLibrary("NitroInAppBrowser")
26 | Log.i(TAG, "Successfully loaded NitroInAppBrowser C++ library!")
27 | didLoad = true
28 | } catch (e: Error) {
29 | Log.e(TAG, "Failed to load NitroInAppBrowser C++ library! Is it properly installed and linked? " +
30 | "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e)
31 | throw e
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/NitroInAppBrowserDismissButtonLabel.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserDismissButtonLabel.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | /**
9 | * Represents the JS union `NitroInAppBrowserDismissButtonLabel`, backed by a C++ enum.
10 | */
11 | public typealias NitroInAppBrowserDismissButtonLabel = margelo.nitro.nitroinappbrowser.NitroInAppBrowserDismissButtonLabel
12 |
13 | public extension NitroInAppBrowserDismissButtonLabel {
14 | /**
15 | * Get a NitroInAppBrowserDismissButtonLabel for the given String value, or
16 | * return `nil` if the given value was invalid/unknown.
17 | */
18 | init?(fromString string: String) {
19 | switch string {
20 | case "cancel":
21 | self = .cancel
22 | case "done":
23 | self = .done
24 | case "close":
25 | self = .close
26 | default:
27 | return nil
28 | }
29 | }
30 |
31 | /**
32 | * Get the String value this NitroInAppBrowserDismissButtonLabel represents.
33 | */
34 | var stringValue: String {
35 | switch self {
36 | case .cancel:
37 | return "cancel"
38 | case .done:
39 | return "done"
40 | case .close:
41 | return "close"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/example/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Alert, Button, StyleSheet} from 'react-native';
3 | import NitroInAppBrowser from 'react-native-nitro-in-app-browser';
4 | import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
5 |
6 | const AppWrapper = () => {
7 | return (
8 |
9 |
30 | );
31 | };
32 |
33 | const App = () => {
34 | return (
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | export default App;
42 |
43 | const styles = StyleSheet.create({
44 | container: {
45 | flex: 1,
46 | justifyContent: 'center',
47 | alignItems: 'center',
48 | },
49 | });
50 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-nitro-in-app-browser-example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios --simulator='iPhone 16'",
8 | "lint": "eslint .",
9 | "start": "react-native start --reset-cache",
10 | "test": "jest",
11 | "pod": "bundle install && bundle exec pod install --project-directory=ios"
12 | },
13 | "dependencies": {
14 | "react": "19.1.0",
15 | "react-native": "0.81.0",
16 | "react-native-nitro-modules": "^0.28.1",
17 | "react-native-safe-area-context": "^5.6.1"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.25.2",
21 | "@babel/preset-env": "^7.25.3",
22 | "@babel/runtime": "^7.25.0",
23 | "@react-native-community/cli": "20.0.0",
24 | "@react-native-community/cli-platform-android": "20.0.0",
25 | "@react-native-community/cli-platform-ios": "20.0.0",
26 | "@react-native/babel-preset": "0.81.0",
27 | "@react-native/eslint-config": "0.81.0",
28 | "@react-native/metro-config": "0.81.0",
29 | "@react-native/typescript-config": "0.81.0",
30 | "@types/jest": "^29.5.13",
31 | "babel-plugin-module-resolver": "^5.0.2"
32 | },
33 | "engines": {
34 | "node": ">=18"
35 | }
36 | }
--------------------------------------------------------------------------------
/ios/HybridNitroInAppBrowser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HybridNitroInAppBrowser.swift
3 | // NitroInAppBrowser
4 | //
5 | // Created by Patrick Kabwe on 19/12/2024.
6 | //
7 |
8 | import Foundation
9 | import NitroModules
10 |
11 | class HybridNitroInAppBrowser: HybridNitroInAppBrowserSpec {
12 | private let browserPresenter: BrowserPresenting = SafariBrowserPresenter()
13 |
14 | func open(url stringUrl: String, options: NitroInAppBrowserOptions?) throws -> Promise {
15 | guard let url = URL(string: stringUrl) else {
16 | throw RuntimeError.error(withMessage: "Invalid URL")
17 | }
18 |
19 | return .async {
20 | return try await withCheckedThrowingContinuation { continuation in
21 | DispatchQueue.main.async { [weak self] in
22 | do {
23 | try self?.browserPresenter.present(url: url, options: options)
24 | continuation.resume()
25 | } catch let error {
26 | continuation.resume(throwing: error)
27 | }
28 | }
29 | }
30 | }
31 | }
32 |
33 | func close() throws -> Promise {
34 | return .async {
35 | DispatchQueue.main.async { [weak self] in
36 | self?.browserPresenter.dismiss()
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/NitroInAppBrowserPresentationStyle.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserPresentationStyle.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | /**
9 | * Represents the JS union `NitroInAppBrowserPresentationStyle`, backed by a C++ enum.
10 | */
11 | public typealias NitroInAppBrowserPresentationStyle = margelo.nitro.nitroinappbrowser.NitroInAppBrowserPresentationStyle
12 |
13 | public extension NitroInAppBrowserPresentationStyle {
14 | /**
15 | * Get a NitroInAppBrowserPresentationStyle for the given String value, or
16 | * return `nil` if the given value was invalid/unknown.
17 | */
18 | init?(fromString string: String) {
19 | switch string {
20 | case "pageSheet":
21 | self = .pagesheet
22 | case "formSheet":
23 | self = .formsheet
24 | case "fullScreen":
25 | self = .fullscreen
26 | default:
27 | return nil
28 | }
29 | }
30 |
31 | /**
32 | * Get the String value this NitroInAppBrowserPresentationStyle represents.
33 | */
34 | var stringValue: String {
35 | switch self {
36 | case .pagesheet:
37 | return "pageSheet"
38 | case .formsheet:
39 | return "formSheet"
40 | case .fullscreen:
41 | return "fullScreen"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | **/.xcode.env.local
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 | *.hprof
33 | .cxx/
34 | *.keystore
35 | !debug.keystore
36 | .kotlin/
37 |
38 | # node.js
39 | #
40 | node_modules/
41 | npm-debug.log
42 | yarn-error.log
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | **/fastlane/report.xml
52 | **/fastlane/Preview.html
53 | **/fastlane/screenshots
54 | **/fastlane/test_output
55 |
56 | # Bundle artifact
57 | *.jsbundle
58 |
59 | # Ruby / CocoaPods
60 | **/Pods/
61 | /vendor/bundle/
62 |
63 | # Temporary files created by Metro to check the health of the file watcher
64 | .metro-health-check*
65 |
66 | # testing
67 | /coverage
68 |
69 | # Yarn
70 | .yarn/*
71 | !.yarn/patches
72 | !.yarn/plugins
73 | !.yarn/releases
74 | !.yarn/sdks
75 | !.yarn/versions
76 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import React
3 | import React_RCTAppDelegate
4 | import ReactAppDependencyProvider
5 |
6 | @main
7 | class AppDelegate: UIResponder, UIApplicationDelegate {
8 | var window: UIWindow?
9 |
10 | var reactNativeDelegate: ReactNativeDelegate?
11 | var reactNativeFactory: RCTReactNativeFactory?
12 |
13 | func application(
14 | _ application: UIApplication,
15 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
16 | ) -> Bool {
17 | let delegate = ReactNativeDelegate()
18 | let factory = RCTReactNativeFactory(delegate: delegate)
19 | delegate.dependencyProvider = RCTAppDependencyProvider()
20 |
21 | reactNativeDelegate = delegate
22 | reactNativeFactory = factory
23 |
24 | window = UIWindow(frame: UIScreen.main.bounds)
25 |
26 | factory.startReactNative(
27 | withModuleName: "NitroInAppBrowserExample",
28 | in: window,
29 | launchOptions: launchOptions
30 | )
31 |
32 | return true
33 | }
34 | }
35 |
36 | class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
37 | override func sourceURL(for bridge: RCTBridge) -> URL? {
38 | self.bundleURL()
39 | }
40 |
41 | override func bundleURL() -> URL? {
42 | #if DEBUG
43 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
44 | #else
45 | Bundle.main.url(forResource: "main", withExtension: "jsbundle")
46 | #endif
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/Func_void.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// Func_void.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | import NitroModules
9 |
10 |
11 | /**
12 | * Wraps a Swift `() -> Void` as a class.
13 | * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.
14 | */
15 | public final class Func_void {
16 | public typealias bridge = margelo.nitro.nitroinappbrowser.bridge.swift
17 |
18 | private let closure: () -> Void
19 |
20 | public init(_ closure: @escaping () -> Void) {
21 | self.closure = closure
22 | }
23 |
24 | @inline(__always)
25 | public func call() -> Void {
26 | self.closure()
27 | }
28 |
29 | /**
30 | * Casts this instance to a retained unsafe raw pointer.
31 | * This acquires one additional strong reference on the object!
32 | */
33 | @inline(__always)
34 | public func toUnsafe() -> UnsafeMutableRawPointer {
35 | return Unmanaged.passRetained(self).toOpaque()
36 | }
37 |
38 | /**
39 | * Casts an unsafe pointer to a `Func_void`.
40 | * The pointer has to be a retained opaque `Unmanaged`.
41 | * This removes one strong reference from the object!
42 | */
43 | @inline(__always)
44 | public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void {
45 | return Unmanaged.fromOpaque(pointer).takeRetainedValue()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/nitroinappbrowserexample/MainApplication.kt:
--------------------------------------------------------------------------------
1 | package com.nitroinappbrowserexample
2 |
3 | import android.app.Application
4 | import com.facebook.react.PackageList
5 | import com.facebook.react.ReactApplication
6 | import com.facebook.react.ReactHost
7 | import com.facebook.react.ReactNativeHost
8 | import com.facebook.react.ReactPackage
9 | import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11 | import com.facebook.react.defaults.DefaultReactNativeHost
12 |
13 |
14 |
15 | class MainApplication : Application(), ReactApplication {
16 |
17 | override val reactNativeHost: ReactNativeHost =
18 | object : DefaultReactNativeHost(this) {
19 | override fun getPackages(): List =
20 | PackageList(this).packages.apply {
21 | // Packages that cannot be autolinked yet can be added manually here, for example:
22 | // add(MyReactNativePackage())
23 | }
24 |
25 | override fun getJSMainModuleName(): String = "index"
26 |
27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
28 |
29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
31 | }
32 |
33 | override val reactHost: ReactHost
34 | get() = getDefaultReactHost(applicationContext, reactNativeHost)
35 |
36 | override fun onCreate() {
37 | super.onCreate()
38 | loadReactNative(this)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | permissions:
7 | contents: read
8 |
9 | concurrency:
10 | group: ${{ github.workflow }}-${{ github.ref }}
11 | cancel-in-progress: true
12 |
13 | jobs:
14 | release:
15 | name: Release
16 | runs-on: ubuntu-latest
17 | permissions:
18 | contents: write
19 | issues: write
20 | pull-requests: write
21 | id-token: write
22 | steps:
23 | - name: Checkout
24 | uses: actions/checkout@v5
25 | with:
26 | fetch-depth: 0
27 | - name: Setup Bun.js
28 | uses: oven-sh/setup-bun@v2
29 | with:
30 | bun-version: latest
31 | - name: Cache bun dependencies
32 | id: bun-cache
33 | uses: actions/cache@v4
34 | with:
35 | path: ~/.bun/install/cache
36 | key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
37 | restore-keys: |
38 | ${{ runner.os }}-bun-
39 |
40 | - name: Install npm dependencies (bun)
41 | run: bun install
42 |
43 | - name: Build lib
44 | run: bun run build
45 |
46 | - name: Release
47 | env:
48 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
50 | NPM_CONFIG_PROVENANCE: true
51 | GIT_AUTHOR_NAME: ${{ github.actor }}
52 | GIT_AUTHOR_EMAIL: "${{ github.actor }}@users.noreply.github.com"
53 | GIT_COMMITTER_NAME: ${{ github.actor }}
54 | GIT_COMMITTER_EMAIL: "${{ github.actor }}@users.noreply.github.com"
55 | run: bun release
--------------------------------------------------------------------------------
/ios/BrowserConfiguration.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowserConfiguration.swift
3 | // NitroInAppBrowser
4 | //
5 | // Created by Patrick Kabwe on 19/12/2024.
6 | //
7 |
8 | import Foundation
9 | import NitroModules
10 | import SafariServices
11 |
12 | // MARK: - Browser Configuration
13 | struct BrowserConfiguration {
14 | func configure(safariVC: SFSafariViewController, options: NitroInAppBrowserOptions?) {
15 | // Configure colors
16 | safariVC.preferredControlTintColor = options?.controlColor.flatMap { UIColor(value: $0) }
17 | safariVC.preferredBarTintColor = options?.barColor.flatMap { UIColor(value: $0) }
18 |
19 | // Configure presentation style
20 | safariVC.modalPresentationStyle = configurePresentationStyle(for: options?.presentationStyle)
21 |
22 |
23 | // Configure dismiss button
24 | if let dismissStyle = options?.dismissButtonLabel {
25 | safariVC.dismissButtonStyle = configureDismissButtonStyle(dismissStyle)
26 | }
27 | }
28 |
29 | private func configurePresentationStyle(for style: NitroInAppBrowserPresentationStyle?) -> UIModalPresentationStyle {
30 | switch style {
31 | case .formsheet: return .formSheet
32 | case .pagesheet: return .pageSheet
33 | case .fullscreen: return .fullScreen
34 | default: return .automatic
35 | }
36 | }
37 |
38 | private func configureDismissButtonStyle(_ style: NitroInAppBrowserDismissButtonLabel?) -> SFSafariViewController.DismissButtonStyle {
39 | switch style {
40 | case .cancel: return .cancel
41 | case .close: return .close
42 | case .done, .none: return .done
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// Func_void_std__exception_ptr.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | import NitroModules
9 |
10 |
11 | /**
12 | * Wraps a Swift `(_ error: Error) -> Void` as a class.
13 | * This class can be used from C++, e.g. to wrap the Swift closure as a `std::function`.
14 | */
15 | public final class Func_void_std__exception_ptr {
16 | public typealias bridge = margelo.nitro.nitroinappbrowser.bridge.swift
17 |
18 | private let closure: (_ error: Error) -> Void
19 |
20 | public init(_ closure: @escaping (_ error: Error) -> Void) {
21 | self.closure = closure
22 | }
23 |
24 | @inline(__always)
25 | public func call(error: std.exception_ptr) -> Void {
26 | self.closure(RuntimeError.from(cppError: error))
27 | }
28 |
29 | /**
30 | * Casts this instance to a retained unsafe raw pointer.
31 | * This acquires one additional strong reference on the object!
32 | */
33 | @inline(__always)
34 | public func toUnsafe() -> UnsafeMutableRawPointer {
35 | return Unmanaged.passRetained(self).toOpaque()
36 | }
37 |
38 | /**
39 | * Casts an unsafe pointer to a `Func_void_std__exception_ptr`.
40 | * The pointer has to be a retained opaque `Unmanaged`.
41 | * This removes one strong reference from the object!
42 | */
43 | @inline(__always)
44 | public static func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> Func_void_std__exception_ptr {
45 | return Unmanaged.fromOpaque(pointer).takeRetainedValue()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroinappbrowser/HybridNitroInAppBrowserSpec.kt:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec.kt
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | package com.margelo.nitro.nitroinappbrowser
9 |
10 | import androidx.annotation.Keep
11 | import com.facebook.jni.HybridData
12 | import com.facebook.proguard.annotations.DoNotStrip
13 | import com.margelo.nitro.core.*
14 |
15 | /**
16 | * A Kotlin class representing the NitroInAppBrowser HybridObject.
17 | * Implement this abstract class to create Kotlin-based instances of NitroInAppBrowser.
18 | */
19 | @DoNotStrip
20 | @Keep
21 | @Suppress(
22 | "KotlinJniMissingFunction", "unused",
23 | "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet",
24 | "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName"
25 | )
26 | abstract class HybridNitroInAppBrowserSpec: HybridObject() {
27 | @DoNotStrip
28 | private var mHybridData: HybridData = initHybrid()
29 |
30 | init {
31 | super.updateNative(mHybridData)
32 | }
33 |
34 | override fun updateNative(hybridData: HybridData) {
35 | mHybridData = hybridData
36 | super.updateNative(hybridData)
37 | }
38 |
39 | // Properties
40 |
41 |
42 | // Methods
43 | @DoNotStrip
44 | @Keep
45 | abstract fun open(url: String, options: NitroInAppBrowserOptions?): Promise
46 |
47 | @DoNotStrip
48 | @Keep
49 | abstract fun close(): Promise
50 |
51 | private external fun initHybrid(): HybridData
52 |
53 | companion object {
54 | private const val TAG = "HybridNitroInAppBrowserSpec"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/NitroInAppBrowserOnLoad.cpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOnLoad.cpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #ifndef BUILDING_NITROINAPPBROWSER_WITH_GENERATED_CMAKE_PROJECT
9 | #error NitroInAppBrowserOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this?
10 | #endif
11 |
12 | #include "NitroInAppBrowserOnLoad.hpp"
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #include "JHybridNitroInAppBrowserSpec.hpp"
19 | #include
20 |
21 | namespace margelo::nitro::nitroinappbrowser {
22 |
23 | int initialize(JavaVM* vm) {
24 | using namespace margelo::nitro;
25 | using namespace margelo::nitro::nitroinappbrowser;
26 | using namespace facebook;
27 |
28 | return facebook::jni::initialize(vm, [] {
29 | // Register native JNI methods
30 | margelo::nitro::nitroinappbrowser::JHybridNitroInAppBrowserSpec::registerNatives();
31 |
32 | // Register Nitro Hybrid Objects
33 | HybridObjectRegistry::registerHybridObjectConstructor(
34 | "NitroInAppBrowser",
35 | []() -> std::shared_ptr {
36 | static DefaultConstructableObject object("com/nitroinappbrowser/HybridNitroInAppBrowser");
37 | auto instance = object.create();
38 | auto globalRef = jni::make_global(instance);
39 | return globalRef->cthis()->shared();
40 | }
41 | );
42 | });
43 | }
44 |
45 | } // namespace margelo::nitro::nitroinappbrowser
46 |
--------------------------------------------------------------------------------
/release.config.js:
--------------------------------------------------------------------------------
1 | const rules = [
2 | { type: 'feat', release: 'minor', title: '✨ Features' },
3 | { type: 'fix', release: 'patch', title: '🐛 Bug Fixes' },
4 | { type: 'perf', release: 'patch', title: '💨 Performance Improvements' },
5 | { type: 'refactor', release: 'patch', title: '🔄 Code Refactors' },
6 | { type: 'docs', release: 'patch', title: '📚 Documentation' },
7 | { type: 'chore', release: 'patch', title: '🛠️ Other changes' },
8 | ]
9 |
10 | const sortMap = Object.fromEntries(
11 | rules.map((rule, index) => [rule.title, index])
12 | )
13 |
14 | /**
15 | * @type {import('semantic-release').GlobalConfig}
16 | */
17 | module.exports = {
18 | branches: ['main', { name: 'next', prerelease: 'next' }],
19 | plugins: [
20 | [
21 | '@semantic-release/commit-analyzer',
22 | {
23 | preset: 'conventionalcommits',
24 | releaseRules: [
25 | { breaking: true, release: 'major' },
26 | { revert: true, release: 'patch' },
27 | ].concat(rules.map(({ type, release }) => ({ type, release }))),
28 | },
29 | ],
30 | [
31 | '@semantic-release/release-notes-generator',
32 | {
33 | preset: 'conventionalcommits',
34 | presetConfig: {
35 | types: rules.map(({ type, title }) => ({ type, section: title })),
36 | },
37 | writerOpts: {
38 | commitGroupsSort: (a, z) => sortMap[a.title] - sortMap[z.title],
39 | },
40 | },
41 | ],
42 | [
43 | '@semantic-release/changelog',
44 | {
45 | changelogFile: 'CHANGELOG.md',
46 | },
47 | ],
48 | '@semantic-release/npm',
49 | '@semantic-release/github',
50 | ['@semantic-release/git', { assets: ['package.json', 'CHANGELOG.md'] }],
51 | ],
52 | }
53 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | NitroInAppBrowserExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSAllowsLocalNetworking
32 |
33 |
34 | NSLocationWhenInUseUsageDescription
35 |
36 | RCTNewArchEnabled
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | arm64
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/HybridNitroInAppBrowserSpec.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | import Foundation
9 | import NitroModules
10 |
11 | /// See ``HybridNitroInAppBrowserSpec``
12 | public protocol HybridNitroInAppBrowserSpec_protocol: HybridObject {
13 | // Properties
14 |
15 |
16 | // Methods
17 | func open(url: String, options: NitroInAppBrowserOptions?) throws -> Promise
18 | func close() throws -> Promise
19 | }
20 |
21 | /// See ``HybridNitroInAppBrowserSpec``
22 | open class HybridNitroInAppBrowserSpec_base {
23 | private weak var cxxWrapper: HybridNitroInAppBrowserSpec_cxx? = nil
24 | public init() { }
25 | public func getCxxWrapper() -> HybridNitroInAppBrowserSpec_cxx {
26 | #if DEBUG
27 | guard self is HybridNitroInAppBrowserSpec else {
28 | fatalError("`self` is not a `HybridNitroInAppBrowserSpec`! Did you accidentally inherit from `HybridNitroInAppBrowserSpec_base` instead of `HybridNitroInAppBrowserSpec`?")
29 | }
30 | #endif
31 | if let cxxWrapper = self.cxxWrapper {
32 | return cxxWrapper
33 | } else {
34 | let cxxWrapper = HybridNitroInAppBrowserSpec_cxx(self as! HybridNitroInAppBrowserSpec)
35 | self.cxxWrapper = cxxWrapper
36 | return cxxWrapper
37 | }
38 | }
39 | }
40 |
41 | /**
42 | * A Swift base-protocol representing the NitroInAppBrowser HybridObject.
43 | * Implement this protocol to create Swift-based instances of NitroInAppBrowser.
44 | * ```swift
45 | * class HybridNitroInAppBrowser : HybridNitroInAppBrowserSpec {
46 | * // ...
47 | * }
48 | * ```
49 | */
50 | public typealias HybridNitroInAppBrowserSpec = HybridNitroInAppBrowserSpec_protocol & HybridNitroInAppBrowserSpec_base
51 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 |
25 | # Use this property to specify which architecture you want to build.
26 | # You can also override it from the CLI using
27 | # ./gradlew -PreactNativeArchitectures=x86_64
28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
29 |
30 | # Use this property to enable support to the new architecture.
31 | # This will allow you to use TurboModules and the Fabric render in
32 | # your application. You should enable this flag either if you want
33 | # to write custom TurboModules/Fabric components OR use libraries that
34 | # are providing them.
35 | newArchEnabled=true
36 |
37 | # Use this property to enable or disable the Hermes JS engine.
38 | # If set to false, you will be using JSC instead.
39 | hermesEnabled=true
40 |
41 | # Use this property to enable edge-to-edge display support.
42 | # This allows your app to draw behind system bars for an immersive UI.
43 | # Note: Only works with ReactActivity and should not be used with custom Activity.
44 | edgeToEdgeEnabled=false
45 |
--------------------------------------------------------------------------------
/nitrogen/generated/shared/c++/HybridNitroInAppBrowserSpec.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #if __has_include()
11 | #include
12 | #else
13 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14 | #endif
15 |
16 | // Forward declaration of `NitroInAppBrowserOptions` to properly resolve imports.
17 | namespace margelo::nitro::nitroinappbrowser { struct NitroInAppBrowserOptions; }
18 |
19 | #include
20 | #include
21 | #include "NitroInAppBrowserOptions.hpp"
22 | #include
23 |
24 | namespace margelo::nitro::nitroinappbrowser {
25 |
26 | using namespace margelo::nitro;
27 |
28 | /**
29 | * An abstract base class for `NitroInAppBrowser`
30 | * Inherit this class to create instances of `HybridNitroInAppBrowserSpec` in C++.
31 | * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
32 | * @example
33 | * ```cpp
34 | * class HybridNitroInAppBrowser: public HybridNitroInAppBrowserSpec {
35 | * public:
36 | * HybridNitroInAppBrowser(...): HybridObject(TAG) { ... }
37 | * // ...
38 | * };
39 | * ```
40 | */
41 | class HybridNitroInAppBrowserSpec: public virtual HybridObject {
42 | public:
43 | // Constructor
44 | explicit HybridNitroInAppBrowserSpec(): HybridObject(TAG) { }
45 |
46 | // Destructor
47 | ~HybridNitroInAppBrowserSpec() override = default;
48 |
49 | public:
50 | // Properties
51 |
52 |
53 | public:
54 | // Methods
55 | virtual std::shared_ptr> open(const std::string& url, const std::optional& options) = 0;
56 | virtual std::shared_ptr> close() = 0;
57 |
58 | protected:
59 | // Hybrid Setup
60 | void loadHybridMethods() override;
61 |
62 | protected:
63 | // Tag for logging
64 | static constexpr auto TAG = "NitroInAppBrowser";
65 | };
66 |
67 | } // namespace margelo::nitro::nitroinappbrowser
68 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowser+autolinking.rb:
--------------------------------------------------------------------------------
1 | #
2 | # NitroInAppBrowser+autolinking.rb
3 | # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | # https://github.com/mrousavy/nitro
5 | # Copyright © 2025 Marc Rousavy @ Margelo
6 | #
7 |
8 | # This is a Ruby script that adds all files generated by Nitrogen
9 | # to the given podspec.
10 | #
11 | # To use it, add this to your .podspec:
12 | # ```ruby
13 | # Pod::Spec.new do |spec|
14 | # # ...
15 | #
16 | # # Add all files generated by Nitrogen
17 | # load 'nitrogen/generated/ios/NitroInAppBrowser+autolinking.rb'
18 | # add_nitrogen_files(spec)
19 | # end
20 | # ```
21 |
22 | def add_nitrogen_files(spec)
23 | Pod::UI.puts "[NitroModules] 🔥 NitroInAppBrowser is boosted by nitro!"
24 |
25 | spec.dependency "NitroModules"
26 |
27 | current_source_files = Array(spec.attributes_hash['source_files'])
28 | spec.source_files = current_source_files + [
29 | # Generated cross-platform specs
30 | "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}",
31 | # Generated bridges for the cross-platform specs
32 | "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}",
33 | ]
34 |
35 | current_public_header_files = Array(spec.attributes_hash['public_header_files'])
36 | spec.public_header_files = current_public_header_files + [
37 | # Generated specs
38 | "nitrogen/generated/shared/**/*.{h,hpp}",
39 | # Swift to C++ bridging helpers
40 | "nitrogen/generated/ios/NitroInAppBrowser-Swift-Cxx-Bridge.hpp"
41 | ]
42 |
43 | current_private_header_files = Array(spec.attributes_hash['private_header_files'])
44 | spec.private_header_files = current_private_header_files + [
45 | # iOS specific specs
46 | "nitrogen/generated/ios/c++/**/*.{h,hpp}",
47 | # Views are framework-specific and should be private
48 | "nitrogen/generated/shared/**/views/**/*"
49 | ]
50 |
51 | current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {}
52 | spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({
53 | # Use C++ 20
54 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
55 | # Enables C++ <-> Swift interop (by default it's only C)
56 | "SWIFT_OBJC_INTEROP_MODE" => "objcxx",
57 | # Enables stricter modular headers
58 | "DEFINES_MODULE" => "YES",
59 | })
60 | end
61 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/c++/JHybridNitroInAppBrowserSpec.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #include
11 | #include
12 | #include "HybridNitroInAppBrowserSpec.hpp"
13 |
14 |
15 |
16 |
17 | namespace margelo::nitro::nitroinappbrowser {
18 |
19 | using namespace facebook;
20 |
21 | class JHybridNitroInAppBrowserSpec: public jni::HybridClass,
22 | public virtual HybridNitroInAppBrowserSpec {
23 | public:
24 | static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroinappbrowser/HybridNitroInAppBrowserSpec;";
25 | static jni::local_ref initHybrid(jni::alias_ref jThis);
26 | static void registerNatives();
27 |
28 | protected:
29 | // C++ constructor (called from Java via `initHybrid()`)
30 | explicit JHybridNitroInAppBrowserSpec(jni::alias_ref jThis) :
31 | HybridObject(HybridNitroInAppBrowserSpec::TAG),
32 | HybridBase(jThis),
33 | _javaPart(jni::make_global(jThis)) {}
34 |
35 | public:
36 | ~JHybridNitroInAppBrowserSpec() override {
37 | // Hermes GC can destroy JS objects on a non-JNI Thread.
38 | jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });
39 | }
40 |
41 | public:
42 | size_t getExternalMemorySize() noexcept override;
43 | void dispose() noexcept override;
44 |
45 | public:
46 | inline const jni::global_ref& getJavaPart() const noexcept {
47 | return _javaPart;
48 | }
49 |
50 | public:
51 | // Properties
52 |
53 |
54 | public:
55 | // Methods
56 | std::shared_ptr> open(const std::string& url, const std::optional& options) override;
57 | std::shared_ptr> close() override;
58 |
59 | private:
60 | friend HybridBase;
61 | using HybridBase::HybridBase;
62 | jni::global_ref _javaPart;
63 | };
64 |
65 | } // namespace margelo::nitro::nitroinappbrowser
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-nitro-in-app-browser
2 |
3 | A Simple React Native Nitro module for in-app browser.
4 |
5 | [](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/actions/workflows/android-build.yml)
6 | [](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/actions/workflows/ios-build.yml)
7 |
8 | [](https://www.npmjs.com/package/react-native-nitro-in-app-browser)
9 | [](https://www.npmjs.com/package/react-native-nitro-in-app-browser)
10 |
11 | ## Installation
12 |
13 | > [!IMPORTANT]
14 | > This package requires `react-native-nitro-modules` to be installed first.
15 | > See [react-native-nitro-modules](https://github.com/mrousavy/nitro) for more information.
16 |
17 | ```sh
18 | bun install react-native-nitro-in-app-browser react-native-nitro-modules@0.28.1
19 | cd ios && pod install && cd ..
20 | ```
21 |
22 | ## Usage
23 |
24 | ```js
25 | import React from 'react';
26 | import { Button, SafeAreaView } from 'react-native';
27 | import NitroInAppBrowser from 'react-native-nitro-in-app-browser';
28 |
29 | const App = () => {
30 | return (
31 |
32 |
48 | );
49 | };
50 |
51 | export default App;
52 | ```
53 |
54 | ## License
55 |
56 | MIT
57 |
58 | ---
59 |
60 | Bootstrapped with [Create Nitro Modules](https://github.com/patrickkabwe/create-nitro-module)
61 |
62 | ## Credits
63 |
64 | This package is based on the [react-native-nitro-modules](https://github.com/mrousavy/nitro) package.
65 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowser-Swift-Cxx-Bridge.cpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowser-Swift-Cxx-Bridge.cpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #include "NitroInAppBrowser-Swift-Cxx-Bridge.hpp"
9 |
10 | // Include C++ implementation defined types
11 | #include "HybridNitroInAppBrowserSpecSwift.hpp"
12 | #include "NitroInAppBrowser-Swift-Cxx-Umbrella.hpp"
13 |
14 | namespace margelo::nitro::nitroinappbrowser::bridge::swift {
15 |
16 | // pragma MARK: std::function
17 | Func_void create_Func_void(void* _Nonnull swiftClosureWrapper) noexcept {
18 | auto swiftClosure = NitroInAppBrowser::Func_void::fromUnsafe(swiftClosureWrapper);
19 | return [swiftClosure = std::move(swiftClosure)]() mutable -> void {
20 | swiftClosure.call();
21 | };
22 | }
23 |
24 | // pragma MARK: std::function
25 | Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* _Nonnull swiftClosureWrapper) noexcept {
26 | auto swiftClosure = NitroInAppBrowser::Func_void_std__exception_ptr::fromUnsafe(swiftClosureWrapper);
27 | return [swiftClosure = std::move(swiftClosure)](const std::exception_ptr& error) mutable -> void {
28 | swiftClosure.call(error);
29 | };
30 | }
31 |
32 | // pragma MARK: std::shared_ptr
33 | std::shared_ptr create_std__shared_ptr_HybridNitroInAppBrowserSpec_(void* _Nonnull swiftUnsafePointer) noexcept {
34 | NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx swiftPart = NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx::fromUnsafe(swiftUnsafePointer);
35 | return std::make_shared(swiftPart);
36 | }
37 | void* _Nonnull get_std__shared_ptr_HybridNitroInAppBrowserSpec_(std__shared_ptr_HybridNitroInAppBrowserSpec_ cppType) noexcept {
38 | std::shared_ptr swiftWrapper = std::dynamic_pointer_cast(cppType);
39 | #ifdef NITRO_DEBUG
40 | if (swiftWrapper == nullptr) [[unlikely]] {
41 | throw std::runtime_error("Class \"HybridNitroInAppBrowserSpec\" is not implemented in Swift!");
42 | }
43 | #endif
44 | NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();
45 | return swiftPart.toUnsafe();
46 | }
47 |
48 | } // namespace margelo::nitro::nitroinappbrowser::bridge::swift
49 |
--------------------------------------------------------------------------------
/.github/workflows/android-build.yml:
--------------------------------------------------------------------------------
1 | name: Build Android
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - '.github/workflows/android-build.yml'
9 | - 'example/android/**'
10 | - 'nitrogen/generated/shared/**'
11 | - 'nitrogen/generated/android/**'
12 | - 'cpp/**'
13 | - 'android/**'
14 | - '**/bun.lock'
15 | - '**/react-native.config.js'
16 | - '**/nitro.json'
17 | pull_request:
18 | paths:
19 | - '.github/workflows/android-build.yml'
20 | - 'example/android/**'
21 | - '**/nitrogen/generated/shared/**'
22 | - '**/nitrogen/generated/android/**'
23 | - 'cpp/**'
24 | - 'android/**'
25 | - '**/bun.lock'
26 | - '**/react-native.config.js'
27 | - '**/nitro.json'
28 |
29 | concurrency:
30 | group: ${{ github.workflow }}-${{ github.ref }}
31 | cancel-in-progress: true
32 |
33 | jobs:
34 | build_new:
35 | name: Build Android Example App (new architecture)
36 | runs-on: ubuntu-latest
37 | steps:
38 | - uses: actions/checkout@v5
39 | - uses: oven-sh/setup-bun@v2
40 |
41 | - name: Install npm dependencies (bun)
42 | run: bun install
43 |
44 | - name: Setup JDK 17
45 | uses: actions/setup-java@v5
46 | with:
47 | distribution: 'zulu'
48 | java-version: 17
49 | java-package: jdk
50 | cache: gradle
51 |
52 | - name: Run Gradle Build for example/android/
53 | working-directory: example/android
54 | run: ./gradlew assembleDebug --no-daemon --build-cache
55 |
56 | - name: Stop Gradle Daemon
57 | working-directory: example/android
58 | run: ./gradlew --stop
59 |
60 | build_old:
61 | name: Build Android Example App (old architecture)
62 | runs-on: ubuntu-latest
63 | steps:
64 | - uses: actions/checkout@v5
65 | - uses: oven-sh/setup-bun@v2
66 |
67 | - name: Install npm dependencies (bun)
68 | run: bun install
69 |
70 | - name: Disable new architecture in gradle.properties
71 | run: sed -i "s/newArchEnabled=true/newArchEnabled=false/g" example/android/gradle.properties
72 |
73 | - name: Setup JDK 17
74 | uses: actions/setup-java@v5
75 | with:
76 | distribution: 'zulu'
77 | java-version: 17
78 | java-package: jdk
79 | cache: gradle
80 |
81 | - name: Run Gradle Build for example/android/
82 | working-directory: example/android
83 | run: ./gradlew assembleDebug --no-daemon --build-cache
84 |
85 | - name: Stop Gradle Daemon
86 | working-directory: example/android
87 | run: ./gradlew --stop
88 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowser-Swift-Cxx-Umbrella.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowser-Swift-Cxx-Umbrella.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | // Forward declarations of C++ defined types
11 | // Forward declaration of `HybridNitroInAppBrowserSpec` to properly resolve imports.
12 | namespace margelo::nitro::nitroinappbrowser { class HybridNitroInAppBrowserSpec; }
13 | // Forward declaration of `NitroInAppBrowserDismissButtonLabel` to properly resolve imports.
14 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserDismissButtonLabel; }
15 | // Forward declaration of `NitroInAppBrowserOptions` to properly resolve imports.
16 | namespace margelo::nitro::nitroinappbrowser { struct NitroInAppBrowserOptions; }
17 | // Forward declaration of `NitroInAppBrowserPresentationStyle` to properly resolve imports.
18 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserPresentationStyle; }
19 |
20 | // Include C++ defined types
21 | #include "HybridNitroInAppBrowserSpec.hpp"
22 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
23 | #include "NitroInAppBrowserOptions.hpp"
24 | #include "NitroInAppBrowserPresentationStyle.hpp"
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | // C++ helpers for Swift
33 | #include "NitroInAppBrowser-Swift-Cxx-Bridge.hpp"
34 |
35 | // Common C++ types used in Swift
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | // Forward declarations of Swift defined types
42 | // Forward declaration of `HybridNitroInAppBrowserSpec_cxx` to properly resolve imports.
43 | namespace NitroInAppBrowser { class HybridNitroInAppBrowserSpec_cxx; }
44 |
45 | // Include Swift defined types
46 | #if __has_include("NitroInAppBrowser-Swift.h")
47 | // This header is generated by Xcode/Swift on every app build.
48 | // If it cannot be found, make sure the Swift module's name (= podspec name) is actually "NitroInAppBrowser".
49 | #include "NitroInAppBrowser-Swift.h"
50 | // Same as above, but used when building with frameworks (`use_frameworks`)
51 | #elif __has_include()
52 | #include
53 | #else
54 | #error NitroInAppBrowser's autogenerated Swift header cannot be found! Make sure the Swift module's name (= podspec name) is actually "NitroInAppBrowser", and try building the app first.
55 | #endif
56 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/c++/JNitroInAppBrowserDismissButtonLabel.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// JNitroInAppBrowserDismissButtonLabel.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #include
11 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
12 |
13 | namespace margelo::nitro::nitroinappbrowser {
14 |
15 | using namespace facebook;
16 |
17 | /**
18 | * The C++ JNI bridge between the C++ enum "NitroInAppBrowserDismissButtonLabel" and the the Kotlin enum "NitroInAppBrowserDismissButtonLabel".
19 | */
20 | struct JNitroInAppBrowserDismissButtonLabel final: public jni::JavaClass {
21 | public:
22 | static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroinappbrowser/NitroInAppBrowserDismissButtonLabel;";
23 |
24 | public:
25 | /**
26 | * Convert this Java/Kotlin-based enum to the C++ enum NitroInAppBrowserDismissButtonLabel.
27 | */
28 | [[maybe_unused]]
29 | [[nodiscard]]
30 | NitroInAppBrowserDismissButtonLabel toCpp() const {
31 | static const auto clazz = javaClassStatic();
32 | static const auto fieldOrdinal = clazz->getField("value");
33 | int ordinal = this->getFieldValue(fieldOrdinal);
34 | return static_cast(ordinal);
35 | }
36 |
37 | public:
38 | /**
39 | * Create a Java/Kotlin-based enum with the given C++ enum's value.
40 | */
41 | [[maybe_unused]]
42 | static jni::alias_ref fromCpp(NitroInAppBrowserDismissButtonLabel value) {
43 | static const auto clazz = javaClassStatic();
44 | static const auto fieldCANCEL = clazz->getStaticField("CANCEL");
45 | static const auto fieldDONE = clazz->getStaticField("DONE");
46 | static const auto fieldCLOSE = clazz->getStaticField("CLOSE");
47 |
48 | switch (value) {
49 | case NitroInAppBrowserDismissButtonLabel::CANCEL:
50 | return clazz->getStaticFieldValue(fieldCANCEL);
51 | case NitroInAppBrowserDismissButtonLabel::DONE:
52 | return clazz->getStaticFieldValue(fieldDONE);
53 | case NitroInAppBrowserDismissButtonLabel::CLOSE:
54 | return clazz->getStaticFieldValue(fieldCLOSE);
55 | default:
56 | std::string stringValue = std::to_string(static_cast(value));
57 | throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
58 | }
59 | }
60 | };
61 |
62 | } // namespace margelo::nitro::nitroinappbrowser
63 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/c++/JNitroInAppBrowserPresentationStyle.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// JNitroInAppBrowserPresentationStyle.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #include
11 | #include "NitroInAppBrowserPresentationStyle.hpp"
12 |
13 | namespace margelo::nitro::nitroinappbrowser {
14 |
15 | using namespace facebook;
16 |
17 | /**
18 | * The C++ JNI bridge between the C++ enum "NitroInAppBrowserPresentationStyle" and the the Kotlin enum "NitroInAppBrowserPresentationStyle".
19 | */
20 | struct JNitroInAppBrowserPresentationStyle final: public jni::JavaClass {
21 | public:
22 | static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroinappbrowser/NitroInAppBrowserPresentationStyle;";
23 |
24 | public:
25 | /**
26 | * Convert this Java/Kotlin-based enum to the C++ enum NitroInAppBrowserPresentationStyle.
27 | */
28 | [[maybe_unused]]
29 | [[nodiscard]]
30 | NitroInAppBrowserPresentationStyle toCpp() const {
31 | static const auto clazz = javaClassStatic();
32 | static const auto fieldOrdinal = clazz->getField("value");
33 | int ordinal = this->getFieldValue(fieldOrdinal);
34 | return static_cast(ordinal);
35 | }
36 |
37 | public:
38 | /**
39 | * Create a Java/Kotlin-based enum with the given C++ enum's value.
40 | */
41 | [[maybe_unused]]
42 | static jni::alias_ref fromCpp(NitroInAppBrowserPresentationStyle value) {
43 | static const auto clazz = javaClassStatic();
44 | static const auto fieldPAGESHEET = clazz->getStaticField("PAGESHEET");
45 | static const auto fieldFORMSHEET = clazz->getStaticField("FORMSHEET");
46 | static const auto fieldFULLSCREEN = clazz->getStaticField("FULLSCREEN");
47 |
48 | switch (value) {
49 | case NitroInAppBrowserPresentationStyle::PAGESHEET:
50 | return clazz->getStaticFieldValue(fieldPAGESHEET);
51 | case NitroInAppBrowserPresentationStyle::FORMSHEET:
52 | return clazz->getStaticFieldValue(fieldFORMSHEET);
53 | case NitroInAppBrowserPresentationStyle::FULLSCREEN:
54 | return clazz->getStaticFieldValue(fieldFULLSCREEN);
55 | default:
56 | std::string stringValue = std::to_string(static_cast(value));
57 | throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
58 | }
59 | }
60 | };
61 |
62 | } // namespace margelo::nitro::nitroinappbrowser
63 |
--------------------------------------------------------------------------------
/ios/SafariBrowserPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariBrowserPresenter.swift
3 | // NitroInAppBrowser
4 | //
5 | // Created by Patrick Kabwe on 19/12/2024.
6 | //
7 |
8 | import Foundation
9 | import NitroModules
10 | import SafariServices
11 |
12 | // MARK: - Browser Presenting
13 | protocol BrowserPresenting {
14 | func present(url: URL, options: NitroInAppBrowserOptions?) throws
15 | func dismiss()
16 | }
17 |
18 | class SafariBrowserPresenter: NSObject, BrowserPresenting {
19 | private weak var safariVC: SFSafariViewController?
20 | private let configuration: BrowserConfiguration
21 | private var currentBrowser: SFSafariViewController? = nil
22 | private var isPresenting = false
23 |
24 | init(configuration: BrowserConfiguration = BrowserConfiguration()) {
25 | self.configuration = configuration
26 | super.init()
27 | }
28 |
29 | func present(url: URL, options: NitroInAppBrowserOptions?) throws {
30 | guard !isPresenting else {
31 | throw RuntimeError.error(withMessage: "Browser already presenting")
32 | }
33 | let config = SFSafariViewController.Configuration()
34 | config.barCollapsingEnabled = false
35 | config.entersReaderIfAvailable = false
36 |
37 | let safariVC = SFSafariViewController(url: url, configuration: config)
38 | safariVC.delegate = self
39 | self.safariVC = safariVC
40 |
41 | configuration.configure(safariVC: safariVC, options: options)
42 |
43 | let rootVC = try getRootViewController()
44 |
45 | self.cleanupBrowser()
46 | self.isPresenting = true
47 |
48 | rootVC.present(safariVC, animated: true)
49 | }
50 |
51 | func dismiss() {
52 | cleanupBrowser()
53 | }
54 |
55 | private func cleanupBrowser() {
56 | safariVC?.dismiss(animated: true)
57 | safariVC = nil
58 | isPresenting = false
59 | }
60 |
61 |
62 | deinit {
63 | cleanupBrowser()
64 | }
65 | }
66 |
67 | extension SafariBrowserPresenter: SFSafariViewControllerDelegate {
68 | func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
69 | cleanupBrowser()
70 | }
71 | }
72 |
73 | extension SafariBrowserPresenter {
74 | func getRootViewController() throws -> UIViewController {
75 | guard let windowScene = UIApplication.shared
76 | .connectedScenes
77 | .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene,
78 | let rootVC = windowScene
79 | .windows
80 | .first(where: { $0.isKeyWindow })?
81 | .rootViewController else {
82 | throw RuntimeError.error(withMessage: "Failed to get root view controller getRootViewController(...)")
83 | }
84 | return rootVC
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/ios/NitroBrowserColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NitroBrowserColor.swift
3 | // NitroInAppBrowser
4 | //
5 | // Created by Patrick Kabwe on 19/12/2024.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 |
11 | extension UIColor {
12 | convenience init?(value: String) {
13 | let r, g, b, a: CGFloat
14 | let value = value.trimmingCharacters(in: .whitespacesAndNewlines)
15 |
16 | if value.hasPrefix("#") {
17 | let start = value.index(value.startIndex, offsetBy: 1)
18 | let hexColor = String(value[start...])
19 |
20 | if hexColor.count == 6 {
21 | let scanner = Scanner(string: hexColor)
22 | var hexNumber: UInt64 = 0
23 |
24 | if scanner.scanHexInt64(&hexNumber) {
25 | r = CGFloat((hexNumber & 0xff0000) >> 16) / 255
26 | g = CGFloat((hexNumber & 0x00ff00) >> 8) / 255
27 | b = CGFloat(hexNumber & 0x0000ff) / 255
28 | a = 1.0
29 |
30 | self.init(red: r, green: g, blue: b, alpha: a)
31 | return
32 | }
33 | }
34 | } else {
35 | let colorName = value.lowercased()
36 | switch colorName {
37 | case "black":
38 | self.init(red: 0, green: 0, blue: 0, alpha: 1)
39 | case "darkgray", "darkgrey":
40 | self.init(red: 0.333, green: 0.333, blue: 0.333, alpha: 1)
41 | case "lightgray", "lightgrey":
42 | self.init(red: 0.667, green: 0.667, blue: 0.667, alpha: 1)
43 | case "white":
44 | self.init(red: 1, green: 1, blue: 1, alpha: 1)
45 | case "gray", "grey":
46 | self.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)
47 | case "red":
48 | self.init(red: 1, green: 0, blue: 0, alpha: 1)
49 | case "green":
50 | self.init(red: 0, green: 1, blue: 0, alpha: 1)
51 | case "blue":
52 | self.init(red: 0, green: 0, blue: 1, alpha: 1)
53 | case "cyan":
54 | self.init(red: 0, green: 1, blue: 1, alpha: 1)
55 | case "yellow":
56 | self.init(red: 1, green: 1, blue: 0, alpha: 1)
57 | case "magenta":
58 | self.init(red: 1, green: 0, blue: 1, alpha: 1)
59 | case "orange":
60 | self.init(red: 1, green: 0.5, blue: 0, alpha: 1)
61 | case "purple":
62 | self.init(red: 0.5, green: 0, blue: 0.5, alpha: 1)
63 | case "brown":
64 | self.init(red: 0.6, green: 0.4, blue: 0.2, alpha: 1)
65 | case "clear":
66 | self.init(red: 0, green: 0, blue: 0, alpha: 0)
67 | default:
68 | return nil
69 | }
70 | return
71 | }
72 | return nil
73 | }
74 | }
75 |
76 |
77 |
--------------------------------------------------------------------------------
/android/src/main/java/com/nitroinappbrowser/NitroInAppBrowserImpl.kt:
--------------------------------------------------------------------------------
1 | package com.nitroinappbrowser
2 |
3 | import android.content.pm.PackageManager
4 | import android.net.Uri
5 | import android.util.Log
6 | import androidx.browser.customtabs.CustomTabColorSchemeParams
7 | import androidx.browser.customtabs.CustomTabsIntent
8 | import com.facebook.react.bridge.ReactApplicationContext
9 | import com.margelo.nitro.core.Promise
10 | import com.margelo.nitro.nitroinappbrowser.NitroInAppBrowserOptions
11 | import androidx.core.graphics.toColorInt
12 | import androidx.core.net.toUri
13 |
14 |
15 | class NitroInAppBrowserImpl(private val reactContext: ReactApplicationContext?) {
16 |
17 | private val chromePackageName = "com.android.chrome"
18 |
19 | fun open(url: String, options: NitroInAppBrowserOptions?): Promise {
20 | if (url.isEmpty()){
21 | Log.d(TAG, "Empty URL")
22 | throw Error("Empty URL")
23 | }
24 | if (!url.startsWith("http://") && !url.startsWith("https://")){
25 | Log.d(TAG, "Invalid URL")
26 | throw Error("Invalid URL")
27 | }
28 |
29 | val customTabParams = CustomTabColorSchemeParams.Builder()
30 | if (options?.barColor != null){
31 | customTabParams.setToolbarColor(getColor(options.barColor))
32 | customTabParams.setSecondaryToolbarColor(getColor(options.barColor))
33 | customTabParams.setNavigationBarColor(getColor(options.barColor))
34 | }
35 |
36 | val customTabIntent = CustomTabsIntent.Builder()
37 | customTabIntent.setShowTitle(false)
38 | customTabIntent.setInstantAppsEnabled(false)
39 | customTabIntent.setDefaultColorSchemeParams(customTabParams.build())
40 | customTabIntent.setShareState(CustomTabsIntent.SHARE_STATE_ON)
41 |
42 | val intent = customTabIntent.build()
43 | intent.apply {
44 | if (!isPackageInstalled()){
45 | Log.d(TAG, "Chrome not installed")
46 | } else {
47 | intent.intent.setPackage(chromePackageName)
48 | }
49 | }
50 | val currentActivity = reactContext?.currentActivity ?: throw Error("No Activity")
51 | intent.launchUrl(currentActivity, url.toUri())
52 | return Promise.resolved(Unit)
53 | }
54 |
55 | fun close(){
56 | Log.d(TAG,"Closing Browser")
57 | reactContext?.currentActivity?.finish()
58 | }
59 |
60 | private fun getColor(color: String): Int{
61 | return try {
62 | color.toColorInt()
63 | } catch (e: IllegalArgumentException){
64 | "#ffffff".toColorInt()
65 | }
66 | }
67 |
68 | private fun isPackageInstalled(): Boolean {
69 | return try {
70 | reactContext?.packageManager?.getPackageInfo(chromePackageName, 0)
71 | true
72 | } catch (e: PackageManager.NameNotFoundException) {
73 | false
74 | }
75 | }
76 |
77 | companion object {
78 | const val TAG = "NitroInAppBrowserImpl"
79 | }
80 | }
--------------------------------------------------------------------------------
/nitrogen/generated/android/NitroInAppBrowser+autolinking.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # NitroInAppBrowser+autolinking.cmake
3 | # This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | # https://github.com/mrousavy/nitro
5 | # Copyright © 2025 Marc Rousavy @ Margelo
6 | #
7 |
8 | # This is a CMake file that adds all files generated by Nitrogen
9 | # to the current CMake project.
10 | #
11 | # To use it, add this to your CMakeLists.txt:
12 | # ```cmake
13 | # include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroInAppBrowser+autolinking.cmake)
14 | # ```
15 |
16 | # Add all headers that were generated by Nitrogen
17 | include_directories(
18 | "../nitrogen/generated/shared/c++"
19 | "../nitrogen/generated/android/c++"
20 | "../nitrogen/generated/android/"
21 | )
22 |
23 | # Add all .cpp sources that were generated by Nitrogen
24 | target_sources(
25 | # CMake project name (Android C++ library name)
26 | NitroInAppBrowser PRIVATE
27 | # Autolinking Setup
28 | ../nitrogen/generated/android/NitroInAppBrowserOnLoad.cpp
29 | # Shared Nitrogen C++ sources
30 | ../nitrogen/generated/shared/c++/HybridNitroInAppBrowserSpec.cpp
31 | # Android-specific Nitrogen C++ sources
32 | ../nitrogen/generated/android/c++/JHybridNitroInAppBrowserSpec.cpp
33 | )
34 |
35 | # Define a flag to check if we are building properly
36 | add_definitions(-DBUILDING_NITROINAPPBROWSER_WITH_GENERATED_CMAKE_PROJECT)
37 |
38 | # From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake
39 | # Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake
40 | target_compile_definitions(
41 | NitroInAppBrowser PRIVATE
42 | -DFOLLY_NO_CONFIG=1
43 | -DFOLLY_HAVE_CLOCK_GETTIME=1
44 | -DFOLLY_USE_LIBCPP=1
45 | -DFOLLY_CFG_NO_COROUTINES=1
46 | -DFOLLY_MOBILE=1
47 | -DFOLLY_HAVE_RECVMMSG=1
48 | -DFOLLY_HAVE_PTHREAD=1
49 | # Once we target android-23 above, we can comment
50 | # the following line. NDK uses GNU style stderror_r() after API 23.
51 | -DFOLLY_HAVE_XSI_STRERROR_R=1
52 | )
53 |
54 | # Add all libraries required by the generated specs
55 | find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++
56 | find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule)
57 | find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library
58 |
59 | # Link all libraries together
60 | target_link_libraries(
61 | NitroInAppBrowser
62 | fbjni::fbjni # <-- Facebook C++ JNI helpers
63 | ReactAndroid::jsi # <-- RN: JSI
64 | react-native-nitro-modules::NitroModules # <-- NitroModules Core :)
65 | )
66 |
67 | # Link react-native (different prefab between RN 0.75 and RN 0.76)
68 | if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
69 | target_link_libraries(
70 | NitroInAppBrowser
71 | ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab
72 | )
73 | else()
74 | target_link_libraries(
75 | NitroInAppBrowser
76 | ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core
77 | )
78 | endif()
79 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/example/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.7)
5 | base64
6 | nkf
7 | rexml
8 | activesupport (7.2.3)
9 | base64
10 | benchmark (>= 0.3)
11 | bigdecimal
12 | concurrent-ruby (~> 1.0, >= 1.3.1)
13 | connection_pool (>= 2.2.5)
14 | drb
15 | i18n (>= 1.6, < 2)
16 | logger (>= 1.4.2)
17 | minitest (>= 5.1)
18 | securerandom (>= 0.3)
19 | tzinfo (~> 2.0, >= 2.0.5)
20 | addressable (2.8.7)
21 | public_suffix (>= 2.0.2, < 7.0)
22 | algoliasearch (1.27.5)
23 | httpclient (~> 2.8, >= 2.8.3)
24 | json (>= 1.5.1)
25 | atomos (0.1.3)
26 | base64 (0.3.0)
27 | benchmark (0.5.0)
28 | bigdecimal (3.3.1)
29 | claide (1.1.0)
30 | cocoapods (1.16.2)
31 | addressable (~> 2.8)
32 | claide (>= 1.0.2, < 2.0)
33 | cocoapods-core (= 1.16.2)
34 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
35 | cocoapods-downloader (>= 2.1, < 3.0)
36 | cocoapods-plugins (>= 1.0.0, < 2.0)
37 | cocoapods-search (>= 1.0.0, < 2.0)
38 | cocoapods-trunk (>= 1.6.0, < 2.0)
39 | cocoapods-try (>= 1.1.0, < 2.0)
40 | colored2 (~> 3.1)
41 | escape (~> 0.0.4)
42 | fourflusher (>= 2.3.0, < 3.0)
43 | gh_inspector (~> 1.0)
44 | molinillo (~> 0.8.0)
45 | nap (~> 1.0)
46 | ruby-macho (>= 2.3.0, < 3.0)
47 | xcodeproj (>= 1.27.0, < 2.0)
48 | cocoapods-core (1.16.2)
49 | activesupport (>= 5.0, < 8)
50 | addressable (~> 2.8)
51 | algoliasearch (~> 1.0)
52 | concurrent-ruby (~> 1.1)
53 | fuzzy_match (~> 2.0.4)
54 | nap (~> 1.0)
55 | netrc (~> 0.11)
56 | public_suffix (~> 4.0)
57 | typhoeus (~> 1.0)
58 | cocoapods-deintegrate (1.0.5)
59 | cocoapods-downloader (2.1)
60 | cocoapods-plugins (1.0.0)
61 | nap
62 | cocoapods-search (1.0.1)
63 | cocoapods-trunk (1.6.0)
64 | nap (>= 0.8, < 2.0)
65 | netrc (~> 0.11)
66 | cocoapods-try (1.2.0)
67 | colored2 (3.1.2)
68 | concurrent-ruby (1.3.5)
69 | connection_pool (2.5.4)
70 | drb (2.2.3)
71 | escape (0.0.4)
72 | ethon (0.16.0)
73 | ffi (>= 1.15.0)
74 | ffi (1.17.2)
75 | fourflusher (2.3.1)
76 | fuzzy_match (2.0.4)
77 | gh_inspector (1.1.3)
78 | httpclient (2.9.0)
79 | mutex_m
80 | i18n (1.14.7)
81 | concurrent-ruby (~> 1.0)
82 | json (2.12.0)
83 | logger (1.7.0)
84 | minitest (5.26.0)
85 | molinillo (0.8.0)
86 | mutex_m (0.3.0)
87 | nanaimo (0.4.0)
88 | nap (1.1.0)
89 | netrc (0.11.0)
90 | nkf (0.2.0)
91 | public_suffix (4.0.7)
92 | rexml (3.4.2)
93 | ruby-macho (2.5.1)
94 | securerandom (0.4.1)
95 | typhoeus (1.4.1)
96 | ethon (>= 0.9.0)
97 | tzinfo (2.0.6)
98 | concurrent-ruby (~> 1.0)
99 | xcodeproj (1.27.0)
100 | CFPropertyList (>= 2.3.3, < 4.0)
101 | atomos (~> 0.1.3)
102 | claide (>= 1.0.2, < 2.0)
103 | colored2 (~> 3.1)
104 | nanaimo (~> 0.4.0)
105 | rexml (>= 3.3.6, < 4.0)
106 |
107 | PLATFORMS
108 | ruby
109 |
110 | DEPENDENCIES
111 | activesupport (>= 6.1.7.5, != 7.1.0)
112 | benchmark
113 | bigdecimal
114 | cocoapods (>= 1.13, != 1.15.1, != 1.15.0)
115 | concurrent-ruby (< 1.3.6)
116 | logger
117 | mutex_m
118 | xcodeproj (< 1.28.0)
119 |
120 | RUBY VERSION
121 | ruby 3.3.6p108
122 |
123 | BUNDLED WITH
124 | 2.5.22
125 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/c++/JNitroInAppBrowserOptions.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// JNitroInAppBrowserOptions.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #include
11 | #include "NitroInAppBrowserOptions.hpp"
12 |
13 | #include "JNitroInAppBrowserDismissButtonLabel.hpp"
14 | #include "JNitroInAppBrowserPresentationStyle.hpp"
15 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
16 | #include "NitroInAppBrowserPresentationStyle.hpp"
17 | #include
18 | #include
19 |
20 | namespace margelo::nitro::nitroinappbrowser {
21 |
22 | using namespace facebook;
23 |
24 | /**
25 | * The C++ JNI bridge between the C++ struct "NitroInAppBrowserOptions" and the the Kotlin data class "NitroInAppBrowserOptions".
26 | */
27 | struct JNitroInAppBrowserOptions final: public jni::JavaClass {
28 | public:
29 | static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroinappbrowser/NitroInAppBrowserOptions;";
30 |
31 | public:
32 | /**
33 | * Convert this Java/Kotlin-based struct to the C++ struct NitroInAppBrowserOptions by copying all values to C++.
34 | */
35 | [[maybe_unused]]
36 | [[nodiscard]]
37 | NitroInAppBrowserOptions toCpp() const {
38 | static const auto clazz = javaClassStatic();
39 | static const auto fieldDismissButtonLabel = clazz->getField("dismissButtonLabel");
40 | jni::local_ref dismissButtonLabel = this->getFieldValue(fieldDismissButtonLabel);
41 | static const auto fieldPresentationStyle = clazz->getField("presentationStyle");
42 | jni::local_ref presentationStyle = this->getFieldValue(fieldPresentationStyle);
43 | static const auto fieldBarColor = clazz->getField("barColor");
44 | jni::local_ref barColor = this->getFieldValue(fieldBarColor);
45 | static const auto fieldControlColor = clazz->getField("controlColor");
46 | jni::local_ref controlColor = this->getFieldValue(fieldControlColor);
47 | return NitroInAppBrowserOptions(
48 | dismissButtonLabel != nullptr ? std::make_optional(dismissButtonLabel->toCpp()) : std::nullopt,
49 | presentationStyle != nullptr ? std::make_optional(presentationStyle->toCpp()) : std::nullopt,
50 | barColor != nullptr ? std::make_optional(barColor->toStdString()) : std::nullopt,
51 | controlColor != nullptr ? std::make_optional(controlColor->toStdString()) : std::nullopt
52 | );
53 | }
54 |
55 | public:
56 | /**
57 | * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
58 | */
59 | [[maybe_unused]]
60 | static jni::local_ref fromCpp(const NitroInAppBrowserOptions& value) {
61 | return newInstance(
62 | value.dismissButtonLabel.has_value() ? JNitroInAppBrowserDismissButtonLabel::fromCpp(value.dismissButtonLabel.value()) : nullptr,
63 | value.presentationStyle.has_value() ? JNitroInAppBrowserPresentationStyle::fromCpp(value.presentationStyle.value()) : nullptr,
64 | value.barColor.has_value() ? jni::make_jstring(value.barColor.value()) : nullptr,
65 | value.controlColor.has_value() ? jni::make_jstring(value.controlColor.value()) : nullptr
66 | );
67 | }
68 | };
69 |
70 | } // namespace margelo::nitro::nitroinappbrowser
71 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/c++/HybridNitroInAppBrowserSpecSwift.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpecSwift.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #include "HybridNitroInAppBrowserSpec.hpp"
11 |
12 | // Forward declaration of `HybridNitroInAppBrowserSpec_cxx` to properly resolve imports.
13 | namespace NitroInAppBrowser { class HybridNitroInAppBrowserSpec_cxx; }
14 |
15 | // Forward declaration of `NitroInAppBrowserOptions` to properly resolve imports.
16 | namespace margelo::nitro::nitroinappbrowser { struct NitroInAppBrowserOptions; }
17 | // Forward declaration of `NitroInAppBrowserDismissButtonLabel` to properly resolve imports.
18 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserDismissButtonLabel; }
19 | // Forward declaration of `NitroInAppBrowserPresentationStyle` to properly resolve imports.
20 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserPresentationStyle; }
21 |
22 | #include
23 | #include
24 | #include "NitroInAppBrowserOptions.hpp"
25 | #include
26 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
27 | #include "NitroInAppBrowserPresentationStyle.hpp"
28 |
29 | #include "NitroInAppBrowser-Swift-Cxx-Umbrella.hpp"
30 |
31 | namespace margelo::nitro::nitroinappbrowser {
32 |
33 | /**
34 | * The C++ part of HybridNitroInAppBrowserSpec_cxx.swift.
35 | *
36 | * HybridNitroInAppBrowserSpecSwift (C++) accesses HybridNitroInAppBrowserSpec_cxx (Swift), and might
37 | * contain some additional bridging code for C++ <> Swift interop.
38 | *
39 | * Since this obviously introduces an overhead, I hope at some point in
40 | * the future, HybridNitroInAppBrowserSpec_cxx can directly inherit from the C++ class HybridNitroInAppBrowserSpec
41 | * to simplify the whole structure and memory management.
42 | */
43 | class HybridNitroInAppBrowserSpecSwift: public virtual HybridNitroInAppBrowserSpec {
44 | public:
45 | // Constructor from a Swift instance
46 | explicit HybridNitroInAppBrowserSpecSwift(const NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx& swiftPart):
47 | HybridObject(HybridNitroInAppBrowserSpec::TAG),
48 | _swiftPart(swiftPart) { }
49 |
50 | public:
51 | // Get the Swift part
52 | inline NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx& getSwiftPart() noexcept {
53 | return _swiftPart;
54 | }
55 |
56 | public:
57 | inline size_t getExternalMemorySize() noexcept override {
58 | return _swiftPart.getMemorySize();
59 | }
60 | void dispose() noexcept override {
61 | _swiftPart.dispose();
62 | }
63 |
64 | public:
65 | // Properties
66 |
67 |
68 | public:
69 | // Methods
70 | inline std::shared_ptr> open(const std::string& url, const std::optional& options) override {
71 | auto __result = _swiftPart.open(url, options);
72 | if (__result.hasError()) [[unlikely]] {
73 | std::rethrow_exception(__result.error());
74 | }
75 | auto __value = std::move(__result.value());
76 | return __value;
77 | }
78 | inline std::shared_ptr> close() override {
79 | auto __result = _swiftPart.close();
80 | if (__result.hasError()) [[unlikely]] {
81 | std::rethrow_exception(__result.error());
82 | }
83 | auto __value = std::move(__result.value());
84 | return __value;
85 | }
86 |
87 | private:
88 | NitroInAppBrowser::HybridNitroInAppBrowserSpec_cxx _swiftPart;
89 | };
90 |
91 | } // namespace margelo::nitro::nitroinappbrowser
92 |
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample.xcodeproj/xcshareddata/xcschemes/NitroInAppBrowserExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
2 |
3 | # Getting Started
4 |
5 | > **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.
6 |
7 | ## Step 1: Start Metro
8 |
9 | First, you will need to run **Metro**, the JavaScript build tool for React Native.
10 |
11 | To start the Metro dev server, run the following command from the root of your React Native project:
12 |
13 | ```sh
14 | # Using npm
15 | npm start
16 |
17 | # OR using Yarn
18 | yarn start
19 | ```
20 |
21 | ## Step 2: Build and run your app
22 |
23 | With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:
24 |
25 | ### Android
26 |
27 | ```sh
28 | # Using npm
29 | npm run android
30 |
31 | # OR using Yarn
32 | yarn android
33 | ```
34 |
35 | ### iOS
36 |
37 | For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).
38 |
39 | The first time you create a new project, run the Ruby bundler to install CocoaPods itself:
40 |
41 | ```sh
42 | bundle install
43 | ```
44 |
45 | Then, and every time you update your native dependencies, run:
46 |
47 | ```sh
48 | bundle exec pod install
49 | ```
50 |
51 | For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).
52 |
53 | ```sh
54 | # Using npm
55 | npm run ios
56 |
57 | # OR using Yarn
58 | yarn ios
59 | ```
60 |
61 | If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.
62 |
63 | This is one way to run your app — you can also build it directly from Android Studio or Xcode.
64 |
65 | ## Step 3: Modify your app
66 |
67 | Now that you have successfully run the app, let's make changes!
68 |
69 | Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).
70 |
71 | When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:
72 |
73 | - **Android**: Press the R key twice or select **"Reload"** from the **Dev Menu**, accessed via Ctrl + M (Windows/Linux) or Cmd ⌘ + M (macOS).
74 | - **iOS**: Press R in iOS Simulator.
75 |
76 | ## Congratulations! :tada:
77 |
78 | You've successfully run and modified your React Native App. :partying_face:
79 |
80 | ### Now what?
81 |
82 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
83 | - If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).
84 |
85 | # Troubleshooting
86 |
87 | If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
88 |
89 | # Learn More
90 |
91 | To learn more about React Native, take a look at the following resources:
92 |
93 | - [React Native Website](https://reactnative.dev) - learn more about React Native.
94 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
95 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
96 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
97 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
98 |
--------------------------------------------------------------------------------
/nitrogen/generated/shared/c++/NitroInAppBrowserDismissButtonLabel.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserDismissButtonLabel.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #if __has_include()
11 | #include
12 | #else
13 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14 | #endif
15 | #if __has_include()
16 | #include
17 | #else
18 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19 | #endif
20 | #if __has_include()
21 | #include
22 | #else
23 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24 | #endif
25 |
26 | namespace margelo::nitro::nitroinappbrowser {
27 |
28 | /**
29 | * An enum which can be represented as a JavaScript union (NitroInAppBrowserDismissButtonLabel).
30 | */
31 | enum class NitroInAppBrowserDismissButtonLabel {
32 | CANCEL SWIFT_NAME(cancel) = 0,
33 | DONE SWIFT_NAME(done) = 1,
34 | CLOSE SWIFT_NAME(close) = 2,
35 | } CLOSED_ENUM;
36 |
37 | } // namespace margelo::nitro::nitroinappbrowser
38 |
39 | namespace margelo::nitro {
40 |
41 | // C++ NitroInAppBrowserDismissButtonLabel <> JS NitroInAppBrowserDismissButtonLabel (union)
42 | template <>
43 | struct JSIConverter final {
44 | static inline margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
45 | std::string unionValue = JSIConverter::fromJSI(runtime, arg);
46 | switch (hashString(unionValue.c_str(), unionValue.size())) {
47 | case hashString("cancel"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::CANCEL;
48 | case hashString("done"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::DONE;
49 | case hashString("close"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::CLOSE;
50 | default: [[unlikely]]
51 | throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum NitroInAppBrowserDismissButtonLabel - invalid value!");
52 | }
53 | }
54 | static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel arg) {
55 | switch (arg) {
56 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::CANCEL: return JSIConverter::toJSI(runtime, "cancel");
57 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::DONE: return JSIConverter::toJSI(runtime, "done");
58 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserDismissButtonLabel::CLOSE: return JSIConverter::toJSI(runtime, "close");
59 | default: [[unlikely]]
60 | throw std::invalid_argument("Cannot convert NitroInAppBrowserDismissButtonLabel to JS - invalid value: "
61 | + std::to_string(static_cast(arg)) + "!");
62 | }
63 | }
64 | static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
65 | if (!value.isString()) {
66 | return false;
67 | }
68 | std::string unionValue = JSIConverter::fromJSI(runtime, value);
69 | switch (hashString(unionValue.c_str(), unionValue.size())) {
70 | case hashString("cancel"):
71 | case hashString("done"):
72 | case hashString("close"):
73 | return true;
74 | default:
75 | return false;
76 | }
77 | }
78 | };
79 |
80 | } // namespace margelo::nitro
81 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [2.0.0](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.2.0...v2.0.0) (2025-08-17)
2 |
3 | ### ⚠ BREAKING CHANGES
4 |
5 | * **ios:** No more `NitroInAppBrowserPresentationStyle` enum import required. Use string literals directly for presentation types.
6 |
7 | ### ✨ Features
8 |
9 | * **ios:** replace enum import with direct string types for `presentationStyle` ([5508dd5](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/5508dd57f6acf537b4aa3417d6016ab5cf15e7f4))
10 |
11 | ### 🛠️ Other changes
12 |
13 | * bump up nitro to v0.28.0 ([7776c7c](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/7776c7c6efdcdfdcd82ff3b13612693311149278))
14 | * update dependencies and improve iOS build configuration ([1a4751a](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/1a4751a694da4ffdd62292d3ccfeba0f3ff1dea3))
15 | * update Xcode version in iOS build workflow to 16.4 ([2e32094](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/2e320941a9140bd693b7928ded4206f61de6f2d3))
16 | * update Xcode version in iOS build workflow to latest stable ([f0582c9](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/f0582c9ef41cb22db20835adbd4c48c8084aa221))
17 |
18 | ## [1.2.0](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.9...v1.2.0) (2025-07-31)
19 |
20 | ### ✨ Features
21 |
22 | * Enable 16KB page size support ([6347427](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/6347427d0146adfedc7da8f69e6f47a1e1b6d830))
23 | * Enable 16KB page size support ([64ce999](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/64ce9994665ed6b2d87a30ed1ffa0c6ebbfd5500))
24 |
25 | ## [1.1.9](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.8...v1.1.9) (2025-07-14)
26 |
27 | ### 🛠️ Other changes
28 |
29 | * **deps-dev:** bump conventional-changelog-conventionalcommits ([44b8c80](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/44b8c80165e8ca3d73e86f91c88cbca2d196455f))
30 |
31 | ## [1.1.8](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.7...v1.1.8) (2025-07-14)
32 |
33 | ### 🛠️ Other changes
34 |
35 | * **deps-dev:** bump semantic-release from 24.2.3 to 24.2.6 ([26497d0](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/26497d0fb632b856a46b820d591bc585e8ea31f6))
36 | * **deps:** bump com.android.tools.build:gradle in /android ([3aea5a5](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/3aea5a5375b214d2c6719391bc9ecd63e9aa8875))
37 | * update nitro-codegen and react-native-nitro-modules to version 0.26.3; bump NitroInAppBrowser to 1.1.7 ([534c3fd](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/534c3fd92cde36f3bb804a1d18908c0ab0e24414))
38 |
39 | ## [1.1.7](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.6...v1.1.7) (2025-07-14)
40 |
41 | ### 🛠️ Other changes
42 |
43 | * bump up nitro ([11a29c5](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/11a29c53621605d849640ff0651dcdeb10f26bff))
44 | * bump up nitro ([3e13409](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/3e13409f824532d0aad6271c774f3e0c52d4dd65))
45 |
46 | ## [1.1.6](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.5...v1.1.6) (2025-06-07)
47 |
48 | ### 🛠️ Other changes
49 |
50 | * **deps:** update nitro-codegen and react-native-nitro-modules to version 0.26.2 ([bfa40ce](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/bfa40ce9ee07a98812f5b0060a58650088872ed0))
51 |
52 | ## [1.1.5](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/compare/v1.1.4...v1.1.5) (2025-05-19)
53 |
54 | ### 🛠️ Other changes
55 |
56 | * **deps:** update semantic-release and related packages ([589c1cd](https://github.com/patrickkabwe/react-native-nitro-in-app-browser/commit/589c1cda87a71520e3017051a5a0143461c30f23))
57 |
--------------------------------------------------------------------------------
/nitrogen/generated/shared/c++/NitroInAppBrowserPresentationStyle.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserPresentationStyle.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #if __has_include()
11 | #include
12 | #else
13 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14 | #endif
15 | #if __has_include()
16 | #include
17 | #else
18 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19 | #endif
20 | #if __has_include()
21 | #include
22 | #else
23 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24 | #endif
25 |
26 | namespace margelo::nitro::nitroinappbrowser {
27 |
28 | /**
29 | * An enum which can be represented as a JavaScript union (NitroInAppBrowserPresentationStyle).
30 | */
31 | enum class NitroInAppBrowserPresentationStyle {
32 | PAGESHEET SWIFT_NAME(pagesheet) = 0,
33 | FORMSHEET SWIFT_NAME(formsheet) = 1,
34 | FULLSCREEN SWIFT_NAME(fullscreen) = 2,
35 | } CLOSED_ENUM;
36 |
37 | } // namespace margelo::nitro::nitroinappbrowser
38 |
39 | namespace margelo::nitro {
40 |
41 | // C++ NitroInAppBrowserPresentationStyle <> JS NitroInAppBrowserPresentationStyle (union)
42 | template <>
43 | struct JSIConverter final {
44 | static inline margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
45 | std::string unionValue = JSIConverter::fromJSI(runtime, arg);
46 | switch (hashString(unionValue.c_str(), unionValue.size())) {
47 | case hashString("pageSheet"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::PAGESHEET;
48 | case hashString("formSheet"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::FORMSHEET;
49 | case hashString("fullScreen"): return margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::FULLSCREEN;
50 | default: [[unlikely]]
51 | throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum NitroInAppBrowserPresentationStyle - invalid value!");
52 | }
53 | }
54 | static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle arg) {
55 | switch (arg) {
56 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::PAGESHEET: return JSIConverter::toJSI(runtime, "pageSheet");
57 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::FORMSHEET: return JSIConverter::toJSI(runtime, "formSheet");
58 | case margelo::nitro::nitroinappbrowser::NitroInAppBrowserPresentationStyle::FULLSCREEN: return JSIConverter::toJSI(runtime, "fullScreen");
59 | default: [[unlikely]]
60 | throw std::invalid_argument("Cannot convert NitroInAppBrowserPresentationStyle to JS - invalid value: "
61 | + std::to_string(static_cast(arg)) + "!");
62 | }
63 | }
64 | static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
65 | if (!value.isString()) {
66 | return false;
67 | }
68 | std::string unionValue = JSIConverter::fromJSI(runtime, value);
69 | switch (hashString(unionValue.c_str(), unionValue.size())) {
70 | case hashString("pageSheet"):
71 | case hashString("formSheet"):
72 | case hashString("fullScreen"):
73 | return true;
74 | default:
75 | return false;
76 | }
77 | }
78 | };
79 |
80 | } // namespace margelo::nitro
81 |
--------------------------------------------------------------------------------
/nitrogen/generated/android/c++/JHybridNitroInAppBrowserSpec.cpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// JHybridNitroInAppBrowserSpec.cpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #include "JHybridNitroInAppBrowserSpec.hpp"
9 |
10 | // Forward declaration of `NitroInAppBrowserOptions` to properly resolve imports.
11 | namespace margelo::nitro::nitroinappbrowser { struct NitroInAppBrowserOptions; }
12 | // Forward declaration of `NitroInAppBrowserDismissButtonLabel` to properly resolve imports.
13 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserDismissButtonLabel; }
14 | // Forward declaration of `NitroInAppBrowserPresentationStyle` to properly resolve imports.
15 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserPresentationStyle; }
16 |
17 | #include
18 | #include
19 | #include
20 | #include "NitroInAppBrowserOptions.hpp"
21 | #include
22 | #include "JNitroInAppBrowserOptions.hpp"
23 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
24 | #include "JNitroInAppBrowserDismissButtonLabel.hpp"
25 | #include "NitroInAppBrowserPresentationStyle.hpp"
26 | #include "JNitroInAppBrowserPresentationStyle.hpp"
27 |
28 | namespace margelo::nitro::nitroinappbrowser {
29 |
30 | jni::local_ref JHybridNitroInAppBrowserSpec::initHybrid(jni::alias_ref jThis) {
31 | return makeCxxInstance(jThis);
32 | }
33 |
34 | void JHybridNitroInAppBrowserSpec::registerNatives() {
35 | registerHybrid({
36 | makeNativeMethod("initHybrid", JHybridNitroInAppBrowserSpec::initHybrid),
37 | });
38 | }
39 |
40 | size_t JHybridNitroInAppBrowserSpec::getExternalMemorySize() noexcept {
41 | static const auto method = javaClassStatic()->getMethod("getMemorySize");
42 | return method(_javaPart);
43 | }
44 |
45 | void JHybridNitroInAppBrowserSpec::dispose() noexcept {
46 | static const auto method = javaClassStatic()->getMethod("dispose");
47 | method(_javaPart);
48 | }
49 |
50 | // Properties
51 |
52 |
53 | // Methods
54 | std::shared_ptr> JHybridNitroInAppBrowserSpec::open(const std::string& url, const std::optional& options) {
55 | static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* url */, jni::alias_ref /* options */)>("open");
56 | auto __result = method(_javaPart, jni::make_jstring(url), options.has_value() ? JNitroInAppBrowserOptions::fromCpp(options.value()) : nullptr);
57 | return [&]() {
58 | auto __promise = Promise::create();
59 | __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& /* unit */) {
60 | __promise->resolve();
61 | });
62 | __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) {
63 | jni::JniException __jniError(__throwable);
64 | __promise->reject(std::make_exception_ptr(__jniError));
65 | });
66 | return __promise;
67 | }();
68 | }
69 | std::shared_ptr> JHybridNitroInAppBrowserSpec::close() {
70 | static const auto method = javaClassStatic()->getMethod()>("close");
71 | auto __result = method(_javaPart);
72 | return [&]() {
73 | auto __promise = Promise::create();
74 | __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& /* unit */) {
75 | __promise->resolve();
76 | });
77 | __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) {
78 | jni::JniException __jniError(__throwable);
79 | __promise->reject(std::make_exception_ptr(__jniError));
80 | });
81 | return __promise;
82 | }();
83 | }
84 |
85 | } // namespace margelo::nitro::nitroinappbrowser
86 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-nitro-in-app-browser",
3 | "version": "2.0.0",
4 | "description": "Nitro module package",
5 | "main": "./lib/commonjs/index.js",
6 | "module": "./lib/module/index.js",
7 | "types": "./lib/typescript/src/index.d.ts",
8 | "react-native": "src/index",
9 | "source": "src/index",
10 | "scripts": {
11 | "typecheck": "tsc --noEmit",
12 | "clean": "git clean -dfX",
13 | "release": "semantic-release",
14 | "build": "bun run typecheck && bob build",
15 | "codegen": "nitro-codegen --logLevel=\"debug\" && bun run build && node post-script.js",
16 | "postcodegen": "bun --cwd example pod"
17 | },
18 | "keywords": [
19 | "react-native",
20 | "nitro",
21 | "in-app-browser",
22 | "in-app-browser-module",
23 | "react-native-nitro-in-app-browser"
24 | ],
25 | "files": [
26 | "src",
27 | "react-native.config.js",
28 | "lib",
29 | "nitrogen",
30 | "cpp",
31 | "android/build.gradle",
32 | "android/gradle.properties",
33 | "android/CMakeLists.txt",
34 | "android/src",
35 | "ios/**/*.h",
36 | "ios/**/*.m",
37 | "ios/**/*.mm",
38 | "ios/**/*.cpp",
39 | "ios/**/*.swift",
40 | "app.plugin.js",
41 | "*.podspec",
42 | "README.md"
43 | ],
44 | "workspaces": [
45 | "example"
46 | ],
47 | "repository": "https://github.com/patrickkabwe/react-native-nitro-in-app-browser.git",
48 | "author": "Patrick Kabwe",
49 | "license": "MIT",
50 | "bugs": "https://github.com/patrickkabwe/react-native-nitro-in-app-browser/issues",
51 | "homepage": "https://github.com/patrickkabwe/react-native-nitro-in-app-browser#readme",
52 | "publishConfig": {
53 | "registry": "https://registry.npmjs.org/",
54 | "provenance": true
55 | },
56 | "devDependencies": {
57 | "@jamesacarr/eslint-formatter-github-actions": "^0.2.0",
58 | "@semantic-release/changelog": "^6.0.3",
59 | "@semantic-release/git": "^10.0.1",
60 | "@types/jest": "^29.5.12",
61 | "@types/react": "^19.0.10",
62 | "conventional-changelog-conventionalcommits": "^9.1.0",
63 | "nitro-codegen": "^0.28.1",
64 | "react": "19.1.0",
65 | "react-native": "0.81.0",
66 | "react-native-builder-bob": "^0.37.0",
67 | "react-native-nitro-modules": "^0.28.1",
68 | "semantic-release": "^24.2.3",
69 | "typescript": "5.0.4"
70 | },
71 | "peerDependencies": {
72 | "react": "*",
73 | "react-native": "*",
74 | "react-native-nitro-modules": "*"
75 | },
76 | "eslintConfig": {
77 | "root": true,
78 | "extends": [
79 | "@react-native",
80 | "prettier"
81 | ],
82 | "plugins": [
83 | "prettier"
84 | ],
85 | "rules": {
86 | "prettier/prettier": [
87 | "warn",
88 | {
89 | "quoteProps": "consistent",
90 | "singleQuote": true,
91 | "tabWidth": 2,
92 | "trailingComma": "es5",
93 | "useTabs": false
94 | }
95 | ]
96 | }
97 | },
98 | "eslintIgnore": [
99 | "node_modules/",
100 | "lib/"
101 | ],
102 | "prettier": {
103 | "quoteProps": "consistent",
104 | "singleQuote": true,
105 | "tabWidth": 2,
106 | "trailingComma": "es5",
107 | "useTabs": false,
108 | "semi": false
109 | },
110 | "react-native-builder-bob": {
111 | "source": "src",
112 | "output": "lib",
113 | "targets": [
114 | "commonjs",
115 | "module",
116 | [
117 | "typescript",
118 | {
119 | "project": "tsconfig.json"
120 | }
121 | ]
122 | ]
123 | }
124 | }
--------------------------------------------------------------------------------
/example/ios/NitroInAppBrowserExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 |
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:8.13.1"
9 | }
10 | }
11 |
12 | def reactNativeArchitectures() {
13 | def value = rootProject.getProperties().get("reactNativeArchitectures")
14 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
15 | }
16 |
17 | def isNewArchitectureEnabled() {
18 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
19 | }
20 |
21 | apply plugin: "com.android.library"
22 | apply plugin: 'org.jetbrains.kotlin.android'
23 | apply from: '../nitrogen/generated/android/NitroInAppBrowser+autolinking.gradle'
24 |
25 | if (isNewArchitectureEnabled()) {
26 | apply plugin: "com.facebook.react"
27 | }
28 |
29 | def getExtOrDefault(name) {
30 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroInAppBrowser_" + name]
31 | }
32 |
33 | def getExtOrIntegerDefault(name) {
34 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroInAppBrowser_" + name]).toInteger()
35 | }
36 |
37 | android {
38 | namespace "com.nitroinappbrowser"
39 |
40 | ndkVersion getExtOrDefault("ndkVersion")
41 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
42 |
43 | defaultConfig {
44 | minSdkVersion getExtOrIntegerDefault("minSdkVersion")
45 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
46 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
47 |
48 | externalNativeBuild {
49 | cmake {
50 | cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
51 | arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
52 | abiFilters (*reactNativeArchitectures())
53 |
54 | buildTypes {
55 | debug {
56 | cppFlags "-O1 -g"
57 | }
58 | release {
59 | cppFlags "-O2"
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
66 | externalNativeBuild {
67 | cmake {
68 | path "CMakeLists.txt"
69 | }
70 | }
71 |
72 | packagingOptions {
73 | excludes = [
74 | "META-INF",
75 | "META-INF/**",
76 | "**/libc++_shared.so",
77 | "**/libfbjni.so",
78 | "**/libjsi.so",
79 | "**/libfolly_json.so",
80 | "**/libfolly_runtime.so",
81 | "**/libglog.so",
82 | "**/libhermes.so",
83 | "**/libhermes-executor-debug.so",
84 | "**/libhermes_executor.so",
85 | "**/libreactnative.so",
86 | "**/libreactnativejni.so",
87 | "**/libturbomodulejsijni.so",
88 | "**/libreact_nativemodule_core.so",
89 | "**/libjscexecutor.so"
90 | ]
91 | }
92 |
93 | buildFeatures {
94 | buildConfig true
95 | prefab true
96 | }
97 |
98 | buildTypes {
99 | release {
100 | minifyEnabled false
101 | }
102 | }
103 |
104 | lintOptions {
105 | disable "GradleCompatible"
106 | }
107 |
108 | compileOptions {
109 | sourceCompatibility JavaVersion.VERSION_1_8
110 | targetCompatibility JavaVersion.VERSION_1_8
111 | }
112 |
113 | sourceSets {
114 | main {
115 | if (isNewArchitectureEnabled()) {
116 | java.srcDirs += [
117 | // React Codegen files
118 | "${project.buildDir}/generated/source/codegen/java"
119 | ]
120 | }
121 | }
122 | }
123 | }
124 |
125 | repositories {
126 | mavenCentral()
127 | google()
128 | }
129 |
130 |
131 | dependencies {
132 | // For < 0.71, this will be from the local maven repo
133 | // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
134 | //noinspection GradleDynamicVersion
135 | implementation "com.facebook.react:react-native:+"
136 |
137 | // Add a dependency on NitroModules
138 | implementation project(":react-native-nitro-modules")
139 |
140 | // Other dependencies
141 | implementation "androidx.browser:browser:1.8.0"
142 | }
143 |
144 | if (isNewArchitectureEnabled()) {
145 | react {
146 | jsRootDir = file("../src/")
147 | libraryName = "NitroInAppBrowser"
148 | codegenJavaPackageName = "com.nitroinappbrowser"
149 | }
150 | }
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/NitroInAppBrowserOptions.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOptions.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | import NitroModules
9 |
10 | /**
11 | * Represents an instance of `NitroInAppBrowserOptions`, backed by a C++ struct.
12 | */
13 | public typealias NitroInAppBrowserOptions = margelo.nitro.nitroinappbrowser.NitroInAppBrowserOptions
14 |
15 | public extension NitroInAppBrowserOptions {
16 | private typealias bridge = margelo.nitro.nitroinappbrowser.bridge.swift
17 |
18 | /**
19 | * Create a new instance of `NitroInAppBrowserOptions`.
20 | */
21 | init(dismissButtonLabel: NitroInAppBrowserDismissButtonLabel?, presentationStyle: NitroInAppBrowserPresentationStyle?, barColor: String?, controlColor: String?) {
22 | self.init({ () -> bridge.std__optional_NitroInAppBrowserDismissButtonLabel_ in
23 | if let __unwrappedValue = dismissButtonLabel {
24 | return bridge.create_std__optional_NitroInAppBrowserDismissButtonLabel_(__unwrappedValue)
25 | } else {
26 | return .init()
27 | }
28 | }(), { () -> bridge.std__optional_NitroInAppBrowserPresentationStyle_ in
29 | if let __unwrappedValue = presentationStyle {
30 | return bridge.create_std__optional_NitroInAppBrowserPresentationStyle_(__unwrappedValue)
31 | } else {
32 | return .init()
33 | }
34 | }(), { () -> bridge.std__optional_std__string_ in
35 | if let __unwrappedValue = barColor {
36 | return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
37 | } else {
38 | return .init()
39 | }
40 | }(), { () -> bridge.std__optional_std__string_ in
41 | if let __unwrappedValue = controlColor {
42 | return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
43 | } else {
44 | return .init()
45 | }
46 | }())
47 | }
48 |
49 | var dismissButtonLabel: NitroInAppBrowserDismissButtonLabel? {
50 | @inline(__always)
51 | get {
52 | return self.__dismissButtonLabel.value
53 | }
54 | @inline(__always)
55 | set {
56 | self.__dismissButtonLabel = { () -> bridge.std__optional_NitroInAppBrowserDismissButtonLabel_ in
57 | if let __unwrappedValue = newValue {
58 | return bridge.create_std__optional_NitroInAppBrowserDismissButtonLabel_(__unwrappedValue)
59 | } else {
60 | return .init()
61 | }
62 | }()
63 | }
64 | }
65 |
66 | var presentationStyle: NitroInAppBrowserPresentationStyle? {
67 | @inline(__always)
68 | get {
69 | return self.__presentationStyle.value
70 | }
71 | @inline(__always)
72 | set {
73 | self.__presentationStyle = { () -> bridge.std__optional_NitroInAppBrowserPresentationStyle_ in
74 | if let __unwrappedValue = newValue {
75 | return bridge.create_std__optional_NitroInAppBrowserPresentationStyle_(__unwrappedValue)
76 | } else {
77 | return .init()
78 | }
79 | }()
80 | }
81 | }
82 |
83 | var barColor: String? {
84 | @inline(__always)
85 | get {
86 | return { () -> String? in
87 | if bridge.has_value_std__optional_std__string_(self.__barColor) {
88 | let __unwrapped = bridge.get_std__optional_std__string_(self.__barColor)
89 | return String(__unwrapped)
90 | } else {
91 | return nil
92 | }
93 | }()
94 | }
95 | @inline(__always)
96 | set {
97 | self.__barColor = { () -> bridge.std__optional_std__string_ in
98 | if let __unwrappedValue = newValue {
99 | return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
100 | } else {
101 | return .init()
102 | }
103 | }()
104 | }
105 | }
106 |
107 | var controlColor: String? {
108 | @inline(__always)
109 | get {
110 | return { () -> String? in
111 | if bridge.has_value_std__optional_std__string_(self.__controlColor) {
112 | let __unwrapped = bridge.get_std__optional_std__string_(self.__controlColor)
113 | return String(__unwrapped)
114 | } else {
115 | return nil
116 | }
117 | }()
118 | }
119 | @inline(__always)
120 | set {
121 | self.__controlColor = { () -> bridge.std__optional_std__string_ in
122 | if let __unwrappedValue = newValue {
123 | return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
124 | } else {
125 | return .init()
126 | }
127 | }()
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/.github/workflows/ios-build.yml:
--------------------------------------------------------------------------------
1 | name: Build iOS
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - '.github/workflows/ios-build.yml'
9 | - 'example/ios/**'
10 | - 'example/Gemfile'
11 | - 'example/Gemfile.lock'
12 | - '**/nitrogen/generated/shared/**'
13 | - '**/nitrogen/generated/ios/**'
14 | - 'cpp/**'
15 | - 'ios/**'
16 | - '**/Podfile.lock'
17 | - '**/bun.lock'
18 | - '**/*.podspec'
19 | - '**/react-native.config.js'
20 | - '**/nitro.json'
21 | pull_request:
22 | paths:
23 | - '.github/workflows/ios-build.yml'
24 | - 'example/ios/**'
25 | - 'example/Gemfile'
26 | - 'example/Gemfile.lock'
27 | - '**/nitrogen/generated/shared/**'
28 | - '**/nitrogen/generated/ios/**'
29 | - 'cpp/**'
30 | - 'ios/**'
31 | - '**/Podfile.lock'
32 | - '**/bun.lock'
33 | - '**/*.podspec'
34 | - '**/react-native.config.js'
35 | - '**/nitro.json'
36 |
37 | env:
38 | USE_CCACHE: 1
39 |
40 | concurrency:
41 | group: ${{ github.workflow }}-${{ github.ref }}
42 | cancel-in-progress: true
43 |
44 | jobs:
45 | build_new:
46 | name: Build iOS Example App (new architecture)
47 | runs-on: macOS-15
48 | steps:
49 | - uses: actions/checkout@v5
50 | - name: Setup Xcode
51 | uses: maxim-lobanov/setup-xcode@v1
52 | with:
53 | xcode-version: 16.4
54 |
55 | - uses: oven-sh/setup-bun@v2
56 |
57 | - name: Install npm dependencies (bun)
58 | run: bun install
59 |
60 | - name: Setup Ruby (bundle)
61 | uses: ruby/setup-ruby@v1
62 | with:
63 | ruby-version: 2.7.2
64 | bundler-cache: true
65 | working-directory: example/ios
66 |
67 | - name: Install xcpretty
68 | run: gem install xcpretty
69 |
70 | - name: Restore Pods cache
71 | uses: actions/cache@v4
72 | with:
73 | path: example/ios/Pods
74 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock', '**/Gemfile.lock') }}
75 | restore-keys: |
76 | ${{ runner.os }}-pods-
77 | - name: Install Pods
78 | working-directory: example/ios
79 | run: pod install
80 | - name: Build App
81 | working-directory: example/ios
82 | run: "set -o pipefail && xcodebuild \
83 | CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
84 | -derivedDataPath build -UseModernBuildSystem=YES \
85 | -workspace NitroInAppBrowserExample.xcworkspace \
86 | -scheme NitroInAppBrowserExample \
87 | -sdk iphonesimulator \
88 | -configuration Debug \
89 | -destination 'platform=iOS Simulator,name=iPhone 16' \
90 | build \
91 | CODE_SIGNING_ALLOWED=NO | xcpretty"
92 |
93 | build_old:
94 | name: Build iOS Example App (old architecture)
95 | runs-on: macOS-15
96 | steps:
97 | - uses: actions/checkout@v5
98 | - uses: oven-sh/setup-bun@v2
99 |
100 | - name: Setup Xcode
101 | uses: maxim-lobanov/setup-xcode@v1
102 | with:
103 | xcode-version: 16.4
104 |
105 | - name: Install npm dependencies (bun)
106 | run: bun install
107 |
108 | - name: Disable new architecture in Podfile
109 | run: sed -i "" "s/ENV\['RCT_NEW_ARCH_ENABLED'\] = '1'/ENV['RCT_NEW_ARCH_ENABLED'] = '0'/g" example/ios/Podfile
110 |
111 | - name: Restore buildcache
112 | uses: mikehardy/buildcache-action@v2
113 | continue-on-error: true
114 |
115 | - name: Setup Ruby (bundle)
116 | uses: ruby/setup-ruby@v1
117 | with:
118 | ruby-version: 2.7.2
119 | bundler-cache: true
120 | working-directory: example/ios
121 |
122 | - name: Install xcpretty
123 | run: gem install xcpretty
124 |
125 | - name: Restore Pods cache
126 | uses: actions/cache@v4
127 | with:
128 | path: example/ios/Pods
129 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock', '**/Gemfile.lock') }}
130 | restore-keys: |
131 | ${{ runner.os }}-pods-
132 | - name: Install Pods
133 | working-directory: example/ios
134 | run: pod install
135 | - name: Build App
136 | working-directory: example/ios
137 | run: "set -o pipefail && xcodebuild \
138 | CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
139 | -derivedDataPath build -UseModernBuildSystem=YES \
140 | -workspace NitroInAppBrowserExample.xcworkspace \
141 | -scheme NitroInAppBrowserExample \
142 | -sdk iphonesimulator \
143 | -configuration Debug \
144 | -destination 'platform=iOS Simulator,name=iPhone 16' \
145 | build \
146 | CODE_SIGNING_ALLOWED=NO | xcpretty"
147 |
--------------------------------------------------------------------------------
/nitrogen/generated/shared/c++/NitroInAppBrowserOptions.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowserOptions.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | #if __has_include()
11 | #include
12 | #else
13 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14 | #endif
15 | #if __has_include()
16 | #include
17 | #else
18 | #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19 | #endif
20 |
21 | // Forward declaration of `NitroInAppBrowserDismissButtonLabel` to properly resolve imports.
22 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserDismissButtonLabel; }
23 | // Forward declaration of `NitroInAppBrowserPresentationStyle` to properly resolve imports.
24 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserPresentationStyle; }
25 |
26 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
27 | #include
28 | #include "NitroInAppBrowserPresentationStyle.hpp"
29 | #include
30 |
31 | namespace margelo::nitro::nitroinappbrowser {
32 |
33 | /**
34 | * A struct which can be represented as a JavaScript object (NitroInAppBrowserOptions).
35 | */
36 | struct NitroInAppBrowserOptions {
37 | public:
38 | std::optional dismissButtonLabel SWIFT_PRIVATE;
39 | std::optional presentationStyle SWIFT_PRIVATE;
40 | std::optional barColor SWIFT_PRIVATE;
41 | std::optional controlColor SWIFT_PRIVATE;
42 |
43 | public:
44 | NitroInAppBrowserOptions() = default;
45 | explicit NitroInAppBrowserOptions(std::optional dismissButtonLabel, std::optional presentationStyle, std::optional barColor, std::optional controlColor): dismissButtonLabel(dismissButtonLabel), presentationStyle(presentationStyle), barColor(barColor), controlColor(controlColor) {}
46 | };
47 |
48 | } // namespace margelo::nitro::nitroinappbrowser
49 |
50 | namespace margelo::nitro {
51 |
52 | // C++ NitroInAppBrowserOptions <> JS NitroInAppBrowserOptions (object)
53 | template <>
54 | struct JSIConverter final {
55 | static inline margelo::nitro::nitroinappbrowser::NitroInAppBrowserOptions fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
56 | jsi::Object obj = arg.asObject(runtime);
57 | return margelo::nitro::nitroinappbrowser::NitroInAppBrowserOptions(
58 | JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "dismissButtonLabel")),
59 | JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "presentationStyle")),
60 | JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "barColor")),
61 | JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, "controlColor"))
62 | );
63 | }
64 | static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitroinappbrowser::NitroInAppBrowserOptions& arg) {
65 | jsi::Object obj(runtime);
66 | obj.setProperty(runtime, "dismissButtonLabel", JSIConverter>::toJSI(runtime, arg.dismissButtonLabel));
67 | obj.setProperty(runtime, "presentationStyle", JSIConverter>::toJSI(runtime, arg.presentationStyle));
68 | obj.setProperty(runtime, "barColor", JSIConverter>::toJSI(runtime, arg.barColor));
69 | obj.setProperty(runtime, "controlColor", JSIConverter>::toJSI(runtime, arg.controlColor));
70 | return obj;
71 | }
72 | static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
73 | if (!value.isObject()) {
74 | return false;
75 | }
76 | jsi::Object obj = value.getObject(runtime);
77 | if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "dismissButtonLabel"))) return false;
78 | if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "presentationStyle"))) return false;
79 | if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "barColor"))) return false;
80 | if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, "controlColor"))) return false;
81 | return true;
82 | }
83 | };
84 |
85 | } // namespace margelo::nitro
86 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply plugin: "org.jetbrains.kotlin.android"
3 | apply plugin: "com.facebook.react"
4 |
5 | /**
6 | * This is the configuration block to customize your React Native Android app.
7 | * By default you don't need to apply any configuration, just uncomment the lines you need.
8 | */
9 | react {
10 | /* Folders */
11 | // The root of your project, i.e. where "package.json" lives. Default is '../..'
12 | // root = file("../../")
13 | // The folder where the react-native NPM package is. Default is ../../node_modules/react-native
14 | reactNativeDir = file("../../../node_modules/react-native")
15 | // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
16 | codegenDir = file("../../../node_modules/@react-native/codegen")
17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
18 | cliFile = file("../../../node_modules/react-native/cli.js")
19 |
20 | /* Variants */
21 | // The list of variants to that are debuggable. For those we're going to
22 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
24 | // debuggableVariants = ["liteDebug", "prodDebug"]
25 |
26 | /* Bundling */
27 | // A list containing the node command and its flags. Default is just 'node'.
28 | // nodeExecutableAndArgs = ["node"]
29 | //
30 | // The command to run when bundling. By default is 'bundle'
31 | // bundleCommand = "ram-bundle"
32 | //
33 | // The path to the CLI configuration file. Default is empty.
34 | // bundleConfig = file(../rn-cli.config.js)
35 | //
36 | // The name of the generated asset file containing your JS bundle
37 | // bundleAssetName = "MyApplication.android.bundle"
38 | //
39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
40 | // entryFile = file("../js/MyApplication.android.js")
41 | //
42 | // A list of extra flags to pass to the 'bundle' commands.
43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
44 | // extraPackagerArgs = []
45 |
46 | /* Hermes Commands */
47 | // The hermes compiler command to run. By default it is 'hermesc'
48 | hermesCommand = "$rootDir/../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"
49 | //
50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
51 | // hermesFlags = ["-O", "-output-source-map"]
52 |
53 | /* Autolinking */
54 | autolinkLibrariesWithApp()
55 | }
56 |
57 | /**
58 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
59 | */
60 | def enableProguardInReleaseBuilds = false
61 |
62 | /**
63 | * The preferred build flavor of JavaScriptCore (JSC)
64 | *
65 | * For example, to use the international variant, you can use:
66 | * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+`
67 | *
68 | * The international variant includes ICU i18n library and necessary data
69 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
70 | * give correct results when using with locales other than en-US. Note that
71 | * this variant is about 6MiB larger per architecture than default.
72 | */
73 | def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
74 |
75 | android {
76 | ndkVersion rootProject.ext.ndkVersion
77 | buildToolsVersion rootProject.ext.buildToolsVersion
78 | compileSdk rootProject.ext.compileSdkVersion
79 |
80 | namespace "com.nitroinappbrowserexample"
81 | defaultConfig {
82 | applicationId "com.nitroinappbrowserexample"
83 | minSdkVersion rootProject.ext.minSdkVersion
84 | targetSdkVersion rootProject.ext.targetSdkVersion
85 | versionCode 1
86 | versionName "1.0"
87 | }
88 | signingConfigs {
89 | debug {
90 | storeFile file('debug.keystore')
91 | storePassword 'android'
92 | keyAlias 'androiddebugkey'
93 | keyPassword 'android'
94 | }
95 | }
96 | buildTypes {
97 | debug {
98 | signingConfig signingConfigs.debug
99 | }
100 | release {
101 | // Caution! In production, you need to generate your own keystore file.
102 | // see https://reactnative.dev/docs/signed-apk-android.
103 | signingConfig signingConfigs.debug
104 | minifyEnabled enableProguardInReleaseBuilds
105 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
106 | }
107 | }
108 | }
109 |
110 | dependencies {
111 | // The version of react-native is set by the React Native Gradle Plugin
112 | implementation("com.facebook.react:react-android")
113 |
114 | if (hermesEnabled.toBoolean()) {
115 | implementation("com.facebook.react:hermes-android")
116 | } else {
117 | implementation jscFlavor
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/swift/HybridNitroInAppBrowserSpec_cxx.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// HybridNitroInAppBrowserSpec_cxx.swift
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | import Foundation
9 | import NitroModules
10 |
11 | /**
12 | * A class implementation that bridges HybridNitroInAppBrowserSpec over to C++.
13 | * In C++, we cannot use Swift protocols - so we need to wrap it in a class to make it strongly defined.
14 | *
15 | * Also, some Swift types need to be bridged with special handling:
16 | * - Enums need to be wrapped in Structs, otherwise they cannot be accessed bi-directionally (Swift bug: https://github.com/swiftlang/swift/issues/75330)
17 | * - Other HybridObjects need to be wrapped/unwrapped from the Swift TCxx wrapper
18 | * - Throwing methods need to be wrapped with a Result type, as exceptions cannot be propagated to C++
19 | */
20 | open class HybridNitroInAppBrowserSpec_cxx {
21 | /**
22 | * The Swift <> C++ bridge's namespace (`margelo::nitro::nitroinappbrowser::bridge::swift`)
23 | * from `NitroInAppBrowser-Swift-Cxx-Bridge.hpp`.
24 | * This contains specialized C++ templates, and C++ helper functions that can be accessed from Swift.
25 | */
26 | public typealias bridge = margelo.nitro.nitroinappbrowser.bridge.swift
27 |
28 | /**
29 | * Holds an instance of the `HybridNitroInAppBrowserSpec` Swift protocol.
30 | */
31 | private var __implementation: any HybridNitroInAppBrowserSpec
32 |
33 | /**
34 | * Holds a weak pointer to the C++ class that wraps the Swift class.
35 | */
36 | private var __cxxPart: bridge.std__weak_ptr_HybridNitroInAppBrowserSpec_
37 |
38 | /**
39 | * Create a new `HybridNitroInAppBrowserSpec_cxx` that wraps the given `HybridNitroInAppBrowserSpec`.
40 | * All properties and methods bridge to C++ types.
41 | */
42 | public init(_ implementation: any HybridNitroInAppBrowserSpec) {
43 | self.__implementation = implementation
44 | self.__cxxPart = .init()
45 | /* no base class */
46 | }
47 |
48 | /**
49 | * Get the actual `HybridNitroInAppBrowserSpec` instance this class wraps.
50 | */
51 | @inline(__always)
52 | public func getHybridNitroInAppBrowserSpec() -> any HybridNitroInAppBrowserSpec {
53 | return __implementation
54 | }
55 |
56 | /**
57 | * Casts this instance to a retained unsafe raw pointer.
58 | * This acquires one additional strong reference on the object!
59 | */
60 | public func toUnsafe() -> UnsafeMutableRawPointer {
61 | return Unmanaged.passRetained(self).toOpaque()
62 | }
63 |
64 | /**
65 | * Casts an unsafe pointer to a `HybridNitroInAppBrowserSpec_cxx`.
66 | * The pointer has to be a retained opaque `Unmanaged`.
67 | * This removes one strong reference from the object!
68 | */
69 | public class func fromUnsafe(_ pointer: UnsafeMutableRawPointer) -> HybridNitroInAppBrowserSpec_cxx {
70 | return Unmanaged.fromOpaque(pointer).takeRetainedValue()
71 | }
72 |
73 | /**
74 | * Gets (or creates) the C++ part of this Hybrid Object.
75 | * The C++ part is a `std::shared_ptr`.
76 | */
77 | public func getCxxPart() -> bridge.std__shared_ptr_HybridNitroInAppBrowserSpec_ {
78 | let cachedCxxPart = self.__cxxPart.lock()
79 | if cachedCxxPart.__convertToBool() {
80 | return cachedCxxPart
81 | } else {
82 | let newCxxPart = bridge.create_std__shared_ptr_HybridNitroInAppBrowserSpec_(self.toUnsafe())
83 | __cxxPart = bridge.weakify_std__shared_ptr_HybridNitroInAppBrowserSpec_(newCxxPart)
84 | return newCxxPart
85 | }
86 | }
87 |
88 |
89 |
90 | /**
91 | * Get the memory size of the Swift class (plus size of any other allocations)
92 | * so the JS VM can properly track it and garbage-collect the JS object if needed.
93 | */
94 | @inline(__always)
95 | public var memorySize: Int {
96 | return MemoryHelper.getSizeOf(self.__implementation) + self.__implementation.memorySize
97 | }
98 |
99 | /**
100 | * Call dispose() on the Swift class.
101 | * This _may_ be called manually from JS.
102 | */
103 | @inline(__always)
104 | public func dispose() {
105 | self.__implementation.dispose()
106 | }
107 |
108 | // Properties
109 |
110 |
111 | // Methods
112 | @inline(__always)
113 | public final func open(url: std.string, options: bridge.std__optional_NitroInAppBrowserOptions_) -> bridge.Result_std__shared_ptr_Promise_void___ {
114 | do {
115 | let __result = try self.__implementation.open(url: String(url), options: { () -> NitroInAppBrowserOptions? in
116 | if bridge.has_value_std__optional_NitroInAppBrowserOptions_(options) {
117 | let __unwrapped = bridge.get_std__optional_NitroInAppBrowserOptions_(options)
118 | return __unwrapped
119 | } else {
120 | return nil
121 | }
122 | }())
123 | let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in
124 | let __promise = bridge.create_std__shared_ptr_Promise_void__()
125 | let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)
126 | __result
127 | .then({ __result in __promiseHolder.resolve() })
128 | .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
129 | return __promise
130 | }()
131 | return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)
132 | } catch (let __error) {
133 | let __exceptionPtr = __error.toCpp()
134 | return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
135 | }
136 | }
137 |
138 | @inline(__always)
139 | public final func close() -> bridge.Result_std__shared_ptr_Promise_void___ {
140 | do {
141 | let __result = try self.__implementation.close()
142 | let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in
143 | let __promise = bridge.create_std__shared_ptr_Promise_void__()
144 | let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)
145 | __result
146 | .then({ __result in __promiseHolder.resolve() })
147 | .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
148 | return __promise
149 | }()
150 | return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)
151 | } catch (let __error) {
152 | let __exceptionPtr = __error.toCpp()
153 | return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | if ! command -v java >/dev/null 2>&1
137 | then
138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
139 |
140 | Please set the JAVA_HOME variable in your environment to match the
141 | location of your Java installation."
142 | fi
143 | fi
144 |
145 | # Increase the maximum file descriptors if we can.
146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
147 | case $MAX_FD in #(
148 | max*)
149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
150 | # shellcheck disable=SC2039,SC3045
151 | MAX_FD=$( ulimit -H -n ) ||
152 | warn "Could not query maximum file descriptor limit"
153 | esac
154 | case $MAX_FD in #(
155 | '' | soft) :;; #(
156 | *)
157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
158 | # shellcheck disable=SC2039,SC3045
159 | ulimit -n "$MAX_FD" ||
160 | warn "Could not set maximum file descriptor limit to $MAX_FD"
161 | esac
162 | fi
163 |
164 | # Collect all arguments for the java command, stacking in reverse order:
165 | # * args from the command line
166 | # * the main class name
167 | # * -classpath
168 | # * -D...appname settings
169 | # * --module-path (only if needed)
170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
171 |
172 | # For Cygwin or MSYS, switch paths to Windows format before running java
173 | if "$cygwin" || "$msys" ; then
174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
176 |
177 | JAVACMD=$( cygpath --unix "$JAVACMD" )
178 |
179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
180 | for arg do
181 | if
182 | case $arg in #(
183 | -*) false ;; # don't mess with options #(
184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
185 | [ -e "$t" ] ;; #(
186 | *) false ;;
187 | esac
188 | then
189 | arg=$( cygpath --path --ignore --mixed "$arg" )
190 | fi
191 | # Roll the args list around exactly as many times as the number of
192 | # args, so each arg winds up back in the position where it started, but
193 | # possibly modified.
194 | #
195 | # NB: a `for` loop captures its iteration list before it begins, so
196 | # changing the positional parameters here affects neither the number of
197 | # iterations, nor the values presented in `arg`.
198 | shift # remove old arg
199 | set -- "$@" "$arg" # push replacement arg
200 | done
201 | fi
202 |
203 |
204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
206 |
207 | # Collect all arguments for the java command:
208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
209 | # and any embedded shellness will be escaped.
210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
211 | # treated as '${Hostname}' itself on the command line.
212 |
213 | set -- \
214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
215 | -classpath "$CLASSPATH" \
216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217 | "$@"
218 |
219 | # Stop when "xargs" is not available.
220 | if ! command -v xargs >/dev/null 2>&1
221 | then
222 | die "xargs is not available"
223 | fi
224 |
225 | # Use "xargs" to parse quoted args.
226 | #
227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
228 | #
229 | # In Bash we could simply go:
230 | #
231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
232 | # set -- "${ARGS[@]}" "$@"
233 | #
234 | # but POSIX shell has neither arrays nor command substitution, so instead we
235 | # post-process each arg (as a line of input to sed) to backslash-escape any
236 | # character that might be a shell metacharacter, then use eval to reverse
237 | # that process (while maintaining the separation between arguments), and wrap
238 | # the whole thing up as a single "set" statement.
239 | #
240 | # This will of course break if any of these variables contains a newline or
241 | # an unmatched quote.
242 | #
243 |
244 | eval "set -- $(
245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
246 | xargs -n1 |
247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
248 | tr '\n' ' '
249 | )" '"$@"'
250 |
251 | exec "$JAVACMD" "$@"
252 |
--------------------------------------------------------------------------------
/nitrogen/generated/ios/NitroInAppBrowser-Swift-Cxx-Bridge.hpp:
--------------------------------------------------------------------------------
1 | ///
2 | /// NitroInAppBrowser-Swift-Cxx-Bridge.hpp
3 | /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4 | /// https://github.com/mrousavy/nitro
5 | /// Copyright © 2025 Marc Rousavy @ Margelo
6 | ///
7 |
8 | #pragma once
9 |
10 | // Forward declarations of C++ defined types
11 | // Forward declaration of `HybridNitroInAppBrowserSpec` to properly resolve imports.
12 | namespace margelo::nitro::nitroinappbrowser { class HybridNitroInAppBrowserSpec; }
13 | // Forward declaration of `NitroInAppBrowserDismissButtonLabel` to properly resolve imports.
14 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserDismissButtonLabel; }
15 | // Forward declaration of `NitroInAppBrowserOptions` to properly resolve imports.
16 | namespace margelo::nitro::nitroinappbrowser { struct NitroInAppBrowserOptions; }
17 | // Forward declaration of `NitroInAppBrowserPresentationStyle` to properly resolve imports.
18 | namespace margelo::nitro::nitroinappbrowser { enum class NitroInAppBrowserPresentationStyle; }
19 |
20 | // Forward declarations of Swift defined types
21 | // Forward declaration of `HybridNitroInAppBrowserSpec_cxx` to properly resolve imports.
22 | namespace NitroInAppBrowser { class HybridNitroInAppBrowserSpec_cxx; }
23 |
24 | // Include C++ defined types
25 | #include "HybridNitroInAppBrowserSpec.hpp"
26 | #include "NitroInAppBrowserDismissButtonLabel.hpp"
27 | #include "NitroInAppBrowserOptions.hpp"
28 | #include "NitroInAppBrowserPresentationStyle.hpp"
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | /**
39 | * Contains specialized versions of C++ templated types so they can be accessed from Swift,
40 | * as well as helper functions to interact with those C++ types from Swift.
41 | */
42 | namespace margelo::nitro::nitroinappbrowser::bridge::swift {
43 |
44 | // pragma MARK: std::shared_ptr>
45 | /**
46 | * Specialized version of `std::shared_ptr>`.
47 | */
48 | using std__shared_ptr_Promise_void__ = std::shared_ptr>;
49 | inline std::shared_ptr> create_std__shared_ptr_Promise_void__() noexcept {
50 | return Promise::create();
51 | }
52 | inline PromiseHolder wrap_std__shared_ptr_Promise_void__(std::shared_ptr> promise) noexcept {
53 | return PromiseHolder(std::move(promise));
54 | }
55 |
56 | // pragma MARK: std::function
57 | /**
58 | * Specialized version of `std::function`.
59 | */
60 | using Func_void = std::function;
61 | /**
62 | * Wrapper class for a `std::function`, this can be used from Swift.
63 | */
64 | class Func_void_Wrapper final {
65 | public:
66 | explicit Func_void_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {}
67 | inline void call() const noexcept {
68 | _function->operator()();
69 | }
70 | private:
71 | std::unique_ptr> _function;
72 | } SWIFT_NONCOPYABLE;
73 | Func_void create_Func_void(void* _Nonnull swiftClosureWrapper) noexcept;
74 | inline Func_void_Wrapper wrap_Func_void(Func_void value) noexcept {
75 | return Func_void_Wrapper(std::move(value));
76 | }
77 |
78 | // pragma MARK: std::function
79 | /**
80 | * Specialized version of `std::function`.
81 | */
82 | using Func_void_std__exception_ptr = std::function;
83 | /**
84 | * Wrapper class for a `std::function`, this can be used from Swift.
85 | */
86 | class Func_void_std__exception_ptr_Wrapper final {
87 | public:
88 | explicit Func_void_std__exception_ptr_Wrapper(std::function&& func): _function(std::make_unique>(std::move(func))) {}
89 | inline void call(std::exception_ptr error) const noexcept {
90 | _function->operator()(error);
91 | }
92 | private:
93 | std::unique_ptr> _function;
94 | } SWIFT_NONCOPYABLE;
95 | Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* _Nonnull swiftClosureWrapper) noexcept;
96 | inline Func_void_std__exception_ptr_Wrapper wrap_Func_void_std__exception_ptr(Func_void_std__exception_ptr value) noexcept {
97 | return Func_void_std__exception_ptr_Wrapper(std::move(value));
98 | }
99 |
100 | // pragma MARK: std::optional
101 | /**
102 | * Specialized version of `std::optional`.
103 | */
104 | using std__optional_NitroInAppBrowserDismissButtonLabel_ = std::optional;
105 | inline std::optional create_std__optional_NitroInAppBrowserDismissButtonLabel_(const NitroInAppBrowserDismissButtonLabel& value) noexcept {
106 | return std::optional(value);
107 | }
108 | inline bool has_value_std__optional_NitroInAppBrowserDismissButtonLabel_(const std::optional& optional) noexcept {
109 | return optional.has_value();
110 | }
111 | inline NitroInAppBrowserDismissButtonLabel get_std__optional_NitroInAppBrowserDismissButtonLabel_(const std::optional& optional) noexcept {
112 | return *optional;
113 | }
114 |
115 | // pragma MARK: std::optional
116 | /**
117 | * Specialized version of `std::optional`.
118 | */
119 | using std__optional_NitroInAppBrowserPresentationStyle_ = std::optional;
120 | inline std::optional create_std__optional_NitroInAppBrowserPresentationStyle_(const NitroInAppBrowserPresentationStyle& value) noexcept {
121 | return std::optional(value);
122 | }
123 | inline bool has_value_std__optional_NitroInAppBrowserPresentationStyle_(const std::optional& optional) noexcept {
124 | return optional.has_value();
125 | }
126 | inline NitroInAppBrowserPresentationStyle get_std__optional_NitroInAppBrowserPresentationStyle_(const std::optional& optional) noexcept {
127 | return *optional;
128 | }
129 |
130 | // pragma MARK: std::optional
131 | /**
132 | * Specialized version of `std::optional`.
133 | */
134 | using std__optional_std__string_ = std::optional;
135 | inline std::optional create_std__optional_std__string_(const std::string& value) noexcept {
136 | return std::optional(value);
137 | }
138 | inline bool has_value_std__optional_std__string_(const std::optional& optional) noexcept {
139 | return optional.has_value();
140 | }
141 | inline std::string get_std__optional_std__string_(const std::optional& optional) noexcept {
142 | return *optional;
143 | }
144 |
145 | // pragma MARK: std::optional
146 | /**
147 | * Specialized version of `std::optional`.
148 | */
149 | using std__optional_NitroInAppBrowserOptions_ = std::optional;
150 | inline std::optional create_std__optional_NitroInAppBrowserOptions_(const NitroInAppBrowserOptions& value) noexcept {
151 | return std::optional(value);
152 | }
153 | inline bool has_value_std__optional_NitroInAppBrowserOptions_(const std::optional& optional) noexcept {
154 | return optional.has_value();
155 | }
156 | inline NitroInAppBrowserOptions get_std__optional_NitroInAppBrowserOptions_(const std::optional& optional) noexcept {
157 | return *optional;
158 | }
159 |
160 | // pragma MARK: std::shared_ptr
161 | /**
162 | * Specialized version of `std::shared_ptr`.
163 | */
164 | using std__shared_ptr_HybridNitroInAppBrowserSpec_ = std::shared_ptr;
165 | std::shared_ptr create_std__shared_ptr_HybridNitroInAppBrowserSpec_(void* _Nonnull swiftUnsafePointer) noexcept;
166 | void* _Nonnull get_std__shared_ptr_HybridNitroInAppBrowserSpec_(std__shared_ptr_HybridNitroInAppBrowserSpec_ cppType) noexcept;
167 |
168 | // pragma MARK: std::weak_ptr
169 | using std__weak_ptr_HybridNitroInAppBrowserSpec_ = std::weak_ptr;
170 | inline std__weak_ptr_HybridNitroInAppBrowserSpec_ weakify_std__shared_ptr_HybridNitroInAppBrowserSpec_(const std::shared_ptr& strong) noexcept { return strong; }
171 |
172 | // pragma MARK: Result>>
173 | using Result_std__shared_ptr_Promise_void___ = Result>>;
174 | inline Result_std__shared_ptr_Promise_void___ create_Result_std__shared_ptr_Promise_void___(const std::shared_ptr