[iOS] Allow multiple JitsiMeetViews
This commit is contained in:
parent
5f64ccb97d
commit
10e5e0fdf5
|
@ -19,10 +19,10 @@ package org.jitsi.meet.sdk;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
|
|
||||||
#import "RCTBridgeModule.h"
|
#import "RCTBridgeModule.h"
|
||||||
|
|
||||||
#import "JitsiMeetView.h"
|
#import "JitsiMeetView+Private.h"
|
||||||
|
|
||||||
@interface ExternalAPI : NSObject<RCTBridgeModule>
|
@interface ExternalAPI : NSObject<RCTBridgeModule>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation ExternalAPI
|
@implementation ExternalAPI
|
||||||
|
@ -31,26 +32,40 @@ RCT_EXPORT_MODULE();
|
||||||
* - name: name of the event.
|
* - name: name of the event.
|
||||||
* - data: dictionary (JSON object in JS) with data associated with the event.
|
* - data: dictionary (JSON object in JS) with data associated with the event.
|
||||||
*/
|
*/
|
||||||
RCT_EXPORT_METHOD(sendEvent:(NSString*)name data:(NSDictionary *) data) {
|
RCT_EXPORT_METHOD(sendEvent:(NSString *)name
|
||||||
JitsiMeetView *view = [JitsiMeetView getInstance];
|
data:(NSDictionary *)data
|
||||||
id delegate = view != nil ? view.delegate : nil;
|
scope:(NSString *)scope) {
|
||||||
|
// The JavaScript App needs to provide uniquely identifying information to
|
||||||
|
// the native ExternalAPI module so that the latter may match the former
|
||||||
|
// to the native JitsiMeetView which hosts it.
|
||||||
|
JitsiMeetView *view = [JitsiMeetView viewForExternalAPIScope:scope];
|
||||||
|
|
||||||
if (delegate == nil) {
|
if (!view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id delegate = view.delegate;
|
||||||
|
|
||||||
|
if (!delegate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([name isEqualToString:@"CONFERENCE_FAILED"]
|
if ([name isEqualToString:@"CONFERENCE_FAILED"]
|
||||||
&& [delegate respondsToSelector:@selector(conferenceFailed:)]) {
|
&& [delegate respondsToSelector:@selector(conferenceFailed:)]) {
|
||||||
[delegate conferenceFailed:data];
|
[delegate conferenceFailed:data];
|
||||||
|
|
||||||
} else if ([name isEqualToString:@"CONFERENCE_JOINED"]
|
} else if ([name isEqualToString:@"CONFERENCE_JOINED"]
|
||||||
&& [delegate respondsToSelector:@selector(conferenceJoined:)]) {
|
&& [delegate respondsToSelector:@selector(conferenceJoined:)]) {
|
||||||
[delegate conferenceJoined:data];
|
[delegate conferenceJoined:data];
|
||||||
|
|
||||||
} else if ([name isEqualToString:@"CONFERENCE_LEFT"]
|
} else if ([name isEqualToString:@"CONFERENCE_LEFT"]
|
||||||
&& [delegate respondsToSelector:@selector(conferenceLeft:)]) {
|
&& [delegate respondsToSelector:@selector(conferenceLeft:)]) {
|
||||||
[delegate conferenceLeft:data];
|
[delegate conferenceLeft:data];
|
||||||
|
|
||||||
} else if ([name isEqualToString:@"CONFERENCE_WILL_JOIN"]
|
} else if ([name isEqualToString:@"CONFERENCE_WILL_JOIN"]
|
||||||
&& [delegate respondsToSelector:@selector(conferenceWillJoin:)]) {
|
&& [delegate respondsToSelector:@selector(conferenceWillJoin:)]) {
|
||||||
[delegate conferenceWillJoin:data];
|
[delegate conferenceWillJoin:data];
|
||||||
|
|
||||||
} else if ([name isEqualToString:@"CONFERENCE_WILL_LEAVE"]
|
} else if ([name isEqualToString:@"CONFERENCE_WILL_LEAVE"]
|
||||||
&& [delegate respondsToSelector:@selector(conferenceWillLeave:)]) {
|
&& [delegate respondsToSelector:@selector(conferenceWillLeave:)]) {
|
||||||
[delegate conferenceWillLeave:data];
|
[delegate conferenceWillLeave:data];
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "JitsiMeetView.h"
|
||||||
|
|
||||||
|
@interface JitsiMeetView ()
|
||||||
|
|
||||||
|
+ (instancetype)viewForExternalAPIScope:(NSString *)externalAPIScope;
|
||||||
|
|
||||||
|
@end
|
|
@ -34,8 +34,6 @@
|
||||||
sourceApplication:(NSString *)sourceApplication
|
sourceApplication:(NSString *)sourceApplication
|
||||||
annotation:(id)annotation;
|
annotation:(id)annotation;
|
||||||
|
|
||||||
+ (instancetype)getInstance;
|
|
||||||
|
|
||||||
- (void)loadURL:(nullable NSURL *)url;
|
- (void)loadURL:(nullable NSURL *)url;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#import <React/RCTLinkingManager.h>
|
#import <React/RCTLinkingManager.h>
|
||||||
#import <React/RCTRootView.h>
|
#import <React/RCTRootView.h>
|
||||||
|
|
||||||
#import "JitsiMeetView.h"
|
#import "JitsiMeetView+Private.h"
|
||||||
#import "RCTBridgeWrapper.h"
|
#import "RCTBridgeWrapper.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,146 +46,12 @@ RCTFatalHandler _RCTFatal = ^(NSError *error) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface JitsiMeetView() {
|
/**
|
||||||
RCTRootView *rootView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation JitsiMeetView
|
|
||||||
|
|
||||||
static RCTBridgeWrapper *bridgeWrapper;
|
|
||||||
static JitsiMeetView *instance;
|
|
||||||
|
|
||||||
#pragma mark Linking delegate helpers
|
|
||||||
// https://facebook.github.io/react-native/docs/linking.html
|
|
||||||
|
|
||||||
+ (BOOL)application:(UIApplication *)application
|
|
||||||
continueUserActivity:(NSUserActivity *)userActivity
|
|
||||||
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
|
|
||||||
{
|
|
||||||
return [RCTLinkingManager application:application
|
|
||||||
continueUserActivity:userActivity
|
|
||||||
restorationHandler:restorationHandler];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (BOOL)application:(UIApplication *)application
|
|
||||||
openURL:(NSURL *)url
|
|
||||||
sourceApplication:(NSString *)sourceApplication
|
|
||||||
annotation:(id)annotation {
|
|
||||||
return [RCTLinkingManager application:application
|
|
||||||
openURL:url
|
|
||||||
sourceApplication:sourceApplication
|
|
||||||
annotation:annotation];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark initializers
|
|
||||||
|
|
||||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
|
||||||
self = [super initWithCoder:coder];
|
|
||||||
if (self) {
|
|
||||||
[self initialize];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame {
|
|
||||||
self = [super initWithFrame:frame];
|
|
||||||
if (self) {
|
|
||||||
[self initialize];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark API
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loads the given URL and joins the specified conference. If the specified URL
|
|
||||||
* is null, the welcome page is shown.
|
|
||||||
*/
|
|
||||||
- (void)loadURL:(NSURL *)url {
|
|
||||||
NSMutableDictionary *props = [[NSMutableDictionary alloc] init];
|
|
||||||
|
|
||||||
// url
|
|
||||||
if (url) {
|
|
||||||
[props setObject:url.absoluteString forKey:@"url"];
|
|
||||||
}
|
|
||||||
// welcomePageEnabled
|
|
||||||
[props setObject:@(self.welcomePageEnabled) forKey:@"welcomePageEnabled"];
|
|
||||||
|
|
||||||
if (rootView == nil) {
|
|
||||||
rootView
|
|
||||||
= [[RCTRootView alloc] initWithBridge:bridgeWrapper.bridge
|
|
||||||
moduleName:@"App"
|
|
||||||
initialProperties:props];
|
|
||||||
rootView.backgroundColor = self.backgroundColor;
|
|
||||||
|
|
||||||
// Add React's root view as a subview which completely covers this one.
|
|
||||||
[rootView setFrame:[self bounds]];
|
|
||||||
[self addSubview:rootView];
|
|
||||||
} else {
|
|
||||||
// Update props with the new URL.
|
|
||||||
rootView.appProperties = props;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark private methods
|
|
||||||
|
|
||||||
+ (instancetype)getInstance {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal initialization:
|
|
||||||
*
|
|
||||||
* - sets the backgroudn color
|
|
||||||
* - creates the React bridge
|
|
||||||
* - loads the necessary custom fonts
|
|
||||||
* - registers a custom fatal error error handler for React
|
|
||||||
*/
|
|
||||||
- (void)initialize {
|
|
||||||
static dispatch_once_t onceToken;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Only allow a single instance for now. All React Native modules are
|
|
||||||
* kinda singletons so global state would be broken since we have a single
|
|
||||||
* bridge. Once we have that sorted out multiple instances of JitsiMeetView
|
|
||||||
* will be allowed.
|
|
||||||
*/
|
|
||||||
if (instance != nil) {
|
|
||||||
@throw [NSException
|
|
||||||
exceptionWithName:@"RuntimeError"
|
|
||||||
reason:@"Only a single instance is currently allowed"
|
|
||||||
userInfo:nil];
|
|
||||||
}
|
|
||||||
instance = self;
|
|
||||||
|
|
||||||
dispatch_once(&onceToken, ^{
|
|
||||||
// Set a background color which is in accord with the JavaScript and
|
|
||||||
// Android parts of the application and causes less perceived visual
|
|
||||||
// flicker than the default background color.
|
|
||||||
self.backgroundColor
|
|
||||||
= [UIColor colorWithRed:.07f green:.07f blue:.07f alpha:1];
|
|
||||||
|
|
||||||
// Initialize the React bridge.
|
|
||||||
bridgeWrapper = [[RCTBridgeWrapper alloc] init];
|
|
||||||
|
|
||||||
// Dynamically load custom bundled fonts.
|
|
||||||
[self loadCustomFonts];
|
|
||||||
|
|
||||||
// Register a fatal error handler for React.
|
|
||||||
[self registerFatalErrorHandler];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper function to dynamically load custom fonts. The UIAppFonts key in the
|
* Helper function to dynamically load custom fonts. The UIAppFonts key in the
|
||||||
* plist file doesn't work for frameworks, so fonts have to be manually loaded.
|
* plist file doesn't work for frameworks, so fonts have to be manually loaded.
|
||||||
*/
|
*/
|
||||||
- (void)loadCustomFonts {
|
void loadCustomFonts(Class clazz) {
|
||||||
NSBundle *bundle = [NSBundle bundleForClass:self.class];
|
NSBundle *bundle = [NSBundle bundleForClass:clazz];
|
||||||
NSArray *fonts = [bundle objectForInfoDictionaryKey:@"JitsiMeetFonts"];
|
NSArray *fonts = [bundle objectForInfoDictionaryKey:@"JitsiMeetFonts"];
|
||||||
|
|
||||||
for (NSString *item in fonts) {
|
for (NSString *item in fonts) {
|
||||||
|
@ -209,12 +75,12 @@ static JitsiMeetView *instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Helper function to register a fatal error handler for React. Our handler
|
* Helper function to register a fatal error handler for React. Our handler
|
||||||
* won't kill the process, it will swallow JS errors and print stack traces
|
* won't kill the process, it will swallow JS errors and print stack traces
|
||||||
* instead.
|
* instead.
|
||||||
*/
|
*/
|
||||||
- (void)registerFatalErrorHandler {
|
void registerFatalErrorHandler() {
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
// In the Release configuration, React Native will (intentionally) raise
|
// In the Release configuration, React Native will (intentionally) raise
|
||||||
// an unhandled NSException for an unhandled JavaScript error. This will
|
// an unhandled NSException for an unhandled JavaScript error. This will
|
||||||
|
@ -226,4 +92,144 @@ static JitsiMeetView *instance;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@interface JitsiMeetView() {
|
||||||
|
/**
|
||||||
|
* The unique identifier of this {@code JitsiMeetView} within the process
|
||||||
|
* for the purposes of {@link ExternalAPI}. The name scope was inspired by
|
||||||
|
* postis which we use on Web for the similar purposes of the iframe-based
|
||||||
|
* external API.
|
||||||
|
*/
|
||||||
|
NSString *externalAPIScope;
|
||||||
|
|
||||||
|
RCTRootView *rootView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation JitsiMeetView
|
||||||
|
|
||||||
|
static RCTBridgeWrapper *bridgeWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code JitsiMeetView}s associated with their {@code ExternalAPI} scopes
|
||||||
|
* (i.e. unique identifiers within the process).
|
||||||
|
*/
|
||||||
|
static NSMapTable<NSString *, JitsiMeetView *> *views;
|
||||||
|
|
||||||
|
#pragma mark Linking delegate helpers
|
||||||
|
// https://facebook.github.io/react-native/docs/linking.html
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)application
|
||||||
|
continueUserActivity:(NSUserActivity *)userActivity
|
||||||
|
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
|
||||||
|
{
|
||||||
|
return [RCTLinkingManager application:application
|
||||||
|
continueUserActivity:userActivity
|
||||||
|
restorationHandler:restorationHandler];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)application
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
sourceApplication:(NSString *)sourceApplication
|
||||||
|
annotation:(id)annotation {
|
||||||
|
return [RCTLinkingManager application:application
|
||||||
|
openURL:url
|
||||||
|
sourceApplication:sourceApplication
|
||||||
|
annotation:annotation];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Initializers
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)coder {
|
||||||
|
self = [super initWithCoder:coder];
|
||||||
|
if (self) {
|
||||||
|
[self initWithXXX];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
if (self) {
|
||||||
|
[self initWithXXX];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark API
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given URL and joins the specified conference. If the specified URL
|
||||||
|
* is null, the welcome page is shown.
|
||||||
|
*/
|
||||||
|
- (void)loadURL:(NSURL *)url {
|
||||||
|
NSMutableDictionary *props = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
|
// externalAPIScope
|
||||||
|
[props setObject:externalAPIScope forKey:@"externalAPIScope"];
|
||||||
|
// url
|
||||||
|
if (url) {
|
||||||
|
[props setObject:url.absoluteString forKey:@"url"];
|
||||||
|
}
|
||||||
|
// welcomePageEnabled
|
||||||
|
[props setObject:@(self.welcomePageEnabled) forKey:@"welcomePageEnabled"];
|
||||||
|
|
||||||
|
if (rootView == nil) {
|
||||||
|
rootView
|
||||||
|
= [[RCTRootView alloc] initWithBridge:bridgeWrapper.bridge
|
||||||
|
moduleName:@"App"
|
||||||
|
initialProperties:props];
|
||||||
|
rootView.backgroundColor = self.backgroundColor;
|
||||||
|
|
||||||
|
// Add React's root view as a subview which completely covers this one.
|
||||||
|
[rootView setFrame:[self bounds]];
|
||||||
|
[self addSubview:rootView];
|
||||||
|
} else {
|
||||||
|
// Update props with the new URL.
|
||||||
|
rootView.appProperties = props;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Private methods
|
||||||
|
|
||||||
|
+ (instancetype)viewForExternalAPIScope:(NSString *)externalAPIScope {
|
||||||
|
return [views objectForKey:externalAPIScope];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal initialization:
|
||||||
|
*
|
||||||
|
* - sets the backgroudn color
|
||||||
|
* - creates the React bridge
|
||||||
|
* - loads the necessary custom fonts
|
||||||
|
* - registers a custom fatal error error handler for React
|
||||||
|
*/
|
||||||
|
- (void)initWithXXX {
|
||||||
|
static dispatch_once_t dispatchOncePredicate;
|
||||||
|
|
||||||
|
dispatch_once(&dispatchOncePredicate, ^{
|
||||||
|
// Initialize the static state of JitsiMeetView.
|
||||||
|
bridgeWrapper = [[RCTBridgeWrapper alloc] init];
|
||||||
|
views = [NSMapTable strongToWeakObjectsMapTable];
|
||||||
|
|
||||||
|
// Dynamically load custom bundled fonts.
|
||||||
|
loadCustomFonts(self.class);
|
||||||
|
|
||||||
|
// Register a fatal error handler for React.
|
||||||
|
registerFatalErrorHandler();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hook this JitsiMeetView into ExternalAPI.
|
||||||
|
externalAPIScope = [NSUUID UUID].UUIDString;
|
||||||
|
[views setObject:self forKey:externalAPIScope];
|
||||||
|
|
||||||
|
// Set a background color which is in accord with the JavaScript and
|
||||||
|
// Android parts of the application and causes less perceived visual
|
||||||
|
// flicker than the default background color.
|
||||||
|
self.backgroundColor
|
||||||
|
= [UIColor colorWithRed:.07f green:.07f blue:.07f alpha:1];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -18,41 +18,45 @@
|
||||||
|
|
||||||
@optional
|
@optional
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Called when a joining a conference was unsuccessful or when there was an error
|
* Called when a joining a conference was unsuccessful or when there was an
|
||||||
* while in a conference.
|
* error while in a conference.
|
||||||
*
|
*
|
||||||
* The `data` dictionary contains an "error" key describing the error and a "url"
|
* The {@code data} dictionary contains an "error" key describing the error and
|
||||||
* key with the conference URL.
|
* a {@code url} key with the conference URL.
|
||||||
*/
|
*/
|
||||||
- (void) conferenceFailed:(NSDictionary *) data;
|
- (void) conferenceFailed:(NSDictionary *)data;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Called when a conference was joined.
|
* Called when a conference was joined.
|
||||||
*
|
*
|
||||||
* The `data` dictionary contains a "url" key with the conference URL.
|
* The {@code data} dictionary contains a {@code url} key with the conference
|
||||||
|
* URL.
|
||||||
*/
|
*/
|
||||||
- (void) conferenceJoined:(NSDictionary *) data;
|
- (void) conferenceJoined:(NSDictionary *)data;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Called when a conference was left.
|
* Called when a conference was left.
|
||||||
*
|
*
|
||||||
* The `data` dictionary contains a "url" key with the conference URL.
|
* The {@code data} dictionary contains a {@code url} key with the conference
|
||||||
|
* URL.
|
||||||
*/
|
*/
|
||||||
- (void) conferenceLeft:(NSDictionary *) data;
|
- (void) conferenceLeft:(NSDictionary *)data;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Called before a conference is joined.
|
* Called before a conference is joined.
|
||||||
*
|
*
|
||||||
* The `data` dictionary contains a "url" key with the conference URL.
|
* The {@code data} dictionary contains a {@code url} key with the conference
|
||||||
|
* URL.
|
||||||
*/
|
*/
|
||||||
- (void) conferenceWillJoin:(NSDictionary *) data;
|
- (void) conferenceWillJoin:(NSDictionary *)data;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Called before a conference is left.
|
* Called before a conference is left.
|
||||||
*
|
*
|
||||||
* The `data` dictionary contains a "url" key with the conference URL.
|
* The {@code data} dictionary contains a {@code url} key with the conference
|
||||||
|
* URL.
|
||||||
*/
|
*/
|
||||||
- (void) conferenceWillLeave:(NSDictionary *) data;
|
- (void) conferenceWillLeave:(NSDictionary *)data;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#include "RCTBridgeWrapper.h"
|
#include "RCTBridgeWrapper.h"
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Wrapper around RCTBridge which also implements the RCTBridgeDelegate methods,
|
* Wrapper around RCTBridge which also implements the RCTBridgeDelegate methods,
|
||||||
* allowing us to specify where the bundles are loaded from.
|
* allowing us to specify where the bundles are loaded from.
|
||||||
*/
|
*/
|
||||||
|
@ -56,9 +56,9 @@ static NSURL *serverRootWithHost(NSString *host) {
|
||||||
|
|
||||||
- (NSString *)guessPackagerHost {
|
- (NSString *)guessPackagerHost {
|
||||||
static NSString *ipGuess;
|
static NSString *ipGuess;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t dispatchOncePredicate;
|
||||||
|
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&dispatchOncePredicate, ^{
|
||||||
NSString *ipPath
|
NSString *ipPath
|
||||||
= [[NSBundle bundleForClass:self.class] pathForResource:@"ip"
|
= [[NSBundle bundleForClass:self.class] pathForResource:@"ip"
|
||||||
ofType:@"txt"];
|
ofType:@"txt"];
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import { NativeModules } from 'react-native';
|
import { NativeModules } from 'react-native';
|
||||||
|
|
||||||
|
import { Platform } from '../../base/react';
|
||||||
import {
|
import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
|
@ -41,8 +42,8 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
// of locationURL at the time of CONFERENCE_WILL_LEAVE and
|
// of locationURL at the time of CONFERENCE_WILL_LEAVE and
|
||||||
// CONFERENCE_LEFT will not be the value with which the
|
// CONFERENCE_LEFT will not be the value with which the
|
||||||
// JitsiConference instance being left.)
|
// JitsiConference instance being left.)
|
||||||
const { locationURL }
|
const state = store.getState();
|
||||||
= store.getState()['features/base/connection'];
|
const { locationURL } = state['features/base/connection'];
|
||||||
|
|
||||||
if (!locationURL) {
|
if (!locationURL) {
|
||||||
// The (redux) action cannot be fully converted to an (external
|
// The (redux) action cannot be fully converted to an (external
|
||||||
|
@ -63,7 +64,14 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
name = name.slice(7, -1);
|
name = name.slice(7, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendEvent(name, data);
|
// The polyfill es6-symbol that we use does not appear to comply with
|
||||||
|
// the Symbol standard and, merely, adds @@ at the beginning of the
|
||||||
|
// description.
|
||||||
|
if (name.startsWith('@@')) {
|
||||||
|
name = name.slice(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendEvent(store, name, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,12 +84,31 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
* apps may listen to such events via the mechanisms provided by the (native)
|
* apps may listen to such events via the mechanisms provided by the (native)
|
||||||
* mobile Jitsi Meet SDK.
|
* mobile Jitsi Meet SDK.
|
||||||
*
|
*
|
||||||
|
* @param {Object} store - The redux store associated with the need to send the
|
||||||
|
* specified event.
|
||||||
* @param {string} name - The name of the event to send.
|
* @param {string} name - The name of the event to send.
|
||||||
* @param {Object} data - The details/specifics of the event to send determined
|
* @param {Object} data - The details/specifics of the event to send determined
|
||||||
* by/associated with the specified {@code name}.
|
* by/associated with the specified {@code name}.
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function _sendEvent(name: string, data: Object) {
|
function _sendEvent(store: Object, name: string, data: Object) {
|
||||||
|
// The JavaScript App needs to provide uniquely identifying information
|
||||||
|
// to the native ExternalAPI module so that the latter may match the former
|
||||||
|
// to the native JitsiMeetView which hosts it.
|
||||||
|
const state = store.getState();
|
||||||
|
const { app } = state['features/app'];
|
||||||
|
|
||||||
|
if (app) {
|
||||||
|
const { externalAPIScope } = app.props;
|
||||||
|
|
||||||
|
// TODO Lift the restriction on the JitsiMeetView instance count on
|
||||||
|
// Android as well.
|
||||||
|
if (externalAPIScope) {
|
||||||
|
NativeModules.ExternalAPI.sendEvent(name, data, externalAPIScope);
|
||||||
|
} else if (Platform.OS === 'android') {
|
||||||
NativeModules.ExternalAPI.sendEvent(name, data);
|
NativeModules.ExternalAPI.sendEvent(name, data);
|
||||||
|
console.warn(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue