init
Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
2025-09-02 14:49:16 +08:00
commit 38ba663466
2885 changed files with 391107 additions and 0 deletions

View File

@@ -0,0 +1 @@
*.tgz

2
react-native-sdk/.npmrc Normal file
View File

@@ -0,0 +1,2 @@
package-lock=true
legacy-peer-deps=true

132
react-native-sdk/README.md Normal file
View File

@@ -0,0 +1,132 @@
# <p align="center">Jitsi Meet React Native SDK</p>
## Installation
Inside your project, run;
```console
npm i @jitsi/react-native-sdk
```
If there are conflicts, you can use ```--force```
<br/>Additionally, if not already installed, some dependencies will need to be added.
This can be done by running the following script:
```console
node node_modules/@jitsi/react-native-sdk/update_dependencies.js
```
This will check and update all your dependencies.<br/><br/>
After that you need to ```npm i```, if some dependency versions were updated.
[comment]: # (These deps definitely need to be added manually, more could be neccesary)
Because of SVG use in react native, you need to update metro.config your project's file:
```javascript
const { getDefaultConfig } = require('metro-config');
module.exports = (async () => {
const {
resolver: {
sourceExts,
assetExts
}
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg']
}
}
})();
```
## iOS
#### Project Info.plist
- Add a *Privacy - Camera Usage Description*
- Add a *Privacy - Microphone Usage Description*
#### General
- Signing & capabilites:
- Add Background modes
- Audio
- Voice over IP
- Background fetch
Run;
```console
cd ios && pod install && cd ..
```
## Android
- In your build.gradle have at least `minSdkVersion = 26`
- In your build.gradle have `gradlePluginVersion = "8.4.2"` or higher
- In `android/app/src/debug/AndroidManifest.xml` and `android/app/src/main/AndroidManifest.xml`, under the `</application>` tag, include
```xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
```
### Services
#### Screen share
- Go to your `MainApplication.java` file and add:
1. `import com.oney.WebRTCModule.WebRTCModuleOptions;` that comes from `react-native-webrtc` dependency.
2. `WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();` instance it.
3. `options.enableMediaProjectionService = true;` enable foreground service that takes care of screen-sharing feature.
- Go to your `android/app/src/main/AndroidManifest.xml`, under the `</application>` tag and include
```xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
```
If you want to test all the steps before applying them to your app, you can check our React Native SDK sample app here:
https://github.com/jitsi/jitsi-meet-sdk-samples/tree/master/react-native
## Using JWT tokens
- If you are planning to use tokens or another domain, you can do that by updating the following props, as shown below.
- For example:
```javascript
<JitsiMeeting
room = { 'ThisIsNotATestRoomName' }
serverURL = { 'https://meet.jit.si/' }
token={ 'dkhalhfajhflahlfaahalhfahfsl' } />
```
## Using custom overflow menu buttons
- If you are planning to add custom overflow menu buttons, you can do that by updating the ```config``` prop, as shown below.
- For example:
```javascript
<JitsiMeeting
config = {{
customToolbarButtons: [
{
icon: "https://w7.pngwing.com/pngs/987/537/png-transparent-download-downloading-save-basic-user-interface-icon-thumbnail.png",
id: "btn1",
text: "Button one"
}, {
icon: "https://w7.pngwing.com/pngs/987/537/png-transparent-download-downloading-save-basic-user-interface-icon-thumbnail.png",
id: "btn2",
text: "Button two"
}
]
}}
room = { 'ThisIsNotATestRoomName' }
serverURL = { 'https://meet.jit.si/' }
token = { 'dkhalhfajhflahlfaahalhfahfsl' } />
```
For more details on how you can use React Native SDK with React Native app, you can follow this link:
https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-react-native-sdk

View File

