@seamlink/cordova-plugin-jitsi 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish.yml +47 -0
- package/README.md +31 -0
- package/build-extras.gradle +14 -0
- package/gradle.properties +22 -0
- package/package.json +27 -0
- package/plugin.xml +80 -0
- package/src/android/JitsiPlugin.java +251 -0
- package/src/android/jitsiplugin.gradle +64 -0
- package/src/ios/JitsiMeetView.h +45 -0
- package/src/ios/JitsiMeetViewDelegate.h +68 -0
- package/src/ios/JitsiPlugin.h +20 -0
- package/src/ios/JitsiPlugin.mm +117 -0
- package/www/JitsiPlugin.js +9 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
# prevent this action from running on forks
|
|
14
|
+
if: github.repository == 'your/repo'
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
pull-requests: read
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: '20.x'
|
|
24
|
+
registry-url: 'https://registry.npmjs.org'
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm ci
|
|
27
|
+
- name: Extract version from package.json
|
|
28
|
+
uses: sergeysova/jq-action@v2
|
|
29
|
+
id: version
|
|
30
|
+
with:
|
|
31
|
+
cmd: 'jq .version package.json -r'
|
|
32
|
+
- name: Get latest tag
|
|
33
|
+
uses: actions-ecosystem/action-get-latest-tag@v1
|
|
34
|
+
id: get-latest-tag
|
|
35
|
+
- name: Publish GitHub Release
|
|
36
|
+
uses: release-drafter/release-drafter@v6
|
|
37
|
+
if: ${{ contains(steps.get-latest-tag.outputs.tag, steps.version.outputs.value) == false }}
|
|
38
|
+
with:
|
|
39
|
+
version: ${{ steps.version.outputs.value }}
|
|
40
|
+
publish: true
|
|
41
|
+
env:
|
|
42
|
+
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
|
43
|
+
- name: Publish to NPM
|
|
44
|
+
if: ${{ contains(steps.get-latest-tag.outputs.tag, steps.version.outputs.value) == false }}
|
|
45
|
+
run: npm publish
|
|
46
|
+
env:
|
|
47
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# cordova-plugin-jitsimeet
|
|
2
|
+
Cordova plugin for Jitsi Meet React Native SDK. Works with both iOS and Android, and fixes the 64-bit binary dependency issue with Android found in previous versions of this plugin.
|
|
3
|
+
|
|
4
|
+
# Summary
|
|
5
|
+
This is based on the repo by findmate, but I updated the JitsiMeet SDK and WebRTC framework to the latest version, to get all features working in a Cordova app.
|
|
6
|
+
The original repo is here: https://github.com/findmate/cordova-plugin-jitsi
|
|
7
|
+
|
|
8
|
+
# Installation
|
|
9
|
+
`cordova plugin add https://github.com/seamlink-dev/cordova-plugin-jitsi`
|
|
10
|
+
|
|
11
|
+
# Usage
|
|
12
|
+
```
|
|
13
|
+
const roomId = 'your-custom-room-id';
|
|
14
|
+
|
|
15
|
+
jitsiplugin.join('https://meet.jit.si/', roomId, false, (data) => {
|
|
16
|
+
//CONFERENCE_WILL_JOIN
|
|
17
|
+
//CONFERENCE_JOINED
|
|
18
|
+
//CONFERENCE_TERMINATED
|
|
19
|
+
//CONFERENCE_FINISHED
|
|
20
|
+
//CONFERENCE_DESTROYED
|
|
21
|
+
if (data === "CONFERENCE_TERMINATED") {
|
|
22
|
+
jitsiplugin.destroy((data) => {
|
|
23
|
+
// call finished
|
|
24
|
+
}, f(err) => {
|
|
25
|
+
console.log(err);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}, (err) => {
|
|
29
|
+
console.log(err);
|
|
30
|
+
});
|
|
31
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
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: -Xmx10248m -XX:MaxPermSize=256m
|
|
13
|
+
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
|
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
|
+
android.useDeprecatedNdk=true
|
|
21
|
+
android.useAndroidX=true
|
|
22
|
+
android.enableJetifier=true
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seamlink/cordova-plugin-jitsi",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "\n This is plugin for Jitsi Meet calling service!\n ",
|
|
5
|
+
"cordova": {
|
|
6
|
+
"id": "@seamlink/cordova-plugin-jitsi",
|
|
7
|
+
"platforms": [
|
|
8
|
+
"android",
|
|
9
|
+
"ios"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/seamlink-dev/cordova-plugin-jitsi.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ecosystem:cordova",
|
|
18
|
+
"cordova-android",
|
|
19
|
+
"cordova-ios"
|
|
20
|
+
],
|
|
21
|
+
"author": "Seamlink",
|
|
22
|
+
"license": "Auris",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/seamlink-dev/cordova-plugin-jitsi/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/seamlink-dev/cordova-plugin-jitsi#readme"
|
|
27
|
+
}
|
package/plugin.xml
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<?xml version='1.0' encoding='utf-8'?>
|
|
2
|
+
<plugin id='@seamlink/cordova-plugin-jitsi' version='2.1.0'
|
|
3
|
+
xmlns='http://apache.org/cordova/ns/plugins/1.0'
|
|
4
|
+
xmlns:tools="http://schemas.android.com/tools"
|
|
5
|
+
xmlns:android='http://schemas.android.com/apk/res/android'>
|
|
6
|
+
<name>JitsiPlugin</name>
|
|
7
|
+
<js-module name='JitsiPlugin' src='www/JitsiPlugin.js'>
|
|
8
|
+
<clobbers target='jitsiplugin' />
|
|
9
|
+
</js-module>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
<platform name='android'>
|
|
13
|
+
<config-file parent='/*' target='res/xml/config.xml'>
|
|
14
|
+
<feature name='JitsiPlugin'>
|
|
15
|
+
<param name='android-package' value='com.cordova.plugin.jitsi.JitsiPlugin' />
|
|
16
|
+
</feature>
|
|
17
|
+
</config-file>
|
|
18
|
+
<config-file parent='/*' target='AndroidManifest.xml'>
|
|
19
|
+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
20
|
+
<uses-permission android:name="android.permission.BLUETOOTH" />
|
|
21
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
22
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
23
|
+
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
|
24
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
25
|
+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
|
26
|
+
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
27
|
+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
28
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
29
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
|
30
|
+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
|
|
31
|
+
</config-file>
|
|
32
|
+
<config-file target="AndroidManifest.xml" parent="/manifest/application">
|
|
33
|
+
<activity
|
|
34
|
+
android:name="com.cordova.plugin.jitsi.JitsiMeetPluginActivity"
|
|
35
|
+
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"
|
|
36
|
+
android:launchMode="singleTask"
|
|
37
|
+
android:resizeableActivity="true"
|
|
38
|
+
android:supportsPictureInPicture="true"
|
|
39
|
+
android:theme="@style/Theme.AppCompat"
|
|
40
|
+
android:parentActivityName=".MainActivity"
|
|
41
|
+
android:fitsSystemWindows="true"
|
|
42
|
+
android:background="@android:color/black"
|
|
43
|
+
android:allowTaskReparenting="true"
|
|
44
|
+
android:windowSoftInputMode="adjustResize">
|
|
45
|
+
</activity>
|
|
46
|
+
<service android:name="com.cordova.plugin.jitsi.JitsiService"
|
|
47
|
+
android:stopWithTask="false" />
|
|
48
|
+
</config-file>
|
|
49
|
+
<source-file src='src/android/JitsiPlugin.java' target-dir='src/com/cordova/plugin/jitsi/' />
|
|
50
|
+
<framework src='src/android/jitsiplugin.gradle' custom='true' type='gradleReference' />
|
|
51
|
+
</platform>
|
|
52
|
+
|
|
53
|
+
<!-- ios -->
|
|
54
|
+
<platform name="ios">
|
|
55
|
+
<config-file target="config.xml" parent="/*">
|
|
56
|
+
<feature name="JitsiPlugin">
|
|
57
|
+
<param name="ios-package" value="JitsiPlugin" />
|
|
58
|
+
</feature>
|
|
59
|
+
</config-file>
|
|
60
|
+
<config-file target="*-Info.plist" parent="UIBackgroundModes">
|
|
61
|
+
<array>
|
|
62
|
+
<string>audio</string>
|
|
63
|
+
<string>voip</string>
|
|
64
|
+
</array>
|
|
65
|
+
</config-file>
|
|
66
|
+
<header-file src="src/ios/JitsiMeetView.h" />
|
|
67
|
+
<header-file src="src/ios/JitsiMeetViewDelegate.h" />
|
|
68
|
+
<header-file src="src/ios/JitsiPlugin.h" />
|
|
69
|
+
<source-file src="src/ios/JitsiPlugin.mm" />
|
|
70
|
+
<podspec>
|
|
71
|
+
<config>
|
|
72
|
+
<source url="https://cdn.cocoapods.org" />
|
|
73
|
+
<source url="https://github.com/CocoaPods/Specs.git" />
|
|
74
|
+
</config>
|
|
75
|
+
<pods use-frameworks="true">
|
|
76
|
+
<pod name="JitsiMeetSDK" spec="10.3.0" />
|
|
77
|
+
</pods>
|
|
78
|
+
</podspec>
|
|
79
|
+
</platform>
|
|
80
|
+
</plugin>
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
package com.cordova.plugin.jitsi;
|
|
2
|
+
|
|
3
|
+
import org.apache.cordova.CordovaInterface;
|
|
4
|
+
import org.apache.cordova.CordovaPlugin;
|
|
5
|
+
import org.apache.cordova.CallbackContext;
|
|
6
|
+
import org.apache.cordova.PluginResult;
|
|
7
|
+
import org.apache.cordova.PermissionHelper;
|
|
8
|
+
import org.apache.cordova.CordovaWebView;
|
|
9
|
+
|
|
10
|
+
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
|
11
|
+
import org.json.JSONArray;
|
|
12
|
+
import org.json.JSONException;
|
|
13
|
+
|
|
14
|
+
import android.content.BroadcastReceiver;
|
|
15
|
+
import android.content.Context;
|
|
16
|
+
import android.content.Intent;
|
|
17
|
+
import android.content.IntentFilter;
|
|
18
|
+
import android.Manifest;
|
|
19
|
+
import android.content.pm.PackageManager;
|
|
20
|
+
import android.content.pm.PackageManager.NameNotFoundException;
|
|
21
|
+
import android.view.View;
|
|
22
|
+
|
|
23
|
+
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
24
|
+
|
|
25
|
+
import java.net.MalformedURLException;
|
|
26
|
+
import java.net.URL;
|
|
27
|
+
|
|
28
|
+
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
|
|
29
|
+
import org.jitsi.meet.sdk.JitsiMeetActivityDelegate;
|
|
30
|
+
import org.jitsi.meet.sdk.JitsiMeetActivityInterface;
|
|
31
|
+
import org.jitsi.meet.sdk.BroadcastEvent; // Import BroadcastEvent
|
|
32
|
+
|
|
33
|
+
import com.facebook.react.modules.core.PermissionListener;
|
|
34
|
+
|
|
35
|
+
import timber.log.Timber;
|
|
36
|
+
|
|
37
|
+
public class JitsiPlugin extends CordovaPlugin
|
|
38
|
+
implements JitsiMeetActivityInterface {
|
|
39
|
+
|
|
40
|
+
private CallbackContext _callback;
|
|
41
|
+
private BroadcastReceiver jitsiBroadcastReceiver;
|
|
42
|
+
|
|
43
|
+
public static final int TAKE_PIC_SEC = 0;
|
|
44
|
+
|
|
45
|
+
private static final String JOIN_ACTION = "join";
|
|
46
|
+
private static final String DESTROY_ACTION = "destroy";
|
|
47
|
+
|
|
48
|
+
@Override
|
|
49
|
+
public void pluginInitialize() {
|
|
50
|
+
super.pluginInitialize();
|
|
51
|
+
|
|
52
|
+
// Create the receiver to listen for Jitsi events
|
|
53
|
+
jitsiBroadcastReceiver = new BroadcastReceiver() {
|
|
54
|
+
@Override
|
|
55
|
+
public void onReceive(Context context, Intent intent) {
|
|
56
|
+
if (intent == null) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
BroadcastEvent event = new BroadcastEvent(intent);
|
|
61
|
+
String eventName = "";
|
|
62
|
+
|
|
63
|
+
Timber.d("Jitsi event received: %s", event.getType());
|
|
64
|
+
|
|
65
|
+
switch (event.getType()) {
|
|
66
|
+
case CONFERENCE_JOINED:
|
|
67
|
+
eventName = "CONFERENCE_JOINED";
|
|
68
|
+
break;
|
|
69
|
+
case CONFERENCE_WILL_JOIN:
|
|
70
|
+
eventName = "CONFERENCE_WILL_JOIN";
|
|
71
|
+
break;
|
|
72
|
+
case CONFERENCE_TERMINATED:
|
|
73
|
+
eventName = "CONFERENCE_TERMINATED";
|
|
74
|
+
break;
|
|
75
|
+
case PARTICIPANT_JOINED:
|
|
76
|
+
eventName = "PARTICIPANT_JOINED";
|
|
77
|
+
break;
|
|
78
|
+
case PARTICIPANT_LEFT:
|
|
79
|
+
eventName = "PARTICIPANT_LEFT";
|
|
80
|
+
break;
|
|
81
|
+
case READY_TO_CLOSE:
|
|
82
|
+
eventName = "READY_TO_CLOSE";
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!eventName.isEmpty() && _callback != null) {
|
|
87
|
+
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, eventName);
|
|
88
|
+
pluginResult.setKeepCallback(true);
|
|
89
|
+
_callback.sendPluginResult(pluginResult);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
LocalBroadcastManager.getInstance(cordova.getActivity())
|
|
94
|
+
.registerReceiver(jitsiBroadcastReceiver, createJitsiIntentFilter());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@Override
|
|
98
|
+
public void onResume(boolean multitasking) {
|
|
99
|
+
super.onResume(multitasking);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Override
|
|
103
|
+
public void onPause(boolean multitasking) {
|
|
104
|
+
super.onPause(multitasking);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private IntentFilter createJitsiIntentFilter() {
|
|
108
|
+
IntentFilter filter = new IntentFilter();
|
|
109
|
+
// Add all actions that the receiver should listen for
|
|
110
|
+
filter.addAction(BroadcastEvent.Type.CONFERENCE_JOINED.getAction());
|
|
111
|
+
filter.addAction(BroadcastEvent.Type.CONFERENCE_WILL_JOIN.getAction());
|
|
112
|
+
filter.addAction(BroadcastEvent.Type.CONFERENCE_TERMINATED.getAction());
|
|
113
|
+
filter.addAction(BroadcastEvent.Type.PARTICIPANT_JOINED.getAction());
|
|
114
|
+
filter.addAction(BroadcastEvent.Type.PARTICIPANT_LEFT.getAction());
|
|
115
|
+
filter.addAction(BroadcastEvent.Type.READY_TO_CLOSE.getAction());
|
|
116
|
+
return filter;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@Override
|
|
120
|
+
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
|
121
|
+
_callback = callbackContext;
|
|
122
|
+
|
|
123
|
+
if (action.equals(JOIN_ACTION)) {
|
|
124
|
+
String serverUrl = args.getString(0);
|
|
125
|
+
String roomId = args.getString(1);
|
|
126
|
+
boolean audioOnly = args.getBoolean(2);
|
|
127
|
+
String token = args.getString(3);
|
|
128
|
+
try {
|
|
129
|
+
this.callJoin(serverUrl, roomId, audioOnly, token);
|
|
130
|
+
} catch (NameNotFoundException e) {
|
|
131
|
+
e.printStackTrace();
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
} else if (action.equals(DESTROY_ACTION)) {
|
|
135
|
+
this.destroy(callbackContext);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ... all your other methods (callJoin, join, destroy, etc.) remain the same
|
|
142
|
+
// ...
|
|
143
|
+
// You can now completely remove the stateChanged() method as it is no longer
|
|
144
|
+
// needed.
|
|
145
|
+
private void callJoin(String serverUrl, String roomId, Boolean audioOnly, String token)
|
|
146
|
+
throws NameNotFoundException {
|
|
147
|
+
|
|
148
|
+
this.join(serverUrl, roomId, audioOnly, token);
|
|
149
|
+
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private void join(final String serverUrl, final String roomId, final Boolean audioOnly, final String token) {
|
|
153
|
+
Timber.e("join called! Server: " + serverUrl + ", room : " + roomId);
|
|
154
|
+
|
|
155
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
156
|
+
URL serverUrlObject;
|
|
157
|
+
try {
|
|
158
|
+
serverUrlObject = new URL(serverUrl);
|
|
159
|
+
} catch (MalformedURLException e) {
|
|
160
|
+
Timber.e(e, "Invalid server URL");
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
|
|
165
|
+
.setServerURL(serverUrlObject)
|
|
166
|
+
.setRoom(roomId)
|
|
167
|
+
.setSubject(" ")
|
|
168
|
+
.setToken(token)
|
|
169
|
+
.setAudioOnly(audioOnly)
|
|
170
|
+
.setFeatureFlag("chat.enabled", true)
|
|
171
|
+
.setFeatureFlag("add-people.enabled", false)
|
|
172
|
+
.setFeatureFlag("invite.enabled", false)
|
|
173
|
+
.setFeatureFlag("calendar.enabled", false)
|
|
174
|
+
.setFeatureFlag("call-integration.enabled", false)
|
|
175
|
+
.setFeatureFlag("close-captions.enabled", false)
|
|
176
|
+
.setFeatureFlag("ios.recording.enabled", false)
|
|
177
|
+
.setFeatureFlag("kick-out.enabled", false)
|
|
178
|
+
.setFeatureFlag("live-streaming.enabled", false)
|
|
179
|
+
.setFeatureFlag("meeting-name.enabled", false)
|
|
180
|
+
.setFeatureFlag("meeting-password.enabled", false)
|
|
181
|
+
.setFeatureFlag("raise-hand.enabled", false)
|
|
182
|
+
.setFeatureFlag("recording.enabled", false)
|
|
183
|
+
.setFeatureFlag("server-url-change.enabled", false)
|
|
184
|
+
.setFeatureFlag("video-share.enabled", false)
|
|
185
|
+
.setFeatureFlag("welcomepage.enabled", false)
|
|
186
|
+
.setFeatureFlag("help.enabled", false)
|
|
187
|
+
.setFeatureFlag("lobby-mode.enabled", false)
|
|
188
|
+
.setFeatureFlag("server-url-change.enabled", false)
|
|
189
|
+
.setConfigOverride("requireDisplayName", false)
|
|
190
|
+
.setConfigOverride("disableModeratorIndicator", true)
|
|
191
|
+
.build();
|
|
192
|
+
|
|
193
|
+
JitsiMeetActivity.launch(cordova.getActivity(), options);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private void destroy(final CallbackContext callbackContext) {
|
|
198
|
+
cordova.getActivity().runOnUiThread(() -> {
|
|
199
|
+
JitsiMeetActivityDelegate.onHostDestroy(cordova.getActivity());
|
|
200
|
+
cordova.getActivity().setContentView(getView());
|
|
201
|
+
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, "DESTROYED");
|
|
202
|
+
pluginResult.setKeepCallback(true);
|
|
203
|
+
callbackContext.sendPluginResult(pluginResult);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private View getView() {
|
|
208
|
+
try {
|
|
209
|
+
return (View) webView.getClass().getMethod("getView").invoke(webView);
|
|
210
|
+
} catch (Exception e) {
|
|
211
|
+
return (View) webView;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@Override
|
|
216
|
+
public void onRequestPermissionsResult(final int requestCode, final String[] permissions,
|
|
217
|
+
final int[] grantResults) {
|
|
218
|
+
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Override
|
|
222
|
+
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
|
|
223
|
+
JitsiMeetActivityDelegate.requestPermissions(cordova.getActivity(), permissions, requestCode, listener);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@Override
|
|
227
|
+
public boolean shouldShowRequestPermissionRationale(String permissions) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@Override
|
|
232
|
+
public int checkSelfPermission(String permission) {
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@Override
|
|
237
|
+
public int checkPermission(String permission, int pid, int uid) {
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@Override
|
|
242
|
+
public void onDestroy() {
|
|
243
|
+
super.onDestroy();
|
|
244
|
+
// Unregister the receiver when the plugin is destroyed to prevent memory leaks
|
|
245
|
+
if (jitsiBroadcastReceiver != null) {
|
|
246
|
+
LocalBroadcastManager.getInstance(cordova.getActivity())
|
|
247
|
+
.unregisterReceiver(jitsiBroadcastReceiver);
|
|
248
|
+
jitsiBroadcastReceiver = null;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
repositories{
|
|
2
|
+
jcenter()
|
|
3
|
+
maven {
|
|
4
|
+
url "https://github.com/jitsi/jitsi-maven-repository/raw/master/releases"
|
|
5
|
+
}
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
maven { url 'https://www.jitpack.io' }
|
|
9
|
+
configurations.all {
|
|
10
|
+
resolutionStrategy {
|
|
11
|
+
force "com.google.android.gms:play-services-basement:15.0.1"
|
|
12
|
+
force "com.google.android.gms:play-services-tasks:15.0.1"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
android {
|
|
17
|
+
compileSdkVersion 35
|
|
18
|
+
buildToolsVersion "26.0.1"
|
|
19
|
+
|
|
20
|
+
defaultConfig {
|
|
21
|
+
minSdkVersion 23
|
|
22
|
+
targetSdkVersion 35
|
|
23
|
+
multiDexEnabled true
|
|
24
|
+
ndk {
|
|
25
|
+
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
packagingOptions {
|
|
29
|
+
// The project react-native does not provide 64-bit binaries at the
|
|
30
|
+
// time of this writing. Unfortunately, packaging any 64-bit
|
|
31
|
+
// binaries into the .apk will crash the app at runtime on 64-bit
|
|
32
|
+
// platforms.
|
|
33
|
+
// exclude '/lib/mips64/**'
|
|
34
|
+
// exclude '/lib/arm64-v8a/**'
|
|
35
|
+
// exclude '/lib/x86_64/**'
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
buildTypes {
|
|
40
|
+
debug {
|
|
41
|
+
signingConfig signingConfigs.debug
|
|
42
|
+
}
|
|
43
|
+
release {
|
|
44
|
+
// Caution! In production, you need to generate your own keystore file.
|
|
45
|
+
// see https://facebook.github.io/react-native/docs/signed-apk-android.
|
|
46
|
+
signingConfig signingConfigs.debug
|
|
47
|
+
// minifyEnabled true
|
|
48
|
+
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
compileOptions {
|
|
53
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
54
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
dependencies {
|
|
58
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
59
|
+
implementation ('org.jitsi.react:jitsi-meet-sdk:+') {
|
|
60
|
+
transitive = true;
|
|
61
|
+
}
|
|
62
|
+
implementation 'androidx.appcompat:appcompat:1.4.1'
|
|
63
|
+
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
|
64
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright @ 2017-present Atlassian Pty Ltd
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import <Foundation/Foundation.h>
|
|
18
|
+
#import <UIKit/UIKit.h>
|
|
19
|
+
#import <JitsiMeetSDK/JitsiMeetConferenceOptions.h>
|
|
20
|
+
|
|
21
|
+
#import "JitsiMeetViewDelegate.h"
|
|
22
|
+
|
|
23
|
+
@interface JitsiMeetView : UIView
|
|
24
|
+
|
|
25
|
+
@property (nonatomic, nullable, weak) id<JitsiMeetViewDelegate> delegate;
|
|
26
|
+
|
|
27
|
+
@property (copy, nonatomic, nullable) NSURL *defaultURL;
|
|
28
|
+
|
|
29
|
+
@property (nonatomic) BOOL welcomePageEnabled;
|
|
30
|
+
|
|
31
|
+
+ (BOOL)application:(UIApplication *_Nonnull)application
|
|
32
|
+
didFinishLaunchingWithOptions:(NSDictionary *_Nonnull)launchOptions;
|
|
33
|
+
|
|
34
|
+
+ (BOOL)application:(UIApplication * _Nonnull)application
|
|
35
|
+
continueUserActivity:(NSUserActivity * _Nonnull)userActivity
|
|
36
|
+
restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler;
|
|
37
|
+
|
|
38
|
+
+ (BOOL)application:(UIApplication * _Nonnull)application
|
|
39
|
+
openURL:(NSURL * _Nonnull)URL
|
|
40
|
+
sourceApplication:(NSString * _Nullable)sourceApplication
|
|
41
|
+
annotation:(id _Nullable)annotation;
|
|
42
|
+
|
|
43
|
+
- (void)join:(JitsiMeetConferenceOptions * _Nullable)options;
|
|
44
|
+
|
|
45
|
+
@end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright @ 2017-present Atlassian Pty Ltd
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
@protocol JitsiMeetViewDelegate <NSObject>
|
|
18
|
+
|
|
19
|
+
@optional
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Called when a joining a conference was unsuccessful or when there was an
|
|
23
|
+
* error while in a conference.
|
|
24
|
+
*
|
|
25
|
+
* The `data` dictionary contains an `error` key describing the error and a
|
|
26
|
+
* `url` key with the conference URL.
|
|
27
|
+
*/
|
|
28
|
+
- (void)conferenceFailed:(NSDictionary *)data;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Called when a conference was joined.
|
|
32
|
+
*
|
|
33
|
+
* The `data` dictionary contains a `url` key with the conference URL.
|
|
34
|
+
*/
|
|
35
|
+
- (void)conferenceJoined:(NSDictionary *)data;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Called when a conference was left.
|
|
39
|
+
*
|
|
40
|
+
* The `data` dictionary contains a `url` key with the conference URL.
|
|
41
|
+
*/
|
|
42
|
+
- (void)conferenceLeft:(NSDictionary *)data;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Called before a conference is joined.
|
|
46
|
+
*
|
|
47
|
+
* The `data` dictionary contains a `url` key with the conference URL.
|
|
48
|
+
*/
|
|
49
|
+
- (void)conferenceWillJoin:(NSDictionary *)data;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Called before a conference is left.
|
|
53
|
+
*
|
|
54
|
+
* The `data` dictionary contains a `url` key with the conference URL.
|
|
55
|
+
*/
|
|
56
|
+
- (void)conferenceTerminated:(NSDictionary *)data;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Called when loading the main configuration file from the Jitsi Meet
|
|
60
|
+
* deployment file.
|
|
61
|
+
*
|
|
62
|
+
* The `data` dictionary contains an `error` key with the error and a `url` key
|
|
63
|
+
* with the conference URL which necessitated the loading of the configuration
|
|
64
|
+
* file.
|
|
65
|
+
*/
|
|
66
|
+
- (void)loadConfigError:(NSDictionary *)data;
|
|
67
|
+
|
|
68
|
+
@end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#import <Cordova/CDVPlugin.h>
|
|
2
|
+
#import "JitsiMeetViewDelegate.h"
|
|
3
|
+
#import "JitsiMeetView.h"
|
|
4
|
+
|
|
5
|
+
@interface JitsiPlugin : CDVPlugin<JitsiMeetViewDelegate> {
|
|
6
|
+
JitsiMeetView* jitsiMeetView;
|
|
7
|
+
CDVInvokedUrlCommand* commandBack;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
- (void)join:(CDVInvokedUrlCommand *)command;
|
|
11
|
+
- (void)destroy:(CDVInvokedUrlCommand *)command;
|
|
12
|
+
- (void)backButtonPressed:(CDVInvokedUrlCommand *)command;
|
|
13
|
+
- (void)conferenceFailed:(NSDictionary *)data;
|
|
14
|
+
- (void)conferenceJoined:(NSDictionary *)data;
|
|
15
|
+
- (void)conferenceLeft:(NSDictionary *)data;
|
|
16
|
+
- (void)conferenceWillJoin:(NSDictionary *)data;
|
|
17
|
+
- (void)conferenceTerminated:(NSDictionary *)data;
|
|
18
|
+
- (void)loadConfigError:(NSDictionary *)data;
|
|
19
|
+
|
|
20
|
+
@end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#import "JitsiPlugin.h"
|
|
2
|
+
#import <JitsiMeetSDK/JitsiMeetConferenceOptions.h>
|
|
3
|
+
|
|
4
|
+
@implementation JitsiPlugin
|
|
5
|
+
{
|
|
6
|
+
CDVPluginResult *plgResult;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
- (void)join:(CDVInvokedUrlCommand *)command {
|
|
10
|
+
NSString* serverUrl = [command.arguments objectAtIndex:0];
|
|
11
|
+
NSString* room = [command.arguments objectAtIndex:1];
|
|
12
|
+
Boolean isAudioOnly = [[command.arguments objectAtIndex:2] boolValue];
|
|
13
|
+
NSString* token = [command.arguments objectAtIndex:3];
|
|
14
|
+
commandBack = command;
|
|
15
|
+
jitsiMeetView = [[JitsiMeetView alloc] initWithFrame:self.viewController.view.frame];
|
|
16
|
+
jitsiMeetView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
17
|
+
jitsiMeetView.delegate = self;
|
|
18
|
+
|
|
19
|
+
JitsiMeetConferenceOptions *options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
|
20
|
+
builder.serverURL = [NSURL URLWithString: serverUrl];
|
|
21
|
+
builder.room = room;
|
|
22
|
+
builder.subject = @" ";
|
|
23
|
+
builder.token = token;
|
|
24
|
+
builder.audioOnly = isAudioOnly;
|
|
25
|
+
[builder setFeatureFlag:@"welcomepage.enabled" withBoolean:false];
|
|
26
|
+
[builder setFeatureFlag:@"chat.enabled" withBoolean:true];
|
|
27
|
+
[builder setFeatureFlag:@"invite.enabled" withBoolean:false];
|
|
28
|
+
[builder setFeatureFlag:@"add-people.enabled" withBoolean:false];
|
|
29
|
+
[builder setFeatureFlag:@"calendar.enabled" withBoolean:false];
|
|
30
|
+
[builder setFeatureFlag:@"pip.enabled" withBoolean:true];
|
|
31
|
+
[builder setFeatureFlag:@"call-integration.enabled" withBoolean:false];
|
|
32
|
+
[builder setFeatureFlag:@"close-captions.enabled" withBoolean:false];
|
|
33
|
+
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:false];
|
|
34
|
+
[builder setFeatureFlag:@"kick-out.enabled" withBoolean:false];
|
|
35
|
+
[builder setFeatureFlag:@"live-streaming.enabled" withBoolean:false];
|
|
36
|
+
[builder setFeatureFlag:@"meeting-name.enabled" withBoolean:false];
|
|
37
|
+
[builder setFeatureFlag:@"meeting-password.enabled" withBoolean:false];
|
|
38
|
+
[builder setFeatureFlag:@"raise-hand.enabled" withBoolean:false];
|
|
39
|
+
[builder setFeatureFlag:@"recording.enabled" withBoolean:false];
|
|
40
|
+
[builder setFeatureFlag:@"server-url-change.enabled" withBoolean:false];
|
|
41
|
+
[builder setFeatureFlag:@"video-share.enabled" withBoolean:false];
|
|
42
|
+
[builder setFeatureFlag:@"help.enabled" withBoolean:false];
|
|
43
|
+
[builder setFeatureFlag:@"lobby-mode.enabled" withBoolean:false];
|
|
44
|
+
[builder setFeatureFlag:@"server-url-change.enabled" withBoolean:false];
|
|
45
|
+
[builder setConfigOverride:@"requireDisplayName" withBoolean:false];
|
|
46
|
+
[builder setConfigOverride:@"disableModeratorIndicator" withBoolean:true];
|
|
47
|
+
}];
|
|
48
|
+
|
|
49
|
+
[jitsiMeetView join: options];
|
|
50
|
+
[self.viewController.view addSubview:jitsiMeetView];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
- (void)destroy:(CDVInvokedUrlCommand *)command {
|
|
55
|
+
if(jitsiMeetView){
|
|
56
|
+
[jitsiMeetView removeFromSuperview];
|
|
57
|
+
jitsiMeetView = nil;
|
|
58
|
+
}
|
|
59
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"DESTROYED"];
|
|
60
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:command.callbackId];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void _onJitsiMeetViewDelegateEvent(NSString *name, NSDictionary *data) {
|
|
64
|
+
NSLog(
|
|
65
|
+
@"[%s:%d] JitsiMeetViewDelegate %@ %@",
|
|
66
|
+
__FILE__, __LINE__, name, data);
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
- (void)conferenceFailed:(NSDictionary *)data {
|
|
71
|
+
_onJitsiMeetViewDelegateEvent(@"CONFERENCE_FAILED", data);
|
|
72
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"CONFERENCE_FAILED"];
|
|
73
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
74
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (void)conferenceJoined:(NSDictionary *)data {
|
|
78
|
+
_onJitsiMeetViewDelegateEvent(@"CONFERENCE_JOINED", data);
|
|
79
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"CONFERENCE_JOINED"];
|
|
80
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
81
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
- (void)conferenceLeft:(NSDictionary *)data {
|
|
85
|
+
_onJitsiMeetViewDelegateEvent(@"CONFERENCE_LEFT", data);
|
|
86
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"CONFERENCE_LEFT"];
|
|
87
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
88
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
- (void)conferenceWillJoin:(NSDictionary *)data {
|
|
93
|
+
_onJitsiMeetViewDelegateEvent(@"CONFERENCE_WILL_JOIN", data);
|
|
94
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"CONFERENCE_WILL_JOIN"];
|
|
95
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
96
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
- (void)conferenceTerminated:(NSDictionary *)data {
|
|
100
|
+
_onJitsiMeetViewDelegateEvent(@"CONFERENCE_TERMINATED", data);
|
|
101
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"CONFERENCE_TERMINATED"];
|
|
102
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
103
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)loadConfigError:(NSDictionary *)data {
|
|
107
|
+
_onJitsiMeetViewDelegateEvent(@"LOAD_CONFIG_ERROR", data);
|
|
108
|
+
plgResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"LOAD_CONFIG_ERROR"];
|
|
109
|
+
[plgResult setKeepCallbackAsBool:YES];
|
|
110
|
+
[self.commandDelegate sendPluginResult:plgResult callbackId:commandBack.callbackId];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//- (void)enterPictureInPicture:(NSDictionary *)data {
|
|
114
|
+
//}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var exec = require('cordova/exec');
|
|
2
|
+
|
|
3
|
+
exports.join = function(serverUrl, room, audioOnly, token, success, error) {
|
|
4
|
+
exec(success, error, "JitsiPlugin", "join", [serverUrl, room, !!audioOnly, token]);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
exports.destroy = function(success, error) {
|
|
8
|
+
exec(success, error, "JitsiPlugin", "destroy", []);
|
|
9
|
+
};
|