[RN] Add initial Jitsi Meet SDK for iOS

Ladies and gentlemen, allow me to introduce you to Jitsi Meet SDK for iOS, the
mobile SDK which powers Jitsi Meet.

The goal is to encapsulate the entire React Native app into a framework / SDK
and offer an API for native (ObjC or Swift) applications to embed the Jitsi
conferencing experience.

While React Native can be embedded in native applications, I don't think it was
designed to be embedded as part of a framework, hidden away from the application
using it. This surfaced as a number of issues which had to be addressed
specifically due to our use-case:

- Universal / deep linking needed to be wrapped to avoid the embedding app from
  linking with RN.
- The bundle URL had to be manually constructed, since RN considers that all
  resources are in the main bundle, but in case of a framework that is not the
  case.
- Custom fonts had to be manually loaded, since UIAppFonts doesn't work on the
  framework's Info.plist file.
- The RN packager has to be manually triggered since the React project will no
  longer do it for us.
- Custom App Transport Security rules were added since the builtin way to do it
  modifies the framework's Info.plist, which is useless in this case.

At this stage, the Jitsi Meet application is just a small single view
application which uses the Jitsi Meet SDK to create a single view which
represents the entire application. Events and external conference handling are
forthcoming.
This commit is contained in:
Saúl Ibarra Corretgé 2017-05-08 17:21:30 +02:00 committed by Lyubo Marinov
parent 8e3dfcf0d0
commit b1100a9c7a
28 changed files with 1400 additions and 945 deletions

4
.gitignore vendored
View File

@ -65,3 +65,7 @@ buck-out/
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
# CocoaPods
Pods/
Podfile.lock

View File

