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 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.1.2 (2022-02-08)
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.1.0'
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.0.0'
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
- token: string, // jwt authentication token
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
- recordingEnabled: false, // enable recording feature, default: false
95
- liveStreamingEnabled: false, // enable live streaming feature, default: false
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 uses the [Jitsi Meet SDK](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-mobile). It was originally developed by then ESTOS' developer Philipp Hancke who then contributed it to the community where development continues with joint forces!
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 androidx.localbroadcastmanager.content.LocalBroadcastManager;
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
- String url = call.getString("url");
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
- Boolean chatEnabled = call.getBoolean("chatEnabled");
41
- Boolean inviteEnabled = call.getBoolean("inviteEnabled");
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
- if(startWithAudioMuted == null) {
64
- startWithAudioMuted = false;
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
- if(startWithVideoMuted == null) {
67
- startWithVideoMuted = false;
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(chatEnabled == null) {
70
- chatEnabled = true;
109
+ if(call.getBoolean("inviteEnabled") != null){
110
+ builder.setFeatureFlag("invite.enabled", call.getBoolean("inviteEnabled"));
71
111
  }
72
- if(inviteEnabled == null) {
73
- chatEnabled = true;
112
+ if(call.getBoolean("callIntegrationEnabled") != null){
113
+ builder.setFeatureFlag("call-integration.enabled", call.getBoolean("callIntegrationEnabled"));
74
114
  }
75
- if(callIntegrationEnabled == null) {
76
- callIntegrationEnabled = true;
115
+ if(call.getBoolean("recordingEnabled") != null){
116
+ builder.setFeatureFlag("recording.enabled", call.getBoolean("recordingEnabled"));
77
117
  }
78
- if(recordingEnabled == null){
79
- recordingEnabled = false;
118
+ if(call.getBoolean("liveStreamingEnabled") != null){
119
+ builder.setFeatureFlag("live-streaming.enabled", call.getBoolean("liveStreamingEnabled"));
80
120
  }
81
- if(screenSharingEnabled == null){
82
- screenSharingEnabled = false;
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
- Intent intent = new Intent(getActivity(), JitsiActivity.class);
87
- intent.putExtra("url", url);
88
- intent.putExtra("token", token);
89
- intent.putExtra("roomName", roomName);
90
- intent.putExtra("displayName", displayName);
91
- intent.putExtra("email", email);
92
- intent.putExtra("avatarURL", avatarURL);
93
- intent.putExtra("startWithAudioMuted", startWithAudioMuted);
94
- intent.putExtra("startWithVideoMuted", startWithVideoMuted);
95
- intent.putExtra("chatEnabled", chatEnabled);
96
- intent.putExtra("inviteEnabled", inviteEnabled);
97
- intent.putExtra("callIntegrationEnabled", callIntegrationEnabled);
98
- intent.putExtra("recordingEnabled", recordingEnabled);
99
- if(liveStreamingEnabled != null){
100
- intent.putExtra("liveStreamingEnabled", Boolean.parseBoolean(liveStreamingEnabled));
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
- getActivity().startActivity(intent);
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 java.net.MalformedURLException;
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.JitsiMeetView;
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
- @Override
32
- protected void initialize() {
33
- broadcastReceiver = new BroadcastReceiver() {
34
- @Override
35
- public void onReceive(Context context, Intent intent) {
36
- onBroadcastReceived(intent);
37
- }
38
- };
39
- registerForBroadcastMessages();
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
- if (email != null) {
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
- // TODO: Some users who enabled PIP report that it doesn't always terminate the call correctly.
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
- Timber.d("Picture-in-picture is stopped. Disposing view and finishing activity.");
172
- if (view != null) {
173
- view.dispose();
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
  }
@@ -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,OAgBtB;;YAiBG,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
+ {"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="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
3
- <device id="retina4_7" orientation="portrait" appearance="light"/>
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="15704"/>
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="fullScreen" useStoryboardIdentifierAsRestorationIdentifier="YES" id="BYZ-38-t0r" customClass="JitsiMeetViewController" customModule="CapacitorJitsiMeet" sceneMemberID="viewController">
14
- <layoutGuides>
15
- <viewControllerLayoutGuide type="top" id="drl-1K-Grw"/>
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
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
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: JitsiMeetView!
15
- var url: String = ""
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 viewDidAppear(_ animated: Bool) {
38
- super.viewDidAppear(animated);
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
- public override func viewWillDisappear(_ animated: Bool) {
78
- super.viewWillDisappear(animated)
33
+ func openJitsiMeet() {
34
+ cleanUp()
79
35
 
80
- print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::leaveConference");
36
+ print("[Jitsi Plugin Native iOS]: JitsiMeetViewController::openJitsiMeet");
81
37
 
82
- jitsiMeetView = view as? JitsiMeetView;
83
- jitsiMeetView?.delegate = self
84
- jitsiMeetView.leave()
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. Room name is \(self.roomName)");
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.url = url;
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
- DispatchQueue.main.async {
47
- self.bridge?.presentVC(self.jitsiMeetViewController, animated: true, completion: {
48
- call.resolve([
49
- "success": true
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
- @objc func leaveConference(_ call: CAPPluginCall) {
56
- self.jitsiMeetViewController.delegate = self;
108
+ self.jitsiMeetViewController?.delegate = self;
109
+
57
110
  DispatchQueue.main.async {
58
- self.bridge?.dismissVC(animated: true, completion: {
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
  }
@@ -7,7 +7,7 @@ target 'Plugin' do
7
7
 
8
8
  # Pods for IonicRunner
9
9
  pod 'Capacitor'
10
- pod 'JitsiMeetSDK', '4.0.0'
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.0.0'
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.1.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",