mirror of
https://github.com/status-im/react-native.git
synced 2025-01-15 20:15:11 +00:00
Updated Websocket to use new event system
Reviewed By: javache Differential Revision: D3292473 fbshipit-source-id: f9a9e0a1b5a12f7fa8b36ebdba88405370f91c54
This commit is contained in:
parent
cd691e2cc2
commit
2525feb37f
@ -12,5 +12,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeEventEmitter = require('NativeEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
|
const KeyboardObserver = require('NativeModules').KeyboardObserver;
|
||||||
|
|
||||||
module.exports = new NativeEventEmitter('KeyboardObserver');
|
module.exports = new NativeEventEmitter(KeyboardObserver);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
const NativeEventEmitter = require('NativeEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
const StatusBar = require('StatusBar');
|
const StatusBar = require('StatusBar');
|
||||||
|
const StatusBarManager = require('NativeModules').StatusBarManager;
|
||||||
|
|
||||||
import type {StatusBarStyle, StatusBarAnimation} from 'StatusBar';
|
import type {StatusBarStyle, StatusBarAnimation} from 'StatusBar';
|
||||||
|
|
||||||
@ -38,6 +39,6 @@ class StatusBarIOS extends NativeEventEmitter {
|
|||||||
);
|
);
|
||||||
StatusBar.setNetworkActivityIndicatorVisible(visible);
|
StatusBar.setNetworkActivityIndicatorVisible(visible);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = new StatusBarIOS('StatusBarManager');
|
module.exports = new StatusBarIOS(StatusBarManager);
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const NativeModules = require('NativeModules');
|
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||||
const invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
@ -24,21 +23,17 @@ import type EmitterSubscription from 'EmitterSubscription';
|
|||||||
*/
|
*/
|
||||||
class NativeEventEmitter {
|
class NativeEventEmitter {
|
||||||
|
|
||||||
_listenerCount: number;
|
|
||||||
_nativeModule: Object;
|
_nativeModule: Object;
|
||||||
|
|
||||||
constructor(nativeModuleName: string) {
|
constructor(nativeModule: Object) {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
this._listenerCount = 0;
|
invariant(nativeModule, 'Native module cannot be null.');
|
||||||
this._nativeModule = NativeModules[nativeModuleName];
|
this._nativeModule = nativeModule;
|
||||||
invariant(this._nativeModule,
|
|
||||||
'Native module `' + nativeModuleName + '` not found.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
this._listenerCount++;
|
|
||||||
this._nativeModule.addListener(eventType);
|
this._nativeModule.addListener(eventType);
|
||||||
}
|
}
|
||||||
return RCTDeviceEventEmitter.nativeAddListener(eventType, listener, context);
|
return RCTDeviceEventEmitter.nativeAddListener(eventType, listener, context);
|
||||||
@ -54,7 +49,7 @@ class NativeEventEmitter {
|
|||||||
removeAllListeners(eventType: string) {
|
removeAllListeners(eventType: string) {
|
||||||
invariant(eventType, 'eventType argument is required.');
|
invariant(eventType, 'eventType argument is required.');
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
var count = RCTDeviceEventEmitter.listeners(eventType).length;
|
const count = RCTDeviceEventEmitter.listeners(eventType).length;
|
||||||
this._nativeModule.removeListeners(count);
|
this._nativeModule.removeListeners(count);
|
||||||
}
|
}
|
||||||
RCTDeviceEventEmitter.removeAllListeners(eventType);
|
RCTDeviceEventEmitter.removeAllListeners(eventType);
|
||||||
@ -62,7 +57,6 @@ class NativeEventEmitter {
|
|||||||
|
|
||||||
removeCurrentListener() {
|
removeCurrentListener() {
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
this._listenerCount--;
|
|
||||||
this._nativeModule.removeListeners(1);
|
this._nativeModule.removeListeners(1);
|
||||||
}
|
}
|
||||||
RCTDeviceEventEmitter.removeCurrentListener();
|
RCTDeviceEventEmitter.removeCurrentListener();
|
||||||
|
@ -13,23 +13,22 @@
|
|||||||
|
|
||||||
const EventEmitter = require('EventEmitter');
|
const EventEmitter = require('EventEmitter');
|
||||||
const BatchedBridge = require('BatchedBridge');
|
const BatchedBridge = require('BatchedBridge');
|
||||||
const NativeModules = require('NativeModules');
|
|
||||||
|
|
||||||
import type EmitterSubscription from 'EmitterSubscription';
|
import type EmitterSubscription from 'EmitterSubscription';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated - subclass NativeEventEmitter to create granular event modules instead of
|
* Deprecated - subclass NativeEventEmitter to create granular event modules instead of
|
||||||
* routing all event observation through RCTDeviceEventEmitter.
|
* adding all event listeners directly to RCTDeviceEventEmitter.
|
||||||
*/
|
*/
|
||||||
class RCTDeviceEventEmitter extends EventEmitter {
|
class RCTDeviceEventEmitter extends EventEmitter {
|
||||||
|
|
||||||
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
addListener(eventType: string, listener: any, context: ?Object): EmitterSubscription {
|
||||||
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
||||||
console.warn('statusBar events should be registered via the StatusBarIOS module');
|
console.warn('`%s` event should be registered via the StatusBarIOS module', eventType);
|
||||||
return require('StatusBarIOS').addListener(eventType, listener, context);
|
return require('StatusBarIOS').addListener(eventType, listener, context);
|
||||||
}
|
}
|
||||||
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
||||||
console.warn('keyboard events should be registered via the Keyboard module');
|
console.warn('`%s` event should be registered via the Keyboard module', eventType);
|
||||||
return require('Keyboard').addListener(eventType, listener, context);
|
return require('Keyboard').addListener(eventType, listener, context);
|
||||||
}
|
}
|
||||||
return super.addListener(eventType, listener, context);
|
return super.addListener(eventType, listener, context);
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "RCTBridgeModule.h"
|
#import "RCTEventEmitter.h"
|
||||||
#import "RCTSRWebSocket.h"
|
#import "RCTSRWebSocket.h"
|
||||||
|
|
||||||
@interface RCTWebSocketModule : NSObject <RCTBridgeModule, RCTSRWebSocketDelegate>
|
@interface RCTWebSocketModule : RCTEventEmitter <RCTSRWebSocketDelegate>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
|
|
||||||
#import "RCTWebSocketModule.h"
|
#import "RCTWebSocketModule.h"
|
||||||
|
|
||||||
#import "RCTBridge.h"
|
|
||||||
#import "RCTEventDispatcher.h"
|
|
||||||
#import "RCTConvert.h"
|
#import "RCTConvert.h"
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
@ -35,7 +33,13 @@
|
|||||||
|
|
||||||
RCT_EXPORT_MODULE()
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
@synthesize bridge = _bridge;
|
- (NSArray *)supportedEvents
|
||||||
|
{
|
||||||
|
return @[@"websocketMessage",
|
||||||
|
@"websocketOpen",
|
||||||
|
@"websocketFailed",
|
||||||
|
@"websocketClosed"];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
@ -84,7 +88,7 @@ RCT_EXPORT_METHOD(close:(nonnull NSNumber *)socketID)
|
|||||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message
|
- (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message
|
||||||
{
|
{
|
||||||
BOOL binary = [message isKindOfClass:[NSData class]];
|
BOOL binary = [message isKindOfClass:[NSData class]];
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"websocketMessage" body:@{
|
[self sendEventWithName:@"websocketMessage" body:@{
|
||||||
@"data": binary ? [message base64EncodedStringWithOptions:0] : message,
|
@"data": binary ? [message base64EncodedStringWithOptions:0] : message,
|
||||||
@"type": binary ? @"binary" : @"text",
|
@"type": binary ? @"binary" : @"text",
|
||||||
@"id": webSocket.reactTag
|
@"id": webSocket.reactTag
|
||||||
@ -93,14 +97,14 @@ RCT_EXPORT_METHOD(close:(nonnull NSNumber *)socketID)
|
|||||||
|
|
||||||
- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket
|
- (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket
|
||||||
{
|
{
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"websocketOpen" body:@{
|
[self sendEventWithName:@"websocketOpen" body:@{
|
||||||
@"id": webSocket.reactTag
|
@"id": webSocket.reactTag
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
|
- (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
|
||||||
{
|
{
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"websocketFailed" body:@{
|
[self sendEventWithName:@"websocketFailed" body:@{
|
||||||
@"message":error.localizedDescription,
|
@"message":error.localizedDescription,
|
||||||
@"id": webSocket.reactTag
|
@"id": webSocket.reactTag
|
||||||
}];
|
}];
|
||||||
@ -109,7 +113,7 @@ RCT_EXPORT_METHOD(close:(nonnull NSNumber *)socketID)
|
|||||||
- (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code
|
- (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code
|
||||||
reason:(NSString *)reason wasClean:(BOOL)wasClean
|
reason:(NSString *)reason wasClean:(BOOL)wasClean
|
||||||
{
|
{
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"websocketClosed" body:@{
|
[self sendEventWithName:@"websocketClosed" body:@{
|
||||||
@"code": @(code),
|
@"code": @(code),
|
||||||
@"reason": RCTNullIfNil(reason),
|
@"reason": RCTNullIfNil(reason),
|
||||||
@"clean": @(wasClean),
|
@"clean": @(wasClean),
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
const RCTWebSocketModule = require('NativeModules').WebSocketModule;
|
|
||||||
const Platform = require('Platform');
|
const Platform = require('Platform');
|
||||||
|
const RCTWebSocketModule = require('NativeModules').WebSocketModule;
|
||||||
const WebSocketEvent = require('WebSocketEvent');
|
const WebSocketEvent = require('WebSocketEvent');
|
||||||
|
|
||||||
const EventTarget = require('event-target-shim');
|
const EventTarget = require('event-target-shim');
|
||||||
@ -67,6 +67,7 @@ class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) {
|
|||||||
CLOSED: number = CLOSED;
|
CLOSED: number = CLOSED;
|
||||||
|
|
||||||
_socketId: number;
|
_socketId: number;
|
||||||
|
_eventEmitter: NativeEventEmitter;
|
||||||
_subscriptions: Array<EventSubscription>;
|
_subscriptions: Array<EventSubscription>;
|
||||||
|
|
||||||
onclose: ?Function;
|
onclose: ?Function;
|
||||||
@ -91,6 +92,7 @@ class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) {
|
|||||||
protocols = null;
|
protocols = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._eventEmitter = new NativeEventEmitter(RCTWebSocketModule);
|
||||||
this._socketId = nextWebSocketId++;
|
this._socketId = nextWebSocketId++;
|
||||||
RCTWebSocketModule.connect(url, protocols, options, this._socketId);
|
RCTWebSocketModule.connect(url, protocols, options, this._socketId);
|
||||||
this._registerEvents();
|
this._registerEvents();
|
||||||
@ -136,8 +138,8 @@ class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) {
|
|||||||
_close(code?: number, reason?: string): void {
|
_close(code?: number, reason?: string): void {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
// See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
||||||
var statusCode = typeof code === 'number' ? code : CLOSE_NORMAL;
|
const statusCode = typeof code === 'number' ? code : CLOSE_NORMAL;
|
||||||
var closeReason = typeof reason === 'string' ? reason : '';
|
const closeReason = typeof reason === 'string' ? reason : '';
|
||||||
RCTWebSocketModule.close(statusCode, closeReason, this._socketId);
|
RCTWebSocketModule.close(statusCode, closeReason, this._socketId);
|
||||||
} else {
|
} else {
|
||||||
RCTWebSocketModule.close(this._socketId);
|
RCTWebSocketModule.close(this._socketId);
|
||||||
@ -151,47 +153,43 @@ class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) {
|
|||||||
|
|
||||||
_registerEvents(): void {
|
_registerEvents(): void {
|
||||||
this._subscriptions = [
|
this._subscriptions = [
|
||||||
RCTDeviceEventEmitter.addListener('websocketMessage', ev => {
|
this._eventEmitter.addListener('websocketMessage', ev => {
|
||||||
if (ev.id !== this._socketId) {
|
if (ev.id !== this._socketId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var event = new WebSocketEvent('message', {
|
this.dispatchEvent(new WebSocketEvent('message', {
|
||||||
data: (ev.type === 'binary') ? base64.toByteArray(ev.data).buffer : ev.data
|
data: (ev.type === 'binary') ? base64.toByteArray(ev.data).buffer : ev.data
|
||||||
});
|
}));
|
||||||
this.dispatchEvent(event);
|
|
||||||
}),
|
}),
|
||||||
RCTDeviceEventEmitter.addListener('websocketOpen', ev => {
|
this._eventEmitter.addListener('websocketOpen', ev => {
|
||||||
if (ev.id !== this._socketId) {
|
if (ev.id !== this._socketId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.readyState = this.OPEN;
|
this.readyState = this.OPEN;
|
||||||
var event = new WebSocketEvent('open');
|
this.dispatchEvent(new WebSocketEvent('open'));
|
||||||
this.dispatchEvent(event);
|
|
||||||
}),
|
}),
|
||||||
RCTDeviceEventEmitter.addListener('websocketClosed', ev => {
|
this._eventEmitter.addListener('websocketClosed', ev => {
|
||||||
if (ev.id !== this._socketId) {
|
if (ev.id !== this._socketId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.readyState = this.CLOSED;
|
this.readyState = this.CLOSED;
|
||||||
var event = new WebSocketEvent('close');
|
this.dispatchEvent(new WebSocketEvent('close', {
|
||||||
event.code = ev.code;
|
code: ev.code,
|
||||||
event.reason = ev.reason;
|
reason: ev.reason,
|
||||||
this.dispatchEvent(event);
|
}));
|
||||||
this._unregisterEvents();
|
this._unregisterEvents();
|
||||||
this.close();
|
this.close();
|
||||||
}),
|
}),
|
||||||
RCTDeviceEventEmitter.addListener('websocketFailed', ev => {
|
this._eventEmitter.addListener('websocketFailed', ev => {
|
||||||
if (ev.id !== this._socketId) {
|
if (ev.id !== this._socketId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var event = new WebSocketEvent('error');
|
this.dispatchEvent(new WebSocketEvent('error', {
|
||||||
event.message = ev.message;
|
message: ev.message,
|
||||||
this.dispatchEvent(event);
|
}));
|
||||||
|
this.dispatchEvent(new WebSocketEvent('close', {
|
||||||
event = new WebSocketEvent('close');
|
message: ev.message,
|
||||||
event.message = ev.message;
|
}));
|
||||||
this.dispatchEvent(event);
|
|
||||||
|
|
||||||
this._unregisterEvents();
|
this._unregisterEvents();
|
||||||
this.close();
|
this.close();
|
||||||
})
|
})
|
||||||
|
@ -23,18 +23,23 @@
|
|||||||
|
|
||||||
- (NSArray<NSString *> *)supportedEvents
|
- (NSArray<NSString *> *)supportedEvents
|
||||||
{
|
{
|
||||||
|
RCTAssert(NO, @"You must override the `supportedEvents` method of %@", [self class]);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendEventWithName:(NSString *)eventName body:(id)body
|
- (void)sendEventWithName:(NSString *)eventName body:(id)body
|
||||||
{
|
{
|
||||||
RCTAssert(self.bridge != nil, @"bridge is not set.");
|
RCTAssert(_bridge != nil, @"bridge is not set.");
|
||||||
|
|
||||||
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
||||||
RCTLogError(@"`%@` is not a supported event type for %@", eventName, [self class]);
|
RCTLogError(@"`%@` is not a supported event type for %@", eventName, [self class]);
|
||||||
}
|
}
|
||||||
[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
if (_listenerCount > 0) {
|
||||||
args:body ? @[eventName, body] : @[eventName]];
|
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||||
|
args:body ? @[eventName, body] : @[eventName]];
|
||||||
|
} else {
|
||||||
|
RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startObserving
|
- (void)startObserving
|
||||||
|
Loading…
x
Reference in New Issue
Block a user