@ -0,0 +1,445 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */; settings = {ATTRIBUTES = (Public, ); }; };
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */; };
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
0B93EF7B1EC608550030D24D /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B93EF7A1EC608550030D24D /* CoreText.framework */; };
0B93EF7E1EC9DDCD0030D24D /* JitsiRCTBridgeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B93EF7C1EC9DDCD0030D24D /* JitsiRCTBridgeWrapper.h */; };
0B93EF7F1EC9DDCD0030D24D /* JitsiRTCBridgeWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B93EF7D1EC9DDCD0030D24D /* JitsiRTCBridgeWrapper.m */; };
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495C1EC4B6C600B793EE /* AudioMode.m */; };
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
0BCA49641EC4B76D00B793EE /* WebRTC.framework in Copy embedded WebRTC framework */ = {isa = PBXBuildFile; fileRef = 0BCA49631EC4B76D00B793EE /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0BCA496B1EC4BBF900B793EE /* jitsi.ttf */; };
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
399E84404A63DA0F3B34EB9C /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F102AB2F4BCDCF220A512816 /* libPods-JitsiMeet.a */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
0BCA49621EC4B74500B793EE /* Copy embedded WebRTC framework */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
0BCA49641EC4B76D00B793EE /* WebRTC.framework in Copy embedded WebRTC framework */,
);
name = "Copy embedded WebRTC framework";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
062651321278D27A9BAEFAD4 /* 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>"; };
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JitsiMeetView.h; sourceTree = "<group>"; };
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitsiMeetView.m; sourceTree = "<group>"; };
0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeetViewDelegate.h; sourceTree = "<group>"; };
0B93EF7A1EC608550030D24D /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
0B93EF7C1EC9DDCD0030D24D /* JitsiRCTBridgeWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JitsiRCTBridgeWrapper.h; sourceTree = "<group>"; };
0B93EF7D1EC9DDCD0030D24D /* JitsiRTCBridgeWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitsiRTCBridgeWrapper.m; sourceTree = "<group>"; };
0BCA495C1EC4B6C600B793EE /* AudioMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioMode.m; sourceTree = "<group>"; };
0BCA495D1EC4B6C600B793EE /* POSIX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = POSIX.m; sourceTree = "<group>"; };
0BCA495E1EC4B6C600B793EE /* Proximity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Proximity.m; sourceTree = "<group>"; };
0BCA49631EC4B76D00B793EE /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
0BCA496B1EC4BBF900B793EE /* jitsi.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = jitsi.ttf; path = ../fonts/jitsi.ttf; sourceTree = "<group>"; };
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E358F7AEFCB4033712107DF5 /* 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>"; };
F102AB2F4BCDCF220A512816 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0BD906E11EC0C00300C8C18E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0B93EF7B1EC608550030D24D /* CoreText.framework in Frameworks */,
399E84404A63DA0F3B34EB9C /* libPods-JitsiMeet.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0BCA49681EC4BBE500B793EE /* Resources */ = {
isa = PBXGroup;
children = (
0BCA496B1EC4BBF900B793EE /* jitsi.ttf */,
);
name = Resources;
sourceTree = "<group>";
};
0BD906DB1EC0C00300C8C18E = {
isa = PBXGroup;
children = (
0BCA49681EC4BBE500B793EE /* Resources */,
0BD906E71EC0C00300C8C18E /* sdk */,
0BD906E61EC0C00300C8C18E /* Products */,
C2471A7E156487CC2009E5E0 /* Pods */,
9C3C6FA2341729836589B856 /* Frameworks */,
);
sourceTree = "<group>";
};
0BD906E61EC0C00300C8C18E /* Products */ = {
isa = PBXGroup;
children = (
0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */,
);
name = Products;
sourceTree = "<group>";
};
0BD906E71EC0C00300C8C18E /* sdk */ = {
isa = PBXGroup;
children = (
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
0BCA495D1EC4B6C600B793EE /* POSIX.m */,
0BCA495E1EC4B6C600B793EE /* Proximity.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
0B93EF7C1EC9DDCD0030D24D /* JitsiRCTBridgeWrapper.h */,
0B93EF7D1EC9DDCD0030D24D /* JitsiRTCBridgeWrapper.m */,
0B412F1B1EDEC80100B1A0A6 /* JitsiMeetViewDelegate.h */,
0B412F161EDEC65D00B1A0A6 /* JitsiMeetView.h */,
0B412F171EDEC65D00B1A0A6 /* JitsiMeetView.m */,
);
path = sdk;
sourceTree = "<group>";
};
9C3C6FA2341729836589B856 /* Frameworks */ = {
isa = PBXGroup;
children = (
0B93EF7A1EC608550030D24D /* CoreText.framework */,
0BCA49631EC4B76D00B793EE /* WebRTC.framework */,
F102AB2F4BCDCF220A512816 /* libPods-JitsiMeet.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
C2471A7E156487CC2009E5E0 /* Pods */ = {
isa = PBXGroup;
children = (
062651321278D27A9BAEFAD4 /* Pods-JitsiMeet.debug.xcconfig */,
E358F7AEFCB4033712107DF5 /* Pods-JitsiMeet.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
0BD906E21EC0C00300C8C18E /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F181EDEC65D00B1A0A6 /* JitsiMeetView.h in Headers */,
0B93EF7E1EC9DDCD0030D24D /* JitsiRCTBridgeWrapper.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
0BD906E41EC0C00300C8C18E /* JitsiMeet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0BD906ED1EC0C00300C8C18E /* Build configuration list for PBXNativeTarget "JitsiMeet" */;
buildPhases = (
8203CAE533C18CEC8284C979 /* [CP] Check Pods Manifest.lock */,
0BD906E01EC0C00300C8C18E /* Sources */,
0BD906E11EC0C00300C8C18E /* Frameworks */,
0BD906E21EC0C00300C8C18E /* Headers */,
0BD906E31EC0C00300C8C18E /* Resources */,
512A060342EDB080C9BBD5BA /* [CP] Copy Pods Resources */,
0BCA49621EC4B74500B793EE /* Copy embedded WebRTC framework */,
0BCA49651EC4B77500B793EE /* Package React bundle */,
);
buildRules = (
);
dependencies = (
);
name = JitsiMeet;
productName = "Jitsi Meet SDK";
productReference = 0BD906E51EC0C00300C8C18E /* JitsiMeet.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
0BD906DC1EC0C00300C8C18E /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = Jitsi;
TargetAttributes = {
0BD906E41EC0C00300C8C18E = {
CreatedOnToolsVersion = 8.3.2;
DevelopmentTeam = BQNXB4G3KQ;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "Jitsi Meet SDK" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 0BD906DB1EC0C00300C8C18E;
productRefGroup = 0BD906E61EC0C00300C8C18E /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
0BD906E41EC0C00300C8C18E /* JitsiMeet */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
0BD906E31EC0C00300C8C18E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0BCA496C1EC4BBF900B793EE /* jitsi.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0BCA49651EC4B77500B793EE /* Package React bundle */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Package React bundle";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
};
512A060342EDB080C9BBD5BA /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources.sh\"\n";
showEnvVarsInLog = 0;
};
8203CAE533C18CEC8284C979 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0BD906E01EC0C00300C8C18E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B93EF7F1EC9DDCD0030D24D /* JitsiRTCBridgeWrapper.m in Sources */,
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */,
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
0B412F191EDEC65D00B1A0A6 /* JitsiMeetView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
0BD906EB1EC0C00300C8C18E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
0BD906EC1EC0C00300C8C18E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
0BD906EE1EC0C00300C8C18E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 062651321278D27A9BAEFAD4 /* Pods-JitsiMeet.debug.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = BQNXB4G3KQ;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = sdk/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiKit;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
0BD906EF1EC0C00300C8C18E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E358F7AEFCB4033712107DF5 /* Pods-JitsiMeet.release.xcconfig */;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = BQNXB4G3KQ;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = sdk/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.JitsiKit;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "Jitsi Meet SDK" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0BD906EB1EC0C00300C8C18E /* Debug */,
0BD906EC1EC0C00300C8C18E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0BD906ED1EC0C00300C8C18E /* Build configuration list for PBXNativeTarget "JitsiMeet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0BD906EE1EC0C00300C8C18E /* Debug */,
0BD906EF1EC0C00300C8C18E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0BD906DC1EC0C00300C8C18E /* Project object */;
}

32
ios/Podfile Normal file
View File

@ -0,0 +1,32 @@
platform :ios, '9.0'
workspace 'jitsi-meet'
project 'Jitsi Meet SDK.xcodeproj'
target 'JitsiMeet' do
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'RCTActionSheet',
'RCTAnimation',
'RCTImage',
'RCTLinkingIOS',
'RCTNetwork',
'RCTText',
'RCTWebSocket',
]
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end

68
ios/README.md Normal file
View File

@ -0,0 +1,68 @@
# Jitsi Meet SDK for iOS
This directory contains the source code for Jitsi Meet for iOS (the application)
and the Jitsi Meet SDK.
## Jitsi Meet SDK
JitsiMeet is an iOS framework which embodies the Jitsi Meet experience,
gift-wrapped so other applications can use it. Using it is very simple. Use
a Storyboard or Interface Builder to add a `JitsiMeetView` to your
application.
Then, once the view has loaded, set the delegate in your controller and load the
desired URL:
```objc
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *meetView = (JitsiMeetView*) self.view;
meetView.delegate = self;
[meetView loadURL:nil];
}
```
### JitsiMeetView class
The `JitsiMeetView` class is the entrypoint to the SDK. It a subclass of
`UIView` which renders a full conference in the designated area.
```objc
[meetView loadURL:[NSURL URLWithString:@"https://meet.jit.si/test123"]];
```
Loads the given URL and joins the room. If `null` is specified the welcome page
is displayed instead.
#### Universal / deep linking
In order to support universal / deep linking, `JitsiMeetView` offers 2 class
methods that you application's delegate should call in order for the application
to follow those links. Example:
```objc
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
return [JitsiMeetView application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [JitsiMeetView application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
```
### JitsiMeetViewDelegate
TODO.

View File

@ -1,14 +1,22 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* 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 <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;

View File

