capacitor-jitsi-meet 2.1.2 → 2.2.0-beta.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/CHANGELOG.md +13 -1
- package/CapacitorJitsiMeet.podspec +2 -2
- package/README.md +18 -8
- package/android/README.md +8 -0
- package/android/src/main/java/com/capacitor/jitsi/plugin/Jitsi.java +108 -48
- package/android/src/main/java/com/capacitor/jitsi/plugin/JitsiActivity.java +27 -123
- package/dist/esm/definitions.d.ts +6 -0
- package/dist/esm/web.d.ts +6 -0
- package/dist/esm/web.js.map +1 -1
- package/ios/Plugin/Plugin/JitsiMeet.storyboard +10 -11
- package/ios/Plugin/Plugin/JitsiMeetViewController.swift +45 -63
- package/ios/Plugin/Plugin/Plugin.swift +88 -39
- package/ios/Plugin/Podfile +2 -2
- package/ios/README.md +9 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,19 @@ Each version of the capacitor plugin uses a specific Jitsi SDK version. In iOS d
|
|
|
4
4
|
|
|
5
5
|
See Jitsi-meet SDK [changelog](https://github.com/jitsi/jitsi-meet-release-notes/blob/master/CHANGELOG-MOBILE-SDKS.md)
|
|
6
6
|
|
|
7
|
-
# 2.
|
|
7
|
+
# 2.2.0 (2022-02-25)
|
|
8
|
+
|
|
9
|
+
- adds the subject, featureFlags, and configOverrides params
|
|
10
|
+
|
|
11
|
+
# 2.1.3 (2022-02-09)
|
|
12
|
+
|
|
13
|
+
## Breaking Changes
|
|
14
|
+
- adds the following optional parameters with their default values. Those defaulted to false must be manually set to true in order to enable them.
|
|
15
|
+
- recordEnabled (default: false)
|
|
16
|
+
- liveStreamingEnabled (default: auto-detected)
|
|
17
|
+
- screenSharingEnabled (android only, default: false)
|
|
18
|
+
|
|
19
|
+
- fixes liveStreamingEnabled bug in 2.1.2
|
|
8
20
|
|
|
9
21
|
## iOS
|
|
10
22
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
Pod::Spec.new do |s|
|
|
3
3
|
s.name = 'CapacitorJitsiMeet'
|
|
4
|
-
s.version = '2.
|
|
4
|
+
s.version = '2.2.0'
|
|
5
5
|
s.summary = 'This plugin is used to make video calls using Jitsi video platform (https://meet.jit.si) on iOS and Android using Capacitor. Since the current implementation of Ionic/PWA apps on iOS run on top of WKWebView, and as of today (24/01/2019), Apple does not support WebRTC on WKWebView, the only way to work with Jitsi Video on this platform is to build it natively.'
|
|
6
6
|
s.license = 'MIT'
|
|
7
7
|
s.homepage = 'https://github.com/calvinckho/capacitor-jitsi-meet'
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
}
|
|
16
16
|
s.ios.deployment_target = '12.0'
|
|
17
17
|
s.dependency 'Capacitor'
|
|
18
|
-
s.dependency 'JitsiMeetSDK', '4.
|
|
18
|
+
s.dependency 'JitsiMeetSDK', '4.1.0'
|
|
19
19
|
end
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Follow the [official Capacitor doc to upgrade to Capacitor 3](https://capacitorj
|
|
|
56
56
|
See the plugin [changelog](https://github.com/calvinckho/capacitor-jitsi-meet/blob/master/CHANGELOG.md) for plugin versions that are compatible to your local Xcode version.
|
|
57
57
|
|
|
58
58
|
## Embedding in web applications
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
This plugin does not currently support web implementation. We recommend using the Jitsi iFrame API (https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe) for full web implementation.
|
|
61
61
|
|
|
62
62
|
## Usage
|
|
@@ -81,8 +81,9 @@ const result = await Jitsi.joinConference({
|
|
|
81
81
|
// required parameters
|
|
82
82
|
roomName: 'room1', // room identifier for the conference
|
|
83
83
|
url: 'https://meet.jit.si', // endpoint of the Jitsi Meet video bridge
|
|
84
|
+
|
|
84
85
|
// optional parameters
|
|
85
|
-
|
|
86
|
+
subject: string, // name of the video room
|
|
86
87
|
displayName: string, // user's display name
|
|
87
88
|
email: string, // user's email
|
|
88
89
|
avatarURL: string, // user's avatar url
|
|
@@ -90,10 +91,17 @@ const result = await Jitsi.joinConference({
|
|
|
90
91
|
startWithVideoMuted: false, // start with video muted, default: false
|
|
91
92
|
chatEnabled: false, // enable Chat feature, default: true
|
|
92
93
|
inviteEnabled: false, // enable Invitation feature, default: true
|
|
94
|
+
|
|
95
|
+
// advanced settings, optional
|
|
96
|
+
token: string, // jwt authentication token
|
|
97
|
+
featureFlags: { 'call-integration.enabled': true, 'live-streaming.enabled': false }, // see list of featureFlags in the official Jitsi Meet SDK documentation
|
|
98
|
+
configOverrides: { 'p2p.enabled': false }, // see list of config overrides in the official Jitsi Meet SDK documentation
|
|
99
|
+
|
|
100
|
+
// advanced settings to be deprecated in 3.0. Use featureFlags and configOverrides instead
|
|
93
101
|
callIntegrationEnabled: true, // enable call integration (CallKit on iOS, ConnectionService on Android), default: true
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
screenSharingEnabled: false, // enable screen sharing feature, default: false
|
|
102
|
+
liveStreamingEnabled: false, // enable live streaming feature, default: auto-detected
|
|
103
|
+
recordingEnabled: false, // (experimental) enable recording feature, default: false, requires adding Dropbox APP_KEY to Info.plist and AndroidManifest.xml
|
|
104
|
+
screenSharingEnabled: false, // enable screen sharing feature, default: false, iOS requires manually adding the Broadcast Upload Extension
|
|
97
105
|
});
|
|
98
106
|
|
|
99
107
|
window.addEventListener('onConferenceJoined', () => {
|
|
@@ -103,8 +111,6 @@ window.addEventListener('onConferenceLeft', () => {
|
|
|
103
111
|
// do things here
|
|
104
112
|
});
|
|
105
113
|
|
|
106
|
-
await Jitsi.leaveConference();
|
|
107
|
-
|
|
108
114
|
```
|
|
109
115
|
|
|
110
116
|
3. Build the project
|
|
@@ -115,6 +121,10 @@ $ npm run build
|
|
|
115
121
|
|
|
116
122
|
4. Follow the deployment instructions for [Android](android/README.md) and [iOS](ios/README.md).
|
|
117
123
|
|
|
124
|
+
## Official Jitsi-Meet SDK Documentation
|
|
125
|
+
|
|
126
|
+
This plugin uses the Jitsi Meet SDK. See the [Jitsi Meet SDK documentation](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-mobile), and the lists of [feature flags](https://jitsi.github.io/handbook/docs/dev-guide/mobile-feature-flags) and [config overrides](https://github.com/jitsi/jitsi-meet/blob/e2731ce73e9221408d0f4d985affc91eb11fc214/config.js).
|
|
127
|
+
|
|
118
128
|
## Sample React App for Android
|
|
119
129
|
|
|
120
130
|
You can see a [React Demo App](https://github.com/calvinckho/react-capacitor-jitsi-meet-sample) which runs the Jitsi meeting on the Android device
|
|
@@ -125,4 +135,4 @@ I appreciate those who use this plugin in their production apps and are funding
|
|
|
125
135
|
|
|
126
136
|
## Acknowledgements
|
|
127
137
|
|
|
128
|
-
This plugin
|
|
138
|
+
This plugin enables web and mobile apps to implement video conferencing feature for free. The Jitsi Meet mobile SDKs are actively maintained by Jitsi. Video bridges for multi-user video conferencing is powered by [Jitsi Meet](https://meet.jit.si), or you can run [your own video bridge](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-start).
|
package/android/README.md
CHANGED
|
@@ -95,6 +95,14 @@ ionic capacitor open android
|
|
|
95
95
|
|
|
96
96
|
f. run `npx cap sync && npx cap open android`
|
|
97
97
|
|
|
98
|
+
### Dropbox Integration
|
|
99
|
+
|
|
100
|
+
See [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk#dropbox-integration).
|
|
101
|
+
|
|
102
|
+
### Screen Sharing Integration
|
|
103
|
+
|
|
104
|
+
Some users experienced issues on Android. Report your issues [here](https://github.com/calvinckho/capacitor-jitsi-meet/issues/35).
|
|
105
|
+
|
|
98
106
|
### Android SDK Developer Guide
|
|
99
107
|
|
|
100
108
|
Consult the official Jitsi Android SDK [documentation](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk).
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
package com.capacitor.jitsi.plugin;
|
|
2
2
|
|
|
3
|
+
import java.net.URL;
|
|
4
|
+
import java.net.MalformedURLException;
|
|
5
|
+
import java.util.*;
|
|
6
|
+
|
|
3
7
|
import com.getcapacitor.JSObject;
|
|
4
8
|
import com.getcapacitor.Plugin;
|
|
5
9
|
import com.getcapacitor.PluginCall;
|
|
@@ -10,12 +14,15 @@ import com.getcapacitor.annotation.Permission;
|
|
|
10
14
|
import android.content.IntentFilter;
|
|
11
15
|
import android.content.Intent;
|
|
12
16
|
import android.Manifest;
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
import org.jitsi.meet.sdk.BroadcastIntentHelper;
|
|
17
|
+
import android.os.Build;
|
|
16
18
|
|
|
19
|
+
import androidx.annotation.RequiresApi;
|
|
20
|
+
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
17
21
|
import timber.log.Timber;
|
|
18
22
|
|
|
23
|
+
import org.jitsi.meet.sdk.*;
|
|
24
|
+
import org.json.JSONException;
|
|
25
|
+
|
|
19
26
|
@CapacitorPlugin(
|
|
20
27
|
name= "Jitsi",
|
|
21
28
|
permissions={
|
|
@@ -26,24 +33,28 @@ import timber.log.Timber;
|
|
|
26
33
|
public class Jitsi extends Plugin {
|
|
27
34
|
private static final String TAG = "CapacitorJitsiMeet";
|
|
28
35
|
private JitsiBroadcastReceiver receiver;
|
|
36
|
+
private JitsiMeetUserInfo userInfo;
|
|
29
37
|
|
|
38
|
+
@RequiresApi(api = Build.VERSION_CODES.N)
|
|
30
39
|
@PluginMethod()
|
|
31
|
-
public void joinConference(PluginCall call) {
|
|
32
|
-
|
|
40
|
+
public void joinConference(PluginCall call) throws JSONException {
|
|
41
|
+
URL url = null;
|
|
42
|
+
try {
|
|
43
|
+
url = new URL(call.getString("url"));
|
|
44
|
+
} catch (MalformedURLException e) {
|
|
45
|
+
call.reject("Must provide an url");
|
|
46
|
+
e.printStackTrace();
|
|
47
|
+
}
|
|
33
48
|
String roomName = call.getString("roomName");
|
|
34
49
|
String token = call.getString("token");
|
|
35
50
|
String displayName = call.getString("displayName");
|
|
51
|
+
String subject = call.getString("subject", " ");
|
|
36
52
|
String email = call.getString("email");
|
|
37
53
|
String avatarURL = call.getString("avatarURL");
|
|
38
54
|
Boolean startWithAudioMuted = call.getBoolean("startWithAudioMuted");
|
|
39
55
|
Boolean startWithVideoMuted = call.getBoolean("startWithVideoMuted");
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Boolean callIntegrationEnabled = call.getBoolean("callIntegrationEnabled");
|
|
43
|
-
Boolean recordingEnabled = call.getBoolean("recordingEnabled");
|
|
44
|
-
Boolean liveStreamingEnabled = call.getBoolean("liveStreamingEnabled");
|
|
45
|
-
Boolean screenSharingEnabled = call.getBoolean("screenSharingEnabled");
|
|
46
|
-
|
|
56
|
+
JSObject featureFlags = call.getObject("featureFlags", new JSObject());
|
|
57
|
+
JSObject configOverrides = call.getObject("configOverrides", new JSObject());
|
|
47
58
|
receiver = new JitsiBroadcastReceiver();
|
|
48
59
|
receiver.setModule(this);
|
|
49
60
|
IntentFilter filter = new IntentFilter();
|
|
@@ -52,56 +63,104 @@ public class Jitsi extends Plugin {
|
|
|
52
63
|
filter.addAction("onConferenceLeft"); // intentionally uses the obsolete onConferenceLeft in order to be consistent with iOS deployment and broadcast to JS listeners
|
|
53
64
|
getContext().registerReceiver(receiver, filter);
|
|
54
65
|
|
|
55
|
-
if(url == null) {
|
|
56
|
-
call.reject("Must provide an url");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
66
|
if(roomName == null) {
|
|
60
67
|
call.reject("Must provide an conference room name");
|
|
61
68
|
return;
|
|
62
69
|
}
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
|
|
71
|
+
// assign user info
|
|
72
|
+
userInfo = new JitsiMeetUserInfo();
|
|
73
|
+
if (displayName != null) {
|
|
74
|
+
userInfo.setDisplayName(displayName);
|
|
75
|
+
}
|
|
76
|
+
if (email != null) {
|
|
77
|
+
userInfo.setEmail(email);
|
|
78
|
+
}
|
|
79
|
+
if (avatarURL != null) {
|
|
80
|
+
// try to assign avatar URL
|
|
81
|
+
try {
|
|
82
|
+
userInfo.setAvatar(new URL(avatarURL));
|
|
83
|
+
} catch (MalformedURLException e) {
|
|
84
|
+
e.printStackTrace();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//Timber.tag(TAG).d("display url: " + call.getString("url"));
|
|
88
|
+
|
|
89
|
+
JitsiMeetConferenceOptions.Builder builder = new JitsiMeetConferenceOptions.Builder()
|
|
90
|
+
.setServerURL(url)
|
|
91
|
+
.setRoom(roomName)
|
|
92
|
+
.setToken(token)
|
|
93
|
+
.setSubject(subject)
|
|
94
|
+
.setUserInfo(userInfo);
|
|
95
|
+
if(startWithAudioMuted != null){
|
|
96
|
+
builder.setAudioMuted(startWithAudioMuted);
|
|
97
|
+
}
|
|
98
|
+
if(startWithVideoMuted != null){
|
|
99
|
+
builder.setVideoMuted(startWithVideoMuted);
|
|
65
100
|
}
|
|
66
|
-
|
|
67
|
-
|
|
101
|
+
|
|
102
|
+
// default PiP is off, but allowing user to overrides it by providing the featureFlag below
|
|
103
|
+
builder.setFeatureFlag("pip.enabled", false);
|
|
104
|
+
|
|
105
|
+
// general settings can be overridden by subsequent featureFlags settings
|
|
106
|
+
if(call.getBoolean("chatEnabled") != null){
|
|
107
|
+
builder.setFeatureFlag("chat.enabled", call.getBoolean("chatEnabled"));
|
|
68
108
|
}
|
|
69
|
-
if(
|
|
70
|
-
|
|
109
|
+
if(call.getBoolean("inviteEnabled") != null){
|
|
110
|
+
builder.setFeatureFlag("invite.enabled", call.getBoolean("inviteEnabled"));
|
|
71
111
|
}
|
|
72
|
-
if(
|
|
73
|
-
|
|
112
|
+
if(call.getBoolean("callIntegrationEnabled") != null){
|
|
113
|
+
builder.setFeatureFlag("call-integration.enabled", call.getBoolean("callIntegrationEnabled"));
|
|
74
114
|
}
|
|
75
|
-
if(
|
|
76
|
-
|
|
115
|
+
if(call.getBoolean("recordingEnabled") != null){
|
|
116
|
+
builder.setFeatureFlag("recording.enabled", call.getBoolean("recordingEnabled"));
|
|
77
117
|
}
|
|
78
|
-
if(
|
|
79
|
-
|
|
118
|
+
if(call.getBoolean("liveStreamingEnabled") != null){
|
|
119
|
+
builder.setFeatureFlag("live-streaming.enabled", call.getBoolean("liveStreamingEnabled"));
|
|
80
120
|
}
|
|
81
|
-
if(screenSharingEnabled
|
|
82
|
-
screenSharingEnabled
|
|
121
|
+
if(call.getBoolean("screenSharingEnabled") != null){
|
|
122
|
+
builder.setFeatureFlag("android.screensharing.enabled", call.getBoolean("screenSharingEnabled"));
|
|
83
123
|
}
|
|
84
|
-
Timber.tag(TAG).v("display url: %s", url);
|
|
85
124
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
125
|
+
// setfeatureFlag() provides finer control, and will override some of the setFeatureFlag methods above
|
|
126
|
+
Iterator<String> keys = featureFlags.keys();
|
|
127
|
+
while(keys.hasNext()) {
|
|
128
|
+
String key = keys.next();
|
|
129
|
+
// Can only be bool, int or string according to
|
|
130
|
+
// the overloads of setFeatureFlag.
|
|
131
|
+
|
|
132
|
+
if (featureFlags.get(key) != null) {
|
|
133
|
+
if (featureFlags.get(key) instanceof Boolean) {
|
|
134
|
+
builder.setFeatureFlag(key, (Boolean) featureFlags.get(key));
|
|
135
|
+
} else if (featureFlags.get(key) instanceof Integer) {
|
|
136
|
+
builder.setFeatureFlag(key, (Integer) featureFlags.get(key));
|
|
137
|
+
} else if (featureFlags.get(key) instanceof String) {
|
|
138
|
+
builder.setFeatureFlag(key, (String) featureFlags.get(key));
|
|
139
|
+
} else {
|
|
140
|
+
builder.setFeatureFlag(key, featureFlags.get(key).toString());
|
|
141
|
+
}
|
|
142
|
+
}
|
|
101
143
|
}
|
|
102
|
-
intent.putExtra("screenSharingEnabled", screenSharingEnabled);
|
|
103
144
|
|
|
104
|
-
|
|
145
|
+
keys = configOverrides.keys();
|
|
146
|
+
while(keys.hasNext()) {
|
|
147
|
+
String key = keys.next();
|
|
148
|
+
// Can only be bool, int or string according to
|
|
149
|
+
// the overloads of setFeatureFlag.
|
|
150
|
+
if (configOverrides.get(key) != null) {
|
|
151
|
+
if (configOverrides.get(key) instanceof Boolean) {
|
|
152
|
+
builder.setConfigOverride(key, (Boolean) configOverrides.get(key));
|
|
153
|
+
} else if (configOverrides.get(key) instanceof Integer) {
|
|
154
|
+
builder.setConfigOverride(key, (Integer) configOverrides.get(key));
|
|
155
|
+
} else if (configOverrides.get(key) instanceof String[]) {
|
|
156
|
+
builder.setConfigOverride(key, (String[]) configOverrides.get(key));
|
|
157
|
+
} else {
|
|
158
|
+
builder.setConfigOverride(key, configOverrides.get(key).toString());
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
JitsiMeetConferenceOptions options = builder.build();
|
|
163
|
+
JitsiActivity.launch(getActivity(), options);
|
|
105
164
|
|
|
106
165
|
JSObject ret = new JSObject();
|
|
107
166
|
ret.put("success", true);
|
|
@@ -120,6 +179,7 @@ public class Jitsi extends Plugin {
|
|
|
120
179
|
|
|
121
180
|
public void onEventReceived(String eventName) {
|
|
122
181
|
bridge.triggerWindowJSEvent(eventName);
|
|
182
|
+
Timber.tag(TAG).d(eventName);
|
|
123
183
|
if(eventName.equals("onConferenceLeft")) {
|
|
124
184
|
if (receiver != null) {
|
|
125
185
|
getContext().unregisterReceiver(receiver);
|
|
@@ -1,122 +1,41 @@
|
|
|
1
1
|
package com.capacitor.jitsi.plugin;
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import java.net.URL;
|
|
5
|
-
import java.util.Map;
|
|
6
|
-
|
|
3
|
+
import android.app.Activity;
|
|
7
4
|
import android.content.BroadcastReceiver;
|
|
8
5
|
import android.content.Context;
|
|
9
6
|
import android.content.Intent;
|
|
10
7
|
import android.content.IntentFilter;
|
|
8
|
+
import android.os.Build;
|
|
11
9
|
import android.os.Bundle;
|
|
12
10
|
|
|
11
|
+
import androidx.annotation.RequiresApi;
|
|
13
12
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
13
|
+
import timber.log.Timber;
|
|
14
14
|
|
|
15
15
|
import com.facebook.react.bridge.UiThreadUtil;
|
|
16
16
|
|
|
17
|
-
import org.jitsi.meet.sdk
|
|
18
|
-
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
|
19
|
-
import org.jitsi.meet.sdk.JitsiMeetViewListener;
|
|
20
|
-
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
|
|
21
|
-
import org.jitsi.meet.sdk.JitsiMeetUserInfo;
|
|
22
|
-
import org.jitsi.meet.sdk.BroadcastEvent;
|
|
23
|
-
|
|
24
|
-
import timber.log.Timber;
|
|
17
|
+
import org.jitsi.meet.sdk.*;
|
|
25
18
|
|
|
26
19
|
public class JitsiActivity extends JitsiMeetActivity {
|
|
27
|
-
private JitsiMeetView view;
|
|
28
|
-
private JitsiMeetUserInfo userInfo;
|
|
29
20
|
private BroadcastReceiver broadcastReceiver;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@Override
|
|
43
|
-
protected void onCreate(Bundle savedInstanceState) {
|
|
44
|
-
super.onCreate(savedInstanceState);
|
|
45
|
-
|
|
46
|
-
view = new JitsiMeetView(this);
|
|
47
|
-
Timber.d("entering");
|
|
48
|
-
|
|
49
|
-
URL serverURL;
|
|
50
|
-
try {
|
|
51
|
-
serverURL = new URL(getIntent().getStringExtra("url"));
|
|
52
|
-
} catch (MalformedURLException e) {
|
|
53
|
-
e.printStackTrace();
|
|
54
|
-
throw new RuntimeException("Invalid server URL!");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
String roomName = getIntent().getStringExtra("roomName");
|
|
58
|
-
String token = getIntent().getStringExtra("token");
|
|
59
|
-
Boolean startWithAudioMuted = getIntent().getBooleanExtra("startWithAudioMuted", false);
|
|
60
|
-
Boolean startWithVideoMuted = getIntent().getBooleanExtra("startWithVideoMuted", false);
|
|
61
|
-
Boolean chatEnabled = getIntent().getBooleanExtra("chatEnabled", false);
|
|
62
|
-
Boolean inviteEnabled = getIntent().getBooleanExtra("inviteEnabled", false);
|
|
63
|
-
Boolean callIntegrationEnabled = getIntent().getBooleanExtra("callIntegrationEnabled", false);
|
|
64
|
-
Boolean recordingEnabled = getIntent().getBooleanExtra("recordingEnabled", false);
|
|
65
|
-
Boolean liveStreamingEnabled = getIntent().getBooleanExtra("liveStreamingEnabled", false);
|
|
66
|
-
Boolean screenSharingEnabled = getIntent().getBooleanExtra("screenSharingEnabled", false);
|
|
67
|
-
|
|
68
|
-
String displayName = getIntent().getStringExtra("displayName");
|
|
69
|
-
String email = getIntent().getStringExtra("email");
|
|
70
|
-
String avatarURL = getIntent().getStringExtra("avatarURL");
|
|
71
|
-
|
|
72
|
-
// assign user info
|
|
73
|
-
userInfo = new JitsiMeetUserInfo();
|
|
74
|
-
if (displayName != null) {
|
|
75
|
-
userInfo.setDisplayName(displayName);
|
|
21
|
+
private static final String TAG = "CapacitorJitsiMeet";
|
|
22
|
+
private static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
|
|
23
|
+
private static JitsiMeetConferenceOptions session_options;
|
|
24
|
+
|
|
25
|
+
// this overrides the launch class and runs the extended JitsiActivity class instead
|
|
26
|
+
public static void launch(Context context, JitsiMeetConferenceOptions options) {
|
|
27
|
+
session_options = options;
|
|
28
|
+
Intent intent = new Intent(context, JitsiActivity.class);
|
|
29
|
+
intent.setAction(ACTION_JITSI_MEET_CONFERENCE);
|
|
30
|
+
intent.putExtra("JitsiMeetConferenceOptions", options);
|
|
31
|
+
if (!(context instanceof Activity)) {
|
|
32
|
+
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
76
33
|
}
|
|
77
|
-
|
|
78
|
-
userInfo.setEmail(email);
|
|
79
|
-
}
|
|
80
|
-
if (avatarURL != null) {
|
|
81
|
-
// try to assign avatar URL
|
|
82
|
-
try {
|
|
83
|
-
userInfo.setAvatar(new URL(getIntent().getStringExtra("avatarURL")));
|
|
84
|
-
} catch (MalformedURLException e) {
|
|
85
|
-
e.printStackTrace();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
JitsiMeetConferenceOptions options = new JitsiMeetConferenceOptions.Builder()
|
|
90
|
-
.setServerURL(serverURL)
|
|
91
|
-
.setRoom(roomName)
|
|
92
|
-
.setToken(token)
|
|
93
|
-
.setSubject(" ")
|
|
94
|
-
.setAudioMuted(startWithAudioMuted)
|
|
95
|
-
.setVideoMuted(startWithVideoMuted)
|
|
96
|
-
.setFeatureFlag("chat.enabled", chatEnabled)
|
|
97
|
-
.setFeatureFlag("invite.enabled", inviteEnabled)
|
|
98
|
-
.setFeatureFlag("call-integration.enabled", callIntegrationEnabled)
|
|
99
|
-
.setFeatureFlag("recording.enabled", recordingEnabled)
|
|
100
|
-
.setFeatureFlag("live-streaming.enabled", liveStreamingEnabled)
|
|
101
|
-
.setFeatureFlag("android.screensharing.enabled", screenSharingEnabled)
|
|
102
|
-
//.setAudioOnly(false)
|
|
103
|
-
.setUserInfo(userInfo)
|
|
104
|
-
.build();
|
|
105
|
-
view.join(options);
|
|
106
|
-
setContentView(view);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private void registerForBroadcastMessages() {
|
|
110
|
-
IntentFilter intentFilter = new IntentFilter();
|
|
111
|
-
|
|
112
|
-
for (BroadcastEvent.Type type : BroadcastEvent.Type.values()) {
|
|
113
|
-
intentFilter.addAction(type.getAction());
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
|
|
34
|
+
context.startActivity(intent);
|
|
117
35
|
}
|
|
118
36
|
|
|
119
37
|
private void onBroadcastReceived(Intent intent) {
|
|
38
|
+
JitsiMeetView view = getJitsiView();
|
|
120
39
|
if (intent != null) {
|
|
121
40
|
BroadcastEvent event = new BroadcastEvent(intent);
|
|
122
41
|
|
|
@@ -128,8 +47,6 @@ public class JitsiActivity extends JitsiMeetActivity {
|
|
|
128
47
|
on("onConferenceWillJoin");
|
|
129
48
|
break;
|
|
130
49
|
case READY_TO_CLOSE:
|
|
131
|
-
view.dispose();
|
|
132
|
-
view = null;
|
|
133
50
|
finish();
|
|
134
51
|
on("onConferenceLeft"); // intentionally uses the obsolete onConferenceLeft in order to be consistent with iOS deployment and broadcast to JS listeners
|
|
135
52
|
break;
|
|
@@ -145,45 +62,32 @@ public class JitsiActivity extends JitsiMeetActivity {
|
|
|
145
62
|
|
|
146
63
|
private void on(String name) {
|
|
147
64
|
UiThreadUtil.assertOnUiThread();
|
|
148
|
-
Timber.d(JitsiMeetView.class.getSimpleName() + ": " + name);
|
|
65
|
+
Timber.tag(TAG).d(JitsiMeetView.class.getSimpleName() + ": " + name);
|
|
149
66
|
|
|
150
67
|
Intent intent = new Intent(name);
|
|
151
68
|
intent.putExtra("eventName", name);
|
|
152
69
|
sendBroadcast(intent);
|
|
153
70
|
}
|
|
154
71
|
|
|
155
|
-
@Override
|
|
156
|
-
public void onDestroy() {
|
|
157
|
-
if (broadcastReceiver != null) {
|
|
158
|
-
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
|
|
159
|
-
broadcastReceiver = null;
|
|
160
|
-
}
|
|
161
|
-
super.onDestroy();
|
|
162
|
-
}
|
|
163
|
-
|
|
164
72
|
// The following handler is triggered when the app transitions from the background to the foreground.
|
|
165
|
-
// For PIP users, uncomment the code to try PIP mode. Also change android:supportsPictureInPicture="true" in AndroidManifest.xml
|
|
166
73
|
// When PIP is enabled, it can detect when the PIP window is closed by caller so it can terminate the call correctly.
|
|
167
|
-
|
|
168
|
-
// Therefore the PIP mode is disabled in the published plugin until this issue is resolved
|
|
169
|
-
/*@Override
|
|
74
|
+
@Override
|
|
170
75
|
public void onStop() {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
view = null;
|
|
76
|
+
JitsiMeetView view = getJitsiView();
|
|
77
|
+
Timber.tag(TAG).d("onStop %s", session_options.getFeatureFlags().getBoolean("pip.enabled"));
|
|
78
|
+
if (session_options.getFeatureFlags().getBoolean("pip.enabled")) { //TODO: also check the CapacitorJitsiMeet's AndroidManifest.xml file and ensure android:supportsPictureInPicture="true"
|
|
175
79
|
finish();
|
|
80
|
+
on("onConferenceLeft"); // intentionally uses the obsolete onConferenceLeft in order to be consistent with iOS deployment and broadcast to JS listeners
|
|
176
81
|
}
|
|
177
|
-
on("onConferenceLeft"); // intentionally uses the obsolete onConferenceLeft in order to be consistent with iOS deployment and broadcast to JS listeners
|
|
178
82
|
super.onStop();
|
|
179
|
-
}
|
|
83
|
+
}
|
|
180
84
|
|
|
181
85
|
// for logging entering and leaving PIP only
|
|
182
86
|
@Override
|
|
183
87
|
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
|
|
184
88
|
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
|
|
185
89
|
|
|
186
|
-
Timber.d("Is in picture-in-picture mode: " + isInPictureInPictureMode);
|
|
90
|
+
Timber.tag(TAG).d("Is in picture-in-picture mode: " + isInPictureInPictureMode);
|
|
187
91
|
}
|
|
188
92
|
|
|
189
93
|
private static final String ADD_PEOPLE_CONTROLLER_QUERY = null;
|
|
@@ -5,6 +5,7 @@ export interface JitsiPlugin {
|
|
|
5
5
|
token?: string;
|
|
6
6
|
channelLastN?: string;
|
|
7
7
|
displayName?: string;
|
|
8
|
+
subject?: string;
|
|
8
9
|
email?: string;
|
|
9
10
|
avatarURL?: string;
|
|
10
11
|
startWithAudioMuted?: boolean;
|
|
@@ -15,12 +16,15 @@ export interface JitsiPlugin {
|
|
|
15
16
|
recordingEnabled?: boolean;
|
|
16
17
|
liveStreamingEnabled?: boolean;
|
|
17
18
|
screenSharingEnabled?: boolean;
|
|
19
|
+
featureFlags?: any;
|
|
20
|
+
configOverrides?: any;
|
|
18
21
|
}): Promise<{
|
|
19
22
|
roomName: string;
|
|
20
23
|
url: string;
|
|
21
24
|
token?: string;
|
|
22
25
|
channelLastN?: string;
|
|
23
26
|
displayName?: string;
|
|
27
|
+
subject?: string;
|
|
24
28
|
email?: string;
|
|
25
29
|
avatarURL?: string;
|
|
26
30
|
startWithAudioMuted?: boolean;
|
|
@@ -31,6 +35,8 @@ export interface JitsiPlugin {
|
|
|
31
35
|
recordingEnabled?: boolean;
|
|
32
36
|
liveStreamingEnabled?: boolean;
|
|
33
37
|
screenSharingEnabled?: boolean;
|
|
38
|
+
featureFlags?: any;
|
|
39
|
+
configOverrides?: any;
|
|
34
40
|
}>;
|
|
35
41
|
leaveConference(options: {}): Promise<{}>;
|
|
36
42
|
}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare class JitsiWeb extends WebPlugin implements JitsiPlugin {
|
|
|
7
7
|
token?: string;
|
|
8
8
|
channelLastN?: string;
|
|
9
9
|
displayName?: string;
|
|
10
|
+
subject?: string;
|
|
10
11
|
email?: string;
|
|
11
12
|
avatarURL?: string;
|
|
12
13
|
startWithAudioMuted?: boolean;
|
|
@@ -17,12 +18,15 @@ export declare class JitsiWeb extends WebPlugin implements JitsiPlugin {
|
|
|
17
18
|
recordingEnabled?: boolean;
|
|
18
19
|
liveStreamingEnabled?: boolean;
|
|
19
20
|
screenSharingEnabled?: boolean;
|
|
21
|
+
featureFlags?: Map<string, any>;
|
|
22
|
+
configOverrides?: Map<string, any>;
|
|
20
23
|
}): Promise<{
|
|
21
24
|
roomName: string;
|
|
22
25
|
url: string;
|
|
23
26
|
token?: string;
|
|
24
27
|
channelLastN?: string;
|
|
25
28
|
displayName?: string;
|
|
29
|
+
subject?: string;
|
|
26
30
|
email?: string;
|
|
27
31
|
avatarURL?: string;
|
|
28
32
|
startWithAudioMuted?: boolean;
|
|
@@ -33,6 +37,8 @@ export declare class JitsiWeb extends WebPlugin implements JitsiPlugin {
|
|
|
33
37
|
recordingEnabled?: boolean;
|
|
34
38
|
liveStreamingEnabled?: boolean;
|
|
35
39
|
screenSharingEnabled?: boolean;
|
|
40
|
+
featureFlags?: Map<string, any>;
|
|
41
|
+
configOverrides?: Map<string, any>;
|
|
36
42
|
}>;
|
|
37
43
|
leaveConference(options: {}): Promise<{}>;
|
|
38
44
|
}
|
package/dist/esm/web.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,OAAO,QAAS,SAAQ,SAAS;IAErC,aAAa;IACL,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,MAAM,OAAO,QAAS,SAAQ,SAAS;IAErC,aAAa;IACL,cAAc,CAAC,OAmBtB;;YAoBG,MAAM,IAAI,CAAC,WAAW,CAAC,kGAAkG,CAAC,CAAC;QAC/H,CAAC;KAAA;IAAA,CAAC;IACA,aAAa;IACT,eAAe,CAAC,OAAW;;YAC7B,MAAM,IAAI,CAAC,WAAW,CAAC,kGAAkG,CAAC,CAAC;QAC/H,CAAC;KAAA;IAAA,CAAC;CACH;AAED,MAAM,KAAK,GAAG,IAAI,QAAQ,EAAE,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="
|
|
3
|
-
<device id="
|
|
2
|
+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
|
3
|
+
<device id="retina5_9" orientation="portrait" appearance="light"/>
|
|
4
4
|
<dependencies>
|
|
5
5
|
<deployment identifier="iOS"/>
|
|
6
|
-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="
|
|
6
|
+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
|
|
7
|
+
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
7
8
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
8
9
|
</dependencies>
|
|
9
10
|
<scenes>
|
|
10
11
|
<!--Jitsi Meet View Controller-->
|
|
11
12
|
<scene sceneID="tne-QT-ifu">
|
|
12
13
|
<objects>
|
|
13
|
-
<viewController storyboardIdentifier="jitsiMeetStoryBoardID" modalPresentationStyle="
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
<viewControllerLayoutGuide type="bottom" id="qI8-KV-6mq"/>
|
|
17
|
-
</layoutGuides>
|
|
18
|
-
<view key="view" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="8bC-Xf-vdC" customClass="JitsiMeetView">
|
|
19
|
-
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
|
14
|
+
<viewController storyboardIdentifier="jitsiMeetStoryBoardID" modalTransitionStyle="crossDissolve" modalPresentationStyle="overFullScreen" useStoryboardIdentifierAsRestorationIdentifier="YES" id="BYZ-38-t0r" customClass="JitsiMeetViewController" customModule="CapacitorJitsiMeet" sceneMemberID="viewController">
|
|
15
|
+
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
|
16
|
+
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
|
|
20
17
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
21
|
-
<
|
|
18
|
+
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
|
19
|
+
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
|
20
|
+
<gestureRecognizers/>
|
|
22
21
|
</view>
|
|
23
22
|
</viewController>
|
|
24
23
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
|
@@ -8,81 +8,60 @@
|
|
|
8
8
|
import Foundation
|
|
9
9
|
import UIKit
|
|
10
10
|
import JitsiMeetSDK
|
|
11
|
+
import WebKit
|
|
11
12
|
|
|
12
|
-
public class JitsiMeetViewController: UIViewController {
|
|
13
|
-
|
|
14
|
-
var jitsiMeetView:
|
|
15
|
-
var
|
|
16
|
-
var roomName: String = ""
|
|
17
|
-
var token: String? = nil
|
|
18
|
-
var startWithAudioMuted: Bool = false
|
|
19
|
-
var startWithVideoMuted: Bool = false
|
|
20
|
-
var chatEnabled: Bool = true
|
|
21
|
-
var inviteEnabled: Bool = true
|
|
22
|
-
var callIntegrationEnabled: Bool = true
|
|
23
|
-
var screenSharingEnabled: Bool = false
|
|
24
|
-
var recordingEnabled: Bool = false
|
|
25
|
-
var liveStreamingEnabled: Bool = false
|
|
26
|
-
var email: String? = nil
|
|
27
|
-
var displayName: String? = nil
|
|
28
|
-
var avatarUrl: String? = nil
|
|
29
|
-
let userLocale = NSLocale.current as NSLocale
|
|
13
|
+
public class JitsiMeetViewController: UIViewController, UIGestureRecognizerDelegate {
|
|
14
|
+
|
|
15
|
+
fileprivate var jitsiMeetView: UIView?
|
|
16
|
+
var options: JitsiMeetConferenceOptions? = nil
|
|
30
17
|
weak var delegate: JitsiMeetViewControllerDelegate?
|
|
18
|
+
fileprivate var pipViewCoordinator: PiPViewCoordinator?
|
|
19
|
+
|
|
20
|
+
var webView: WKWebView? = nil;
|
|
31
21
|
|
|
32
22
|
public override func viewDidLoad() {
|
|
33
23
|
super.viewDidLoad()
|
|
34
24
|
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::viewDidLoad");
|
|
25
|
+
openJitsiMeet();
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
public override func
|
|
38
|
-
super.
|
|
39
|
-
|
|
40
|
-
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::viewDidAppear");
|
|
41
|
-
|
|
42
|
-
jitsiMeetView = view as? JitsiMeetView;
|
|
43
|
-
jitsiMeetView?.delegate = self
|
|
44
|
-
|
|
45
|
-
if userLocale.countryCode?.contains("CN") ?? false ||
|
|
46
|
-
userLocale.countryCode?.contains("CHN") ?? false ||
|
|
47
|
-
userLocale.countryCode?.contains("MO") ?? false ||
|
|
48
|
-
userLocale.countryCode?.contains("HK") ?? false {
|
|
49
|
-
print("currentLocale is China so we cannot use CallKit.")
|
|
50
|
-
callIntegrationEnabled = false
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let userInfo = JitsiMeetUserInfo()
|
|
54
|
-
userInfo.displayName = self.displayName
|
|
55
|
-
userInfo.email = self.email
|
|
56
|
-
userInfo.avatar = URL(string: self.avatarUrl ?? "")
|
|
57
|
-
|
|
58
|
-
let options = JitsiMeetConferenceOptions.fromBuilder({ builder in
|
|
59
|
-
builder.serverURL = URL(string: self.url)
|
|
60
|
-
builder.room = self.roomName
|
|
61
|
-
builder.token = self.token
|
|
62
|
-
builder.setAudioMuted(self.startWithAudioMuted);
|
|
63
|
-
builder.setVideoMuted(self.startWithVideoMuted);
|
|
64
|
-
builder.setFeatureFlag("meeting-name.enabled", withBoolean: false)
|
|
65
|
-
builder.setFeatureFlag("chat.enabled", withBoolean: self.chatEnabled)
|
|
66
|
-
builder.setFeatureFlag("invite.enabled", withBoolean: self.inviteEnabled)
|
|
67
|
-
builder.setFeatureFlag("call-integration.enabled", withBoolean: self.callIntegrationEnabled)
|
|
68
|
-
builder.setFeatureFlag("ios.screensharing.enabled", withBoolean: self.screenSharingEnabled)
|
|
69
|
-
builder.setFeatureFlag("ios.recording.enabled", withBoolean: self.recordingEnabled)
|
|
70
|
-
builder.setFeatureFlag("live-streaming.enabled", withBoolean: self.liveStreamingEnabled)
|
|
71
|
-
|
|
72
|
-
builder.userInfo = userInfo
|
|
73
|
-
})
|
|
74
|
-
jitsiMeetView.join(options)
|
|
28
|
+
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
|
29
|
+
super.viewWillTransition(to: size, with: coordinator)
|
|
30
|
+
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::viewWillTransition");
|
|
75
31
|
}
|
|
76
32
|
|
|
77
|
-
|
|
78
|
-
|
|
33
|
+
func openJitsiMeet() {
|
|
34
|
+
cleanUp()
|
|
79
35
|
|
|
80
|
-
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::
|
|
36
|
+
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::openJitsiMeet");
|
|
81
37
|
|
|
82
|
-
|
|
83
|
-
jitsiMeetView
|
|
84
|
-
jitsiMeetView.
|
|
38
|
+
// create and configure the absorbPointerView and jitsimeet view
|
|
39
|
+
let jitsiMeetView = JitsiMeetView()
|
|
40
|
+
jitsiMeetView.delegate = self
|
|
41
|
+
self.jitsiMeetView = jitsiMeetView
|
|
42
|
+
jitsiMeetView.join(options)
|
|
43
|
+
|
|
44
|
+
// Enable jitsimeet view to be a view that can be displayed
|
|
45
|
+
// on top of all the things, and let the coordinator to manage
|
|
46
|
+
// the view state and interactions
|
|
47
|
+
pipViewCoordinator = PiPViewCoordinator(withView: jitsiMeetView)
|
|
48
|
+
pipViewCoordinator?.configureAsStickyView(withParentView: view)
|
|
85
49
|
|
|
50
|
+
// animate in
|
|
51
|
+
jitsiMeetView.alpha = 1
|
|
52
|
+
pipViewCoordinator?.show()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public override func viewDidDisappear(_ animated: Bool) {
|
|
56
|
+
super.viewDidDisappear(animated)
|
|
57
|
+
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::viewDidDisappear");
|
|
58
|
+
cleanUp();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fileprivate func cleanUp() {
|
|
62
|
+
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::cleanUp");
|
|
63
|
+
jitsiMeetView?.removeFromSuperview()
|
|
64
|
+
jitsiMeetView = nil
|
|
86
65
|
}
|
|
87
66
|
}
|
|
88
67
|
|
|
@@ -94,14 +73,17 @@ protocol JitsiMeetViewControllerDelegate: AnyObject {
|
|
|
94
73
|
|
|
95
74
|
// MARK: JitsiMeetViewDelegate
|
|
96
75
|
extension JitsiMeetViewController: JitsiMeetViewDelegate {
|
|
76
|
+
|
|
97
77
|
@objc public func conferenceJoined(_ data: [AnyHashable : Any]!) {
|
|
98
78
|
delegate?.onConferenceJoined()
|
|
99
|
-
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::conference joined.
|
|
79
|
+
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::conference joined.");
|
|
100
80
|
}
|
|
101
81
|
|
|
102
82
|
@objc public func ready(toClose: [AnyHashable : Any]!) {
|
|
103
83
|
print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::ready to close");
|
|
104
84
|
delegate?.onConferenceLeft()
|
|
85
|
+
self.cleanUp()
|
|
86
|
+
|
|
105
87
|
self.dismiss(animated: true, completion: nil); // e.g. user ends the call. This is preferred over conferenceLeft to shorten the white screen while exiting the room
|
|
106
88
|
}
|
|
107
89
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import Capacitor
|
|
3
|
-
|
|
3
|
+
import JitsiMeetSDK
|
|
4
|
+
import UIKit
|
|
4
5
|
/**
|
|
5
6
|
* Please read the Capacitor iOS Plugin Development Guide
|
|
6
7
|
* here: https://capacitor.ionicframework.com/docs/plugins/ios
|
|
@@ -8,17 +9,9 @@ import Capacitor
|
|
|
8
9
|
@objc(Jitsi)
|
|
9
10
|
public class Jitsi: CAPPlugin {
|
|
10
11
|
|
|
11
|
-
var jitsiMeetViewController: JitsiMeetViewController
|
|
12
|
+
var jitsiMeetViewController: JitsiMeetViewController?
|
|
12
13
|
|
|
13
14
|
@objc func joinConference(_ call: CAPPluginCall) {
|
|
14
|
-
guard let url = call.options["url"] as? String else {
|
|
15
|
-
call.reject("Must provide an url")
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
guard let roomName = call.options["roomName"] as? String else {
|
|
19
|
-
call.reject("Must provide a roomName")
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
15
|
|
|
23
16
|
let podBundle = Bundle(for: JitsiMeetViewController.self)
|
|
24
17
|
let bundleURL = podBundle.url(forResource: "Plugin", withExtension: "bundle")
|
|
@@ -26,40 +19,96 @@ public class Jitsi: CAPPlugin {
|
|
|
26
19
|
|
|
27
20
|
let storyboard = UIStoryboard(name: "JitsiMeet", bundle: bundle)
|
|
28
21
|
self.jitsiMeetViewController = storyboard.instantiateViewController(withIdentifier: "jitsiMeetStoryBoardID") as? JitsiMeetViewController
|
|
22
|
+
guard let url = call.options["url"] as? String else {
|
|
23
|
+
call.reject("Must provide an url")
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
guard let roomName = call.options["roomName"] as? String else {
|
|
27
|
+
call.reject("Must provide a roomName")
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
let subject = call.options["subject"] as? String ?? " "
|
|
29
31
|
|
|
30
|
-
self.jitsiMeetViewController
|
|
31
|
-
self.jitsiMeetViewController.token = call.options["token"] as? String ?? nil;
|
|
32
|
-
self.jitsiMeetViewController.roomName = roomName;
|
|
33
|
-
self.jitsiMeetViewController.startWithAudioMuted = call.options["startWithAudioMuted"] as? Bool ?? false;
|
|
34
|
-
self.jitsiMeetViewController.startWithVideoMuted = call.options["startWithVideoMuted"] as? Bool ?? false;
|
|
35
|
-
self.jitsiMeetViewController.chatEnabled = call.options["chatEnabled"] as? Bool ?? false;
|
|
36
|
-
self.jitsiMeetViewController.inviteEnabled = call.options["inviteEnabled"] as? Bool ?? false;
|
|
37
|
-
self.jitsiMeetViewController.email = call.options["email"] as? String ?? nil
|
|
38
|
-
self.jitsiMeetViewController.displayName = call.options["displayName"] as? String ?? nil
|
|
39
|
-
self.jitsiMeetViewController.avatarUrl = call.options["avatarURL"] as? String ?? nil
|
|
40
|
-
self.jitsiMeetViewController.callIntegrationEnabled = call.options["callIntegrationEnabled"] as? Bool ?? true
|
|
41
|
-
self.jitsiMeetViewController.screenSharingEnabled = call.options["screenSharingEnabled"] as? Bool ?? false
|
|
42
|
-
self.jitsiMeetViewController.recordingEnabled = call.options["recordingEnabled"] as? Bool ?? false
|
|
43
|
-
self.jitsiMeetViewController.liveStreamingEnabled = call.options["liveStreamingEnabled"] as? Bool ?? false
|
|
44
|
-
self.jitsiMeetViewController.delegate = self;
|
|
32
|
+
self.jitsiMeetViewController?.webView = self.webView
|
|
45
33
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
self.jitsiMeetViewController?.options = JitsiMeetConferenceOptions.fromBuilder { (builder) in
|
|
35
|
+
builder.serverURL = URL(string: url)
|
|
36
|
+
builder.room = roomName
|
|
37
|
+
builder.setSubject(subject)
|
|
38
|
+
|
|
39
|
+
if let token = call.options["token"] as? String {
|
|
40
|
+
builder.token = token;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if let isAudioMuted = call.options["startWithAudioMuted"] as? Bool {
|
|
44
|
+
builder.setAudioMuted(isAudioMuted);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* if let isAudioOnly = call.options["isAudioOnly"] as? Bool {
|
|
48
|
+
builder.setAudioOnly(isAudioOnly)
|
|
49
|
+
} */
|
|
50
|
+
|
|
51
|
+
if let isVideoMuted = call.options["startWithVideoMuted"] as? Bool {
|
|
52
|
+
builder.setVideoMuted(isVideoMuted)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let displayName = call.options["displayName"] as? String
|
|
56
|
+
let email = call.options["email"] as? String
|
|
57
|
+
let avatarUrlString = call.options["avatarURL"] as? String
|
|
58
|
+
|
|
59
|
+
if (displayName != nil || email != nil || avatarUrlString != nil) {
|
|
60
|
+
let avatarUrl = avatarUrlString != nil ? URL(string: avatarUrlString!) : nil
|
|
61
|
+
builder.userInfo = JitsiMeetUserInfo(displayName: displayName, andEmail: email, andAvatar: avatarUrl)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var callIntegrationEnabled = call.options["callIntegrationEnabled"] as? Bool ?? true
|
|
65
|
+
let userLocale = NSLocale.current as NSLocale
|
|
66
|
+
if userLocale.countryCode?.contains("CN") ?? false ||
|
|
67
|
+
userLocale.countryCode?.contains("CHN") ?? false ||
|
|
68
|
+
userLocale.countryCode?.contains("MO") ?? false ||
|
|
69
|
+
userLocale.countryCode?.contains("HK") ?? false {
|
|
70
|
+
print("currentLocale is China so we cannot use CallKit.")
|
|
71
|
+
callIntegrationEnabled = false
|
|
72
|
+
}
|
|
73
|
+
builder.setFeatureFlag("call-integration.enabled", withBoolean: callIntegrationEnabled)
|
|
74
|
+
|
|
75
|
+
// default PiP is off as the feature is not fully functioning yet, but allow user to overrides it by providing the featureFlag
|
|
76
|
+
builder.setFeatureFlag("pip.enabled", withBoolean: false)
|
|
77
|
+
|
|
78
|
+
// if not set in the feature flags above, this will take effect
|
|
79
|
+
if let chatEnabled = call.options["chatEnabled"] as? Bool {
|
|
80
|
+
builder.setFeatureFlag("chat.enabled", withBoolean: chatEnabled)
|
|
81
|
+
}
|
|
82
|
+
if let inviteEnabled = call.options["inviteEnabled"] as? Bool {
|
|
83
|
+
builder.setFeatureFlag("invite.enabled", withBoolean: inviteEnabled)
|
|
84
|
+
}
|
|
85
|
+
if let screenSharingEnabled = call.options["screenSharingEnabled"] as? Bool {
|
|
86
|
+
builder.setFeatureFlag("ios.screensharing.enabled", withBoolean: screenSharingEnabled)
|
|
87
|
+
}
|
|
88
|
+
if let recordingEnabled = call.options["recordingEnabled"] as? Bool {
|
|
89
|
+
builder.setFeatureFlag("ios.recording.enabled", withBoolean: recordingEnabled)
|
|
90
|
+
}
|
|
91
|
+
if let liveStreamingEnabled = call.options["liveStreamingEnabled"] as? Bool {
|
|
92
|
+
builder.setFeatureFlag("live-streaming.enabled", withBoolean: liveStreamingEnabled)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// setfeatureFlag() provides finer control, and will override some of the settings above
|
|
96
|
+
let featureFlags = call.options["featureFlags"] as? Dictionary<String, Any>
|
|
97
|
+
|
|
98
|
+
featureFlags?.forEach { key, value in
|
|
99
|
+
builder.setFeatureFlag(key, withValue: value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let configOverrides = call.options["configOverrides"] as? Dictionary<String, Any>
|
|
103
|
+
configOverrides?.forEach { key, value in
|
|
104
|
+
builder.setConfigOverride(key, withValue: value);
|
|
105
|
+
}
|
|
52
106
|
}
|
|
53
|
-
}
|
|
54
107
|
|
|
55
|
-
|
|
56
|
-
|
|
108
|
+
self.jitsiMeetViewController?.delegate = self;
|
|
109
|
+
|
|
57
110
|
DispatchQueue.main.async {
|
|
58
|
-
self.bridge?.
|
|
59
|
-
call.resolve([
|
|
60
|
-
"success": true
|
|
61
|
-
])
|
|
62
|
-
})
|
|
111
|
+
self.bridge?.viewController?.present(self.jitsiMeetViewController!, animated: true, completion: nil);
|
|
63
112
|
}
|
|
64
113
|
}
|
|
65
114
|
}
|
package/ios/Plugin/Podfile
CHANGED
|
@@ -7,7 +7,7 @@ target 'Plugin' do
|
|
|
7
7
|
|
|
8
8
|
# Pods for IonicRunner
|
|
9
9
|
pod 'Capacitor'
|
|
10
|
-
pod 'JitsiMeetSDK', '4.
|
|
10
|
+
pod 'JitsiMeetSDK', '4.1.0'
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
post_install do |installer|
|
|
@@ -22,5 +22,5 @@ target 'PluginTests' do
|
|
|
22
22
|
use_frameworks!
|
|
23
23
|
|
|
24
24
|
pod 'Capacitor'
|
|
25
|
-
pod 'JitsiMeetSDK', '4.
|
|
25
|
+
pod 'JitsiMeetSDK', '4.1.0'
|
|
26
26
|
end
|
package/ios/README.md
CHANGED
|
@@ -53,6 +53,15 @@ npx cap sync
|
|
|
53
53
|
ionic capacitor open ios
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
### Dropbox Integration
|
|
57
|
+
|
|
58
|
+
See [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-ios-sdk#dropbox-integration).
|
|
59
|
+
|
|
60
|
+
### Screen Sharing Integration
|
|
61
|
+
|
|
62
|
+
See [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-ios-sdk#screen-sharing-integration).
|
|
63
|
+
|
|
64
|
+
|
|
56
65
|
### iOS SDK Developer Guide
|
|
57
66
|
|
|
58
67
|
Consult the official Jitsi iOS SDK [documentation](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-ios-sdk).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-jitsi-meet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0-beta.0",
|
|
4
4
|
"description": "This Ionic Capacitor plugin is created to make video calls through the free, open-sourced Jitsi video platform (https://meet.jit.si) on iOS and Android.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"build": "npm run clean && tsc && rollup -c rollup.config.js",
|
|
13
13
|
"clean": "rimraf ./dist",
|
|
14
14
|
"watch": "tsc --watch",
|
|
15
|
+
"prepare": "npm run build",
|
|
15
16
|
"prepublishOnly": "npm run build"
|
|
16
17
|
},
|
|
17
18
|
"author": "Calvin Ho",
|