Quellcode durchsuchen

feat(mobile) adds ability to send and receive text messages (#8425)

master
tmoldovan8x8 vor 4 Jahren
Ursprung
Commit
61037b982b
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden

+ 2
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastAction.java Datei anzeigen

60
 
60
 
61
     enum Type {
61
     enum Type {
62
         SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
62
         SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
63
-        HANG_UP("org.jitsi.meet.HANG_UP");
63
+        HANG_UP("org.jitsi.meet.HANG_UP"),
64
+        SEND_ENDPOINT_TEXT_MESSAGE("org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE");
64
 
65
 
65
         private final String action;
66
         private final String action;
66
 
67
 

+ 5
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastEvent.java Datei anzeigen

80
         CONFERENCE_WILL_JOIN("org.jitsi.meet.CONFERENCE_WILL_JOIN"),
80
         CONFERENCE_WILL_JOIN("org.jitsi.meet.CONFERENCE_WILL_JOIN"),
81
         AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"),
81
         AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"),
82
         PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
82
         PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
83
-        PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT");
83
+        PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"),
84
+        ENDPOINT_TEXT_MESSAGE_RECEIVED("org.jitsi.meet.ENDPOINT_TEXT_MESSAGE_RECEIVED");
84
 
85
 
85
         private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
86
         private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
86
         private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
87
         private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
88
         private static final String AUDIO_MUTED_CHANGED_NAME = "AUDIO_MUTED_CHANGED";
89
         private static final String AUDIO_MUTED_CHANGED_NAME = "AUDIO_MUTED_CHANGED";
89
         private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED";
90
         private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED";
90
         private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT";
91
         private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT";
92
+        private static final String ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME = "ENDPOINT_TEXT_MESSAGE_RECEIVED";
91
 
93
 
92
         private final String action;
94
         private final String action;
93
 
95
 
122
                     return PARTICIPANT_JOINED;
124
                     return PARTICIPANT_JOINED;
123
                 case PARTICIPANT_LEFT_NAME:
125
                 case PARTICIPANT_LEFT_NAME:
124
                     return PARTICIPANT_LEFT;
126
                     return PARTICIPANT_LEFT;
127
+                case ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME:
128
+                    return ENDPOINT_TEXT_MESSAGE_RECEIVED;
125
             }
129
             }
126
 
130
 
127
             return null;
131
             return null;

+ 7
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastIntentHelper.java Datei anzeigen

12
     public static Intent buildHangUpIntent() {
12
     public static Intent buildHangUpIntent() {
13
         return new Intent(BroadcastAction.Type.HANG_UP.getAction());
13
         return new Intent(BroadcastAction.Type.HANG_UP.getAction());
14
     }
14
     }
15
+
16
+    public static Intent buildSendEndpointTextMessageIntent(String to, String message) {
17
+        Intent intent = new Intent(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
18
+        intent.putExtra("to", to);
19
+        intent.putExtra("message", message);
20
+        return intent;
21
+    }
15
 }
22
 }

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastReceiver.java Datei anzeigen

18
         IntentFilter intentFilter = new IntentFilter();
18
         IntentFilter intentFilter = new IntentFilter();
19
         intentFilter.addAction(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
19
         intentFilter.addAction(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
20
         intentFilter.addAction(BroadcastAction.Type.HANG_UP.getAction());
20
         intentFilter.addAction(BroadcastAction.Type.HANG_UP.getAction());
21
+        intentFilter.addAction(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
21
 
22
 
22
         localBroadcastManager.registerReceiver(this, intentFilter);
23
         localBroadcastManager.registerReceiver(this, intentFilter);
23
     }
24
     }

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ExternalAPIModule.java Datei anzeigen

77
 
77
 
78
         constants.put("SET_AUDIO_MUTED", BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
78
         constants.put("SET_AUDIO_MUTED", BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
79
         constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction());
79
         constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction());
80
+        constants.put("SEND_ENDPOINT_TEXT_MESSAGE", BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
80
 
81
 
81
         return constants;
82
         return constants;
82
     }
83
     }

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetActivity.java Datei anzeigen