@ -1,101 +1,51 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* 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 "AppDelegate.h"
#import <React/RCTAssert.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
#import <JitsiMeet/JitsiMeet.h>
/**
* A <tt>RCTFatalHandler</tt> implementation which swallows JavaScript errors.
* In the Release configuration, React Native will (intentionally) raise an
* unhandled NSException for an unhandled JavaScript error. This will
* effectively kill the application. <tt>_RCTFatal</tt> is suitable to be in
* accord with the Web i.e. not kill the application.
*/
RCTFatalHandler _RCTFatal = ^(NSError *error) {
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName,
error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
};
@implementation AppDelegate
// https://facebook.github.io/react-native/docs/linking.html
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
#pragma mark linking delegate methods
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
return [JitsiMeetView application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if !DEBUG
// In the Release configuration, React Native will (intentionally) raise an
// unhandled NSException for an unhandled JavaScript error. This will
// effectively kill the application. In accord with the Web, do not kill the
// application.
if (!RCTGetFatalHandler()) {
RCTSetFatalHandler(_RCTFatal);
}
#endif
NSURL *jsCodeLocation
= [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios"
fallbackResource:nil];
RCTRootView *rootView
= [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"App"
initialProperties:nil
launchOptions:launchOptions];
// 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.
rootView.backgroundColor
= [[UIColor alloc] initWithRed:.07f green:.07f blue:.07f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
// https://facebook.github.io/react-native/docs/linking.html
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [RCTLinkingManager application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
return [JitsiMeetView application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
@end

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="u7g-vg-A8m">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="xSm-U5-Hdu">
<objects>
<viewController id="u7g-vg-A8m" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="d40-fc-Y8P"/>
<viewControllerLayoutGuide type="bottom" id="1KD-Ho-g0H"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="QpR-jB-WOw" customClass="JitsiMeetView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ZIj-K3-jVH" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="28" y="138"/>
</scene>
</scenes>
</document>

View File

@ -61,17 +61,14 @@
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in conferences with audio.</string>
<key>UIAppFonts</key>
<array>
<string>jitsi.ttf</string>
<string>FontAwesome.ttf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
<string>voip</string>
</array>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>

View File

@ -1,24 +0,0 @@
#import "RCTBridgeModule.h"
#import <UIKit/UIKit.h>
@interface Proximity : NSObject<RCTBridgeModule>
@end
@implementation Proximity
RCT_EXPORT_MODULE();
/**
* Enables / disables the proximity sensor monitoring. On iOS enabling the
* proximity sensor automatically dims the screen and disables touch controls,
* so there is nothing else to do (unlike on Android)!
*
* @param enabled {@code YES} to enable proximity (sensor) monitoring;
* {@code NO}, otherwise.
*/
RCT_EXPORT_METHOD(setEnabled:(BOOL)enabled) {
[[UIDevice currentDevice] setProximityMonitoringEnabled:enabled];
}
@end

24
ios/app/ViewController.h Normal file
View File

@ -0,0 +1,24 @@
/*
* 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 <UIKit/UIKit.h>
#import <JitsiMeet/JitsiMeet.h>
@interface ViewController : UIViewController<JitsiMeetViewDelegate>
@end

37
ios/app/ViewController.m Normal file
View File

@ -0,0 +1,37 @@
/*
* 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 "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *meetView = (JitsiMeetView*) self.view;
meetView.delegate = self;
[meetView loadURL:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end

View File

@ -1,10 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
* 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 <UIKit/UIKit.h>

File diff suppressed because it is too large Load Diff

View File

@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
BlueprintIdentifier = "0BD906E41EC0C00300C8C18E"
BuildableName = "JitsiMeet.framework"
BlueprintName = "JitsiMeet"
ReferencedContainer = "container:Jitsi Meet SDK.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry

View File

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Jitsi Meet SDK.xcodeproj">
</FileRef>
<FileRef
location = "group:jitsi-meet.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,3 +1,19 @@
/*
* 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 "RCTBridgeModule.h"
#import "RCTLog.h"

29
ios/sdk/Info.plist Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
<key>JitsiKitFonts</key>
<array>
<string>jitsi.ttf</string>
<string>FontAwesome.ttf</string>
</array>
</dict>
</plist>

18
ios/sdk/JitsiMeet.h Normal file
View File

@ -0,0 +1,18 @@
/*
* 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 <JitsiMeet/JitsiMeetView.h>
#import <JitsiMeet/JitsiMeetViewDelegate.h>

38
ios/sdk/JitsiMeetView.h Normal file
View File

@ -0,0 +1,38 @@
/*
* 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 <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "JitsiMeetViewDelegate.h"
@interface JitsiMeetView : UIView
@property (nonatomic, weak, nullable) id<JitsiMeetViewDelegate> delegate;
+ (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler;
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)URL
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation;
- (void)loadURL:(nullable NSURL *)url;
@end

212
ios/sdk/JitsiMeetView.m Normal file
View File

@ -0,0 +1,212 @@
/*
* 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 <CoreText/CoreText.h>
#import <React/RCTAssert.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
#import "JitsiMeetView.h"
#import "JitsiRCTBridgeWrapper.h"
/**
* A <tt>RCTFatalHandler</tt> implementation which swallows JavaScript errors.
* In the Release configuration, React Native will (intentionally) raise an
* unhandled NSException for an unhandled JavaScript error. This will
* effectively kill the application. <tt>_RCTFatal</tt> is suitable to be in
* accord with the Web i.e. not kill the application.
*/
RCTFatalHandler _RCTFatal = ^(NSError *error)
{
id jsStackTrace = error.userInfo[RCTJSStackTraceKey];
@try {
NSString *name
= [NSString stringWithFormat:@"%@: %@",
RCTFatalExceptionName, error.localizedDescription];
NSString *message
= RCTFormatError(error.localizedDescription, jsStackTrace, 75);
[NSException raise:name format:@"%@", message];
} @catch (NSException *e) {
if (!jsStackTrace) {
@throw;
}
}
};
@interface JitsiMeetView() {
RCTRootView *rootView;
}
@end
@implementation JitsiMeetView
static JitsiRCTBridgeWrapper *jitsiBridge;
#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)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
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
{
NSDictionary *props = url ? @{ url : url.absoluteString } : nil;
if (rootView == nil) {
rootView
= [[RCTRootView alloc] initWithBridge:jitsiBridge.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
/*
* 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;
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.
jitsiBridge = [[JitsiRCTBridgeWrapper 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
* plist file doesn't work for frameworks, so fonts have to be manually loaded.
*/
- (void)loadCustomFonts
{
NSBundle *bundle = [NSBundle bundleForClass:self.class];
NSArray *fonts = [bundle objectForInfoDictionaryKey:@"JitsiKitFonts"];
for (NSString *item in fonts) {
NSString *fontName = [item stringByDeletingPathExtension];
NSString *fontExt = [item pathExtension];
NSString *fontPath = [bundle pathForResource:fontName ofType:fontExt];
NSData *inData = [NSData dataWithContentsOfFile:fontPath];
CFErrorRef error;
CGDataProviderRef provider
= CGDataProviderCreateWithCFData((__bridge CFDataRef)inData);
CGFontRef font = CGFontCreateWithDataProvider(provider);
if (!CTFontManagerRegisterGraphicsFont(font, &error)) {
CFStringRef errorDescription = CFErrorCopyDescription(error);
NSLog(@"Failed to load font: %@", errorDescription);
CFRelease(errorDescription);
}
CFRelease(font);
CFRelease(provider);
}
}
/*
* 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
* instead.
*/
- (void)registerFatalErrorHandler
{
#if !DEBUG
// In the Release configuration, React Native will (intentionally) raise
// an unhandled NSException for an unhandled JavaScript error. This will
// effectively kill the application. In accord with the Web, do not kill
// the application.
if (!RCTGetFatalHandler()) {
RCTSetFatalHandler(_RCTFatal);
}
#endif
}
@end

View File

@ -0,0 +1,21 @@
/*
* 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.
*/
@protocol JitsiMeetViewDelegate <NSObject>
// TODO: add delegate methods
@end

View File

@ -0,0 +1,37 @@
/*
* 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 <Foundation/Foundation.h>
#import <React/RCTBridge.h>
#import <React/RCTBridgeDelegate.h>
/**
* A wrapper around the <tt>RCTBridge</tt> which implements the delegate methods
* that allow us to serve the JS bundle from within the framework's resources
* directory. This is the recommended way for those cases where the builtin API
* doesn't cut it, as is the case.
*
* In addition, we will create a single bridge and then create all root views
* off it, thus only loading the JS bundle a single time. This class is not a
* singleton, however, so it's possible for us to create multiple instances of
* it, though that's not currently used.
*/
@interface JitsiRCTBridgeWrapper : NSObject<RCTBridgeDelegate>
@property (nonatomic, readonly, strong) RCTBridge *bridge;
@end

View File

@ -0,0 +1,119 @@
/*
* 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.
*/
#include "JitsiRCTBridgeWrapper.h"
/*
* Wrapper around RCTBridge which also implements the RCTBridgeDelegate methods,
* allowing us to specify where the bundles are loaded from.
*/
@implementation JitsiRCTBridgeWrapper
- (instancetype)init
{
self = [super init];
if (self) {
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
}
return self;
}
#pragma mark helper methods for getting the packager URL
#if DEBUG
static NSURL *serverRootWithHost(NSString *host)
{
return [NSURL URLWithString:
[NSString stringWithFormat:@"http://%@:8081/", host]];
}
- (BOOL)isPackagerRunning:(NSString *)host
{
NSURL *url = [serverRootWithHost(host)
URLByAppendingPathComponent:@"status"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:NULL];
NSString *status = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [status isEqualToString:@"packager-status:running"];
}
- (NSString *)guessPackagerHost
{
static NSString *ipGuess;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *ipPath = [[NSBundle bundleForClass:self.class]
pathForResource:@"ip" ofType:@"txt"];
ipGuess = [[NSString stringWithContentsOfFile:ipPath
encoding:NSUTF8StringEncoding
error:nil]
stringByTrimmingCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
});
NSString *host = ipGuess ?: @"localhost";
if ([self isPackagerRunning:host]) {
return host;
}
return nil;
}
#endif
#pragma mark RCTBridgeDelegate methods
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
/*
* In debug mode, try to fetch the bundle from the packager, or fallback to
* the one inside the framework. The IP address for the packager host is
* fetched from the ip.txt file inside the framework.
*
* This duplicates some functionality present in RCTBundleURLProvider, but
* that mode is not designed to work inside a framework, because all
* resources are loaded from the main bundle.
*/
NSString *host = [self guessPackagerHost];
if (host != nil) {
NSString *path = @"/index.ios.bundle";
NSString *query = @"platform=ios&dev=true&minify=false";
NSURLComponents *components
= [NSURLComponents componentsWithURL:serverRootWithHost(host)
resolvingAgainstBaseURL:NO];
components.path = path;
components.query = query;
return components.URL;
}
#endif
return [self fallbackSourceURLForBridge:bridge];
}
- (NSURL *)fallbackSourceURLForBridge:(RCTBridge *)bridge
{
return [[NSBundle bundleForClass:self.class] URLForResource:@"main"
withExtension:@"jsbundle"];
}
@end

View File

@ -1,3 +1,19 @@
/*
* 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 "RCTBridgeModule.h"
#include <arpa/inet.h>

40
ios/sdk/Proximity.m Normal file
View File

@ -0,0 +1,40 @@
/*
* 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 "RCTBridgeModule.h"
#import <UIKit/UIKit.h>
@interface Proximity : NSObject<RCTBridgeModule>
@end
@implementation Proximity
RCT_EXPORT_MODULE();
/**
* Enables / disables the proximity sensor monitoring. On iOS enabling the
* proximity sensor automatically dims the screen and disables touch controls,
* so there is nothing else to do (unlike on Android)!
*
* @param enabled {@code YES} to enable proximity (sensor) monitoring;
* {@code NO}, otherwise.
*/
RCT_EXPORT_METHOD(setEnabled:(BOOL)enabled) {
[[UIDevice currentDevice] setProximityMonitoringEnabled:enabled];
}
@end

36
ios/utils/fixup-ats.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
# This script gets executed from Xcode to disable ATS (App Transport Security)
# on Debug builds. Doing this allows loading resources over HTTP, such as the
# JS bundle.
set -x
case "$CONFIGURATION" in
Debug)
# Speed up build times by skipping the creation of the offline package for debug
# builds on the simulator since the packager is supposed to be running anyways.
if [[ "$PLATFORM_NAME" == *simulator ]]; then
echo "Skipping bundling for Simulator platform"
exit 0;
fi
DEV=true
;;
"")
echo "$0 must be invoked by Xcode"
exit 1
;;
*)
DEV=false
;;
esac
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
if [[ "$CONFIGURATION" = "Debug" && ! "$PLATFORM_NAME" == *simulator ]]; then
PLISTBUDDY='/usr/libexec/PlistBuddy'
PLIST=$TARGET_BUILD_DIR/$INFOPLIST_PATH
`$PLISTBUDDY -c "Add NSAppTransportSecurity:NSAllowsArbitraryLoads bool true" "$PLIST"` || true
fi

39
ios/utils/fixup-frameworks.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/bash
# This script gets executed from Xcode to fixup the embedded frameworks and
# bundle the necessary architectures.
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
if lipo -info "$FRAMEWORK_EXECUTABLE_PATH" | grep -q -v "^Non-fat"
then
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
fi
done
if [ -n "$EXTRACTED_ARCHS" ]
then
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi
done

16
ios/utils/run-packager.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
# This script is executed from Xcode to start the React packager for Debug
# targets.
if [[ "$CONFIGURATION" = "Debug" ]]; then
if nc -w 5 -z localhost 8081 ; then
if ! curl -s "http://localhost:8081/status" | grep -q "packager-status:running" ; then
echo "Port 8081 already in use, packager is either not running or not running correctly"
exit 2
fi
else
open "$SRCROOT/../node_modules/react-native/packager/launchPackager.command" || echo "Can't start packager automatically"
fi
fi