@@ -0,0 +1,157 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:$rootProject.ext.gradlePluginVersion"
}
}
def isNewArchitectureEnabled() {
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
}
apply plugin: 'com.android.library'
if (isNewArchitectureEnabled()) {
apply plugin: 'com.facebook.react'
}
def getExtOrDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['JitsiMeetReactNative_' + name]
}
def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['JitsiMeetReactNative_' + name]).toInteger()
}
android {
namespace 'org.jitsi.meet.sdk'
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
defaultConfig {
minSdkVersion getExtOrIntegerDefault('minSdkVersion')
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
}
buildTypes {
release {
minifyEnabled false
}
}
lintOptions {
disable 'GradleCompatible'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
repositories {
mavenCentral()
google()
def found = false
def defaultDir = null
def androidSourcesName = 'React Native sources'
if (rootProject.ext.has('reactNativeAndroidRoot')) {
defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
} else {
defaultDir = new File(
projectDir,
'/../../../node_modules/react-native/android'
)
}
if (defaultDir.exists()) {
maven {
url defaultDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
found = true
} else {
def parentDir = rootProject.projectDir
1.upto(5, {
if (found) return true
parentDir = parentDir.parentFile
def androidSourcesDir = new File(
parentDir,
'node_modules/react-native'
)
def androidPrebuiltBinaryDir = new File(
parentDir,
'node_modules/react-native/android'
)
if (androidPrebuiltBinaryDir.exists()) {
maven {
url androidPrebuiltBinaryDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
found = true
} else if (androidSourcesDir.exists()) {
maven {
url androidSourcesDir.toString()
name androidSourcesName
}
logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
found = true
}
})
}
if (!found) {
throw new GradleException(
"${project.name}: unable to locate React Native android sources. " +
"Ensure you have you installed React Native as a dependency in your project and try again."
)
}
}
dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
implementation 'com.jakewharton.timber:timber:4.7.1'
// From node_modules
}
if (isNewArchitectureEnabled()) {
react {
jsRootDir = file("../")
libraryName = "JitsiMeetReactNative"
codegenJavaPackageName = "org.jitsi.meet.sdk"
}
}
// Copy sounds to assets directory
android.libraryVariants.all { def variant ->
def mergeAssetsTask = variant.mergeAssetsProvider.get()
def mergeResourcesTask = variant.mergeResourcesProvider.get()
mergeAssetsTask.doLast {
def assetsDir = mergeAssetsTask.outputDir.get()
def soundsDir = "${projectDir}/../sounds"
copy {
from("${soundsDir}")
include("*.wav")
include("*.mp3")
into("${assetsDir}/sounds")
}
}
}

View File

@@ -0,0 +1,5 @@
JitsiMeetReactNative_kotlinVersion=2.0.21
JitsiMeetReactNative_minSdkVersion=26
JitsiMeetReactNative_targetSdkVersion=34
JitsiMeetReactNative_compileSdkVersion=34
JitsiMeetReactNative_ndkversion=27.1.12297006

176
react-native-sdk/index.tsx Normal file
View File

@@ -0,0 +1,176 @@
/* eslint-disable lines-around-comment, no-undef, no-unused-vars */
// NB: This import must always come first.
import './react/bootstrap.native';
import React, {
forwardRef,
useEffect,
useImperativeHandle,
useLayoutEffect,
useRef,
useState
} from 'react';
import { View, ViewStyle } from 'react-native';
import type { IRoomsInfo } from '../react/features/breakout-rooms/types';
import { appNavigate } from './react/features/app/actions.native';
import { App } from './react/features/app/components/App.native';
import { setAudioOnly } from './react/features/base/audio-only/actions';
import { setAudioMuted, setVideoMuted } from './react/features/base/media/actions';
import { getRoomsInfo } from './react/features/breakout-rooms/functions';
interface IEventListeners {
onAudioMutedChanged?: Function;
onVideoMutedChanged?: Function;
onConferenceBlurred?: Function;
onConferenceFocused?: Function;
onConferenceJoined?: Function;
onConferenceLeft?: Function;
onConferenceWillJoin?: Function;
onEnterPictureInPicture?: Function;
onEndpointMessageReceived?: Function;
onParticipantJoined?: Function;
onParticipantLeft?: ({ id }: { id: string }) => void;
onReadyToClose?: Function;
}
interface IUserInfo {
avatarURL: string;
displayName: string;
email: string;
}
interface IAppProps {
config: object;
eventListeners?: IEventListeners;
flags?: object;
room: string;
serverURL?: string;
style?: Object;
token?: string;
userInfo?: IUserInfo;
}
export interface JitsiRefProps {
close: Function;
setAudioOnly?: (value: boolean) => void;
setAudioMuted?: (muted: boolean) => void;
setVideoMuted?: (muted: boolean) => void;
getRoomsInfo?: () => IRoomsInfo;
}
/**
* Main React Native SDK component that displays a Jitsi Meet conference and gets all required params as props
*/
export const JitsiMeeting = forwardRef<JitsiRefProps, IAppProps>((props, ref) => {
const [ appProps, setAppProps ] = useState({});
const app = useRef(null);
const {
config,
eventListeners,
flags,
room,
serverURL,
style,
token,
userInfo
} = props;
// eslint-disable-next-line arrow-body-style
useImperativeHandle(ref, () => ({
close: () => {
const dispatch = app.current.state.store.dispatch;
dispatch(appNavigate(undefined));
},
setAudioOnly: value => {
const dispatch = app.current.state.store.dispatch;
dispatch(setAudioOnly(value));
},
setAudioMuted: muted => {
const dispatch = app.current.state.store.dispatch;
dispatch(setAudioMuted(muted));
},
setVideoMuted: muted => {
const dispatch = app.current.state.store.dispatch;
dispatch(setVideoMuted(muted));
},
getRoomsInfo: () => {
const state = app.current.state.store.getState();
return getRoomsInfo(state);
}
}));
useEffect(
() => {
const urlObj = {
config,
jwt: token
};
let urlProps;
if (room.includes('://')) {
urlProps = {
...urlObj,
url: room
};
} else {
urlProps = {
...urlObj,
room,
serverURL
};
}
setAppProps({
'flags': flags,
'rnSdkHandlers': {
onAudioMutedChanged: eventListeners?.onAudioMutedChanged,
onVideoMutedChanged: eventListeners?.onVideoMutedChanged,
onConferenceBlurred: eventListeners?.onConferenceBlurred,
onConferenceFocused: eventListeners?.onConferenceFocused,
onConferenceJoined: eventListeners?.onConferenceJoined,
onConferenceWillJoin: eventListeners?.onConferenceWillJoin,
onConferenceLeft: eventListeners?.onConferenceLeft,
onEnterPictureInPicture: eventListeners?.onEnterPictureInPicture,
onEndpointMessageReceived: eventListeners?.onEndpointMessageReceived,
onParticipantJoined: eventListeners?.onParticipantJoined,
onParticipantLeft: eventListeners?.onParticipantLeft,
onReadyToClose: eventListeners?.onReadyToClose
},
'url': urlProps,
'userInfo': userInfo
});
}, []
);
// eslint-disable-next-line arrow-body-style
useLayoutEffect(() => {
/**
* When you close the component you need to reset it.
* In some cases it needs to be added as the parent component may have been destroyed.
* Without this change the call remains active without having the jitsi screen.
*/
return () => {
const dispatch = app.current?.state?.store?.dispatch;
dispatch && dispatch(appNavigate(undefined));
};
}, []);
return (
<View style = { style as ViewStyle }>
<App
{ ...appProps }
ref = { app } />
</View>
);
});

View File

@@ -0,0 +1,35 @@
require 'json'
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
Pod::Spec.new do |s|
s.name = 'jitsi-meet-rnsdk'
s.version = package['version']
s.summary = package['description']
s.description = package['description']
s.license = package['license']
s.author = package['author']
s.homepage = package['homepage']
s.source = { :git => package['repository']['url'], :tag => s.version }
s.requires_arc = true
s.platform = :ios, '15.1'
s.preserve_paths = 'ios/**/*'
s.source_files = 'ios/**/*.{h,m}'
s.dependency 'React-Core'
s.dependency 'react-native-webrtc'
s.dependency 'ObjectiveDropboxOfficial', '6.2.3'
s.script_phase = {
:name => 'Copy Sound Files',
:script => '
SOURCE_PATH="${PODS_TARGET_SRCROOT}/sounds/"
TARGET_PATH=$(dirname "${CONFIGURATION_BUILD_DIR}")
PROJECT_NAME=$(basename $(dirname $(dirname "${PROJECT_DIR}"))).app
cp -R "${SOURCE_PATH}" "${TARGET_PATH}/${PROJECT_NAME}"
',
}
end

View File

@@ -0,0 +1,100 @@
{
"name": "@jitsi/react-native-sdk",
"version": "0.0.0",
"description": "React Native SDK for Jitsi Meet.",
"main": "index.tsx",
"license": "Apache-2.0",
"author": "",
"homepage": "https://jitsi.org",
"repository": {
"type": "git",
"url": "git+https://github.com/jitsi/jitsi-meet.git"
},
"dependencies": {
"@braintree/sanitize-url": "0.0.0",
"@jitsi/js-utils": "0.0.0",
"@jitsi/logger": "0.0.0",
"@jitsi/rtcstats": "0.0.0",
"@react-navigation/bottom-tabs": "0.0.0",
"@react-navigation/elements": "0.0.0",
"@react-navigation/material-top-tabs": "0.0.0",
"@react-navigation/native": "0.0.0",
"@react-navigation/stack": "0.0.0",
"@stomp/stompjs": "0.0.0",
"@xmldom/xmldom": "0.0.0",
"abab": "0.0.0",
"base64-js": "0.0.0",
"dayjs": "0.0.0",
"grapheme-splitter": "0.0.0",
"i18n-iso-countries": "0.0.0",
"i18next": "0.0.0",
"js-md5": "0.0.0",
"i18next-http-backend": "0.0.0",
"js-sha512": "0.0.0",
"jwt-decode": "0.0.0",
"lib-jitsi-meet": "0.0.0",
"lodash-es": "0.0.0",
"optional-require": "0.0.0",
"promise.allsettled": "0.0.0",
"promise.withresolvers": "0.0.0",
"punycode": "0.0.0",
"react-emoji-render": "0.0.0",
"react-i18next": "0.0.0",
"react-linkify": "0.0.0",
"react-native-dialog": "0.0.0",
"react-native-paper": "0.0.0",
"react-native-svg-transformer": "0.0.0",
"react-native-tab-view": "0.0.0",
"react-native-url-polyfill": "0.0.0",
"react-native-youtube-iframe": "0.0.0",
"react-redux": "0.0.0",
"redux": "0.0.0",
"redux-thunk": "0.0.0",
"text-encoding": "0.0.0",
"unorm": "0.0.0",
"util": "0.0.0",
"uuid": "0.0.0",
"zxcvbn": "0.0.0"
},
"peerDependencies": {
"@amplitude/analytics-react-native": "0.0.0",
"@giphy/react-native-sdk": "0.0.0",
"@react-native-async-storage/async-storage": "0.0.0",
"@react-native-clipboard/clipboard": "0.0.0",
"@react-native-community/netinfo": "0.0.0",
"@react-native-community/slider": "0.0.0",
"@react-native-google-signin/google-signin": "0.0.0",
"@sayem314/react-native-keep-awake": "0.0.0",
"react-native": "0.0.0",
"react": "*",
"react-native-background-timer": "0.0.0",
"react-native-calendar-events": "0.0.0",
"react-native-default-preference": "0.0.0",
"react-native-device-info": "0.0.0",
"react-native-get-random-values": "0.0.0",
"react-native-gesture-handler": "0.0.0",
"react-native-immersive-mode": "0.0.0",
"react-native-pager-view": "0.0.0",
"react-native-performance": "0.0.0",
"react-native-orientation-locker": "0.0.0",
"react-native-safe-area-context": "0.0.0",
"react-native-screens": "0.0.0",
"react-native-sound": "0.0.0",
"react-native-splash-view": "0.0.0",
"react-native-svg": "0.0.0",
"react-native-video": "0.0.0",
"react-native-watch-connectivity": "0.0.0",
"react-native-webrtc": "0.0.0",
"react-native-webview": "0.0.0"
},
"scripts": {
"postinstall": "node sdk_instructions.js",
"prepare": "node prepare_sdk.js"
},
"bugs": {
"url": "https://github.com/jitsi/jitsi-meet/issues"
},
"keywords": [
"react-native"
]
}

210
react-native-sdk/prepare_sdk.js vendored Normal file
View File

@@ -0,0 +1,210 @@
const fs = require('fs');
const path = require('path');
const androidSourcePath = '../android/sdk/src/main/java/org/jitsi/meet/sdk';
const androidMainSourcePath = '../android/sdk/src/main/res';
const androidTargetPath = './android/src/main/java/org/jitsi/meet/sdk';
const androidMainTargetPath = './android/src/main/res';
const iosSrcPath = '../ios/sdk/src';
const iosDestPath = './ios/src';
/**
* Copies a specified file in a way that recursive copy is possible.
*/
function copyFileSync(source, target) {
let targetFile = target;
// If target is a directory, a new file with the same name will be created
if (fs.existsSync(target)) {
if (fs.lstatSync(target).isDirectory()) {
targetFile = path.join(target, path.basename(source));
}
}
fs.copyFileSync(source, targetFile);
}
/**
* Copies a specified directory recursively.
*/
function copyFolderRecursiveSync(source, target) {
let files = [];
const targetFolder = path.join(target, path.basename(source));
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder, { recursive: true });
}
if (fs.lstatSync(source).isDirectory()) {
files = fs.readdirSync(source);
files.forEach(file => {
const curSource = path.join(source, file);
if (fs.lstatSync(curSource).isDirectory()) {
copyFolderRecursiveSync(curSource, targetFolder);
} else {
copyFileSync(curSource, targetFolder);
}
});
}
}
copyFolderRecursiveSync(
'../images',
'.'
);
copyFolderRecursiveSync(
'../sounds',
'.'
);
copyFolderRecursiveSync(
'../lang',
'.'
);
copyFolderRecursiveSync(
'../modules',
'.'
);
copyFolderRecursiveSync(
'../react',
'.'
);
copyFolderRecursiveSync(
'../ios/sdk/sdk.xcodeproj',
'./ios'
);
copyFolderRecursiveSync(
`${iosSrcPath}/callkit`,
iosDestPath
);
copyFolderRecursiveSync(
`${iosSrcPath}/dropbox`,
iosDestPath
);
fs.copyFileSync(
`${iosSrcPath}/AppInfo.m`,
`${iosDestPath}/AppInfo.m`
);
fs.copyFileSync(
`${iosSrcPath}/AudioMode.m`,
`${iosDestPath}/AudioMode.m`
);
fs.copyFileSync(
`${iosSrcPath}/InfoPlistUtil.m`,
`${iosDestPath}/InfoPlistUtil.m`
);
fs.copyFileSync(
`${iosSrcPath}/InfoPlistUtil.h`,
`${iosDestPath}/InfoPlistUtil.h`
);
fs.copyFileSync(
`${iosSrcPath}/JavaScriptSandbox.m`,
`${iosDestPath}/JavaScriptSandbox.m`
);
fs.copyFileSync(
`${iosSrcPath}/JitsiAudioSession.m`,
`${iosDestPath}/JitsiAudioSession.m`
);
fs.copyFileSync(
`${iosSrcPath}/JitsiAudioSession.h`,
`${iosDestPath}/JitsiAudioSession.h`
);
fs.copyFileSync(
`${iosSrcPath}/JitsiAudioSession+Private.h`,
`${iosDestPath}/JitsiAudioSession+Private.h`
);
fs.copyFileSync(
`${iosSrcPath}/LocaleDetector.m`,
`${iosDestPath}/LocaleDetector.m`
);
fs.copyFileSync(
`${iosSrcPath}/POSIX.m`,
`${iosDestPath}/POSIX.m`
);
fs.copyFileSync(
`${iosSrcPath}/Proximity.m`,
`${iosDestPath}/Proximity.m`
);
copyFolderRecursiveSync(
`${androidSourcePath}/log`,
`${androidTargetPath}/log`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/values`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/drawable-hdpi`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/drawable-mdpi`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/drawable-xhdpi`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/drawable-xxhdpi`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidMainSourcePath}/drawable-xxxhdpi`,
`${androidMainTargetPath}`
);
copyFolderRecursiveSync(
`${androidSourcePath}/net`,
`${androidTargetPath}/log`
);
fs.copyFileSync(
`${androidSourcePath}/AndroidSettingsModule.java`,
`${androidTargetPath}/AndroidSettingsModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/AppInfoModule.java`,
`${androidTargetPath}/AppInfoModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/AudioDeviceHandlerConnectionService.java`,
`${androidTargetPath}/AudioDeviceHandlerConnectionService.java`
);
fs.copyFileSync(
`${androidSourcePath}/AudioDeviceHandlerGeneric.java`,
`${androidTargetPath}/AudioDeviceHandlerGeneric.java`
);
fs.copyFileSync(
`${androidSourcePath}/AudioModeModule.java`,
`${androidTargetPath}/AudioModeModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/ConnectionService.java`,
`${androidTargetPath}/ConnectionService.java`
);
fs.copyFileSync(
`${androidSourcePath}/JavaScriptSandboxModule.java`,
`${androidTargetPath}/JavaScriptSandboxModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/LocaleDetector.java`,
`${androidTargetPath}/LocaleDetector.java`
);
fs.copyFileSync(
`${androidSourcePath}/LogBridgeModule.java`,
`${androidTargetPath}/LogBridgeModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/PictureInPictureModule.java`,
`${androidTargetPath}/PictureInPictureModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/ProximityModule.java`,
`${androidTargetPath}/ProximityModule.java`
);
fs.copyFileSync(
`${androidSourcePath}/RNConnectionService.java`,
`${androidTargetPath}/RNConnectionService.java`
);

2
react-native-sdk/sdk_instructions.js vendored Normal file
View File

@@ -0,0 +1,2 @@
console.log('Run node node_modules/@jitsi/react-native-sdk/update_dependencies.js '
+ 'script to update the necessary dependencies');

102
react-native-sdk/update_dependencies.js vendored Normal file
View File

@@ -0,0 +1,102 @@
/* eslint-disable guard-for-in */
/* global __dirname */
const fs = require('fs');
const path = require('path');
const semver = require('semver');
const pathToPackageJSON = path.resolve(__dirname, '../../../package.json');
const packageJSON = require(pathToPackageJSON);
const RNSDKpackageJSON = require(path.resolve(__dirname, './package.json'));
/**
* Updates dependencies from the app package.json with the peer dependencies of the RNSDK package.json.
*/
function updateDependencies() {
let updated = false;
for (const key in RNSDKpackageJSON.peerDependencies) {
if (!packageJSON.dependencies.hasOwnProperty(key)) {
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
updated = true;
}
if (!semver.valid(packageJSON.dependencies[key])
&& packageJSON.dependencies[key] !== RNSDKpackageJSON.peerDependencies[key]) {
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
updated = true;
console.log(`
We changed ${key} version number from ${packageJSON.dependencies[key]} to ${RNSDKpackageJSON.peerDependencies[key]}`
);
continue;
}
if (semver.satisfies(RNSDKpackageJSON.peerDependencies[key], `=${packageJSON.dependencies[key]}`)) {
continue;
}
if (semver.satisfies(RNSDKpackageJSON.peerDependencies[key], `>${packageJSON.dependencies[key]}`)) {
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
updated = true;
console.log(`${key} is now set to ${RNSDKpackageJSON.peerDependencies[key]}`);
}
if (!semver.valid(RNSDKpackageJSON.peerDependencies[key])
&& RNSDKpackageJSON.peerDependencies[key].includes('github')
&& packageJSON.dependencies[key] !== RNSDKpackageJSON.peerDependencies[key]) {
packageJSON.dependencies[key] = RNSDKpackageJSON.peerDependencies[key];
updated = true;
console.log(
`A fix for ${key} is available on ${RNSDKpackageJSON.peerDependencies[key]}.
This is now set on your end.`
);
}
}
packageJSON.overrides = packageJSON.overrides || {};
for (const key in RNSDKpackageJSON.overrides) {
if (!packageJSON.overrides.hasOwnProperty(key)) {
packageJSON.overrides[key] = RNSDKpackageJSON.overrides[key];
updated = true;
}
}
if (!updated) {
console.log('All your dependencies are up to date!');
return;
}
console.log(`
=========================
🚀 Your project was updated!
🛠 Make sure you run npm install
📱 If you are building for iOS run cd ios && pod install to link them.
=========================
`);
packageJSON.dependencies = Object.keys(packageJSON.dependencies)
.sort()
.reduce((item, itemKey) => {
item[itemKey] = packageJSON.dependencies[itemKey];
return item;
}, {});
fs.writeFileSync(pathToPackageJSON, JSON.stringify(packageJSON, null, 2));
console.log(
'All needed dependencies have been updated. \nPlease run npm install.'
);
}
updateDependencies();

View File

@@ -0,0 +1,52 @@
const fs = require('fs');
const semver = require('semver');
const packageJSON = require('../package.json');
const SDKPackageJSON = require('./package.json');
// Skip checking these.
const skipDeps = [ 'react', 'react-native' ];
/**
* Merges the dependency versions from the root package.json with the dependencies of the SDK package.json.
*/
function mergeDependencyVersions() {
// Updates SDK dependencies to match project dependencies.
for (const key in SDKPackageJSON.dependencies) {
if (SDKPackageJSON.dependencies.hasOwnProperty(key)) {
SDKPackageJSON.dependencies[key] = packageJSON.dependencies[key] || packageJSON.devDependencies[key];
}
}
// Updates SDK peer dependencies.
for (const key in packageJSON.dependencies) {
if (SDKPackageJSON.peerDependencies.hasOwnProperty(key) && !skipDeps.includes(key)) {
SDKPackageJSON.peerDependencies[key] = packageJSON.dependencies[key];
}
}
// Set RN peer dependency.
const rnVersion = semver.parse(packageJSON.dependencies['react-native']);
if (!rnVersion) {
throw new Error('failed to parse React Native version');
}
// In RN the "major" version is the Semver minor.
SDKPackageJSON.peerDependencies['react-native'] = `~0.${rnVersion.minor}.0`;
// Updates SDK overrides dependencies.
for (const key in packageJSON.overrides) {
if (SDKPackageJSON.overrides.hasOwnProperty(key)) {
SDKPackageJSON.overrides[key] = packageJSON.overrides[key];
}
}
const data = JSON.stringify(SDKPackageJSON, null, 4);
fs.writeFileSync('package.json', data);
}
mergeDependencyVersions();