271
         intentFilter.addAction(BroadcastEvent.Type.CONFERENCE_TERMINATED.getAction());
271
         intentFilter.addAction(BroadcastEvent.Type.CONFERENCE_TERMINATED.getAction());
272
         intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_JOINED.getAction());
272
         intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_JOINED.getAction());
273
         intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_LEFT.getAction());
273
         intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_LEFT.getAction());
274
+        intentFilter.addAction(BroadcastEvent.Type.ENDPOINT_TEXT_MESSAGE_RECEIVED.getAction());
274
 
275
 
275
         LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
276
         LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
276
     }
277
     }

+ 4
- 0
ios/app/src/ViewController.m Datei anzeigen

115
   NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
115
   NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
116
 }
116
 }
117
 
117
 
118
+- (void)endpointTextMessageReceived:(NSDictionary *)data; {
119
+  NSLog(@"%@%@", @"Endpoint text message received: ", data);
120
+}
121
+
118
 #pragma mark - Helpers
122
 #pragma mark - Helpers
119
 
123
 
120
 - (void)terminate {
124
 - (void)terminate {

+ 1
- 0
ios/sdk/src/ExternalAPI.h Datei anzeigen

20
 
20
 
21
 - (void)sendHangUp;
21
 - (void)sendHangUp;
22
 - (void)sendSetAudioMuted: (BOOL)muted;
22
 - (void)sendSetAudioMuted: (BOOL)muted;
23
+- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
23
 
24
 
24
 @end
25
 @end

+ 19
- 8
ios/sdk/src/ExternalAPI.m Datei anzeigen

18
 #import "JitsiMeetView+Private.h"
18
 #import "JitsiMeetView+Private.h"
19
 
19
 
20
 // Events
20
 // Events
21
-static NSString * const hangUpEvent = @"org.jitsi.meet.HANG_UP";
22
-static NSString * const setAudioMutedEvent = @"org.jitsi.meet.SET_AUDIO_MUTED";
21
+static NSString * const hangUpAction = @"org.jitsi.meet.HANG_UP";
22
+static NSString * const setAudioMutedAction = @"org.jitsi.meet.SET_AUDIO_MUTED";
23
+static NSString * const sendEndpointTextMessageAction = @"org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE";
23
 
24
 
24
 @implementation ExternalAPI
25
 @implementation ExternalAPI
25
 
26
 
27
 
28
 
28
 - (NSDictionary *)constantsToExport {
29
 - (NSDictionary *)constantsToExport {
29
     return @{
30
     return @{
30
-        @"HANG_UP": hangUpEvent,
31
-        @"SET_AUDIO_MUTED" : setAudioMutedEvent
31
+        @"HANG_UP": hangUpAction,
32
+        @"SET_AUDIO_MUTED" : setAudioMutedAction,
33
+        @"SEND_ENDPOINT_TEXT_MESSAGE": sendEndpointTextMessageAction
32
     };
34
     };
33
 };
35
 };
34
 
36
 
44
 }
46
 }
45
 
47
 
46
 - (NSArray<NSString *> *)supportedEvents {
48
 - (NSArray<NSString *> *)supportedEvents {
47
-    return @[ hangUpEvent, setAudioMutedEvent ];
49
+    return @[ hangUpAction, setAudioMutedAction, sendEndpointTextMessageAction ];
48
 }
50
 }
49
 
51
 
