Commit b12c14fb authored by Diego Mello's avatar Diego Mello Committed by GitHub

[IMPROVEMENT] Use expo-web-browser (#992)

* Add unimodules

* Working on iOS

* Working on android

* Remove react-native-safari-view

* Remove previous android link lib

* Show webpage title on Android

* Fix iOS build
parent dad18219
export default {
openBrowserAsync: () => ''
};
......@@ -80,6 +80,7 @@ project.ext.react = [
]
apply from: "../../node_modules/react-native/react.gradle"
apply from: '../../node_modules/react-native-unimodules/gradle.groovy'
/**
* Set this to true to create two separate APKs instead of one:
......@@ -171,6 +172,7 @@ android {
}
dependencies {
addUnimodulesDependencies()
implementation "org.webkit:android-jsc:r241213"
implementation project(':react-native-firebase')
implementation project(':react-native-webview')
......
package chat.rocket.reactnative;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.support.customtabs.CustomTabsIntent;
import android.widget.Toast;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.List;
import chat.rocket.reactnative.R;
/**
* Launches custom tabs.
*/
public class CustomTabsAndroid extends ReactContextBaseJavaModule {
public CustomTabsAndroid(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "CustomTabsAndroid";
}
@ReactMethod
public void openURL(String url) throws NullPointerException {
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
if (CustomTabsHelper.isChromeCustomTabsSupported(getReactApplicationContext())) {
customTabsIntent.launchUrl(getReactApplicationContext().getCurrentActivity(), Uri.parse(url));
} else {
//open in browser
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
//ensure browser is present
final List<ResolveInfo> customTabsApps = getReactApplicationContext()
.getCurrentActivity().getPackageManager().queryIntentActivities(i, 0);
if (customTabsApps.size() > 0) {
getReactApplicationContext().startActivity(i);
} else {
// no browser
Toast.makeText(getReactApplicationContext(), R.string.no_browser_found, Toast.LENGTH_SHORT).show();
}
}
}
}
package chat.rocket.reactnative;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import java.util.List;
/**
* Contains helper methods for custom tabs.
*/
public class CustomTabsHelper {
private static final String SERVICE_ACTION = "android.support.customtabs.action.CustomTabsService";
private static final String CHROME_PACKAGE = "com.android.chrome";
public static boolean isChromeCustomTabsSupported(final Context context) {
Intent serviceIntent = new Intent(SERVICE_ACTION);
serviceIntent.setPackage(CHROME_PACKAGE);
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentServices(serviceIntent, 0);
return !(resolveInfos == null || resolveInfos.isEmpty());
}
}
......@@ -35,6 +35,12 @@ import com.actionsheet.ActionSheetPackage;
import io.realm.react.RealmReactPackage;
import com.swmansion.rnscreens.RNScreensPackage;
import chat.rocket.reactnative.generated.BasePackageList;
import org.unimodules.adapters.react.ModuleRegistryAdapter;
import org.unimodules.adapters.react.ReactModuleRegistryProvider;
import org.unimodules.core.interfaces.SingletonModule;
import android.content.Context;
import android.os.Bundle;
......@@ -43,6 +49,8 @@ import java.util.List;
public class MainApplication extends Application implements ReactApplication, INotificationsApplication {
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(new BasePackageList().getPackageList(), Arrays.<SingletonModule>asList());
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
......@@ -71,10 +79,10 @@ public class MainApplication extends Application implements ReactApplication, IN
new ReactVideoPackage(),
new ReactNativeAudioPackage(),
new KeyboardInputPackage(MainApplication.this),
new RocketChatNativePackage(),
new FastImageViewPackage(),
new RNI18nPackage(),
new RNNotificationsPackage(MainApplication.this)
new RNNotificationsPackage(MainApplication.this),
new ModuleRegistryAdapter(mModuleRegistryProvider)
);
}
......
package chat.rocket.reactnative;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RocketChatNativePackage implements ReactPackage {
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ViewManager> managers = new ArrayList<>();
return managers;
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new CustomTabsAndroid(reactContext));
return modules;
}
}
package chat.rocket.reactnative.generated;
import java.util.Arrays;
import java.util.List;
import org.unimodules.core.interfaces.Package;
public class BasePackageList {
public List<Package> getPackageList() {
return Arrays.<Package>asList(
new expo.modules.constants.ConstantsPackage(),
new expo.modules.filesystem.FileSystemPackage(),
new expo.modules.permissions.PermissionsPackage(),
new expo.modules.webbrowser.WebBrowserPackage()
);
}
}
......@@ -6,6 +6,7 @@ buildscript {
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
glideVersion = "4.9.0"
}
repositories {
mavenLocal()
......
apply from: '../node_modules/react-native-unimodules/gradle.groovy'
includeUnimodulesProjects()
rootProject.name = 'RocketChatRN'
include ':react-native-firebase'
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
......
......@@ -24,3 +24,4 @@ export const STATUS_COLORS = {
export const HEADER_BACKGROUND = isIOS ? '#f8f8f8' : '#2F343D';
export const HEADER_TITLE = isIOS ? COLOR_TITLE : COLOR_WHITE;
export const HEADER_BACK = isIOS ? COLOR_PRIMARY : COLOR_WHITE;
export const HEADER_TINT = isIOS ? COLOR_PRIMARY : COLOR_WHITE;
/**
* This exposes the native CustomTabsAndroid module as a JS module. This has a
* function 'openURL' which takes the following parameters:
*
* 1. String url: A url to be opened in customTabs
*/
import { NativeModules } from 'react-native';
module.exports = NativeModules.CustomTabsAndroid;
import * as WebBrowser from 'expo-web-browser';
import { HEADER_TINT, HEADER_BACKGROUND } from '../constants/colors';
const openLink = url => WebBrowser.openBrowserAsync(url, {
toolbarColor: HEADER_BACKGROUND,
controlsColor: HEADER_TINT,
collapseToolbar: true,
showTitle: true
});
export default openLink;
import CustomTabsAndroid from '../../nativeModules/CustomTabsAndroid';
const openLink = url => CustomTabsAndroid.openURL(url);
export default openLink;
import SafariView from 'react-native-safari-view';
import { HEADER_BACK } from '../../constants/colors';
const openLink = url => SafariView.show({ url, fromBottom: false, tintColor: HEADER_BACK });
export default openLink;
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
platform :ios, '10.0'
require_relative '../node_modules/react-native-unimodules/cocoapods.rb'
target 'RocketChatRN' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
......@@ -44,6 +46,8 @@ target 'RocketChatRN' do
pod 'GoogleIDFASupport', '~> 3.14.0'
pod 'Firebase/Performance', '~> 5.20.1'
use_unimodules!
end
post_install do |installer|
......
......@@ -3,6 +3,18 @@ PODS:
- Crashlytics (3.12.0):
- Fabric (~> 1.9.0)
- DoubleConversion (1.1.6)
- EXAppLoaderProvider (5.0.1)
- EXConstants (5.0.1):
- UMConstantsInterface
- UMCore
- EXFileSystem (5.0.1):
- UMCore
- UMFileSystemInterface
- EXPermissions (5.0.1):
- UMCore
- UMPermissionsInterface
- EXWebBrowser (5.0.3):
- UMCore
- Fabric (1.9.0)
- Firebase/Core (5.20.2):
- Firebase/CoreOnly
......@@ -136,11 +148,31 @@ PODS:
- RNScreens (1.0.0-alpha.22):
- React
- RSKImageCropper (2.2.1)
- UMBarCodeScannerInterface (2.0.1)
- UMCameraInterface (2.0.1)
- UMConstantsInterface (2.0.1)
- UMCore (2.0.1)
- UMFaceDetectorInterface (2.0.1)
- UMFileSystemInterface (2.0.1)
- UMFontInterface (2.0.1)
- UMImageLoaderInterface (2.0.1)
- UMPermissionsInterface (2.0.1)
- UMReactNativeAdapter (2.0.1):
- React
- UMCore
- UMFontInterface
- UMSensorsInterface (2.0.1)
- UMTaskManagerInterface (2.0.1)
- yoga (0.59.8.React)
DEPENDENCIES:
- Crashlytics (~> 3.12.0)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXAppLoaderProvider (from `../node_modules/expo-app-loader-provider/ios`)
- EXConstants (from `../node_modules/expo-constants/ios`)
- EXFileSystem (from `../node_modules/expo-file-system/ios`)
- EXPermissions (from `../node_modules/expo-permissions/ios`)
- EXWebBrowser (from `../node_modules/expo-web-browser/ios`)
- Fabric (~> 1.9.0)
- Firebase/Core (~> 5.20.1)
- Firebase/Performance (~> 5.20.1)
......@@ -163,6 +195,18 @@ DEPENDENCIES:
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNScreens (from `../node_modules/react-native-screens`)
- UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`)
- UMCameraInterface (from `../node_modules/unimodules-camera-interface/ios`)
- UMConstantsInterface (from `../node_modules/unimodules-constants-interface/ios`)
- "UMCore (from `../node_modules/@unimodules/core/ios`)"
- UMFaceDetectorInterface (from `../node_modules/unimodules-face-detector-interface/ios`)
- UMFileSystemInterface (from `../node_modules/unimodules-file-system-interface/ios`)
- UMFontInterface (from `../node_modules/unimodules-font-interface/ios`)
- UMImageLoaderInterface (from `../node_modules/unimodules-image-loader-interface/ios`)
- UMPermissionsInterface (from `../node_modules/unimodules-permissions-interface/ios`)
- "UMReactNativeAdapter (from `../node_modules/@unimodules/react-native-adapter/ios`)"
- UMSensorsInterface (from `../node_modules/unimodules-sensors-interface/ios`)
- UMTaskManagerInterface (from `../node_modules/unimodules-task-manager-interface/ios`)
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
......@@ -190,6 +234,21 @@ SPEC REPOS:
EXTERNAL SOURCES:
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
EXAppLoaderProvider:
:path: !ruby/object:Pathname
path: "../node_modules/expo-app-loader-provider/ios"
EXConstants:
:path: !ruby/object:Pathname
path: "../node_modules/expo-constants/ios"
EXFileSystem:
:path: !ruby/object:Pathname
path: "../node_modules/expo-file-system/ios"
EXPermissions:
:path: !ruby/object:Pathname
path: "../node_modules/expo-permissions/ios"
EXWebBrowser:
:path: !ruby/object:Pathname
path: "../node_modules/expo-web-browser/ios"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
......@@ -208,6 +267,42 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-image-crop-picker"
RNScreens:
:path: "../node_modules/react-native-screens"
UMBarCodeScannerInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-barcode-scanner-interface/ios"
UMCameraInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-camera-interface/ios"
UMConstantsInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-constants-interface/ios"
UMCore:
:path: !ruby/object:Pathname
path: "../node_modules/@unimodules/core/ios"
UMFaceDetectorInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-face-detector-interface/ios"
UMFileSystemInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-file-system-interface/ios"
UMFontInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-font-interface/ios"
UMImageLoaderInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-image-loader-interface/ios"
UMPermissionsInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-permissions-interface/ios"
UMReactNativeAdapter:
:path: !ruby/object:Pathname
path: "../node_modules/@unimodules/react-native-adapter/ios"
UMSensorsInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-sensors-interface/ios"
UMTaskManagerInterface:
:path: !ruby/object:Pathname
path: "../node_modules/unimodules-task-manager-interface/ios"
yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
......@@ -215,6 +310,11 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
Crashlytics: 07fb167b1694128c1c9a5a5cc319b0e9c3ca0933
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
EXAppLoaderProvider: 8f2c04a0a8d9be91f7c37c2b8824077ee5d4bc01
EXConstants: 9fe56eec8bf0a3ee9beb8f3381fa91340a5b1e57
EXFileSystem: 96624bd4b93a0684335c421a6567a92b25bd7ddb
EXPermissions: 8e05008ed4fc8c9be6c17ea95301fc3f3f005a7b
EXWebBrowser: e03894b4583bb726e5ea05d01b341ba00134c2b5
Fabric: f988e33c97f08930a413e08123064d2e5f68d655
Firebase: 0c8cf33f266410c61ab3e2265cfa412200351d9c
FirebaseABTesting: 1f50b8d50f5e3469eea54e7463a7b7fe221d1f5e
......@@ -241,8 +341,20 @@ SPEC CHECKSUMS:
RNImageCropPicker: e608efe182652dc8690268cb99cb5a201f2b5ea3
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
UMBarCodeScannerInterface: d5602e23de37f95bb4ee49ee3b2711e128058ae9
UMCameraInterface: dde8491778ed062348e569bad33a890e60c32c9d
UMConstantsInterface: de48a63a5af572fc4dcc0e68051b00503b83e301
UMCore: 047dc01ae4ccdd0c993f2c190f2489e5409c3ad0
UMFaceDetectorInterface: badd9e3d206f5ba254c85a26afa43da06638575f
UMFileSystemInterface: ff9a18c26ee6321dc21a3f9663efe3a55313d4db
UMFontInterface: 0575f33184974a38f3528a4750729c7f5256b848
UMImageLoaderInterface: ee8642347161d66272e841377a888957feb1f48e
UMPermissionsInterface: 2238fe9d7f99457a5cfe7f3140c2521c5bf453a6
UMReactNativeAdapter: 110be971ff044f8cfd37cbf565a264cd79858391
UMSensorsInterface: cda3ec177c7ff0a138e3135414b4a29013389358
UMTaskManagerInterface: 296793ab2a7e181fe5ebe2ba9b40ae208ab4b8fa
yoga: 92b2102c3d373d1a790db4ab761d2b0ffc634f64
PODFILE CHECKSUM: f98adf896db83acfddda2f17bf015d55d15a89f2
PODFILE CHECKSUM: b5e15bac5f306ea636e16393a7a6eb42c017ea99
COCOAPODS: 1.6.2
../../../../../node_modules/expo-app-loader-provider/ios/EXAppLoaderProvider/Interfaces/EXAppLoaderInterface.h
\ No newline at end of file
../../../../../node_modules/expo-app-loader-provider/ios/EXAppLoaderProvider/EXAppLoaderProvider.h
\ No newline at end of file
../../../../../node_modules/expo-app-loader-provider/ios/EXAppLoaderProvider/Interfaces/EXAppRecordInterface.h
\ No newline at end of file
../../../../../node_modules/expo-constants/ios/EXConstants/EXConstants.h
\ No newline at end of file
../../../../../node_modules/expo-constants/ios/EXConstants/EXConstantsService.h
\ No newline at end of file
../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXDownloadDelegate.h
\ No newline at end of file
../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXFilePermissionModule.h
\ No newline at end of file
../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXFileSystem.h
\ No newline at end of file
../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXFileSystemAssetLibraryHandler.h
\ No newline at end of file
../../../../../node_modules/expo-file-system/ios/EXFileSystem/EXFileSystemLocalFileHandler.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXAudioRecordingPermissionRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXCalendarRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXCameraPermissionRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXCameraRollRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXContactsRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXLocationRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXPermissions.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXReactNativeUserNotificationCenterProxy.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXRemindersRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXRemoteNotificationRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXSystemBrightnessRequester.h
\ No newline at end of file
../../../../../node_modules/expo-permissions/ios/EXPermissions/EXUserNotificationRequester.h
\ No newline at end of file
../../../../../node_modules/expo-web-browser/ios/EXWebBrowser/EXWebBrowser.h
\ No newline at end of file
../../../../../node_modules/unimodules-barcode-scanner-interface/ios/UMBarCodeScannerInterface/UMBarCodeScannerInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-barcode-scanner-interface/ios/UMBarCodeScannerInterface/UMBarCodeScannerProviderInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-camera-interface/ios/UMCameraInterface/UMCameraInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-constants-interface/ios/UMConstantsInterface/UMConstantsInterface.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMAppDelegateWrapper.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMAppLifecycleListener.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMAppLifecycleService.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMDefines.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMEventEmitter.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMEventEmitterService.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMExportedModule.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMInternalModule.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMJavaScriptContextProvider.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMKernelService.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMLogHandler.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Services/UMLogManager.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMModuleRegistry/UMModuleRegistry.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMModuleRegistryConsumer.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMModuleRegistry/UMModuleRegistryDelegate.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMModuleRegistryProvider/UMModuleRegistryProvider.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMSingletonModule.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMUIManager.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMUtilities.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/Protocols/UMUtilitiesInterface.h
\ No newline at end of file
../../../../../node_modules/@unimodules/core/ios/UMCore/UMViewManager.h
\ No newline at end of file
../../../../../node_modules/unimodules-face-detector-interface/ios/UMFaceDetectorInterface/UMFaceDetectorManager.h
\ No newline at end of file
../../../../../node_modules/unimodules-face-detector-interface/ios/UMFaceDetectorInterface/UMFaceDetectorManagerProvider.h
\ No newline at end of file
../../../../../node_modules/unimodules-file-system-interface/ios/UMFileSystemInterface/UMFilePermissionModuleInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-file-system-interface/ios/UMFileSystemInterface/UMFileSystemInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-font-interface/ios/UMFontInterface/UMFontManagerInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-font-interface/ios/UMFontInterface/UMFontProcessorInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-font-interface/ios/UMFontInterface/UMFontScalerInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-font-interface/ios/UMFontInterface/UMFontScalersManagerInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-image-loader-interface/ios/UMImageLoaderInterface/UMImageLoaderInterface.h
\ No newline at end of file
../../../../../node_modules/unimodules-permissions-interface/ios/UMPermissionsInterface/UMPermissionsInterface.h
\ No newline at end of file