feat(dropbox): Implement react-native module.
This commit is contained in:
parent
b7b43e8d9c
commit
38517127c3
|
@ -491,3 +491,29 @@ Picture-in-Picture style scenario, in a rectangle too small to accommodate its
|
||||||
Jitsi Meet SDK automatically enables (unless explicitly disabled by a
|
Jitsi Meet SDK automatically enables (unless explicitly disabled by a
|
||||||
`setPictureInPictureEnabled(false)` call) Android's native Picture-in-Picture
|
`setPictureInPictureEnabled(false)` call) Android's native Picture-in-Picture
|
||||||
mode iff the platform is supported i.e. Android >= Oreo.
|
mode iff the platform is supported i.e. Android >= Oreo.
|
||||||
|
|
||||||
|
## Dropbox integration
|
||||||
|
|
||||||
|
To setup the Dropbox integration, follow these steps:
|
||||||
|
|
||||||
|
1. Add the following to the app's AndroidManifest.xml and change `<APP_KEY>` to
|
||||||
|
your Dropbox app key:
|
||||||
|
```
|
||||||
|
<activity
|
||||||
|
android:configChanges="keyboard|orientation"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:name="com.dropbox.core.android.AuthActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:scheme="db-<APP_KEY>" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add the following to the app's strings.xml and change `<APP_KEY>` to your
|
||||||
|
Dropbox app key:
|
||||||
|
```
|
||||||
|
<string name="dropbox_app_key"><APP_KEY></string>
|
||||||
|
```
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
def dropboxAppID = ""
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
|
|
||||||
|
@ -28,10 +30,12 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
|
resValue("string", "dropbox_app_key", "${dropboxAppID}")
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
|
resValue("string", "dropbox_app_key", "${dropboxAppID}")
|
||||||
minifyEnabled true
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
|
||||||
}
|
}
|
||||||
|
@ -41,6 +45,36 @@ android {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dropboxAppID) {
|
||||||
|
def dropboxActivity = """<activity
|
||||||
|
android:name="com.dropbox.core.android.AuthActivity"
|
||||||
|
android:configChanges="orientation|keyboard"
|
||||||
|
android:launchMode="singleTask">
|
||||||
|
<intent-filter>
|
||||||
|
<data android:scheme="db-${dropboxAppID}" />
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>""";
|
||||||
|
|
||||||
|
|
||||||
|
applicationVariants.all { variant ->
|
||||||
|
variant.outputs.each { output ->
|
||||||
|
output.processManifest.doLast {
|
||||||
|
File manifestOutFile = new File(output.processManifest.manifestOutputDirectory, "AndroidManifest.xml")
|
||||||
|
if (!manifestOutFile.isFile()) {
|
||||||
|
manifestOutFile = new File(new File(output.processManifest.manifestOutputDirectory, output.dirName),"AndroidManifest.xml")
|
||||||
|
}
|
||||||
|
if (manifestOutFile.exists()) {
|
||||||
|
def newFileContents = manifestOutFile.getText('UTF-8').replace("</application>", "${dropboxActivity}</application>")
|
||||||
|
manifestOutFile.write(newFileContents, 'UTF-8')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -22,6 +22,7 @@ dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
compile 'com.android.support:appcompat-v7:27.0.2'
|
compile 'com.android.support:appcompat-v7:27.0.2'
|
||||||
|
compile 'com.dropbox.core:dropbox-core-sdk:3.0.8'
|
||||||
compile 'com.facebook.react:react-native:+'
|
compile 'com.facebook.react:react-native:+'
|
||||||
|
|
||||||
compile project(':react-native-background-timer')
|
compile project(':react-native-background-timer')
|
||||||
|
|
|
@ -45,6 +45,7 @@ class ReactInstanceManagerHolder {
|
||||||
new PictureInPictureModule(reactContext),
|
new PictureInPictureModule(reactContext),
|
||||||
new ProximityModule(reactContext),
|
new ProximityModule(reactContext),
|
||||||
new WiFiStatsModule(reactContext),
|
new WiFiStatsModule(reactContext),
|
||||||
|
new org.jitsi.meet.sdk.dropbox.Dropbox(reactContext),
|
||||||
new org.jitsi.meet.sdk.invite.InviteModule(reactContext),
|
new org.jitsi.meet.sdk.invite.InviteModule(reactContext),
|
||||||
new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext)
|
new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext)
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
package org.jitsi.meet.sdk.dropbox;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.dropbox.core.DbxException;
|
||||||
|
import com.dropbox.core.DbxRequestConfig;
|
||||||
|
import com.dropbox.core.v2.DbxClientV2;
|
||||||
|
import com.dropbox.core.v2.users.FullAccount;
|
||||||
|
import com.dropbox.core.v2.users.SpaceAllocation;
|
||||||
|
import com.dropbox.core.v2.users.SpaceUsage;
|
||||||
|
import com.facebook.react.bridge.Arguments;
|
||||||
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
|
import com.facebook.react.bridge.Promise;
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
|
import com.dropbox.core.android.Auth;
|
||||||
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import org.jitsi.meet.sdk.R;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the react-native module for the dropbox integration.
|
||||||
|
*/
|
||||||
|
public class Dropbox extends ReactContextBaseJavaModule implements LifecycleEventListener {
|
||||||
|
|
||||||
|
private Promise promise = null;
|
||||||
|
private String clientId;
|
||||||
|
private String appID;
|
||||||
|
private boolean isEnabled = false;
|
||||||
|
|
||||||
|
public Dropbox(ReactApplicationContext reactContext) {
|
||||||
|
super(reactContext);
|
||||||
|
reactContext.addLifecycleEventListener(this);
|
||||||
|
clientId = generateClientId();
|
||||||
|
appID = reactContext.getString(R.string.dropbox_app_key);
|
||||||
|
if (!TextUtils.isEmpty(appID)) {
|
||||||
|
isEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Dropbox";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the dropbox auth flow.
|
||||||
|
*
|
||||||
|
* @param promise The promise used to return the result of the auth flow.
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void authorize(final Promise promise) {
|
||||||
|
if (!isEnabled) {
|
||||||
|
promise.reject(new Exception("Dropbox integration isn't configured."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Auth.startOAuth2Authentication(this.getCurrentActivity(), appID);
|
||||||
|
this.promise = promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getConstants() {
|
||||||
|
final Map<String, Object> constants = new HashMap<>();
|
||||||
|
constants.put("ENABLED", isEnabled);
|
||||||
|
return constants;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the current user dropbox display name.
|
||||||
|
*
|
||||||
|
* @param token A dropbox access token.
|
||||||
|
* @param promise The promise used to return the result of the auth flow.
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void getDisplayName(final String token, final Promise promise) {
|
||||||
|
DbxRequestConfig config
|
||||||
|
= DbxRequestConfig.newBuilder(clientId).build();
|
||||||
|
DbxClientV2 client = new DbxClientV2(config, token);
|
||||||
|
// Get current account info
|
||||||
|
try {
|
||||||
|
FullAccount account = client.users().getCurrentAccount();
|
||||||
|
promise.resolve(account.getName().getDisplayName());
|
||||||
|
} catch (DbxException e) {
|
||||||
|
promise.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the current user space usage.
|
||||||
|
*
|
||||||
|
* @param token A dropbox access token.
|
||||||
|
* @param promise The promise used to return the result of the auth flow.
|
||||||
|
*/
|
||||||
|
@ReactMethod
|
||||||
|
public void getSpaceUsage(final String token, final Promise promise) {
|
||||||
|
DbxRequestConfig config
|
||||||
|
= DbxRequestConfig.newBuilder(clientId).build();
|
||||||
|
DbxClientV2 client = new DbxClientV2(config, token);
|
||||||
|
try {
|
||||||
|
SpaceUsage spaceUsage = client.users().getSpaceUsage();
|
||||||
|
WritableMap map = Arguments.createMap();
|
||||||
|
map.putString("used", String.valueOf(spaceUsage.getUsed()));
|
||||||
|
SpaceAllocation allocation = spaceUsage.getAllocation();
|
||||||
|
long allocated = 0;
|
||||||
|
if(allocation.isIndividual()) {
|
||||||
|
allocated += allocation.getIndividualValue().getAllocated();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(allocation.isTeam()) {
|
||||||
|
allocated += allocation.getTeamValue().getAllocated();
|
||||||
|
}
|
||||||
|
map.putString("allocated", String.valueOf(allocated));
|
||||||
|
promise.resolve(map);
|
||||||
|
} catch (DbxException e) {
|
||||||
|
promise.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a client identifier for the dropbox sdk.
|
||||||
|
*
|
||||||
|
* @returns a client identifier for the dropbox sdk.
|
||||||
|
* @see {https://dropbox.github.io/dropbox-sdk-java/api-docs/v3.0.x/com/dropbox/core/DbxRequestConfig.html#getClientIdentifier--}
|
||||||
|
*/
|
||||||
|
private String generateClientId() {
|
||||||
|
Context context = getReactApplicationContext();
|
||||||
|
PackageManager packageManager = context.getPackageManager();
|
||||||
|
ApplicationInfo applicationInfo = null;
|
||||||
|
PackageInfo packageInfo = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String packageName = context.getPackageName();
|
||||||
|
|
||||||
|
applicationInfo
|
||||||
|
= packageManager.getApplicationInfo(packageName, 0);
|
||||||
|
packageInfo = packageManager.getPackageInfo(packageName, 0);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
String applicationLabel
|
||||||
|
= applicationInfo == null
|
||||||
|
? "JitsiMeet"
|
||||||
|
: packageManager.getApplicationLabel(applicationInfo)
|
||||||
|
.toString().replaceAll("\\s", "");
|
||||||
|
String version = packageInfo == null ? "dev" : packageInfo.versionName;
|
||||||
|
|
||||||
|
return applicationLabel + "/" + version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHostResume() {
|
||||||
|
final String token = Auth.getOAuth2Token();
|
||||||
|
if (token == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.promise != null) {
|
||||||
|
this.promise.resolve(token);
|
||||||
|
this.promise = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHostPause() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHostDestroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Jitsi Meet SDK</string>
|
<string name="app_name">Jitsi Meet SDK</string>
|
||||||
|
<string name="dropbox_app_key"></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -26,6 +26,8 @@ target 'JitsiMeet' do
|
||||||
pod 'Folly',
|
pod 'Folly',
|
||||||
:podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
:podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
||||||
|
|
||||||
|
pod 'ObjectiveDropboxOfficial'
|
||||||
|
|
||||||
pod 'react-native-background-timer',
|
pod 'react-native-background-timer',
|
||||||
:path => '../node_modules/react-native-background-timer'
|
:path => '../node_modules/react-native-background-timer'
|
||||||
pod 'react-native-fast-image',
|
pod 'react-native-fast-image',
|
||||||
|
|
|
@ -27,6 +27,7 @@ PODS:
|
||||||
- GTMSessionFetcher/Core (1.2.0)
|
- GTMSessionFetcher/Core (1.2.0)
|
||||||
- GTMSessionFetcher/Full (1.2.0):
|
- GTMSessionFetcher/Full (1.2.0):
|
||||||
- GTMSessionFetcher/Core (= 1.2.0)
|
- GTMSessionFetcher/Core (= 1.2.0)
|
||||||
|
- ObjectiveDropboxOfficial (3.9.1)
|
||||||
- React (0.55.4):
|
- React (0.55.4):
|
||||||
- React/Core (= 0.55.4)
|
- React/Core (= 0.55.4)
|
||||||
- react-native-background-timer (2.0.0):
|
- react-native-background-timer (2.0.0):
|
||||||
|
@ -103,6 +104,7 @@ DEPENDENCIES:
|
||||||
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||||
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||||
|
- ObjectiveDropboxOfficial
|
||||||
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
|
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
|
||||||
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
|
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
|
||||||
- react-native-fast-image (from `../node_modules/react-native-fast-image`)
|
- react-native-fast-image (from `../node_modules/react-native-fast-image`)
|
||||||
|
@ -132,6 +134,7 @@ SPEC REPOS:
|
||||||
- GoogleToolboxForMac
|
- GoogleToolboxForMac
|
||||||
- GTMOAuth2
|
- GTMOAuth2
|
||||||
- GTMSessionFetcher
|
- GTMSessionFetcher
|
||||||
|
- ObjectiveDropboxOfficial
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
@ -174,6 +177,7 @@ SPEC CHECKSUMS:
|
||||||
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
|
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
|
||||||
GTMOAuth2: c77fe325e4acd453837e72d91e3b5f13116857b2
|
GTMOAuth2: c77fe325e4acd453837e72d91e3b5f13116857b2
|
||||||
GTMSessionFetcher: 0c4baf0a73acd0041bf9f71ea018deedab5ea84e
|
GTMSessionFetcher: 0c4baf0a73acd0041bf9f71ea018deedab5ea84e
|
||||||
|
ObjectiveDropboxOfficial: 274ce69d66286c94416daf1da5237c55e105e8c0
|
||||||
React: aa2040dbb6f317b95314968021bd2888816e03d5
|
React: aa2040dbb6f317b95314968021bd2888816e03d5
|
||||||
react-native-background-timer: 63dcbf37dbcf294b5c6c071afcdc661fa06a7594
|
react-native-background-timer: 63dcbf37dbcf294b5c6c071afcdc661fa06a7594
|
||||||
react-native-calendar-events: fe6fbc8ed337a7423c98f2c9012b25f20444de09
|
react-native-calendar-events: fe6fbc8ed337a7423c98f2c9012b25f20444de09
|
||||||
|
@ -187,6 +191,6 @@ SPEC CHECKSUMS:
|
||||||
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
|
SDWebImage: 624d6e296c69b244bcede364c72ae0430ac14681
|
||||||
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a
|
yoga: a23273df0088bf7f2bb7e5d7b00044ea57a2a54a
|
||||||
|
|
||||||
PODFILE CHECKSUM: da74c08f6eb674668c49d8d799f8d9e2476a9fc5
|
PODFILE CHECKSUM: cf8276ba4b0933b24c6082a25a5f4eabe0ba4ea6
|
||||||
|
|
||||||
COCOAPODS: 1.5.3
|
COCOAPODS: 1.5.3
|
||||||
|
|
|
@ -212,3 +212,37 @@ resize `JitsiMeetView`.
|
||||||
If `pictureInPictureEnabled` is set to `YES` or `delegate` implements
|
If `pictureInPictureEnabled` is set to `YES` or `delegate` implements
|
||||||
`enterPictureInPicture:`, the in-call toolbar will render a button to afford the
|
`enterPictureInPicture:`, the in-call toolbar will render a button to afford the
|
||||||
user to request entering Picture-in-Picture.
|
user to request entering Picture-in-Picture.
|
||||||
|
|
||||||
|
## Dropbox integration
|
||||||
|
|
||||||
|
To setup the dropbox integration you need to do the following steps:
|
||||||
|
|
||||||
|
1. Add the following lines in your Info.plist file and replace `<APP_KEY>` with your dropbox app key:
|
||||||
|
```
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>db-<APP_KEY></string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>dbapi-8-emm</string>
|
||||||
|
<string>dbapi-2</string>
|
||||||
|
</array>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add the following method to `AppDelegate`:
|
||||||
|
```objc
|
||||||
|
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||||
|
return [JitsiMeetView application:app
|
||||||
|
openURL:url
|
||||||
|
options:options];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -46,4 +46,12 @@
|
||||||
annotation:annotation];
|
annotation:annotation];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||||
|
return [JitsiMeetView application:app
|
||||||
|
openURL:url
|
||||||
|
options: options];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; };
|
75635B0A20751D6D00F29C9F /* joined.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0820751D6D00F29C9F /* joined.wav */; };
|
||||||
75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; };
|
75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; };
|
||||||
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
|
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
|
||||||
|
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
|
||||||
B386B85720981A75000DEF7A /* InviteController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85020981A74000DEF7A /* InviteController.m */; };
|
B386B85720981A75000DEF7A /* InviteController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85020981A74000DEF7A /* InviteController.m */; };
|
||||||
B386B85820981A75000DEF7A /* AddPeopleController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85120981A74000DEF7A /* AddPeopleController.m */; };
|
B386B85820981A75000DEF7A /* AddPeopleController.m in Sources */ = {isa = PBXBuildFile; fileRef = B386B85120981A74000DEF7A /* AddPeopleController.m */; };
|
||||||
B386B85920981A75000DEF7A /* AddPeopleControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
B386B85920981A75000DEF7A /* AddPeopleControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
@ -87,6 +88,8 @@
|
||||||
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
|
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
|
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
A4414ADF20B37F1A003546E6 /* rejected.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = rejected.wav; path = ../../sounds/rejected.wav; sourceTree = "<group>"; };
|
A4414ADF20B37F1A003546E6 /* rejected.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = rejected.wav; path = ../../sounds/rejected.wav; sourceTree = "<group>"; };
|
||||||
|
A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = "<group>"; };
|
||||||
|
A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = "<group>"; };
|
||||||
B386B85020981A74000DEF7A /* InviteController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InviteController.m; sourceTree = "<group>"; };
|
B386B85020981A74000DEF7A /* InviteController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InviteController.m; sourceTree = "<group>"; };
|
||||||
B386B85120981A74000DEF7A /* AddPeopleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddPeopleController.m; sourceTree = "<group>"; };
|
B386B85120981A74000DEF7A /* AddPeopleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddPeopleController.m; sourceTree = "<group>"; };
|
||||||
B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddPeopleControllerDelegate.h; sourceTree = "<group>"; };
|
B386B85220981A74000DEF7A /* AddPeopleControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddPeopleControllerDelegate.h; sourceTree = "<group>"; };
|
||||||
|
@ -122,9 +125,6 @@
|
||||||
0BCA49681EC4BBE500B793EE /* Resources */ = {
|
0BCA49681EC4BBE500B793EE /* Resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6C31EDC720C06D490089C899 /* recordingOn.mp3 */,
|
|
||||||
6C31EDC920C06D530089C899 /* recordingOff.mp3 */,
|
|
||||||
A4414ADF20B37F1A003546E6 /* rejected.wav */,
|
|
||||||
0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */,
|
0BC4B8681F8C01E100CE8B21 /* CallKitIcon.png */,
|
||||||
C6245F5B2053091D0040BE68 /* image-resize@2x.png */,
|
C6245F5B2053091D0040BE68 /* image-resize@2x.png */,
|
||||||
C6245F5C2053091D0040BE68 /* image-resize@3x.png */,
|
C6245F5C2053091D0040BE68 /* image-resize@3x.png */,
|
||||||
|
@ -133,6 +133,9 @@
|
||||||
75635B0920751D6D00F29C9F /* left.wav */,
|
75635B0920751D6D00F29C9F /* left.wav */,
|
||||||
0B49424420AD8DBD00BD2DE0 /* outgoingRinging.wav */,
|
0B49424420AD8DBD00BD2DE0 /* outgoingRinging.wav */,
|
||||||
0B49424320AD8DBD00BD2DE0 /* outgoingStart.wav */,
|
0B49424320AD8DBD00BD2DE0 /* outgoingStart.wav */,
|
||||||
|
6C31EDC920C06D530089C899 /* recordingOff.mp3 */,
|
||||||
|
6C31EDC720C06D490089C899 /* recordingOn.mp3 */,
|
||||||
|
A4414ADF20B37F1A003546E6 /* rejected.wav */,
|
||||||
);
|
);
|
||||||
name = Resources;
|
name = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -162,6 +165,7 @@
|
||||||
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
|
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
|
||||||
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
|
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
|
||||||
C69EFA02209A0EFD0027712B /* callkit */,
|
C69EFA02209A0EFD0027712B /* callkit */,
|
||||||
|
A4A934E7212F3AB8001E9388 /* dropbox */,
|
||||||
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
|
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
|
||||||
0BD906E91EC0C00300C8C18E /* Info.plist */,
|
0BD906E91EC0C00300C8C18E /* Info.plist */,
|
||||||
B386B84F20981A11000DEF7A /* invite */,
|
B386B84F20981A11000DEF7A /* invite */,
|
||||||
|
@ -193,6 +197,15 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
A4A934E7212F3AB8001E9388 /* dropbox */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
A4A934EB21349A06001E9388 /* Dropbox.h */,
|
||||||
|
A4A934E8212F3ADB001E9388 /* Dropbox.m */,
|
||||||
|
);
|
||||||
|
path = dropbox;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
B386B84F20981A11000DEF7A /* invite */ = {
|
B386B84F20981A11000DEF7A /* invite */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -433,6 +446,7 @@
|
||||||
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
|
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
|
||||||
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
|
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
|
||||||
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
|
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
|
||||||
|
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
|
||||||
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
|
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
|
||||||
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
|
C69EFA0E209A0F660027712B /* JMCallKitListener.swift in Sources */,
|
||||||
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
|
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
|
||||||
|
|
|
@ -18,12 +18,17 @@
|
||||||
<string>1.9.0</string>
|
<string>1.9.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>JitsiMeetFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>FontAwesome.ttf</string>
|
||||||
|
<string>jitsi.ttf</string>
|
||||||
|
</array>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>dbapi-2</string>
|
||||||
|
<string>dbapi-8-emm</string>
|
||||||
|
</array>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>JitsiMeetFonts</key>
|
|
||||||
<array>
|
|
||||||
<string>FontAwesome.ttf</string>
|
|
||||||
<string>jitsi.ttf</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -39,6 +39,10 @@
|
||||||
continueUserActivity:(NSUserActivity * _Nonnull)userActivity
|
continueUserActivity:(NSUserActivity * _Nonnull)userActivity
|
||||||
restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler;
|
restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler;
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)app
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
|
||||||
|
|
||||||
+ (BOOL)application:(UIApplication * _Nonnull)application
|
+ (BOOL)application:(UIApplication * _Nonnull)application
|
||||||
openURL:(NSURL * _Nonnull)URL
|
openURL:(NSURL * _Nonnull)URL
|
||||||
sourceApplication:(NSString * _Nullable)sourceApplication
|
sourceApplication:(NSString * _Nullable)sourceApplication
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#import <React/RCTLinkingManager.h>
|
#import <React/RCTLinkingManager.h>
|
||||||
#import <React/RCTRootView.h>
|
#import <React/RCTRootView.h>
|
||||||
|
|
||||||
|
#import "Dropbox.h"
|
||||||
#import "Invite+Private.h"
|
#import "Invite+Private.h"
|
||||||
#import "InviteController+Private.h"
|
#import "InviteController+Private.h"
|
||||||
#import "JitsiMeetView+Private.h"
|
#import "JitsiMeetView+Private.h"
|
||||||
|
@ -137,6 +138,8 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
|
||||||
// Store launch options, will be used when we create the bridge.
|
// Store launch options, will be used when we create the bridge.
|
||||||
_launchOptions = [launchOptions copy];
|
_launchOptions = [launchOptions copy];
|
||||||
|
|
||||||
|
[Dropbox setAppKey];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +214,13 @@ static NSMapTable<NSString *, JitsiMeetView *> *views;
|
||||||
annotation:annotation];
|
annotation:annotation];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||||
|
return [Dropbox application:app
|
||||||
|
openURL:url
|
||||||
|
options: options];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark Initializers
|
#pragma mark Initializers
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright @ 2018-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 <React/RCTBridge.h>
|
||||||
|
|
||||||
|
@interface Dropbox : NSObject<RCTBridgeModule>
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)app
|
||||||
|
openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
|
||||||
|
|
||||||
|
+ (void)setAppKey;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* 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 <React/RCTBridgeModule.h>
|
||||||
|
#import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
|
||||||
|
#import "Dropbox.h"
|
||||||
|
|
||||||
|
RCTPromiseResolveBlock currentResolve = nil;
|
||||||
|
RCTPromiseRejectBlock currentReject = nil;
|
||||||
|
|
||||||
|
@implementation Dropbox
|
||||||
|
|
||||||
|
+ (NSString *)getAppKey{
|
||||||
|
NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
|
||||||
|
for(NSDictionary<NSString *, NSArray *> *urlType in urlTypes) {
|
||||||
|
NSArray *urlSchemes = urlType[@"CFBundleURLSchemes"];
|
||||||
|
if(urlSchemes != nil) {
|
||||||
|
for(NSString *urlScheme in urlSchemes) {
|
||||||
|
if(urlScheme != nil) {
|
||||||
|
if ([urlScheme hasPrefix:@"db-"]) {
|
||||||
|
return [urlScheme substringFromIndex:3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE();
|
||||||
|
|
||||||
|
- (NSDictionary *)constantsToExport {
|
||||||
|
BOOL enabled = [Dropbox getAppKey] != nil;
|
||||||
|
|
||||||
|
return @{
|
||||||
|
@"ENABLED": [NSNumber numberWithBool:enabled]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(authorize: (RCTPromiseResolveBlock)resolve
|
||||||
|
reject:(__unused RCTPromiseRejectBlock)reject) {
|
||||||
|
currentResolve = resolve;
|
||||||
|
currentReject = reject;
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[DBClientsManager authorizeFromController:[UIApplication sharedApplication]
|
||||||
|
controller:[[self class] topMostController]
|
||||||
|
openURL:^(NSURL *url) {
|
||||||
|
[[UIApplication sharedApplication] openURL:url];
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getDisplayName: (NSString *)token
|
||||||
|
resolve: (RCTPromiseResolveBlock)resolve
|
||||||
|
reject:(RCTPromiseRejectBlock)reject) {
|
||||||
|
DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:token];
|
||||||
|
[[client.usersRoutes getCurrentAccount] setResponseBlock:^(DBUSERSFullAccount *result, DBNilObject *routeError, DBRequestError *networkError) {
|
||||||
|
if (result) {
|
||||||
|
resolve(result.name.displayName);
|
||||||
|
} else {
|
||||||
|
NSString *msg = @"Failed!";
|
||||||
|
if (networkError != nil) {
|
||||||
|
msg = [NSString stringWithFormat:@"Failed! Error: %@", networkError];
|
||||||
|
}
|
||||||
|
reject(@"getDisplayName", @"Failed", nil);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(getSpaceUsage: (NSString *)token
|
||||||
|
resolve: (RCTPromiseResolveBlock)resolve
|
||||||
|
reject:(RCTPromiseRejectBlock)reject) {
|
||||||
|
DBUserClient *client = [[DBUserClient alloc] initWithAccessToken:token];
|
||||||
|
[[client.usersRoutes getSpaceUsage] setResponseBlock:^(DBUSERSSpaceUsage *result, DBNilObject *routeError, DBRequestError *networkError) {
|
||||||
|
if (result) {
|
||||||
|
DBUSERSSpaceAllocation *allocation = result.allocation;
|
||||||
|
NSNumber *allocated = 0;
|
||||||
|
NSNumber *used = 0;
|
||||||
|
if([allocation isIndividual]) {
|
||||||
|
allocated = allocation.individual.allocated;
|
||||||
|
used = result.used;
|
||||||
|
} else if ([allocation isTeam]) {
|
||||||
|
allocated = allocation.team.allocated;
|
||||||
|
used = allocation.team.used;
|
||||||
|
}
|
||||||
|
id objects[] = { used, allocated };
|
||||||
|
id keys[] = { @"used", @"allocated" };
|
||||||
|
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects
|
||||||
|
forKeys:keys
|
||||||
|
count:2];
|
||||||
|
resolve(dictionary);
|
||||||
|
} else {
|
||||||
|
NSString *msg = @"Failed!";
|
||||||
|
if (networkError != nil) {
|
||||||
|
msg = [NSString stringWithFormat:@"Failed! Error: %@", networkError];
|
||||||
|
}
|
||||||
|
reject(@"getSpaceUsage", msg, nil);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
|
||||||
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||||
|
DBOAuthResult *authResult = [DBClientsManager handleRedirectURL:url];
|
||||||
|
if (authResult != nil) {
|
||||||
|
if ([authResult isSuccess]) {
|
||||||
|
currentResolve(authResult.accessToken.accessToken);
|
||||||
|
currentResolve = nil;
|
||||||
|
currentReject = nil;
|
||||||
|
return YES;
|
||||||
|
} else {
|
||||||
|
NSString *msg;
|
||||||
|
if ([authResult isError]) {
|
||||||
|
msg = [NSString stringWithFormat:@"%@, error type: %ld",[authResult errorDescription], [authResult errorType]];
|
||||||
|
} else {
|
||||||
|
msg = @"OAuth canceled!";
|
||||||
|
}
|
||||||
|
currentReject(@"authorize", msg, nil);
|
||||||
|
currentResolve = nil;
|
||||||
|
currentReject = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIViewController*)topMostController
|
||||||
|
{
|
||||||
|
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
|
||||||
|
|
||||||
|
while (topController.presentedViewController) {
|
||||||
|
topController = topController.presentedViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
return topController;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setAppKey {
|
||||||
|
NSString *appKey = [self getAppKey];
|
||||||
|
if (appKey != nil) {
|
||||||
|
[DBClientsManager setupWithAppKey:appKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
Loading…
Reference in New Issue