50
 /**
52
 /**
103
 }
105
 }
104
 
106
 
105
 - (void)sendHangUp {
107
 - (void)sendHangUp {
106
-    [self sendEventWithName:hangUpEvent body:nil];
108
+    [self sendEventWithName:hangUpAction body:nil];
107
 }
109
 }
108
 
110
 
109
-- (void)sendSetAudioMuted: (BOOL)muted {
111
+- (void)sendSetAudioMuted:(BOOL)muted {
110
     NSDictionary *data = @{ @"muted": [NSNumber numberWithBool:muted]};
112
     NSDictionary *data = @{ @"muted": [NSNumber numberWithBool:muted]};
111
 
113
 
112
-    [self sendEventWithName:setAudioMutedEvent body:data];
114
+    [self sendEventWithName:setAudioMutedAction body:data];
115
+}
116
+
117
+- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
118
+    NSDictionary *data = @{
119
+        @"to": to,
120
+        @"message": message
121
+    };
122
+    
123
+    [self sendEventWithName:sendEndpointTextMessageAction body:data];
113
 }
124
 }
114
 
125
 
115
 @end
126
 @end

+ 2
- 0
ios/sdk/src/JitsiMeet+Private.h Datei anzeigen

16
 
16
 
17
 #import <React/RCTBridge.h>
17
 #import <React/RCTBridge.h>
18
 
18
 
19
+#import "ExternalAPI.h"
19
 #import "JitsiMeet.h"
20
 #import "JitsiMeet.h"
20
 
21
 
21
 @interface JitsiMeet ()
22
 @interface JitsiMeet ()
22
 
23
 
23
 - (NSDictionary *)getDefaultProps;
24
 - (NSDictionary *)getDefaultProps;
24
 - (RCTBridge *)getReactBridge;
25
 - (RCTBridge *)getReactBridge;
26
+- (ExternalAPI *)getExternalAPI;
25
 
27
 
26
 @end
28
 @end

+ 4
- 0
ios/sdk/src/JitsiMeet.m Datei anzeigen

213
     return _bridgeWrapper.bridge;
213
     return _bridgeWrapper.bridge;
214
 }
214
 }
215
 
215
 
216
+- (ExternalAPI *)getExternalAPI {
217
+    return [_bridgeWrapper.bridge moduleForClass:ExternalAPI.class];
218
+}
219
+
216
 @end
220
 @end

+ 2
- 0
ios/sdk/src/JitsiMeetView.h Datei anzeigen

41
 
41
 
42
 - (void)setAudioMuted:(BOOL)muted;
42
 - (void)setAudioMuted:(BOOL)muted;
43
 
43
 
44
+- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
45
+
44
 @end
46
 @end

+ 9
- 4
ios/sdk/src/JitsiMeetView.m Datei anzeigen

116
 }
116
 }
117
 
117
 
118
 - (void)hangUp {
118
 - (void)hangUp {
119
-    RCTBridge *bridge = [[JitsiMeet sharedInstance] getReactBridge];
120
-    [[bridge moduleForClass:ExternalAPI.class] sendHangUp];
119
+    ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
120
+    [externalAPI sendHangUp];
121
 }
121
 }
122
 
122
 
123
 - (void)setAudioMuted:(BOOL)muted {
123
 - (void)setAudioMuted:(BOOL)muted {
124
-    RCTBridge *bridge = [[JitsiMeet sharedInstance] getReactBridge];
125
-    [[bridge moduleForClass:ExternalAPI.class] sendSetAudioMuted:muted];
124
+    ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
125
+    [externalAPI sendSetAudioMuted:muted];
126
+}
127
+
128
+- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
129
+    ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
130
+    [externalAPI sendEndpointTextMessage:to :message];
126
 }
131
 }
127
 
132
 
128
 #pragma mark Private methods
133
 #pragma mark Private methods

+ 8
- 0
ios/sdk/src/JitsiMeetViewDelegate.h Datei anzeigen

75
  * The `data` dictionary contains a `muted` key with state of the audioMuted for the localParticipant.
75
  * The `data` dictionary contains a `muted` key with state of the audioMuted for the localParticipant.
76
  */
76
  */
77
 - (void)audioMutedChanged:(NSDictionary *)data;
77
 - (void)audioMutedChanged:(NSDictionary *)data;
78
+
79
+/**
80
+ * Called when an endpoint text message is received.
81
+ *
82
+ * The `data` dictionary contains a `senderId` key with the participantId of the sender and a 'message' key with the content.
83
+ */
84
+- (void)endpointTextMessageReceived:(NSDictionary *)data;
85
+
78
 @end
86
 @end

+ 5
- 0
react/features/mobile/external-api/logger.js Datei anzeigen

1
+// @flow
2
+
3
+import { getLogger } from '../../base/logging/functions';
4
+
5
+export default getLogger('features/mobile/external-api');

+ 60
- 4
react/features/mobile/external-api/middleware.js Datei anzeigen

2
 
2
 
3
 import { NativeEventEmitter, NativeModules } from 'react-native';
3
 import { NativeEventEmitter, NativeModules } from 'react-native';
4
 
4
 
5
+import { ENDPOINT_TEXT_MESSAGE_NAME } from '../../../../modules/API/constants';
5
 import { appNavigate } from '../../app/actions';
6
 import { appNavigate } from '../../app/actions';
6
 import { APP_WILL_MOUNT } from '../../base/app/actionTypes';
7
 import { APP_WILL_MOUNT } from '../../base/app/actionTypes';
7
 import {
8
 import {
12
     JITSI_CONFERENCE_URL_KEY,
13
     JITSI_CONFERENCE_URL_KEY,
13
     SET_ROOM,
14
     SET_ROOM,
14
     forEachConference,
15
     forEachConference,
16
+    getCurrentConference,
15
     isRoomValid
17
     isRoomValid
16
 } from '../../base/conference';
18
 } from '../../base/conference';
17
 import { LOAD_CONFIG_ERROR } from '../../base/config';
19
 import { LOAD_CONFIG_ERROR } from '../../base/config';
22
     JITSI_CONNECTION_URL_KEY,
24
     JITSI_CONNECTION_URL_KEY,
23
     getURLWithoutParams
25
     getURLWithoutParams
24
 } from '../../base/connection';
26
 } from '../../base/connection';
27
+import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
25
 import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
28
 import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
26
 import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants';
29
 import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants';
27
 import { MiddlewareRegistry } from '../../base/redux';
30
 import { MiddlewareRegistry } from '../../base/redux';
29
 import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
32
 import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
30
 
33
 
31
 import { sendEvent } from './functions';
34
 import { sendEvent } from './functions';
35
+import logger from './logger';
32
 
36
 
33
 /**
37
 /**
34
  * Event which will be emitted on the native side to indicate the conference
38
  * Event which will be emitted on the native side to indicate the conference
36
  */
40
  */
37
 const CONFERENCE_TERMINATED = 'CONFERENCE_TERMINATED';
41
 const CONFERENCE_TERMINATED = 'CONFERENCE_TERMINATED';
38
 
42
 
43
+/**
44
+ * Event which will be emitted on the native side to indicate a message was received
45
+ * through the channel.
46
+ */
47
+const ENDPOINT_TEXT_MESSAGE_RECEIVED = 'ENDPOINT_TEXT_MESSAGE_RECEIVED';
48
+
39
 const { ExternalAPI } = NativeModules;
49
 const { ExternalAPI } = NativeModules;
40
 const eventEmitter = new NativeEventEmitter(ExternalAPI);
50
 const eventEmitter = new NativeEventEmitter(ExternalAPI);
41
 
51
 
52
 
62
 
53
     switch (type) {
63
     switch (type) {
54
     case APP_WILL_MOUNT:
64
     case APP_WILL_MOUNT:
55
-        _registerForNativeEvents(store.dispatch);
65
+        _registerForNativeEvents(store);
56
         break;
66
         break;
57
     case CONFERENCE_FAILED: {
67
     case CONFERENCE_FAILED: {
58
         const { error, ...data } = action;
68
         const { error, ...data } = action;
75
         break;
85
         break;
76
     }
86
     }
77
 
87
 
78
-    case CONFERENCE_JOINED:
79
     case CONFERENCE_LEFT:
88
     case CONFERENCE_LEFT:
80
     case CONFERENCE_WILL_JOIN:
89
     case CONFERENCE_WILL_JOIN:
81
         _sendConferenceEvent(store, action);
90
         _sendConferenceEvent(store, action);
82
         break;
91
         break;
83
 
92
 
93
+    case CONFERENCE_JOINED:
94
+        _sendConferenceEvent(store, action);
95
+        _registerForEndpointTextMessages(store);
96
+        break;
97
+
84
     case CONNECTION_DISCONNECTED: {
98
     case CONNECTION_DISCONNECTED: {
85
         // FIXME: This is a hack. See the description in the JITSI_CONNECTION_CONFERENCE_KEY constant definition.
99
         // FIXME: This is a hack. See the description in the JITSI_CONNECTION_CONFERENCE_KEY constant definition.
86
         // Check if this connection was attached to any conference. If it wasn't, fake a CONFERENCE_TERMINATED event.
100
         // Check if this connection was attached to any conference. If it wasn't, fake a CONFERENCE_TERMINATED event.
160
 /**
174
 /**
161
  * Registers for events sent from the native side via NativeEventEmitter.
175
  * Registers for events sent from the native side via NativeEventEmitter.
162
  *
176
  *
163
- * @param {Dispatch} dispatch - The Redux dispatch function.
177
+ * @param {Store} store - The redux store.
164
  * @private
178
  * @private
165
  * @returns {void}
179
  * @returns {void}
166
  */
180
  */
167
-function _registerForNativeEvents(dispatch) {
181
+function _registerForNativeEvents({ getState, dispatch }) {
168
     eventEmitter.addListener(ExternalAPI.HANG_UP, () => {
182
     eventEmitter.addListener(ExternalAPI.HANG_UP, () => {
169
         dispatch(appNavigate(undefined));
183
         dispatch(appNavigate(undefined));
170
     });
184
     });
172
     eventEmitter.addListener(ExternalAPI.SET_AUDIO_MUTED, ({ muted }) => {
186
     eventEmitter.addListener(ExternalAPI.SET_AUDIO_MUTED, ({ muted }) => {
173
         dispatch(muteLocal(muted === 'true'));
187
         dispatch(muteLocal(muted === 'true'));
174
     });
188
     });
189
+
190
+    eventEmitter.addListener(ExternalAPI.SEND_ENDPOINT_TEXT_MESSAGE, ({ to, message }) => {
191
+        const conference = getCurrentConference(getState());
192
+
193
+        try {
194
+            conference && conference.sendEndpointMessage(to, {
195
+                name: ENDPOINT_TEXT_MESSAGE_NAME,
196
+                text: message
197
+            });
198
+        } catch (error) {
199
+            logger.warn('Cannot send endpointMessage', error);
200
+        }
201
+    });
202
+}
203
+
204
+/**
205
+ * Registers for endpoint messages sent on conference data channel.
206
+ *
207
+ * @param {Store} store - The redux store.
208
+ * @private
209
+ * @returns {void}
210
+ */
211
+function _registerForEndpointTextMessages(store) {
212
+    const conference = getCurrentConference(store.getState());
213
+
214
+    conference && conference.on(
215
+        JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
216
+        (...args) => {
217
+            if (args && args.length >= 2) {
218
+                const [ sender, eventData ] = args;
219
+
220
+                if (eventData.name === ENDPOINT_TEXT_MESSAGE_NAME) {
221
+                    sendEvent(
222
+                        store,
223
+                        ENDPOINT_TEXT_MESSAGE_RECEIVED,
224
+                        /* data */ {
225
+                            message: eventData.text,
226
+                            senderId: sender._id
227
+                        });
228
+                }
229
+            }
230
+        });
175
 }
231
 }
176
 
232
 
177
 /**
233
 /**

Laden…
Abbrechen
Speichern